[
  {
    "path": ".circleci/config.yml",
    "content": "version: 2.1\norbs:\n  coveralls: coveralls/coveralls@1.0.6\n  node: circleci/node@1.1.6\n\nworkflows:\n  hardhat:\n    jobs:\n      - checkout-and-install-hardhat\n      - compile-hardhat:\n          requires:\n            - checkout-and-install-hardhat\n      - lint-hardhat:\n          requires:\n            - compile-hardhat\n      - unit-test-hardhat:\n          requires:\n            - compile-hardhat\n      - integration-test-hardhat:\n          requires:\n            - compile-hardhat\n      - contract-size-hardhat:\n          requires:\n            - compile-hardhat\n      - e2e-test-hardhat:\n          requires:\n            - compile-hardhat\n  frontend:\n    jobs:\n      - checkout-and-install-frontend\n      - unit-test-frontend:\n          requires:\n            - checkout-and-install-frontend\n  crab-netting:\n    jobs:\n      - lint-crab-netting\n      - compile-crab-netting:\n          requires:\n            - lint-crab-netting\n      - test-crab-netting:\n          requires:\n            - compile-crab-netting\n  zen-bull-vault:\n    jobs:\n      - compile-zen-bull-vault\n      - test-zen-bull-vault:\n          requires:\n            - compile-zen-bull-vault\n\njobs:\n  ################ hardhat jobs\n  checkout-and-install-hardhat:\n    working_directory: ~/squeeth/packages/hardhat\n    docker:\n      - image: cimg/node:18.15.0\n    steps:\n      - checkout:\n          path: ~/squeeth\n      - restore_cache:\n          key: dependency-cache-{{ checksum \"package.json\" }}\n      - run:\n          name: Install packages\n          command: yarn install\n      - save_cache:\n          key: dependency-cache-{{ checksum \"package.json\" }}\n          paths:\n            - node_modules\n      - save_cache:\n          key: squeeth-{{ .Environment.CIRCLE_SHA1 }}\n          paths:\n            - ~/squeeth\n\n  compile-hardhat:\n    working_directory: ~/squeeth/packages/hardhat\n    docker:\n      - image: cimg/node:18.15.0\n    steps:\n      - checkout:\n          path: ~/squeeth\n      - restore_cache:\n          key: squeeth-{{ .Environment.CIRCLE_SHA1 }}\n      - run:\n          name: Compile Contracts\n          command: npx hardhat compile\n      - save_cache:\n          key: typechain-cache-{{ .Environment.CIRCLE_SHA1 }}\n          paths:\n            - typechain\n      - save_cache:\n          key: artifacts-cache-{{ .Environment.CIRCLE_SHA1 }}\n          paths:\n            - artifacts\n\n  lint-hardhat:\n    working_directory: ~/squeeth/packages/hardhat\n    docker:\n      - image: cimg/node:18.15.0\n    steps:\n      - checkout:\n          path: ~/squeeth\n      - restore_cache:\n          key: squeeth-{{ .Environment.CIRCLE_SHA1 }}\n      - restore_cache:\n          key: typechain-cache-{{ .Environment.CIRCLE_SHA1 }}\n      - run:\n          name: Lint\n          command: yarn lint:check\n\n  unit-test-hardhat:\n    working_directory: ~/squeeth/packages/hardhat\n    docker:\n      - image: cimg/node:18.15.0\n    steps:\n      - checkout:\n          path: ~/squeeth\n      - restore_cache:\n          key: squeeth-{{ .Environment.CIRCLE_SHA1 }}\n      - restore_cache:\n          key: typechain-cache-{{ .Environment.CIRCLE_SHA1 }}\n      - run:\n          name: Unit tests\n          command: yarn test:crab-unit\n\n  integration-test-hardhat:\n    working_directory: ~/squeeth/packages/hardhat\n    docker:\n      - image: cimg/node:18.15.0\n    steps:\n      - checkout:\n          path: ~/squeeth\n      - restore_cache:\n          key: squeeth-{{ .Environment.CIRCLE_SHA1 }}\n      - restore_cache:\n          key: typechain-cache-{{ .Environment.CIRCLE_SHA1 }}\n      - run:\n          name: Integration tests\n          command: yarn test:crab-integration\n\n  contract-size-hardhat:\n    working_directory: ~/squeeth/packages/hardhat\n    docker:\n      - image: cimg/node:18.15.0\n    steps:\n      - checkout:\n          path: ~/squeeth\n      - restore_cache:\n          key: squeeth-{{ .Environment.CIRCLE_SHA1 }}\n      - restore_cache:\n          key: artifacts-cache-{{ .Environment.CIRCLE_SHA1 }}\n      - run:\n          name: Check Contracts Size\n          command: npx hardhat size-contracts\n\n  e2e-test-hardhat:\n    working_directory: ~/squeeth/packages/hardhat\n    docker:\n      - image: cimg/node:18.15.0\n    steps:\n      - restore_cache:\n          key: squeeth-{{ .Environment.CIRCLE_SHA1 }}\n      - restore_cache:\n          key: typechain-cache-{{ .Environment.CIRCLE_SHA1 }}\n      - run:\n          name: Set Env Variables\n          command: echo \"export ALCHEMY_KEY=${ALCHEMY_KEY}\" >> $BASH_ENV\n      - run:\n          name: Mainnet E2E Test\n          command: yarn test:e2e\n\n  ################ frontend jobs\n  checkout-and-install-frontend:\n    working_directory: ~/squeeth/packages/frontend\n    docker:\n      - image: cimg/node:18.15.0\n    steps:\n      - checkout:\n          path: ~/squeeth\n      - restore_cache:\n          key: dependency-frontend-cache-{{ checksum \"package.json\" }}\n      - run:\n          name: Install packages\n          command: yarn install\n      - save_cache:\n          key: dependency-frontend-cache-{{ checksum \"package.json\" }}\n          paths:\n            - node_modules\n      - save_cache:\n          key: squeeth-frontend-{{ .Environment.CIRCLE_SHA1 }}\n          paths:\n            - ~/squeeth\n\n  unit-test-frontend:\n    working_directory: ~/squeeth/packages/frontend\n    docker:\n      - image: cimg/node:18.15.0\n    steps:\n      - checkout:\n          path: ~/squeeth\n      - restore_cache:\n          key: squeeth-frontend-{{ .Environment.CIRCLE_SHA1 }}\n      - run:\n          name: Unit tests\n          command: yarn test:ci\n\n  ################ crab-netting jobs\n  lint-crab-netting:\n    working_directory: ~/squeeth/packages/crab-netting\n    docker:\n      - image: ghcr.io/foundry-rs/foundry:latest\n    steps:\n      - checkout\n      - run:\n          name: Lint crab-netting\n          command: cd packages/crab-netting && FOUNDRY_PROFILE=fmt forge fmt --check\n\n  compile-crab-netting:\n    working_directory: ~/squeeth/packages/crab-netting\n    docker:\n      - image: ghcr.io/foundry-rs/foundry:latest\n    steps:\n      - checkout\n      - run:\n          name: Build crab-netting\n          command: cd packages/crab-netting && forge build --force\n\n  test-crab-netting:\n    working_directory: ~/squeeth/packages/crab-netting\n    docker:\n      - image: ghcr.io/foundry-rs/foundry:latest\n    steps:\n      - checkout\n      - run: cd packages/crab-netting && forge test -vv --gas-report\n\n  ################ zen-bull-vault jobs\n  compile-zen-bull-vault:\n    working_directory: ~/squeeth/packages/zen-bull-vault\n    docker:\n      - image: ghcr.io/foundry-rs/foundry:latest\n    steps:\n      - checkout\n      - run:\n          name: Build zen-bull-vault\n          command: cd packages/zen-bull-vault && forge build --force\n\n  test-zen-bull-vault:\n    working_directory: ~/squeeth/packages/zen-bull-vault\n    docker:\n      - image: ghcr.io/foundry-rs/foundry:latest\n    steps:\n      - checkout\n      - run: cd packages/zen-bull-vault && forge test -vv --gas-report\n\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[packages/**.js{,x}]\nindent_style = space\nindent_size = 2\n\n[*.{sol,yul}]\nindent_style = space\nindent_size = 4\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"\"\nlabels: \"\"\nassignees: \"\"\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: \"\"\nlabels: \"\"\nassignees: \"\"\n---\n\n**Please describe the problem you're having.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "# Task:\n\n## Description\n\nPlease include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.\n\nFixes (linear-task)\n\n## Type of change\n\n- [ ] New feature\n- [ ] Bug fix\n- [ ] Testing code\n- [ ] Document update or config files"
  },
  {
    "path": ".gitignore",
    "content": "packages/subgraph/subgraph.yaml\npackages/subgraph/generated\npackages/subgraph/abis/*\npackages/hardhat/*.txt\n**/aws.json\n\n# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n**/node_modules\npackages/hardhat/artifacts*\npackages/hardhat/typechain*\n# ignore localhost, but keep other deployment record on git\npackages/hardhat/deployments/localhost\npackages/react-app/src/contracts/*\n!packages/react-app/src/contracts/external_contracts.js\npackages/hardhat/cache*\npackages/hardhat/coverage.json\npackages/hardhat/coverage/\n\npackages/**/data\n\npackages/subgraph/config/config.json\ntenderly.yaml\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\ncoverage\n\n# production\nbuild\n\n# misc\n.DS_Store\n.env\n\npackages/hardhat/.env*\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n.idea\n\n#Local vscode folder\n.vscode\n\n# Local Netlify folder\n.netlify\n\n# asdf config\n**/.tool-versions\n\n\n\npackages/bull-vault/out\npackages/bull-vault/cache\n\npackages/crab-netting/out\npackages/crab-netting/cache\n\n\nsoljson*\nlcov.info"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"packages/services/arbitrum\"]\n\tpath = packages/services/arbitrum\n\turl = https://github.com/OffchainLabs/arbitrum\n\tbranch = master\n[submodule \"packages/services/optimism\"]\n\tpath = packages/services/optimism\n\turl = https://github.com/ethereum-optimism/optimism\n\tbranch = regenesis/0.4.0\n[submodule \"packages/zen-bull-vault/lib/squeeth-monorepo\"]\n\tpath = packages/zen-bull-vault/lib/squeeth-monorepo\n\turl = https://github.com/opynfinance/squeeth-monorepo\n[submodule \"packages/zen-bull-vault/lib/openzeppelin-contracts\"]\n\tpath = packages/zen-bull-vault/lib/openzeppelin-contracts\n\turl = https://github.com/openzeppelin/openzeppelin-contracts\n[submodule \"packages/zen-bull-vault/lib/v3-core\"]\n\tpath = packages/zen-bull-vault/lib/v3-core\n\turl = https://github.com/Uniswap/v3-core\n[submodule \"packages/zen-bull-vault/lib/v3-periphery\"]\n\tpath = packages/zen-bull-vault/lib/v3-periphery\n\turl = https://github.com/Uniswap/v3-periphery\n[submodule \"packages/crab-netting/lib/forge-std\"]\n\tpath = packages/crab-netting/lib/forge-std\n\turl = https://github.com/foundry-rs/forge-std\n[submodule \"packages/crab-netting/lib/squeeth-monorepo\"]\n\tpath = packages/crab-netting/lib/squeeth-monorepo\n\turl = https://github.com/opynfinance/squeeth-monorepo/\n[submodule \"packages/crab-netting/lib/openzeppelin-contracts\"]\n\tpath = packages/crab-netting/lib/openzeppelin-contracts\n\turl = https://github.com/OpenZeppelin/openzeppelin-contracts\n[submodule \"packages/crab-netting/lib/v3-periphery\"]\n\tpath = packages/crab-netting/lib/v3-periphery\n\turl = https://github.com/uniswap/v3-periphery\n[submodule \"packages/crab-netting/lib/v3-core\"]\n\tpath = packages/crab-netting/lib/v3-core\n\turl = https://github.com/uniswap/v3-core\n[submodule \"packages/zen-bull-vault/lib/forge-std\"]\n\tpath = packages/zen-bull-vault/lib/forge-std\n\turl = https://github.com/foundry-rs/forge-std\n[submodule \"packages/zen-bull-netting/lib/forge-std\"]\n\tpath = packages/zen-bull-netting/lib/forge-std\n\turl = https://github.com/foundry-rs/forge-std\n[submodule \"packages/zen-bull-netting/lib/v3-core\"]\n\tpath = packages/zen-bull-netting/lib/v3-core\n\turl = https://github.com/Uniswap/v3-core\n\tbranch = 0.8\n[submodule \"packages/zen-bull-netting/lib/v3-periphery\"]\n\tpath = packages/zen-bull-netting/lib/v3-periphery\n\turl = https://github.com/Uniswap/v3-periphery\n\tbranch = 0.8\n[submodule \"packages/zen-bull-netting/lib/openzeppelin-contracts\"]\n\tpath = packages/zen-bull-netting/lib/openzeppelin-contracts\n\turl = https://github.com/OpenZeppelin/openzeppelin-contracts\n"
  },
  {
    "path": ".gitpod.yml",
    "content": "tasks:\n  - name: App\n    init: >\n      yarn &&\n      gp sync-done install\n    command: REACT_APP_PROVIDER=$(gp url 8545) yarn start\n  - name: Chain\n    init: gp sync-await install\n    command: yarn chain\n    openMode: split-right\n  - name: Deployment\n    init: gp sync-await install\n    command: yarn deploy\n    openMode: split-right\nports:\n  - port: 3000\n    onOpen: open-preview\n  - port: 8545\n    onOpen: ignore\ngithub:\n  prebuilds:\n    pullRequestsFromForks: true\n    addComment: true\nvscode:\n  extensions:\n    - dbaeumer.vscode-eslint\n    - esbenp.prettier-vscode\n    - juanblanco.solidity"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpx lint-staged"
  },
  {
    "path": ".huskyrc",
    "content": "{\n  \"hooks\": {\n    \"pre-commit\": \"lint-staged\",\n    \"pre-push\": \"yarn pre-push\"\n  }\n}"
  },
  {
    "path": ".lintstagedrc",
    "content": "{\n  \"packages/hardhat/**/*.+(js|ts|json|sol)\": [\n    \"yarn lint-contracts\"\n  ]\n}"
  },
  {
    "path": "README.md",
    "content": "# Squeeth Monorepo\n\n<p align=\"center\">\n<img src=\"https://i.imgur.com/Iyulvqq.png\" width=400>\n</p>\n<p align=\"center\"> The Squeethiest 🐱 </p>\n<p align=\"center\">\n  <a href=\"https://discord.gg/ztEuhjyaBF\"> <img alt=\"Discord\" src=\"https://img.shields.io/discord/590664003815211058?style=for-the-badge\" height=20></a>\n  <a href=\"https://twitter.com/opyn_\"><img alt=\"Twitter Follow\" src=\"https://img.shields.io/twitter/follow/opyn_?style=for-the-badge\" height=20></a>\n</p>\n\n## 🤔 What is Squeeth\n\nThe squeeth contract is designed for users to long or short a special index: Eth², as an implementation of a Power Perpetual.\n\n<p align=\"center\">\n<img height=\"150\" src=\"https://i.imgur.com/bGue31m.png\"> </img>\n</p>\n\nThis monorepo contains the source code for the frontend app as well as the contracts, you can spin up the environment locally, run tests, or play around with the code. For more details about how to use the contracts and frontend, go to `packages/` and choose `hardhat` for the contracts or `frontend`, we have more detailed explanation in each sub-folder.\n\n## 📚 Learn more\n\n- Read our [GitBook](https://opyn.gitbook.io/squeeth/) Documentation\n- Visit our official [Medium page](https://medium.com/opyn) where we have tons of great posts\n- Original paper on [Power Perpetual](https://www.paradigm.xyz/2021/08/power-perpetuals/)\n- Join our [Discord](https://tiny.cc/opyndiscord) to chat with all the derivative big brains\n\n## 🔒 Security And Bug Bounty Program\n\nSecurity is our one of our highest priorities. Our team has created a protocol that we believe is safe and dependable, and is audited by Trail of Bits and Akira, and is insured by Sherlock. All smart contract code is publicly verifiable and we have a bug bounty for undiscovered vulnerabilities. We encourage our users to be mindful of risk and only use funds they can afford to lose. Smart contracts are still new and experimental technology. We want to remind our users to be optimistic about innovation while remaining cautious about where they put their money.\n\nPlease see here for details on our [security audit](https://opyn.gitbook.io/squeeth/security/audits-and-insurance) and [bug bounty program](https://opyn.gitbook.io/squeeth/security/bug-bounty).\n\n## 🏄‍♂️ Quick Start\n\n### Prerequisites\n\n1. Install [Node](https://nodejs.org/en/download/) LTS\n1. Install [Yarn](https://classic.yarnpkg.com/en/docs/install/)\n\n### Steps\n\n> install and start your 👷‍ Hardhat chain:\n\n```bash\ncd packages/hardhat\nyarn install\nyarn chain\n```\n\n> in a second terminal window, start your 📱 frontend:\n\n```bash\ncd packages/frontend\nyarn install\nyarn dev\n```\n\n> in a third terminal window, 🛰 deploy your contract:\n\n```bash\ncd packages/hardhat\nyarn deploy\n```\n\nOpen http://localhost:3000 to see the app\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@squeeth/monorepo\",\n  \"version\": \"1.0.0\",\n  \"keywords\": [\n    \"ethereum\",\n    \"react\",\n    \"uniswap\",\n    \"workspaces\",\n    \"yarn\"\n  ],\n  \"private\": true,\n  \"scripts\": {\n    \"frontend:build\": \"NODE_OPTIONS=--max-old-space-size=12288 yarn workspace @squeeth/frontend build\",\n    \"frontend:eject\": \"yarn workspace @squeeth/frontend eject\",\n    \"frontend:start\": \"yarn workspace @squeeth/frontend dev\",\n    \"frontend:test\": \"yarn workspace @squeeth/frontend test\",\n    \"build\": \"NODE_OPTIONS=--max-old-space-size=12288 yarn workspace @squeeth/frontend build \",\n    \"chain\": \"yarn workspace @squeeth/hardhat chain\",\n    \"node\": \"yarn workspace @squeeth/hardhat chain\",\n    \"test\": \"yarn workspace @squeeth/hardhat test\",\n    \"start\": \"yarn workspace @squeeth/frontend start\",\n    \"compile\": \"yarn workspace @squeeth/hardhat compile\",\n    \"deploy\": \"yarn workspace @squeeth/hardhat deploy\",\n    \"watch\": \"yarn workspace @squeeth/hardhat watch\",\n    \"accounts\": \"yarn workspace @squeeth/hardhat accounts\",\n    \"balance\": \"yarn workspace @squeeth/hardhat balance\",\n    \"send\": \"yarn workspace @squeeth/hardhat send\",\n    \"ipfs\": \"yarn workspace @squeeth/frontend ipfs\",\n    \"surge\": \"yarn workspace @squeeth/frontend surge\",\n    \"s3\": \"yarn workspace @squeeth/frontend s3\",\n    \"ship\": \"yarn workspace @squeeth/frontend ship\",\n    \"generate\": \"yarn workspace @squeeth/hardhat generate\",\n    \"account\": \"yarn workspace @squeeth/hardhat account\",\n    \"mineContractAddress\": \"cd packages/hardhat && npx hardhat mineContractAddress\",\n    \"wallet\": \"cd packages/hardhat && npx hardhat wallet\",\n    \"fundedwallet\": \"cd packages/hardhat && npx hardhat fundedwallet\",\n    \"flatten\": \"cd packages/hardhat && npx hardhat flatten\",\n    \"clean\": \"cd packages/hardhat && npx hardhat clean\",\n    \"run-graph-node\": \"yarn workspace @squeeth/services run-graph-node\",\n    \"remove-graph-node\": \"yarn workspace @squeeth/services remove-graph-node\",\n    \"clean-graph-node\": \"yarn workspace @squeeth/services clean-graph-node\",\n    \"graph-prepare\": \"mustache packages/subgraph/config/config.json packages/subgraph/src/subgraph.template.yaml > packages/subgraph/subgraph.yaml\",\n    \"graph-codegen\": \"yarn workspace @squeeth/subgraph graph codegen\",\n    \"graph-build\": \"yarn workspace @squeeth/subgraph graph build\",\n    \"graph-create-local\": \"yarn workspace @squeeth/subgraph graph create --node http://localhost:8020/ scaffold-eth/your-contract\",\n    \"graph-remove-local\": \"yarn workspace @squeeth/subgraph graph remove --node http://localhost:8020/ scaffold-eth/your-contract\",\n    \"graph-deploy-local\": \"yarn workspace @squeeth/subgraph graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 scaffold-eth/your-contract\",\n    \"graph-ship-local\": \"yarn graph-prepare && yarn graph-codegen && yarn graph-deploy-local\",\n    \"deploy-and-graph\": \"yarn deploy && yarn graph-ship-local\",\n    \"theme\": \"yarn workspace @squeeth/frontend theme\",\n    \"watch-theme\": \"yarn workspace @squeeth/frontend watch\",\n    \"lint-contracts\": \"yarn workspace @squeeth/hardhat lint\",\n    \"pre-push\": \"cd packages/bull-vault && forge fmt && git commit -a -m 'auto foundry lint commit'\"\n  },\n  \"workspaces\": {\n    \"packages\": [\n      \"packages/*\"\n    ],\n    \"nohoist\": [\n      \"**/@graphprotocol/graph-ts\",\n      \"**/@graphprotocol/graph-ts/**\",\n      \"**/hardhat\",\n      \"**/hardhat/**\",\n      \"**/ip-range-check\",\n      \"**/ip-range-check/**\"\n    ]\n  },\n  \"dependencies\": {},\n  \"resolutions\": {\n    \"ipfs-http-client@34.0.0/concat-stream\": \"2.0.0\"\n  },\n  \"devDependencies\": {\n    \"husky\": \"^7.0.1\",\n    \"lint-staged\": \"^11.1.2\"\n  }\n}"
  },
  {
    "path": "packages/crab-netting/LICENSE_BUSL",
    "content": "Business Source License 1.1\n\nLicense text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.\n\n\n\"Business Source License\" is a trademark of MariaDB Corporation Ab.\n\n-----------------------------------------------------------------------------\n\nParameters\nLicensor:            Opyn \nLicensed Work:       Opyn Crab Netting v1.0\n                     The Licensed Work is (c) 2022 Opyn\n\nAdditional Use Grant: Any uses listed and defined at\nhttps://github.com/opynfinance/squeeth-monorepo/tree/main/packages/crab-netting/USE_GRANT\n\nChange Date:          The earlier of 2023-12-14 or a date specified at\nhttps://github.com/opynfinance/squeeth-monorepo/tree/main/packages/crab-netting/CHANGE_DATE\n\nChange License:       GNU General Public License v2.0 or later\n\n-----------------------------------------------------------------------------\n\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provided that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON\nAN \"AS IS\" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License’s text to license\nyour works, and to refer to it using the trademark \"Business Source License\",\nas long as you comply with the Covenants of Licensor below.\n\n-----------------------------------------------------------------------------\n\nCovenants of Licensor\n\nIn consideration of the right to use this License’s text and the \"Business\nSource License\" name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provided by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n  or a license that is compatible with GPL Version 2.0 or a later version,\n  where \"compatible\" means that software provided under the Change License can\n  be included in a program with software provided under GPL Version 2.0 or a\n  later version. Licensor may specify additional Change Licenses without\n  limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n  impose any additional restriction on the right granted in this License, as\n  the Additional Use Grant; or (b) insert the text \"None\".\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\n\n-----------------------------------------------------------------------------\n\nNotice\n\nThe Business Source License (this document, or the \"License\") is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\n"
  },
  {
    "path": "packages/crab-netting/foundry.toml",
    "content": "[profile.default]\nsrc = 'src'\nout = 'out'\nlibs = ['lib']\n\n# See more config options https://github.com/foundry-rs/foundry/tree/master/config"
  },
  {
    "path": "packages/crab-netting/remappings.txt",
    "content": "ds-test/=lib/forge-std/lib/ds-test/src/\nforge-std/=lib/forge-std/src/\nsqueeth-monorepo/=lib/squeeth-monorepo/packages/hardhat/contracts/\nopenzeppelin/=lib/openzeppelin-contracts/contracts/\n@uniswap/v3-periphery/=lib/v3-periphery/\n@uniswap/v3-core/=lib/v3-core/"
  },
  {
    "path": "packages/crab-netting/script/Counter.s.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport \"forge-std/Script.sol\";\n\ncontract CounterScript is Script {\n    function setUp() public {}\n\n    function run() public {\n        vm.broadcast();\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/src/CrabNetting.sol",
    "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.13;\n\n// interface\nimport {IERC20} from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport {IWETH} from \"../src/interfaces/IWETH.sol\";\nimport {IOracle} from \"../src/interfaces/IOracle.sol\";\nimport \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\nimport {ICrabStrategyV2} from \"../src/interfaces/ICrabStrategyV2.sol\";\nimport {IController} from \"../src/interfaces/IController.sol\";\n\n// contract\nimport {Ownable} from \"openzeppelin/access/Ownable.sol\";\nimport {EIP712} from \"openzeppelin/utils/cryptography/draft-EIP712.sol\";\nimport {ECDSA} from \"openzeppelin/utils/cryptography/ECDSA.sol\";\n\n/// @dev order struct for a signed order from market maker\nstruct Order {\n    uint256 bidId;\n    address trader;\n    uint256 quantity;\n    uint256 price;\n    bool isBuying;\n    uint256 expiry;\n    uint256 nonce;\n    uint8 v;\n    bytes32 r;\n    bytes32 s;\n}\n\n/// @dev struct to store proportional amounts of erc20s (received or to send)\nstruct Portion {\n    uint256 crab;\n    uint256 eth;\n    uint256 sqth;\n}\n\n/// @dev params for deposit auction\nstruct DepositAuctionParams {\n    /// @dev USDC to deposit\n    uint256 depositsQueued;\n    /// @dev minETH equivalent to get from uniswap of the USDC to deposit\n    uint256 minEth;\n    /// @dev total ETH to deposit after selling the minted SQTH\n    uint256 totalDeposit;\n    /// @dev orders to buy sqth\n    Order[] orders;\n    /// @dev price from the auction to sell sqth\n    uint256 clearingPrice;\n    /// @dev remaining ETH to flashDeposit\n    uint256 ethToFlashDeposit;\n    /// @dev fee to pay uniswap for ethUSD swap\n    uint24 ethUSDFee;\n    /// @dev fee to pay uniswap for sqthETH swap\n    uint24 flashDepositFee;\n}\n\n/// @dev params for withdraw auction\nstruct WithdrawAuctionParams {\n    /// @dev amont of crab to queue for withdrawal\n    uint256 crabToWithdraw;\n    /// @dev orders that sell sqth to the auction\n    Order[] orders;\n    /// @dev price that the auction pays for the purchased sqth\n    uint256 clearingPrice;\n    /// @dev minUSDC to receive from swapping the ETH obtained by withdrawing\n    uint256 minUSDC;\n    /// @dev uniswap fee for swapping eth to USD;\n    uint24 ethUSDFee;\n}\n\n/// @dev receipt used to store deposits and withdraws\nstruct Receipt {\n    /// @dev address of the depositor or withdrawer\n    address sender;\n    /// @dev usdc amount to queue for deposit or crab amount to queue for withdrawal\n    uint256 amount;\n    /// @dev time of deposit\n    uint256 timestamp;\n}\n\n/**\n * Crab netting error codes\n * N1: deposit amount smaller than minimum OTC amount\n * N2: auction is live\n * N3: remaining amount smaller than minimum, consider removing full balance\n * N4: force withdraw after 1 week from deposit\n * N5: withdraw amount smaller than minimum OTC amount\n * N6: remaining amount smaller than minimum, consider removing full balance\n * N7: Not enough deposits to net\n * N8: Not enough withdrawals to net\n * N9: signature incorrect\n * N10: order expired\n * N11: Min ETH out too low\n * N12: auction order not buying sqth\n * N13: buy order price less than clearing\n * N14: not enough buy orders for sqth\n * N15: auction order is not selling\n * N16: sell order price greater than clearing\n * N17: min USDC out too low\n * N18: twap period cannot be less than 180\n * N19: Price tolerance has to be less than 20%\n * N20: Nonce already used\n * N21: Price too high relative to Uniswap twap.\n * N22: Price too low relative to Uniswap twap.\n * N23: Crab Price too high\n * N24: Crab Price too low\n * N25: only weth and crab can send me monies\n */\n\n/**\n * @dev CrabNetting contract\n * @notice Contract for Netting Deposits and Withdrawals\n * @author Opyn team\n */\ncontract CrabNetting is Ownable, EIP712 {\n    /// @dev typehash for signed orders\n    bytes32 private constant _CRAB_NETTING_TYPEHASH = keccak256(\n        \"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\"\n    );\n    /// @dev owner sets to true when starting auction\n    bool public isAuctionLive;\n\n    /// @dev sqth twap period\n    uint32 public immutable sqthTwapPeriod;\n    /// @dev twap period to use for auction calculations\n    uint32 public auctionTwapPeriod = 420 seconds;\n\n    /// @dev min USDC amounts to withdraw or deposit via netting\n    uint256 public minUSDCAmount;\n\n    /// @dev min CRAB amounts to withdraw or deposit via netting\n    uint256 public minCrabAmount;\n\n    // @dev OTC price must be within this distance of the uniswap twap price\n    uint256 public otcPriceTolerance = 5e16; // 5%\n    // @dev OTC price tolerance cannot exceed 20%\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\n\n    /// @dev address for ERC20 tokens\n    address public immutable usdc;\n    address public immutable crab;\n    address public immutable weth;\n    address public immutable sqth;\n\n    /// @dev address for uniswap router\n    ISwapRouter public immutable swapRouter;\n\n    /// @dev address for uniswap oracle\n    address public immutable oracle;\n\n    /// @dev address for sqth eth pool\n    address public immutable ethSqueethPool;\n\n    /// @dev address for usdc eth pool\n    address public immutable ethUsdcPool;\n\n    /// @dev address for sqth controller\n    address public immutable sqthController;\n\n    /// @dev array index of last processed deposits\n    uint256 public depositsIndex;\n\n    /// @dev array index of last processed withdraws\n    uint256 public withdrawsIndex;\n\n    /// @dev array of deposit receipts\n    Receipt[] public deposits;\n    /// @dev array of withdrawal receipts\n    Receipt[] public withdraws;\n\n    /// @dev usd amount to deposit for an address\n    mapping(address => uint256) public usdBalance;\n\n    /// @dev crab amount to withdraw for an address\n    mapping(address => uint256) public crabBalance;\n\n    /// @dev indexes of deposit receipts of an address\n    mapping(address => uint256[]) public userDepositsIndex;\n\n    /// @dev indexes of withdraw receipts of an address\n    mapping(address => uint256[]) public userWithdrawsIndex;\n\n    /// @dev store the used flag for a nonce for each address\n    mapping(address => mapping(uint256 => bool)) public nonces;\n\n    event USDCQueued(\n        address indexed depositor, uint256 amount, uint256 depositorsBalance, uint256 indexed receiptIndex\n    );\n\n    event USDCDeQueued(address indexed depositor, uint256 amount, uint256 depositorsBalance);\n\n    event CrabQueued(\n        address indexed withdrawer, uint256 amount, uint256 withdrawersBalance, uint256 indexed receiptIndex\n    );\n\n    event CrabDeQueued(address indexed withdrawer, uint256 amount, uint256 withdrawersBalance);\n\n    event USDCDeposited(\n        address indexed depositor,\n        uint256 usdcAmount,\n        uint256 crabAmount,\n        uint256 indexed receiptIndex,\n        uint256 refundedETH\n    );\n\n    event CrabWithdrawn(\n        address indexed withdrawer, uint256 crabAmount, uint256 usdcAmount, uint256 indexed receiptIndex\n    );\n\n    event WithdrawRejected(address indexed withdrawer, uint256 crabAmount, uint256 index);\n\n    event BidTraded(uint256 indexed bidId, address indexed trader, uint256 quantity, uint256 price, bool isBuying);\n\n    event SetAuctionTwapPeriod(uint32 previousTwap, uint32 newTwap);\n    event SetOTCPriceTolerance(uint256 previousTolerance, uint256 newOtcPriceTolerance);\n    event SetMinCrab(uint256 amount);\n    event SetMinUSDC(uint256 amount);\n    event SetDepositsIndex(uint256 newDepositsIndex);\n    event SetWithdrawsIndex(uint256 newWithdrawsIndex);\n    event NonceTrue(address sender, uint256 nonce);\n    event ToggledAuctionLive(bool isAuctionLive);\n\n    /**\n     * @notice netting contract constructor\n     * @dev initializes the erc20 address, uniswap router and approves them\n     * @param _crab address of crab contract token\n     * @param _swapRouter address of uniswap swap router\n     */\n    constructor(address _crab, address _swapRouter) EIP712(\"CRABNetting\", \"1\") {\n        crab = _crab;\n        swapRouter = ISwapRouter(_swapRouter);\n\n        sqthController = ICrabStrategyV2(_crab).powerTokenController();\n        usdc = IController(sqthController).quoteCurrency();\n        weth = ICrabStrategyV2(_crab).weth();\n        sqth = ICrabStrategyV2(_crab).wPowerPerp();\n        oracle = ICrabStrategyV2(_crab).oracle();\n        ethSqueethPool = ICrabStrategyV2(_crab).ethWSqueethPool();\n        ethUsdcPool = IController(sqthController).ethQuoteCurrencyPool();\n        sqthTwapPeriod = IController(sqthController).TWAP_PERIOD();\n\n        // approve crab and sqth so withdraw can happen\n        IERC20(sqth).approve(crab, type(uint256).max);\n\n        IERC20(weth).approve(address(swapRouter), type(uint256).max);\n        IERC20(usdc).approve(address(swapRouter), type(uint256).max);\n    }\n\n    /**\n     * @dev view function to get the domain seperator used in signing\n     */\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\n        return _domainSeparatorV4();\n    }\n\n    /**\n     * @dev toggles the value of isAuctionLive\n     */\n    function toggleAuctionLive() external onlyOwner {\n        isAuctionLive = !isAuctionLive;\n        emit ToggledAuctionLive(isAuctionLive);\n    }\n\n    /**\n     * @notice set nonce to true\n     * @param _nonce the number to be set true\n     */\n    function setNonceTrue(uint256 _nonce) external {\n        nonces[msg.sender][_nonce] = true;\n        emit NonceTrue(msg.sender, _nonce);\n    }\n\n    /**\n     * @notice set minUSDCAmount\n     * @param _amount the number to be set as minUSDC\n     */\n    function setMinUSDC(uint256 _amount) external onlyOwner {\n        minUSDCAmount = _amount;\n        emit SetMinUSDC(_amount);\n    }\n\n    /**\n     * @notice set minCrabAmount\n     * @param _amount the number to be set as minCrab\n     */\n    function setMinCrab(uint256 _amount) external onlyOwner {\n        minCrabAmount = _amount;\n        emit SetMinCrab(_amount);\n    }\n\n    /**\n     * @notice set the depositIndex so that we want to skip processing some deposits\n     * @param _newDepositsIndex the new deposits index\n     */\n    function setDepositsIndex(uint256 _newDepositsIndex) external onlyOwner {\n        depositsIndex = _newDepositsIndex;\n        emit SetDepositsIndex(_newDepositsIndex);\n    }\n\n    /**\n     * @notice set the withdraw index so that we want to skip processing some withdraws\n     * @param _newWithdrawsIndex the new withdraw index\n     */\n    function setWithdrawsIndex(uint256 _newWithdrawsIndex) external onlyOwner {\n        withdrawsIndex = _newWithdrawsIndex;\n        emit SetWithdrawsIndex(_newWithdrawsIndex);\n    }\n\n    /**\n     * @notice queue USDC for deposit into crab strategy\n     * @param _amount USDC amount to deposit\n     */\n    function depositUSDC(uint256 _amount) external {\n        require(_amount >= minUSDCAmount, \"N1\");\n\n        IERC20(usdc).transferFrom(msg.sender, address(this), _amount);\n\n        // update usd balance of user, add their receipt, and receipt index to user deposits index\n        usdBalance[msg.sender] = usdBalance[msg.sender] + _amount;\n        deposits.push(Receipt(msg.sender, _amount, block.timestamp));\n        userDepositsIndex[msg.sender].push(deposits.length - 1);\n\n        emit USDCQueued(msg.sender, _amount, usdBalance[msg.sender], deposits.length - 1);\n    }\n\n    /**\n     * @notice withdraw USDC from queue\n     * @param _amount USDC amount to dequeue\n     * @param _force forceWithdraw if deposited more than a week ago\n     */\n    function withdrawUSDC(uint256 _amount, bool _force) external {\n        require(!isAuctionLive || _force, \"N2\");\n\n        usdBalance[msg.sender] = usdBalance[msg.sender] - _amount;\n        require(usdBalance[msg.sender] >= minUSDCAmount || usdBalance[msg.sender] == 0, \"N3\");\n\n        // start withdrawing from the users last deposit\n        uint256 toRemove = _amount;\n        uint256 lastIndexP1 = userDepositsIndex[msg.sender].length;\n        for (uint256 i = lastIndexP1; i > 0; i--) {\n            Receipt storage r = deposits[userDepositsIndex[msg.sender][i - 1]];\n            if (_force) {\n                require(block.timestamp > r.timestamp + 1 weeks, \"N4\");\n            }\n            if (r.amount > toRemove) {\n                r.amount -= toRemove;\n                toRemove = 0;\n                break;\n            } else {\n                toRemove -= r.amount;\n                delete deposits[userDepositsIndex[msg.sender][i - 1]];\n                userDepositsIndex[msg.sender].pop();\n            }\n        }\n        IERC20(usdc).transfer(msg.sender, _amount);\n\n        emit USDCDeQueued(msg.sender, _amount, usdBalance[msg.sender]);\n    }\n\n    /**\n     * @notice queue Crab for withdraw from crab strategy\n     * @param _amount crab amount to withdraw\n     */\n    function queueCrabForWithdrawal(uint256 _amount) external {\n        require(_amount >= minCrabAmount, \"N5\");\n        IERC20(crab).transferFrom(msg.sender, address(this), _amount);\n        crabBalance[msg.sender] = crabBalance[msg.sender] + _amount;\n        withdraws.push(Receipt(msg.sender, _amount, block.timestamp));\n        userWithdrawsIndex[msg.sender].push(withdraws.length - 1);\n        emit CrabQueued(msg.sender, _amount, crabBalance[msg.sender], withdraws.length - 1);\n    }\n\n    /**\n     * @notice withdraw Crab from queue\n     * @param _amount Crab amount to dequeue\n     * @param _force forceWithdraw if deposited more than a week ago\n     */\n    function dequeueCrab(uint256 _amount, bool _force) external {\n        require(!isAuctionLive || _force, \"N2\");\n        crabBalance[msg.sender] = crabBalance[msg.sender] - _amount;\n        require(crabBalance[msg.sender] >= minCrabAmount || crabBalance[msg.sender] == 0, \"N6\");\n        // deQueue crab from the last, last in first out\n        uint256 toRemove = _amount;\n        uint256 lastIndexP1 = userWithdrawsIndex[msg.sender].length;\n        for (uint256 i = lastIndexP1; i > 0; i--) {\n            Receipt storage r = withdraws[userWithdrawsIndex[msg.sender][i - 1]];\n            if (_force) {\n                require(block.timestamp > r.timestamp + 1 weeks, \"N4\");\n            }\n            if (r.amount > toRemove) {\n                r.amount -= toRemove;\n                toRemove = 0;\n                break;\n            } else {\n                toRemove -= r.amount;\n                delete withdraws[userWithdrawsIndex[msg.sender][i - 1]];\n                userWithdrawsIndex[msg.sender].pop();\n            }\n        }\n        IERC20(crab).transfer(msg.sender, _amount);\n        emit CrabDeQueued(msg.sender, _amount, crabBalance[msg.sender]);\n    }\n\n    /**\n     * @dev swaps _quantity amount of usdc for crab at _price\n     * @param _price price of crab in usdc\n     * @param _quantity amount of USDC to net\n     */\n    function netAtPrice(uint256 _price, uint256 _quantity) external onlyOwner {\n        _checkCrabPrice(_price);\n        uint256 crabQuantity = (_quantity * 1e18) / _price;\n        require(_quantity <= IERC20(usdc).balanceOf(address(this)), \"N7\");\n        require(crabQuantity <= IERC20(crab).balanceOf(address(this)), \"N8\");\n\n        // process deposits and send crab\n        uint256 i = depositsIndex;\n        uint256 amountToSend;\n        while (_quantity > 0) {\n            Receipt memory deposit = deposits[i];\n            if (deposit.amount == 0) {\n                i++;\n                continue;\n            }\n            if (deposit.amount <= _quantity) {\n                // deposit amount is lesser than quantity use it fully\n                _quantity = _quantity - deposit.amount;\n                usdBalance[deposit.sender] -= deposit.amount;\n                amountToSend = (deposit.amount * 1e18) / _price;\n                IERC20(crab).transfer(deposit.sender, amountToSend);\n                emit USDCDeposited(deposit.sender, deposit.amount, amountToSend, i, 0);\n                delete deposits[i];\n                i++;\n            } else {\n                // deposit amount is greater than quantity; use it partially\n                deposits[i].amount = deposit.amount - _quantity;\n                usdBalance[deposit.sender] -= _quantity;\n                amountToSend = (_quantity * 1e18) / _price;\n                IERC20(crab).transfer(deposit.sender, amountToSend);\n                emit USDCDeposited(deposit.sender, _quantity, amountToSend, i, 0);\n                _quantity = 0;\n            }\n        }\n        depositsIndex = i;\n\n        // process withdraws and send usdc\n        i = withdrawsIndex;\n        while (crabQuantity > 0) {\n            Receipt memory withdraw = withdraws[i];\n            if (withdraw.amount == 0) {\n                i++;\n                continue;\n            }\n            if (withdraw.amount <= crabQuantity) {\n                crabQuantity = crabQuantity - withdraw.amount;\n                crabBalance[withdraw.sender] -= withdraw.amount;\n                amountToSend = (withdraw.amount * _price) / 1e18;\n                IERC20(usdc).transfer(withdraw.sender, amountToSend);\n\n                emit CrabWithdrawn(withdraw.sender, withdraw.amount, amountToSend, i);\n\n                delete withdraws[i];\n                i++;\n            } else {\n                withdraws[i].amount = withdraw.amount - crabQuantity;\n                crabBalance[withdraw.sender] -= crabQuantity;\n                amountToSend = (crabQuantity * _price) / 1e18;\n                IERC20(usdc).transfer(withdraw.sender, amountToSend);\n\n                emit CrabWithdrawn(withdraw.sender, withdraw.amount, amountToSend, i);\n\n                crabQuantity = 0;\n            }\n        }\n        withdrawsIndex = i;\n    }\n\n    /**\n     * @return sum usdc amount in queue\n     */\n    function depositsQueued() external view returns (uint256) {\n        uint256 j = depositsIndex;\n        uint256 sum;\n        while (j < deposits.length) {\n            sum = sum + deposits[j].amount;\n            j++;\n        }\n        return sum;\n    }\n\n    /**\n     * @return sum crab amount in queue\n     */\n    function withdrawsQueued() external view returns (uint256) {\n        uint256 j = withdrawsIndex;\n        uint256 sum;\n        while (j < withdraws.length) {\n            sum = sum + withdraws[j].amount;\n            j++;\n        }\n        return sum;\n    }\n\n    function checkOrder(Order memory _order) external view {\n        return _checkOrder(_order);\n    }\n\n    /**\n     * @dev checks the expiry nonce and signer of an order\n     * @param _order is the Order struct\n     */\n    function _checkOrder(Order memory _order) internal view {\n        bytes32 structHash = keccak256(\n            abi.encode(\n                _CRAB_NETTING_TYPEHASH,\n                _order.bidId,\n                _order.trader,\n                _order.quantity,\n                _order.price,\n                _order.isBuying,\n                _order.expiry,\n                _order.nonce\n            )\n        );\n\n        bytes32 hash = _hashTypedDataV4(structHash);\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\n        require(offerSigner == _order.trader, \"N9\");\n        require(_order.expiry >= block.timestamp, \"N10\");\n    }\n\n    /**\n     * @dev calculates wSqueeth minted when amount is deposited\n     * @param _amount to deposit into crab\n     */\n    function _debtToMint(uint256 _amount) internal view returns (uint256) {\n        uint256 feeAdjustment = _calcFeeAdjustment();\n        (,, uint256 collateral, uint256 debt) = ICrabStrategyV2(crab).getVaultDetails();\n        uint256 wSqueethToMint = (_amount * debt) / (collateral + (debt * feeAdjustment) / 1e18);\n        return wSqueethToMint;\n    }\n\n    /**\n     * @dev takes in orders from mm's to buy sqth and deposits the usd amount from the depositQueue into crab along with the eth from selling sqth\n     * @param _p DepositAuction Params that contain orders, usdToDeposit, uniswap min amount and fee\n     */\n    function depositAuction(DepositAuctionParams calldata _p) external onlyOwner {\n        _checkOTCPrice(_p.clearingPrice, false);\n        uint256 ethUSDCPrice = IOracle(oracle).getTwap(ethUsdcPool, weth, usdc, auctionTwapPeriod, true);\n        require((_p.depositsQueued * (1e18 - otcPriceTolerance) * 1e12 / ethUSDCPrice) < _p.minEth, \"N11\");\n        /**\n         * step 1: get eth from mm\n         *     step 2: get eth from deposit usdc\n         *     step 3: crab deposit\n         *     step 4: flash deposit\n         *     step 5: send sqth to mms\n         *     step 6: send crab to depositors\n         */\n        uint256 initCrabBalance = IERC20(crab).balanceOf(address(this));\n        uint256 initEthBalance = address(this).balance;\n\n        uint256 sqthToSell = _debtToMint(_p.totalDeposit);\n        // step 1 get all the eth in\n        uint256 remainingToSell = sqthToSell;\n        for (uint256 i = 0; i < _p.orders.length; i++) {\n            require(_p.orders[i].isBuying, \"N12\");\n            require(_p.orders[i].price >= _p.clearingPrice, \"N13\");\n            _checkOrder(_p.orders[i]);\n            _useNonce(_p.orders[i].trader, _p.orders[i].nonce);\n            if (_p.orders[i].quantity >= remainingToSell) {\n                IWETH(weth).transferFrom(\n                    _p.orders[i].trader, address(this), (remainingToSell * _p.clearingPrice) / 1e18\n                );\n                remainingToSell = 0;\n                break;\n            } else {\n                IWETH(weth).transferFrom(\n                    _p.orders[i].trader, address(this), (_p.orders[i].quantity * _p.clearingPrice) / 1e18\n                );\n                remainingToSell -= _p.orders[i].quantity;\n            }\n        }\n        require(remainingToSell == 0, \"N14\");\n\n        // step 2\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\n            tokenIn: usdc,\n            tokenOut: weth,\n            fee: _p.ethUSDFee,\n            recipient: address(this),\n            deadline: block.timestamp,\n            amountIn: _p.depositsQueued,\n            amountOutMinimum: _p.minEth,\n            sqrtPriceLimitX96: 0\n        });\n        swapRouter.exactInputSingle(params);\n\n        // step 3\n        IWETH(weth).withdraw(IWETH(weth).balanceOf(address(this)));\n        ICrabStrategyV2(crab).deposit{value: _p.totalDeposit}();\n\n        // step 4\n        Portion memory to_send;\n        to_send.eth = address(this).balance - initEthBalance;\n        if (to_send.eth > 0 && _p.ethToFlashDeposit > 0) {\n            if (to_send.eth <= _p.ethToFlashDeposit) {\n                // we cant send more than the flashDeposit\n                ICrabStrategyV2(crab).flashDeposit{value: to_send.eth}(_p.ethToFlashDeposit, _p.flashDepositFee);\n            }\n        }\n\n        // step 5\n        to_send.sqth = IERC20(sqth).balanceOf(address(this));\n        remainingToSell = to_send.sqth;\n        for (uint256 j = 0; j < _p.orders.length; j++) {\n            if (_p.orders[j].quantity < remainingToSell) {\n                IERC20(sqth).transfer(_p.orders[j].trader, _p.orders[j].quantity);\n                remainingToSell -= _p.orders[j].quantity;\n                emit BidTraded(_p.orders[j].bidId, _p.orders[j].trader, _p.orders[j].quantity, _p.clearingPrice, true);\n            } else {\n                IERC20(sqth).transfer(_p.orders[j].trader, remainingToSell);\n                emit BidTraded(_p.orders[j].bidId, _p.orders[j].trader, remainingToSell, _p.clearingPrice, true);\n                break;\n            }\n        }\n\n        // step 6 send crab to depositors\n        uint256 remainingDeposits = _p.depositsQueued;\n        uint256 k = depositsIndex;\n\n        to_send.crab = IERC20(crab).balanceOf(address(this)) - initCrabBalance;\n        // get the balance between start and now\n        to_send.eth = address(this).balance - initEthBalance;\n        IWETH(weth).deposit{value: to_send.eth}();\n\n        while (remainingDeposits > 0) {\n            uint256 queuedAmount = deposits[k].amount;\n            Portion memory portion;\n            if (queuedAmount == 0) {\n                k++;\n                continue;\n            }\n            if (queuedAmount <= remainingDeposits) {\n                remainingDeposits = remainingDeposits - queuedAmount;\n                usdBalance[deposits[k].sender] -= queuedAmount;\n\n                portion.crab = queuedAmount * to_send.crab / _p.depositsQueued;\n\n                IERC20(crab).transfer(deposits[k].sender, portion.crab);\n\n                portion.eth = queuedAmount * to_send.eth / _p.depositsQueued;\n                if (portion.eth > 1e12) {\n                    IWETH(weth).transfer(deposits[k].sender, portion.eth);\n                } else {\n                    portion.eth = 0;\n                }\n                emit USDCDeposited(deposits[k].sender, queuedAmount, portion.crab, k, portion.eth);\n\n                delete deposits[k];\n                k++;\n            } else {\n                usdBalance[deposits[k].sender] -= remainingDeposits;\n\n                portion.crab = remainingDeposits * to_send.crab / _p.depositsQueued;\n                IERC20(crab).transfer(deposits[k].sender, portion.crab);\n\n                portion.eth = remainingDeposits * to_send.eth / _p.depositsQueued;\n                if (portion.eth > 1e12) {\n                    IWETH(weth).transfer(deposits[k].sender, portion.eth);\n                } else {\n                    portion.eth = 0;\n                }\n                emit USDCDeposited(deposits[k].sender, remainingDeposits, portion.crab, k, portion.eth);\n\n                deposits[k].amount -= remainingDeposits;\n                remainingDeposits = 0;\n            }\n        }\n        depositsIndex = k;\n        isAuctionLive = false;\n    }\n\n    /**\n     * @dev takes in orders from mm's to sell sqth and withdraws the crab amount in q\n     * @param _p Withdraw Params that contain orders, crabToWithdraw, uniswap min amount and fee\n     */\n    function withdrawAuction(WithdrawAuctionParams calldata _p) public onlyOwner {\n        _checkOTCPrice(_p.clearingPrice, true);\n        uint256 initWethBalance = IERC20(weth).balanceOf(address(this));\n        uint256 initEthBalance = address(this).balance;\n        /**\n         * step 1: get sqth from mms\n         *     step 2: withdraw from crab\n         *     step 3: send eth to mms\n         *     step 4: convert eth to usdc\n         *     step 5: send usdc to withdrawers\n         */\n\n        // step 1 get sqth from mms\n        uint256 sqthRequired = ICrabStrategyV2(crab).getWsqueethFromCrabAmount(_p.crabToWithdraw);\n        uint256 toPull = sqthRequired;\n        for (uint256 i = 0; i < _p.orders.length && toPull > 0; i++) {\n            _checkOrder(_p.orders[i]);\n            _useNonce(_p.orders[i].trader, _p.orders[i].nonce);\n            require(!_p.orders[i].isBuying, \"N15\");\n            require(_p.orders[i].price <= _p.clearingPrice, \"N16\");\n            if (_p.orders[i].quantity < toPull) {\n                toPull -= _p.orders[i].quantity;\n                IERC20(sqth).transferFrom(_p.orders[i].trader, address(this), _p.orders[i].quantity);\n            } else {\n                IERC20(sqth).transferFrom(_p.orders[i].trader, address(this), toPull);\n                toPull = 0;\n            }\n        }\n\n        // step 2 withdraw from crab\n        ICrabStrategyV2(crab).withdraw(_p.crabToWithdraw);\n\n        // step 3 pay all mms\n        IWETH(weth).deposit{value: address(this).balance - initEthBalance}();\n        toPull = sqthRequired;\n        uint256 sqthQuantity;\n        for (uint256 i = 0; i < _p.orders.length && toPull > 0; i++) {\n            if (_p.orders[i].quantity < toPull) {\n                sqthQuantity = _p.orders[i].quantity;\n            } else {\n                sqthQuantity = toPull;\n            }\n            IERC20(weth).transfer(_p.orders[i].trader, (sqthQuantity * _p.clearingPrice) / 1e18);\n            toPull -= sqthQuantity;\n            emit BidTraded(_p.orders[i].bidId, _p.orders[i].trader, sqthQuantity, _p.clearingPrice, false);\n        }\n\n        // step 4 convert to USDC\n        uint256 ethUSDCPrice = IOracle(oracle).getTwap(ethUsdcPool, weth, usdc, auctionTwapPeriod, true);\n        uint256 amountIn = (IERC20(weth).balanceOf(address(this)) - initWethBalance);\n        require((amountIn * ethUSDCPrice * (1e18 - otcPriceTolerance) / 1e36 / 1e12) < _p.minUSDC, \"N17\");\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\n            tokenIn: address(weth),\n            tokenOut: address(usdc),\n            fee: _p.ethUSDFee,\n            recipient: address(this),\n            deadline: block.timestamp,\n            amountIn: amountIn,\n            amountOutMinimum: _p.minUSDC,\n            sqrtPriceLimitX96: 0\n        });\n        uint256 usdcReceived = swapRouter.exactInputSingle(params);\n\n        // step 5 pay all withdrawers and mark their withdraws as done\n        uint256 remainingWithdraws = _p.crabToWithdraw;\n        uint256 j = withdrawsIndex;\n        uint256 usdcAmount;\n        while (remainingWithdraws > 0) {\n            Receipt memory withdraw = withdraws[j];\n            if (withdraw.amount == 0) {\n                j++;\n                continue;\n            }\n            if (withdraw.amount <= remainingWithdraws) {\n                // full usage\n                remainingWithdraws -= withdraw.amount;\n                crabBalance[withdraw.sender] -= withdraw.amount;\n\n                // send proportional usdc\n                usdcAmount = withdraw.amount * usdcReceived / _p.crabToWithdraw;\n                IERC20(usdc).transfer(withdraw.sender, usdcAmount);\n                emit CrabWithdrawn(withdraw.sender, withdraw.amount, usdcAmount, j);\n                delete withdraws[j];\n                j++;\n            } else {\n                withdraws[j].amount -= remainingWithdraws;\n                crabBalance[withdraw.sender] -= remainingWithdraws;\n\n                // send proportional usdc\n                usdcAmount = remainingWithdraws * usdcReceived / _p.crabToWithdraw;\n                IERC20(usdc).transfer(withdraw.sender, usdcAmount);\n                emit CrabWithdrawn(withdraw.sender, remainingWithdraws, usdcAmount, j);\n\n                remainingWithdraws = 0;\n            }\n        }\n        withdrawsIndex = j;\n        isAuctionLive = false;\n    }\n\n    /**\n     * @dev owner rejects the withdraw at index i thereby sending the withdrawer their crab back\n     * @param i index of the Withdraw receipt to reject\n     */\n    function rejectWithdraw(uint256 i) external onlyOwner {\n        Receipt memory withdraw = withdraws[i];\n        crabBalance[withdraw.sender] -= withdraw.amount;\n        ICrabStrategyV2(crab).transfer(withdraw.sender, withdraw.amount);\n        delete withdraws[i];\n\n        emit WithdrawRejected(withdraw.sender, withdraw.amount, i);\n    }\n\n    /**\n     * @notice owner can set the twap period in seconds that is used for obtaining TWAP prices\n     * @param _auctionTwapPeriod the twap period, in seconds\n     */\n    function setAuctionTwapPeriod(uint32 _auctionTwapPeriod) external onlyOwner {\n        require(_auctionTwapPeriod >= 180, \"N18\");\n        uint32 previousTwap = auctionTwapPeriod;\n\n        auctionTwapPeriod = _auctionTwapPeriod;\n\n        emit SetAuctionTwapPeriod(previousTwap, _auctionTwapPeriod);\n    }\n\n    /**\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\n     */\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\n        // Tolerance cannot be more than 20%\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \"N19\");\n        uint256 previousOtcTolerance = otcPriceTolerance;\n\n        otcPriceTolerance = _otcPriceTolerance;\n\n        emit SetOTCPriceTolerance(previousOtcTolerance, _otcPriceTolerance);\n    }\n\n    /**\n     * @dev set nonce flag of the trader to true\n     * @param _trader address of the signer\n     * @param _nonce number that is to be traded only once\n     */\n    function _useNonce(address _trader, uint256 _nonce) internal {\n        require(!nonces[_trader][_nonce], \"N20\");\n        nonces[_trader][_nonce] = true;\n    }\n\n    /**\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\n     * @param _price clearing price provided by manager\n     * @param _isAuctionBuying is crab buying or selling oSQTH\n     */\n    function _checkOTCPrice(uint256 _price, bool _isAuctionBuying) internal view {\n        // Get twap\n        uint256 squeethEthPrice = IOracle(oracle).getTwap(ethSqueethPool, sqth, weth, auctionTwapPeriod, true);\n\n        if (_isAuctionBuying) {\n            require(_price <= (squeethEthPrice * (1e18 + otcPriceTolerance)) / 1e18, \"N21\");\n        } else {\n            require(_price >= (squeethEthPrice * (1e18 - otcPriceTolerance)) / 1e18, \"N22\");\n        }\n    }\n\n    function _checkCrabPrice(uint256 _price) internal view {\n        // Get twap\n        uint256 squeethEthPrice = IOracle(oracle).getTwap(ethSqueethPool, sqth, weth, auctionTwapPeriod, true);\n        uint256 usdcEthPrice = IOracle(oracle).getTwap(ethUsdcPool, weth, usdc, auctionTwapPeriod, true);\n        (,, uint256 collateral, uint256 debt) = ICrabStrategyV2(crab).getVaultDetails();\n        uint256 crabFairPrice =\n            ((collateral - ((debt * squeethEthPrice) / 1e18)) * usdcEthPrice) / ICrabStrategyV2(crab).totalSupply();\n        crabFairPrice = crabFairPrice / 1e12; //converting from units of 18 to 6\n        require(_price <= (crabFairPrice * (1e18 + otcPriceTolerance)) / 1e18, \"N23\");\n        require(_price >= (crabFairPrice * (1e18 - otcPriceTolerance)) / 1e18, \"N24\");\n    }\n\n    function _calcFeeAdjustment() internal view returns (uint256) {\n        uint256 feeRate = IController(sqthController).feeRate();\n        if (feeRate == 0) return 0;\n        uint256 squeethEthPrice = IOracle(oracle).getTwap(ethSqueethPool, sqth, weth, sqthTwapPeriod, true);\n        return (squeethEthPrice * feeRate) / 10000;\n    }\n\n    receive() external payable {\n        require(msg.sender == weth || msg.sender == crab, \"N25\");\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/src/interfaces/IController.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\n\ninterface IController {\n    function feeRate() external view returns (uint256);\n\n    function TWAP_PERIOD() external view returns (uint32);\n\n    function quoteCurrency() external view returns (address);\n\n    function ethQuoteCurrencyPool() external view returns (address);\n\n    function setFeeRate(uint256 _newFeeRate) external;\n\n    function setFeeRecipient(address _newFeeRecipient) external;\n}\n"
  },
  {
    "path": "packages/crab-netting/src/interfaces/ICrabStrategyV2.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport {IERC20} from \"openzeppelin/interfaces/IERC20.sol\";\n\ninterface ICrabStrategyV2 is IERC20 {\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256);\n\n    function deposit() external payable;\n\n    function withdraw(uint256 _crabAmount) external;\n\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\n\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256);\n\n    function powerTokenController() external view returns (address);\n\n    function weth() external view returns (address);\n\n    function wPowerPerp() external view returns (address);\n\n    function oracle() external view returns (address);\n\n    function ethWSqueethPool() external view returns (address);\n}\n"
  },
  {
    "path": "packages/crab-netting/src/interfaces/IOracle.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\ninterface IOracle {\n    function getTwap(address _pool, address _base, address _quote, uint32 _period, bool _checkPeriod)\n        external\n        view\n        returns (uint256);\n}\n"
  },
  {
    "path": "packages/crab-netting/src/interfaces/IWETH.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport {IERC20} from \"openzeppelin/interfaces/IERC20.sol\";\n\ninterface IWETH is IERC20 {\n    function deposit() external payable;\n\n    function withdraw(uint256 wad) external;\n}\n"
  },
  {
    "path": "packages/crab-netting/test/BaseForkSetup.t.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\n\nimport \"forge-std/Test.sol\";\n\nimport {ERC20} from \"openzeppelin/token/ERC20/ERC20.sol\";\nimport {IWETH} from \"../src/interfaces/IWETH.sol\";\nimport {IOracle} from \"../src/interfaces/IOracle.sol\";\nimport {ICrabStrategyV2} from \"../src/interfaces/ICrabStrategyV2.sol\";\nimport {CrabNetting, Order} from \"../src/CrabNetting.sol\";\nimport \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\nimport {IQuoter} from \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\";\nimport {IController} from \"../src/interfaces/IController.sol\";\n\ncontract BaseForkSetup is Test {\n    ICrabStrategyV2 crab;\n    ERC20 usdc;\n    IWETH weth;\n    ERC20 sqth;\n    CrabNetting netting;\n    ISwapRouter swapRouter;\n    IController sqthController;\n    IQuoter quoter;\n    IOracle oracle;\n    uint256 activeFork;\n\n    uint256 internal ownerPrivateKey;\n    address internal owner;\n    uint256 internal depositorPk;\n    address internal depositor;\n    uint256 internal withdrawerPk;\n    address internal withdrawer;\n\n    uint256 internal mm1Pk;\n    address internal mm1;\n\n    uint256 internal mm2Pk;\n    address internal mm2;\n\n    Order[] orders;\n\n    function setUp() public virtual {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        activeFork = vm.createSelectFork(FORK_URL, 15819213);\n\n        crab = ICrabStrategyV2(0x3B960E47784150F5a63777201ee2B15253D713e8);\n        weth = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n        usdc = ERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n        sqth = ERC20(0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B);\n        swapRouter = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);\n        quoter = IQuoter(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);\n        oracle = IOracle(0x65D66c76447ccB45dAf1e8044e918fA786A483A1);\n        sqthController = IController(0x64187ae08781B09368e6253F9E94951243A493D5);\n\n        netting = new CrabNetting(address(crab), address(swapRouter));\n        vm.prank(address(netting));\n        payable(depositor).transfer(address(netting).balance);\n\n        ownerPrivateKey = 0xA11CE;\n        owner = vm.addr(ownerPrivateKey);\n\n        depositorPk = 0xA11CA;\n        depositor = vm.addr(depositorPk);\n        vm.label(depositor, \"depositor\");\n\n        withdrawerPk = 0xA11CB;\n        withdrawer = vm.addr(withdrawerPk);\n        vm.label(withdrawer, \"withdrawer\");\n\n        mm1Pk = 0xA11CC;\n        mm1 = vm.addr(mm1Pk);\n        vm.label(mm1, \"market maker 1\");\n        mm2Pk = 0xA11CA;\n        mm2 = vm.addr(mm2Pk);\n        vm.label(mm2, \"market maker 2\");\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/test/BaseSetup.t.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\n\nimport \"forge-std/Test.sol\";\nimport {ERC20} from \"openzeppelin/token/ERC20/ERC20.sol\";\n\nimport {CrabNetting} from \"../src/CrabNetting.sol\";\nimport \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\nimport {IOracle} from \"../src/interfaces/IOracle.sol\";\n\ncontract FixedERC20 is ERC20 {\n    constructor(uint256 initialSupply) ERC20(\"USDC\", \"USDC\") {\n        _mint(msg.sender, initialSupply);\n    }\n}\n\ncontract BaseSetup is Test {\n    FixedERC20 usdc;\n    FixedERC20 crab;\n    FixedERC20 weth;\n    FixedERC20 sqth;\n    CrabNetting netting;\n    ISwapRouter public immutable swapRouter = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);\n\n    IOracle public immutable oracle = IOracle(0x65D66c76447ccB45dAf1e8044e918fA786A483A1);\n\n    uint256 internal ownerPrivateKey;\n    address internal owner;\n    uint256 internal depositorPk;\n    address internal depositor;\n    uint256 internal withdrawerPk;\n    address internal withdrawer;\n\n    function setUp() public virtual {\n        usdc = new FixedERC20(10000 * 1e6);\n        crab = new FixedERC20(10000 * 1e18);\n        weth = new FixedERC20(10000 * 1e18);\n        sqth = new FixedERC20(10000 * 1e18);\n        netting = new CrabNetting(address(crab), address(swapRouter));\n\n        ownerPrivateKey = 0xA11CE;\n        owner = vm.addr(ownerPrivateKey);\n\n        depositorPk = 0xA11CA;\n        depositor = vm.addr(depositorPk);\n        vm.label(depositor, \"depositor\");\n\n        withdrawerPk = 0xA11CB;\n        withdrawer = vm.addr(withdrawerPk);\n        vm.label(withdrawer, \"withdrawer\");\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/test/Deposit.t.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport {BaseForkSetup} from \"./BaseForkSetup.t.sol\";\n\ncontract DepositTest is BaseForkSetup {\n    function setUp() public override {\n        BaseForkSetup.setUp(); // gives you netting, depositor, withdrawer, usdc, crab\n\n        vm.startPrank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        usdc.transfer(depositor, 20e6);\n        vm.stopPrank();\n\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        crab.transfer(withdrawer, 20e18);\n    }\n\n    function testDepositMin() public {\n        netting.setMinUSDC(1e6);\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 2 * 1e6);\n        netting.depositUSDC(1e6);\n        assertEq(netting.usdBalance(depositor), 1e6);\n    }\n\n    function testDepositLessThanMin() public {\n        netting.setMinUSDC(1e6);\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 5 * 1e5);\n        vm.expectRevert();\n        netting.depositUSDC(5e5);\n    }\n\n    function testDepositAndWithdrawPartialUSDC() public {\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 2 * 1e6);\n\n        netting.depositUSDC(2 * 1e6);\n        assertEq(netting.usdBalance(depositor), 2e6);\n\n        netting.withdrawUSDC(1 * 1e6, false);\n\n        assertEq(netting.usdBalance(depositor), 1e6);\n        assertEq(netting.depositsQueued(), 1e6);\n    }\n\n    function testDepositAndWithdrawFullUSDC() public {\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 2 * 1e6);\n\n        netting.depositUSDC(2 * 1e6);\n        assertEq(netting.usdBalance(depositor), 2e6);\n\n        netting.withdrawUSDC(2 * 1e6, false);\n        assertEq(netting.usdBalance(depositor), 0);\n        assertEq(netting.depositsQueued(), 0);\n    }\n\n    function testLargeWithdraw() public {\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 4 * 1e6);\n\n        netting.depositUSDC(2 * 1e6);\n        netting.depositUSDC(2 * 1e6);\n        assertEq(netting.usdBalance(depositor), 4e6);\n\n        netting.withdrawUSDC(3 * 1e6, false);\n        assertEq(netting.usdBalance(depositor), 1e6);\n        assertEq(netting.depositsQueued(), 1e6);\n    }\n\n    function testDepositAndWithdrawCrabPartial() public {\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), 2 * 1e6);\n\n        netting.queueCrabForWithdrawal(2 * 1e6);\n        assertEq(netting.crabBalance(withdrawer), 2e6);\n\n        netting.dequeueCrab(1 * 1e6, false);\n        assertEq(netting.crabBalance(withdrawer), 1e6);\n        assertEq(netting.withdrawsQueued(), 1e6);\n    }\n\n    function testDepositAndWithdrawCrabFull() public {\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), 2 * 1e6);\n\n        netting.queueCrabForWithdrawal(2 * 1e6);\n        assertEq(netting.crabBalance(withdrawer), 2e6);\n\n        netting.dequeueCrab(2 * 1e6, false);\n        assertEq(netting.crabBalance(withdrawer), 0);\n        assertEq(netting.withdrawsQueued(), 0);\n    }\n\n    function testCrabDepositLargeWithdraw() public {\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), 4 * 1e6);\n\n        netting.queueCrabForWithdrawal(2 * 1e6);\n        netting.queueCrabForWithdrawal(2 * 1e6);\n        assertEq(netting.crabBalance(withdrawer), 4e6);\n\n        netting.dequeueCrab(3 * 1e6, false);\n\n        assertEq(netting.crabBalance(withdrawer), 1e6, \"withdrawer balance incorrect\");\n        assertEq(netting.withdrawsQueued(), 1e6, \"withdraws queued balance incorrect\");\n    }\n\n    function testCannotWithdrawCrabWhenAuctionLive() public {\n        netting.toggleAuctionLive();\n\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), 2 * 1e18);\n        netting.queueCrabForWithdrawal(2 * 1e18);\n\n        vm.expectRevert(bytes(\"N2\"));\n        netting.dequeueCrab(2 * 1e18, false);\n        vm.stopPrank();\n    }\n\n    function testCannotWithdrawUSDCWhenAuctionLive() public {\n        netting.toggleAuctionLive();\n\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 2 * 1e6);\n        netting.depositUSDC(2 * 1e6);\n\n        vm.expectRevert(bytes(\"N2\"));\n        netting.withdrawUSDC(2 * 1e6, false);\n        vm.stopPrank();\n    }\n\n    function testDepositAndWithdrawFail_POC() public {\n        netting.setMinUSDC(10e6);\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 10e9);\n        netting.depositUSDC(10e6);\n\n        for (uint256 i = 0; i < 100; i++) {\n            netting.depositUSDC(10e6);\n            netting.withdrawUSDC{gas: 200_000}(10e6, false);\n        }\n    }\n\n    function testWithdrawAndDeQueueFail_POC() public {\n        netting.setMinCrab(1);\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), 20e18);\n        netting.queueCrabForWithdrawal(10e18);\n\n        for (uint256 i = 0; i < 100; i++) {\n            netting.queueCrabForWithdrawal(10);\n            netting.dequeueCrab{gas: 200_000}(10e6, false);\n        }\n    }\n\n    function testForceWithdraw() public {\n        uint256 startBalance = usdc.balanceOf(depositor);\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 2 * 1e6);\n        netting.depositUSDC(2 * 1e6);\n        vm.stopPrank();\n\n        netting.toggleAuctionLive();\n\n        vm.startPrank(depositor);\n        vm.expectRevert(bytes(\"N2\"));\n        netting.withdrawUSDC(2e6, false);\n        skip(8 * 24 * 60 * 60);\n        netting.withdrawUSDC(2e6, true);\n        assertEq(startBalance, usdc.balanceOf(depositor));\n    }\n\n    function testForceWithdrawCrab() public {\n        uint256 startBalance = crab.balanceOf(withdrawer);\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), 2e18);\n        netting.queueCrabForWithdrawal(2e18);\n        vm.stopPrank();\n\n        netting.toggleAuctionLive();\n\n        vm.startPrank(withdrawer);\n        vm.expectRevert(bytes(\"N2\"));\n        netting.dequeueCrab(2e18, false);\n        skip(8 * 24 * 60 * 60);\n        netting.dequeueCrab(2e18, true);\n        assertEq(startBalance, crab.balanceOf(withdrawer));\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/test/DepositAuction.t.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport \"forge-std/Test.sol\";\nimport {BaseForkSetup} from \"./BaseForkSetup.t.sol\";\n\nimport {Order, DepositAuctionParams} from \"../src/CrabNetting.sol\";\nimport {ICrabStrategyV2} from \"../src/interfaces/ICrabStrategyV2.sol\";\n\nimport {SigUtils} from \"./utils/SigUtils.sol\";\n\nstruct Sign {\n    uint8 v;\n    bytes32 r;\n    bytes32 s;\n}\n\ncontract DepositAuctionTest is BaseForkSetup {\n    SigUtils sig;\n\n    function setUp() public override {\n        BaseForkSetup.setUp();\n        sig = new SigUtils(netting.DOMAIN_SEPARATOR());\n\n        vm.deal(depositor, 100000000e18);\n\n        // this is a crab whale, get some crab token from\n        //vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        // crab.tranfer(depositor, 100e18);\n\n        // some WETH and USDC rich address\n        vm.startPrank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        weth.transfer(depositor, 10000e18);\n        weth.transfer(mm1, 1000e18);\n        weth.transfer(mm2, 1000e18);\n        usdc.transfer(depositor, 500000e6);\n        vm.stopPrank();\n\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 1500000 * 1e6);\n        netting.depositUSDC(200000 * 1e6);\n        vm.stopPrank();\n\n        // depositor has queued in 200k USDC\n    }\n\n    function _findTotalDepositAndToMint(uint256 _eth, uint256 _collateral, uint256 _debt, uint256 _price)\n        internal\n        pure\n        returns (uint256, uint256)\n    {\n        uint256 totalDeposit = (_eth * 1e18) / (1e18 - ((_debt * _price) / _collateral));\n        return (totalDeposit, (totalDeposit * _debt) / _collateral);\n    }\n\n    function _findTotalDepositFromAuctioned(uint256 _collateral, uint256 _debt, uint256 _auctionedSqth)\n        internal\n        pure\n        returns (uint256)\n    {\n        return (_collateral * _auctionedSqth) / _debt;\n    }\n\n    function testDepositAuctionPartialFill() public {\n        DepositAuctionParams memory p;\n        uint256 sqthPriceLimit = (_getSqthPrice(1e18) * 988) / 1000;\n        (,, uint256 collateral, uint256 debt) = crab.getVaultDetails();\n        // Large first deposit. 10 & 40 as the deposit. 20 is the amount to net\n        vm.prank(depositor);\n        netting.depositUSDC(300000 * 1e6); //200+300 500k usdc deposited\n\n        p.depositsQueued = 300000 * 1e6;\n        p.minEth = (_convertUSDToETH(p.depositsQueued) * 9975) / 10000;\n\n        uint256 toMint;\n        (p.totalDeposit, toMint) = _findTotalDepositAndToMint(p.minEth, collateral, debt, sqthPriceLimit);\n        bool trade_works = _isEnough(p.minEth, toMint, sqthPriceLimit, p.totalDeposit);\n        require(trade_works, \"depositing more than we have from sellling\");\n        Order memory order =\n            Order(0, mm1, toMint, (sqthPriceLimit * 1005) / 1000, true, block.timestamp, 0, 1, 0x00, 0x00);\n\n        bytes32 digest = sig.getTypedDataHash(order);\n        (uint8 v, bytes32 r, bytes32 s) = vm.sign(mm1Pk, digest);\n        order.v = v;\n        order.r = r;\n        order.s = s;\n\n        orders.push(order);\n        p.orders = orders;\n        vm.prank(mm1);\n        weth.approve(address(netting), 1e30);\n\n        p.clearingPrice = (sqthPriceLimit * 1005) / 1000;\n        uint256 excessEth = (toMint * (p.clearingPrice - sqthPriceLimit)) / 1e18;\n\n        p.ethUSDFee = 500;\n        p.flashDepositFee = 3000;\n\n        // Find the borrow ration for toFlash\n        uint256 mid = _findBorrow(excessEth, debt, collateral);\n        p.ethToFlashDeposit = (excessEth * mid) / 10 ** 7;\n        // ------------- //\n        uint256 depositorBalance = weth.balanceOf(depositor);\n        netting.depositAuction(p);\n\n        assertApproxEqAbs(ICrabStrategyV2(crab).balanceOf(depositor), 221e18, 1e18);\n        assertEq(netting.usdBalance(depositor), 200000e6);\n        assertEq(sqth.balanceOf(mm1), toMint);\n        assertEq(weth.balanceOf(address(netting)), 1);\n        assertApproxEqAbs(weth.balanceOf(depositor) - depositorBalance, 5e17, 1e17);\n    }\n\n    function testDepositAuctionAfterFullWithdrawal() public {\n        vm.startPrank(depositor);\n        console.log(netting.usdBalance(depositor), \"depositor balance\");\n        netting.withdrawUSDC(netting.usdBalance(depositor), false);\n        assertEq(netting.usdBalance(depositor), 0, \"depositor balancez ero\");\n        netting.depositUSDC(200000e6);\n        vm.stopPrank();\n\n        DepositAuctionParams memory p;\n        uint256 sqthPriceLimit = (_getSqthPrice(1e18) * 988) / 1000;\n        (,, uint256 collateral, uint256 debt) = crab.getVaultDetails();\n        // Large first deposit. 10 & 40 as the deposit. 20 is the amount to net\n        vm.prank(depositor);\n        netting.depositUSDC(300000 * 1e6); //200+300 500k usdc deposited\n\n        p.depositsQueued = 300000 * 1e6;\n        p.minEth = (_convertUSDToETH(p.depositsQueued) * 9975) / 10000;\n\n        uint256 toMint;\n        (p.totalDeposit, toMint) = _findTotalDepositAndToMint(p.minEth, collateral, debt, sqthPriceLimit);\n        bool trade_works = _isEnough(p.minEth, toMint, sqthPriceLimit, p.totalDeposit);\n        require(trade_works, \"depositing more than we have from sellling\");\n        Order memory order =\n            Order(0, mm1, toMint, (sqthPriceLimit * 1005) / 1000, true, block.timestamp, 0, 1, 0x00, 0x00);\n\n        bytes32 digest = sig.getTypedDataHash(order);\n        (uint8 v, bytes32 r, bytes32 s) = vm.sign(mm1Pk, digest);\n        order.v = v;\n        order.r = r;\n        order.s = s;\n\n        orders.push(order);\n        p.orders = orders;\n        vm.prank(mm1);\n        weth.approve(address(netting), 1e30);\n\n        p.clearingPrice = (sqthPriceLimit * 1005) / 1000;\n        uint256 excessEth = (toMint * (p.clearingPrice - sqthPriceLimit)) / 1e18;\n\n        p.ethUSDFee = 500;\n        p.flashDepositFee = 3000;\n\n        // Find the borrow ration for toFlash\n        uint256 mid = _findBorrow(excessEth, debt, collateral);\n        p.ethToFlashDeposit = (excessEth * mid) / 10 ** 7;\n        // ------------- //\n        uint256 depositorBalance = weth.balanceOf(depositor);\n        console.log(depositorBalance, \"balance bfore\");\n        netting.depositAuction(p);\n\n        console.log(ICrabStrategyV2(crab).balanceOf(depositor), \"crab balance\");\n        assertGt(ICrabStrategyV2(crab).balanceOf(depositor), 221e18);\n        assertEq(netting.usdBalance(depositor), 200000e6);\n        assertEq(sqth.balanceOf(mm1), toMint);\n        assertLe(weth.balanceOf(address(netting)), 1e16);\n        assertGt(weth.balanceOf(depositor) - depositorBalance, 5e17, \"0.5 eth not remaining\");\n        assertEq(netting.depositsIndex(), 2);\n    }\n\n    function testSqthPriceTooLow() public {\n        DepositAuctionParams memory p;\n        uint256 sqthPriceLimit = (_getSqthPrice(1e18) * 99) / 100;\n        (,, uint256 collateral, uint256 debt) = crab.getVaultDetails();\n        // Large first deposit. 10 & 40 as the deposit. 20 is the amount to net\n        vm.prank(depositor);\n        netting.depositUSDC(300000 * 1e6); //200+300 500k usdc deposited\n\n        p.depositsQueued = 300000 * 1e6;\n        p.minEth = (_convertUSDToETH(p.depositsQueued) * 9975) / 10000;\n\n        uint256 toMint;\n        (p.totalDeposit, toMint) = _findTotalDepositAndToMint(p.minEth, collateral, debt, sqthPriceLimit);\n        Order memory order = Order(0, mm1, toMint, sqthPriceLimit, true, block.timestamp, 0, 1, 0x00, 0x00);\n        orders.push(order);\n        p.orders = orders;\n\n        vm.prank(mm1);\n        weth.approve(address(netting), 1e30);\n\n        p.clearingPrice = (sqthPriceLimit * 94) / 100;\n        p.ethUSDFee = 500;\n        p.flashDepositFee = 3000;\n        p.ethToFlashDeposit = (p.ethToFlashDeposit * 1) / 10 ** 7;\n\n        vm.expectRevert(bytes(\"N22\"));\n        netting.depositAuction(p);\n    }\n\n    function testFirstDepositAuction() public {\n        DepositAuctionParams memory p;\n        // get the usd to deposit remaining\n        p.depositsQueued = netting.depositsQueued();\n        // find the eth value of it\n        p.minEth = (_convertUSDToETH(p.depositsQueued) * 9975) / 10000;\n\n        // lets get the uniswap price, you can get this from uniswap function in crabstratgegy itself\n        uint256 sqthPrice = (_getSqthPrice(1e18) * 988) / 1000;\n        // get the vault details\n        (,, uint256 collateral, uint256 debt) = crab.getVaultDetails();\n        // get the total deposit\n        uint256 toMint;\n        (p.totalDeposit, toMint) = _findTotalDepositAndToMint(p.minEth, collateral, debt, sqthPrice);\n        // --------\n        // then write a test suite with a high eth value where it fails\n        bool trade_works = _isEnough(p.minEth, toMint, sqthPrice, p.totalDeposit);\n        require(trade_works, \"depositing more than we have from sellling\");\n\n        // if i sell the sqth and get eth add to user eth, will it be > total deposit\n\n        // then reduce the total value to get more trade value like in crab otc looping\n        // find out the root cause of this rounding issue\n\n        // turns out the issue did not occur,\n        // so we go ahead as though the auction closed for 0.993 osqth price\n\n        Order memory order =\n            Order(0, mm1, toMint - 1e18, (sqthPrice * 1005) / 1000, true, block.timestamp, 0, 1, 0x00, 0x00);\n\n        Sign memory s;\n        (s.v, s.r, s.s) = vm.sign(mm1Pk, sig.getTypedDataHash(order));\n        order.v = s.v;\n        order.r = s.r;\n        order.s = s.s;\n\n        Order memory order0 = Order(0, mm1, 1e18, (sqthPrice * 1005) / 1000, true, block.timestamp, 1, 1, 0x00, 0x00);\n\n        Sign memory s0;\n        (s0.v, s0.r, s0.s) = vm.sign(mm1Pk, sig.getTypedDataHash(order0));\n        order0.v = s0.v;\n        order0.r = s0.r;\n        order0.s = s0.s;\n\n        orders.push(order0);\n        orders.push(order);\n        vm.prank(mm1);\n        weth.approve(address(netting), 1e30);\n\n        p.orders = orders;\n        p.clearingPrice = (sqthPrice * 1005) / 1000;\n        uint256 excessEth = (toMint * (p.clearingPrice - sqthPrice)) / 1e18;\n        console.log(excessEth, \"excess eth is\");\n\n        console.log(ICrabStrategyV2(crab).balanceOf(depositor), \"balance start crab\");\n\n        // Find the borrow ration for toFlash\n        uint256 mid = _findBorrow(excessEth, debt, collateral);\n        console.log(mid, \"borrow percentage is\");\n        p.ethToFlashDeposit = (excessEth * mid) / 10 ** 7;\n        console.log(\"after multiplying\", p.ethToFlashDeposit);\n        p.ethUSDFee = 500;\n        p.flashDepositFee = 3000;\n        // ------------- //\n        console.log(p.depositsQueued, p.minEth, p.totalDeposit, toMint);\n        console.log(p.clearingPrice);\n        uint256 initEthBalance = weth.balanceOf(depositor);\n        netting.depositAuction(p);\n\n        assertApproxEqAbs(ICrabStrategyV2(crab).balanceOf(depositor), 147e18, 1e18);\n        assertEq(sqth.balanceOf(mm1), toMint);\n        assertApproxEqAbs(weth.balanceOf(depositor) - initEthBalance, 3e17, 1e17);\n    }\n\n    function testFirstDepositAuctionWithFee() public {\n        vm.startPrank(0x609FFF64429e2A275a879e5C50e415cec842c629);\n        sqthController.setFeeRecipient(depositor);\n        sqthController.setFeeRate(10);\n        vm.stopPrank();\n\n        DepositAuctionParams memory p;\n        p.depositsQueued = netting.depositsQueued();\n        p.minEth = (_convertUSDToETH(p.depositsQueued) * 9975) / 10000;\n\n        uint256 sqthPrice = (_getSqthPrice(1e18) * 988) / 1000;\n        (,, uint256 collateral, uint256 debt) = crab.getVaultDetails();\n        uint256 toMint;\n        (p.totalDeposit, toMint) = _findTotalDepositAndToMint(p.minEth, collateral, debt, sqthPrice);\n        bool trade_works = _isEnough(p.minEth, toMint, sqthPrice, p.totalDeposit);\n        require(trade_works, \"depositing more than we have from sellling\");\n        Order memory order =\n            Order(0, mm1, toMint - 1e18, (sqthPrice * 1005) / 1000, true, block.timestamp, 0, 1, 0x00, 0x00);\n\n        Sign memory s;\n        (s.v, s.r, s.s) = vm.sign(mm1Pk, sig.getTypedDataHash(order));\n        order.v = s.v;\n        order.r = s.r;\n        order.s = s.s;\n\n        Order memory order0 = Order(0, mm1, 1e18, (sqthPrice * 1005) / 1000, true, block.timestamp, 1, 1, 0x00, 0x00);\n\n        Sign memory s0;\n        (s0.v, s0.r, s0.s) = vm.sign(mm1Pk, sig.getTypedDataHash(order0));\n        order0.v = s0.v;\n        order0.r = s0.r;\n        order0.s = s0.s;\n\n        orders.push(order0);\n        orders.push(order);\n        vm.prank(mm1);\n        weth.approve(address(netting), 1e30);\n\n        p.orders = orders;\n        p.clearingPrice = (sqthPrice * 1005) / 1000;\n        uint256 excessEth = (toMint * (p.clearingPrice - sqthPrice)) / 1e18;\n\n        // Find the borrow ration for toFlash\n        uint256 mid = _findBorrow(excessEth, debt, collateral);\n        p.ethToFlashDeposit = (excessEth * mid) / 10 ** 7;\n        p.ethUSDFee = 500;\n        p.flashDepositFee = 3000;\n        // ------------- //\n        uint256 initEthBalance = weth.balanceOf(depositor);\n        netting.depositAuction(p);\n\n        assertApproxEqAbs(ICrabStrategyV2(crab).balanceOf(depositor), 147e18, 1e18);\n        assertApproxEqAbs(sqth.balanceOf(mm1), toMint, 2e18);\n        assertApproxEqAbs(weth.balanceOf(depositor) - initEthBalance, 3e17, 1e17);\n    }\n\n    // TODO find a way to make this reusable and test easily\n    // for multiple ETH movements and external events like partial fills\n    // eth going down\n    function testDepositAuctionEthUp() public {\n        DepositAuctionParams memory p;\n        // get the usd to deposit remaining\n        p.depositsQueued = netting.depositsQueued();\n        // find the eth value of it\n        p.minEth = _convertUSDToETH(p.depositsQueued);\n        console.log(\"Starting ETH\", p.minEth / 10 ** 18);\n\n        // lets get the uniswap price, you can get this from uniswap function in crabstratgegy itself\n        uint256 sqthPrice = (_getSqthPrice(1e18) * 988) / 1000;\n        // get the vault details\n        (,, uint256 collateral, uint256 debt) = crab.getVaultDetails();\n        // get the total deposit\n        uint256 toMint;\n        (p.totalDeposit, toMint) = _findTotalDepositAndToMint(p.minEth, collateral, debt, sqthPrice);\n        console.log(\"Auctioning for \", toMint / 10 ** 18, \"sqth\");\n        // --------\n        // then write a test suite with a high eth value where it fails\n        require(_isEnough(p.minEth, toMint, sqthPrice, p.totalDeposit), \"depositing more than we have from sellling\");\n\n        // if i sell the sqth and get eth add to user eth, will it be > total deposit\n\n        // then reduce the total value to get more trade value like in crab otc looping\n        // find out the root cause of this rounding issue\n\n        // turns out the issue did not occur,\n        // so we go ahead as though the auction closed for 0.993 osqth price\n\n        Order memory order = Order(\n            0,\n            mm1,\n            toMint,\n            63974748984830990, // sqth price in the future\n            true,\n            block.timestamp + 26000000,\n            0,\n            1,\n            0x00,\n            0x00\n        );\n\n        (uint8 v, bytes32 r, bytes32 s) = vm.sign(mm1Pk, sig.getTypedDataHash(order));\n        order.v = v;\n        order.r = r;\n        order.s = s;\n        orders.push(order);\n        vm.prank(mm1);\n        weth.approve(address(netting), 1e30);\n\n        p.orders = orders;\n        p.clearingPrice = (sqthPrice * 1005) / 1000;\n        uint256 excessEth = (toMint * (p.clearingPrice - sqthPrice)) / 1e18;\n\n        console.log(ICrabStrategyV2(crab).balanceOf(depositor), \"balance start crab\");\n\n        // Find the borrow ration for toFlash\n        uint256 mid = _findBorrow(excessEth, debt, collateral);\n        p.ethToFlashDeposit = (excessEth * mid) / 10 ** 7;\n        p.ethUSDFee = 500;\n        p.flashDepositFee = 3000;\n        // ------------- //\n\n        // vm.stopPrank();\n        assertEq(activeFork, vm.activeFork());\n        vm.makePersistent(address(netting));\n        vm.makePersistent(address(weth));\n        vm.makePersistent(address(usdc));\n\n        vm.rollFork(activeFork, 15829113);\n        console.log(address(depositor).balance, \"starting\");\n        p.minEth = _convertUSDToETH(p.depositsQueued);\n        p.clearingPrice = _getSqthPrice(1e18);\n        console.log(\"Ending ETH\", p.minEth / 10 ** 18);\n        (,, collateral, debt) = ICrabStrategyV2(crab).getVaultDetails();\n        p.totalDeposit = _findTotalDepositFromAuctioned(collateral, debt, toMint);\n        console.log(\"Using only\", toMint, \"sqth\");\n        console.log(p.totalDeposit);\n\n        uint256 mm1Balance = weth.balanceOf(mm1);\n        uint256 initDepositorBalance = weth.balanceOf(depositor);\n        netting.depositAuction(p);\n        assertLe(((toMint * p.clearingPrice) / 10 ** 18) - (mm1Balance - weth.balanceOf(mm1)), 180);\n\n        assertApproxEqAbs(ICrabStrategyV2(crab).balanceOf(depositor), 147e18, 5e18);\n        assertApproxEqAbs(\n            sqth.balanceOf(mm1), toMint, 0.001e18, \"All minted not sold, check if we sold only what we took for\"\n        );\n        assertApproxEqAbs(\n            weth.balanceOf(depositor) - initDepositorBalance, 23e17, 1e17, \"deposit not refunded enough eth\"\n        );\n    }\n\n    function _findBorrow(uint256 toFlash, uint256 debt, uint256 collateral) internal returns (uint256) {\n        // we want a precision of six decimals\n        // TODo fix the inifinte loop\n        uint8 decimals = 6;\n\n        uint256 start = 5 * 10 ** decimals;\n        uint256 end = 30 * 10 ** decimals;\n        uint256 mid;\n        uint256 ethToBorrow;\n        uint256 totDep;\n        uint256 debtMinted;\n        uint256 ethReceived;\n        while (true) {\n            mid = (start + end) / 2;\n            ethToBorrow = (toFlash * mid) / 10 ** (decimals + 1);\n            totDep = toFlash + ethToBorrow;\n            debtMinted = (totDep * debt) / collateral;\n\n            // get quote for debt minted and check if eth value is > borrowed but within deviation\n            // if eth value is lesser, then we borrow less so end = mid; else start = mid\n            ethReceived = _getSqthPrice(debtMinted);\n            if (ethReceived >= ethToBorrow && ethReceived <= (ethToBorrow * 10100) / 10000) {\n                break;\n            }\n            // mid is the multiple\n            else {\n                if (ethReceived > ethToBorrow) {\n                    start = mid;\n                } else {\n                    end = mid;\n                }\n            }\n        }\n        // why is all the eth not being take in\n        return mid + 1e7;\n    }\n\n    function _isEnough(uint256 _userETh, uint256 oSqthQuantity, uint256 oSqthPrice, uint256 _totalDep)\n        internal\n        pure\n        returns (bool)\n    {\n        uint256 totalAfterSelling = (_userETh + ((oSqthQuantity * oSqthPrice)) / 1e18);\n        return totalAfterSelling > _totalDep;\n    }\n\n    function _convertUSDToETH(uint256 _usdc) internal returns (uint256) {\n        // get the uniswap quoter contract code and address and initiate it\n        return quoter.quoteExactInputSingle(\n            address(usdc),\n            address(weth),\n            500, //3000 is 0.3\n            _usdc,\n            0\n        );\n    }\n\n    function _getSqthPrice(uint256 _quantity) internal returns (uint256) {\n        return quoter.quoteExactInputSingle(address(sqth), address(weth), 3000, _quantity, 0);\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/test/ForkTestNetAtPrice.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\n\nimport \"forge-std/Test.sol\";\nimport {BaseForkSetup} from \"./BaseForkSetup.t.sol\";\n\ncontract ForkTestNetAtPrice is BaseForkSetup {\n    function setUp() public override {\n        BaseForkSetup.setUp();\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        crab.transfer(withdrawer, 1e18);\n\n        // some WETH and USDC rich address\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        usdc.transfer(depositor, 20e6);\n    }\n\n    function testForkTestNetAtPrice() public {\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 17e6);\n        netting.depositUSDC(17e6);\n        vm.stopPrank();\n\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), 1e18);\n        netting.queueCrabForWithdrawal(1e18);\n        vm.stopPrank();\n\n        assertEq(usdc.balanceOf(withdrawer), 0);\n        assertEq(crab.balanceOf(depositor), 0);\n        uint256 priceToNet = 1336290000;\n        uint256 quantityToNet = 16840842;\n        netting.netAtPrice(priceToNet, quantityToNet); // $1336.29 per crab and nets $16.84\n        assertApproxEqAbs(usdc.balanceOf(withdrawer), quantityToNet, 1); // withdrawer gets that amount\n        uint256 crabReceived = (quantityToNet * 1e18) / priceToNet;\n        assertEq(crab.balanceOf(depositor), crabReceived); // depositor gets 0.01265755 crab\n        assertEq(netting.crabBalance(withdrawer), 1e18 - crabReceived); // ensure crab remains\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/test/Netting.t.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport \"forge-std/Test.sol\";\nimport {BaseForkSetup} from \"./BaseForkSetup.t.sol\";\n\nimport {console} from \"forge-std/console.sol\";\n\ncontract NettingTest is BaseForkSetup {\n    function setUp() public override {\n        BaseForkSetup.setUp(); // gives you netting, depositor, withdrawer, usdc, crab\n        vm.startPrank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        usdc.transfer(depositor, 400e6);\n        vm.stopPrank();\n\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        crab.transfer(withdrawer, 40e18);\n\n        vm.startPrank(depositor); // makes some USDC deposits\n        usdc.approve(address(netting), 280 * 1e6);\n        netting.depositUSDC(20 * 1e6);\n        netting.depositUSDC(100 * 1e6);\n        netting.depositUSDC(80 * 1e6);\n        assertEq(netting.usdBalance(depositor), 200e6);\n        vm.stopPrank();\n\n        vm.startPrank(withdrawer); // queue some crab\n        crab.approve(address(netting), 200 * 1e18);\n        netting.queueCrabForWithdrawal(5 * 1e18);\n        netting.queueCrabForWithdrawal(4 * 1e18);\n        netting.queueCrabForWithdrawal(11 * 1e18);\n        assertEq(netting.crabBalance(withdrawer), 20e18);\n        vm.stopPrank();\n\n        // withdrawer has 20 queued and depositor 200\n    }\n\n    function testNettingAmountEqlsDeposit() public {\n        uint256 price = 1330e6;\n        uint256 quantity = 20e6;\n        netting.netAtPrice(price, quantity);\n        assertEq(netting.usdBalance(depositor), 180e6);\n        uint256 crabReceived = ((quantity * 1e18) / price);\n        assertEq(crab.balanceOf(depositor), crabReceived);\n    }\n\n    function testNettingAmountEqlsZero() public {\n        uint256 price = 1330e6;\n        uint256 quantity = 0;\n        netting.netAtPrice(price, quantity);\n        assertEq(netting.usdBalance(depositor), 200e6);\n    }\n\n    function testNettingAmountGreaterThanBalance() public {\n        uint256 price = 1330e6;\n        uint256 quantity = 30e10;\n        vm.expectRevert();\n        netting.netAtPrice(price, quantity);\n    }\n\n    function testNetting() public {\n        // TODO turn this into a fuzzing test\n        assertEq(usdc.balanceOf(withdrawer), 0, \"starting balance\");\n        assertEq(crab.balanceOf(depositor), 0, \"depositor got their crab\");\n        uint256 price = 1330e6;\n        uint256 quantity = 100e6;\n        netting.netAtPrice(price, quantity); // net for 100 USD where 1 crab is 10 USD, so 10 crab\n        assertApproxEqAbs(usdc.balanceOf(withdrawer), quantity, 1, \"withdrawer did not get their usdc\");\n        assertEq(crab.balanceOf(depositor), (quantity * 1e18) / price, \"depositor did not get their crab\");\n    }\n\n    function testNettingWithMultipleDeposits() public {\n        assertEq(usdc.balanceOf(withdrawer), 0, \"withdrawer starting balance\");\n        assertEq(crab.balanceOf(depositor), 0, \"depositor starting balance\");\n        uint256 price = 1330e6;\n        uint256 quantity = 200e6;\n        netting.netAtPrice(price, quantity); // net for 200 USD where 1 crab is 10 USD, so 20 crab\n        assertApproxEqAbs(usdc.balanceOf(withdrawer), quantity, 1, \"withdrawer did not get their usdc\");\n        assertEq(crab.balanceOf(depositor), (quantity * 1e18) / price, \"depositor did not get their crab\");\n    }\n\n    function testNettingWithPartialReceipt() public {\n        assertEq(usdc.balanceOf(withdrawer), 0, \"withdrawer starting balance\");\n        assertEq(crab.balanceOf(depositor), 0, \"depositor starting balance\");\n        uint256 price = 1330e6;\n        uint256 quantity = 30e6;\n        netting.netAtPrice(price, quantity); // 20 from first desposit and 10 from second (partial)\n        assertEq(netting.depositsQueued(), 170e6, \"receipts were not updated correctly\");\n        netting.netAtPrice(price, 170e6);\n        assertEq(crab.balanceOf(depositor), (200e6 * 1e18) / price, \"depositor got their crab\");\n    }\n\n    function testNettingAfterWithdraw() public {\n        assertEq(usdc.balanceOf(withdrawer), 0, \"withdrawer starting balance\");\n        assertEq(crab.balanceOf(depositor), 0, \"depositor starting balance\");\n        vm.prank(depositor);\n        uint256 withdrawQuantity = 50e6;\n        netting.withdrawUSDC(withdrawQuantity, false);\n        uint256 price = 1330e6;\n        uint256 quantity = 200e6 - withdrawQuantity;\n        netting.netAtPrice(price, quantity);\n        assertEq(crab.balanceOf(depositor), (quantity * 1e18) / price, \"depositor got their crab\");\n    }\n\n    function testNettingAfterARun() public {\n        uint256 price = 1330e6;\n        uint256 quantity = 200e6;\n        vm.startPrank(depositor);\n        netting.withdrawUSDC(80e6, false);\n        netting.depositUSDC(80e6);\n        vm.stopPrank();\n\n        vm.prank(withdrawer);\n        netting.dequeueCrab(20e18 - (quantity * 1e18) / price, false);\n        netting.netAtPrice(price, 200e6); // net for 100 USD where 1 crab is 10 USD, so 10 crab\n        assertEq(netting.crabBalance(withdrawer), 0, \"crab balance not zero after first netting\");\n\n        // queue more\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 200 * 1e6);\n        netting.depositUSDC(20 * 1e6);\n        netting.depositUSDC(100 * 1e6);\n        netting.depositUSDC(80 * 1e6);\n        assertEq(netting.usdBalance(depositor), 200e6, \"usd balance not reflecting correctly\");\n        vm.stopPrank();\n\n        console.log(\"no issues till here 2\");\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), 200 * 1e18);\n        netting.queueCrabForWithdrawal(5 * 1e18);\n        netting.queueCrabForWithdrawal(4 * 1e18);\n        netting.queueCrabForWithdrawal(11 * 1e18);\n        assertEq(netting.crabBalance(withdrawer), 20e18, \"crab balance not reflecting correctly\");\n        vm.stopPrank();\n\n        console.log(\"no issues till here 3\");\n        netting.netAtPrice(price, 200e6); // net for 100 USD where 1 crab is 10 USD, so 10 crab\n        console.log(\"no issues till here 4\");\n        assertApproxEqAbs(usdc.balanceOf(withdrawer), 400e6, 2, \"witadrawer got their usdc\");\n        assertEq(crab.balanceOf(depositor), (400e6 * 1e18) / price, \"depositor got their crab\");\n    }\n\n    function testCannotWithdrawMoreThanDeposited() public {\n        vm.startPrank(depositor);\n        vm.expectRevert(stdError.arithmeticError);\n        netting.withdrawUSDC(210e6, false);\n        vm.stopPrank();\n    }\n\n    function testSkipsUSDCBannedAddress() public {\n        // remove the withdrawers crab so that we dont net them\n        vm.prank(withdrawer);\n        netting.dequeueCrab(20e18, false);\n\n        // get bob the blacklisted address some crab\n        address bob = address(0xAa05F7C7eb9AF63D6cC03C36c4f4Ef6c37431EE0);\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        crab.transfer(bob, 10e18);\n\n        // bob now deposits\n        vm.startPrank(bob);\n        crab.approve(address(netting), 10e18);\n        netting.queueCrabForWithdrawal(10e18);\n        vm.stopPrank();\n\n        vm.expectRevert(bytes(\"Blacklistable: account is blacklisted\"));\n        netting.netAtPrice(1330e6, 200e6);\n\n        netting.rejectWithdraw(3);\n        vm.prank(withdrawer);\n        netting.queueCrabForWithdrawal(20e18);\n        netting.netAtPrice(1330e6, 200e6);\n\n        assertEq(crab.balanceOf(bob), 10e18);\n        assertEq(netting.crabBalance(bob), 0);\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/test/PriceChecks.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport \"forge-std/Test.sol\";\nimport {BaseForkSetup} from \"./BaseForkSetup.t.sol\";\n\ncontract PriceChecks is BaseForkSetup {\n    uint256 crabsToWithdraw = 40e18;\n    uint256 price = 1269e6; // 1335 bounds are 1267 and 1401\n    uint256 totalUSDCRequired = (crabsToWithdraw * price) / 1e18;\n\n    function setUp() public override {\n        BaseForkSetup.setUp(); // gives you netting, depositor, withdrawer, usdc, crab\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        usdc.transfer(depositor, totalUSDCRequired);\n\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        crab.transfer(withdrawer, crabsToWithdraw);\n\n        // make multiple deposits from depositor\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), totalUSDCRequired);\n        netting.depositUSDC(totalUSDCRequired);\n        vm.stopPrank();\n\n        // queue multiple crabs from withdrawer\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), crabsToWithdraw);\n        netting.queueCrabForWithdrawal(crabsToWithdraw);\n        vm.stopPrank();\n    }\n\n    function testCrabPriceHigh() public {\n        console.log(\"expecting a high crdab price\");\n        vm.expectRevert(bytes(\"N23\"));\n        netting.netAtPrice(1500e6, totalUSDCRequired / 2);\n    }\n\n    function testCrabPriceLow() public {\n        vm.expectRevert(bytes(\"N24\"));\n        netting.netAtPrice(1100e6, totalUSDCRequired / 2);\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/test/QueuedBalances.t.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport {BaseForkSetup} from \"./BaseForkSetup.t.sol\";\n\ncontract QueuedBalancesTest is BaseForkSetup {\n    uint256 crabsToWithdraw = 40e18;\n    uint256 price = 1279e6; // 1338 bounds are 1271 and 1404\n    uint256 totalUSDCRequired = (crabsToWithdraw * price) / 1e18;\n\n    function setUp() public override {\n        BaseForkSetup.setUp(); // gives you netting, depositor, withdrawer, usdc, crab\n        vm.startPrank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        usdc.transfer(depositor, totalUSDCRequired);\n        vm.stopPrank();\n\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        crab.transfer(withdrawer, crabsToWithdraw);\n\n        // make multiple deposits from depositor\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), totalUSDCRequired);\n        netting.depositUSDC((totalUSDCRequired * 10) / 100);\n        netting.depositUSDC((totalUSDCRequired * 50) / 100);\n        netting.depositUSDC((totalUSDCRequired * 40) / 100);\n        assertEq(netting.usdBalance(depositor), totalUSDCRequired);\n        vm.stopPrank();\n\n        // queue multiple crabs from withdrawer\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), crabsToWithdraw);\n        netting.queueCrabForWithdrawal((crabsToWithdraw * 25) / 100);\n        netting.queueCrabForWithdrawal((crabsToWithdraw * 20) / 100);\n        netting.queueCrabForWithdrawal((crabsToWithdraw * 55) / 100);\n        assertEq(netting.crabBalance(withdrawer), crabsToWithdraw);\n        vm.stopPrank();\n\n        netting.netAtPrice(price, totalUSDCRequired / 2); // net for 100 USD where 1 crab is 10 USD, so 10 crab\n    }\n\n    function testcrabBalanceQueued() public {\n        assertEq(netting.depositsQueued(), totalUSDCRequired / 2);\n    }\n\n    function testWithdrawsQueued() public {\n        assertEq(netting.withdrawsQueued(), crabsToWithdraw / 2);\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/test/SkipDeposits.t.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport {BaseForkSetup} from \"./BaseForkSetup.t.sol\";\n\ncontract SkipDeposits is BaseForkSetup {\n    function setUp() public override {\n        BaseForkSetup.setUp(); // gives you netting, depositor, withdrawer, usdc, crab\n\n        vm.startPrank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        usdc.transfer(depositor, 20e6);\n        vm.stopPrank();\n\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        crab.transfer(withdrawer, 20e18);\n    }\n\n    function testSkipDeposits() public {\n        netting.setMinUSDC(1e6);\n        vm.startPrank(depositor);\n        usdc.approve(address(netting), 2 * 1e6);\n        netting.depositUSDC(1e6);\n        netting.depositUSDC(1e6);\n        vm.stopPrank();\n        assertEq(netting.depositsQueued(), 2e6);\n        netting.setDepositsIndex(1);\n        assertEq(netting.depositsQueued(), 1e6);\n    }\n\n    function testSkipWithdraws() public {\n        netting.setMinCrab(1e18);\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), 2 * 1e18);\n        netting.queueCrabForWithdrawal(1e18);\n        netting.queueCrabForWithdrawal(1e18);\n        vm.stopPrank();\n        assertEq(netting.withdrawsQueued(), 2e18);\n        netting.setWithdrawsIndex(1);\n        assertEq(netting.withdrawsQueued(), 1e18);\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/test/WithdrawAuction.t.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\n\nimport \"forge-std/Test.sol\";\n\nimport {Order, WithdrawAuctionParams} from \"../src/CrabNetting.sol\";\nimport {ICrabStrategyV2} from \"../src/interfaces/ICrabStrategyV2.sol\";\n\nimport {UniswapQuote} from \"./utils/UniswapQuote.sol\";\nimport {BaseForkSetup} from \"./BaseForkSetup.t.sol\";\n\nimport {ERC20} from \"openzeppelin/token/ERC20/ERC20.sol\";\nimport {IWETH} from \"../src/interfaces/IWETH.sol\";\n\nimport {SigUtils} from \"./utils/SigUtils.sol\";\n\nstruct TimeBalances {\n    uint256 start;\n    uint256 end;\n}\n\nstruct Portion {\n    uint256 collateral;\n    uint256 debt;\n}\n\nstruct Sign {\n    uint8 v;\n    bytes32 r;\n    bytes32 s;\n}\n\ncontract TestWithdrawAuction is BaseForkSetup {\n    SigUtils sig;\n\n    function setUp() public override {\n        BaseForkSetup.setUp();\n        sig = new SigUtils(netting.DOMAIN_SEPARATOR());\n\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        crab.transfer(withdrawer, 20e18);\n\n        // send sqth to market makers todo\n        vm.startPrank(0x56178a0d5F301bAf6CF3e1Cd53d9863437345Bf9);\n        sqth.transfer(mm1, 1000e18);\n        sqth.transfer(mm2, 1000e18);\n        vm.stopPrank();\n\n        // deposit crab for withdrawing\n        vm.startPrank(withdrawer);\n        crab.approve(address(netting), 19 * 1e18);\n        netting.queueCrabForWithdrawal(2 * 1e18);\n        netting.queueCrabForWithdrawal(3 * 1e18);\n        netting.queueCrabForWithdrawal(6 * 1e18);\n        vm.stopPrank();\n        // 11 crabs queued for withdrawal\n    }\n\n    function testWithdrawAuction() public {\n        WithdrawAuctionParams memory params;\n        // find the sqth to buy to make the trade\n        params.crabToWithdraw = 10e18;\n        uint256 sqthToBuy = crab.getWsqueethFromCrabAmount(params.crabToWithdraw);\n        UniswapQuote quote = new UniswapQuote();\n        uint256 sqthPrice = quote.getSqthPrice(1e18);\n        params.clearingPrice = (sqthPrice * 1001) / 1000;\n\n        // get the orders for that sqth\n        vm.prank(mm1);\n        sqth.approve(address(netting), 1000000e18);\n\n        Order memory order0 = Order(0, mm1, 1e18, params.clearingPrice, false, block.timestamp, 2, 1, 0x00, 0x00);\n        Sign memory s0;\n        (s0.v, s0.r, s0.s) = vm.sign(mm1Pk, sig.getTypedDataHash(order0));\n        order0.v = s0.v;\n        order0.r = s0.r;\n        order0.s = s0.s;\n        orders.push(order0);\n\n        Order memory order =\n            Order(0, mm1, sqthToBuy - 1e18, params.clearingPrice, false, block.timestamp, 0, 1, 0x00, 0x00);\n        Sign memory s1;\n        (s1.v, s1.r, s1.s) = vm.sign(mm1Pk, sig.getTypedDataHash(order));\n        order.v = s1.v;\n        order.r = s1.r;\n        order.s = s1.s;\n        orders.push(order);\n        params.orders = orders;\n\n        // find the minUSDC to receive\n        // get col and wsqth from crab amount, find the equity value in eth\n        (,, uint256 collateral,) = crab.getVaultDetails();\n        Portion memory p;\n        p.collateral = (params.crabToWithdraw * collateral) / crab.totalSupply();\n        p.debt = crab.getWsqueethFromCrabAmount(params.crabToWithdraw);\n        uint256 equityInEth = p.collateral - (p.debt * params.clearingPrice) / 1e18;\n\n        params.minUSDC = (quote.convertWETHToUSDC(equityInEth) * 999) / 1000;\n        params.ethUSDFee = 500;\n        // get equivalent usdc quote with slippage and send\n\n        // call withdrawAuction on netting contract\n        TimeBalances memory timeUSDC;\n        TimeBalances memory timeWETH;\n        timeUSDC.start = ERC20(usdc).balanceOf(withdrawer);\n        timeWETH.start = IWETH(weth).balanceOf(mm1);\n\n        netting.withdrawAuction(params);\n\n        timeUSDC.end = ERC20(usdc).balanceOf(withdrawer);\n        timeWETH.end = IWETH(weth).balanceOf(mm1);\n        assertGe(timeUSDC.end - timeUSDC.start, params.minUSDC);\n        assertGe(timeWETH.end - timeWETH.start, (sqthToBuy * sqthPrice) / 1e18);\n\n        // and eth recevied for mm\n        assertEq(address(netting).balance, 0);\n        assertEq(ERC20(sqth).balanceOf(address(netting)), 0, \"sqth balance\");\n        assertLe(ERC20(usdc).balanceOf(address(netting)), 1, \"usdc balance\");\n        assertEq(ICrabStrategyV2(crab).balanceOf(address(netting)), 1e18, \"crab balance\");\n        assertEq(netting.crabBalance(address(withdrawer)), 11e18 - params.crabToWithdraw);\n        assertEq(IWETH(weth).balanceOf(address(netting)), 0, \"weth balance\");\n    }\n\n    function testWithdrawAuctionAfterFullWithdraw() public {\n        vm.startPrank(withdrawer);\n        netting.dequeueCrab(6e18, false);\n        netting.queueCrabForWithdrawal(6e18);\n        vm.stopPrank();\n\n        WithdrawAuctionParams memory params;\n        // find the sqth to buy to make the trade\n        params.crabToWithdraw = 10e18;\n        uint256 sqthToBuy = crab.getWsqueethFromCrabAmount(params.crabToWithdraw);\n        UniswapQuote quote = new UniswapQuote();\n        uint256 sqthPrice = quote.getSqthPrice(1e18);\n        params.clearingPrice = (sqthPrice * 1001) / 1000;\n\n        // get the orders for that sqth\n        vm.prank(mm1);\n        sqth.approve(address(netting), 1000000e18);\n\n        Order memory order0 = Order(0, mm1, 1e18, params.clearingPrice, false, block.timestamp, 2, 1, 0x00, 0x00);\n        Sign memory s0;\n        (s0.v, s0.r, s0.s) = vm.sign(mm1Pk, sig.getTypedDataHash(order0));\n        order0.v = s0.v;\n        order0.r = s0.r;\n        order0.s = s0.s;\n        orders.push(order0);\n\n        Order memory order =\n            Order(0, mm1, sqthToBuy - 1e18, params.clearingPrice, false, block.timestamp, 0, 1, 0x00, 0x00);\n        Sign memory s1;\n        (s1.v, s1.r, s1.s) = vm.sign(mm1Pk, sig.getTypedDataHash(order));\n        order.v = s1.v;\n        order.r = s1.r;\n        order.s = s1.s;\n        orders.push(order);\n        params.orders = orders;\n\n        // find the minUSDC to receive\n        // get col and wsqth from crab amount, find the equity value in eth\n        (,, uint256 collateral,) = crab.getVaultDetails();\n        Portion memory p;\n        p.collateral = (params.crabToWithdraw * collateral) / crab.totalSupply();\n        p.debt = crab.getWsqueethFromCrabAmount(params.crabToWithdraw);\n        uint256 equityInEth = p.collateral - (p.debt * params.clearingPrice) / 1e18;\n\n        params.minUSDC = (quote.convertWETHToUSDC(equityInEth) * 999) / 1000;\n        params.ethUSDFee = 500;\n        // get equivalent usdc quote with slippage and send\n\n        // call withdrawAuction on netting contract\n        TimeBalances memory timeUSDC;\n        TimeBalances memory timeWETH;\n        timeUSDC.start = ERC20(usdc).balanceOf(withdrawer);\n        timeWETH.start = IWETH(weth).balanceOf(mm1);\n\n        netting.withdrawAuction(params);\n\n        timeUSDC.end = ERC20(usdc).balanceOf(withdrawer);\n        timeWETH.end = IWETH(weth).balanceOf(mm1);\n        assertGe(timeUSDC.end - timeUSDC.start, params.minUSDC);\n        assertGe(timeWETH.end - timeWETH.start, (sqthToBuy * sqthPrice) / 1e18);\n\n        // and eth recevied for mm\n        assertEq(address(netting).balance, 0);\n        assertEq(ERC20(sqth).balanceOf(address(netting)), 0, \"sqth balance\");\n        assertLe(ERC20(usdc).balanceOf(address(netting)), 1, \"usdc balance\");\n        assertEq(ICrabStrategyV2(crab).balanceOf(address(netting)), 1e18, \"crab balance\");\n        assertEq(netting.crabBalance(address(withdrawer)), 11e18 - params.crabToWithdraw);\n        assertEq(IWETH(weth).balanceOf(address(netting)), 0, \"weth balance\");\n    }\n\n    function testSqthPriceAboveThreshold() public {\n        WithdrawAuctionParams memory params;\n        // find the sqth to buy to make the trade\n        params.crabToWithdraw = 10e18;\n        uint256 sqthToBuy = 1e6;\n        UniswapQuote quote = new UniswapQuote();\n        uint256 sqthPrice = quote.getSqthPrice(1e18);\n        params.clearingPrice = (sqthPrice * 106) / 100;\n\n        // get the orders for that sqth\n\n        Order memory order = Order(0, mm1, sqthToBuy, params.clearingPrice, false, block.timestamp, 0, 1, 0x00, 0x00);\n        (uint8 v, bytes32 r, bytes32 s) = vm.sign(mm1Pk, sig.getTypedDataHash(order));\n        order.v = v;\n        order.r = r;\n        order.s = s;\n        orders.push(order);\n        params.orders = orders;\n\n        params.minUSDC = 1e6;\n        params.ethUSDFee = 500;\n        // get equivalent usdc quote with slippage and send\n\n        vm.expectRevert(bytes(\"N21\"));\n        netting.withdrawAuction(params);\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/test/utils/SigUtils.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\n\nimport {console} from \"forge-std/console.sol\";\n\nimport {Order} from \"../../src/CrabNetting.sol\";\n\ncontract SigUtils {\n    bytes32 internal DOMAIN_SEPARATOR;\n\n    constructor(bytes32 _DOMAIN_SEPARATOR) {\n        DOMAIN_SEPARATOR = _DOMAIN_SEPARATOR;\n    }\n\n    // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n    bytes32 public constant _CRAB_NETTING_TYPEHASH = keccak256(\n        \"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\"\n    );\n\n    // computes the hash of a permit\n    function getStructHash(Order memory _order) internal pure returns (bytes32) {\n        return keccak256(\n            abi.encode(\n                _CRAB_NETTING_TYPEHASH,\n                _order.bidId,\n                _order.trader,\n                _order.quantity,\n                _order.price,\n                _order.isBuying,\n                _order.expiry,\n                _order.nonce\n            )\n        );\n    }\n\n    // computes the hash of the fully encoded EIP-712 message for the domain, which can be used to recover the signer\n    function getTypedDataHash(Order memory _order) public view returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR, getStructHash(_order)));\n    }\n}\n"
  },
  {
    "path": "packages/crab-netting/test/utils/UniswapQuote.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\n\nimport {IQuoter} from \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\";\n\ncontract UniswapQuote {\n    address usdc = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n    address sqth = 0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B;\n    address weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n    IQuoter public immutable quoter = IQuoter(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);\n\n    function convertUSDToETH(uint256 _usdc) external returns (uint256) {\n        // get the uniswap quoter contract code and address and initiate it\n        return quoter.quoteExactInputSingle(\n            (usdc),\n            (weth),\n            500, //3000 is 0.3\n            _usdc,\n            0\n        );\n    }\n\n    function convertWETHToUSDC(uint256 _weth) external returns (uint256) {\n        // get the uniswap quoter contract code and address and initiate it\n        return quoter.quoteExactInputSingle(\n            (weth),\n            (usdc),\n            500, //3000 is 0.3\n            _weth,\n            0\n        );\n    }\n\n    function getSqthPrice(uint256 _quantity) external returns (uint256) {\n        return quoter.quoteExactInputSingle((sqth), (weth), 3000, _quantity, 0);\n    }\n}\n"
  },
  {
    "path": "packages/frontend/.babelrc",
    "content": "{\n  \"presets\": [\"next/babel\"]\n}\n"
  },
  {
    "path": "packages/frontend/.eslintrc",
    "content": "{\n  \"parser\": \"@typescript-eslint/parser\",\n  \"plugins\": [\"prettier\", \"@typescript-eslint\", \"react\", \"react-hooks\", \"simple-import-sort\"],\n  \"extends\": [\n    \"plugin:react/recommended\",\n    \"plugin:@typescript-eslint/recommended\",\n    \"plugin:prettier/recommended\",\n    \"prettier\",\n    \"next\",\n    \"next/core-web-vitals\"\n  ],\n  \"env\": {\n    \"browser\": true,\n    \"jest\": true\n  },\n  \"parserOptions\": {\n    \"ecmaVersion\": 2020,\n    \"sourceType\": \"module\",\n    \"ecmaFeatures\": {\n      \"jsx\": true\n    }\n  },\n  \"settings\": {\n    \"react\": {\n      \"version\": \"detect\"\n    }\n  },\n  \"rules\": {\n    \"@typescript-eslint/no-unused-vars\": [\n      \"warn\",\n      {\n        \"argsIgnorePattern\": \"^_\",\n        \"ignoreRestSiblings\": true\n      }\n    ],\n    \"@typescript-eslint/explicit-function-return-type\": \"off\",\n    \"@typescript-eslint/explicit-module-boundary-types\": \"off\",\n    \"@typescript-eslint/no-explicit-any\": \"off\",\n    \"@typescript-eslint/member-delimiter-style\": \"off\",\n    \"@typescript-eslint/no-non-null-assertion\": \"off\",\n    \"@typescript-eslint/no-use-before-define\": \"off\",\n    \"@typescript-eslint/no-empty-interface\": \"off\",\n    \"@typescript-eslint/ban-ts-ignore\": \"off\",\n    \"@typescript-eslint/ban-ts-comment\": \"off\",\n    \"@typescript-eslint/camelcase\": \"off\",\n    \"react-hooks/rules-of-hooks\": \"error\",\n    \"react-hooks/exhaustive-deps\": [\n      \"warn\",\n      {\n        \"additionalHooks\": \"(useAppEffect|useAppMemo|useAppCallback)\"\n      }\n    ],\n    \"react/prop-types\": \"off\",\n    \"import/order\": \"off\",\n    \"sort-imports\": \"off\",\n    \"simple-import-sort/exports\": \"error\",\n    \"@typescript-eslint/ban-types\": \"off\",\n    \"@typescript-eslint/no-empty-function\": \"off\",\n    // This rule will help with preventing to commit code that is not yet finished\n    // I removed TODO as a term so that we can still use that for future work\n    // and use FIXME during the development process\n    \"no-warning-comments\": [\n      \"warn\",\n      {\n        \"terms\": [\"fixme\"],\n        \"location\": \"start\"\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/frontend/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# next.js\n/.next/\n/out/\n\n# production\n/build\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# local env files\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\n# vercel\n.vercel\n\n# tests\ncypress/screenshots\ncypress/videos\ncypress/downloads\n"
  },
  {
    "path": "packages/frontend/.nvmrc",
    "content": "v18.15.0\n"
  },
  {
    "path": "packages/frontend/.prettierrc",
    "content": "{\n  \"semi\": false,\n  \"trailingComma\": \"all\",\n  \"singleQuote\": true,\n  \"useTabs\": false,\n  \"bracketSpacing\": true,\n  \"printWidth\": 120,\n  \"tabWidth\": 2\n}"
  },
  {
    "path": "packages/frontend/CONTRIBUTING.md",
    "content": "# Squeeth Frontend Contribution Guidelines\n\n## Issues\n\n- Check to see if your issue has been previously brought up, and if so add a comment to the existing issue\n- Follow the issue templates for bugs or feature requests\n- As much as possible, tie the issue back to the problem users are facing\n\n## Branches\n\n- Please create a feature / fix / documentation branch for what you’re working on\n- Make a PR from your branch into the either the _master_ branch or a _staging_ branch.\n  - Make PRs into _master_ for fixes and single features\n  - Make PRs into the _staging_ branch for a bigger feature or set of fixes that need to be tested and then released all at once. Different features might have different staging branches. eg. \"staging/strategies\" and \"staging/lp-nft-collateral\"\n\n## Commits\n\n- Follow the [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) format\n\n```\nbuild: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)\n\nci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)\n\ndocs: Documentation only changes\n\nfeat: A new feature\n\nfix: A bug fix\n\nperf: A code change that improves performance\n\nrefactor: A code change that neither fixes a bug nor adds a feature\n\nstyle: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)\n\ntest: Adding missing tests or correcting existing tests\n```\n\n## PRs\n\n- Each PR requires at least one review before it can be merged to master\n- Follow the PR template when making PRs\n- Link to the issue you are working on\n"
  },
  {
    "path": "packages/frontend/LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>."
  },
  {
    "path": "packages/frontend/README.md",
    "content": "# Squeeth frontend\n\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)\n\n## Getting started\n\nAs the first step, install the node dependencies\n\n```\nyarn install\n```\n\n### Set up the environment\n\nCopy the contents of `.env.example` to a new file `.env`.\n\n`NEXT_PUBLIC_INFURA_API_KEY` - Sign up in [Infura](https://infura.io/dashboard/ethereum) and create an Ethereum project to get infura key.\n`NEXT_PUBLIC_ALCHEMY_API_KEY` - Sign up at [Alchemy] (https://www.alchemy.com/) and create an Etheruem project to get an alchemy key\n`NEXT_PUBLIC_BLOCKNATIVE_DAPP_ID` - Sign up in [Blocknative](https://www.blocknative.com/) and get the api key.\n\nThe backtests use Tardis and Firebase and we use Fathom for analytics. All of those fields are optional (note that the backtests will not show up without them though).\n\n### Run the app\n\nOnce everything is set run the following command.\n\n```\nyarn dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) with your browser to see the result.\n\n## Deployment\n\nThe easiest way to deploy this Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.\n\nCheck out the [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.\n\n## Contributions\n\nWe welcome contributions to the Squeeth Frontend! You can contribute by resolving existing issues, taking on feature requests, and refactoring code. Please feel free to open new issues / feature requests as well. You can find our [contribution guidelines here.](CONTRIBUTING.md) If you have questions about contributing, ping us on #dev in the [Opyn discord](http://tiny.cc/opyndiscord) :)\n\n## Branding\n\nDon't use the Opyn or Squeeth logo or name in anything dishonest or fraudulent. If you deploy another version of the interface, please make it clear that it is an interface to the Squeeth Protocol, but not affiliated with Opyn Inc.\n"
  },
  {
    "path": "packages/frontend/custom.d.ts",
    "content": "declare module 'fzero'\n"
  },
  {
    "path": "packages/frontend/cypress/TEST.md",
    "content": "- Setup / Preparation\n\n  1. Test Environment\n     1. Test locally\n     2. Network: Ropsten\n     3. Wallet: Metamask\n     4. Browser: Default is Chrome\n        1. Can test with firefox or chromium-based browsers as well, but will need to change the command in `package.json` ,\n     5. Test websites\n        1. squeeth, at `localhost:3000`\n        2. uniswap lp page to lp oSQTH\n  2. Test setup\n\n     1. Make sure `synpress` and `dotenv-cli` packages are installed successfully with `package.json`\n        1. if there is no `dotenv-cli` installed, run `yarn global add dotenv-cli`\n     2. Put SECRET_WORDS or PRIVATE_KEY and NETWORK in `.env` file, i.e.\n\n        ```jsx\n        SECRET_WORDS = 'word1, word2, word3...'\n        NETWORK_NAME = ropsten\n        OR\n        PRIVATE_KEY = 'your PRIVATE_KEY'\n        NETWORK_NAME = ropsten\n        ```\n\n     3. If you want to test with squeeth website, set `baseUrl` in `cypress.json` as `\"baseUrl\": \"http://localhost:3000\",`\n     4. if you want to test lp, set `baseUrl` in `cypress.json` as `\"baseUrl\": \"https://squeeth-uniswap.netlify.app/#/add/ETH/0xa4222f78d23593e82Aa74742d25D06720DCa4ab7/3000\",`\n     5. Recommended to clear your existing position before you run the tests, otherwise it may be hard to tell if the test fails because of the existing position or the new position\n     6. Run `yarn run build` and `yarn start` , dont use `yarn dev` , cuz it will have warning pop-ups hiding some DOM elements\n     7. **Recommended**: if you only want to test one page or related functionalities or the functionalities you changed, plz specify the tests file you would like to include, it will run only provided spec files, i.e.\n\n        ```jsx\n        yarn run cypress -s cypress/integration/specs/01-trade-long.spec.js\n        yarn run cypress -s cypress/integration/specs/02-trade-short.spec.js\n        ```\n\n        1. Tests you should run\n           1. Test long: `01-trade-long.spec`\n           2. Test short: `02-trade-short.spec`\n           3. Test vault with short or mint position: `03-vault.spec`\n           4. Test lp:\n              1. buy to lp: `04-buy-lp` + `05-lp-uniswap` + `05-lp-position`\n              2. mint to lp: `04-mint-lp` + `05-lp-uniswap` + `05-lp-position` + `05-lp-vault`\n           5. Test manual short : `06-manual-short`\n           6. Test strategy: `07-strategy`\n           7. Test on position page : `08-position`\n           8. Test on lp nft as collateral : `09-lp-token`\n\n     8. **Not recommended**: Run `yarn run cypress` to start all testing, it will start with `01-trade-long.spec` by default, it will take forever to run through all the tests\n"
  },
  {
    "path": "packages/frontend/cypress/fixtures/example.json",
    "content": "{\n    \"name\": \"Using fixtures to represent data\",\n    \"email\": \"hello@cypress.io\",\n    \"body\": \"Fixtures are a great way to mock data for responses to routes\"\n}"
  },
  {
    "path": "packages/frontend/cypress/integration/pages/header.js",
    "content": "import Page from './page'\nexport default class Header extends Page {\n  getConnectWalletBtn() {\n    return cy.get('#connect-wallet')\n  }\n  getWalletAddress() {\n    return cy.get('#wallet-address')\n  }\n}\n"
  },
  {
    "path": "packages/frontend/cypress/integration/pages/notifications.js",
    "content": "import Page from './page'\nexport default class Notifications extends Page {\n  getTransactionSuccessNotification() {\n    return cy.contains('has succeeded', { timeout: 600000 }).should(`exist`)\n  }\n  getTransactionSuccessNotificationLink() {\n    return cy.get('.bn-notify-notification-success a', { timeout: 60000 })\n  }\n}\n"
  },
  {
    "path": "packages/frontend/cypress/integration/pages/onboard.js",
    "content": "import Page from './page'\nexport default class Onboard extends Page {\n  getBrowserWalletBtn() {\n    return cy.get('[alt=\"MetaMask\"]')\n  }\n}\n"
  },
  {
    "path": "packages/frontend/cypress/integration/pages/page.js",
    "content": "export default class Page {\n  getTitle() {\n    return cy.title()\n  }\n\n  getMetamaskWalletAddress() {\n    return cy.fetchMetamaskWalletAddress()\n  }\n\n  acceptMetamaskAccessRequest() {\n    cy.acceptMetamaskAccess()\n  }\n\n  confirmMetamaskTransaction() {\n    // Currently without supplying a gas configuration results in failing transactions\n    // Possibly caused by wrong default behaviour within Synpress\n    cy.confirmMetamaskTransaction({ gasFee: 30, gasLimit: 5000000 })\n  }\n\n  confirmMetamaskPermissionToSpend() {\n    cy.confirmMetamaskPermissionToSpend().then((approved) => {\n      expect(approved).to.be.true\n    })\n  }\n}\n"
  },
  {
    "path": "packages/frontend/cypress/integration/pages/trade.js",
    "content": "import Page from './page'\nimport Header from './header'\nimport Onboard from './onboard'\nimport Notifications from './notifications.js'\n\nexport default class TradePage extends Page {\n  constructor() {\n    super()\n    this.header = new Header()\n    this.onboard = new Onboard()\n    this.notifications = new Notifications()\n  }\n\n  connectBrowserWallet() {\n    const connectWalletButton = this.header.getConnectWalletBtn()\n    connectWalletButton.click()\n    const onboardBrowserWalletButton = this.onboard.getBrowserWalletBtn()\n    onboardBrowserWalletButton.click()\n  }\n\n  getLoggedInWalletAddress() {\n    const addr = this.header.getWalletAddress()\n    return addr.invoke('text')\n  }\n\n  waitForTransactionSuccess() {\n    cy.waitUntil(\n      () => {\n        const txSuccessNotification = this.notifications.getTransactionSuccessNotification()\n        return txSuccessNotification.should('exist')\n      },\n      {\n        // tx takes a bit longer so extend the timeout duration, wait for 200000 ms\n        timeout: 200000,\n      },\n    )\n  }\n\n  getTransactionUrl() {\n    const txUrl = this.notifications.getTransactionSuccessNotificationLink()\n    return txUrl.invoke('attr', 'href')\n  }\n}\n"
  },
  {
    "path": "packages/frontend/cypress/integration/specs/01-trade-long.spec.js",
    "content": "/// <reference types=\"cypress\" />\n\nimport TradePage from '../pages/trade'\nimport BigNumber from 'bignumber.js'\n\nconst trade = new TradePage()\n\ndescribe('Trade on trade page', () => {\n  context('Before tests', () => {\n    it(`Before tests`, () => {\n      cy.disconnectMetamaskWalletFromAllDapps()\n      cy.visit('/')\n    })\n  })\n\n  context('Connect metamask wallet', () => {\n    it(`should login with success`, () => {\n      trade.connectBrowserWallet()\n      trade.acceptMetamaskAccessRequest()\n      cy.get('#wallet-address').should(`contain.text`, '0x' || '.eth')\n    })\n  })\n\n  context('Trade switch checks', () => {\n    it('check if there is open long card opened by default', () => {\n      cy.get('#open-long-header-box').should('contain.text', 'Pay ETH to buy squeeth ERC20')\n    })\n\n    it('switch between long & short, open & close trade cards with default 0 value', () => {\n      cy.get('#long-card-btn').click({ force: true })\n      cy.get('#open-btn').click({ force: true })\n      cy.get('#open-long-header-box').should('contain.text', 'Pay ETH to buy squeeth ERC20')\n      cy.get('#open-long-eth-input').should('have.value', '0')\n      cy.get('#open-long-osqth-input').should('have.value', '0')\n      // to make sure the cards are function independently after switching\n      cy.get('#open-long-eth-input').type('2', { delay: 200 }).should('have.value', '2')\n\n      cy.get('#long-card-btn').click({ force: true })\n      cy.get('#close-btn').click({ force: true })\n      cy.get('#close-long-header-box').should('contain.text', 'Sell squeeth ERC20 to get ETH')\n      cy.get('#close-long-eth-input').should('have.value', '0')\n      cy.get('#close-long-osqth-input').should('have.value', '0')\n      cy.get('#close-long-eth-input').type('2', { delay: 200 }).should('have.value', '2')\n\n      cy.get('#short-card-btn').click({ force: true })\n      cy.get('#open-btn').click({ force: true })\n      cy.get('#open-short-header-box').should('contain.text', 'Mint & sell squeeth for premium')\n      cy.get('#open-short-eth-input').should('have.value', '0')\n      cy.get('#open-short-trade-details .trade-details-amount').should('contain.text', '0')\n      cy.get('#open-short-eth-input').type('2', { delay: 200 }).should('have.value', '2')\n\n      cy.get('#short-card-btn').click({ force: true })\n      cy.get('#close-btn').click({ force: true })\n      cy.get('#close-short-header-box').should('contain.text', 'Buy back oSQTH & close position')\n      cy.get('#close-short-osqth-input').should('have.value', '0')\n      cy.get('#close-short-trade-details .trade-details-amount').should('contain.text', '0')\n    })\n  })\n\n  let openLongoSQTHInput\n  let openLongETHInput\n  let closeLongoSQTHInput\n  let closeLongETHInput\n  let openLongOsqthBeforeTradeBal\n  let posCardBeforeLongTradeBal\n  let closeLongBeforeTradeBal\n\n  context(`open long position`, () => {\n    before('jump to open long trade card', () => {\n      cy.get('#long-card-btn').click({ force: true })\n      cy.get('#open-btn').click({ force: true })\n    })\n\n    before(() => {\n      it('eth balance should be greater than 0', () => {\n        cy.get('#user-eth-wallet-balance').invoke('text').then(parseFloat).should('be.greaterThan', 0)\n      })\n    })\n\n    context('open long trade condition checks', () => {\n      it('eth balance from wallet should be the same as eth input box', () => {\n        cy.get('#user-eth-wallet-balance').then((bal) => {\n          cy.get('#open-long-eth-before-trade-balance').should('contain.text', Number(bal.text()).toFixed(4))\n        })\n      })\n\n      it('it is on open long card', () => {\n        cy.get('#open-long-header-box').should('contain.text', 'Pay ETH to buy squeeth ERC20')\n      })\n    })\n\n    context('input checks', () => {\n      // issue 277\n      it.skip('inputs should be zero by default and tx button is disabled', () => {\n        cy.get('#open-long-header-box').should('contain.text', 'Pay ETH to buy squeeth ERC20')\n        cy.get('#open-long-eth-input').should('have.value', '0')\n        cy.get('#open-long-osqth-input').should('have.value', '0')\n        cy.get('#open-long-submit-tx-btn').should('be.disabled')\n      })\n\n      it('zero input amount', () => {\n        cy.get('#open-long-eth-input').clear().type('0', { delay: 200 }).should('have.value', '0')\n        cy.get('#open-long-osqth-input').clear().type('0', { delay: 200 }).should('have.value', '0')\n      })\n\n      it('invalid input amount', () => {\n        cy.get('#open-long-eth-input').clear().type('\\\\', { delay: 200 }).should('have.value', '0')\n        cy.get('#open-long-osqth-input').clear().type('\\\\', { delay: 200 }).should('have.value', '0')\n      })\n    })\n\n    context('can enter an amount into eth input, check position card & input box balances', () => {\n      it('can enter an amount into eth input', () => {\n        cy.get('#open-long-eth-input').should('be.visible')\n        cy.get('#open-long-eth-input').clear().type('1.', { force: true, delay: 200 }).should('have.value', '1.0')\n\n        cy.get('#open-long-osqth-input').should('not.equal', '0')\n        cy.get('#open-long-osqth-input').then((v) => {\n          openLongoSQTHInput = new BigNumber(v.val().toString())\n        })\n      })\n\n      // a-post = a + input\n      it('input box oSQTH post trade balance should be the same as before-trade + input when input changes', () => {\n        cy.get('#open-long-osqth-before-trade-balance').then((bal) => {\n          cy.get('#open-long-osqth-post-trade-balance')\n            .then((v) => Number(parseFloat(v.text()).toFixed(4)))\n            .should('be.approximately', Number(openLongoSQTHInput.plus(Number(bal.text()))), 0.0002)\n        })\n      })\n\n      // b-post = b + input\n      it('position card oSQTH post trade balance should be the same as before-trade + input when input changes', () => {\n        cy.get('#position-card-before-trade-balance').then((bal) => {\n          cy.get('#position-card-post-trade-balance')\n            .then((v) => Number(parseFloat(v.text()).toFixed(4)))\n            .should('be.approximately', Number(openLongoSQTHInput.plus(Number(bal.text()))), 0.0002)\n        })\n      })\n\n      // a = b\n      it('position card oSQTH before trade balance should be the same as input box before oSQTH trade balance', () => {\n        cy.get('#open-long-osqth-before-trade-balance').then((bal) => {\n          cy.get('#position-card-before-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', new BigNumber(bal.text().toString()).toFixed(4))\n        })\n      })\n\n      // a + input = b + input != 0\n      it('position card oSQTH post trade balance should be the same as input box post oSQTH trade balance and not equal 0', () => {\n        cy.get('#open-long-osqth-post-trade-balance').then((bal) => {\n          cy.get('#position-card-post-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', new BigNumber(bal.text().toString()).toFixed(4))\n        })\n        cy.get('#open-long-osqth-post-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n        cy.get('#position-card-post-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n      })\n\n      // eth-post = eth-before - openLongETHInput\n      it('input box eth post trade balance should be the same as before-trade - input when input changes', () => {\n        cy.get('#open-long-eth-before-trade-balance').then((bal) => {\n          cy.get('#open-long-eth-post-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', (Number(bal.text()) - 1).toFixed(4))\n        })\n      })\n    })\n\n    context('can enter an amount into osqth input, check position card & input box balances', () => {\n      it('can enter an amount into osqth input', () => {\n        cy.get('#open-long-osqth-input').should('be.visible')\n        cy.get('#open-long-osqth-input').clear().type('1.', { force: true, delay: 200 }).should('have.value', '1.0')\n        openLongoSQTHInput = new BigNumber(1)\n      })\n\n      // a-post = a + input\n      it('input box oSQTH post trade balance should be the same as before-trade + input when input changes', () => {\n        cy.get('#open-long-osqth-before-trade-balance').then((bal) => {\n          cy.get('#open-long-osqth-post-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', openLongoSQTHInput.plus(Number(bal.text())).toFixed(4))\n        })\n      })\n\n      // b-post = b + input\n      it('position card oSQTH post trade balance should be the same as before-trade + input when input changes', () => {\n        cy.get('#position-card-before-trade-balance').then((bal) => {\n          cy.get('#position-card-post-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', openLongoSQTHInput.plus(Number(bal.text())).toFixed(4))\n        })\n      })\n\n      // a = b\n      it('position card oSQTH before trade balance should be the same as input box before oSQTH trade balance', () => {\n        cy.get('#open-long-osqth-before-trade-balance').then((bal) => {\n          cy.get('#position-card-before-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', new BigNumber(bal.text().toString()).toFixed(4))\n        })\n      })\n\n      // a + input = b + input != 0\n      it('position card oSQTH post trade balance should be the same as input box post oSQTH trade balance and not equal 0', () => {\n        cy.get('#open-long-eth-input').then((bal) => {\n          openLongETHInput = new BigNumber(bal.text().toString())\n        })\n        cy.get('#open-long-osqth-post-trade-balance').then((bal) => {\n          cy.get('#position-card-post-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', new BigNumber(bal.text().toString()).toFixed(4))\n        })\n        cy.get('#open-long-osqth-post-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n        cy.get('#position-card-post-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n      })\n\n      // eth-post = eth-before - openLongETHInput\n      // issue #280\n      it.skip('input box eth post trade balance should be the same as before-trade - input when input changes', () => {\n        cy.get('#open-long-eth-before-trade-balance').then((bal) => {\n          cy.get('#open-long-eth-post-trade-balance')\n            .wait(15000)\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', new BigNumber(bal.text()).minus(openLongETHInput).toFixed(4))\n        })\n      })\n    })\n\n    context('can open long position', () => {\n      it('can open long position for osqth, and tx succeeds', () => {\n        cy.get('#open-long-eth-input').clear().type('1.', { force: true, delay: 200 }).should('have.value', '1.0')\n        cy.get('#open-long-osqth-input').should('not.equal', '0')\n        cy.get('#open-long-osqth-input').then((v) => {\n          openLongoSQTHInput = new BigNumber(v.val().toString())\n        })\n\n        cy.get('#open-long-submit-tx-btn').should('contain.text', 'Buy')\n        cy.get('#open-long-submit-tx-btn').should('not.be.disabled')\n\n        cy.get('#open-long-osqth-before-trade-balance').then((val) => {\n          openLongOsqthBeforeTradeBal = new BigNumber(val.text())\n        })\n\n        cy.get('#position-card-before-trade-balance').then((val) => {\n          posCardBeforeLongTradeBal = new BigNumber(val.text())\n        })\n\n        cy.get('#open-long-submit-tx-btn').click({ force: true })\n        trade.confirmMetamaskTransaction()\n        trade.waitForTransactionSuccess()\n      })\n\n      it('there is open loong tx finished card after tx succeeds with correct closing value', () => {\n        cy.get('#open-long-card').should('contain.text', 'Close').should('contain.text', 'Bought')\n        cy.get('#conf-msg').should('contain.text', openLongoSQTHInput.toFixed(6))\n        cy.get('#open-long-close-btn').click({ force: true })\n      })\n\n      it('return to open long card successfully with all values update to 0', () => {\n        cy.get('#open-long-header-box').should('contain.text', 'Pay ETH to buy squeeth ERC20')\n        cy.get('#open-long-eth-input').should('have.value', '0')\n        cy.get('#open-long-osqth-input').should('have.value', '0')\n        cy.get('#open-long-submit-tx-btn').should('be.disabled')\n      })\n\n      it('position card should update to new osqth balance', () => {\n        // wait for 20 sec to update positon\n        cy.get('#position-card-before-trade-balance')\n          .wait(30000)\n          .then((v) => Number(parseFloat(v.text()).toFixed(4)))\n          .should('be.approximately', Number(posCardBeforeLongTradeBal.plus(openLongoSQTHInput)), 0.0002)\n      })\n\n      it('input box before trade update to new osqth balance', () => {\n        cy.get('#open-long-osqth-before-trade-balance')\n          .then((v) => Number(parseFloat(v.text()).toFixed(4)))\n          .should('be.approximately', Number(openLongOsqthBeforeTradeBal.plus(openLongoSQTHInput)), 0.0002)\n      })\n\n      it('position card update to the same value as input box before trade balance and not equal 0', () => {\n        cy.get('#open-long-osqth-before-trade-balance').then((bal) => {\n          cy.get('#position-card-before-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', new BigNumber(bal.text().toString()).toFixed(4))\n        })\n        cy.get('#open-long-osqth-before-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n        cy.get('#position-card-before-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n      })\n\n      // issue #282\n      it.skip('unrealized PnL display', () => {\n        cy.get('#unrealized-pnl-value').should('not.contain.text', 'Loading').should('not.contain.text', '--')\n      })\n\n      it('should have \"close your long position to open a long\" error in short oSQTH input when user have short oSQTH', () => {\n        cy.get('#short-card-btn').click({ force: true })\n        cy.get('#open-btn').click({ force: true })\n        cy.get('#open-short-eth-input-box').should('contain.text', 'Close your long position to open a short')\n      })\n    })\n  })\n\n  context(`close long position`, () => {\n    before(() => {\n      cy.get('#long-card-btn').click({ force: true })\n      cy.get('#close-btn').click({ force: true })\n    })\n\n    context('close long trade condition checks', () => {\n      it('it is on close long card', () => {\n        cy.get('#close-long-header-box').should('contain.text', 'Sell squeeth ERC20 to get ETH')\n      })\n\n      it('inputs should be zero by default and tx button is disabled', () => {\n        cy.get('#close-long-eth-input').should('have.value', '0')\n        cy.get('#close-long-osqth-input').should('have.value', '0')\n        cy.get('#close-long-submit-tx-btn').should('be.disabled')\n      })\n\n      it('should have oSQTH long balance in position card', () => {\n        cy.get('#position-card-before-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n      })\n    })\n\n    context('input checks', () => {\n      it('zero input amount', () => {\n        cy.get('#close-long-eth-input').clear().type('0', { delay: 200 }).should('have.value', '0')\n        cy.get('#close-long-osqth-input').clear().type('0', { delay: 200 }).should('have.value', '0')\n      })\n\n      it('invalid input amount', () => {\n        cy.get('#close-long-eth-input').clear().type('\\\\', { delay: 200 }).should('have.value', '0')\n        cy.get('#close-long-osqth-input').clear().type('\\\\', { delay: 200 }).should('have.value', '0')\n      })\n\n      it('submit tx button should be disabled when input is zero', () => {\n        cy.get('#close-long-osqth-input').clear().type('0', { delay: 200 }).should('have.value', '0')\n        cy.get('#close-long-submit-tx-btn').should('be.disabled')\n      })\n    })\n\n    //1 input status check -> trade status check -> send tx -> post trade status check\n    context('can close long with manual osqth inputs and tx succeeds', () => {\n      it('can enter an amount into osqth input', () => {\n        cy.get('#close-long-osqth-input').clear().type('0.1', { force: true, delay: 800 }).should('have.value', '0.1')\n        cy.get('#close-long-eth-input').should('not.equal', '0')\n        cy.get('#close-long-submit-tx-btn').should('not.be.disabled')\n      })\n\n      it('position card before trade balance should be the same as input box before trade balance', () => {\n        cy.get('#position-card-before-trade-balance').then((val) => {\n          cy.get('#close-long-osqth-before-trade-balance')\n            .then((v) => Number(v.text()).toFixed(6))\n            .should('eq', Number(val.text()).toFixed(6))\n        })\n      })\n\n      it('position card post trade balance should become before-trade - input when input changes', () => {\n        cy.get('#position-card-before-trade-balance').then((val) => {\n          cy.get('#position-card-post-trade-balance')\n            .then((v) => Number(parseFloat(v.text()).toFixed(6)))\n            .should('be.approximately', Number(val.text()) - 0.1, 0.000002)\n        })\n      })\n\n      it('input box before trade balance should become before-trade - input when input changes', () => {\n        cy.get('#close-long-osqth-before-trade-balance').then((val) => {\n          cy.get('#close-long-osqth-post-trade-balance')\n            .then((v) => Number(parseFloat(v.text()).toFixed(6)))\n            .should('be.approximately', Number(val.text()) - 0.1, 0.000002)\n        })\n      })\n\n      it('send tx', () => {\n        cy.get('#close-long-osqth-before-trade-balance').then((bal) => {\n          closeLongBeforeTradeBal = bal.text()\n        })\n\n        cy.get('#position-card-before-trade-balance').then((bal) => {\n          posCardBeforeLongTradeBal = bal.text()\n        })\n\n        cy.get('#close-long-submit-tx-btn').then((btn) => {\n          if (btn.text().includes('Approve oSQTH')) {\n            cy.get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskPermissionToSpend()\n            trade.waitForTransactionSuccess()\n            cy.wait(15000).get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          } else if (btn.text().includes('Sell')) {\n            cy.get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          }\n        })\n      })\n\n      it('there is close long tx finished card after tx succeeds with correct closing value', () => {\n        cy.get('#close-long-card').should('contain.text', 'Close').should('contain.text', 'Sold')\n        cy.get('#conf-msg').should('contain.text', (0.1).toFixed(6))\n        cy.get('#close-long-close-btn').click({ force: true })\n      })\n\n      it('new position card value should be the same as prev position card value', () => {\n        // wait for 30 sec to update positon\n        cy.get('#position-card-before-trade-balance')\n          .wait(30000)\n          .then((v) => Number(parseFloat(v.text()).toFixed(6)))\n          .should('be.approximately', Number(posCardBeforeLongTradeBal) - 0.1, 0.000002)\n      })\n\n      // issue #280\n      it.skip('new input box before trade value should be the same as the one before trade', () => {\n        cy.get('#close-long-osqth-before-trade-balance')\n          .then((v) => Number(parseFloat(v.text()).toFixed(6)))\n          .should('be.approximately', Number(closeLongBeforeTradeBal) - 0.1, 0.000002)\n      })\n\n      it('return to close long card successfully', () => {\n        cy.get('#close-long-header-box').should('contain.text', 'Sell squeeth ERC20 to get ETH')\n        cy.get('#close-long-eth-input').should('have.value', '0')\n        cy.get('#close-long-osqth-input').should('have.value', '0')\n        cy.get('#close-long-submit-tx-btn').should('be.disabled')\n      })\n\n      it('should have \"close your long position\" first error in short oSQTH input when user have long oSQTH', () => {\n        cy.get('#short-card-btn').click({ force: true })\n        cy.get('#open-btn').click({ force: true })\n        cy.get('#open-short-eth-input-box').should('contain.text', 'Close your long position to open a short')\n      })\n\n      // issue #282\n      it.skip('there should be unrealized PnL value', () => {\n        cy.get('#unrealized-pnl-value').should('not.contain.text', 'Loading').should('not.contain.text', '--')\n      })\n\n      it('there should be realized PnL value', () => {\n        cy.get('#realized-pnl-value').should('not.contain.text', 'Loading').should('not.contain.text', '--')\n      })\n    })\n\n    context('close long with manual eth inputs and tx succeeds', () => {\n      before(() => {\n        cy.get('#long-card-btn').click({ force: true })\n        cy.get('#close-btn').click({ force: true })\n      })\n      it('can enter an amount into eth input and tx succeeds', () => {\n        cy.get('#close-long-eth-input').clear().type('0.1', { force: true, delay: 800 }).should('have.value', '0.1')\n        cy.get('#close-long-osqth-input').should('not.equal', '0')\n        cy.get('#close-long-submit-tx-btn').should('not.be.disabled')\n\n        // wait for 15 secs for trade amount to load\n        cy.get('#close-long-osqth-input')\n          .wait(15000)\n          .then((v) => {\n            closeLongoSQTHInput = new BigNumber(v.val().toString())\n          })\n      })\n\n      it('position card before trade balance should be the same as input box before trade balance', () => {\n        cy.get('#position-card-before-trade-balance').then((val) => {\n          cy.get('#close-long-osqth-before-trade-balance')\n            .then((v) => Number(v.text()).toFixed(6))\n            .should('eq', Number(val.text()).toFixed(6))\n        })\n      })\n\n      it('position card post trade balance should become before-trade - input when input changes', () => {\n        cy.get('#position-card-before-trade-balance').then((val) => {\n          cy.get('#position-card-post-trade-balance')\n            .then((v) => Number(parseFloat(v.text()).toFixed(6)))\n            .should('be.approximately', Number(new BigNumber(val.text()).minus(closeLongoSQTHInput)), 0.0002)\n        })\n      })\n\n      it('input box before trade balance should become before-trade - input when input changes', () => {\n        cy.get('#close-long-osqth-before-trade-balance').then((val) => {\n          cy.get('#close-long-osqth-post-trade-balance')\n            .then((v) => Number(parseFloat(v.text()).toFixed(6)))\n            .should('be.approximately', Number(new BigNumber(val.text()).minus(closeLongoSQTHInput)), 0.0002)\n        })\n      })\n\n      it('send tx', () => {\n        cy.get('#close-long-osqth-before-trade-balance').then((bal) => {\n          closeLongBeforeTradeBal = new BigNumber(bal.text().toString())\n        })\n\n        cy.get('#position-card-before-trade-balance').then((bal) => {\n          posCardBeforeLongTradeBal = new BigNumber(bal.text().toString())\n        })\n        cy.get('#close-long-submit-tx-btn').then((btn) => {\n          if (btn.text().includes('Approve oSQTH')) {\n            cy.get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskPermissionToSpend()\n            trade.waitForTransactionSuccess()\n            cy.wait(15000).get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          } else if (btn.text().includes('Sell')) {\n            cy.get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          }\n        })\n      })\n\n      it('there is close long tx finished card after tx succeeds with correct closing value', () => {\n        cy.get('#close-long-card').should('contain.text', 'Close').should('contain.text', 'Sold')\n        cy.get('#conf-msg').should('contain.text', closeLongoSQTHInput.toFixed(6))\n        cy.get('#close-long-close-btn').click({ force: true })\n      })\n\n      it('new position card value should be the same as prev position card value', () => {\n        // wait for 30 sec to update positon\n        cy.get('#position-card-before-trade-balance')\n          .wait(30000)\n          .then((v) => Number(parseFloat(v.text()).toFixed(6)))\n          .should('be.approximately', Number(posCardBeforeLongTradeBal.minus(closeLongoSQTHInput)), 0.000002)\n      })\n\n      it.skip('new input box before trade value should be the same as the one before trade', () => {\n        // issue #280\n        cy.get('#close-long-osqth-before-trade-balance')\n          .then((v) => Number(parseFloat(v.text()).toFixed(6)))\n          .should('be.approximately', Number(closeLongBeforeTradeBal.minus(closeLongoSQTHInput)), 0.000002)\n      })\n\n      it('return to close long card successfully', () => {\n        cy.get('#close-long-header-box').should('contain.text', 'Sell squeeth ERC20 to get ETH')\n        cy.get('#close-long-eth-input').should('have.value', '0')\n        cy.get('#close-long-osqth-input').should('have.value', '0')\n        cy.get('#close-long-submit-tx-btn').should('be.disabled')\n      })\n\n      it('should have \"close your long position\" first error in short oSQTH input when user have long oSQTH', () => {\n        cy.get('#short-card-btn').click({ force: true })\n        cy.get('#open-btn').click({ force: true })\n        cy.get('#open-short-eth-input-box').should('contain.text', 'Close your long position to open a short')\n      })\n\n      // issue #282\n      it.skip('there should be unrealized PnL value', () => {\n        cy.get('#unrealized-pnl-value').should('not.contain.text', 'Loading').should('not.contain.text', '--')\n      })\n\n      it('there should be realized PnL value', () => {\n        cy.get('#realized-pnl-value').should('not.contain.text', 'Loading').should('not.contain.text', '--')\n      })\n    })\n\n    context('close long position with max button and tx succeeds', () => {\n      before(() => {\n        cy.get('#long-card-btn').click({ force: true })\n        cy.get('#close-btn').click({ force: true })\n      })\n      // issue #280, sometimes get incorrect amount to close due to loading issue\n      it('can use max button for close long osqth input and tx succeeds', () => {\n        cy.get('#close-long-osqth-input-action').click()\n        cy.get('#close-long-osqth-input').should('not.equal', '0')\n        cy.get('#close-long-eth-input').should('not.equal', '0')\n        cy.get('#close-long-submit-tx-btn').should('not.be.disabled')\n\n        cy.get('#close-long-osqth-input')\n          .wait(15000)\n          .then((v) => {\n            closeLongoSQTHInput = new BigNumber(v.val().toString())\n          })\n      })\n\n      it('send tx', () => {\n        cy.get('#close-long-submit-tx-btn').then((btn) => {\n          if (btn.text().includes('Approve oSQTH')) {\n            cy.get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskPermissionToSpend()\n            trade.waitForTransactionSuccess()\n            cy.wait(15000).get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          } else if (btn.text().includes('Sell')) {\n            cy.get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          }\n        })\n      })\n\n      // issue #286\n      it.skip('there is close long tx finished card after tx succeeds with correct closing value', () => {\n        cy.get('#close-long-card').should('contain.text', 'Close').should('contain.text', 'Sold')\n        cy.get('#conf-msg').should('contain.text', closeLongoSQTHInput.toFixed(6))\n        cy.get('#close-long-close-btn').click({ force: true })\n      })\n\n      it('return to close long card successfully with all values update to 0', () => {\n        cy.get('#close-long-close-btn').click({ force: true })\n        cy.get('#close-long-header-box').should('contain.text', 'Sell squeeth ERC20 to get ETH')\n        cy.get('#close-long-eth-input').should('have.value', '0')\n        cy.get('#close-long-osqth-input').should('have.value', '0')\n        cy.get('#close-long-submit-tx-btn').should('be.disabled')\n      })\n\n      it('position card should update to 0', () => {\n        cy.get('#position-card-before-trade-balance').should('contain.text', '0')\n      })\n\n      // issue 280\n      it.skip('input box before trade balance should update to 0', () => {\n        cy.get('#close-long-osqth-before-trade-balance').should('contain.text', '0')\n      })\n\n      it('unrealized PnL should be --', () => {\n        cy.get('#unrealized-pnl-value').should('contain.text', '--')\n      })\n\n      it('realized PnL should be --', () => {\n        cy.get('#realized-pnl-value').should('contain.text', '--')\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/frontend/cypress/integration/specs/02-trade-short.spec.js",
    "content": "/// <reference types=\"cypress\" />\nimport TradePage from '../pages/trade'\nimport BigNumber from 'bignumber.js'\nimport { MIN_COLLATERAL_AMOUNT } from '../../../src/constants/index'\n\nconst trade = new TradePage()\n\ndescribe('Trade on trade page', () => {\n  context('Before tests', () => {\n    it(`Before tests`, () => {\n      cy.disconnectMetamaskWalletFromAllDapps()\n      cy.visit('/')\n    })\n  })\n\n  context('Connect metamask wallet', () => {\n    it(`should login with success`, () => {\n      trade.connectBrowserWallet()\n      trade.acceptMetamaskAccessRequest()\n\n      cy.get('#wallet-address').should(`contain.text`, '0x' || '.eth')\n    })\n  })\n\n  let openShortOsqthInput\n  let openShortOsqthBeforeTradeBal\n  let posCardBeforeShortTradeBal\n\n  context(`open short position`, () => {\n    before('jump to open short trade card', () => {\n      cy.get('#short-card-btn').click({ force: true })\n      cy.get('#open-btn').click({ force: true })\n    })\n\n    before(() => {\n      it('eth balance should be greater than minimum collateral amount', () => {\n        cy.get('#user-eth-wallet-balance').invoke('text').then(parseFloat).should('be.at.least', MIN_COLLATERAL_AMOUNT)\n      })\n    })\n\n    context('open short trade condition checks', () => {\n      it('eth balance from wallet should be the same as balance of eth input box', () => {\n        cy.get('#user-eth-wallet-balance').then((bal) => {\n          cy.get('#open-short-eth-before-trade-balance').should('contain.text', Number(bal.text()))\n        })\n      })\n\n      it('it is on open short card', () => {\n        cy.get('#open-short-header-box').should('contain.text', 'Mint & sell squeeth for premium')\n      })\n    })\n\n    context('input checks', () => {\n      it('inputs should be zero by default and tx button is disabled', () => {\n        cy.get('#open-short-eth-input').should('have.value', '0')\n        cy.get('#open-short-trade-details .trade-details-amount').should('contain.text', '0')\n        cy.get('#open-short-submit-tx-btn').should('be.disabled')\n      })\n\n      it('open short input should be more than minimum collateral amount', () => {\n        cy.get('#open-short-eth-input').clear().type('6.9', { delay: 200, force: true }).should('have.value', '6.90')\n        cy.get('#open-short-eth-input').invoke('val').then(parseFloat).should('be.at.least', MIN_COLLATERAL_AMOUNT)\n      })\n\n      it('zero input amount', () => {\n        cy.get('#trade-card').parent().scrollTo('top')\n        cy.get('#open-short-eth-input').should('be.visible')\n        cy.get('#open-short-eth-input').clear().type('0', { delay: 200, force: true }).should('have.value', '0')\n        cy.get('#open-short-trade-details .trade-details-amount').should('contain.text', '0')\n      })\n\n      it('invalid input amount', () => {\n        cy.get('#trade-card').parent().scrollTo('top')\n        cy.get('#open-short-eth-input').should('be.visible')\n        cy.get('#open-short-eth-input').clear().type('\\\\', { delay: 200, force: true }).should('have.value', '0')\n        cy.get('#open-short-trade-details .trade-details-amount').should('contain.text', '0')\n      })\n    })\n\n    context('can enter an amount into osqth input, check position card & input box balances', () => {\n      it('can enter an amount into eth input', () => {\n        cy.get('#trade-card').parent().scrollTo('top')\n        cy.get('#open-short-eth-input').should('be.visible')\n        cy.get('#open-short-eth-input').clear().type('8.', { force: true, delay: 200 }).should('have.value', '8.0')\n        cy.get('#open-short-trade-details .trade-details-amount').invoke('text').then(parseFloat).should('not.equal', 0)\n        cy.get('#open-short-trade-details .trade-details-amount').then((val) => {\n          openShortOsqthInput = new BigNumber(val.text())\n        })\n      })\n\n      // post = before + input\n      // a = input box oSQTH before trade balance\n      // a-post = a + input\n      it('input box oSQTH post trade balance should be the same as before-trade + input when input changes', () => {\n        cy.get('#open-short-osqth-before-trade-balance').then((bal) => {\n          cy.get('#open-short-osqth-post-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', openShortOsqthInput.plus(Number(bal.text())).toFixed(4))\n        })\n      })\n\n      // b = position card oSQTH before trade balance\n      // b-post = b + input\n      it('position card oSQTH post trade balance should be the same as before-trade + input when input changes', () => {\n        cy.get('#position-card-before-trade-balance').then((bal) => {\n          cy.get('#position-card-post-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', openShortOsqthInput.plus(Number(bal.text())).toFixed(4))\n        })\n      })\n\n      // a = b\n      it('position card oSQTH before trade balance should be the same as input box before oSQTH trade balance', () => {\n        cy.get('#open-short-osqth-before-trade-balance').then((bal) => {\n          cy.get('#position-card-before-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', new BigNumber(bal.text().toString()).toFixed(4))\n        })\n      })\n\n      // a + input = b + input != 0\n      it('position card oSQTH post trade balance should be the same as input box post oSQTH trade balance and not equal 0', () => {\n        cy.get('#open-short-osqth-post-trade-balance').then((bal) => {\n          cy.get('#position-card-post-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', new BigNumber(bal.text().toString()).toFixed(4))\n        })\n        cy.get('#open-short-osqth-post-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n        cy.get('#position-card-post-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n      })\n\n      // eth-post = eth-before - 8\n      it('input box eth post trade balance should be the same as before-trade - input when input changes', () => {\n        cy.get('#open-short-eth-before-trade-balance').then((bal) => {\n          cy.get('#open-short-eth-post-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', (Number(bal.text()) - 8).toFixed(4))\n        })\n      })\n\n      it('can adjust collateral ratio', () => {\n        cy.get('.open-short-collat-ratio-input-box input')\n          .clear()\n          .type('250.', { delay: 200, force: true })\n          .should('have.value', '250.0')\n      })\n    })\n\n    context('open short position', () => {\n      it('can open short position for osqth, and tx succeeds', () => {\n        cy.get('#trade-card').parent().scrollTo('top')\n        cy.get('#open-short-eth-input').should('be.visible')\n        cy.get('#open-short-eth-input').clear().type('8.', { force: true, delay: 200 }).should('have.value', '8.0')\n\n        cy.get('#open-short-trade-details .trade-details-amount').then((val) => {\n          openShortOsqthInput = new BigNumber(val.text())\n        })\n\n        cy.get('#open-short-osqth-before-trade-balance').then((val) => {\n          openShortOsqthBeforeTradeBal = new BigNumber(val.text())\n        })\n\n        cy.get('#position-card-before-trade-balance').then((val) => {\n          posCardBeforeShortTradeBal = new BigNumber(val.text())\n        })\n\n        cy.get('#open-short-submit-tx-btn').then((btn) => {\n          if (btn.text().includes('Allow wrapper')) {\n            cy.get('#open-short-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n            cy.get('#open-short-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          } else if (btn.text().includes('Deposit and sell')) {\n            cy.get('#open-short-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          }\n        })\n      })\n\n      it('there is open short tx finished card after tx succeeds with correct closing value', () => {\n        cy.get('#open-short-card').should('contain.text', 'Close').should('contain.text', 'Opened')\n        cy.get('#conf-msg').should('contain.text', openShortOsqthInput.toFixed(6))\n        cy.get('#open-short-close-btn').click({ force: true })\n      })\n\n      it('return to open short card successfully with all values update to 0', () => {\n        cy.get('#open-short-header-box').should('contain.text', 'Mint & sell squeeth for premium')\n        cy.get('#open-short-eth-input').should('have.value', '0')\n        cy.get('#open-short-trade-details .trade-details-amount').should('contain.text', '0')\n        cy.get('#open-short-submit-tx-btn').should('be.disabled')\n      })\n\n      it('position card should update to new osqth balance', () => {\n        // wait for 20 sec to update positon\n        cy.get('#position-card-before-trade-balance')\n          .wait(30000)\n          .then((v) => Number(parseFloat(v.text()).toFixed(4)))\n          .should('be.approximately', Number(posCardBeforeShortTradeBal.plus(openShortOsqthInput)), 0.0002)\n      })\n\n      it('input box before trade update to new osqth balance', () => {\n        cy.get('#open-short-osqth-before-trade-balance')\n          .then((v) => Number(parseFloat(v.text()).toFixed(4)))\n          .should('be.approximately', Number(openShortOsqthBeforeTradeBal.plus(openShortOsqthInput)), 0.0002)\n      })\n\n      it('position card update to the same value as input box before trade balance and not equal 0', () => {\n        cy.get('#open-short-osqth-before-trade-balance').then((bal) => {\n          cy.get('#position-card-before-trade-balance')\n            .then((v) => Number(v.text()).toFixed(4))\n            .should('eq', new BigNumber(bal.text().toString()).toFixed(4))\n        })\n        cy.get('#open-short-osqth-before-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n        cy.get('#position-card-before-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n      })\n\n      // issue #282\n      it.skip('unrealized PnL display', () => {\n        cy.get('#unrealized-pnl-value').should('not.contain.text', 'Loading').should('not.contain.text', '--')\n      })\n\n      it('should have \"close your short position\" first error in long oSQTH input when user have short oSQTH', () => {\n        cy.get('#long-card-btn').click({ force: true })\n        cy.get('#open-btn').click({ force: true })\n        cy.get('#open-long-eth-input-box').should('contain.text', 'Close your short position to open a long')\n      })\n    })\n  })\n\n  context(`when have short oSQTH balance, the default trade card would be short`, () => {\n    // issue #278\n    it.skip('reload to see if by default is short & open trade cards', () => {\n      cy.reload()\n      trade.connectBrowserWallet()\n      trade.acceptMetamaskAccessRequest()\n      cy.get('#wallet-address').should(`contain.text`, '0x' || '.eth')\n      cy.get('#open-short-header-box').should('contain.text', 'Mint & sell squeeth for premium')\n    })\n  })\n\n  let closeShortBeforeTradeBal\n  let maxBtnShortCloseInput\n  let fullShortCloseInput\n\n  context(`close short position`, () => {\n    before('jump to close short card', () => {\n      cy.get('#short-card-btn').click({ force: true })\n      cy.get('#close-btn').click({ force: true })\n    })\n\n    context('close short position partially', () => {\n      context('close short trade condition checks', () => {\n        it('it is on close short card', () => {\n          cy.get('#close-short-header-box').should('contain.text', 'Buy back oSQTH & close position')\n        })\n\n        // loading issues\n        it.skip('should select full close by default and there should be oSQTH short balance in input, input shoulde be disabled and tx button is not disabled', () => {\n          cy.get('#close-short-type-select').should('contain.text', 'Full Close')\n          cy.get('#close-short-osqth-input').should('not.equal', '0')\n\n          cy.get('#close-short-trade-details .trade-details-amount')\n            .invoke('text')\n            .then(parseFloat)\n            .should('not.equal', 0)\n\n          cy.get('#close-short-osqth-input').should('be.disabled')\n          cy.get('#close-short-submit-tx-btn').should('not.be.disabled')\n        })\n\n        it('should have oSQTH short balance in position card', () => {\n          cy.get('#position-card-before-trade-balance').invoke('text').then(parseFloat).should('not.equal', 0)\n        })\n      })\n\n      context('input checks', () => {\n        it('zero input amount when partial close is selected', () => {\n          cy.get('#close-short-type-select .MuiSelect-select').wait(10000).click({ force: true })\n          cy.get('#close-short-partial-close').click({ force: true })\n          cy.get('#close-short-type-select').should('contain.text', 'Partial Close')\n          cy.get('#close-short-osqth-input').clear().type('0', { delay: 200 }).should('have.value', '0')\n          cy.get('#close-short-trade-details .trade-details-amount').should('contain.text', '0')\n        })\n\n        it('invalid input amount when partial close is selected', () => {\n          cy.get('#close-short-type-select .MuiSelect-select').click({ force: true })\n          cy.get('#close-short-partial-close').click({ force: true })\n          cy.get('#close-short-type-select').should('contain.text', 'Partial Close')\n          cy.get('#close-short-osqth-input').clear().type('\\\\', { delay: 200 }).should('have.value', '0')\n          cy.get('#close-short-trade-details .trade-details-amount').should('contain.text', '0')\n        })\n\n        it('submit tx button should be disabled when input is zero', () => {\n          cy.get('#close-short-osqth-input').clear().type('0', { delay: 200 }).should('have.value', '0')\n          cy.get('#close-short-submit-tx-btn').should('be.disabled')\n        })\n      })\n\n      context('can enter an amount into osqth input', () => {\n        it('select partial close and have manual input', () => {\n          cy.get('#close-short-type-select .MuiSelect-select').click({ force: true })\n          cy.get('#close-short-partial-close').click({ force: true })\n          cy.get('#close-short-type-select').wait(2000).should('contain.text', 'Partial Close')\n\n          cy.get('#close-short-osqth-input')\n            .clear()\n            .type('0.1', { force: true, delay: 800 })\n            .should('have.value', '0.1')\n\n          // make sure it's able to close short partially\n          cy.get('.close-short-collat-ratio-input-box input')\n            .clear()\n            .type('250.', { delay: 200, force: true })\n            .should('have.value', '250.0')\n\n          cy.get('#close-short-trade-details .trade-details-amount')\n            .invoke('text')\n            .then(parseFloat)\n            .should('not.equal', 0)\n\n          cy.get('#close-short-submit-tx-btn').should('not.be.disabled')\n        })\n\n        it('position card before trade balance should be the same as input box before trade balance', () => {\n          cy.get('#position-card-before-trade-balance').then((val) => {\n            cy.get('#close-short-osqth-before-trade-balance')\n              .then((v) => Number(v.text()).toFixed(6))\n              .should('eq', Number(val.text()).toFixed(6))\n          })\n        })\n\n        it('position card post trade balance should become before-trade - input when input changes', () => {\n          cy.get('#position-card-before-trade-balance').then((val) => {\n            cy.get('#position-card-post-trade-balance')\n              .then((v) => Number(v.text()).toFixed(6))\n              .should('eq', (Number(val.text()) - 0.1).toFixed(6))\n          })\n        })\n\n        it('input box before trade balance should become before-trade - input when input changes', () => {\n          cy.get('#close-short-osqth-before-trade-balance').then((val) => {\n            cy.get('#close-short-osqth-post-trade-balance')\n              .then((v) => Number(v.text()).toFixed(6))\n              .should('eq', (Number(val.text()) - 0.1).toFixed(6))\n          })\n        })\n      })\n\n      context('can use max button for osqth input when partially close first selected', () => {\n        it('can select partial close first then full close', () => {\n          cy.get('#close-short-type-select .MuiSelect-select').click({ force: true })\n          cy.get('#close-short-partial-close').click({ force: true })\n          cy.get('#close-short-type-select').should('contain.text', 'Partial Close')\n          cy.get('#close-short-osqth-input-action').click()\n          cy.get('#close-short-type-select').should('contain.text', 'Full Close')\n          cy.get('#close-short-osqth-input').should('not.equal', '0')\n          cy.get('#close-short-trade-details .trade-details-amount')\n            .invoke('text')\n            .then(parseFloat)\n            .should('not.equal', 0)\n          cy.get('#close-short-osqth-input').should('be.disabled')\n          cy.get('#close-short-submit-tx-btn').should('not.be.disabled')\n\n          cy.get('#close-short-osqth-input').then((val) => {\n            maxBtnShortCloseInput = new BigNumber(val.val().toString()).toFixed(6)\n          })\n        })\n\n        it('position card before trade balance should be the same as input when input changes', () => {\n          cy.get('#position-card-before-trade-balance')\n            .then((v) => Number(v.text()).toFixed(6))\n            .should('eq', maxBtnShortCloseInput)\n        })\n\n        it('position card post trade balance should become 0 when input changes', () => {\n          cy.get('#position-card-post-trade-balance').should('contain.text', '0')\n        })\n\n        it('input box before trade balance should be the same as input when input changes', () => {\n          cy.get('#close-short-osqth-before-trade-balance')\n            .then((v) => Number(v.text()).toFixed(6))\n            .should('eq', maxBtnShortCloseInput)\n        })\n\n        it('position card post trade balance should become 0 when input changes', () => {\n          cy.get('#close-short-osqth-post-trade-balance').should('contain.text', (0).toFixed(6))\n        })\n      })\n\n      context('close short position partially tx', () => {\n        it('can close short position partially, and tx succeeds', () => {\n          cy.get('#close-short-type-select .MuiSelect-select').click({ force: true })\n          // issue #279\n          cy.get('#close-short-partial-close').wait(2000).click({ force: true })\n          cy.get('#close-short-type-select').should('contain.text', 'Partial Close')\n          cy.get('#close-short-osqth-input').should('not.be.disabled')\n          cy.get('#close-short-osqth-input')\n            .clear()\n            .type('0.01', { force: true, delay: 800 })\n            .should('have.value', '0.01')\n\n          // make sure it's able to close short partially\n          cy.get('.close-short-collat-ratio-input-box input')\n            .clear()\n            .type('250.', { delay: 200, force: true })\n            .should('have.value', '250.0')\n\n          cy.get('#close-short-osqth-before-trade-balance').then((bal) => {\n            closeShortBeforeTradeBal = bal.text()\n          })\n\n          cy.get('#position-card-before-trade-balance').then((bal) => {\n            posCardBeforeShortTradeBal = bal.text()\n          })\n\n          cy.get('#close-short-submit-tx-btn').then((btn) => {\n            if (btn.text().includes('Allow wrapper')) {\n              cy.get('#close-short-submit-tx-btn').click({ force: true })\n              trade.confirmMetamaskTransaction()\n              trade.waitForTransactionSuccess()\n              cy.get('#close-short-submit-tx-btn').click({ force: true })\n              trade.confirmMetamaskTransaction()\n              trade.waitForTransactionSuccess()\n            }\n            if (btn.text().includes('Buy back')) {\n              cy.get('#close-short-submit-tx-btn').click({ force: true })\n              trade.confirmMetamaskTransaction()\n              trade.waitForTransactionSuccess()\n            }\n          })\n        })\n\n        it('there is close short tx finished card after tx succeeds with correct closing value', () => {\n          cy.get('#close-short-card').should('contain.text', 'Close').should('contain.text', 'Closed')\n          cy.get('#conf-msg').should('contain.text', (0.01).toFixed(6))\n          cy.get('#close-short-close-btn').click({ force: true })\n        })\n\n        it('new position card value should be the same as prev position card value', () => {\n          // wait for 30 sec to update positon\n          cy.get('#position-card-before-trade-balance')\n            .wait(30000)\n            .then((v) => Number(v.text()).toFixed(6))\n            .should('eq', (Number(posCardBeforeShortTradeBal) - 0.01).toFixed(6))\n        })\n\n        it.skip('new input box before trade value should be the same as the one before trade', () => {\n          // new input box before trade value should be the same as the one before trade\n          // issue #280\n          cy.get('#close-short-osqth-before-trade-balance')\n            .then((v) => Number(v.text()).toFixed(6))\n            .should('eq', (Number(closeShortBeforeTradeBal) - 0.01).toFixed(6))\n        })\n\n        it('return to close short card successfully', () => {\n          cy.get('#close-short-header-box').should('contain.text', 'Buy back oSQTH & close position')\n          cy.get('#close-short-type-select').should('contain.text', 'Full Close')\n          cy.get('#close-short-trade-details .trade-details-amount')\n            .invoke('text')\n            .then(parseFloat)\n            .should('not.equal', 0)\n          cy.get('#close-short-osqth-input').should('not.equal', '0').should('be.disabled')\n          cy.get('#close-short-submit-tx-btn').should('not.be.disabled')\n        })\n\n        it('should have \"close your short position\" first error in long oSQTH input when user have short oSQTH', () => {\n          cy.get('#long-card-btn').click({ force: true })\n          cy.get('#open-btn').click({ force: true })\n          cy.get('#open-long-eth-input-box').should('contain.text', 'Close your short position to open a long')\n        })\n\n        // issue #282\n        it.skip('there should be unrealized PnL value', () => {\n          cy.get('#unrealized-pnl-value').should('not.contain.text', 'Loading').should('not.contain.text', '--')\n        })\n\n        it('there should be realized PnL value', () => {\n          cy.get('#realized-pnl-value').should('not.contain.text', 'Loading').should('not.contain.text', '--')\n        })\n      })\n    })\n\n    context('close short position fully tx', () => {\n      before('jump to short close card', () => {\n        cy.get('#short-card-btn').click({ force: true })\n        cy.get('#close-btn').click({ force: true })\n      })\n\n      it(`can close short position fully and tx succeeds`, () => {\n        cy.get('#close-short-type-select .MuiSelect-select').click({ force: true })\n        cy.get('#close-short-full-close').click({ force: true })\n        cy.get('#close-short-type-select').should('contain.text', 'Full Close')\n        cy.get('#close-short-osqth-input').should('not.equal', '0')\n        cy.get('#close-short-osqth-input').then((bal) => {\n          fullShortCloseInput = new BigNumber(bal.val().toString()).toFixed(6)\n        })\n\n        cy.get('#close-short-submit-tx-btn').then((btn) => {\n          if (btn.text().includes('Allow wrapper')) {\n            cy.get('#close-short-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n            cy.get('#close-short-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          } else if (btn.text().includes('Buy back')) {\n            cy.get('#close-short-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          }\n        })\n      })\n\n      it('there is close short tx finished card after tx succeeds with correct closing value', () => {\n        cy.get('#close-short-card').should('contain.text', 'Close').should('contain.text', 'Closed')\n        cy.get('#conf-msg').should('contain.text', fullShortCloseInput)\n        cy.get('#close-short-close-btn').click({ force: true })\n      })\n\n      it('return to close short card successfully with all values update to 0', () => {\n        cy.get('#close-short-header-box').should('contain.text', 'Buy back oSQTH & close position')\n        cy.get('#close-short-type-select').should('contain.text', 'Full Close')\n        cy.get('#close-short-osqth-input').should('have.value', '0')\n        cy.get('#close-short-trade-details .trade-details-amount').should('contain.text', '0')\n        cy.get('#close-short-submit-tx-btn').should('be.disabled')\n      })\n\n      it('position card should update to 0', () => {\n        cy.get('#position-card-before-trade-balance').should('contain.text', '0')\n      })\n\n      it('input box before trade balance should update to 0', () => {\n        cy.get('#close-short-osqth-before-trade-balance').should('contain.text', '0')\n      })\n\n      // issue #281\n      it.skip('Current CR in close short trade card is not updated to 0 after close out all of the short position', () => {\n        cy.get('#close-short-collateral-ratio .trade-info-item-value').should('contain.text', '0')\n      })\n\n      it('unrealized PnL should be --', () => {\n        cy.get('#unrealized-pnl-value').should('contain.text', '--')\n      })\n\n      it('realized PnL should be --', () => {\n        cy.get('#realized-pnl-value').should('contain.text', '--')\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/frontend/cypress/integration/specs/06-manual-short.spec.js",
    "content": "/// <reference types=\"cypress\" />\nimport BigNumber from 'bignumber.js'\nimport TradePage from '../pages/trade'\n\nconst trade = new TradePage()\n\n// need to change close long component to manually sell osqth, add these two lines:\n// const mintedDebt = useMintedDebt()\n// const longSqthBal = mintedDebt\n\ndescribe('Trade on trade page', () => {\n  context('Before tests', () => {\n    it(`Before tests`, () => {\n      cy.disconnectMetamaskWalletFromAllDapps()\n      cy.visit('/lp')\n    })\n  })\n\n  context('Connect metamask wallet', () => {\n    it(`should login with success`, () => {\n      trade.connectBrowserWallet()\n      trade.acceptMetamaskAccessRequest()\n      cy.get('#wallet-address').should(`contain.text`, '0x' || '.eth')\n    })\n  })\n  context('can create short position in 2 sep txs', () => {\n    it('can mint first on LP page', () => {\n      cy.get('#lp-prev-step-btn').click({ force: true }).click({ force: true })\n      cy.get('#mint-sqth-to-lp-btn').click({ force: true })\n      cy.get('#lp-page-mint-eth-input').clear().type('8.', { force: true, delay: 200 }).should('have.value', '8.0')\n      cy.get('#mint-to-lp-btn').click({ force: true })\n      trade.confirmMetamaskTransaction()\n      trade.waitForTransactionSuccess()\n    })\n    context(`sell minted squth, which is create short position`, () => {\n      before(() => {\n        cy.visit('/')\n        cy.get('#long-card-btn').click({ force: true })\n        cy.get('#close-btn').click({ force: true })\n      })\n      it('can create short position with manual selling with custom input', () => {\n        cy.get('#close-long-osqth-input').clear().type('0.1', { force: true, delay: 200 }).should('have.value', '0.1')\n        cy.get('#close-long-submit-tx-btn').then((btn) => {\n          if (btn.text().includes('Approve oSQTH')) {\n            cy.get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskPermissionToSpend()\n            trade.waitForTransactionSuccess()\n            cy.wait(15000).get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          }\n          if (btn.text().includes('Sell')) {\n            cy.get('#close-long-submit-tx-btn').click({ force: true })\n            trade.confirmMetamaskTransaction()\n            trade.waitForTransactionSuccess()\n          }\n        })\n      })\n      it('there is tx finished card with correct trade amount', () => {\n        cy.get('#close-long-card').should('contain.text', 'Close').should('contain.text', 'Sold')\n        cy.get('#conf-msg').should('contain.text', Number(0.1).toFixed(6))\n        cy.get('#close-long-close-btn').click()\n      })\n\n      it('check position card with correct short position', () => {\n        cy.get('#position-card-before-trade-balance').wait(15000).should('contain.text', Number(0.1).toFixed(6))\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/frontend/cypress/plugins/index.js",
    "content": "import synpressPlugins from '@synthetixio/synpress/plugins'\n\n/** @type {Cypress.PluginConfig} */\n// eslint-disable-next-line no-unused-vars\nmodule.exports = (on, config) => {\n  // `on` is used to hook into various events Cypress emits\n  // `config` is the resolved Cypress config\n\n  synpressPlugins(on, config)\n}\n"
  },
  {
    "path": "packages/frontend/cypress/support/commands.js",
    "content": "// ***********************************************\n// This example commands.js shows you how to\n// create various custom commands and overwrite\n// existing commands.\n//\n// For more comprehensive examples of custom\n// commands please read more here:\n// https://on.cypress.io/custom-commands\n// ***********************************************\n//\n//\n// -- This is a parent command --\n// Cypress.Commands.add('login', (email, password) => { ... })\n//\n//\n// -- This is a child command --\n// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })\n//\n//\n// -- This is a dual command --\n// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })\n//\n//\n// -- This will overwrite an existing command --\n// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })\n// Cypress.Commands.add('connectWallet', () => {\n//   cy.get('body').then(($body) => {\n//     if ($body.find('.chakra-modal__content').length <= 0) {\n//       cy.findByText('Connect to a wallet').click()\n//     }\n//   })\n//   cy.findByText('MetaMask').click()\n//   cy.task('acceptMetamaskAccess')\n// })\n"
  },
  {
    "path": "packages/frontend/cypress/support/index.js",
    "content": "// ***********************************************************\n// This example support/index.js is processed and\n// loaded automatically before your test files.\n//\n// This is a great place to put global configuration and\n// behavior that modifies Cypress.\n//\n// You can change the location of this file or turn off\n// automatically serving support files with the\n// 'supportFile' configuration option.\n//\n// You can read more here:\n// https://on.cypress.io/configuration\n// ***********************************************************\n\n// Import commands.js using ES2015 syntax:\nimport './commands'\nimport '@synthetixio/synpress/support'\n// Alternatively you can use CommonJS syntax:\n// require('./commands')\n"
  },
  {
    "path": "packages/frontend/cypress.json",
    "content": "{\n    \"baseUrl\": \"http://localhost:3000\",\n    \"userAgent\": \"synpress\",\n    \"retries\": {\n        \"runMode\": 0,\n        \"openMode\": 0\n    },\n    \"integrationFolder\": \"cypress/integration/specs\",\n    \"screenshotsFolder\": \"cypress/screenshots\",\n    \"videosFolder\": \"cypress/videos\",\n    \"supportFile\": \"cypress/support/index.js\",\n    \"pluginsFile\": \"cypress/plugins/index.js\",\n    \"chromeWebSecurity\": true,\n    \"viewportWidth\": 1920,\n    \"viewportHeight\": 1080,\n    \"scrollBehavior\": false,\n    \"component\": {\n        \"componentFolder\": \".\",\n        \"testFiles\": \"**/*.spec.{js,jsx,ts,tsx}\"\n    },\n    \"env\": {\n        \"coverage\": true\n    },\n    \"defaultCommandTimeout\": 30000,\n    \"pageLoadTimeout\": 30000,\n    \"requestTimeout\": 30000\n}"
  },
  {
    "path": "packages/frontend/env.example",
    "content": "NEXT_PUBLIC_INFURA_API_KEY=\" \"\nNEXT_PUBLIC_BLOCKNATIVE_DAPP_ID=\" \"\nNEXT_PUBLIC_UPDATE_DB=\"false\"\nNEXT_PUBLIC_TARDIS_API_KEY=\" \"\nNEXT_PUBLIC_FIREBASE_API_KEY=\" \"\nNEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=\" \"\nNEXT_PUBLIC_FIREBASE_PROJECT_ID=\" \"\nNEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=\" \"\nNEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=\" \"\nNEXT_PUBLIC_FIREBASE_APP_ID=\" \"\nNEXT_PUBLIC_FATHOM_CODE=\" \""
  },
  {
    "path": "packages/frontend/jest.config.js",
    "content": "module.exports = {\n  testEnvironment: 'jsdom',\n  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],\n  testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/', '<rootDir>/cypress/'],\n  moduleNameMapper: {\n    '^src(.*)$': '<rootDir>/src$1',\n    '^@utils(.*)$': '<rootDir>/src/utils$1',\n    '^@hooks(.*)$': '<rootDir>/src/hooks$1',\n    '^@components(.*)$': '<rootDir>/src/components$1',\n  },\n}\n"
  },
  {
    "path": "packages/frontend/jest.setup.ts",
    "content": "import '@testing-library/jest-dom'\nimport 'cross-fetch/polyfill'\nimport dotenv from \"dotenv\"\ndotenv.config()\n"
  },
  {
    "path": "packages/frontend/middleware.ts",
    "content": "import { NextRequest, NextResponse } from 'next/server'\nimport { Redis } from '@upstash/redis'\n\nimport { isVPN } from 'src/server/ipqs'\nimport { BLOCKED_IP_VALUE } from 'src/constants'\n\nconst redis = new Redis({\n  url: process.env.UPSTASH_REDIS_REST_URL!,\n  token: process.env.UPSTASH_REDIS_REST_TOKEN!,\n})\n\nconst THIRTY_DAYS_IN_MS = 30 * 24 * 60 * 60 * 1000\n\ninterface RedisResponse {\n  value: string\n  timestamp: number\n}\n\nasync function isIPBlockedInRedis(ip: string, currentTime: number) {\n  let redisData: RedisResponse | null = null\n  try {\n    redisData = await redis.get<RedisResponse>(ip)\n  } catch (error) {\n    console.error('Failed to get data from Redis:', error)\n  }\n\n  let isIPBlocked = false\n  if (redisData) {\n    try {\n      const { value, timestamp } = redisData\n      // check if entry is valid and is not more than 30 days old\n      if (value === BLOCKED_IP_VALUE && currentTime - timestamp <= THIRTY_DAYS_IN_MS) {\n        isIPBlocked = true\n      }\n    } catch (error) {\n      console.error('Failed to parse data from Redis:', error)\n    }\n  }\n\n  return isIPBlocked\n}\n\nexport async function middleware(request: NextRequest) {\n  const cloudflareCountry = request.headers.get('cf-ipcountry')\n  const country = cloudflareCountry ?? request.geo?.country\n  const url = request.nextUrl\n\n  const ip = request.headers.get('cf-connecting-ip') || request.headers.get('x-forwarded-for') || request.ip\n\n  const allowedIPs = (process.env.WHITELISTED_IPS || '').split(',')\n  const isIPWhitelisted = ip && allowedIPs.includes(ip)\n\n  if (ip && !isIPWhitelisted) {\n    const currentTime = Date.now()\n    // check if IP is blocked\n    const isIPBlocked = await isIPBlockedInRedis(ip, currentTime)\n    if (isIPBlocked && url.pathname !== '/blocked') {\n      return NextResponse.redirect(`${url.protocol}//${url.host}/blocked`)\n    }\n\n    // check if IP is from VPN\n    const isIPFromVPN = await isVPN(ip)\n    if (isIPFromVPN && url.pathname !== '/blocked') {\n      try {\n        await redis.set(ip, { value: BLOCKED_IP_VALUE, timestamp: currentTime })\n      } catch (error) {\n        console.error('Failed to set data in Redis:', error)\n      }\n      return NextResponse.redirect(`${url.protocol}//${url.host}/blocked`)\n    }\n  }\n\n  if (url.searchParams.has('ct') && url.searchParams.get('ct') === String(country)) {\n    return NextResponse.next()\n  }\n\n  url.searchParams.set('ct', country!)\n  return NextResponse.redirect(url)\n}\n\n/*\n  matcher for excluding public assets/api routes/_next\n  link: https://github.com/vercel/next.js/discussions/36308#discussioncomment-3758041\n*/\nexport const config = {\n  matcher: '/((?!api|static|.*\\\\..*|_next|blocked).*)',\n}\n"
  },
  {
    "path": "packages/frontend/next-env.d.ts",
    "content": "/// <reference types=\"next\" />\n/// <reference types=\"next/image-types/global\" />\n\n// NOTE: This file should not be edited\n// see https://nextjs.org/docs/basic-features/typescript for more information.\n"
  },
  {
    "path": "packages/frontend/next.config.js",
    "content": "// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { withSentryConfig } = require('@sentry/nextjs')\n\nconst securityHeaders = [\n  {\n    key: 'X-Frame-Options',\n    value: 'SAMEORIGIN',\n  },\n]\n\nconst moduleExports = {\n  reactStrictMode: true,\n  images: {\n    domains: ['media.giphy.com'],\n  },\n  async rewrites() {\n    return [\n      {\n        source: '/api/amplitude',\n        destination: 'https://api.eu.amplitude.com/2/httpapi',\n      },\n    ]\n  },\n  async headers() {\n    return [\n      {\n        // Apply these headers to all routes in your application.\n        source: '/:path*',\n        headers: securityHeaders,\n      },\n    ]\n  },\n  eslint: {\n    dirs: ['pages', 'src'],\n  },\n}\n\nconst sentryWebpackPluginOptions = {\n  org: 'opyn',\n  project: 'squeeth',\n  // authToken: process.env.SENTRY_AUTH_TOKEN,\n  silent: true,\n}\n\nmodule.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions)\n"
  },
  {
    "path": "packages/frontend/package.json",
    "content": "{\n    \"name\": \"@squeeth/frontend\",\n    \"version\": \"0.1.0\",\n    \"private\": true,\n    \"engines\": {\n        \"node\": \"^18\"\n    },\n    \"scripts\": {\n        \"dev\": \"next dev\",\n        \"build\": \"next build\",\n        \"start\": \"next start\",\n        \"build-start\": \"npm run build && npm run start\",\n        \"lint\": \"next lint\",\n        \"test\": \"jest --watch\",\n        \"test:ci\": \"jest --no-watch\",\n        \"cypress\": \"dotenv -e .env -- synpress run --configFile cypress.json --config supportFile='cypress/support/index.js',pluginsFile='cypress/plugins/index.js' -b chrome\",\n        \"cypress:mobile\": \"dotenv -e .env -- synpress run --configFile cypress.json --config supportFile='cypress/support/index.js',pluginsFile='cypress/plugins/index.js,viewportWidth=375,viewportHeight=667' --env guildName='Cypress Mobile Gang',guildUrlName='cypress-mobile-gang',dcInvite='https://discord.gg/G6VWkWJrzp',tgId='-1001689086791' -b chromium\",\n        \"cypress:record\": \"dotenv -e .env -e .env.development.local -- synpress run --record --configFile cypress.json --config supportFile='cypress/support/index.js',pluginsFile='cypress/plugins/index.js' -b chromium\",\n        \"cypress:mobile:record\": \"dotenv -e .env -e .env.development.local -- synpress run --record --configFile cypress.json --config supportFile='cypress/support/index.js',pluginsFile='cypress/plugins/index.js,viewportWidth=375,viewportHeight=667' -b chromium\",\n        \"cypress:open\": \"dotenv -e .env -- synpress open --configFile cypress.json\",\n        \"cypress:gh\": \"synpress run --record --configFile cypress.json --config supportFile='cypress/support/index.js',pluginsFile='cypress/plugins/index.js' --group Desktop -b chromium\",\n        \"cypress:mobile:gh\": \"synpress run --record --configFile cypress.json --config supportFile='cypress/support/index.js',pluginsFile='cypress/plugins/index.js,viewportWidth=375,viewportHeight=667' --group Mobile -b chromium\",\n        \"start:server\": \"serve tests/test-dapp -p 3000\",\n        \"test:e2e:ci\": \"start-server-and-test 'yarn start:server' http-get://localhost:3000 'yarn run cypress'\",\n        \"codegen:uniswap\": \"apollo client:codegen --target typescript --globalTypesFile=types/global_apollo.ts --includes=./src/queries/uniswap/**/*.ts  --endpoint 'https://api.thegraph.com/subgraphs/name/kmkoushik/uniswap-v3-ropsten'\",\n        \"codegen:squeeth\": \"apollo client:codegen --target typescript --globalTypesFile=types/global_apollo.ts --includes=./src/queries/squeeth/**/*.ts  --endpoint 'https://api.thegraph.com/subgraphs/name/haythem96/squeeth-temp-subgraph'\"\n    },\n    \"dependencies\": {\n        \"@amplitude/analytics-browser\": \"^1.3.0\",\n        \"@apollo/client\": \"^3.4.10\",\n        \"@cypress/react\": \"^5.12.4\",\n        \"@date-io/date-fns\": \"^1.3.13\",\n        \"@davatar/react\": \"^1.8.1\",\n        \"@ethersproject/providers\": \"^5.5.2\",\n        \"@material-ui/core\": \"^4.12.3\",\n        \"@material-ui/icons\": \"^4.11.2\",\n        \"@material-ui/lab\": \"^4.0.0-alpha.60\",\n        \"@material-ui/pickers\": \"^3.3.10\",\n        \"@testing-library/react-hooks\": \"^8.0.0\",\n        \"@thanpolas/univ3prices\": \"^3.0.2\",\n        \"@uniswap/sdk-core\": \"^3.0.1\",\n        \"@uniswap/smart-order-router\": \"^2.5.30\",\n        \"@uniswap/v3-sdk\": \"^3.3.2\",\n        \"@upstash/redis\": \"^1.22.0\",\n        \"@vercel/og\": \"^0.0.25\",\n        \"axios\": \"^0.24.0\",\n        \"bignumber.js\": \"^9.0.1\",\n        \"bnc-notify\": \"^1.9.1\",\n        \"bnc-onboard\": \"1.27.0\",\n        \"chart.js\": \"^2.9.4\",\n        \"clsx\": \"^1.1.1\",\n        \"copy-to-clipboard\": \"^3.3.1\",\n        \"crisp-sdk-web\": \"^1.0.11\",\n        \"date-fns\": \"^2.29.3\",\n        \"fathom-client\": \"^3.2.0\",\n        \"firebase\": \"^8.8.0\",\n        \"firebase-admin\": \"^11.10.1\",\n        \"framer-motion\": \"^5.3.3\",\n        \"fzero\": \"^0.2.4\",\n        \"graphql\": \"^16.1.0\",\n        \"gray-matter\": \"^4.0.3\",\n        \"hamburger-react\": \"^2.5.0\",\n        \"highcharts\": \"^10.2.1\",\n        \"highcharts-react-official\": \"^3.1.0\",\n        \"javascript-time-ago\": \"^2.5.7\",\n        \"jotai\": \"^1.5.3\",\n        \"kaktana-react-lightweight-charts\": \"^2.0.0\",\n        \"lodash\": \"^4.17.21\",\n        \"lodash.isequal\": \"^4.5.0\",\n        \"markdown-to-jsx\": \"^7.1.5\",\n        \"next\": \"^12.2.3\",\n        \"next-seo\": \"^5.15.0\",\n        \"react\": \"17.0.2\",\n        \"react-chartjs-2\": \"^2.11.1\",\n        \"react-cookie-consent\": \"^8.0.1\",\n        \"react-dom\": \"17.0.2\",\n        \"react-query\": \"^3.34.0\",\n        \"react-use\": \"^17.3.2\",\n        \"recharts\": \"^2.2.0\",\n        \"set-interval-async\": \"^2.0.3\",\n        \"subscriptions-transport-ws\": \"^0.11.0\",\n        \"use-debounce\": \"^9.0.2\",\n        \"web3\": \"^1.5.2\"\n    },\n    \"devDependencies\": {\n        \"@babel/preset-react\": \"^7.16.7\",\n        \"@sentry/nextjs\": \"^7.10.0\",\n        \"@synthetixio/synpress\": \"^1.1.1\",\n        \"@testing-library/dom\": \"^8.11.3\",\n        \"@testing-library/jest-dom\": \"^5.16.2\",\n        \"@testing-library/react\": \"^12.1.3\",\n        \"@testing-library/user-event\": \"^13.5.0\",\n        \"@types/firebase\": \"^3.2.1\",\n        \"@types/jest\": \"^27.4.1\",\n        \"@types/lodash.isequal\": \"^4.5.5\",\n        \"@types/react\": \"17.0.17\",\n        \"@types/set-interval-async\": \"^1.0.0\",\n        \"@typescript-eslint/eslint-plugin\": \"^4.14.2\",\n        \"@typescript-eslint/parser\": \"^4.14.2\",\n        \"babel-jest\": \"^27.5.1\",\n        \"dotenv-cli\": \"^5.0.0\",\n        \"eslint\": \"7.32.0\",\n        \"eslint-config-next\": \"11.0.1\",\n        \"eslint-config-prettier\": \"^8.3.0\",\n        \"eslint-plugin-prettier\": \"^3.3.1\",\n        \"eslint-plugin-react\": \"^7.22.0\",\n        \"eslint-plugin-react-hooks\": \"^4.2.0\",\n        \"eslint-plugin-simple-import-sort\": \"^7.0.0\",\n        \"jest\": \"^27.5.1\",\n        \"mock-apollo-client\": \"^1.2.0\",\n        \"node-mocks-http\": \"^1.11.0\",\n        \"prettier\": \"^2.3.1\",\n        \"typescript\": \"4.3.5\"\n    },\n    \"resolutions\": {\n        \"assemblyscript\": \"git+https://github.com/AssemblyScript/assemblyscript.git#v0.6\"\n    },\n    \"workspaces\": {\n        \"nohoist\": [\n            \"ip-range-check\",\n            \"ip-range-check/**\"\n        ]\n    }\n}"
  },
  {
    "path": "packages/frontend/pages/_app.tsx",
    "content": "import useRenderCounter from '../src/hooks/useRenderCounter'\nimport '../styles/globals.css'\nimport { ApolloProvider } from '@apollo/client'\nimport CssBaseline from '@material-ui/core/CssBaseline'\nimport { ThemeProvider } from '@material-ui/core/styles'\nimport * as Fathom from 'fathom-client'\nimport Head from 'next/head'\nimport { useRouter } from 'next/router'\nimport { Crisp } from 'crisp-sdk-web'\nimport React, { memo, useEffect, useMemo, useRef } from 'react'\nimport { QueryClient, QueryClientProvider } from 'react-query'\nimport { ReactQueryDevtools } from 'react-query/devtools'\nimport { useAtomValue } from 'jotai'\nimport { RestrictUserProvider, useRestrictUser } from '@context/restrict-user'\nimport getTheme, { Mode } from '../src/theme'\nimport { uniswapClient } from '@utils/apollo-client'\nimport { useOnboard, useConnectWallet } from 'src/state/wallet/hooks'\nimport { networkIdAtom, onboardAddressAtom, walletFailVisibleAtom } from 'src/state/wallet/atoms'\nimport { useUpdateSqueethPrices, useUpdateSqueethPoolData } from 'src/state/squeethPool/hooks'\nimport { useInitController } from 'src/state/controller/hooks'\nimport { ComputeSwapsProvider } from 'src/state/positions/providers'\nimport { useSwaps } from 'src/state/positions/hooks'\nimport { useUpdateAtom } from 'jotai/utils'\nimport useAppEffect from '@hooks/useAppEffect'\nimport WalletFailModal from '@components/WalletFailModal'\nimport { checkIsValidAddress, updateBlockedAddress } from 'src/state/wallet/apis'\nimport TimeAgo from 'javascript-time-ago'\nimport en from 'javascript-time-ago/locale/en'\nimport '@utils/amplitude'\nimport { initializeAmplitude } from '@utils/amplitude'\nimport useAmplitude from '@hooks/useAmplitude'\nimport StrategyLayout from '@components/StrategyLayout/StrategyLayout'\nimport useTrackSiteReload from '@hooks/useTrackSiteReload'\nimport { hideCrispChat, showCrispChat } from '@utils/crisp-chat'\nimport { TOS_UPDATE_DATE, LEGAL_PAGES } from '@constants/index'\nimport StrikeWarning from '@components/StrikeWarning'\nimport { getAddressStrikeCount } from '@state/wallet/apis'\nimport { addressStrikeCountAtom, isStrikeCountModalOpenAtom } from '@state/wallet/atoms'\n\ninitializeAmplitude()\n\nTimeAgo.addDefaultLocale(en)\nconst queryClient = new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false } } })\n\nfunction MyApp({ Component, pageProps }: any) {\n  useRenderCounter('9', '0')\n  const router = useRouter()\n  const { track } = useAmplitude()\n  const networkId = useAtomValue(networkIdAtom)\n  const client = useMemo(() => uniswapClient[networkId] || uniswapClient[1], [networkId])\n\n  React.useEffect(() => {\n    // Remove the server-side injected CSS.\n    const jssStyles = document.querySelector('#jss-server-side')\n    if (jssStyles) {\n      jssStyles.parentElement!.removeChild(jssStyles)\n    }\n  }, [])\n\n  const siteID = process.env.NEXT_PUBLIC_FATHOM_CODE ? process.env.NEXT_PUBLIC_FATHOM_CODE : ''\n\n  useEffect(() => {\n    // Initialize Fathom when the app loads\n    // Example: yourdomain.com\n    //  - Do not include https://\n    //  - This must be an exact match of your domain.\n    //  - If you're using www. for your domain, make sure you include that here.\n    Fathom.load(siteID, {\n      includedDomains: ['opyn.co', 'www.opyn.co'],\n    })\n\n    function onRouteChangeComplete() {\n      Fathom.trackPageview()\n    }\n    // Record a pageview when route changes\n    router.events.on('routeChangeComplete', onRouteChangeComplete)\n\n    // Unassign event listener\n    return () => {\n      router.events.off('routeChangeComplete', onRouteChangeComplete)\n    }\n  }, [router.events, siteID])\n\n  useEffect(() => {\n    function onRouteChangeComplete(url: string) {\n      const e: string = url.split('?')[0].substring(1).toUpperCase()\n      track('NAV_' + e)\n    }\n    router.events.on('routeChangeComplete', onRouteChangeComplete)\n\n    return () => {\n      router.events.off('routeChangeComplete', onRouteChangeComplete)\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [track])\n\n  useEffect(() => {\n    Crisp.configure(process.env.NEXT_PUBLIC_CRISP_WEBSITE_ID as string)\n  }, [])\n\n  useEffect(() => {\n    if (router.pathname !== '/') {\n      showCrispChat()\n    } else hideCrispChat()\n  }, [router])\n\n  return (\n    <RestrictUserProvider>\n      <QueryClientProvider client={queryClient}>\n        <ApolloProvider client={client}>\n          <TradeApp Component={Component} pageProps={pageProps} />\n        </ApolloProvider>\n        <ReactQueryDevtools initialIsOpen={false} />\n      </QueryClientProvider>\n    </RestrictUserProvider>\n  )\n}\n\nconst Init = () => {\n  const onboardAddress = useAtomValue(onboardAddressAtom)\n  const setWalletFailVisible = useUpdateAtom(walletFailVisibleAtom)\n  const setAddressStrikeCount = useUpdateAtom(addressStrikeCountAtom)\n  const setIsStrikeCountModalOpen = useUpdateAtom(isStrikeCountModalOpenAtom)\n\n  const firstAddressCheck = useRef(true)\n  const router = useRouter()\n  const connectWallet = useConnectWallet()\n\n  const { isRestricted, blockUser } = useRestrictUser()\n\n  const isZenbullPage = router.pathname === '/strategies/bull'\n\n  useAppEffect(() => {\n    if (!onboardAddress) {\n      return\n    }\n\n    checkIsValidAddress(onboardAddress).then((valid) => {\n      if (valid) {\n        const hasConnectedAfterTosUpdate = window.localStorage.getItem(TOS_UPDATE_DATE) === 'true'\n        if (!hasConnectedAfterTosUpdate) {\n          return\n        } else if (isZenbullPage) {\n          // connect automatically (to zenbull) only if user has specifically connected to zenbull page\n          const hasConnectedToZenbullBefore = window.localStorage.getItem('walletConnectedToZenbull') === 'true'\n          if (hasConnectedToZenbullBefore) {\n            connectWallet(onboardAddress)\n          }\n        } else {\n          connectWallet(onboardAddress)\n        }\n      } else {\n        if (firstAddressCheck.current) {\n          firstAddressCheck.current = false\n        } else {\n          setWalletFailVisible(true)\n        }\n      }\n    })\n  }, [onboardAddress, setWalletFailVisible, isZenbullPage, connectWallet])\n\n  // Check if the current page is exempt from restriction (e.g., legal pages)\n  const isLegalPage = LEGAL_PAGES.includes(router.pathname)\n\n  // increment strike count if user is restricted\n  useEffect(() => {\n    if (!isRestricted || !onboardAddress) {\n      return\n    }\n\n    if (isRestricted && !isLegalPage) {\n      // increment strike count\n      updateBlockedAddress(onboardAddress).then((visitCount) => {\n        setAddressStrikeCount(visitCount)\n\n        if (visitCount >= 3) {\n          blockUser()\n        }\n\n        // show strike count modal after updating strike count\n        setIsStrikeCountModalOpen(true)\n      })\n    }\n  }, [isRestricted, onboardAddress, setAddressStrikeCount, blockUser, setIsStrikeCountModalOpen, isLegalPage])\n\n  // update user's strike count and block user if strike count >= 3\n  useEffect(() => {\n    if (!onboardAddress) {\n      return\n    }\n\n    getAddressStrikeCount(onboardAddress).then((visitCount) => {\n      setAddressStrikeCount(visitCount)\n\n      if (visitCount >= 3) {\n        blockUser()\n      }\n    })\n  }, [blockUser, onboardAddress, setAddressStrikeCount])\n\n  useOnboard()\n  useTrackSiteReload()\n  useUpdateSqueethPrices()\n  useUpdateSqueethPoolData()\n  useInitController()\n  useSwaps()\n  return null\n}\nconst MemoizedInit = memo(Init)\n\nconst TradeApp = ({ Component, pageProps }: any) => {\n  return (\n    <React.Fragment>\n      <Head>\n        <meta name=\"viewport\" content=\"minimum-scale=1, initial-scale=1, width=device-width\" />\n      </Head>\n\n      <MemoizedInit />\n      <ThemeProvider theme={getTheme(Mode.NEW_DARK)}>\n        {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}\n        <CssBaseline />\n        <ComputeSwapsProvider>\n          <WalletFailModal />\n          <StrikeWarning />\n          <StrategyLayout>\n            <Component {...pageProps} />\n          </StrategyLayout>\n        </ComputeSwapsProvider>\n      </ThemeProvider>\n    </React.Fragment>\n  )\n}\n\nexport default MyApp\n"
  },
  {
    "path": "packages/frontend/pages/_document.tsx",
    "content": "import { ServerStyleSheets } from '@material-ui/core/styles'\nimport Document, { Head, Html, Main, NextScript } from 'next/document'\nimport React from 'react'\n\nexport default class MyDocument extends Document {\n  render() {\n    return (\n      <Html lang=\"en\">\n        <Head>\n          <link rel=\"icon\" href=\"/favicon.ico\" />\n\n          {/*  preload fonts */}\n          <link\n            href=\"https://fonts.googleapis.com/css2?family=Open+Sans:wght@100;300;400;500;700&display=swap\"\n            rel=\"stylesheet\"\n          />\n          <link\n            href=\"https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=DM+Mono:wght@300;400;500&display=swap\"\n            rel=\"stylesheet\"\n          />\n          <link href=\"https://fonts.cdnfonts.com/css/avenir\" rel=\"stylesheet\" />\n        </Head>\n        <body>\n          <Main />\n          <NextScript />\n          <div id=\"rain\"></div>\n          <div id=\"popup\"></div>\n          <div id=\"background-radial-gradient\"></div>\n        </body>\n      </Html>\n    )\n  }\n}\n\n// `getInitialProps` belongs to `_document` (instead of `_app`),\n// it's compatible with server-side generation (SSG).\nMyDocument.getInitialProps = async (ctx) => {\n  // Render app and page and get the context of the page with collected side effects.\n  const sheets = new ServerStyleSheets()\n  const originalRenderPage = ctx.renderPage\n\n  ctx.renderPage = () =>\n    originalRenderPage({\n      enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),\n    })\n\n  const initialProps = await Document.getInitialProps(ctx)\n\n  return {\n    ...initialProps,\n    // Styles fragment is rendered after the app and page rendering finish.\n    styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],\n  }\n}\n"
  },
  {
    "path": "packages/frontend/pages/api/__tests__/isValidAddress.test.ts",
    "content": "/**\n * @jest-environment node\n */\n import { createMocks, RequestMethod, createRequest, createResponse } from 'node-mocks-http';\n import type { NextApiResponse } from 'next';\n import requestHandler from '../../../pages/api/isValidAddress';\n import axios from 'axios';\n \n jest.mock(\"axios\");\n const mockedAxios = axios as jest.Mocked<typeof axios>;\n\n type APIRequest = NextApiResponse & ReturnType<typeof createRequest>;\n type APIResponse = NextApiResponse & ReturnType<typeof createResponse>;\n\n export interface isValidAddressResponse {\n    valid: boolean,\n    madeThirdPartyConnection: boolean\n  }\n\n describe('/api/isValidAddress/[address] API Endpoint', () => {\n\n   const safeAddress = '0xa3cb04d8bd927eec8826bd77b7c71abe3d29c081'\n   const highRiskAddress = '0x098B716B8Aaf21512996dC57EB0615e2383E2f96'\n   const invalidAddress = 'jksd'\n   \n   function mockRequestResponse(method: RequestMethod = 'GET', address: string) {\n     const {\n       req,\n       res,\n     }: { req: APIRequest; res: APIResponse } = createMocks({ method });\n     req.query = { address: address };\n     return { req, res };\n   }\n\n   it('should return TRUE for a safe address supplied', async () => {\n    const { req, res } = mockRequestResponse('GET',safeAddress);\n\n    mockedAxios.post.mockResolvedValue({\n        data: [\n            {\n                \"asset\": \"ETH\",\n                \"address\": \"0xa3cb04d8bd927eec8826bd77b7c71abe3d29c081\",\n                \"cluster\": null,\n                \"rating\": \"unknown\",\n                \"customAddress\": null,\n                \"chainalysisIdentification\": null\n            }\n        ],\n      });\n\n    await requestHandler(req, res);\n\n    const responseData = res._getJSONData() as isValidAddressResponse\n\n    expect(responseData.valid).toEqual(true);\n    expect(responseData.madeThirdPartyConnection).toEqual(true);\n   });\n\n   it('should return FALSE for a risky address supplied', async () => {\n     const { req, res } = mockRequestResponse('GET',highRiskAddress);\n\n     mockedAxios.post.mockResolvedValue({\n        data: [\n            {\n                \"asset\": \"ETH\",\n                \"address\": \"0x098B716B8Aaf21512996dC57EB0615e2383E2f96\",\n                \"cluster\": {\n                    \"name\": \"OFAC SDN Lazarus Group 2022-04-14\",\n                    \"category\": \"sanctions\"\n                },\n                \"rating\": \"highRisk\",\n                \"customAddress\": null,\n                \"chainalysisIdentification\": {\n                    \"addressName\": \"Some info\",\n                    \"description\": \"Some info\",\n                    \"categoryName\": \"Some info\"\n                }\n            }\n        ],\n      });\n     \n     await requestHandler(req, res);\n \n     const responseData = res._getJSONData() as isValidAddressResponse\n     expect(responseData.valid).toEqual(false);\n     expect(responseData.madeThirdPartyConnection).toEqual(true);\n   });\n\n   it('should return TRUE if response body does not match what we expect', async () => {\n    const { req, res } = mockRequestResponse('GET',highRiskAddress);\n\n    mockedAxios.post.mockResolvedValue({\n       data: null,\n     });\n    \n    await requestHandler(req, res);\n\n    const responseData = res._getJSONData() as isValidAddressResponse\n    expect(responseData.valid).toEqual(true);\n    expect(responseData.madeThirdPartyConnection).toEqual(true);\n  });\n\n\n   it('should return TRUE for all errors encountered when querying third-party service', async () => {\n\n    const { req, res } = mockRequestResponse('GET',invalidAddress);\n   \n    mockedAxios.post.mockRejectedValue(new Error('💣'))\n    \n    await requestHandler(req, res);\n\n    const responseData = res._getJSONData() as isValidAddressResponse\n    expect(responseData.valid).toEqual(true);\n    expect(responseData.madeThirdPartyConnection).toEqual(false);\n  });\n\n });"
  },
  {
    "path": "packages/frontend/pages/api/auction/lastHedgeAuction.ts",
    "content": "import axios from 'axios'\nimport type { NextApiRequest, NextApiResponse } from 'next'\n\nconst SQUEETH_PORTAL_API = process.env.NEXT_PUBLIC_SQUEETH_PORTAL_BASE_URL\n\nconst handleRequest = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (!SQUEETH_PORTAL_API) {\n    res.status(400).json({ status: 'error', message: 'Error fetching information' })\n    return\n  }\n\n  const jsonResponse = await axios.get(`${SQUEETH_PORTAL_API}/api/auction/getLastHedge?type=${req.query.type}`)\n  res.status(200).json(jsonResponse.data)\n}\n\nexport default handleRequest\n"
  },
  {
    "path": "packages/frontend/pages/api/charts/longchart.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next'\nimport { getCoingeckoETHPricesBetweenTimestamps as getETHPricesBetweenTs } from '@utils/ethPriceCharts'\nimport { getLiveVolMap, getSqueethChartWithFunding, getVolForTimestampOrDefault, getVolMap } from '@utils/pricer'\n\nexport default async function handler(req: NextApiRequest, res: NextApiResponse) {\n  const collatRatio = Number(req.query.collatRatio)\n  const fromTs = Number(req.query.fromTs)\n  const toTs = Number(req.query.toTs)\n  const volMultiplier = Number(req.query.volMultiplier)\n  const oneDay = 24 * 60 * 60 * 1000\n  const days = (toTs - fromTs) / oneDay\n\n  try {\n    const ethPrices = await getETHPricesBetweenTs(fromTs, toTs)\n\n    const ethSqueethPNLSeriesPromise = getETHSqueethPNLCompounding(ethPrices, volMultiplier, days)\n    const squeethSeriesPromise = getSqueethChartWithFunding(ethPrices, volMultiplier, collatRatio)\n\n    const [ethSqueethPNLSeries, squeethSeries] = await Promise.all([ethSqueethPNLSeriesPromise, squeethSeriesPromise])\n    const longEthPNL = ethSqueethPNLSeries.ethPNL.map(({ time, longPNL }) => {\n      return { time, value: longPNL }\n    })\n    const longSeries = ethSqueethPNLSeries.squeethPNL.map(({ time, longPNL }) => {\n      return { time, value: longPNL }\n    })\n    const squeethIsLive = ethSqueethPNLSeries.squeethPNL.map(({ isLive }) => {\n      return isLive\n    })\n    const positionSizeSeries = squeethSeries.series.map(({ time, positionSize }) => {\n      return { time, value: positionSize * 100 }\n    })\n\n    const response = { longEthPNL, longSeries, positionSizeSeries, squeethIsLive }\n\n    res.status(200).send(response)\n  } catch (error: any) {\n    console.log({ error: error.message })\n    res.status(400).json({ error: 'There was an error fetching the data' })\n  }\n}\n\nasync function getETHSqueethPNLCompounding(\n  ethPrices: { time: number; value: number }[],\n  volMultiplier = 1.2,\n  days = 365,\n) {\n  const timestamps = ethPrices.map(({ time }) => time)\n\n  let cumulativeSqueethLongReturn = 0\n  let cumulativeSqueethCrabReturn = 1\n  const volsMap = await getVolMap()\n  const liveVolsMap = await getLiveVolMap()\n\n  const annualVolData = await Promise.all(\n    timestamps.map(async (timestamp, index) => {\n      const { value: price, time } = ethPrices[index > 0 ? index : 0]\n      const utcDate = new Date(timestamp * 1000).toISOString().split('T')[0]\n      let annualVol = liveVolsMap[utcDate]\n      let isLive = true\n      if (!annualVol) {\n        annualVol = await getVolForTimestampOrDefault(volsMap, time, price)\n        isLive = false\n      }\n\n      return { annualVol, isLive }\n    }),\n  )\n\n  let cumulativeEthLongShortReturn = 0\n\n  const ethChartData = ethPrices.map((ethItem, index) => {\n    const { value: price, time } = ethItem\n    const preEthPrice = ethPrices[index > 0 ? index - 1 : 0].value\n    cumulativeEthLongShortReturn += Math.log(price / preEthPrice)\n\n    const longPNL = Math.round((Math.exp(cumulativeEthLongShortReturn) - 1) * 10000) / 100\n    const shortPNL = Math.round((Math.exp(-cumulativeEthLongShortReturn) - 1) * 10000) / 100\n    return { shortPNL, longPNL, time }\n  })\n\n  const squeethChartData = annualVolData.map((item, index) => {\n    const { annualVol, isLive } = item\n    const { value: price, time } = ethPrices[index > 0 ? index : 0]\n\n    const fundingPeriodMultiplier = days > 90 ? 365 : days > 1 ? 365 * 24 : 356 * 24 * 12\n\n    let vol = annualVol * volMultiplier\n    const preEthPrice = ethPrices[index > 0 ? index - 1 : 0].value\n    let fundingCost = index === 0 ? 0 : (vol / Math.sqrt(fundingPeriodMultiplier)) ** 2\n    cumulativeSqueethLongReturn += 2 * Math.log(price / preEthPrice) + Math.log(price / preEthPrice) ** 2 - fundingCost\n    // crab return\n    const crabVolMultiplier = 0.9\n    vol = annualVol * crabVolMultiplier\n    fundingCost = index === 0 ? 0 : (vol / Math.sqrt(fundingPeriodMultiplier)) ** 2\n    const simR = price / preEthPrice - 1\n    cumulativeSqueethCrabReturn *= 1 + -(simR ** 2) + fundingCost\n    const longPNL = Math.round((Math.exp(cumulativeSqueethLongReturn) - 1) * 10000) / 100\n    const shortPNL = Math.round(Math.log(cumulativeSqueethCrabReturn) * 10000) / 100\n\n    return { shortPNL, longPNL, time, isLive }\n  })\n\n  return { ethPNL: ethChartData, squeethPNL: squeethChartData }\n}\n"
  },
  {
    "path": "packages/frontend/pages/api/currentsqueethvol.ts",
    "content": "import axios from 'axios'\nimport type { NextApiRequest, NextApiResponse } from 'next'\n\nconst SQUEETH_VOL_API = process.env.SQUEETH_VOL_API_BASE_URL\n\nconst handleRequest = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (!SQUEETH_VOL_API) {\n    res.status(400).json({ status: 'error', message: 'Error fetching information' })\n    return\n  }\n\n  const jsonResponse = await axios.get(`${SQUEETH_VOL_API}/get_squeeth_iv`)\n  res.status(200).json(jsonResponse.data['squeethVol'])\n}\n\nexport default handleRequest\n"
  },
  {
    "path": "packages/frontend/pages/api/historicalprice.ts",
    "content": "import { format } from 'date-fns'\nimport type { NextApiRequest, NextApiResponse } from 'next'\n\nconst TWELVE_DATA_API = 'https://api.twelvedata.com'\n\n/**\n * Get Historical price using https://twelvedata.com/docs#complex-data complex data API\n */\nconst handleRequest = async (req: NextApiRequest, res: NextApiResponse) => {\n  const { timestamps, interval, pair, tz } = req.query\n\n  if (timestamps instanceof Array) {\n    res.status(400).json({ status: 'error', message: 'Array params is not supported' })\n    return\n  }\n  if (!interval) {\n    res.status(400).json({ status: 'error', message: 'Interval param is required' })\n    return\n  }\n\n  const timestampArr = timestamps?.split(',') ?? []\n  const methods = generateMethodData(timestampArr, interval)\n\n  const resp = await fetch(`${TWELVE_DATA_API}/complex_data?apikey=${process.env.NEXT_PUBLIC_TWELVEDATA_APIKEY}`, {\n    method: 'POST',\n    body: JSON.stringify({\n      symbols: [pair],\n      timezone: tz,\n      intervals: [interval],\n      outputsize: 1,\n      methods,\n    }),\n  })\n\n  const respJson = await resp.json()\n  // return res.status(200).json(respJson)\n\n  const [current, ...rest] = respJson.data as Array<any>\n\n  // complex_data API returns current price, historical price for each timestamp\n  // So rest value will be in the format [1st historical price, current price, 2nd historical price, current price, ...]\n  // So filtering historical price\n  const priceData = rest.filter((_, index) => index % 2 === 0)\n\n  if (timestampArr.length !== priceData.length) {\n    res.status(400).json({ status: 'error', message: 'Timestamps size and price data length mis match' })\n    return\n  }\n\n  const resultJson = timestampArr.reduce((acc, timestamp, index) => {\n    const priceResp = priceData[index]\n    if (priceResp.status === 'error') {\n      acc[timestamp] = current.values[0].close\n    } else {\n      acc[timestamp] = priceResp.values[0].close\n    }\n    return acc\n  }, {} as { [key: string]: string })\n\n  res.status(200).json(resultJson)\n}\n\n// Generate method param from timestamps that's needed to sent to twelvedata API\nconst generateMethodData = (timestampArr: string[], interval: string | string[]) => {\n  const methods = []\n\n  for (const timestamp of timestampArr) {\n    const date = format(new Date(Number(timestamp)).setUTCSeconds(0, 0), 'yyyy-MM-dd HH:mm:ss')\n\n    const params = {\n      interval,\n      start_date: date,\n      end_date: date,\n      symbols: ['ETH/USD'],\n    }\n    methods.push('time_series', params)\n  }\n\n  return methods\n}\n\nexport default handleRequest\n"
  },
  {
    "path": "packages/frontend/pages/api/isValidAddress.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next'\nimport axios from 'axios'\nimport * as Sentry from '@sentry/nextjs'\n\nconst handleRequest = async (req: NextApiRequest, res: NextApiResponse) => {\n  const { address } = req.query\n  let isValidAddress = true\n\n  try {\n    const { data } = await axios.post(\n      `https://api.chainalysis.com/api/kyt/v1/users/${address}/withdrawaladdresses`,\n      [\n        {\n          network: 'Ethereum',\n          asset: 'ETH',\n          address,\n        },\n      ],\n      { headers: { Token: process.env.AML_API_KEY ?? '' } },\n    )\n   \n    if (data && data?.[0]?.rating)\n      isValidAddress = (data?.[0].rating === 'highRisk') ? false : true \n\n    res.status(200).json({ valid: isValidAddress, madeThirdPartyConnection: true })\n\n  } catch (error) {\n    // catches all reponses not 2XX from source\n    if (error instanceof Error) {\n      Sentry.captureMessage(`AML Check: Error occured when checking for address:${address}. Error: ${error.message} `)\n    } else {\n      Sentry.captureMessage(`AML Check: Error occured when checking for address:${address}. Error: ${JSON.stringify(error)}`)\n    }\n\n    res.status(200).json({ valid: true, madeThirdPartyConnection: false })\n  }\n}\n\nexport default handleRequest\n"
  },
  {
    "path": "packages/frontend/pages/api/pnl.tsx",
    "content": "/* eslint-disable @next/next/no-img-element */\nimport { ImageResponse } from '@vercel/og'\nimport { NextRequest } from 'next/server'\nimport React from 'react'\nimport { Duration, isFuture, intervalToDuration, format, isBefore } from 'date-fns'\n\nimport { SQUEETH_BASE_URL, CRABV2_START_DATE, BULL_START_DATE } from '@constants/index'\n\nconst OMDB_BASE_URL = process.env.NEXT_PUBLIC_OMDB_BASE_URL as string\n\nexport const config = {\n  runtime: 'experimental-edge',\n}\n\nconst formatDuration = (duration: Duration) => {\n  const { years, months, days, hours } = duration\n  const formattedDuration = []\n\n  if (years) {\n    formattedDuration.push(`${years}y`)\n  }\n  if (months) {\n    formattedDuration.push(`${months}m`)\n  }\n  if (days) {\n    formattedDuration.push(`${days}d`)\n  }\n  if (hours) {\n    formattedDuration.push(`${hours}h`)\n  }\n\n  return formattedDuration.join(' ')\n}\n\nconst CHART_WIDTH = 1000\nconst CHART_HEIGHT = 280\n\nconst X_AXIS_WIDTH = 5\nconst Y_AXIS_WIDTH = 5\n\nconst PADDING_X = 3\nconst PADDING_Y = 36\n\ntype StrategyType = 'crab' | 'zenbull'\ntype PnLDataPoint = [number, number]\ninterface UserPnlProps {\n  strategy: StrategyType\n  depositTimestamp: number\n  pnl: number\n  pnlData: PnLDataPoint[]\n}\n\nconst UserPnl: React.FC<UserPnlProps> = ({ strategy, depositTimestamp, pnl, pnlData }) => {\n  const date = new Date(depositTimestamp * 1000)\n  const strategyDuration = intervalToDuration({ start: new Date(), end: date })\n  const formattedDuration = formatDuration(strategyDuration)\n\n  const pnlColor = pnl >= 0 ? '#67fabf' : '#FA7B67'\n\n  const xMax = Math.max(...pnlData.map(([x]) => x))\n  const xMin = Math.min(...pnlData.map(([x]) => x))\n  const yMax = Math.max(...pnlData.map(([, y]) => y))\n  const yMin = Math.min(...pnlData.map(([, y]) => y))\n\n  const yRange = yMax - yMin\n  const xRange = xMax - xMin\n  const offsetX = xMin\n  const offsetY = yMin\n\n  const chartXPadding = Y_AXIS_WIDTH + PADDING_X\n  const chartYPadding = X_AXIS_WIDTH + PADDING_Y\n\n  const availableChartWidth = CHART_WIDTH - 2 * chartXPadding\n  const availableChartHeight = CHART_HEIGHT - 2 * chartYPadding\n\n  const points = pnlData\n    .map(([x, y]) => {\n      const pointX = chartXPadding + ((x - offsetX) / xRange) * availableChartWidth\n      const pointY = CHART_HEIGHT - chartYPadding - ((y - offsetY) / yRange) * availableChartHeight\n\n      return `${pointX},${pointY}`\n    })\n    .join(' ')\n\n  return (\n    <div\n      style={{\n        height: '100%',\n        width: '100%',\n        display: 'flex',\n        flexDirection: 'column',\n        backgroundColor: '#191B1C',\n        padding: '44px 100px',\n      }}\n    >\n      <div tw=\"flex items-center justify-between w-full\">\n        <div tw=\"flex items-center\">\n          <div tw=\"flex text-4xl\">\n            {strategy === 'crab' && (\n              <img src={`${SQUEETH_BASE_URL}/images/crab-logo.png`} alt=\"opyn crab logo\" height=\"32px\" />\n            )}\n            {strategy === 'zenbull' && (\n              <img src={`${SQUEETH_BASE_URL}/images/zenbull-logo.png`} alt=\"opyn zenbull logo\" height=\"32px\" />\n            )}\n          </div>\n          <div tw=\"flex text-4xl text-white font-bold ml-4\">\n            {strategy === 'crab' && 'Crabber - Stacking USDC'}\n            {strategy === 'zenbull' && 'Zen Bull - Stacking ETH'}\n          </div>\n        </div>\n        <div tw=\"flex text-2xl text-white text-opacity-60 ml-5\">\n          <img src={`${SQUEETH_BASE_URL}/images/logo.png`} alt=\"opyn logo\" height=\"68px\" />\n        </div>\n      </div>\n\n      <div tw=\"flex flex-col mt-6\">\n        <div tw=\"flex text-xl text-white font-bold\">\n          {strategy === 'crab' && 'My Crab Position'}\n          {strategy === 'zenbull' && 'My Zen Bull Position'}\n        </div>\n        <div tw=\"flex items-baseline mt-2\">\n          <div tw=\"flex text-4xl text-white font-bold\" style={{ color: pnlColor }}>\n            {pnl > 0 && '+'}\n            {pnl.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '%'}\n          </div>\n\n          <div tw=\"flex text-2xl text-white text-opacity-60 ml-4\">\n            {strategy === 'crab' && 'USD return'}\n            {strategy === 'zenbull' && 'ETH return'}\n          </div>\n        </div>\n      </div>\n\n      <div tw=\"flex mt-9\">\n        <div tw=\"flex absolute ml-5 text-white text-opacity-60 text-sm\">\n          {strategy === 'crab' && 'Crab Strategy'}\n          {strategy === 'zenbull' && 'Zen Bull Strategy'}\n        </div>\n\n        <svg viewBox={`0 0 ${CHART_WIDTH} ${CHART_HEIGHT}`}>\n          <defs>\n            <marker id=\"arrowhead\" markerWidth=\"10\" markerHeight=\"10\" refX=\"5\" refY=\"5\" orient=\"auto\">\n              <polygon points=\"0 0, 10 5, 0 10\" fill=\"#fff\" opacity=\"0.5\" />\n            </marker>\n          </defs>\n\n          <polyline fill=\"none\" stroke=\"#70E3F6\" strokeWidth=\"3\" points={points} />\n          <g>\n            <line\n              x1={Y_AXIS_WIDTH}\n              x2={CHART_WIDTH - Y_AXIS_WIDTH}\n              y1={CHART_HEIGHT - X_AXIS_WIDTH}\n              y2={CHART_HEIGHT - X_AXIS_WIDTH}\n              stroke=\"#fff\"\n              strokeOpacity=\"0.6\"\n              markerEnd=\"url(#arrowhead)\"\n              strokeDasharray=\"5,5\"\n            ></line>\n          </g>\n          <g>\n            {/* y-axis */}\n            <line\n              x1={Y_AXIS_WIDTH}\n              x2={Y_AXIS_WIDTH}\n              y1={CHART_HEIGHT - X_AXIS_WIDTH}\n              y2={X_AXIS_WIDTH}\n              stroke=\"#fff\"\n              strokeOpacity=\"0.6\"\n              markerEnd=\"url(#arrowhead)\"\n              strokeDasharray=\"5,5\"\n            ></line>\n          </g>\n        </svg>\n      </div>\n\n      <div tw=\"flex text-white text-opacity-60 mt-2\">\n        {format(date, 'MM/dd/yy')} (deposited {formattedDuration} ago)\n      </div>\n    </div>\n  )\n}\n\nconst font = fetch(new URL('../../public/fonts/DMSans-Regular.ttf', import.meta.url).toString()).then((res) =>\n  res.arrayBuffer(),\n)\nconst fontMedium = fetch(new URL('../../public/fonts/DMSans-Medium.ttf', import.meta.url).toString()).then((res) =>\n  res.arrayBuffer(),\n)\n\nconst fetchPnlData = async (strategy: StrategyType, startTimestamp: number, endTimestamp: number) => {\n  if (strategy === 'crab') {\n    const response = await fetch(\n      `${OMDB_BASE_URL}/metrics/crabv2?start_timestamp=${startTimestamp}&end_timestamp=${endTimestamp}`,\n    ).then((res) => res.json())\n\n    return response.data.map((x: Record<string, number>) => [x.timestamp * 1000, x.crabPnL * 100])\n  } else if (strategy === 'zenbull') {\n    const response = await fetch(`${OMDB_BASE_URL}/metrics/zenbull/pnl/${startTimestamp}/${endTimestamp}`).then((res) =>\n      res.json(),\n    )\n\n    return response.data.map((x: Record<string, number>) => [x.timestamp * 1000, x.bullEthPnl])\n  }\n\n  throw new Error('Invalid strategy')\n}\n\nexport default async function handler(req: NextRequest) {\n  try {\n    const [fontData, fontMediumData] = await Promise.all([font, fontMedium])\n\n    const { searchParams } = new URL(req.url)\n    const strategy = searchParams.get('strategy') as StrategyType\n    const depositedAt = searchParams.get('depositedAt')\n    const pnl = searchParams.get('pnl')\n\n    if (!strategy || !depositedAt || !pnl) {\n      return new Response(`Missing \"strategy\", \"depositedAt\" or \"pnl\" query param`, {\n        status: 400,\n      })\n    }\n\n    const depositDate = new Date(Number(depositedAt) * 1000)\n    if (isFuture(depositDate)) {\n      return new Response(`Deposit date is in future`, {\n        status: 400,\n      })\n    }\n\n    const crabV2LaunchDate = new Date(CRABV2_START_DATE)\n    const zenBullLaunchDate = new Date(BULL_START_DATE)\n\n    let startDate = depositDate\n    if (strategy === 'crab' && isBefore(depositDate, crabV2LaunchDate)) {\n      startDate = crabV2LaunchDate\n    } else if (strategy === 'zenbull' && isBefore(depositDate, zenBullLaunchDate)) {\n      startDate = zenBullLaunchDate\n    }\n\n    const startTimestamp = startDate.getTime() / 1000\n    const endTimestamp = Math.round(new Date().getTime() / 1000)\n    const pnlData = await fetchPnlData(strategy, startTimestamp, endTimestamp)\n\n    return new ImageResponse(\n      <UserPnl strategy={strategy} depositTimestamp={startTimestamp} pnl={Number(pnl)} pnlData={pnlData} />,\n      {\n        width: 1200,\n        height: 630,\n        fonts: [\n          {\n            name: 'DMSans',\n            data: fontData,\n            style: 'normal',\n            weight: 400,\n          },\n          {\n            name: 'DMSans',\n            data: fontMediumData,\n            style: 'normal',\n            weight: 500,\n          },\n        ],\n      },\n    )\n  } catch (e: any) {\n    console.log(`${e.message}`)\n    return new Response(`Failed to generate the image`, {\n      status: 500,\n    })\n  }\n}\n"
  },
  {
    "path": "packages/frontend/pages/api/strikes.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next'\nimport { getAddressStrikeCount } from 'src/server/firebase-admin'\n\nconst handleRequest = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== 'GET') {\n    return res.status(400).json({ message: 'Only GET is allowed' })\n  }\n\n  const { address } = req.query\n\n  try {\n    const count = await getAddressStrikeCount(address as string)\n    return res.status(200).json({ count })\n  } catch (error) {\n    console.error(error)\n    return res.status(500).json({ message: error })\n  }\n}\n\nexport default handleRequest\n"
  },
  {
    "path": "packages/frontend/pages/api/tvl.ts",
    "content": "import axios from 'axios'\nimport type { NextApiRequest, NextApiResponse } from 'next'\n\nconst handleRequest = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method === 'GET') {\n    try {\n      const response = await axios.get(`${process.env.DEFILLAMA_ENDPOINT}/tvl/opyn`)\n      res.status(200).json(response.data)\n    } catch (error) {\n      res.status(500).json({ error: 'Error fetching data from Defillama' })\n    }\n  } else {\n    // Handle any other HTTP method\n    res.setHeader('Allow', ['GET'])\n    res.status(405).end(`Method ${req.method} Not Allowed`)\n  }\n}\n\nexport default handleRequest\n"
  },
  {
    "path": "packages/frontend/pages/api/twelvedata.ts",
    "content": "import axios from 'axios'\nimport type { NextApiRequest, NextApiResponse } from 'next'\n\nconst TWELVE_DATA_API = 'https://api.twelvedata.com'\n\nconst handleRequest = async (req: NextApiRequest, res: NextApiResponse) => {\n  const { path } = req.query\n  const queryString = Object.keys(req.query).reduce((acc, key) => {\n    if (key !== 'path') acc += `${key}=${req.query[key]}&`\n    return acc\n  }, '')\n\n  if (!path) {\n    res.status(400).json({ status: 'error', message: 'Path parameter is missing' })\n    return\n  }\n\n  const jsonResponse = await axios.get(\n    `${TWELVE_DATA_API}/${path}?${queryString}&apikey=${process.env.NEXT_PUBLIC_TWELVEDATA_APIKEY}`,\n  )\n\n  res.status(200).json(jsonResponse.data)\n}\n\nexport default handleRequest\n"
  },
  {
    "path": "packages/frontend/pages/api/updateBlockedAddress.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next'\nimport { updateBlockedAddress } from 'src/server/firebase-admin'\n\nconst handleRequest = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== 'POST') return res.status(400).json({ message: 'Only post is allowed' })\n\n  const { address } = req.body\n\n  try {\n    const visitCount = await updateBlockedAddress(address)\n    return res.status(200).json({ message: 'success', visitCount })\n  } catch (error) {\n    console.error(error)\n    return res.status(500).json({ message: error })\n  }\n}\n\nexport default handleRequest\n"
  },
  {
    "path": "packages/frontend/pages/blocked.tsx",
    "content": "import React from 'react'\nimport { Box, Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      width: '50%',\n      justifyContent: 'center',\n      display: 'flex',\n      alignItems: 'center',\n      margin: 'auto',\n      marginTop: theme.spacing(10),\n    },\n    title: {\n      marginTop: theme.spacing(10),\n    },\n  }),\n)\n\nconst BlockedPage: React.FC = () => {\n  const classes = useStyles()\n\n  return (\n    <Box className={classes.container}>\n      <Typography align=\"center\" variant=\"h6\" className={classes.title}>\n        Seems you are using a VPN service or accessing our website from a blocked country, which is a violation of our terms of service. Please disconnect from your VPN\n        and refresh the page to continue using our service.\n      </Typography>\n    </Box>\n  )\n}\n\nexport default BlockedPage\n"
  },
  {
    "path": "packages/frontend/pages/index.tsx",
    "content": "import React, { useEffect } from 'react'\nimport Hidden from '@material-ui/core/Hidden'\nimport DesktopLandingPage from '@components/LandingPage/DesktopLandingPage'\nimport MobileLandingPage from '@components/LandingPage/MobileLandingPage'\nimport DefaultSiteSeo from '@components/DefaultSiteSeo/DefaultSiteSeo'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { LANDING_EVENTS } from '@utils/amplitude'\n\nfunction LandingPage() {\n  const { track } = useAmplitude()\n\n  useEffect(() => {\n    track(LANDING_EVENTS.LANDING_VISIT)\n  }, [track])\n\n  return (\n    <div>\n      <DefaultSiteSeo />\n      <Hidden smDown>\n        <DesktopLandingPage />\n      </Hidden>\n      <Hidden mdUp>\n        <MobileLandingPage />\n      </Hidden>\n    </div>\n  )\n}\n\nexport default LandingPage\n"
  },
  {
    "path": "packages/frontend/pages/lp.tsx",
    "content": "import { createStyles, makeStyles } from '@material-ui/core'\nimport { Box, Typography } from '@material-ui/core'\nimport React, { useState } from 'react'\n\nimport ObtainSqueeth from '@components/Lp/ObtainSqueeth'\nimport SqueethInfo from '@components/Lp/SqueethInfo'\nimport LPPosition from '@components/Lp/LPPosition'\nimport LPBuyChart from '@components/Charts/LPBuyChart'\nimport LPMintChart from '@components/Charts/LPMintChart'\nimport Nav from '@components/Nav'\nimport { LPProvider } from '@context/lp'\nimport { SqueethTabNew, SqueethTabsNew } from '@components/Tabs'\nimport { useETHPrice } from '@hooks/useETHPrice'\nimport DefaultSiteSeo from '@components/DefaultSiteSeo/DefaultSiteSeo'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      maxWidth: '1280px',\n      width: '80%',\n      display: 'flex',\n      justifyContent: 'center',\n      gridGap: '96px',\n      flexWrap: 'wrap',\n      padding: theme.spacing(6, 5),\n      margin: '0 auto',\n      [theme.breakpoints.down('lg')]: {\n        maxWidth: 'none',\n        width: '90%',\n      },\n      [theme.breakpoints.down('md')]: {\n        width: '100%',\n        gridGap: '40px',\n      },\n      [theme.breakpoints.down('sm')]: {\n        padding: theme.spacing(3, 4),\n      },\n      [theme.breakpoints.down('xs')]: {\n        padding: theme.spacing(3, 3),\n      },\n    },\n    leftColumn: {\n      flex: 1,\n      minWidth: '480px',\n      [theme.breakpoints.down('xs')]: {\n        minWidth: '320px',\n      },\n    },\n    rightColumn: {\n      flexBasis: '452px',\n      [theme.breakpoints.down('xs')]: {\n        flex: '1',\n      },\n    },\n    title: {\n      fontSize: '28px',\n      fontWeight: 700,\n      letterSpacing: '-0.02em',\n    },\n    description: {\n      fontSize: '18px',\n      fontWeight: 400,\n      color: theme.palette.grey[400],\n    },\n    subtitle: {\n      fontSize: '22px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n    },\n    sectionTitle: {\n      marginTop: theme.spacing(3),\n      color: 'rgb(255, 255, 255)',\n      fontWeight: 500,\n      fontSize: '18px',\n      letterSpacing: '-0.01em',\n    },\n\n    details: {\n      marginTop: theme.spacing(4),\n    },\n    tradeSection: {\n      position: 'sticky',\n      top: '100px',\n      border: '1px solid #242728',\n      boxShadow: '0px 4px 40px rgba(0, 0, 0, 0.25)',\n      borderRadius: theme.spacing(0.7),\n      padding: '32px 24px',\n    },\n    chartNav: {\n      border: `1px solid ${theme.palette.primary.main}30`,\n    },\n    content: {\n      color: '#bdbdbd',\n      marginTop: '4px',\n    },\n  }),\n)\n\nconst LPInfo: React.FC<{ lpType: number }> = ({ lpType }) => {\n  const classes = useStyles()\n  const ethPrice = useETHPrice()\n\n  if (lpType === 0) {\n    return (\n      <>\n        <Typography variant=\"h4\" className={classes.subtitle}>\n          Buy squeeth and LP\n        </Typography>\n        <Typography variant=\"body1\" className={classes.content}>\n          Earn a payoff similar to ETH<sup>1.5</sup>\n        </Typography>\n        <Typography variant=\"subtitle1\" className={classes.sectionTitle}>\n          Strategy Overview\n        </Typography>\n        <Typography variant=\"body1\" className={classes.content}>\n          Buying and LPing gives you a leverage position with a payoff similar to ETH<sup>1.5</sup>. You give up some of\n          your squeeth upside in exchange for trading fees. You are paying daily premiums for being long squeeth, but\n          earning fees from LPing on Uniswap.\n        </Typography>\n        <Typography variant=\"subtitle1\" className={classes.sectionTitle}>\n          Payoff\n        </Typography>\n        <LPBuyChart ethPrice={ethPrice.toNumber()} />\n        <Typography variant=\"caption\" color=\"textSecondary\">\n          This payoff diagram does not include premiums or trading fees and assumes implied volatility stays constant.{' '}\n        </Typography>\n        <Typography variant=\"subtitle1\" className={classes.sectionTitle}>\n          Risks\n        </Typography>\n        <Typography variant=\"body1\" className={classes.content}>\n          You are exposed to squeeth premiums, so if you hold the position for a long period of time without upward\n          price movements in ETH, you can lose considerable funds to premium payments.\n        </Typography>\n        <br />\n        <Typography variant=\"body1\" className={classes.content}>\n          {' '}\n          Squeeth smart contracts have been audited by Trail of Bits, Akira, and Sherlock. However, smart contracts are\n          experimental technology and we encourage caution only risking funds you can afford to lose.\n        </Typography>\n      </>\n    )\n  }\n\n  return (\n    <>\n      <Typography variant=\"h4\" className={classes.subtitle}>\n        Mint squeeth and LP\n      </Typography>\n      <Typography variant=\"body1\" className={classes.content}>\n        Earn yield from trading fees while being long ETH\n      </Typography>\n      <Typography variant=\"subtitle1\" className={classes.sectionTitle}>\n        Strategy Overview\n      </Typography>\n      <Typography variant=\"body1\" className={classes.content}>\n        Minting and LPing is similar to a covered call. You start off with a position similar to 1x long ETH that gets\n        less long ETH as the price moves up and longer ETH as the price moves down.\n      </Typography>\n      <Typography variant=\"subtitle1\" className={classes.sectionTitle}>\n        Payoff\n      </Typography>\n      <LPMintChart ethPrice={ethPrice.toNumber()} />\n      <Typography variant=\"caption\" color=\"textSecondary\">\n        This payoff diagram does not included premiums or trading fees and assumes implied volatility stays constant.{' '}\n      </Typography>\n      <Typography variant=\"subtitle1\" className={classes.sectionTitle}>\n        Risks\n      </Typography>\n      <Typography variant=\"body1\" className={classes.content}>\n        You enter this position neutral to squeeth exposure, but could end up long squeeth exposed to premiums or short\n        squeeth depending on ETH price movements. If you fall below the minimum collateralization threshold (150%), you\n        are at risk of liquidation.\n      </Typography>\n      <br />\n      <Typography variant=\"body1\" className={classes.content}>\n        Squeeth smart contracts have been audited by Trail of Bits, Akira, and Sherlock. However, smart contracts are\n        experimental technology and we encourage caution only risking funds you can afford to lose.\n      </Typography>\n    </>\n  )\n}\n\nexport function LPCalculator() {\n  const classes = useStyles()\n  const [lpType, setLpType] = useState(0)\n\n  return (\n    <>\n      <Nav />\n\n      <div className={classes.container}>\n        <div className={classes.leftColumn}>\n          <>\n            <Typography variant=\"h3\" className={classes.title}>\n              Uniswap V3 LP SQTH-ETH Pool\n            </Typography>\n            <Typography variant=\"subtitle1\" className={classes.description}>\n              Earn LP fees for providing SQTH-ETH liquidity\n            </Typography>\n          </>\n\n          <Box marginTop=\"24px\">\n            <LPPosition />\n          </Box>\n\n          <div className={classes.details}>\n            <Box display=\"flex\">\n              <SqueethTabsNew\n                style={{ background: 'transparent' }}\n                className={classes.chartNav}\n                value={lpType}\n                onChange={(evt, val) => setLpType(val)}\n                aria-label=\"Sub nav tabs\"\n                scrollButtons=\"auto\"\n                variant=\"scrollable\"\n              >\n                <SqueethTabNew label=\"Buy and LP\" style={{ width: '140px' }} />\n                <SqueethTabNew label=\"Mint and LP\" style={{ width: '140px' }} />\n              </SqueethTabsNew>\n            </Box>\n\n            <Box marginTop=\"24px\">\n              <LPInfo lpType={lpType} />\n            </Box>\n          </div>\n\n          <Box marginTop=\"32px\">\n            <Typography variant=\"h4\" className={classes.subtitle}>\n              Details\n            </Typography>\n            <SqueethInfo marginTop=\"16px\" />\n          </Box>\n        </div>\n\n        <div className={classes.rightColumn}>\n          <div className={classes.tradeSection}>\n            <ObtainSqueeth />\n          </div>\n        </div>\n      </div>\n    </>\n  )\n}\n\nexport function LPage() {\n  return (\n    <>\n      <DefaultSiteSeo />\n      <LPProvider>\n        <LPCalculator />\n      </LPProvider>\n    </>\n  )\n}\n\nexport default LPage\n"
  },
  {
    "path": "packages/frontend/pages/mint.tsx",
    "content": "import React from 'react'\nimport { Box, Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\n\nimport MintSqueeth from '@components/Trade/Mint'\nimport Nav from '@components/Nav'\nimport DefaultSiteSeo from '@components/DefaultSiteSeo/DefaultSiteSeo'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(4, 0),\n    },\n    title: {\n      fontSize: '20px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n    },\n    getSqueethCard: {\n      width: '440px',\n      margin: 'auto',\n      padding: theme.spacing(2, 0),\n    },\n  }),\n)\n\nconst MintPage: React.FC = () => {\n  const classes = useStyles()\n\n  return (\n    <>\n      <DefaultSiteSeo />\n      <Nav />\n\n      <div className={classes.container}>\n        <Typography align=\"center\" variant=\"h6\" className={classes.title}>\n          Mint Squeeth\n        </Typography>\n\n        <Box className={classes.getSqueethCard}>\n          <MintSqueeth onMint={() => console.log('Minted')} showManageLink />\n        </Box>\n      </div>\n    </>\n  )\n}\n\nexport default MintPage\n"
  },
  {
    "path": "packages/frontend/pages/opt-out.tsx",
    "content": "import React, { useEffect, useState } from 'react'\nimport { Box, Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport { setOptOut } from '@amplitude/analytics-browser'\n\nimport { PrimaryButton } from '@components/Button'\nimport Nav from '@components/Nav'\nimport { isOptedOut } from '@utils/amplitude'\nimport DefaultSiteSeo from '@components/DefaultSiteSeo/DefaultSiteSeo'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(2),\n    },\n    title: {\n      marginTop: theme.spacing(10),\n    },\n    getSqueethCard: {\n      width: '300px',\n      overflow: 'auto',\n      margin: 'auto',\n      marginTop: theme.spacing(4),\n      padding: theme.spacing(2, 0),\n    },\n  }),\n)\n\nconst MintPage: React.FC = () => {\n  const classes = useStyles()\n  const [optOut, setOpt] = useState(false)\n\n  useEffect(() => {\n    isOptedOut().then(setOpt)\n  }, [])\n\n  const toggleOptOut = () => {\n    setOptOut(!optOut)\n    setOpt(!optOut)\n  }\n\n  return (\n    <>\n      <DefaultSiteSeo />\n      <Nav />\n      <Typography align=\"center\" variant=\"h6\" className={classes.title}>\n        {optOut ? 'You opted out from Amplitude tracking' : 'Opt out from Amplitude tracking'}\n      </Typography>\n      <Box className={classes.getSqueethCard}>\n        <PrimaryButton onClick={toggleOptOut}>{optOut ? 'Opt In' : 'Opt out'}</PrimaryButton>\n      </Box>\n    </>\n  )\n}\n\nexport default MintPage\n"
  },
  {
    "path": "packages/frontend/pages/pos-merge.tsx",
    "content": "import { getMarkdown } from '@utils/markdown'\nimport MarkdownPage from '@components/MarkdownPage'\nimport DefaultSiteSeo from '@components/DefaultSiteSeo/DefaultSiteSeo'\n\nconst PosMerge = (props: any) => {\n  return (\n    <>\n      <DefaultSiteSeo />\n      <MarkdownPage markdown={props.file} />\n    </>\n  )\n}\n\nexport async function getStaticProps() {\n  const file = getMarkdown('pos-merge')\n\n  return { props: { file } }\n}\n\nexport default PosMerge\n"
  },
  {
    "path": "packages/frontend/pages/positions.tsx",
    "content": "import { useAtomValue } from 'jotai'\n\nimport ConnectWallet from '@pages/positions/ConnectWallet'\nimport Positions from '@pages/positions/Positions'\nimport { useInitCrabMigration } from 'src/state/crabMigration/hooks'\nimport { addressAtom, supportedNetworkAtom } from 'src/state/wallet/atoms'\nimport DefaultSiteSeo from '@components/DefaultSiteSeo/DefaultSiteSeo'\n\nconst PositionsPage = () => {\n  const address = useAtomValue(addressAtom)\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n  useInitCrabMigration()\n\n  if (address && supportedNetwork) return <Positions />\n\n  return (\n    <>\n      <DefaultSiteSeo />\n      <ConnectWallet />\n    </>\n  )\n}\n\nexport default PositionsPage\n"
  },
  {
    "path": "packages/frontend/pages/privacy-policy.tsx",
    "content": "import ReactMarkdown from 'markdown-to-jsx'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport Box from '@material-ui/core/Box'\nimport Link from '@material-ui/core/Link'\nimport Typography from '@material-ui/core/Typography'\n\nimport Nav from '@components/Nav'\nimport { getMarkdown } from '@utils/markdown'\nimport DefaultSiteSeo from '@components/DefaultSiteSeo/DefaultSiteSeo'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      width: '90%',\n      margin: '7em auto 3em',\n      maxWidth: '900px',\n      paddingBottom: '1em',\n    },\n    subHeading: {\n      fontWeight: theme.typography.fontWeightBold,\n    },\n  }),\n)\n\nfunction MarkdownListItem(props: any) {\n  return <Box component=\"li\" sx={{ mt: 1, fontSize: 15 }} {...props} />\n}\n\nconst options = {\n  overrides: {\n    h1: {\n      component: Typography,\n      props: {\n        gutterBottom: true,\n        variant: 'h4',\n        component: 'h1',\n      },\n    },\n    h2: {\n      component: Typography,\n      props: { gutterBottom: true, component: 'h2' },\n    },\n    h3: {\n      component: Typography,\n      props: { gutterBottom: true, variant: 'h5', component: 'div' },\n    },\n    h4: {\n      component: Typography,\n      props: {\n        gutterBottom: true,\n        variant: 'h6',\n        paragraph: true,\n      },\n    },\n    h5: {\n      component: Typography,\n      props: {\n        gutterBottom: true,\n        // variant: 'h6',\n        paragraph: true,\n        fontSize: 10,\n        fontWeight: 600,\n      },\n    },\n    p: {\n      component: Typography,\n      props: { paragraph: true },\n    },\n    a: { component: Link },\n    li: {\n      component: MarkdownListItem,\n    },\n  },\n}\n\nconst PrivacyPolicy = (props: any) => {\n  const classes = useStyles()\n  return (\n    <>\n      <DefaultSiteSeo />\n      <Nav />\n      <main>\n        <div className={classes.container}>\n          <ReactMarkdown options={options}>{props.file}</ReactMarkdown>\n        </div>\n      </main>\n    </>\n  )\n}\n\nexport async function getStaticProps() {\n  const file = getMarkdown('privacy-policy')\n\n  return { props: { file } }\n}\n\nexport default PrivacyPolicy\n"
  },
  {
    "path": "packages/frontend/pages/share-pnl/[...slug].tsx",
    "content": "import { GetServerSideProps } from 'next'\nimport { NextSeo } from 'next-seo'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport { Typography, Button, useMediaQuery, useTheme } from '@material-ui/core'\nimport clsx from 'clsx'\nimport Image from 'next/image'\nimport isBefore from 'date-fns/isBefore'\n\nimport { SQUEETH_BASE_URL, BULL_START_DATE, CRABV2_START_DATE } from '@constants/index'\nimport Nav from '@components/Nav'\nimport { formatNumber } from '@utils/formatter'\n\nimport opynLogo from 'public/images/logo.png'\nimport crabLogo from 'public/images/crab-logo.png'\nimport zenBullLogo from 'public/images/zenbull-logo.png'\nimport PnlChart from '@components/SharePnl/PnlChart'\n\ntype StrategyType = 'crab' | 'zenbull'\n\ninterface SharePnlProps {\n  strategy: StrategyType\n  depositedAt: number\n  pnl: number\n}\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      maxWidth: '980px',\n      width: '80%',\n      padding: theme.spacing(6, 5),\n      margin: '0 auto',\n      [theme.breakpoints.down('lg')]: {\n        width: '90%',\n      },\n      [theme.breakpoints.down('md')]: {\n        width: '100%',\n      },\n      [theme.breakpoints.down('sm')]: {\n        padding: theme.spacing(3, 4),\n      },\n      [theme.breakpoints.down('xs')]: {\n        padding: theme.spacing(3, 3),\n      },\n    },\n    flex: {\n      display: 'flex',\n    },\n    alignCenter: {\n      alignItems: 'center',\n    },\n    alignBaseline: {\n      alignItems: 'baseline',\n    },\n    justifyBetween: {\n      justifyContent: 'space-between',\n    },\n    title: {\n      fontSize: '36px',\n      fontWeight: 500,\n      lineHeight: '130%',\n      letterSpacing: '-0.01em',\n      [theme.breakpoints.down('sm')]: {\n        fontSize: '28px',\n      },\n      [theme.breakpoints.down('xs')]: {\n        fontSize: '24px',\n      },\n    },\n    positionLabel: {\n      fontSize: '18px',\n      fontWeight: 700,\n      lineHeight: '130%',\n      [theme.breakpoints.down('sm')]: {\n        fontSize: '16px',\n      },\n    },\n    position: {\n      fontSize: '36px',\n      fontWeight: 500,\n      lineHeight: '130%',\n      letterSpacing: '-0.01em',\n      fontFamily: 'DM Mono',\n      [theme.breakpoints.down('sm')]: {\n        fontSize: '28px',\n      },\n    },\n    colorSuccess: {\n      color: theme.palette.success.main,\n    },\n    colorError: {\n      color: theme.palette.error.main,\n    },\n    positionUnit: {\n      fontSize: '20px',\n      fontWeight: 400,\n      lineHeight: '130%',\n      color: '#BABBBB',\n      [theme.breakpoints.down('sm')]: {\n        fontSize: '18px',\n      },\n    },\n    textMargin: {\n      marginLeft: theme.spacing(2),\n    },\n    sectionOutsetMargin: {\n      marginTop: theme.spacing(6),\n    },\n    sectionInsetMargin: {\n      marginTop: theme.spacing(1),\n    },\n    ctaButton: {\n      fontSize: '16px',\n      padding: theme.spacing(1, 3),\n    },\n  }),\n)\n\n// startDate can't be before the launch date of the strategy\nconst getStartTimestamp = (strategy: StrategyType, depositDate: Date) => {\n  const crabV2LaunchDate = new Date(CRABV2_START_DATE)\n  const zenBullLaunchDate = new Date(BULL_START_DATE)\n\n  let startDate = depositDate\n  if (strategy === 'crab' && isBefore(depositDate, crabV2LaunchDate)) {\n    startDate = crabV2LaunchDate\n  } else if (strategy === 'zenbull' && isBefore(depositDate, zenBullLaunchDate)) {\n    startDate = zenBullLaunchDate\n  }\n\n  return startDate.getTime() / 1000\n}\n\nconst UI = ({ strategy, depositedAt, pnl }: SharePnlProps) => {\n  const theme = useTheme()\n  const isMobileBreakpoint = useMediaQuery(theme.breakpoints.down('xs'))\n  const classes = useStyles()\n\n  const isCrab = strategy === 'crab'\n\n  return (\n    <>\n      <Nav />\n\n      <div className={classes.container}>\n        <div className={clsx(classes.flex, classes.justifyBetween, classes.alignCenter)}>\n          <div className={clsx(classes.flex, classes.alignCenter)}>\n            <Image src={isCrab ? crabLogo : zenBullLogo} alt=\"opyn crab logo\" height=\"32px\" width=\"32px\" />\n            <Typography variant=\"h2\" className={clsx(classes.title, classes.textMargin)}>\n              {isCrab ? 'Crabber - Stacking USDC' : 'Zen Bull - Stacking ETH'}\n            </Typography>\n          </div>\n          {!isMobileBreakpoint && <Image src={opynLogo} alt=\"opyn logo\" width=\"80px\" height=\"62px\" />}\n        </div>\n\n        <div className={classes.sectionOutsetMargin}>\n          <Typography className={classes.positionLabel}>\n            {isCrab ? 'My Crab Position' : 'My Zen Bull Position'}\n          </Typography>\n          <div className={clsx(classes.flex, classes.alignBaseline, classes.sectionInsetMargin)}>\n            <Typography className={clsx(classes.position, pnl >= 0 ? classes.colorSuccess : classes.colorError)}>\n              {pnl > 0 && '+'}\n              {formatNumber(pnl) + '%'}\n            </Typography>\n            <Typography className={clsx(classes.positionUnit, classes.textMargin)}>\n              {isCrab ? 'USD Return' : 'ETH Return'}\n            </Typography>\n          </div>\n        </div>\n\n        <div className={classes.sectionOutsetMargin}>\n          <PnlChart strategy={strategy} depositedAt={depositedAt} />\n        </div>\n\n        <div className={classes.sectionOutsetMargin}>\n          <Button\n            variant=\"outlined\"\n            color=\"primary\"\n            className={classes.ctaButton}\n            href={isCrab ? '/strategies/crab' : '/strategies/bull'}\n          >\n            Try {isCrab ? 'Crab' : 'Zen Bull'}\n          </Button>\n        </div>\n      </div>\n    </>\n  )\n}\n\nconst SharePnl = ({ strategy, depositedAt, pnl }: SharePnlProps) => {\n  const isCrab = strategy === 'crab'\n\n  const title = isCrab ? 'Opyn Crab Strategy - Stack USDC' : 'Opyn Zen Bull Strategy - Stack ETH'\n  const description = isCrab ? 'Stack USDC when ETH is flat' : 'Stack ETH when ETH increases slow and steady'\n  const ogImageUrl = SQUEETH_BASE_URL + '/api/pnl?strategy=' + strategy + '&depositedAt=' + depositedAt + '&pnl=' + pnl\n\n  const depositDate = new Date(depositedAt * 1000)\n  const startTimestamp = getStartTimestamp(strategy, depositDate)\n\n  return (\n    <>\n      <NextSeo\n        title={title}\n        description={description}\n        canonical={SQUEETH_BASE_URL}\n        openGraph={{\n          type: 'website',\n          images: [\n            {\n              url: ogImageUrl,\n              width: 1200,\n              height: 630,\n              alt: title,\n            },\n          ],\n        }}\n        twitter={{\n          handle: '@opyn_',\n          site: '@opyn_',\n          cardType: 'summary_large_image',\n        }}\n      />\n\n      <UI strategy={strategy} depositedAt={startTimestamp} pnl={pnl} />\n    </>\n  )\n}\n\nexport const getServerSideProps: GetServerSideProps = async (context) => {\n  const slug = (context.query.slug as string[]) || []\n\n  const strategy = slug[0] as StrategyType\n  const depositedAt = slug[1]\n  const pnl = slug[2]\n\n  return { props: { strategy, depositedAt: Number(depositedAt), pnl: Number(pnl) } }\n}\n\nexport default SharePnl\n"
  },
  {
    "path": "packages/frontend/pages/squeeth.tsx",
    "content": "import { useState } from 'react'\nimport { Typography, Box, Tooltip } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport { useAtomValue, useAtom } from 'jotai'\nimport { useResetAtom } from 'jotai/utils'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport clsx from 'clsx'\nimport { NextSeo } from 'next-seo'\n\nimport Nav from '@components/Nav'\nimport { WelcomeModal } from '@components/Trade/WelcomeModal'\nimport { ethTradeAmountAtom, sqthTradeAmountAtom, tradeTypeAtom } from '@state/trade/atoms'\nimport { isTransactionFirstStepAtom, transactionDataAtom, transactionLoadingAtom } from '@state/wallet/atoms'\nimport { LongChartPayoff } from '@components/Charts/LongChartPayoff'\nimport ShortFundingChart from '@components/Charts/ShortFundingChart'\nimport SqueethMetrics from '@components/Trade/SqueethMetrics'\nimport { SqueethTabNew, SqueethTabsNew } from '@components/Tabs'\nimport Trade from '@components/Trade'\nimport PositionCard from '@components/PositionCard'\nimport { TradeType } from 'src/types'\nimport { LinkWrapper } from '@components/LinkWrapper'\nimport { SQUEETH_BASE_URL } from '@constants/index'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      maxWidth: '1280px',\n      width: '80%',\n      display: 'flex',\n      justifyContent: 'center',\n      gridGap: '96px',\n      flexWrap: 'wrap',\n      padding: theme.spacing(6, 5),\n      margin: '0 auto',\n      [theme.breakpoints.down('lg')]: {\n        maxWidth: 'none',\n        width: '90%',\n      },\n      [theme.breakpoints.down('md')]: {\n        width: '100%',\n        gridGap: '40px',\n      },\n      [theme.breakpoints.down('sm')]: {\n        padding: theme.spacing(3, 4),\n      },\n      [theme.breakpoints.down('xs')]: {\n        padding: theme.spacing(3, 3),\n      },\n    },\n    leftColumn: {\n      flex: 1,\n      minWidth: '480px',\n      [theme.breakpoints.down('xs')]: {\n        minWidth: '320px',\n      },\n    },\n    rightColumn: {\n      flexBasis: '452px',\n      [theme.breakpoints.down('xs')]: {\n        flex: '1',\n      },\n    },\n    title: {\n      fontSize: '28px',\n      fontWeight: 700,\n      letterSpacing: '-0.02em',\n    },\n    tooltip: {\n      marginLeft: theme.spacing(0.5),\n    },\n    infoIcon: {\n      fontSize: '15px',\n    },\n    subtitle: {\n      fontSize: '20px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n    },\n    description: {\n      fontSize: '18px',\n      fontWeight: 400,\n      color: theme.palette.grey[400],\n    },\n    longIndicator: {\n      background: theme.palette.success.light,\n      borderRadius: theme.spacing(0.7),\n    },\n    shortIndicator: {\n      background: theme.palette.error.light,\n      borderRadius: theme.spacing(0.7),\n    },\n    longTab: {\n      color: theme.palette.success.main,\n    },\n    shortTab: {\n      color: theme.palette.error.main,\n    },\n    sectionMargin: {\n      marginTop: theme.spacing(4),\n    },\n    tradeSection: {\n      border: '1px solid #242728',\n      boxShadow: '0px 4px 40px rgba(0, 0, 0, 0.25)',\n      borderRadius: theme.spacing(1),\n      padding: '32px 24px',\n    },\n  }),\n)\n\nconst Header: React.FC = () => {\n  const classes = useStyles()\n  const tradeType = useAtomValue(tradeTypeAtom)\n\n  if (tradeType === TradeType.LONG) {\n    return (\n      <>\n        <Typography variant=\"h3\" className={classes.title}>\n          Long Squeeth: ETH&sup2; Leverage\n          <a\n            href=\"https://medium.com/opyn/squeeth-primer-a-guide-to-understanding-opyns-implementation-of-squeeth-a0f5e8b95684\"\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n          >\n            <Tooltip\n              className={classes.tooltip}\n              title={\n                <>\n                  {'Learn more about long squeeth '}\n                  <LinkWrapper href=\"https://medium.com/opyn/squeeth-primer-a-guide-to-understanding-opyns-implementation-of-squeeth-a0f5e8b95684\">\n                    here\n                  </LinkWrapper>\n                </>\n              }\n            >\n              <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n          </a>\n        </Typography>\n        <Typography variant=\"subtitle1\" className={classes.description}>\n          Perpetual leverage without liquidations\n        </Typography>\n      </>\n    )\n  } else {\n    return (\n      <>\n        <Typography variant=\"h3\" className={classes.title}>\n          Covered Short Squeeth: Short ETH&sup2; Position\n          <a\n            href=\"https://medium.com/opyn/squeeth-primer-a-guide-to-understanding-opyns-implementation-of-squeeth-a0f5e8b95684\"\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n          >\n            <Tooltip\n              className={classes.tooltip}\n              title={\n                <>\n                  {'Learn more about short squeeth '}\n                  <LinkWrapper href=\"https://medium.com/opyn/squeeth-primer-a-guide-to-understanding-opyns-implementation-of-squeeth-a0f5e8b95684\">\n                    here\n                  </LinkWrapper>\n                </>\n              }\n            >\n              <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n          </a>\n        </Typography>\n        <Typography variant=\"subtitle1\" className={classes.description}>\n          Earn premiums for selling ETH collateralized squeeth\n        </Typography>\n      </>\n    )\n  }\n}\n\nconst TabComponent: React.FC = () => {\n  const [tradeType, setTradeType] = useAtom(tradeTypeAtom)\n  const resetEthTradeAmount = useResetAtom(ethTradeAmountAtom)\n  const resetSqthTradeAmount = useResetAtom(sqthTradeAmountAtom)\n  const resetTransactionData = useResetAtom(transactionDataAtom)\n  const transactionInProgress = useAtomValue(transactionLoadingAtom)\n  const isTxFirstStep = useAtomValue(isTransactionFirstStepAtom)\n\n  const classes = useStyles()\n\n  return (\n    <div>\n      <SqueethTabsNew\n        value={tradeType}\n        onChange={(evt, val) => {\n          setTradeType(val)\n\n          if (!transactionInProgress || !isTxFirstStep) {\n            resetEthTradeAmount()\n            resetSqthTradeAmount()\n            resetTransactionData()\n          }\n        }}\n        aria-label=\"Sub nav tabs\"\n        centered\n        variant=\"fullWidth\"\n        classes={{ indicator: tradeType === TradeType.SHORT ? classes.shortIndicator : classes.longIndicator }}\n      >\n        <SqueethTabNew label=\"Redeem oSQTH\" id=\"long-card-btn\" classes={{ root: classes.longTab }} />\n        <SqueethTabNew label=\"Redeem Short Vault\" id=\"short-card-btn\" classes={{ root: classes.shortTab }} />\n      </SqueethTabsNew>\n    </div>\n  )\n}\n\nfunction TradePage() {\n  const classes = useStyles()\n  const [isWelcomeModalOpen, setWelcomeModalOpen] = useState(false)\n  const tradeType = useAtomValue(tradeTypeAtom)\n\n  const handleClose = () => setWelcomeModalOpen(false)\n\n  return (\n    <>\n      <NextSeo\n        title=\"Opyn Squeeth - Leverage without liquidations \"\n        description=\"Bet on ETH with unlimited upside, protected downside, and no liquidations.\"\n        canonical={SQUEETH_BASE_URL}\n        openGraph={{\n          images: [\n            {\n              url: SQUEETH_BASE_URL + '/images/previews/squeeth.png',\n              width: 1200,\n              height: 630,\n              alt: 'Squeeth',\n            },\n          ],\n        }}\n        twitter={{\n          handle: '@opyn_',\n          site: '@opyn_',\n          cardType: 'summary_large_image',\n        }}\n      />\n\n      <div>\n        <Nav />\n\n        <Box className={classes.container}>\n          <Box className={classes.leftColumn}>\n            <Header />\n\n            {/* <div className={classes.sectionMargin}>\n              {tradeType === TradeType.LONG ? <LongChartPayoff /> : <ShortFundingChart />}\n            </div> */}\n\n            {/* <Box marginTop=\"76px\">\n              <PositionCard />\n            </Box> */}\n\n            <Box marginTop=\"40px\">\n              <Typography variant=\"h4\" className={classes.subtitle}>\n                Details\n              </Typography>\n\n              <SqueethMetrics marginTop=\"16px\" />\n            </Box>\n          </Box>\n\n          <Box className={classes.rightColumn}>\n            <TabComponent />\n\n            <div className={clsx(classes.sectionMargin, classes.tradeSection)}>\n              {/* <Typography variant=\"h4\" className={classes.subtitle}>\n                Position\n              </Typography> */}\n\n              <Trade />\n            </div>\n          </Box>\n        </Box>\n      </div>\n\n      <WelcomeModal open={isWelcomeModalOpen} handleClose={handleClose} />\n    </>\n  )\n}\n\nexport default TradePage\n"
  },
  {
    "path": "packages/frontend/pages/strategies/bull.tsx",
    "content": "import React from 'react'\nimport { NextSeo } from 'next-seo'\n\nimport BullStrategy from '@components/Strategies/Bull'\nimport { SQUEETH_BASE_URL } from '@constants/index'\n\nconst Page: React.FC = () => {\n  return (\n    <>\n      <NextSeo\n        title=\"Opyn Zen Bull Strategy - Stack ETH\"\n        description=\"Stack ETH when ETH increases slow and steady\"\n        canonical={SQUEETH_BASE_URL}\n        openGraph={{\n          images: [\n            {\n              url: SQUEETH_BASE_URL + '/images/previews/bull.png',\n              width: 1200,\n              height: 630,\n              alt: 'Zen Bull Strategy',\n            },\n          ],\n        }}\n        twitter={{\n          handle: '@opyn_',\n          site: '@opyn_',\n          cardType: 'summary_large_image',\n        }}\n      />\n\n      <BullStrategy />\n    </>\n  )\n}\n\nexport default Page\n"
  },
  {
    "path": "packages/frontend/pages/strategies/crab.tsx",
    "content": "import React, { useEffect } from 'react'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport { NextSeo } from 'next-seo'\n\nimport CrabTradeV2 from '@components/Strategies/Crab/CrabTradeV2'\nimport MyPosition from '@components/Strategies/Crab/MyPosition'\nimport About from '@components/Strategies/Crab/About'\nimport StrategyPerformance from '@components/Strategies/Crab/StrategyPerformance'\nimport { useSetStrategyData, useSetStrategyDataV2, useCurrentCrabPositionValueV2 } from '@state/crab/hooks'\nimport { useInitCrabMigration } from '@state/crabMigration/hooks'\nimport { SQUEETH_BASE_URL } from '@constants/index'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      marginTop: '32px',\n      display: 'flex',\n      justifyContent: 'center',\n      gridGap: '96px',\n      flexWrap: 'wrap',\n      [theme.breakpoints.down('md')]: {\n        gridGap: '40px',\n      },\n    },\n    leftColumn: {\n      flex: 1,\n      minWidth: '480px',\n      [theme.breakpoints.down('xs')]: {\n        minWidth: '320px',\n      },\n    },\n    rightColumn: {\n      flexBasis: '452px',\n      [theme.breakpoints.down('xs')]: {\n        flex: '1',\n      },\n    },\n    infoContainer: {\n      display: 'flex',\n      flexDirection: 'column',\n      gap: '72px',\n    },\n    tradeSection: {\n      border: '1px solid #242728',\n      boxShadow: '0px 4px 40px rgba(0, 0, 0, 0.25)',\n      borderRadius: theme.spacing(1),\n      padding: '32px 24px',\n    },\n  }),\n)\n\nconst Crab: React.FC = () => {\n  const setStrategyData = useSetStrategyData()\n  const setStrategyDataV2 = useSetStrategyDataV2()\n  const classes = useStyles()\n  const { currentCrabPositionValue, isCrabPositionValueLoading, refetchCrabTokenBalance } =\n    useCurrentCrabPositionValueV2()\n\n  useInitCrabMigration()\n\n  useEffect(() => {\n    setStrategyData()\n    setStrategyDataV2()\n  }, [setStrategyData, setStrategyDataV2])\n\n  return (\n    <>\n      <NextSeo\n        title=\"Opyn Crab Strategy - Stack USDC\"\n        description=\"Stack USDC when ETH is flat\"\n        canonical={SQUEETH_BASE_URL}\n        openGraph={{\n          images: [\n            {\n              url: SQUEETH_BASE_URL + '/images/previews/crab.png',\n              width: 1200,\n              height: 630,\n              alt: 'Crab Strategy',\n            },\n          ],\n        }}\n        twitter={{\n          handle: '@opyn_',\n          site: '@opyn_',\n          cardType: 'summary_large_image',\n        }}\n      />\n\n      <div className={classes.container}>\n        <div className={classes.leftColumn}>\n          <div className={classes.infoContainer}>\n            <MyPosition\n              currentCrabPositionValue={currentCrabPositionValue}\n              isCrabPositionValueLoading={isCrabPositionValueLoading}\n            />\n            {/* <StrategyPerformance /> */}\n            <About />\n          </div>\n        </div>\n        <div className={classes.rightColumn}>\n          <div className={classes.tradeSection}>\n            <CrabTradeV2 refetchCrabTokenBalance={refetchCrabTokenBalance} />\n          </div>\n        </div>\n      </div>\n    </>\n  )\n}\n\nexport default Crab\n"
  },
  {
    "path": "packages/frontend/pages/strategies/index.tsx",
    "content": "import React, { useEffect } from 'react'\nimport { useRouter } from 'next/router'\n\nconst Redirection = () => {\n  const router = useRouter()\n\n  useEffect(() => {\n    router.push('/strategies/crab', undefined, { shallow: true })\n  }, [router])\n\n  return <></>\n}\n\nconst Page: React.FC = () => <Redirection />\n\nexport default Page\n\nexport async function getServerSideProps() {\n  return {\n    redirect: {\n      destination: '/strategies/crab',\n      permanent: true,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/frontend/pages/terms-of-service-faq.tsx",
    "content": "import { getMarkdown } from '@utils/markdown'\nimport MarkdownPage from '@components/MarkdownPage'\nimport DefaultSiteSeo from '@components/DefaultSiteSeo/DefaultSiteSeo'\n\nconst TermsOfServiceFAQ = (props: any) => {\n  return (\n    <>\n      <DefaultSiteSeo />\n      <MarkdownPage markdown={props.file} />\n    </>\n  )\n}\n\nexport async function getStaticProps() {\n  const file = getMarkdown('terms-of-service-faq')\n\n  return { props: { file } }\n}\n\nexport default TermsOfServiceFAQ\n"
  },
  {
    "path": "packages/frontend/pages/terms-of-service.tsx",
    "content": "import { getMarkdown } from '@utils/markdown'\nimport MarkdownPage from '@components/MarkdownPage'\nimport DefaultSiteSeo from '@components/DefaultSiteSeo/DefaultSiteSeo'\n\nconst TermsOfService = (props: any) => {\n  return (\n    <>\n      <DefaultSiteSeo />\n      <MarkdownPage markdown={props.file} />\n    </>\n  )\n}\n\nexport async function getStaticProps() {\n  const file = getMarkdown('terms-of-service')\n\n  return { props: { file } }\n}\n\nexport default TermsOfService\n"
  },
  {
    "path": "packages/frontend/pages/vault/[vid].tsx",
    "content": "import { useQuery } from '@apollo/client'\nimport {\n  CircularProgress,\n  Link,\n  Typography,\n  Tooltip,\n  Select,\n  MenuItem,\n  FormControl,\n  InputLabel,\n} from '@material-ui/core'\nimport { orange } from '@material-ui/core/colors'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport AccessTimeIcon from '@material-ui/icons/AccessTime'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport ReportProblemOutlinedIcon from '@material-ui/icons/ReportProblemOutlined'\nimport BigNumber from 'bignumber.js'\nimport clsx from 'clsx'\nimport Image from 'next/image'\nimport { useRouter } from 'next/router'\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useAtom, useAtomValue } from 'jotai'\n\nimport ethLogo from '../../public/images/ethereum-eth.svg'\nimport squeethLogo from '../../public/images/Squeeth.svg'\nimport { AddButton, RemoveButton } from '@components/Button'\nimport CollatRange from '@components/CollatRange'\nimport NumberInput from '@components/Input/NumberInput'\nimport Nav from '@components/Nav'\nimport TradeInfoItem from '@components/TradeOld/TradeInfoItem'\nimport { Tooltips } from '@constants/enums'\nimport { BIG_ZERO, MIN_COLLATERAL_AMOUNT, OSQUEETH_DECIMALS, SQUEETH_BASE_URL } from '../../src/constants'\nimport { PositionType } from '../../src/types'\nimport { useRestrictUser } from '@context/restrict-user'\nimport { useVaultLiquidations } from '@hooks/contracts/useLiquidations'\nimport { CollateralStatus, Vault } from '../../src/types'\nimport { getCollatPercentStatus, toTokenAmount } from '@utils/calculations'\nimport { LinkButton } from '@components/Button'\nimport { useERC721 } from '@hooks/contracts/useERC721'\nimport { ACTIVE_POSITIONS_QUERY } from '@queries/uniswap/positionsQuery'\nimport { positions, positionsVariables } from '@queries/uniswap/__generated__/positions'\nimport { addressAtom, connectedWalletAtom, supportedNetworkAtom, networkIdAtom } from 'src/state/wallet/atoms'\nimport { useWalletBalance } from 'src/state/wallet/hooks'\nimport { useVaultQuery } from 'src/state/positions/hooks'\nimport { addressesAtom, collatPercentAtom, positionTypeAtom } from 'src/state/positions/atoms'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport { UniswapIframe } from 'src/components/Modal/UniswapIframe'\nimport {\n  useBurnAndRedeem,\n  useDepositCollateral,\n  useDepositUnuPositionToken,\n  useGetCollatRatioAndLiqPrice,\n  useGetDebtAmount,\n  useGetShortAmountFromDebt,\n  useGetTwapEthPrice,\n  useGetUniNFTCollatDetail,\n  useGetUniNFTDetails,\n  useOpenDepositAndMint,\n  useWithdrawCollateral,\n  useWithdrawUniPositionToken,\n  useRedeemVault,\n} from 'src/state/controller/hooks'\nimport {\n  useComputeSwaps,\n  useLpDebt,\n  useMintedDebt,\n  useShortDebt,\n  usePositionsAndFeesComputation,\n} from 'src/state/positions/hooks'\nimport { useVaultData } from '@hooks/useVaultData'\nimport useVault from '@hooks/useVault'\nimport DefaultSiteSeo from '@components/DefaultSiteSeo/DefaultSiteSeo'\nimport RestrictionInfo from '@components/RestrictionInfo'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      margin: theme.spacing(0, 'auto'),\n      padding: theme.spacing(6, 0),\n      width: '840px',\n      [theme.breakpoints.down('sm')]: {\n        width: '100%',\n        padding: theme.spacing(0, 2),\n        margin: theme.spacing(0, 'auto'),\n      },\n    },\n    overviewHeaderTitle: {\n      fontSize: '20px',\n      marginTop: theme.spacing(1),\n      fontWeight: 300,\n    },\n    overview: {\n      display: 'flex',\n      marginTop: theme.spacing(2),\n      gap: '15px',\n    },\n    overviewItem: {\n      display: 'flex',\n      flexDirection: 'column',\n      background: theme.palette.background.stone,\n      // height: '75px',\n      width: '100%',\n      maxWidth: '225px',\n      borderRadius: theme.spacing(2),\n      padding: theme.spacing(2, 3),\n      marginBottom: '1em',\n    },\n    overviewTitle: {\n      fontSize: '14px',\n      color: theme.palette.text.secondary,\n      fontWeight: 600,\n      display: 'flex',\n      alignItems: 'center',\n    },\n    overviewValue: {\n      fontSize: '22px',\n    },\n    redeemVaultBtnContainer: {\n      marginTop: theme.spacing(4),\n      padding: theme.spacing(3),\n      background: theme.palette.background.stone,\n      borderRadius: theme.spacing(2),\n    },\n    redeemVaultBtn: {\n      width: '100%',\n      minHeight: '40px',\n      marginTop: theme.spacing(2),\n      cursor: 'pointer',\n    },\n    redeemVaultTitle: {\n      fontSize: '20px',\n      fontWeight: 500,\n      marginBottom: theme.spacing(2),\n    },\n    redeemVaultDescription: {\n      color: theme.palette.text.secondary,\n      fontSize: '14px',\n      '& span': {\n        display: 'block',\n        marginTop: theme.spacing(0.5),\n        paddingLeft: theme.spacing(2),\n      },\n    },\n    redeemVaultWarning: {\n      color: theme.palette.text.secondary,\n      marginTop: theme.spacing(2),\n      borderRadius: theme.spacing(1),\n      fontSize: '14px',\n\n      '& a': {\n        textDecoration: 'underline',\n      },\n    },\n    manager: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      margin: theme.spacing(3, 0),\n      gap: theme.spacing(2),\n    },\n    managerItem: {\n      background: theme.palette.background.stone,\n      borderRadius: theme.spacing(2),\n      padding: theme.spacing(4, 6.8),\n    },\n    managerItemHeader: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'flex-start',\n      '& > *': {\n        display: 'flex',\n        justifyContent: 'flex-start',\n      },\n    },\n    managerItemTitle: {\n      fontSize: '24px',\n      marginLeft: theme.spacing(1),\n      fontWeight: 300,\n    },\n    managerActions: {\n      margin: 'auto',\n      width: '300px',\n      display: 'flex',\n      justifyContent: 'space-around',\n      marginTop: theme.spacing(2),\n    },\n    actionBtn: {\n      width: '75px',\n    },\n    collatContainer: {\n      margin: 'auto',\n      width: '300px',\n      marginBottom: '16px',\n      display: 'flex',\n      flexDirection: 'column',\n      alignItems: 'left',\n      justifyContent: 'center',\n      marginTop: '16px',\n    },\n    txDetails: {\n      background: theme.palette.background.paper,\n      width: '300px',\n      borderRadius: theme.spacing(1),\n      marginLeft: 'auto',\n      marginRight: 'auto',\n      marginTop: theme.spacing(2),\n      marginBottom: theme.spacing(2),\n      padding: theme.spacing(1),\n    },\n    collatStatus: {\n      padding: theme.spacing(0, 1),\n      borderRadius: theme.spacing(0.5),\n      fontSize: '10px',\n      fontWeight: 600,\n    },\n    safe: {\n      background: `${theme.palette.success.main}30`,\n      color: theme.palette.success.main,\n    },\n    risky: {\n      background: `${orange[600]}30`,\n      color: orange[600],\n    },\n    danger: {\n      background: `${theme.palette.error.main}30`,\n      color: theme.palette.error.main,\n    },\n    loading: {\n      width: '100%',\n      display: 'flex',\n      justifyContent: 'center',\n      marginTop: theme.spacing(8),\n    },\n    liquidationContainer: {\n      width: '380px',\n      background: `${theme.palette.error.main}20`,\n      borderRadius: theme.spacing(2),\n      marginTop: theme.spacing(2),\n      padding: theme.spacing(2, 3),\n    },\n    liqTitle: {\n      fontWeight: 600,\n      marginLeft: theme.spacing(2),\n    },\n    liqItem: {\n      display: 'flex',\n      alignItems: 'center',\n      marginTop: theme.spacing(1),\n    },\n    withdrawBtn: {\n      padding: theme.spacing(0, 1),\n      borderRadius: theme.spacing(0.5),\n      fontSize: '10px',\n      fontWeight: 600,\n      marginLeft: theme.spacing(1),\n      color: theme.palette.error.main,\n      textDecoration: 'underline',\n      background: 'transparent',\n      border: 'none',\n      cursor: 'pointer',\n    },\n    debtOverview: {\n      margin: '2em 0 2em 0',\n    },\n    debtItem: {\n      display: 'flex',\n      flexDirection: 'column',\n      border: '1px solid #DCDAE94D',\n      width: '100%',\n      padding: theme.spacing(2),\n      borderRadius: theme.spacing(2),\n      // marginBottom: '1em',\n    },\n    vaultHeader: {\n      display: 'flex',\n      justifyContent: 'space-between',\n    },\n    infoIcon: {\n      fontSize: '14px',\n      marginLeft: theme.spacing(0.5),\n    },\n    mintBurnTooltip: {\n      display: 'flex',\n      justifyContent: 'space-between',\n    },\n    manageLPTokenActionsContainer: {\n      display: 'flex',\n      flexDirection: 'column',\n      justifyContent: 'space-between',\n      alignItems: 'center',\n      gap: '8px',\n      width: '100%',\n    },\n    manageLPTokenActions: {\n      display: 'flex',\n      justifyContent: 'space-around',\n      width: '100%',\n    },\n    lpManagerContainer: {\n      marginTop: theme.spacing(4),\n      padding: theme.spacing(3),\n      background: theme.palette.background.stone,\n      borderRadius: theme.spacing(2),\n    },\n    lpManagerHeader: {\n      display: 'flex',\n      alignItems: 'center',\n      gap: theme.spacing(2),\n      marginBottom: theme.spacing(3),\n    },\n    lpManagerTitle: {\n      fontSize: '20px',\n      fontWeight: 500,\n    },\n    lpManagerContent: {\n      display: 'flex',\n      flexDirection: 'column',\n      alignItems: 'center',\n      gap: theme.spacing(2),\n    },\n    lpManagerDescription: {\n      color: theme.palette.text.secondary,\n      textAlign: 'center',\n      maxWidth: '600px',\n      fontSize: '14px',\n      lineHeight: 1.5,\n    },\n    logoContainer: {\n      width: '40px',\n      height: '40px',\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n    },\n  }),\n)\n\nenum VaultAction {\n  ADD_COLLATERAL,\n  REMOVE_COLLATERAL,\n  MINT_SQUEETH,\n  BURN_SQUEETH,\n  APPROVE_UNI_POSITION,\n  DEPOSIT_UNI_POSITION,\n  WITHDRAW_UNI_POSITION,\n  REDEEM_UNI_POSITION,\n  REDEEM_VAULT,\n}\n\nenum VaultError {\n  MIN_COLLATERAL = 'Minimum vault collateral is 6.9 ETH',\n  MIN_COLLAT_PERCENT = 'Minimum collateral ratio is 150%',\n  INSUFFICIENT_ETH_BALANCE = 'Insufficient ETH Balance',\n  INSUFFICIENT_OSQTH_BALANCE = 'Insufficient oSQTH Balance',\n}\n\nconst SelectLP: React.FC<{ lpToken: number; setLpToken: (t: number) => void; disabled?: boolean }> = ({\n  lpToken,\n  setLpToken,\n  disabled,\n}) => {\n  const { squeethPool } = useAtomValue(addressesAtom)\n  const address = useAtomValue(addressAtom)\n\n  const { data } = useQuery<positions, positionsVariables>(ACTIVE_POSITIONS_QUERY, {\n    variables: {\n      poolAddress: squeethPool,\n      owner: address || '',\n    },\n    fetchPolicy: 'no-cache',\n  })\n\n  return (\n    <FormControl variant=\"outlined\" style={{ width: '300px' }} size=\"small\">\n      <InputLabel id=\"demo-simple-select-outlined-label\">LP Id</InputLabel>\n      <Select\n        disabled={disabled}\n        labelId=\"demo-simple-select-label\"\n        id=\"lp-id-select\"\n        value={lpToken}\n        onChange={(e) => setLpToken(Number(e.target.value))}\n        label=\"LP id\"\n      >\n        <MenuItem value={0} id=\"lp-id-option-none\">\n          None\n        </MenuItem>\n        {data?.positions?.map((p, index) => (\n          <MenuItem key={p.id} value={p.id} id={'lp-id-option' + '-' + index}>\n            {p.id}\n          </MenuItem>\n        ))}\n      </Select>\n    </FormControl>\n  )\n}\n\nconst Component: React.FC = () => {\n  const classes = useStyles()\n  const router = useRouter()\n  const { isRestricted, isWithdrawAllowed } = useRestrictUser()\n  usePositionsAndFeesComputation()\n\n  const getCollatRatioAndLiqPrice = useGetCollatRatioAndLiqPrice()\n  const getDebtAmount = useGetDebtAmount()\n  const withdrawCollateral = useWithdrawCollateral()\n  const getTwapEthPrice = useGetTwapEthPrice()\n  const redeemVault = useRedeemVault()\n  const getUniNFTCollatDetail = useGetUniNFTCollatDetail()\n\n  const { vid } = router.query\n  const { liquidations } = useVaultLiquidations(Number(vid))\n  const mintedDebt = useMintedDebt()\n  const shortDebt = useShortDebt()\n\n  const lpedSqueeth = useLpDebt()\n\n  const [minCollateral, setMinCollateral] = useState<string | undefined>(undefined)\n  const [collateral, setCollateral] = useState('0')\n  const [lpNftCollatPercent, setLpNftCollatPercent] = useState(0)\n  const collateralBN = new BigNumber(collateral)\n  const [shortAmount, setShortAmount] = useState('0')\n\n  const [twapEthPrice, setTwapEthPrice] = useState(new BigNumber(0))\n  const [newLiqPrice, setNewLiqPrice] = useState(new BigNumber(0))\n  const [newLpNftLiqPrice, setNewLpNftLiqPrice] = useState(new BigNumber(0))\n  const [action, setAction] = useState(VaultAction.ADD_COLLATERAL)\n  const [txLoading, setTxLoading] = useState(false)\n\n  const { vault, loading: isVaultLoading, updateVault } = useVault(Number(vid))\n  const { existingCollatPercent, existingLiqPrice } = useVaultData(vault as any)\n  const [collatPercent, setCollatPercent] = useAtom(collatPercentAtom)\n\n  const [lpedEth, setLpedEth] = useState(new BigNumber(0))\n  const [lpedSqueethInEth, setLpedSqueethInEth] = useState(new BigNumber(0))\n  const [lpedSqueethAmount, setLpedSqueethAmount] = useState(new BigNumber(0))\n\n  const getUniNFTDetails = useGetUniNFTDetails()\n\n  useEffect(() => {\n    const getLPValues = async () => {\n      // make sure vault is loaded and has NFT as collateral\n      if (!isVaultLoading && vault && Number(vault?.NFTCollateralId) !== 0) {\n        try {\n          const { ethAmount, squeethValueInEth, squeethAmount } = await getUniNFTDetails(Number(vault?.NFTCollateralId))\n          setLpedEth(ethAmount)\n          setLpedSqueethInEth(squeethValueInEth)\n          setLpedSqueethAmount(squeethAmount)\n        } catch (err) {\n          console.error('Error getting LP values:', err)\n          setLpedEth(new BigNumber(0))\n          setLpedSqueethInEth(new BigNumber(0))\n          setLpedSqueethAmount(new BigNumber(0))\n        }\n      } else {\n        setLpedEth(new BigNumber(0))\n        setLpedSqueethInEth(new BigNumber(0))\n        setLpedSqueethAmount(new BigNumber(0))\n      }\n    }\n\n    getLPValues()\n  }, [vault?.NFTCollateralId, isVaultLoading])\n\n  useEffect(() => {\n    ;(async () => {\n      if (vault) {\n        let collateralAmount = vault.collateralAmount\n        if (currentLpNftId) {\n          const { collateral: uniCollat } = await getUniNFTCollatDetail(currentLpNftId)\n          collateralAmount = collateralAmount.plus(uniCollat)\n        }\n        const debt = await getDebtAmount(vault.shortAmount)\n        const collateralWithMinRatio = debt.times(1.5).minus(collateralAmount).toNumber()\n        const minCollateral = vault.collateralAmount.minus(MIN_COLLATERAL_AMOUNT).negated().toNumber()\n        if (collateralWithMinRatio < 0 && minCollateral < 0) {\n          setMinCollateral(Math.max(collateralWithMinRatio, minCollateral).toString())\n        } else if (collateralWithMinRatio >= 0 && minCollateral < 0) {\n          setMinCollateral(minCollateral.toString())\n        } else if (collateralWithMinRatio < 0 && minCollateral >= 0) {\n          setMinCollateral(collateralWithMinRatio.toString())\n        } else {\n          setMinCollateral('0')\n        }\n      } else {\n        setMinCollateral(collateral)\n      }\n    })()\n  }, [vault])\n\n  useEffect(() => {\n    getTwapEthPrice().then((price) => {\n      setTwapEthPrice(price)\n    })\n  }, [getTwapEthPrice])\n\n  const updateNftCollateral = async (\n    collatAmountToUpdate: BigNumber,\n    shortAmountToUpdate: BigNumber,\n    lpNftIdToManage: number,\n  ) => {\n    if (!vault) return\n\n    const { collateralPercent: cp, liquidationPrice: lp } = await getCollatRatioAndLiqPrice(\n      collatAmountToUpdate.plus(vault.collateralAmount),\n      shortAmountToUpdate.plus(vault.shortAmount),\n      lpNftIdToManage, // 0 means to simulate the removal of lp nft\n    )\n\n    setNewLpNftLiqPrice(lp)\n    setLpNftCollatPercent(cp)\n  }\n\n  const updateCollateral = async (collatAmount: string) => {\n    setCollateral(collatAmount)\n    if (!vault) return\n    const collatAmountBN = new BigNumber(collatAmount)\n\n    const { collateralPercent: cp, liquidationPrice: lp } = await getCollatRatioAndLiqPrice(\n      collatAmountBN.plus(vault.collateralAmount), // Get liquidation price and collatPercent for total collat after tx happens\n      vault.shortAmount,\n      currentLpNftId,\n    )\n    setNewLiqPrice(lp)\n    setCollatPercent(cp)\n    setAction(collatAmountBN.isPositive() ? VaultAction.ADD_COLLATERAL : VaultAction.REMOVE_COLLATERAL)\n  }\n\n  const removeCollat = async (collatAmount: BigNumber) => {\n    if (!vault) return\n\n    setTxLoading(true)\n    try {\n      await withdrawCollateral(Number(vault.id), collatAmount.abs())\n      updateVault()\n\n      updateNftCollateral(BIG_ZERO, BIG_ZERO, currentLpNftId)\n    } catch (e) {\n      console.log(e)\n    }\n    setTxLoading(false)\n  }\n\n  const handleRedeemVault = async () => {\n    if (!vault) return\n\n    setTxLoading(true)\n    setAction(VaultAction.REDEEM_VAULT)\n    try {\n      await redeemVault(Number(vault.id))\n      updateVault()\n    } catch (e) {\n      console.log(e)\n    }\n    setTxLoading(false)\n  }\n\n  const collatStatus = useCallback(() => {\n    return getCollatPercentStatus(existingCollatPercent)\n  }, [existingCollatPercent])\n\n  const collatClass = useMemo(() => {\n    if (collatStatus() === CollateralStatus.SAFE) return classes.safe\n    if (collatStatus() === CollateralStatus.RISKY) return classes.risky\n    return classes.danger\n  }, [classes.danger, classes.risky, classes.safe, collatStatus()])\n\n  const { totalLiquidated, totalCollatPaid } = liquidations.reduce(\n    (acc, l) => {\n      acc.totalLiquidated = acc.totalLiquidated.plus(l.debtAmount)\n      acc.totalCollatPaid = acc.totalCollatPaid.plus(l.collateralPaid)\n      return acc\n    },\n    {\n      totalLiquidated: new BigNumber(0),\n      totalCollatPaid: new BigNumber(0),\n    },\n  )\n\n  const currentLpNftId = Number(vault?.NFTCollateralId)\n  const isLPDeposited = currentLpNftId !== 0\n\n  useEffect(() => {\n    if (isLPDeposited && !!currentLpNftId && vault) {\n      setAction(VaultAction.DEPOSIT_UNI_POSITION)\n      updateNftCollateral(BIG_ZERO, BIG_ZERO, 0)\n    }\n  }, [isLPDeposited, currentLpNftId, vault, vault?.collateralAmount, vault?.shortAmount])\n\n  return (\n    <div>\n      <Nav />\n      {isVaultLoading ? (\n        <div className={classes.loading}>\n          <Typography variant=\"h5\" color=\"textSecondary\">\n            Loading...\n          </Typography>\n        </div>\n      ) : (\n        <div className={classes.container}>\n          <div className={classes.vaultHeader}>\n            <Typography color=\"primary\" variant=\"h6\">\n              Manage Vault #{vid}\n            </Typography>\n            <div className={classes.liqItem}>\n              <Typography color=\"textSecondary\" variant=\"body2\">\n                ETH Price:\n              </Typography>\n              <Typography variant=\"body2\" color=\"textPrimary\" style={{ marginLeft: '8px' }}>\n                $ {twapEthPrice.toFixed(2)}\n              </Typography>\n              <Tooltip title=\"This is a 7min TWAP from Uniswap\">\n                <AccessTimeIcon fontSize=\"small\" className={classes.infoIcon} />\n              </Tooltip>\n            </div>\n          </div>\n          {liquidations.length ? (\n            <div className={classes.liquidationContainer}>\n              <div style={{ display: 'flex', alignItems: 'center' }}>\n                <ReportProblemOutlinedIcon color=\"error\" fontSize=\"small\" />\n                <Typography className={classes.liqTitle} color=\"error\">\n                  Vault Liquidated\n                </Typography>\n              </div>\n              <div className={classes.liqItem}>\n                <Typography color=\"textSecondary\" variant=\"body2\">\n                  Total squeeth liquidated:\n                </Typography>\n                <Typography variant=\"body2\" color=\"textPrimary\" style={{ marginLeft: '8px' }}>\n                  {totalLiquidated.toFixed(6)} oSQTH\n                </Typography>\n              </div>\n              <div className={classes.liqItem}>\n                <Typography color=\"textSecondary\" variant=\"body2\">\n                  Total collateral paid:\n                </Typography>\n                <Typography variant=\"body2\" color=\"textPrimary\" style={{ marginLeft: '8px' }}>\n                  {totalCollatPaid.toFixed(6)} ETH\n                </Typography>\n              </div>\n            </div>\n          ) : null}\n\n          <div className={classes.debtOverview}>\n            <div className={classes.overview}>\n              <div className={classes.debtItem}>\n                <Typography className={classes.overviewTitle}>\n                  <span>Total Debt (oSQTH)</span>\n                  <Tooltip title={Tooltips.TotalDebt}>\n                    <InfoIcon className={classes.infoIcon} />\n                  </Tooltip>\n                </Typography>\n                <Typography className={classes.overviewValue} id=\"vault-total-debt-bal\">\n                  {vault?.shortAmount.gt(0) ? vault?.shortAmount.toFixed(6) : 0}\n                </Typography>\n              </div>\n              <div className={classes.debtItem}>\n                <Typography className={classes.overviewTitle}>\n                  <span>Short Debt (oSQTH)</span>\n                  <Tooltip title={Tooltips.ShortDebt}>\n                    <InfoIcon className={classes.infoIcon} />\n                  </Tooltip>\n                </Typography>\n                <Typography className={classes.overviewValue} id=\"vault-shorted-debt-bal\">\n                  {shortDebt?.gt(0) ? shortDebt.toFixed(6) : 0}\n                </Typography>\n              </div>\n              <div className={classes.debtItem}>\n                <Typography className={classes.overviewTitle}>\n                  <span>Minted Debt (oSQTH)</span>\n                  <Tooltip title={Tooltips.MintedDebt}>\n                    <InfoIcon className={classes.infoIcon} />\n                  </Tooltip>\n                </Typography>\n\n                <Typography className={classes.overviewValue} id=\"vault-minted-debt-bal\">\n                  {mintedDebt.gt(0) ? mintedDebt.toFixed(6) : 0}\n                </Typography>\n              </div>\n              <div className={classes.debtItem}>\n                <Typography className={classes.overviewTitle}>\n                  <span>LPed Debt (oSQTH)</span>\n                  <Tooltip title={Tooltips.LPDebt}>\n                    <InfoIcon className={classes.infoIcon} />\n                  </Tooltip>\n                </Typography>\n                <Typography className={classes.overviewValue} id=\"vault-lped-debt-bal\">\n                  {lpedSqueeth?.gt(0) ? lpedSqueeth.toFixed(6) : 0}\n                </Typography>\n              </div>\n            </div>\n          </div>\n\n          <Typography className={classes.overviewHeaderTitle} variant=\"h6\">\n            Vault Stats\n          </Typography>\n          <div className={classes.overview}>\n            <div className={classes.overviewItem}>\n              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n                <Typography className={classes.overviewValue}>\n                  {existingCollatPercent === Infinity ? '--' : `${existingCollatPercent || 0} %`}\n                </Typography>\n                <Typography className={clsx(classes.collatStatus, collatClass)} variant=\"caption\" id=\"vault-cr\">\n                  {getCollatPercentStatus(existingCollatPercent)}\n                </Typography>\n              </div>\n              <Typography className={classes.overviewTitle}>Collateral percent</Typography>\n            </div>\n            <div className={classes.overviewItem}>\n              <Typography className={classes.overviewValue}>\n                $ <span id=\"vault-liqp\">{!existingLiqPrice.isFinite() ? '--' : existingLiqPrice.toFixed(2)}</span>\n              </Typography>\n              <Typography className={classes.overviewTitle}>Liquidation Price</Typography>\n            </div>\n          </div>\n\n          <Typography className={classes.overviewHeaderTitle} variant=\"h6\">\n            Vault Components\n          </Typography>\n          <div className={classes.overview}>\n            <div className={classes.overviewItem}>\n              <Typography className={classes.overviewValue}>{vault?.shortAmount.toFixed(6)}</Typography>\n              <Typography className={classes.overviewTitle}>Total Debt (oSQTH)</Typography>\n            </div>\n            <div className={classes.overviewItem}>\n              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n                <Typography className={classes.overviewValue} id=\"vault-collat-amount\">\n                  {vault?.collateralAmount.toFixed(4)}\n                </Typography>\n                {!isRestricted || isWithdrawAllowed ? (\n                  <>\n                    {vault?.shortAmount.isZero() && vault.collateralAmount.gt(0) ? (\n                      <button\n                        className={clsx(classes.withdrawBtn)}\n                        onClick={() => {\n                          updateCollateral(vault!.collateralAmount.negated().toString())\n                          removeCollat(vault!.collateralAmount)\n                        }}\n                        id=\"withdraw-collat-submit-btn\"\n                      >\n                        WITHDRAW\n                      </button>\n                    ) : null}\n                  </>\n                ) : null}\n              </div>\n              <Typography className={classes.overviewTitle}>Collateral (ETH)</Typography>\n            </div>\n\n            {isLPDeposited && (\n              <>\n                <div className={classes.overviewItem}>\n                  <Typography className={classes.overviewValue}>{lpedEth.toFixed(4)}</Typography>\n                  <Typography className={classes.overviewTitle}>LP ETH Amount</Typography>\n                </div>\n                <div className={classes.overviewItem}>\n                  <Typography className={classes.overviewValue}>{lpedSqueethAmount.toFixed(6)}</Typography>\n                  <Typography className={classes.overviewTitle}>LP oSQTH Amount</Typography>\n                </div>\n              </>\n            )}\n          </div>\n\n          <VaultRedeemSection\n            vault={vault}\n            isLPDeposited={isLPDeposited}\n            lpedSqueeth={lpedSqueeth}\n            txLoading={txLoading}\n            action={action}\n            handleRedeemVault={handleRedeemVault}\n            vaultId={Number(vid)} // Pass the vault ID from router.query\n          />\n\n          {!isRestricted || isWithdrawAllowed ? (\n            <div className={classes.lpManagerContainer}>\n              <div className={classes.lpManagerHeader}>\n                <div className={classes.logoContainer}>\n                  <Image src={ethLogo} alt=\"ETH logo\" width={40} height={40} />\n                </div>\n                <Typography className={classes.lpManagerTitle}>Manage LP Token</Typography>\n              </div>\n\n              <div className={classes.lpManagerContent}>\n                <UniswapIframe text={'Withdraw LP Position'} closePosition={true} />\n                <Typography className={classes.lpManagerDescription}>\n                  If you have an LP position in Uniswap, you can withdraw it directly here. <br />\n                  The withdrawn oSQTH can then be redeemed separately from the <Link href=\"/squeeth\">trade page</Link>.\n                </Typography>\n              </div>\n            </div>\n          ) : null}\n        </div>\n      )}\n    </div>\n  )\n}\n\ninterface VaultRedeemSectionProps {\n  vault: Vault | undefined\n  isLPDeposited: boolean\n  lpedSqueeth: BigNumber\n  txLoading: boolean\n  action: VaultAction\n  handleRedeemVault: () => Promise<void>\n  vaultId: number\n}\n\nconst VaultRedeemSection: React.FC<VaultRedeemSectionProps> = ({\n  vault,\n  isLPDeposited,\n  lpedSqueeth,\n  txLoading,\n  action,\n  handleRedeemVault,\n  vaultId,\n}) => {\n  const classes = useStyles()\n\n  const currentUserAddress = useAtomValue(addressAtom)\n  const { data: vaultQueryData } = useVaultQuery(vaultId)\n\n  const isVaultOwner = currentUserAddress?.toLowerCase() === vaultQueryData?.owner?.toLowerCase()\n  if (!isVaultOwner) return null\n\n  return (\n    <div className={classes.redeemVaultBtnContainer}>\n      <Typography className={classes.redeemVaultTitle}>Redeem Vault</Typography>\n      <Typography className={classes.redeemVaultDescription}>\n        {!vault?.shortAmount?.gt(0) && !isLPDeposited ? (\n          <Typography className={classes.redeemVaultDescription}>This vault has no positions to redeem.</Typography>\n        ) : (\n          <>\n            <Typography className={classes.redeemVaultDescription}>\n              {(vault?.shortAmount?.gt(0) || isLPDeposited) && (\n                <>\n                  This will:\n                  {isLPDeposited && <span>• Withdraw your LP position from vault</span>}\n                  {vault?.shortAmount?.gt(0) && (\n                    <span>• Close your short position by burning {vault.shortAmount.toFixed(6)} oSQTH</span>\n                  )}\n                </>\n              )}\n            </Typography>\n\n            <RemoveButton\n              id=\"redeem-vault-submit-tx-btn\"\n              onClick={handleRedeemVault}\n              disabled={txLoading}\n              className={classes.redeemVaultBtn}\n            >\n              {action === VaultAction.REDEEM_VAULT && txLoading ? (\n                <CircularProgress color=\"primary\" size=\"1rem\" />\n              ) : (\n                'Redeem Vault'\n              )}\n            </RemoveButton>\n          </>\n        )}\n      </Typography>\n\n      {lpedSqueeth?.gt(vault?.shortAmount || BIG_ZERO) && (\n        <Typography className={classes.redeemVaultWarning}>\n          <b>Note:</b> After redemption, you&apos;ll need to manually redeem{' '}\n          {lpedSqueeth.minus(vault?.shortAmount || BIG_ZERO).toFixed(6)} oSQTH from your LP position using the\n          &quot;Redeem Long&quot; functionality on the <Link href=\"/squeeth\">trade page</Link>\n        </Typography>\n      )}\n    </div>\n  )\n}\n\nconst Main: React.FC = () => {\n  const classes = useStyles()\n\n  const connected = useAtomValue(connectedWalletAtom)\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n\n  if (!connected || !supportedNetwork) {\n    return (\n      <div>\n        <Nav />\n        <div className={classes.loading}>\n          <Typography variant=\"h5\" color=\"textSecondary\">\n            {!supportedNetwork ? 'Unsupported Network' : 'Connect wallet'}\n          </Typography>\n        </div>\n      </div>\n    )\n  }\n\n  return <Component />\n}\n\nconst Page: React.FC = () => {\n  return (\n    <>\n      <DefaultSiteSeo />\n      <Main />\n    </>\n  )\n}\n\nexport default Page\n"
  },
  {
    "path": "packages/frontend/sentry.client.config.ts",
    "content": "import * as Sentry from '@sentry/nextjs'\n\nSentry.init({\n  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,\n  // We recommend adjusting this value in production, or using tracesSampler\n  // for finer control\n  tracesSampleRate: 1.0,\n  // ...\n  // Note: if you want to override the automatic release value, do not set a\n  // `release` value here - use the environment variable `SENTRY_RELEASE`, so\n  // that it will also get attached to your source maps\n})\n"
  },
  {
    "path": "packages/frontend/sentry.server.config.ts",
    "content": "import * as Sentry from '@sentry/nextjs'\n\nSentry.init({\n  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,\n  // We recommend adjusting this value in production, or using tracesSampler\n  // for finer control\n  tracesSampleRate: 1.0,\n  // ...\n  // Note: if you want to override the automatic release value, do not set a\n  // `release` value here - use the environment variable `SENTRY_RELEASE`, so\n  // that it will also get attached to your source maps\n})\n"
  },
  {
    "path": "packages/frontend/src/abis/NFTpositionmanager.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_factory\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_WETH9\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_tokenDescriptor_\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"approved\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Approval\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"operator\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"approved\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"ApprovalForAll\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Collect\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint128\",\n        \"name\": \"liquidity\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"DecreaseLiquidity\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint128\",\n        \"name\": \"liquidity\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"IncreaseLiquidity\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Transfer\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"DOMAIN_SEPARATOR\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"PERMIT_TYPEHASH\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"WETH9\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"approve\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"balanceOf\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"baseURI\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"pure\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"burn\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"tokenId\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"recipient\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint128\",\n            \"name\": \"amount0Max\",\n            \"type\": \"uint128\"\n          },\n          {\n            \"internalType\": \"uint128\",\n            \"name\": \"amount1Max\",\n            \"type\": \"uint128\"\n          }\n        ],\n        \"internalType\": \"struct INonfungiblePositionManager.CollectParams\",\n        \"name\": \"params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"collect\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token0\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token1\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"fee\",\n        \"type\": \"uint24\"\n      },\n      {\n        \"internalType\": \"uint160\",\n        \"name\": \"sqrtPriceX96\",\n        \"type\": \"uint160\"\n      }\n    ],\n    \"name\": \"createAndInitializePoolIfNecessary\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"pool\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"tokenId\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint128\",\n            \"name\": \"liquidity\",\n            \"type\": \"uint128\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amount0Min\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amount1Min\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"deadline\",\n            \"type\": \"uint256\"\n          }\n        ],\n        \"internalType\": \"struct INonfungiblePositionManager.DecreaseLiquidityParams\",\n        \"name\": \"params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"decreaseLiquidity\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"factory\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"getApproved\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"tokenId\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amount0Desired\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amount1Desired\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amount0Min\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amount1Min\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"deadline\",\n            \"type\": \"uint256\"\n          }\n        ],\n        \"internalType\": \"struct INonfungiblePositionManager.IncreaseLiquidityParams\",\n        \"name\": \"params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"increaseLiquidity\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"liquidity\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"operator\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"isApprovedForAll\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"address\",\n            \"name\": \"token0\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"token1\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"fee\",\n            \"type\": \"uint24\"\n          },\n          {\n            \"internalType\": \"int24\",\n            \"name\": \"tickLower\",\n            \"type\": \"int24\"\n          },\n          {\n            \"internalType\": \"int24\",\n            \"name\": \"tickUpper\",\n            \"type\": \"int24\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amount0Desired\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amount1Desired\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amount0Min\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amount1Min\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"recipient\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"deadline\",\n            \"type\": \"uint256\"\n          }\n        ],\n        \"internalType\": \"struct INonfungiblePositionManager.MintParams\",\n        \"name\": \"params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"mint\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"liquidity\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"bytes[]\",\n        \"name\": \"data\",\n        \"type\": \"bytes[]\"\n      }\n    ],\n    \"name\": \"multicall\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bytes[]\",\n        \"name\": \"results\",\n        \"type\": \"bytes[]\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"name\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"ownerOf\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"deadline\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"v\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"r\",\n        \"type\": \"bytes32\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"s\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"name\": \"permit\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"positions\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint96\",\n        \"name\": \"nonce\",\n        \"type\": \"uint96\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"operator\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token0\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token1\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"fee\",\n        \"type\": \"uint24\"\n      },\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tickLower\",\n        \"type\": \"int24\"\n      },\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tickUpper\",\n        \"type\": \"int24\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"liquidity\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"feeGrowthInside0LastX128\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"feeGrowthInside1LastX128\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"tokensOwed0\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"tokensOwed1\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"refundETH\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"safeTransferFrom\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"_data\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"safeTransferFrom\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"value\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"deadline\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"v\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"r\",\n        \"type\": \"bytes32\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"s\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"name\": \"selfPermit\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"nonce\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"expiry\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"v\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"r\",\n        \"type\": \"bytes32\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"s\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"name\": \"selfPermitAllowed\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"nonce\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"expiry\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"v\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"r\",\n        \"type\": \"bytes32\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"s\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"name\": \"selfPermitAllowedIfNecessary\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"value\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"deadline\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"v\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"r\",\n        \"type\": \"bytes32\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"s\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"name\": \"selfPermitIfNecessary\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"operator\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"approved\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"setApprovalForAll\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"bytes4\",\n        \"name\": \"interfaceId\",\n        \"type\": \"bytes4\"\n      }\n    ],\n    \"name\": \"supportsInterface\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountMinimum\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"sweepToken\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"symbol\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"index\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"tokenByIndex\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"index\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"tokenOfOwnerByIndex\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"tokenURI\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"totalSupply\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"transferFrom\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0Owed\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1Owed\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"data\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"uniswapV3MintCallback\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountMinimum\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"unwrapWETH9\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"stateMutability\": \"payable\",\n    \"type\": \"receive\"\n  }\n]\n"
  },
  {
    "path": "packages/frontend/src/abis/auctionBull.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_auctionManager\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_bull\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_factory\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_crab\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_eToken\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_dToken\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"asset\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"receiver\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"Farm\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"clearingPrice\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"isDepositingInCrab\",\n        \"type\": \"bool\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wPowerPerpAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wethTargetInEuler\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"FullRebalance\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"isSellingUsdc\",\n        \"type\": \"bool\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"usdcAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wethLimitAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"LeverageRebalance\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"previousOwner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"OwnershipTransferred\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"oldAuctionManager\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"newAuctionManager\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"SetAuctionManager\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"oldCrLower\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"oldCrUpper\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newCrLower\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newCrUpper\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetCrUpperAndLower\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"oldDeltaLower\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"oldDeltaUpper\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newDeltaLower\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newDeltaUpper\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetDeltaUpperAndLower\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"oldPriceTolerance\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newPriceTolerance\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetFullRebalanceClearingPriceTolerance\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"oldWethLimitPriceTolerance\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newWethLimitPriceTolerance\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetRebalanceWethLimitPriceTolerance\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"DOMAIN_SEPARATOR\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"MAX_FULL_REBALANCE_CLEARING_PRICE_TOLERANCE\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"MAX_REBALANCE_WETH_LIMIT_PRICE_TOLERANCE\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"auctionManager\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"crLower\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"crUpper\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"deltaLower\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"deltaUpper\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_asset\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_receiver\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"farm\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"bidId\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"trader\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"quantity\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"price\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"bool\",\n            \"name\": \"isBuying\",\n            \"type\": \"bool\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"expiry\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"nonce\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint8\",\n            \"name\": \"v\",\n            \"type\": \"uint8\"\n          },\n          {\n            \"internalType\": \"bytes32\",\n            \"name\": \"r\",\n            \"type\": \"bytes32\"\n          },\n          {\n            \"internalType\": \"bytes32\",\n            \"name\": \"s\",\n            \"type\": \"bytes32\"\n          }\n        ],\n        \"internalType\": \"struct ZenAuction.Order[]\",\n        \"name\": \"_orders\",\n        \"type\": \"tuple[]\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_clearingPrice\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wethTargetInEuler\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wethLimitPrice\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"_ethUsdcPoolFee\",\n        \"type\": \"uint24\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"_isDepositingInCrab\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"fullRebalance\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"fullRebalanceClearingPriceTolerance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"getCurrentDeltaAndCollatRatio\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"_isSellingUsdc\",\n        \"type\": \"bool\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_usdcAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wethLimitPrice\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"_poolFee\",\n        \"type\": \"uint24\"\n      }\n    ],\n    \"name\": \"leverageRebalance\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"nonces\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"owner\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"rebalanceWethLimitPriceTolerance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"renounceOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_auctionManager\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"setAuctionManager\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_crLower\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_crUpper\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setCrUpperAndLower\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_deltaLower\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_deltaUpper\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setDeltaUpperAndLower\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_fullRebalancePriceTolerance\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setFullRebalanceClearingPriceTolerance\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_rebalanceWethLimitPriceTolerance\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setRebalanceWethLimitPriceTolerance\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"transferOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount0Delta\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount1Delta\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"_data\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"uniswapV3SwapCallback\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_nonce\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"useNonce\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"stateMutability\": \"payable\",\n    \"type\": \"receive\"\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/bullEmergencyWithdraw.json",
    "content": "[\n  {\n    \"inputs\": [\n      { \"internalType\": \"address\", \"name\": \"_crab\", \"type\": \"address\" },\n      { \"internalType\": \"address\", \"name\": \"_zenBull\", \"type\": \"address\" },\n      { \"internalType\": \"address\", \"name\": \"_weth\", \"type\": \"address\" },\n      { \"internalType\": \"address\", \"name\": \"_usdc\", \"type\": \"address\" },\n      { \"internalType\": \"address\", \"name\": \"_wPowerPerp\", \"type\": \"address\" },\n      { \"internalType\": \"address\", \"name\": \"_ethUSDCPool\", \"type\": \"address\" },\n      { \"internalType\": \"address\", \"name\": \"_eToken\", \"type\": \"address\" },\n      { \"internalType\": \"address\", \"name\": \"_dToken\", \"type\": \"address\" },\n      { \"internalType\": \"address\", \"name\": \"_factory\", \"type\": \"address\" }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      { \"indexed\": true, \"internalType\": \"address\", \"name\": \"owner\", \"type\": \"address\" },\n      { \"indexed\": true, \"internalType\": \"address\", \"name\": \"spender\", \"type\": \"address\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"value\", \"type\": \"uint256\" }\n    ],\n    \"name\": \"Approval\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      { \"indexed\": true, \"internalType\": \"address\", \"name\": \"sender\", \"type\": \"address\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"ratio\", \"type\": \"uint256\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"usdcToRepay\", \"type\": \"uint256\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"wethToWithdraw\", \"type\": \"uint256\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"maxEthForUsdc\", \"type\": \"uint256\" },\n      { \"indexed\": false, \"internalType\": \"bool\", \"name\": \"isEthWithdrawalActivated\", \"type\": \"bool\" }\n    ],\n    \"name\": \"EmergencyRepayEulerDebt\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      { \"indexed\": true, \"internalType\": \"address\", \"name\": \"from\", \"type\": \"address\" },\n      { \"indexed\": true, \"internalType\": \"address\", \"name\": \"to\", \"type\": \"address\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"value\", \"type\": \"uint256\" }\n    ],\n    \"name\": \"Transfer\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      { \"indexed\": true, \"internalType\": \"address\", \"name\": \"recepient\", \"type\": \"address\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"zenBullAmountRedeemed\", \"type\": \"uint256\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"crabAmountRedeemed\", \"type\": \"uint256\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"wPowerPerpRedeemed\", \"type\": \"uint256\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"ethReceived\", \"type\": \"uint256\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"eulerRecoveryTokenAmount\", \"type\": \"uint256\" }\n    ],\n    \"name\": \"Withdraw\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      { \"indexed\": true, \"internalType\": \"address\", \"name\": \"recepient\", \"type\": \"address\" },\n      { \"indexed\": false, \"internalType\": \"uint256\", \"name\": \"ethAmount\", \"type\": \"uint256\" }\n    ],\n    \"name\": \"WithdrawEth\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"LIMIT_PRICE_TOLERANCE\",\n    \"outputs\": [{ \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"MAX_WETH_PER_DEBT_REPAY\",\n    \"outputs\": [{ \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      { \"internalType\": \"address\", \"name\": \"owner\", \"type\": \"address\" },\n      { \"internalType\": \"address\", \"name\": \"spender\", \"type\": \"address\" }\n    ],\n    \"name\": \"allowance\",\n    \"outputs\": [{ \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      { \"internalType\": \"address\", \"name\": \"spender\", \"type\": \"address\" },\n      { \"internalType\": \"uint256\", \"name\": \"amount\", \"type\": \"uint256\" }\n    ],\n    \"name\": \"approve\",\n    \"outputs\": [{ \"internalType\": \"bool\", \"name\": \"\", \"type\": \"bool\" }],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [{ \"internalType\": \"address\", \"name\": \"account\", \"type\": \"address\" }],\n    \"name\": \"balanceOf\",\n    \"outputs\": [{ \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"decimals\",\n    \"outputs\": [{ \"internalType\": \"uint8\", \"name\": \"\", \"type\": \"uint8\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      { \"internalType\": \"address\", \"name\": \"spender\", \"type\": \"address\" },\n      { \"internalType\": \"uint256\", \"name\": \"subtractedValue\", \"type\": \"uint256\" }\n    ],\n    \"name\": \"decreaseAllowance\",\n    \"outputs\": [{ \"internalType\": \"bool\", \"name\": \"\", \"type\": \"bool\" }],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      { \"internalType\": \"uint256\", \"name\": \"_ratio\", \"type\": \"uint256\" },\n      { \"internalType\": \"uint256\", \"name\": \"_limitPriceUsdcPerEth\", \"type\": \"uint256\" },\n      { \"internalType\": \"uint24\", \"name\": \"_poolFee\", \"type\": \"uint24\" }\n    ],\n    \"name\": \"emergencyRepayEulerDebt\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      { \"internalType\": \"uint256\", \"name\": \"_zenBullAmount\", \"type\": \"uint256\" },\n      { \"internalType\": \"uint256\", \"name\": \"_maxEthForWPowerPerp\", \"type\": \"uint256\" }\n    ],\n    \"name\": \"emergencyWithdrawEthFromCrab\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"ethWithdrawalActivated\",\n    \"outputs\": [{ \"internalType\": \"bool\", \"name\": \"\", \"type\": \"bool\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      { \"internalType\": \"address\", \"name\": \"spender\", \"type\": \"address\" },\n      { \"internalType\": \"uint256\", \"name\": \"addedValue\", \"type\": \"uint256\" }\n    ],\n    \"name\": \"increaseAllowance\",\n    \"outputs\": [{ \"internalType\": \"bool\", \"name\": \"\", \"type\": \"bool\" }],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"name\",\n    \"outputs\": [{ \"internalType\": \"string\", \"name\": \"\", \"type\": \"string\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"redeemedRecoveryAmountForEulerWithdrawal\",\n    \"outputs\": [{ \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"redeemedZenBullAmountForCrabWithdrawal\",\n    \"outputs\": [{ \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"symbol\",\n    \"outputs\": [{ \"internalType\": \"string\", \"name\": \"\", \"type\": \"string\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"totalSupply\",\n    \"outputs\": [{ \"internalType\": \"uint256\", \"name\": \"\", \"type\": \"uint256\" }],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      { \"internalType\": \"address\", \"name\": \"recipient\", \"type\": \"address\" },\n      { \"internalType\": \"uint256\", \"name\": \"amount\", \"type\": \"uint256\" }\n    ],\n    \"name\": \"transfer\",\n    \"outputs\": [{ \"internalType\": \"bool\", \"name\": \"\", \"type\": \"bool\" }],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      { \"internalType\": \"address\", \"name\": \"sender\", \"type\": \"address\" },\n      { \"internalType\": \"address\", \"name\": \"recipient\", \"type\": \"address\" },\n      { \"internalType\": \"uint256\", \"name\": \"amount\", \"type\": \"uint256\" }\n    ],\n    \"name\": \"transferFrom\",\n    \"outputs\": [{ \"internalType\": \"bool\", \"name\": \"\", \"type\": \"bool\" }],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      { \"internalType\": \"int256\", \"name\": \"amount0Delta\", \"type\": \"int256\" },\n      { \"internalType\": \"int256\", \"name\": \"amount1Delta\", \"type\": \"int256\" },\n      { \"internalType\": \"bytes\", \"name\": \"_data\", \"type\": \"bytes\" }\n    ],\n    \"name\": \"uniswapV3SwapCallback\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [{ \"internalType\": \"uint256\", \"name\": \"_recoveryTokenAmount\", \"type\": \"uint256\" }],\n    \"name\": \"withdrawEth\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  { \"stateMutability\": \"payable\", \"type\": \"receive\" }\n]\n"
  },
  {
    "path": "packages/frontend/src/abis/bullShutdownEmergencyWithdraw.json",
    "content": "[\n  {\n    \"type\": \"constructor\",\n    \"inputs\": [\n      {\n        \"name\": \"_crab\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"_zenBull\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"_weth\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"_usdc\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"_wPowerPerp\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"_ethUsdcPool\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"_oracle\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"_zenBullEmergencyWithdraw\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"_controller\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"_owner\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\"\n  },\n  {\n    \"type\": \"receive\",\n    \"stateMutability\": \"payable\"\n  },\n  {\n    \"type\": \"function\",\n    \"name\": \"INDEX_SCALE\",\n    \"inputs\": [],\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"uint256\",\n        \"internalType\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\"\n  },\n  {\n    \"type\": \"function\",\n    \"name\": \"TWAP_PERIOD\",\n    \"inputs\": [],\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"uint32\",\n        \"internalType\": \"uint32\"\n      }\n    ],\n    \"stateMutability\": \"view\"\n  },\n  {\n    \"type\": \"function\",\n    \"name\": \"claimZenBullRedemption\",\n    \"inputs\": [\n      {\n        \"name\": \"_amountToRedeem\",\n        \"type\": \"uint256\",\n        \"internalType\": \"uint256\"\n      }\n    ],\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\"\n  },\n  {\n    \"type\": \"function\",\n    \"name\": \"owner\",\n    \"inputs\": [],\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\"\n  },\n  {\n    \"type\": \"function\",\n    \"name\": \"renounceOwnership\",\n    \"inputs\": [],\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\"\n  },\n  {\n    \"type\": \"function\",\n    \"name\": \"shutdownEmergencyWithdraw\",\n    \"inputs\": [],\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\"\n  },\n  {\n    \"type\": \"function\",\n    \"name\": \"transferOwnership\",\n    \"inputs\": [\n      {\n        \"name\": \"newOwner\",\n        \"type\": \"address\",\n        \"internalType\": \"address\"\n      }\n    ],\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\"\n  },\n  {\n    \"type\": \"function\",\n    \"name\": \"wethAtRedemption\",\n    \"inputs\": [],\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"uint256\",\n        \"internalType\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\"\n  },\n  {\n    \"type\": \"function\",\n    \"name\": \"zenBullTotalSupplyAtRedemption\",\n    \"inputs\": [],\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"uint256\",\n        \"internalType\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\"\n  },\n  {\n    \"type\": \"event\",\n    \"name\": \"OwnershipTransferred\",\n    \"inputs\": [\n      {\n        \"name\": \"previousOwner\",\n        \"type\": \"address\",\n        \"indexed\": true,\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"newOwner\",\n        \"type\": \"address\",\n        \"indexed\": true,\n        \"internalType\": \"address\"\n      }\n    ],\n    \"anonymous\": false\n  },\n  {\n    \"type\": \"event\",\n    \"name\": \"ShutdownEmergencyWithdraw\",\n    \"inputs\": [\n      {\n        \"name\": \"sender\",\n        \"type\": \"address\",\n        \"indexed\": true,\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"crabAmountRedeemed\",\n        \"type\": \"uint256\",\n        \"indexed\": false,\n        \"internalType\": \"uint256\"\n      },\n      {\n        \"name\": \"wPowerPerpRedeemed\",\n        \"type\": \"uint256\",\n        \"indexed\": false,\n        \"internalType\": \"uint256\"\n      },\n      {\n        \"name\": \"totalPayout\",\n        \"type\": \"uint256\",\n        \"indexed\": false,\n        \"internalType\": \"uint256\"\n      },\n      {\n        \"name\": \"ethValueInWPowerPerp\",\n        \"type\": \"uint256\",\n        \"indexed\": false,\n        \"internalType\": \"uint256\"\n      },\n      {\n        \"name\": \"wethAtRedemption\",\n        \"type\": \"uint256\",\n        \"indexed\": false,\n        \"internalType\": \"uint256\"\n      }\n    ],\n    \"anonymous\": false\n  },\n  {\n    \"type\": \"event\",\n    \"name\": \"ZenBullRedeemed\",\n    \"inputs\": [\n      {\n        \"name\": \"sender\",\n        \"type\": \"address\",\n        \"indexed\": true,\n        \"internalType\": \"address\"\n      },\n      {\n        \"name\": \"zenAmountRedeemed\",\n        \"type\": \"uint256\",\n        \"indexed\": false,\n        \"internalType\": \"uint256\"\n      },\n      {\n        \"name\": \"wethReceived\",\n        \"type\": \"uint256\",\n        \"indexed\": false,\n        \"internalType\": \"uint256\"\n      }\n    ],\n    \"anonymous\": false\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/bullStrategy.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_crab\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_powerTokenController\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_euler\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_eulerMarketsModule\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"value\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Approval\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"usdcToRepay\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wethToWithdraw\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"AuctionRepayAndWithdrawFromLeverage\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wethLent\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"usdcBorrowed\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Deposit\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wethDeposited\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"usdcRepaid\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"DepositAndRepayFromLeverage\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"ethToDeposit\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"DepositEthIntoCrab\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"asset\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"receiver\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"Farm\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"previousOwner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"OwnershipTransferred\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabToRedeem\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wPowerPerpRedeemed\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wethBalanceReturned\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"RedeemCrabAndWithdrawEth\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"oldAuction\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"newAuction\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"SetAuction\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"oldCap\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newCap\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetCap\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"oldShutdownContract\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"newShutdownContract\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"SetShutdownContract\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wethToUniswap\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"shareToUnwind\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabToRedeem\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"ShutdownRepayAndWithdraw\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"value\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Transfer\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"bullAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabToRedeem\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wPowerPerpToRedeem\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"usdcToRepay\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wethToWithdraw\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Withdraw\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"withdrawer\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"bullAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"ethToReceive\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"WithdrawShutdown\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"TARGET_CR\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"allowance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"approve\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"auction\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wethToDeposit\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_usdcToRepay\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"auctionDepositAndRepayFromLeverage\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_usdcToRepay\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wethToWithdraw\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"auctionRepayAndWithdrawFromLeverage\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"account\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"balanceOf\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_bullShare\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_ethInCrab\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wPowerPerpInCrab\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_totalCrabSupply\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"calcLeverageEthUsdc\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_bullShare\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"calcUsdcToRepay\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_bullShare\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"calcWethToWithdraw\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"crab\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"decimals\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"\",\n        \"type\": \"uint8\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"subtractedValue\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"decreaseAllowance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_crabAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"deposit\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wethToDeposit\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_usdcToBorrow\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"depositAndBorrowFromLeverage\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_ethToDeposit\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"depositEthIntoCrab\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_asset\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_receiver\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"farm\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"getCrabBalance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"getCrabVaultDetails\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"hasRedeemedInShutdown\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"addedValue\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"increaseAllowance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"name\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"owner\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"powerTokenController\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_crabToRedeem\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wPowerPerpToRedeem\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"redeemCrabAndWithdrawWEth\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"renounceOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_auction\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"setAuction\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_cap\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setCap\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_shutdownContract\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"setShutdownContract\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"shutdownContract\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"wethToUniswap\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"shareToUnwind\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"shutdownRepayAndWithdraw\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"strategyCap\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"symbol\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"totalSupply\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"transfer\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"transferFrom\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"transferOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_bullAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"withdraw\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_bullAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"withdrawShutdown\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"stateMutability\": \"payable\",\n    \"type\": \"receive\"\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/controller.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_oracle\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_shortPowerPerp\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_wPowerPerp\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_weth\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_quoteCurrency\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_ethQuoteCurrencyPool\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_wPowerPerpPool\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_uniPositionManager\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"vaultId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"BurnShort\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"DepositCollateral\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"DepositUniPositionToken\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"oldFee\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newFee\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"FeeRateUpdated\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"oldFeeRecipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"newFeeRecipient\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"FeeRecipientUpdated\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"liquidator\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"debtAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"collateralPaid\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Liquidate\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"vaultId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"MintShort\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"oldNormFactor\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newNormFactor\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"lastModificationTimestamp\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"timestamp\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"NormalizationFactorUpdated\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"vaultId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"OpenVault\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"previousOwner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"OwnershipTransferred\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"pausesLeft\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Paused\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wPowerPerpAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"payoutAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"RedeemLong\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"vauldId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"collateralAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"RedeemShort\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"ethRedeemed\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wPowerPerpRedeemed\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wPowerPerpBurned\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wPowerPerpExcess\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"bounty\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"ReduceDebt\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"indexForSettlement\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Shutdown\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"unpauser\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"UnPaused\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"operator\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"UpdateOperator\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"WithdrawCollateral\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"WithdrawUniPositionToken\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"FUNDING_PERIOD\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"TWAP_PERIOD\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"applyFunding\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_powerPerpAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_withdrawAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"burnPowerPerpAmount\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wPowerPerpAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_withdrawAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"burnWPowerPerpAmount\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"deposit\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_uniTokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"depositUniPositionToken\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"donate\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"ethQuoteCurrencyPool\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"feeRate\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"feeRecipient\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"_period\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"name\": \"getDenormalizedMark\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"_period\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"name\": \"getDenormalizedMarkForFunding\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"getExpectedNormalizationFactor\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"_period\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"name\": \"getIndex\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"_period\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"name\": \"getUnscaledIndex\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"indexForSettlement\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"isShutDown\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"isSystemPaused\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"isVaultSafe\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"lastFundingUpdateTimestamp\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"lastPauseTime\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_maxDebtAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"liquidate\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_powerPerpAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_uniTokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"mintPowerPerpAmount\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wPowerPerpAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_uniTokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"mintWPowerPerpAmount\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"normalizationFactor\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"onERC721Received\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bytes4\",\n        \"name\": \"\",\n        \"type\": \"bytes4\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"oracle\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"owner\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"pause\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"pausesLeft\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"quoteCurrency\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wPerpAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"redeemLong\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"redeemShort\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"reduceDebt\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"reduceDebtShutdown\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"renounceOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_newFeeRate\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setFeeRate\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_newFeeRecipient\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"setFeeRecipient\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"shortPowerPerp\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"shutDown\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"transferOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"unPauseAnyone\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"unPauseOwner\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_operator\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"updateOperator\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"vaults\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"operator\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"NftCollateralId\",\n        \"type\": \"uint32\"\n      },\n      {\n        \"internalType\": \"uint96\",\n        \"name\": \"collateralAmount\",\n        \"type\": \"uint96\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"shortAmount\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"wPowerPerp\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"wPowerPerpPool\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"weth\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"withdraw\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"withdrawUniPositionToken\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"stateMutability\": \"payable\",\n    \"type\": \"receive\"\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/controllerHelper.json",
    "content": "[\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controller\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_nonfungiblePositionManager\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniswapFactory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_exec\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_euler\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_dToken\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"burnExactRemoved\",\n              \"type\": \"bool\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.CloseShortWithUserNftParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"closeShortWithUserNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"dToken\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"euler\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"exec\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToFlashloan\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"burnExactRemoved\",\n              \"type\": \"bool\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashloanCloseVaultLpNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmount\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToFlashloan\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToLp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashloanWMintLpDepositNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToMint\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToSell\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"minToReceive\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashSellLongWMintParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashswapSellLongWMint\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBuy\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"maxToPay\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashswapWBurnBuyLongParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashswapWBurnBuyLong\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"encodedData\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onDeferredLiquidityCheck\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onERC721Received\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_collateralToFlashloan\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"enum ControllerHelperDataType.RebalanceVaultNftType\",\n              \"name\": \"rebalanceLpInVaultType\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"bytes\",\n              \"name\": \"data\",\n              \"type\": \"bytes\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.RebalanceLpInVaultParams[]\",\n          \"name\": \"_params\",\n          \"type\": \"tuple[]\"\n        }\n      ],\n      \"name\": \"rebalanceLpInVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountDesired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wethAmountDesired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0DesiredMin\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1DesiredMin\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.RebalanceLpWithoutVaultParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"rebalanceLpWithoutVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.ReduceLiquidityAndSellParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"reduceLiquidityAndSell\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"token\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmount\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToLp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.MintAndLpParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"wMintLp\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ]"
  },
  {
    "path": "packages/frontend/src/abis/crabHelper.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_crab\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_swapRouter\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"depositor\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"depositedERC20\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"depositedAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"depositedEthAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"returnedEth\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"FlashDepositERC20\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"withdrawer\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"withdrawnERC20\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"withdrawnAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"withdrawnEthAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"FlashWithdrawERC20\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"crab\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_ethToDeposit\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_amountIn\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_minEthToGet\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"_erc20Fee\",\n        \"type\": \"uint24\"\n      },\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"_wPowerPerpFee\",\n        \"type\": \"uint24\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_tokenIn\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"flashDepositERC20\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_maxEthToPay\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_tokenOut\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_minAmountOut\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"_erc20Fee\",\n        \"type\": \"uint24\"\n      },\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"_wPowerPerpFee\",\n        \"type\": \"uint24\"\n      }\n    ],\n    \"name\": \"flashWithdrawERC20\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"swapRouter\",\n    \"outputs\": [\n      {\n        \"internalType\": \"contract ISwapRouter\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"weth\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"stateMutability\": \"payable\",\n    \"type\": \"receive\"\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/crabMigration.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address payable\",\n        \"name\": \"_crabV1\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_weth\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_eulerExec\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_dToken\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_eulerMainnet\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"user\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"ClaimAndWithdraw\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"user\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"ClaimV2Shares\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"user\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabV1Amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"DepositV1Shares\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"user\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabV1Amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabV2Amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"excessEth\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"FlashMigrate\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"previousOwner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"OwnershipTransferred\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"user\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabV1Amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"WithdrawV1Shares\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_strategyCap\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"batchMigrate\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_amountToWithdraw\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_maxEthToPay\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"_poolFee\",\n        \"type\": \"uint24\"\n      }\n    ],\n    \"name\": \"claimAndWithdraw\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"claimV2Shares\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"crabV1\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address payable\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"crabV2\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address payable\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"depositV1Shares\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"euler\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_v1Shares\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_ethToFlashDeposit\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_ethToBorrow\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_withdrawMaxEthToPay\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"_poolFee\",\n        \"type\": \"uint24\"\n      }\n    ],\n    \"name\": \"flashMigrateAndWithdrawFromV1toV2\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_v1Shares\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_ethToFlashDeposit\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"_poolFee\",\n        \"type\": \"uint24\"\n      }\n    ],\n    \"name\": \"flashMigrateFromV1toV2\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_v1Shares\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"flashMigrationDetails\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"isMigrated\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"encodedData\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"onDeferredLiquidityCheck\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"owner\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"renounceOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address payable\",\n        \"name\": \"_crabV2\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"setCrabV2\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"sharesDeposited\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"transferOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"weth\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"withdrawV1Shares\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"stateMutability\": \"payable\",\n    \"type\": \"receive\"\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/crabNetting.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_crab\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_swapRouter\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"bidId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"trader\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"quantity\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"price\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"isBuying\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"BidTraded\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"withdrawer\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"withdrawersBalance\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"CrabDeQueued\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"withdrawer\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"withdrawersBalance\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"receiptIndex\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"CrabQueued\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"withdrawer\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"usdcAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"receiptIndex\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"CrabWithdrawn\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"nonce\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"NonceTrue\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"previousOwner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"OwnershipTransferred\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint32\",\n        \"name\": \"previousTwap\",\n        \"type\": \"uint32\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint32\",\n        \"name\": \"newTwap\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"name\": \"SetAuctionTwapPeriod\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newDepositsIndex\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetDepositsIndex\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetMinCrab\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetMinUSDC\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"previousTolerance\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newOtcPriceTolerance\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetOTCPriceTolerance\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newWithdrawsIndex\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetWithdrawsIndex\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"isAuctionLive\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"ToggledAuctionLive\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"depositor\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"depositorsBalance\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"USDCDeQueued\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"depositor\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"usdcAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"receiptIndex\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"refundedETH\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"USDCDeposited\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"depositor\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"depositorsBalance\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"receiptIndex\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"USDCQueued\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"withdrawer\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"index\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"WithdrawRejected\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"DOMAIN_SEPARATOR\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"MAX_OTC_PRICE_TOLERANCE\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"auctionTwapPeriod\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"bidId\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"trader\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"quantity\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"price\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"bool\",\n            \"name\": \"isBuying\",\n            \"type\": \"bool\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"expiry\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"nonce\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint8\",\n            \"name\": \"v\",\n            \"type\": \"uint8\"\n          },\n          {\n            \"internalType\": \"bytes32\",\n            \"name\": \"r\",\n            \"type\": \"bytes32\"\n          },\n          {\n            \"internalType\": \"bytes32\",\n            \"name\": \"s\",\n            \"type\": \"bytes32\"\n          }\n        ],\n        \"internalType\": \"struct Order\",\n        \"name\": \"_order\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"checkOrder\",\n    \"outputs\": [],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"crab\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"crabBalance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"depositsQueued\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"minEth\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"totalDeposit\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"components\": [\n              {\n                \"internalType\": \"uint256\",\n                \"name\": \"bidId\",\n                \"type\": \"uint256\"\n              },\n              {\n                \"internalType\": \"address\",\n                \"name\": \"trader\",\n                \"type\": \"address\"\n              },\n              {\n                \"internalType\": \"uint256\",\n                \"name\": \"quantity\",\n                \"type\": \"uint256\"\n              },\n              {\n                \"internalType\": \"uint256\",\n                \"name\": \"price\",\n                \"type\": \"uint256\"\n              },\n              {\n                \"internalType\": \"bool\",\n                \"name\": \"isBuying\",\n                \"type\": \"bool\"\n              },\n              {\n                \"internalType\": \"uint256\",\n                \"name\": \"expiry\",\n                \"type\": \"uint256\"\n              },\n              {\n                \"internalType\": \"uint256\",\n                \"name\": \"nonce\",\n                \"type\": \"uint256\"\n              },\n              {\n                \"internalType\": \"uint8\",\n                \"name\": \"v\",\n                \"type\": \"uint8\"\n              },\n              {\n                \"internalType\": \"bytes32\",\n                \"name\": \"r\",\n                \"type\": \"bytes32\"\n              },\n              {\n                \"internalType\": \"bytes32\",\n                \"name\": \"s\",\n                \"type\": \"bytes32\"\n              }\n            ],\n            \"internalType\": \"struct Order[]\",\n            \"name\": \"orders\",\n            \"type\": \"tuple[]\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"clearingPrice\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"ethToFlashDeposit\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"ethUSDFee\",\n            \"type\": \"uint24\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"flashDepositFee\",\n            \"type\": \"uint24\"\n          }\n        ],\n        \"internalType\": \"struct DepositAuctionParams\",\n        \"name\": \"_p\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"depositAuction\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"depositUSDC\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"deposits\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"timestamp\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"depositsIndex\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"depositsQueued\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"_force\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"dequeueCrab\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"ethSqueethPool\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"ethUsdcPool\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"isAuctionLive\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"minCrabAmount\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"minUSDCAmount\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_price\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_quantity\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"netAtPrice\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"nonces\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"oracle\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"otcPriceTolerance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"owner\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"queueCrabForWithdrawal\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"i\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"rejectWithdraw\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"renounceOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"_auctionTwapPeriod\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"name\": \"setAuctionTwapPeriod\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_newDepositsIndex\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setDepositsIndex\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setMinCrab\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setMinUSDC\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_nonce\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setNonceTrue\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_otcPriceTolerance\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setOTCPriceTolerance\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_newWithdrawsIndex\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setWithdrawsIndex\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"sqth\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"sqthController\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"sqthTwapPeriod\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"swapRouter\",\n    \"outputs\": [\n      {\n        \"internalType\": \"contract ISwapRouter\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"toggleAuctionLive\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"transferOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"usdBalance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"usdc\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"userDepositsIndex\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"userWithdrawsIndex\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"weth\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"crabToWithdraw\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"components\": [\n              {\n                \"internalType\": \"uint256\",\n                \"name\": \"bidId\",\n                \"type\": \"uint256\"\n              },\n              {\n                \"internalType\": \"address\",\n                \"name\": \"trader\",\n                \"type\": \"address\"\n              },\n              {\n                \"internalType\": \"uint256\",\n                \"name\": \"quantity\",\n                \"type\": \"uint256\"\n              },\n              {\n                \"internalType\": \"uint256\",\n                \"name\": \"price\",\n                \"type\": \"uint256\"\n              },\n              {\n                \"internalType\": \"bool\",\n                \"name\": \"isBuying\",\n                \"type\": \"bool\"\n              },\n              {\n                \"internalType\": \"uint256\",\n                \"name\": \"expiry\",\n                \"type\": \"uint256\"\n              },\n              {\n                \"internalType\": \"uint256\",\n                \"name\": \"nonce\",\n                \"type\": \"uint256\"\n              },\n              {\n                \"internalType\": \"uint8\",\n                \"name\": \"v\",\n                \"type\": \"uint8\"\n              },\n              {\n                \"internalType\": \"bytes32\",\n                \"name\": \"r\",\n                \"type\": \"bytes32\"\n              },\n              {\n                \"internalType\": \"bytes32\",\n                \"name\": \"s\",\n                \"type\": \"bytes32\"\n              }\n            ],\n            \"internalType\": \"struct Order[]\",\n            \"name\": \"orders\",\n            \"type\": \"tuple[]\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"clearingPrice\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"minUSDC\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"ethUSDFee\",\n            \"type\": \"uint24\"\n          }\n        ],\n        \"internalType\": \"struct WithdrawAuctionParams\",\n        \"name\": \"_p\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"withdrawAuction\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"_force\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"withdrawUSDC\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"withdraws\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"timestamp\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"withdrawsIndex\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"withdrawsQueued\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"stateMutability\": \"payable\",\n    \"type\": \"receive\"\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/crabStrategy.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_wSqueethController\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_oracle\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_weth\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_uniswapFactory\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_ethWSqueethPool\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_hedgeTimeThreshold\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_hedgePriceThreshold\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_auctionTime\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_minPriceMultiplier\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_maxPriceMultiplier\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"value\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Approval\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"depositor\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wSqueethAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"lpAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Deposit\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"seller\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wSqueethBought\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"ethSold\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"isHedgingOnUniswap\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"ExecuteBuyAuction\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"buyer\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wSqueethSold\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"ethBought\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"isHedgingOnUniswap\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"ExecuteSellAuction\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"depositor\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"depositedAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"tradedAmountOut\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"FlashDeposit\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"depositor\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"flashswapDebt\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"excess\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"FlashDepositCallback\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"withdrawer\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wSqueethAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"FlashWithdraw\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"withdrawer\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"flashswapDebt\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"excess\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"FlashWithdrawCallback\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"hedger\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"auctionType\",\n        \"type\": \"bool\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"hedgerPrice\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"auctionPrice\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wSqueethHedgeTargetAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"ethHedgetargetAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Hedge\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"hedger\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"auctionType\",\n        \"type\": \"bool\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"auctionPrice\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wSqueethHedgeTargetAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"ethHedgetargetAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"HedgeOnUniswap\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"previousOwner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"OwnershipTransferred\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"hedger\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"auctionType\",\n        \"type\": \"bool\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"hedgerPrice\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"auctionTriggerTimestamp\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"PriceHedge\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"hedger\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"hedgeTimestamp\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"auctionTriggerTimestamp\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"minWSqueeth\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"minEth\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"PriceHedgeOnUniswap\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newAuctionTime\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetAuctionTime\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newDeltaHedgeThreshold\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetDeltaHedgeThreshold\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newHedgePriceThreshold\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetHedgePriceThreshold\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newHedgeTimeThreshold\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetHedgeTimeThreshold\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint32\",\n        \"name\": \"newHedgingTwapPeriod\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"name\": \"SetHedgingTwapPeriod\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newMaxPriceMultiplier\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetMaxPriceMultiplier\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newMinPriceMultiplier\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetMinPriceMultiplier\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"newCapAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"SetStrategyCap\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"hedger\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"auctionType\",\n        \"type\": \"bool\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"hedgerPrice\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"auctionTriggerTimestamp\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"TimeHedge\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"hedger\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"hedgeTimestamp\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"auctionTriggerTimestamp\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"minWSqueeth\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"minEth\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"TimeHedgeOnUniswap\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"value\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Transfer\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"withdrawer\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wSqueethAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"ethWithdrawn\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Withdraw\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"withdrawer\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"ethWithdrawn\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"WithdrawShutdown\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"POWER_PERP_PERIOD\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"allowance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"approve\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"auctionTime\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"account\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"balanceOf\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_auctionTriggerTime\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"checkPriceHedge\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"checkTimeHedge\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"decimals\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"\",\n        \"type\": \"uint8\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"subtractedValue\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"decreaseAllowance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"deltaHedgeThreshold\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"deposit\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"ethQuoteCurrencyPool\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"ethWSqueethPool\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"factory\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_ethToDeposit\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"flashDeposit\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_maxEthToPay\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"flashWithdraw\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_auctionTriggerTime\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"getAuctionDetails\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"getStrategyVaultId\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"getVaultDetails\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_crabAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"getWsqueethFromCrabAmount\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"hedgePriceThreshold\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"hedgeTimeThreshold\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"hedgingTwapPeriod\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"addedValue\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"increaseAllowance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"maxPriceMultiplier\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"minPriceMultiplier\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"name\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"oracle\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"owner\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"powerTokenController\",\n    \"outputs\": [\n      {\n        \"internalType\": \"contract IController\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"priceAtLastHedge\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_auctionTriggerTime\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"_isStrategySellingWSqueeth\",\n        \"type\": \"bool\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_limitPrice\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"priceHedge\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_auctionTriggerTime\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_minWSqueeth\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_minEth\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"priceHedgeOnUniswap\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"quoteCurrency\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"redeemShortShutdown\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"renounceOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_auctionTime\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setAuctionTime\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_deltaHedgeThreshold\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setDeltaHedgeThreshold\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_hedgePriceThreshold\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setHedgePriceThreshold\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_hedgeTimeThreshold\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setHedgeTimeThreshold\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"_hedgingTwapPeriod\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"name\": \"setHedgingTwapPeriod\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_maxPriceMultiplier\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setMaxPriceMultiplier\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_minPriceMultiplier\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setMinPriceMultiplier\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_capAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"setStrategyCap\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"strategyCap\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"symbol\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"timeAtLastHedge\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"_isStrategySellingWSqueeth\",\n        \"type\": \"bool\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_limitPrice\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"timeHedge\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_minWSqueeth\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_minEth\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"timeHedgeOnUniswap\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"totalSupply\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"transfer\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"transferFrom\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"newOwner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"transferOwnership\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount0Delta\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount1Delta\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"_data\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"uniswapV3SwapCallback\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"vaultId\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"wPowerPerp\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"weth\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_crabAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"withdraw\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_crabAmount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"withdrawShutdown\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"stateMutability\": \"payable\",\n    \"type\": \"receive\"\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/crabStrategyV2.json",
    "content": "[\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wSqueethController\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_oracle\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_weth\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniswapFactory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_ethWSqueethPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_timelock\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_crabMigration\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"lpAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Deposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"depositedAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tradedAmountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDeposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDepositCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdrawCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"bidId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"quantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"clearingPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"HedgeOTC\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"trader\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"bidId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"quantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"price\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"clearingPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"HedgeOTCSingle\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newHedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetHedgePriceThreshold\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newHedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetHedgeTimeThreshold\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint32\",\n          \"name\": \"newHedgingTwapPeriod\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"SetHedgingTwapPeriod\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"otcPriceTolerance\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetOTCPriceTolerance\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newCapAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetStrategyCap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newStrategy\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"VaultTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Withdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawShutdown\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"DOMAIN_SEPARATOR\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"MAX_OTC_PRICE_TOLERANCE\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"POWER_PERP_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"checkPriceHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"checkTimeHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"crabMigration\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"subtractedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"decreaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"deposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"ethWSqueethPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToDeposit\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashDeposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxEthToPay\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashWithdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getStrategyVaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getVaultDetails\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getWsqueethFromCrabAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_totalQuantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_clearingPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_isHedgeBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"bidId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"trader\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"quantity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"price\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"isBuying\",\n              \"type\": \"bool\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"expiry\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"nonce\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint8\",\n              \"name\": \"v\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"bytes32\",\n              \"name\": \"r\",\n              \"type\": \"bytes32\"\n            },\n            {\n              \"internalType\": \"bytes32\",\n              \"name\": \"s\",\n              \"type\": \"bytes32\"\n            }\n          ],\n          \"internalType\": \"struct CrabStrategyV2.Order[]\",\n          \"name\": \"_orders\",\n          \"type\": \"tuple[]\"\n        }\n      ],\n      \"name\": \"hedgeOTC\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgePriceThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgeTimeThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgingTwapPeriod\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"addedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"increaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"incrementNonce\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"current\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wSqueethToMint\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabSharesToMint\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_timeAtLastHedge\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_priceAtLastHedge\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_strategyCap\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"initialize\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isInitialized\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_owner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"nonces\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"oracle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"otcPriceTolerance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"powerTokenController\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IController\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"priceAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"redeemShortShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setHedgePriceThreshold\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setHedgeTimeThreshold\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_hedgingTwapPeriod\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"setHedgingTwapPeriod\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_otcPriceTolerance\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setOTCPriceTolerance\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_capAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setStrategyCap\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"strategyCap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"timeAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"timelock\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_newStrategy\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"vaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdrawShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ]"
  },
  {
    "path": "packages/frontend/src/abis/erc20.json",
    "content": "[\n  {\n    \"constant\": true,\n    \"inputs\": [],\n    \"name\": \"name\",\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": false,\n    \"inputs\": [\n      {\n        \"name\": \"_spender\",\n        \"type\": \"address\"\n      },\n      {\n        \"name\": \"_value\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"approve\",\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": true,\n    \"inputs\": [],\n    \"name\": \"totalSupply\",\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": false,\n    \"inputs\": [\n      {\n        \"name\": \"_from\",\n        \"type\": \"address\"\n      },\n      {\n        \"name\": \"_to\",\n        \"type\": \"address\"\n      },\n      {\n        \"name\": \"_value\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"transferFrom\",\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": true,\n    \"inputs\": [],\n    \"name\": \"decimals\",\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"uint8\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": true,\n    \"inputs\": [\n      {\n        \"name\": \"_owner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"balanceOf\",\n    \"outputs\": [\n      {\n        \"name\": \"balance\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": true,\n    \"inputs\": [],\n    \"name\": \"symbol\",\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": false,\n    \"inputs\": [\n      {\n        \"name\": \"_to\",\n        \"type\": \"address\"\n      },\n      {\n        \"name\": \"_value\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"transfer\",\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": true,\n    \"inputs\": [\n      {\n        \"name\": \"_owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"name\": \"_spender\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"allowance\",\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"payable\": true,\n    \"stateMutability\": \"payable\",\n    \"type\": \"fallback\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"name\": \"spender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"name\": \"value\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Approval\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"name\": \"value\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Transfer\",\n    \"type\": \"event\"\n  }\n]\n"
  },
  {
    "path": "packages/frontend/src/abis/erc721.json",
    "content": "[\n  {\n    \"constant\": false,\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"approve\",\n    \"outputs\": [],\n    \"payable\": false,\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": false,\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"mint\",\n    \"outputs\": [],\n    \"payable\": false,\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": false,\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"safeTransferFrom\",\n    \"outputs\": [],\n    \"payable\": false,\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": false,\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"_data\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"safeTransferFrom\",\n    \"outputs\": [],\n    \"payable\": false,\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": false,\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"approved\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"setApprovalForAll\",\n    \"outputs\": [],\n    \"payable\": false,\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": false,\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"transferFrom\",\n    \"outputs\": [],\n    \"payable\": false,\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"payable\": false,\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Transfer\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"approved\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Approval\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"operator\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"approved\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"ApprovalForAll\",\n    \"type\": \"event\"\n  },\n  {\n    \"constant\": true,\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"balanceOf\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": true,\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"getApproved\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": true,\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"operator\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"isApprovedForAll\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": true,\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"ownerOf\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"constant\": true,\n    \"inputs\": [\n      {\n        \"internalType\": \"bytes4\",\n        \"name\": \"interfaceId\",\n        \"type\": \"bytes4\"\n      }\n    ],\n    \"name\": \"supportsInterface\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"payable\": false,\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/eulerEToken.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"account\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"balanceOf\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"account\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"balanceOfUnderlying\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"subAccountId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"deposit\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"subAccountId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"withdraw\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/eulerSimpleLens.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"moduleGitCommit_\",\n        \"type\": \"bytes32\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"euler_\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"euler\",\n    \"outputs\": [\n      {\n        \"internalType\": \"contract Euler\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"exec\",\n    \"outputs\": [\n      {\n        \"internalType\": \"contract Exec\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"account\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"getAccountStatus\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"collateralValue\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"liabilityValue\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"healthScore\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"account\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"getDTokenBalance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"account\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"getETokenBalance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"account\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"getEnteredMarkets\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address[]\",\n        \"name\": \"\",\n        \"type\": \"address[]\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"account\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"getEulerAccountAllowance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"account\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"getPTokenBalance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"getPriceFull\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"twap\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"twapPeriod\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"currPrice\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"getPricingConfig\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint16\",\n        \"name\": \"pricingType\",\n        \"type\": \"uint16\"\n      },\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"pricingParameters\",\n        \"type\": \"uint32\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"pricingForwarded\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"getTokenInfo\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"name\",\n        \"type\": \"string\"\n      },\n      {\n        \"internalType\": \"string\",\n        \"name\": \"symbol\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"getTotalSupplyAndDebts\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"poolSize\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"totalBalances\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"totalBorrows\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"reserveBalance\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"interestAccumulator\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"interestRateModel\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"interestRates\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"borrowSPY\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"borrowAPY\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"supplyAPY\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"irmSettings\",\n    \"outputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"kink\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"baseAPY\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"kinkAPY\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"maxAPY\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"baseSupplyAPY\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"kinkSupplyAPY\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"maxSupplyAPY\",\n            \"type\": \"uint256\"\n          }\n        ],\n        \"internalType\": \"struct EulerSimpleLens.ResponseIRM\",\n        \"name\": \"r\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"markets\",\n    \"outputs\": [\n      {\n        \"internalType\": \"contract Markets\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"moduleGitCommit\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"reserveFee\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"underlyingToAssetConfig\",\n    \"outputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"address\",\n            \"name\": \"eTokenAddress\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"bool\",\n            \"name\": \"borrowIsolated\",\n            \"type\": \"bool\"\n          },\n          {\n            \"internalType\": \"uint32\",\n            \"name\": \"collateralFactor\",\n            \"type\": \"uint32\"\n          },\n          {\n            \"internalType\": \"uint32\",\n            \"name\": \"borrowFactor\",\n            \"type\": \"uint32\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"twapWindow\",\n            \"type\": \"uint24\"\n          }\n        ],\n        \"internalType\": \"struct Storage.AssetConfig\",\n        \"name\": \"config\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"underlyingToDToken\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"dToken\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"underlyingToEToken\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"eToken\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"underlyingToInternalTokens\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"eToken\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"dToken\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"pToken\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"underlying\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"underlyingToPToken\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"pToken\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/flashBullStrategy.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_bull\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_factory\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"crabAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"ethDeposited\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wPowerPerpToMint\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"usdcToBorrow\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wethToLend\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"FlashDeposit\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"bullAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"ethReturned\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"FlashWithdraw\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"bullStrategy\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"ethToCrab\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"minEthFromSqth\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"minEthFromUsdc\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"wPowerPerpPoolFee\",\n            \"type\": \"uint24\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"usdcPoolFee\",\n            \"type\": \"uint24\"\n          }\n        ],\n        \"internalType\": \"struct FlashZen.FlashDepositParams\",\n        \"name\": \"_params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"flashDeposit\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"bullAmount\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"maxEthForWPowerPerp\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"maxEthForUsdc\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"wPowerPerpPoolFee\",\n            \"type\": \"uint24\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"usdcPoolFee\",\n            \"type\": \"uint24\"\n          }\n        ],\n        \"internalType\": \"struct FlashZen.FlashWithdrawParams\",\n        \"name\": \"_params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"flashWithdraw\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount0Delta\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount1Delta\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"_data\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"uniswapV3SwapCallback\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"stateMutability\": \"payable\",\n    \"type\": \"receive\"\n  }\n]"
  },
  {
    "path": "packages/frontend/src/abis/oracle.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_pool\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_base\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_quote\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"_secondsAgoToStartOfTwap\",\n        \"type\": \"uint32\"\n      },\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"_secondsAgoToEndOfTwap\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"name\": \"getHistoricalTwap\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_pool\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"getMaxPeriod\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_pool\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"_period\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"name\": \"getTimeWeightedAverageTickSafe\",\n    \"outputs\": [\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"timeWeightedAverageTick\",\n        \"type\": \"int24\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_pool\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_base\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_quote\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"_period\",\n        \"type\": \"uint32\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"_checkPeriod\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"getTwap\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  }\n]\n"
  },
  {
    "path": "packages/frontend/src/abis/quoter.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_factory\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_WETH9\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"WETH9\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"factory\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"path\",\n        \"type\": \"bytes\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountIn\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"quoteExactInput\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountOut\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint160[]\",\n        \"name\": \"sqrtPriceX96AfterList\",\n        \"type\": \"uint160[]\"\n      },\n      {\n        \"internalType\": \"uint32[]\",\n        \"name\": \"initializedTicksCrossedList\",\n        \"type\": \"uint32[]\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"gasEstimate\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenIn\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenOut\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountIn\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"fee\",\n            \"type\": \"uint24\"\n          },\n          {\n            \"internalType\": \"uint160\",\n            \"name\": \"sqrtPriceLimitX96\",\n            \"type\": \"uint160\"\n          }\n        ],\n        \"internalType\": \"struct IQuoterV2.QuoteExactInputSingleParams\",\n        \"name\": \"params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"quoteExactInputSingle\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountOut\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint160\",\n        \"name\": \"sqrtPriceX96After\",\n        \"type\": \"uint160\"\n      },\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"initializedTicksCrossed\",\n        \"type\": \"uint32\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"gasEstimate\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"path\",\n        \"type\": \"bytes\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountOut\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"quoteExactOutput\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountIn\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint160[]\",\n        \"name\": \"sqrtPriceX96AfterList\",\n        \"type\": \"uint160[]\"\n      },\n      {\n        \"internalType\": \"uint32[]\",\n        \"name\": \"initializedTicksCrossedList\",\n        \"type\": \"uint32[]\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"gasEstimate\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenIn\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenOut\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amount\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"fee\",\n            \"type\": \"uint24\"\n          },\n          {\n            \"internalType\": \"uint160\",\n            \"name\": \"sqrtPriceLimitX96\",\n            \"type\": \"uint160\"\n          }\n        ],\n        \"internalType\": \"struct IQuoterV2.QuoteExactOutputSingleParams\",\n        \"name\": \"params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"quoteExactOutputSingle\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountIn\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint160\",\n        \"name\": \"sqrtPriceX96After\",\n        \"type\": \"uint160\"\n      },\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"initializedTicksCrossed\",\n        \"type\": \"uint32\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"gasEstimate\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount0Delta\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount1Delta\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"path\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"uniswapV3SwapCallback\",\n    \"outputs\": [],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  }\n]\n"
  },
  {
    "path": "packages/frontend/src/abis/shortHelper.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_controllerAddr\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_swapRouter\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_wethAddr\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_wPowerPerpAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_withdrawAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"components\": [\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenIn\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenOut\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"fee\",\n            \"type\": \"uint24\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"recipient\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"deadline\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountOut\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountInMaximum\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint160\",\n            \"name\": \"sqrtPriceLimitX96\",\n            \"type\": \"uint160\"\n          }\n        ],\n        \"internalType\": \"struct ISwapRouter.ExactOutputSingleParams\",\n        \"name\": \"_exactOutputParams\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"closeShort\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"controller\",\n    \"outputs\": [\n      {\n        \"internalType\": \"contract IController\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"onERC721Received\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bytes4\",\n        \"name\": \"\",\n        \"type\": \"bytes4\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_vaultId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_powerPerpAmount\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"_uniNftId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"components\": [\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenIn\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenOut\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"fee\",\n            \"type\": \"uint24\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"recipient\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"deadline\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountIn\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountOutMinimum\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint160\",\n            \"name\": \"sqrtPriceLimitX96\",\n            \"type\": \"uint160\"\n          }\n        ],\n        \"internalType\": \"struct ISwapRouter.ExactInputSingleParams\",\n        \"name\": \"_exactInputParams\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"openShort\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"router\",\n    \"outputs\": [\n      {\n        \"internalType\": \"contract ISwapRouter\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"shortPowerPerp\",\n    \"outputs\": [\n      {\n        \"internalType\": \"contract IShortPowerPerp\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"wPowerPerp\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"weth\",\n    \"outputs\": [\n      {\n        \"internalType\": \"contract IWETH9\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"stateMutability\": \"payable\",\n    \"type\": \"receive\"\n  }\n]\n"
  },
  {
    "path": "packages/frontend/src/abis/squeeth.json",
    "content": "[\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"string\",\n                \"name\": \"_name\",\n                \"type\": \"string\"\n            },\n            {\n                \"internalType\": \"string\",\n                \"name\": \"_symbol\",\n                \"type\": \"string\"\n            }\n        ],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"constructor\"\n    },\n    {\n        \"anonymous\": false,\n        \"inputs\": [\n            {\n                \"indexed\": true,\n                \"internalType\": \"address\",\n                \"name\": \"owner\",\n                \"type\": \"address\"\n            },\n            {\n                \"indexed\": true,\n                \"internalType\": \"address\",\n                \"name\": \"spender\",\n                \"type\": \"address\"\n            },\n            {\n                \"indexed\": false,\n                \"internalType\": \"uint256\",\n                \"name\": \"value\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"Approval\",\n        \"type\": \"event\"\n    },\n    {\n        \"anonymous\": false,\n        \"inputs\": [\n            {\n                \"indexed\": true,\n                \"internalType\": \"address\",\n                \"name\": \"from\",\n                \"type\": \"address\"\n            },\n            {\n                \"indexed\": true,\n                \"internalType\": \"address\",\n                \"name\": \"to\",\n                \"type\": \"address\"\n            },\n            {\n                \"indexed\": false,\n                \"internalType\": \"uint256\",\n                \"name\": \"value\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"Transfer\",\n        \"type\": \"event\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"owner\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"spender\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"allowance\",\n        \"outputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"spender\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amount\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"approve\",\n        \"outputs\": [\n            {\n                \"internalType\": \"bool\",\n                \"name\": \"\",\n                \"type\": \"bool\"\n            }\n        ],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"account\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"balanceOf\",\n        \"outputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"_account\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"_amount\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"burn\",\n        \"outputs\": [],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [],\n        \"name\": \"controller\",\n        \"outputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"\",\n                \"type\": \"address\"\n            }\n        ],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [],\n        \"name\": \"decimals\",\n        \"outputs\": [\n            {\n                \"internalType\": \"uint8\",\n                \"name\": \"\",\n                \"type\": \"uint8\"\n            }\n        ],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"spender\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"subtractedValue\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"decreaseAllowance\",\n        \"outputs\": [\n            {\n                \"internalType\": \"bool\",\n                \"name\": \"\",\n                \"type\": \"bool\"\n            }\n        ],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"spender\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"addedValue\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"increaseAllowance\",\n        \"outputs\": [\n            {\n                \"internalType\": \"bool\",\n                \"name\": \"\",\n                \"type\": \"bool\"\n            }\n        ],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"_controller\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"init\",\n        \"outputs\": [],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"_account\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"_amount\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"mint\",\n        \"outputs\": [],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [],\n        \"name\": \"name\",\n        \"outputs\": [\n            {\n                \"internalType\": \"string\",\n                \"name\": \"\",\n                \"type\": \"string\"\n            }\n        ],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [],\n        \"name\": \"symbol\",\n        \"outputs\": [\n            {\n                \"internalType\": \"string\",\n                \"name\": \"\",\n                \"type\": \"string\"\n            }\n        ],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [],\n        \"name\": \"totalSupply\",\n        \"outputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"recipient\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amount\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"transfer\",\n        \"outputs\": [\n            {\n                \"internalType\": \"bool\",\n                \"name\": \"\",\n                \"type\": \"bool\"\n            }\n        ],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"sender\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"recipient\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amount\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"transferFrom\",\n        \"outputs\": [\n            {\n                \"internalType\": \"bool\",\n                \"name\": \"\",\n                \"type\": \"bool\"\n            }\n        ],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    }\n]"
  },
  {
    "path": "packages/frontend/src/abis/swapRouter.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_factory\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_WETH9\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"WETH9\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"bytes\",\n            \"name\": \"path\",\n            \"type\": \"bytes\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"recipient\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"deadline\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountIn\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountOutMinimum\",\n            \"type\": \"uint256\"\n          }\n        ],\n        \"internalType\": \"struct ISwapRouter.ExactInputParams\",\n        \"name\": \"params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"exactInput\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountOut\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenIn\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenOut\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"fee\",\n            \"type\": \"uint24\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"recipient\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"deadline\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountIn\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountOutMinimum\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint160\",\n            \"name\": \"sqrtPriceLimitX96\",\n            \"type\": \"uint160\"\n          }\n        ],\n        \"internalType\": \"struct ISwapRouter.ExactInputSingleParams\",\n        \"name\": \"params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"exactInputSingle\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountOut\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"bytes\",\n            \"name\": \"path\",\n            \"type\": \"bytes\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"recipient\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"deadline\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountOut\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountInMaximum\",\n            \"type\": \"uint256\"\n          }\n        ],\n        \"internalType\": \"struct ISwapRouter.ExactOutputParams\",\n        \"name\": \"params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"exactOutput\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountIn\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"components\": [\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenIn\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"tokenOut\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint24\",\n            \"name\": \"fee\",\n            \"type\": \"uint24\"\n          },\n          {\n            \"internalType\": \"address\",\n            \"name\": \"recipient\",\n            \"type\": \"address\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"deadline\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountOut\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint256\",\n            \"name\": \"amountInMaximum\",\n            \"type\": \"uint256\"\n          },\n          {\n            \"internalType\": \"uint160\",\n            \"name\": \"sqrtPriceLimitX96\",\n            \"type\": \"uint160\"\n          }\n        ],\n        \"internalType\": \"struct ISwapRouter.ExactOutputSingleParams\",\n        \"name\": \"params\",\n        \"type\": \"tuple\"\n      }\n    ],\n    \"name\": \"exactOutputSingle\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountIn\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"factory\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"bytes[]\",\n        \"name\": \"data\",\n        \"type\": \"bytes[]\"\n      }\n    ],\n    \"name\": \"multicall\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bytes[]\",\n        \"name\": \"results\",\n        \"type\": \"bytes[]\"\n      }\n    ],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"refundETH\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"value\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"deadline\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"v\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"r\",\n        \"type\": \"bytes32\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"s\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"name\": \"selfPermit\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"nonce\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"expiry\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"v\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"r\",\n        \"type\": \"bytes32\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"s\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"name\": \"selfPermitAllowed\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"nonce\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"expiry\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"v\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"r\",\n        \"type\": \"bytes32\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"s\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"name\": \"selfPermitAllowedIfNecessary\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"value\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"deadline\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"v\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"r\",\n        \"type\": \"bytes32\"\n      },\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"s\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"name\": \"selfPermitIfNecessary\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountMinimum\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"sweepToken\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"token\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountMinimum\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"feeBips\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"feeRecipient\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"sweepTokenWithFee\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount0Delta\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount1Delta\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"_data\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"uniswapV3SwapCallback\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountMinimum\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"unwrapWETH9\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amountMinimum\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"feeBips\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"feeRecipient\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"unwrapWETH9WithFee\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"stateMutability\": \"payable\",\n    \"type\": \"receive\"\n  }\n]\n"
  },
  {
    "path": "packages/frontend/src/abis/swapRouter2.json",
    "content": "[\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"_factoryV2\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"factoryV3\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"_positionManager\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"_WETH9\",\n                \"type\": \"address\"\n            }\n        ],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"constructor\"\n    },\n    {\n        \"inputs\": [],\n        \"name\": \"WETH9\",\n        \"outputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"\",\n                \"type\": \"address\"\n            }\n        ],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"approveMax\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"approveMaxMinusOne\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"approveZeroThenMax\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"approveZeroThenMaxMinusOne\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"bytes\",\n                \"name\": \"data\",\n                \"type\": \"bytes\"\n            }\n        ],\n        \"name\": \"callPositionManager\",\n        \"outputs\": [\n            {\n                \"internalType\": \"bytes\",\n                \"name\": \"result\",\n                \"type\": \"bytes\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"bytes[]\",\n                \"name\": \"paths\",\n                \"type\": \"bytes[]\"\n            },\n            {\n                \"internalType\": \"uint128[]\",\n                \"name\": \"amounts\",\n                \"type\": \"uint128[]\"\n            },\n            {\n                \"internalType\": \"uint24\",\n                \"name\": \"maximumTickDivergence\",\n                \"type\": \"uint24\"\n            },\n            {\n                \"internalType\": \"uint32\",\n                \"name\": \"secondsAgo\",\n                \"type\": \"uint32\"\n            }\n        ],\n        \"name\": \"checkOracleSlippage\",\n        \"outputs\": [],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"bytes\",\n                \"name\": \"path\",\n                \"type\": \"bytes\"\n            },\n            {\n                \"internalType\": \"uint24\",\n                \"name\": \"maximumTickDivergence\",\n                \"type\": \"uint24\"\n            },\n            {\n                \"internalType\": \"uint32\",\n                \"name\": \"secondsAgo\",\n                \"type\": \"uint32\"\n            }\n        ],\n        \"name\": \"checkOracleSlippage\",\n        \"outputs\": [],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"components\": [\n                    {\n                        \"internalType\": \"bytes\",\n                        \"name\": \"path\",\n                        \"type\": \"bytes\"\n                    },\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"recipient\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amountIn\",\n                        \"type\": \"uint256\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amountOutMinimum\",\n                        \"type\": \"uint256\"\n                    }\n                ],\n                \"internalType\": \"struct IV3SwapRouter.ExactInputParams\",\n                \"name\": \"params\",\n                \"type\": \"tuple\"\n            }\n        ],\n        \"name\": \"exactInput\",\n        \"outputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountOut\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"components\": [\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"tokenIn\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"tokenOut\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"uint24\",\n                        \"name\": \"fee\",\n                        \"type\": \"uint24\"\n                    },\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"recipient\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amountIn\",\n                        \"type\": \"uint256\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amountOutMinimum\",\n                        \"type\": \"uint256\"\n                    },\n                    {\n                        \"internalType\": \"uint160\",\n                        \"name\": \"sqrtPriceLimitX96\",\n                        \"type\": \"uint160\"\n                    }\n                ],\n                \"internalType\": \"struct IV3SwapRouter.ExactInputSingleParams\",\n                \"name\": \"params\",\n                \"type\": \"tuple\"\n            }\n        ],\n        \"name\": \"exactInputSingle\",\n        \"outputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountOut\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"components\": [\n                    {\n                        \"internalType\": \"bytes\",\n                        \"name\": \"path\",\n                        \"type\": \"bytes\"\n                    },\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"recipient\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amountOut\",\n                        \"type\": \"uint256\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amountInMaximum\",\n                        \"type\": \"uint256\"\n                    }\n                ],\n                \"internalType\": \"struct IV3SwapRouter.ExactOutputParams\",\n                \"name\": \"params\",\n                \"type\": \"tuple\"\n            }\n        ],\n        \"name\": \"exactOutput\",\n        \"outputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountIn\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"components\": [\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"tokenIn\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"tokenOut\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"uint24\",\n                        \"name\": \"fee\",\n                        \"type\": \"uint24\"\n                    },\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"recipient\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amountOut\",\n                        \"type\": \"uint256\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amountInMaximum\",\n                        \"type\": \"uint256\"\n                    },\n                    {\n                        \"internalType\": \"uint160\",\n                        \"name\": \"sqrtPriceLimitX96\",\n                        \"type\": \"uint160\"\n                    }\n                ],\n                \"internalType\": \"struct IV3SwapRouter.ExactOutputSingleParams\",\n                \"name\": \"params\",\n                \"type\": \"tuple\"\n            }\n        ],\n        \"name\": \"exactOutputSingle\",\n        \"outputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountIn\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [],\n        \"name\": \"factory\",\n        \"outputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"\",\n                \"type\": \"address\"\n            }\n        ],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [],\n        \"name\": \"factoryV2\",\n        \"outputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"\",\n                \"type\": \"address\"\n            }\n        ],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amount\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"getApprovalType\",\n        \"outputs\": [\n            {\n                \"internalType\": \"enum IApproveAndCall.ApprovalType\",\n                \"name\": \"\",\n                \"type\": \"uint8\"\n            }\n        ],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"components\": [\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"token0\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"token1\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"tokenId\",\n                        \"type\": \"uint256\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amount0Min\",\n                        \"type\": \"uint256\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amount1Min\",\n                        \"type\": \"uint256\"\n                    }\n                ],\n                \"internalType\": \"struct IApproveAndCall.IncreaseLiquidityParams\",\n                \"name\": \"params\",\n                \"type\": \"tuple\"\n            }\n        ],\n        \"name\": \"increaseLiquidity\",\n        \"outputs\": [\n            {\n                \"internalType\": \"bytes\",\n                \"name\": \"result\",\n                \"type\": \"bytes\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"components\": [\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"token0\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"token1\",\n                        \"type\": \"address\"\n                    },\n                    {\n                        \"internalType\": \"uint24\",\n                        \"name\": \"fee\",\n                        \"type\": \"uint24\"\n                    },\n                    {\n                        \"internalType\": \"int24\",\n                        \"name\": \"tickLower\",\n                        \"type\": \"int24\"\n                    },\n                    {\n                        \"internalType\": \"int24\",\n                        \"name\": \"tickUpper\",\n                        \"type\": \"int24\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amount0Min\",\n                        \"type\": \"uint256\"\n                    },\n                    {\n                        \"internalType\": \"uint256\",\n                        \"name\": \"amount1Min\",\n                        \"type\": \"uint256\"\n                    },\n                    {\n                        \"internalType\": \"address\",\n                        \"name\": \"recipient\",\n                        \"type\": \"address\"\n                    }\n                ],\n                \"internalType\": \"struct IApproveAndCall.MintParams\",\n                \"name\": \"params\",\n                \"type\": \"tuple\"\n            }\n        ],\n        \"name\": \"mint\",\n        \"outputs\": [\n            {\n                \"internalType\": \"bytes\",\n                \"name\": \"result\",\n                \"type\": \"bytes\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"bytes32\",\n                \"name\": \"previousBlockhash\",\n                \"type\": \"bytes32\"\n            },\n            {\n                \"internalType\": \"bytes[]\",\n                \"name\": \"data\",\n                \"type\": \"bytes[]\"\n            }\n        ],\n        \"name\": \"multicall\",\n        \"outputs\": [\n            {\n                \"internalType\": \"bytes[]\",\n                \"name\": \"\",\n                \"type\": \"bytes[]\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"deadline\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"bytes[]\",\n                \"name\": \"data\",\n                \"type\": \"bytes[]\"\n            }\n        ],\n        \"name\": \"multicall\",\n        \"outputs\": [\n            {\n                \"internalType\": \"bytes[]\",\n                \"name\": \"\",\n                \"type\": \"bytes[]\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"bytes[]\",\n                \"name\": \"data\",\n                \"type\": \"bytes[]\"\n            }\n        ],\n        \"name\": \"multicall\",\n        \"outputs\": [\n            {\n                \"internalType\": \"bytes[]\",\n                \"name\": \"results\",\n                \"type\": \"bytes[]\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [],\n        \"name\": \"positionManager\",\n        \"outputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"\",\n                \"type\": \"address\"\n            }\n        ],\n        \"stateMutability\": \"view\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"value\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"pull\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [],\n        \"name\": \"refundETH\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"value\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"deadline\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint8\",\n                \"name\": \"v\",\n                \"type\": \"uint8\"\n            },\n            {\n                \"internalType\": \"bytes32\",\n                \"name\": \"r\",\n                \"type\": \"bytes32\"\n            },\n            {\n                \"internalType\": \"bytes32\",\n                \"name\": \"s\",\n                \"type\": \"bytes32\"\n            }\n        ],\n        \"name\": \"selfPermit\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"nonce\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"expiry\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint8\",\n                \"name\": \"v\",\n                \"type\": \"uint8\"\n            },\n            {\n                \"internalType\": \"bytes32\",\n                \"name\": \"r\",\n                \"type\": \"bytes32\"\n            },\n            {\n                \"internalType\": \"bytes32\",\n                \"name\": \"s\",\n                \"type\": \"bytes32\"\n            }\n        ],\n        \"name\": \"selfPermitAllowed\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"nonce\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"expiry\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint8\",\n                \"name\": \"v\",\n                \"type\": \"uint8\"\n            },\n            {\n                \"internalType\": \"bytes32\",\n                \"name\": \"r\",\n                \"type\": \"bytes32\"\n            },\n            {\n                \"internalType\": \"bytes32\",\n                \"name\": \"s\",\n                \"type\": \"bytes32\"\n            }\n        ],\n        \"name\": \"selfPermitAllowedIfNecessary\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"value\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"deadline\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint8\",\n                \"name\": \"v\",\n                \"type\": \"uint8\"\n            },\n            {\n                \"internalType\": \"bytes32\",\n                \"name\": \"r\",\n                \"type\": \"bytes32\"\n            },\n            {\n                \"internalType\": \"bytes32\",\n                \"name\": \"s\",\n                \"type\": \"bytes32\"\n            }\n        ],\n        \"name\": \"selfPermitIfNecessary\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountIn\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountOutMin\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"address[]\",\n                \"name\": \"path\",\n                \"type\": \"address[]\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"to\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"swapExactTokensForTokens\",\n        \"outputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountOut\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountOut\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountInMax\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"address[]\",\n                \"name\": \"path\",\n                \"type\": \"address[]\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"to\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"swapTokensForExactTokens\",\n        \"outputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountIn\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountMinimum\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"recipient\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"sweepToken\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountMinimum\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"sweepToken\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountMinimum\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"feeBips\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"feeRecipient\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"sweepTokenWithFee\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"address\",\n                \"name\": \"token\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountMinimum\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"recipient\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"feeBips\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"feeRecipient\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"sweepTokenWithFee\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"int256\",\n                \"name\": \"amount0Delta\",\n                \"type\": \"int256\"\n            },\n            {\n                \"internalType\": \"int256\",\n                \"name\": \"amount1Delta\",\n                \"type\": \"int256\"\n            },\n            {\n                \"internalType\": \"bytes\",\n                \"name\": \"_data\",\n                \"type\": \"bytes\"\n            }\n        ],\n        \"name\": \"uniswapV3SwapCallback\",\n        \"outputs\": [],\n        \"stateMutability\": \"nonpayable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountMinimum\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"recipient\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"unwrapWETH9\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountMinimum\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"unwrapWETH9\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountMinimum\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"recipient\",\n                \"type\": \"address\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"feeBips\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"feeRecipient\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"unwrapWETH9WithFee\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"amountMinimum\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"feeBips\",\n                \"type\": \"uint256\"\n            },\n            {\n                \"internalType\": \"address\",\n                \"name\": \"feeRecipient\",\n                \"type\": \"address\"\n            }\n        ],\n        \"name\": \"unwrapWETH9WithFee\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"inputs\": [\n            {\n                \"internalType\": \"uint256\",\n                \"name\": \"value\",\n                \"type\": \"uint256\"\n            }\n        ],\n        \"name\": \"wrapETH\",\n        \"outputs\": [],\n        \"stateMutability\": \"payable\",\n        \"type\": \"function\"\n    },\n    {\n        \"stateMutability\": \"payable\",\n        \"type\": \"receive\"\n    }\n]"
  },
  {
    "path": "packages/frontend/src/abis/uniswapPool.json",
    "content": "[\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"int24\",\n        \"name\": \"tickLower\",\n        \"type\": \"int24\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"int24\",\n        \"name\": \"tickUpper\",\n        \"type\": \"int24\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint128\",\n        \"name\": \"amount\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Burn\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"int24\",\n        \"name\": \"tickLower\",\n        \"type\": \"int24\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"int24\",\n        \"name\": \"tickUpper\",\n        \"type\": \"int24\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint128\",\n        \"name\": \"amount0\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint128\",\n        \"name\": \"amount1\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"name\": \"Collect\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint128\",\n        \"name\": \"amount0\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint128\",\n        \"name\": \"amount1\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"name\": \"CollectProtocol\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"paid0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"paid1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Flash\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint16\",\n        \"name\": \"observationCardinalityNextOld\",\n        \"type\": \"uint16\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint16\",\n        \"name\": \"observationCardinalityNextNew\",\n        \"type\": \"uint16\"\n      }\n    ],\n    \"name\": \"IncreaseObservationCardinalityNext\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint160\",\n        \"name\": \"sqrtPriceX96\",\n        \"type\": \"uint160\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"int24\",\n        \"name\": \"tick\",\n        \"type\": \"int24\"\n      }\n    ],\n    \"name\": \"Initialize\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"int24\",\n        \"name\": \"tickLower\",\n        \"type\": \"int24\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"int24\",\n        \"name\": \"tickUpper\",\n        \"type\": \"int24\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint128\",\n        \"name\": \"amount\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Mint\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint8\",\n        \"name\": \"feeProtocol0Old\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint8\",\n        \"name\": \"feeProtocol1Old\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint8\",\n        \"name\": \"feeProtocol0New\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint8\",\n        \"name\": \"feeProtocol1New\",\n        \"type\": \"uint8\"\n      }\n    ],\n    \"name\": \"SetFeeProtocol\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"sender\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"int256\",\n        \"name\": \"amount0\",\n        \"type\": \"int256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"int256\",\n        \"name\": \"amount1\",\n        \"type\": \"int256\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint160\",\n        \"name\": \"sqrtPriceX96\",\n        \"type\": \"uint160\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint128\",\n        \"name\": \"liquidity\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"int24\",\n        \"name\": \"tick\",\n        \"type\": \"int24\"\n      }\n    ],\n    \"name\": \"Swap\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tickLower\",\n        \"type\": \"int24\"\n      },\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tickUpper\",\n        \"type\": \"int24\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"amount\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"name\": \"burn\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tickLower\",\n        \"type\": \"int24\"\n      },\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tickUpper\",\n        \"type\": \"int24\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"amount0Requested\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"amount1Requested\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"name\": \"collect\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"amount0\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"amount1\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"amount0Requested\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"amount1Requested\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"name\": \"collectProtocol\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"amount0\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"amount1\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"factory\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"fee\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint24\",\n        \"name\": \"\",\n        \"type\": \"uint24\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"feeGrowthGlobal0X128\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"feeGrowthGlobal1X128\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"data\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"flash\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint16\",\n        \"name\": \"observationCardinalityNext\",\n        \"type\": \"uint16\"\n      }\n    ],\n    \"name\": \"increaseObservationCardinalityNext\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint160\",\n        \"name\": \"sqrtPriceX96\",\n        \"type\": \"uint160\"\n      }\n    ],\n    \"name\": \"initialize\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"liquidity\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"maxLiquidityPerTick\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tickLower\",\n        \"type\": \"int24\"\n      },\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tickUpper\",\n        \"type\": \"int24\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"amount\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"data\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"mint\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount0\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"amount1\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"index\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"observations\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"blockTimestamp\",\n        \"type\": \"uint32\"\n      },\n      {\n        \"internalType\": \"int56\",\n        \"name\": \"tickCumulative\",\n        \"type\": \"int56\"\n      },\n      {\n        \"internalType\": \"uint160\",\n        \"name\": \"secondsPerLiquidityCumulativeX128\",\n        \"type\": \"uint160\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"initialized\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint32[]\",\n        \"name\": \"secondsAgos\",\n        \"type\": \"uint32[]\"\n      }\n    ],\n    \"name\": \"observe\",\n    \"outputs\": [\n      {\n        \"internalType\": \"int56[]\",\n        \"name\": \"tickCumulatives\",\n        \"type\": \"int56[]\"\n      },\n      {\n        \"internalType\": \"uint160[]\",\n        \"name\": \"secondsPerLiquidityCumulativeX128s\",\n        \"type\": \"uint160[]\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"bytes32\",\n        \"name\": \"key\",\n        \"type\": \"bytes32\"\n      }\n    ],\n    \"name\": \"positions\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"_liquidity\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"feeGrowthInside0LastX128\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"feeGrowthInside1LastX128\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"tokensOwed0\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"tokensOwed1\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"protocolFees\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"token0\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"token1\",\n        \"type\": \"uint128\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"feeProtocol0\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"feeProtocol1\",\n        \"type\": \"uint8\"\n      }\n    ],\n    \"name\": \"setFeeProtocol\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"slot0\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint160\",\n        \"name\": \"sqrtPriceX96\",\n        \"type\": \"uint160\"\n      },\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tick\",\n        \"type\": \"int24\"\n      },\n      {\n        \"internalType\": \"uint16\",\n        \"name\": \"observationIndex\",\n        \"type\": \"uint16\"\n      },\n      {\n        \"internalType\": \"uint16\",\n        \"name\": \"observationCardinality\",\n        \"type\": \"uint16\"\n      },\n      {\n        \"internalType\": \"uint16\",\n        \"name\": \"observationCardinalityNext\",\n        \"type\": \"uint16\"\n      },\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"feeProtocol\",\n        \"type\": \"uint8\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"unlocked\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tickLower\",\n        \"type\": \"int24\"\n      },\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tickUpper\",\n        \"type\": \"int24\"\n      }\n    ],\n    \"name\": \"snapshotCumulativesInside\",\n    \"outputs\": [\n      {\n        \"internalType\": \"int56\",\n        \"name\": \"tickCumulativeInside\",\n        \"type\": \"int56\"\n      },\n      {\n        \"internalType\": \"uint160\",\n        \"name\": \"secondsPerLiquidityInsideX128\",\n        \"type\": \"uint160\"\n      },\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"secondsInside\",\n        \"type\": \"uint32\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"recipient\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"zeroForOne\",\n        \"type\": \"bool\"\n      },\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amountSpecified\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"uint160\",\n        \"name\": \"sqrtPriceLimitX96\",\n        \"type\": \"uint160\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"data\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"swap\",\n    \"outputs\": [\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount0\",\n        \"type\": \"int256\"\n      },\n      {\n        \"internalType\": \"int256\",\n        \"name\": \"amount1\",\n        \"type\": \"int256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"int16\",\n        \"name\": \"wordPosition\",\n        \"type\": \"int16\"\n      }\n    ],\n    \"name\": \"tickBitmap\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"tickSpacing\",\n    \"outputs\": [\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"\",\n        \"type\": \"int24\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"int24\",\n        \"name\": \"tick\",\n        \"type\": \"int24\"\n      }\n    ],\n    \"name\": \"ticks\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint128\",\n        \"name\": \"liquidityGross\",\n        \"type\": \"uint128\"\n      },\n      {\n        \"internalType\": \"int128\",\n        \"name\": \"liquidityNet\",\n        \"type\": \"int128\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"feeGrowthOutside0X128\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"feeGrowthOutside1X128\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"int56\",\n        \"name\": \"tickCumulativeOutside\",\n        \"type\": \"int56\"\n      },\n      {\n        \"internalType\": \"uint160\",\n        \"name\": \"secondsPerLiquidityOutsideX128\",\n        \"type\": \"uint160\"\n      },\n      {\n        \"internalType\": \"uint32\",\n        \"name\": \"secondsOutside\",\n        \"type\": \"uint32\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"initialized\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"token0\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"token1\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  }\n]\n"
  },
  {
    "path": "packages/frontend/src/abis/vaultManager.json",
    "content": "[\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"_name\",\n        \"type\": \"string\"\n      },\n      {\n        \"internalType\": \"string\",\n        \"name\": \"_symbol\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"constructor\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"approved\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Approval\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"operator\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"bool\",\n        \"name\": \"approved\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"ApprovalForAll\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Transfer\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"approve\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"balanceOf\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"baseURI\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"controller\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"getApproved\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_controller\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"init\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"operator\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"isApprovedForAll\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"_recipient\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"mintNFT\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"name\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"nextId\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"ownerOf\",\n    \"outputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"safeTransferFrom\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      },\n      {\n        \"internalType\": \"bytes\",\n        \"name\": \"_data\",\n        \"type\": \"bytes\"\n      }\n    ],\n    \"name\": \"safeTransferFrom\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"operator\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"approved\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"name\": \"setApprovalForAll\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"bytes4\",\n        \"name\": \"interfaceId\",\n        \"type\": \"bytes4\"\n      }\n    ],\n    \"name\": \"supportsInterface\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"symbol\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"index\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"tokenByIndex\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"owner\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"index\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"tokenOfOwnerByIndex\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"tokenURI\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"totalSupply\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"from\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"to\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"tokenId\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"transferFrom\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  }\n]\n"
  },
  {
    "path": "packages/frontend/src/abis/weth.json",
    "content": "[\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"src\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"guy\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wad\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Approval\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"dst\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wad\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Deposit\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"src\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"dst\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wad\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Transfer\",\n    \"type\": \"event\"\n  },\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\n        \"indexed\": true,\n        \"internalType\": \"address\",\n        \"name\": \"src\",\n        \"type\": \"address\"\n      },\n      {\n        \"indexed\": false,\n        \"internalType\": \"uint256\",\n        \"name\": \"wad\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"Withdrawal\",\n    \"type\": \"event\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"allowance\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"guy\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"wad\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"approve\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"\",\n        \"type\": \"address\"\n      }\n    ],\n    \"name\": \"balanceOf\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"decimals\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint8\",\n        \"name\": \"\",\n        \"type\": \"uint8\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"deposit\",\n    \"outputs\": [],\n    \"stateMutability\": \"payable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"name\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"symbol\",\n    \"outputs\": [\n      {\n        \"internalType\": \"string\",\n        \"name\": \"\",\n        \"type\": \"string\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [],\n    \"name\": \"totalSupply\",\n    \"outputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"stateMutability\": \"view\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"dst\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"wad\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"transfer\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"address\",\n        \"name\": \"src\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"address\",\n        \"name\": \"dst\",\n        \"type\": \"address\"\n      },\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"wad\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"transferFrom\",\n    \"outputs\": [\n      {\n        \"internalType\": \"bool\",\n        \"name\": \"\",\n        \"type\": \"bool\"\n      }\n    ],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  },\n  {\n    \"inputs\": [\n      {\n        \"internalType\": \"uint256\",\n        \"name\": \"wad\",\n        \"type\": \"uint256\"\n      }\n    ],\n    \"name\": \"withdraw\",\n    \"outputs\": [],\n    \"stateMutability\": \"nonpayable\",\n    \"type\": \"function\"\n  }\n]\n"
  },
  {
    "path": "packages/frontend/src/components/Alert.tsx",
    "content": "import React from 'react'\nimport { Box, Typography, BoxProps } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport InfoIcon from '@material-ui/icons/Info'\n\ntype AlertSeverity = 'warning' | 'error' | 'info' | 'success'\n\ninterface StylesProps {\n  severity: AlertSeverity\n}\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    root: {\n      backgroundColor: (props: StylesProps): string => theme.palette[props.severity].light,\n      border: '1px solid',\n      borderColor: (props: StylesProps): string => theme.palette[props.severity].main,\n      borderRadius: '14px',\n      display: 'flex',\n      alignItems: 'center',\n      gap: '20px',\n      padding: '16px',\n    },\n    text: {\n      fontWeight: 500,\n      fontSize: '15px',\n    },\n  }),\n)\n\ninterface AlertCustomProps {\n  severity: AlertSeverity\n  showIcon?: boolean\n}\ntype AlertProps = BoxProps & AlertCustomProps\n\nconst Alert: React.FC<AlertProps> = ({ severity, showIcon = true, children, ...props }) => {\n  const classes = useStyles({ severity })\n\n  return (\n    <Box className={classes.root} {...props}>\n      {showIcon && <InfoIcon />}\n      {typeof children === 'string' ? (\n        <Typography variant=\"body2\" className={classes.text}>\n          {children}\n        </Typography>\n      ) : (\n        children\n      )}\n    </Box>\n  )\n}\n\nexport default Alert\n"
  },
  {
    "path": "packages/frontend/src/components/Alerts/ShutdownAlert.tsx",
    "content": "import React from 'react'\nimport Link from 'next/link'\nimport { Typography, useMediaQuery, useTheme } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport { format } from 'date-fns'\n\nimport Alert from '../Alert'\nimport { SHUTDOWN_DATE } from '@constants/index'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    link: {\n      color: theme.palette.primary.main,\n      '&:hover': {\n        textDecoration: 'underline',\n      },\n    },\n    boldText: {\n      fontWeight: 700,\n    },\n    text: {\n      fontSize: '15px',\n      fontWeight: 500,\n    },\n    textBig: {\n      fontSize: '16.5px',\n      fontWeight: 600,\n    },\n    container: {\n      maxWidth: '1280px',\n      width: '80%',\n      margin: '12px auto 0 auto',\n\n      [theme.breakpoints.down('lg')]: {\n        maxWidth: 'none',\n        width: 'calc(90% - 80px)',\n      },\n      [theme.breakpoints.down('md')]: {\n        width: 'calc(100% - 6vw)',\n        gridGap: '40px',\n      },\n    },\n  }),\n)\n\nexport const ShutdownAlert: React.FC = () => {\n  const classes = useStyles()\n\n  const theme = useTheme()\n  const isMobileBreakpoint = useMediaQuery(theme.breakpoints.down('xs'))\n\n  const shutdownDate = new Date(SHUTDOWN_DATE)\n\n  // Format the date, using UTC methods to ensure UTC time\n  const shutdownDateFormatted = format(\n    new Date(\n      shutdownDate.getUTCFullYear(),\n      shutdownDate.getUTCMonth(),\n      shutdownDate.getUTCDate(),\n      shutdownDate.getUTCHours(),\n      shutdownDate.getUTCMinutes(),\n    ),\n    \"MMMM d, yyyy 'at' HH:mm 'UTC'\",\n  )\n\n  return (\n    <div className={classes.container}>\n      <Alert severity=\"warning\" showIcon={!isMobileBreakpoint}>\n        <div>\n          <Typography variant=\"body1\" className={classes.textBig}>\n            On {shutdownDateFormatted} the Squeeth protocol was shutdown.\n          </Typography>\n\n          <Typography variant=\"body2\" className={classes.text} style={{ marginTop: theme.spacing(0.5) }}>\n            Positions can be redeemed with 0 price impact (from the settlement price) by connecting your wallet. For\n            more information, please refer to the{' '}\n            <Link\n              href=\"https://opyn.gitbook.io/opyn-hub/squeeth-retirement/post-shutdown-osqth-and-crab-withdrawal-functions\"\n              passHref\n            >\n              <a className={classes.link} target=\"_blank\" rel=\"noopener noreferrer\">\n                GitBook\n              </a>\n            </Link>{' '}\n            and{' '}\n            <Link href=\"https://medium.com/opyn/squeeth-has-shutdown-a8a3c2869eaa\" passHref>\n              <a className={classes.link} target=\"_blank\" rel=\"noopener noreferrer\">\n                Announcement\n              </a>\n            </Link>\n            .\n          </Typography>\n\n          <Typography variant=\"body2\" className={classes.text} style={{ marginTop: theme.spacing(0.5) }}>\n            More announcements to come on the launch of Opyn Markets.\n          </Typography>\n        </div>\n      </Alert>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Alerts/ZenBullAlert.tsx",
    "content": "import React from 'react'\nimport Link from 'next/link'\nimport { Typography, useMediaQuery, useTheme } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\n\nimport Alert from '../Alert'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    link: {\n      fontSize: '15px',\n      fontWeight: 500,\n      color: theme.palette.primary.main,\n    },\n    container: {\n      maxWidth: '1280px',\n      width: '80%',\n      margin: '12px auto 0 auto',\n\n      [theme.breakpoints.down('lg')]: {\n        maxWidth: 'none',\n        width: 'calc(90% - 80px)',\n      },\n      [theme.breakpoints.down('md')]: {\n        width: 'calc(100% - 6vw)',\n        gridGap: '40px',\n      },\n    },\n  }),\n)\n\nexport const ZenBullAlert = () => {\n  const classes = useStyles()\n\n  const theme = useTheme()\n  const isMobileBreakpoint = useMediaQuery(theme.breakpoints.down('xs'))\n\n  return (\n    <div className={classes.container}>\n      <Alert severity=\"warning\" showIcon={!isMobileBreakpoint}>\n        <Typography style={{ fontSize: '15px', fontWeight: 500 }}>\n          Zen Bull was impacted by the Euler Finance exploit. Please{' '}\n          <Link href=\"https://opyn.gitbook.io/opyn-strategies/strategies-faq/faq\">\n            <a className={classes.link} target=\"_blank\">\n              join discord\n            </a>\n          </Link>{' '}\n          for updates. You can recover funds from the section below.\n        </Typography>\n      </Alert>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Announcement.tsx",
    "content": "import { Box, createStyles, IconButton, Link, makeStyles, Typography } from '@material-ui/core'\nimport React, { useEffect, useState } from 'react'\nimport CloseIcon from '@material-ui/icons/Close'\n\nconst ANNOUNCEMENT_KEY = 'DISABLE_MERGE_ANNOUNCEMENT'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      backgroundColor: theme.palette.background.lightStone,\n      padding: theme.spacing(1, 0),\n      display: 'flex',\n      justifyContent: 'center',\n    },\n  }),\n)\n\nconst Announcement: React.FC = () => {\n  const styles = useStyles()\n  const [visible, setVisible] = useState(false)\n\n  useEffect(() => {\n    const _disableAnnouncemnt = localStorage.getItem(ANNOUNCEMENT_KEY)\n    setVisible(!_disableAnnouncemnt)\n  }, [])\n\n  const dontShowAgain = () => {\n    setVisible(false)\n    localStorage.setItem(ANNOUNCEMENT_KEY, 'true')\n  }\n\n  if (!visible) return null\n\n  return (\n    <Box py=\"8\" className={styles.container}>\n      <Typography align=\"center\" variant=\"body2\" component=\"span\">\n        The Merge is coming. Read more about what Opyn users should know about the merge{' '}\n        <Link href=\"/pos-merge\" target=\"_blank\">\n          here\n        </Link>\n        .{' '}\n        <IconButton onClick={dontShowAgain} aria-label=\"close\" size=\"small\">\n          <CloseIcon fontSize=\"small\" style={{ color: '#fff' }} />\n        </IconButton>\n      </Typography>\n    </Box>\n  )\n}\n\nexport default Announcement\n"
  },
  {
    "path": "packages/frontend/src/components/Button/WalletButton.tsx",
    "content": "import { Hidden, Box, Button, Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React from 'react'\nimport { useMemo, useState } from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { Networks } from '../../types'\nimport { toTokenAmount } from '@utils/calculations'\nimport { useENS } from '@hooks/useENS'\nimport { addressAtom, connectedWalletAtom, networkIdAtom, supportedNetworkAtom } from 'src/state/wallet/atoms'\nimport { useDisconnectWallet, useSelectWallet, useWalletBalance } from 'src/state/wallet/hooks'\nimport { BIG_ZERO } from '../../constants'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    walletBox: {\n      [theme.breakpoints.up('md')]: {\n        marginLeft: theme.spacing(1),\n      },\n    },\n    walletContainer: {\n      display: 'flex',\n      alignItems: 'center',\n      background: `${theme.palette.primary.main}90`,\n      borderRadius: theme.spacing(1),\n    },\n    balance: {\n      padding: theme.spacing(1, 1),\n      height: theme.spacing(4),\n      alignItems: 'center',\n      display: 'flex',\n      borderRadius: theme.spacing(1),\n    },\n    walletBtn: {\n      background: theme.palette.background.default,\n    },\n    connectWalletBtn: {\n      fontSize: '16px',\n      fontWeight: 700,\n      textTransform: 'initial',\n      color: theme.palette.background.default,\n    },\n    account: {\n      display: 'flex',\n      alignItems: 'center',\n      '& img': {\n        marginRight: theme.spacing(1),\n      },\n      '& div': {\n        marginRight: theme.spacing(1),\n      },\n    },\n    networkErrorBtn: {\n      background: theme.palette.error.main,\n      color: theme.palette.text.primary,\n      '&:hover': {\n        background: theme.palette.error.main,\n      },\n    },\n    networkErrorContent: {\n      position: 'absolute',\n      top: 42,\n      right: 0,\n      width: 260,\n      padding: 12,\n      border: `1px solid ${theme.palette.divider}`,\n      background: theme.palette.background.default,\n      borderRadius: 12,\n      zIndex: 2,\n      '& button': {\n        marginTop: 8,\n      },\n      [theme.breakpoints.down('sm')]: {\n        right: 'unset',\n        left: 0,\n      },\n    },\n  }),\n)\n\nconst WalletButton: React.FC = () => {\n  const connected = useAtomValue(connectedWalletAtom)\n  const address = useAtomValue(addressAtom)\n  const networkId = useAtomValue(networkIdAtom)\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n  const { data: balance } = useWalletBalance()\n  const disconnectWallet = useDisconnectWallet()\n  const selectWallet = useSelectWallet()\n  const [networkErrorVisible, setNetworkErrorVisible] = useState(false)\n\n  const classes = useStyles()\n  const { ensName } = useENS(address)\n\n  const shortAddress = useMemo(\n    () => (address ? address.slice(0, 6) + '...' + address.slice(address.length - 4, address.length) : ''),\n    [address],\n  )\n\n  const switchToMainnet = () => {\n    const { ethereum } = window as any\n    ethereum.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: '0x1' }] })\n  }\n\n  const Circle = ({ networkId }: { networkId: Networks }) => {\n    const color = networkId === Networks.MAINNET ? '#05b169' : '#8F7FFE'\n    return (\n      <div\n        style={{\n          marginRight: '1rem',\n          display: 'inline-block',\n          backgroundColor: color,\n          borderRadius: '50%',\n          width: '.6rem',\n          height: '.6rem',\n        }}\n      />\n    )\n  }\n\n  return (\n    <div className={classes.walletBox}>\n      {!connected ? (\n        <Button\n          variant=\"contained\"\n          color=\"primary\"\n          onClick={selectWallet}\n          id=\"connect-wallet\"\n          className={classes.connectWalletBtn}\n        >\n          Connect wallet\n        </Button>\n      ) : !supportedNetwork ? (\n        <Box position=\"relative\">\n          <Button\n            variant=\"contained\"\n            className={classes.networkErrorBtn}\n            onMouseOver={() => setNetworkErrorVisible(true)}\n            onClick={() => setNetworkErrorVisible(!networkErrorVisible)}\n          >\n            Unsupported Network\n          </Button>\n          {networkErrorVisible && (\n            <div onMouseLeave={() => setNetworkErrorVisible(false)} className={classes.networkErrorContent}>\n              <Typography color=\"textPrimary\">This network is not supported.</Typography>\n              <Button fullWidth variant=\"outlined\" color=\"primary\" onClick={switchToMainnet}>\n                Switch to Mainnet\n              </Button>\n            </div>\n          )}\n        </Box>\n      ) : (\n        <div className={classes.walletContainer}>\n          <Hidden smDown>\n            <div className={classes.balance}>\n              <span id=\"user-eth-wallet-balance\">{toTokenAmount(balance ?? BIG_ZERO, 18).toFixed(4)}</span>\n              ETH\n            </div>\n          </Hidden>\n          <Button variant=\"outlined\" color=\"primary\" onClick={disconnectWallet} className={classes.walletBtn}>\n            <Circle networkId={networkId} />\n            <div className={classes.account} id=\"wallet-address\">\n              {/* <Davatar size={20} address={address || ''} /> */}\n              <span>{ensName || shortAddress}</span>\n            </div>\n          </Button>\n        </div>\n      )}\n    </div>\n  )\n}\n\nexport default WalletButton\n"
  },
  {
    "path": "packages/frontend/src/components/Button/index.tsx",
    "content": "import Button from '@material-ui/core/Button'\nimport { withStyles } from '@material-ui/core/styles'\n\nexport const PrimaryButton = withStyles((theme) => ({\n  root: {\n    color: '#000',\n    backgroundColor: theme.palette.primary.main,\n    '&:hover': {\n      backgroundColor: theme.palette.primary.dark,\n    },\n    minHeight: '2rem',\n    minWidth: '300px',\n  },\n}))(Button)\n\nexport const ErrorButton = withStyles((theme) => ({\n  root: {\n    color: theme.palette.text.secondary,\n    backgroundColor: theme.palette.error.main,\n    '&:hover': {\n      backgroundColor: theme.palette.error.dark,\n    },\n    minHeight: '2rem',\n    minWidth: '300px',\n  },\n}))(Button)\n\nexport const LinkButton = withStyles((theme) => ({\n  root: {\n    color: theme.palette.primary.main,\n    background: 'transparent',\n    '&:hover': {\n      background: 'transparent',\n    },\n    padding: '0',\n  },\n}))(Button)\n\nexport const AddButton = withStyles((theme) => ({\n  root: {\n    color: '#000',\n    backgroundColor: theme.palette.success.main,\n    '&:hover': {\n      backgroundColor: theme.palette.success.dark,\n    },\n    '&:disabled': {\n      backgroundColor: theme.palette.background.lightStone,\n    },\n  },\n}))(Button)\n\nexport const RemoveButton = withStyles((theme) => ({\n  root: {\n    color: '#000',\n    backgroundColor: theme.palette.error.main,\n    '&:hover': {\n      backgroundColor: theme.palette.error.dark,\n    },\n    '&:disabled': {\n      backgroundColor: theme.palette.background.lightStone,\n    },\n  },\n}))(Button)\n\nexport const GreyButton = withStyles((theme) => ({\n  root: {\n    color: theme.palette.text.secondary,\n    backgroundColor: theme.palette.action.hover,\n    '&:hover': {\n      backgroundColor: theme.palette.action.selected,\n    },\n  },\n}))(Button)\n\nexport const PrimaryButtonNew = withStyles((theme) => ({\n  root: {\n    color: theme.palette.background.default,\n    backgroundColor: theme.palette.primary.main,\n    '&:hover': {\n      backgroundColor: theme.palette.primary.dark,\n    },\n    '&:disabled': {\n      color: 'rgba(255, 255, 255, 0.4)',\n      backgroundColor: theme.palette.background.lightStone,\n    },\n    minHeight: '2rem',\n    minWidth: '300px',\n    padding: '8px',\n    fontSize: '18px',\n    fontWeight: 700,\n    textTransform: 'initial',\n  },\n}))(Button)\n\nexport const RoundedButton = withStyles((theme) => ({\n  root: {\n    backgroundColor: theme.palette.background.stone,\n    '&:disabled': {\n      color: 'rgba(255, 255, 255, 0.1)',\n      backgroundColor: 'rgba(36, 39, 40, 0.6)',\n      opacity: 1,\n      border: '2px solid rgba(255, 255, 255, 0.1)',\n    },\n    textTransform: 'initial',\n    borderRadius: '20px',\n    padding: '4px 24px',\n    fontSize: '16px',\n    fontWeight: 700,\n  },\n}))(Button)\n\nexport const TextButton = withStyles((theme) => ({\n  root: {\n    color: theme.palette.primary.main,\n    backgroundColor: 'transparent',\n    '&:hover': {\n      backgroundColor: 'transparent',\n    },\n    textTransform: 'initial',\n    padding: '0',\n    fontSize: '16px',\n    fontWeight: 400,\n  },\n}))(Button)\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/BullStrategyPerformanceChart.tsx",
    "content": "import { Box, CircularProgress } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React, { memo, useEffect } from 'react'\nimport HighchartsReact from 'highcharts-react-official'\nimport Highcharts from 'highcharts'\nimport Grid from '@material-ui/core/Grid'\nimport DateFnsUtils from '@date-io/date-fns'\nimport { useAtom } from 'jotai'\nimport { DatePicker, MuiPickersUtilsProvider } from '@material-ui/pickers'\n\nimport useAppMemo from '@hooks/useAppMemo'\nimport { pnlGraphOptions } from '@constants/diagram'\nimport { BULL_START_DATE } from '@constants/index'\nimport { bullStrategyFilterEndDateAtom, bullStrategyFilterStartDateAtom, useBullPnLChartData } from '@state/bull/atoms'\n\nexport type ChartDataInfo = {\n  timestamp: number\n  bullEthPnl: number\n}\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(0),\n      marginTop: theme.spacing(4),\n      marginBottom: theme.spacing(1),\n      maxWidth: '640px',\n    },\n    chartContainer: {\n      borderRadius: theme.spacing(1),\n      padding: theme.spacing(1, 0),\n      display: 'flex',\n      marginTop: theme.spacing(2),\n      [theme.breakpoints.up('sm')]: {\n        maxHeight: '310px',\n      },\n      [theme.breakpoints.down('sm')]: {\n        flexDirection: 'column',\n      },\n    },\n    navDiv: {\n      display: 'flex',\n      marginBottom: theme.spacing(2),\n      marginTop: theme.spacing(2),\n      alignItems: 'center',\n    },\n    grid: {\n      rowGap: '24px',\n      columnGap: '24px',\n      marginRight: 'auto',\n      marginTop: '12px',\n    },\n  }),\n)\n\nfunction BullStrategyPerformanceChart() {\n  const classes = useStyles()\n\n  const minDate = BULL_START_DATE\n  const [startDate, setStartDate] = useAtom(bullStrategyFilterStartDateAtom)\n  const [endDate, setEndDate] = useAtom(bullStrategyFilterEndDateAtom)\n\n  const query = useBullPnLChartData()\n\n  const bullEthPnlSeries = query?.data?.data.map((x: ChartDataInfo) => [x.timestamp * 1000, x.bullEthPnl])\n\n  useEffect(() => {\n    Highcharts.setOptions({\n      lang: {\n        thousandsSep: ',',\n      },\n    })\n  }, [])\n\n  const series = [\n    {\n      yAxis: 0,\n      name: 'Bull/ETH 🧘🐂 % Return',\n      data: bullEthPnlSeries,\n      tooltip: {\n        valueDecimals: 2,\n        valueSuffix: '%',\n      },\n    \n      color: '#70E3F6',\n    }\n  ]\n\n  const axes = {\n    yAxis: [\n      {\n        title: {\n          text: '',\n        },\n        labels: {\n          style: {\n            color: '#BABBBB',\n          },\n        },\n        gridLineColor: 'rgba(221,221,221,0.1)',\n      },\n    ],\n  }\n\n  const chartOptions = useAppMemo(() => {\n    return {\n      ...pnlGraphOptions,\n      series: series,\n      ...axes,\n    }\n  })\n\n  return (\n    <>\n      <MuiPickersUtilsProvider utils={DateFnsUtils}>\n        <Grid container className={classes.grid}>\n          <DatePicker\n            label=\"Start Date\"\n            placeholder=\"MM/DD/YYYY\"\n            format={'MM/dd/yyyy'}\n            value={startDate}\n            minDate={minDate}\n            onChange={(d) => setStartDate(d || new Date())}\n            animateYearScrolling={false}\n            autoOk={true}\n            clearable\n          />\n\n          <DatePicker\n            label=\"End Date\"\n            placeholder=\"MM/DD/YYYY\"\n            format={'MM/dd/yyyy'}\n            value={endDate}\n            minDate={startDate}\n            onChange={(d) => setEndDate(d || new Date())}\n            animateYearScrolling={false}\n            autoOk={true}\n            clearable\n          />\n        </Grid>\n      </MuiPickersUtilsProvider>\n\n      <div className={classes.chartContainer} style={{ maxHeight: 'none' }}>\n        <div style={{ flex: '1 1 0', marginTop: '8px' }}>\n          {bullEthPnlSeries ? (\n            <HighchartsReact highcharts={Highcharts} options={chartOptions} />\n          ) : (\n            <Box display=\"flex\" height=\"300px\" width={1} alignItems=\"center\" justifyContent=\"center\">\n              <CircularProgress size={40} color=\"secondary\" />\n            </Box>\n          )}\n        </div>\n      </div>\n    </>\n  )\n}\n\nconst ChartMemoized = memo(BullStrategyPerformanceChart)\n\nexport default ChartMemoized\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/CrabStrategyChart.tsx",
    "content": "import { createStyles, Hidden, InputAdornment, makeStyles, TextField, Tooltip } from '@material-ui/core'\nimport Alert from '@material-ui/lab/Alert'\nimport dynamic from 'next/dynamic'\nimport React, { memo, useState } from 'react'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport { useAtom } from 'jotai'\n\nimport { graphOptions, Links, Tooltips, Vaults } from '../../constants'\nimport {\n  daysAtom,\n  useGetStableYieldPNL,\n  useGetVaultPNLWithRebalance,\n  useLongEthPNL,\n  useShortEthPNL,\n  useShortSeries,\n} from 'src/state/ethPriceCharts/atoms'\nimport useAppMemo from '@hooks/useAppMemo'\n\nconst Chart = dynamic(() => import('kaktana-react-lightweight-charts'), { ssr: false })\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    navDiv: {\n      display: 'flex',\n      marginBottom: theme.spacing(2),\n      alignItems: 'center',\n    },\n    chartNav: {\n      border: `1px solid ${theme.palette.primary.main}30`,\n      [theme.breakpoints.down('sm')]: {\n        width: '100%',\n      },\n    },\n    cardDetail: {\n      color: theme.palette.text.secondary,\n      lineHeight: '1.75rem',\n      fontSize: '14px',\n      marginTop: theme.spacing(2),\n      maxWidth: '800px',\n    },\n    cardTitle: {\n      color: theme.palette.primary.main,\n    },\n    header: {\n      color: theme.palette.primary.main,\n    },\n    payoffContainer: {\n      display: 'grid',\n      gap: '2rem',\n      overflow: 'auto',\n      // maxHeight: '310',\n      [theme.breakpoints.up('md')]: {\n        gridTemplateColumns: '1fr 1fr',\n      },\n    },\n    infoIcon: {\n      fontSize: '1rem',\n      marginLeft: theme.spacing(0.5),\n      marginTop: '2px',\n    },\n    shortPayoff: {\n      width: '90%',\n      margin: '0 auto',\n      [theme.breakpoints.up('md')]: {\n        width: '100%',\n        margin: 0,\n      },\n    },\n    legendBox: {\n      display: 'flex',\n      gap: '10px',\n      marginTop: '10px',\n      justifyContent: 'center',\n    },\n    legendContainer: {\n      display: 'flex',\n      gap: '5px',\n    },\n    shortDescription: {\n      [theme.breakpoints.up('md')]: {\n        justifySelf: 'end',\n      },\n    },\n  }),\n)\n\nfunction CrabStrategyChart({ vault, longAmount }: { vault?: Vaults; longAmount: number }) {\n  // const startingETHPrice = useStartingETHPrice()\n  const getVaultPNLWithRebalance = useGetVaultPNLWithRebalance()\n  const longEthPNL = useLongEthPNL()\n  const shortEthPNL = useShortEthPNL()\n  const getStableYieldPNL = useGetStableYieldPNL()\n  const shortSeries = useShortSeries()\n\n  const [days, setDays] = useAtom(daysAtom)\n\n  const seriesRebalance = getVaultPNLWithRebalance(longAmount)\n  const classes = useStyles()\n  const [chartType] = useState(0)\n\n  const compoundSeries = getStableYieldPNL(1)\n\n  const lineSeries = useAppMemo(() => {\n    if (!shortEthPNL || !longEthPNL || !seriesRebalance || !shortSeries) return\n\n    if (vault === Vaults.ETHZenBull)\n      return [\n        { data: longEthPNL, legend: 'Long ETH' },\n        { data: seriesRebalance, legend: 'ETH Bull Strategy (incl. premium)' },\n      ]\n    if (vault === Vaults.CrabVault)\n      return [\n        { data: seriesRebalance, legend: 'Crab Strategy PNL (incl. premium)' },\n        { data: getStableYieldPNL(longAmount), legend: 'Compound Interest yield' },\n      ]\n    if (vault === Vaults.ETHBear)\n      return [\n        { data: shortEthPNL, legend: 'Short ETH' },\n        { data: seriesRebalance, legend: 'ETH Bear Strategy (incl. premium)' },\n      ]\n    if (vault === Vaults.Short)\n      return [\n        { data: compoundSeries, legend: 'Compound PNL (%)' },\n        { data: shortSeries, legend: 'Crab PnL (%) (incl. premium)' },\n        // { data: convertPNLToPriceChart(shortEthPNL, startingETHPrice), legend: 'Short ETH' },\n        // { data: convertPNLToPriceChart(shortSeries, startingETHPrice), legend: 'Short Squeeth (incl. funding)' },\n      ]\n    return [{ data: seriesRebalance, legend: 'PNL' }]\n  }, [compoundSeries, getStableYieldPNL, longAmount, longEthPNL, seriesRebalance, shortEthPNL, shortSeries, vault])\n\n  // const lineSeriesPercentage = useAppMemo(() => {\n  //   if (!startingETHPrice || !seriesRebalance || !longEthPNL || !shortEthPNL) return\n\n  //   if (vault === Vaults.ETHZenBull)\n  //     return [\n  //       { data: convertPNLToPriceChart(longEthPNL, startingETHPrice), legend: 'Long ETH' },\n  //       {\n  //         data: convertPNLToPriceChart(seriesRebalance, startingETHPrice),\n  //         legend: 'ETH Bull Strategy (incl. funding)',\n  //       },\n  //     ]\n  //   if (vault === Vaults.CrabVault)\n  //     return [\n  //       {\n  //         data: convertPNLToPriceChart(getStableYieldPNL(longAmount), startingETHPrice),\n  //         legend: 'Compound Interest Yield',\n  //       },\n  //       {\n  //         data: convertPNLToPriceChart(seriesRebalance, startingETHPrice),\n  //         legend: 'Crab Strategy PNL (incl. funding)',\n  //       },\n  //     ]\n  //   if (vault === Vaults.ETHBear)\n  //     return [\n  //       { data: convertPNLToPriceChart(shortEthPNL, startingETHPrice), legend: 'Short ETH' },\n  //       {\n  //         data: convertPNLToPriceChart(seriesRebalance, startingETHPrice),\n  //         legend: 'ETH Bear Strategy (incl. funding)',\n  //       },\n  //     ]\n  //   if (vault === Vaults.Short)\n  //     return [\n  //       { data: shortEthPNL, legend: 'Short ETH PNL' },\n  //       { data: shortSeries, legend: 'Crab (incl. funding)' },\n  //       // { data: convertPNLToPriceChart(shortEthPNL, startingETHPrice), legend: 'Short ETH' },\n  //       // { data: convertPNLToPriceChart(shortSeries, startingETHPrice), legend: 'Short Squeeth (incl. funding)' },\n  //     ]\n  //   return [{ data: seriesRebalance, legend: 'PNL' }]\n  // }, [vault, shortEthPNL, seriesRebalance, getStableYieldPNL, longAmount, startingETHPrice, shortSeries, longEthPNL])\n\n  const startTimestamp = useAppMemo(\n    () => (lineSeries && lineSeries.length > 0 && lineSeries[0].data.length > 0 ? lineSeries[0].data[0].time : 0),\n    [lineSeries],\n  )\n\n  const endTimestamp = useAppMemo(\n    () =>\n      lineSeries && lineSeries.length > 0 && lineSeries[0].data.length > 0\n        ? lineSeries[0].data[lineSeries[0].data.length - 1].time\n        : 0,\n    [lineSeries],\n  )\n\n  const chartOptions = {\n    ...graphOptions,\n    localization: {\n      priceFormatter: (num: number) => num.toFixed(2) + '%',\n    },\n  }\n\n  return (\n    <div>\n      <div className={classes.navDiv}>\n        {/* <SqueethTabs\n          style={{ background: 'transparent' }}\n          className={classes.chartNav}\n          value={chartType}\n          onChange={(evt, val) => setChartType(val)}\n          aria-label=\"Sub nav tabs\"\n        >\n          <SqueethTab label={`Historical ${days}D PNL`} />\n          <SqueethTab label=\"Payoff\" />\n          <SqueethTab label=\"Details\" />\n          <SqueethTab label=\"Risks\" />\n        </SqueethTabs> */}\n        <Hidden smDown>\n          {chartType === 0 ? (\n            <TextField\n              onChange={(event) => setDays(parseInt(event.target.value))}\n              size=\"small\"\n              value={days}\n              type=\"number\"\n              style={{ width: 150, marginLeft: '16px' }}\n              label=\"Historical Days\"\n              variant=\"outlined\"\n              InputProps={{\n                endAdornment: (\n                  <InputAdornment position=\"end\">\n                    <a href={Links.BacktestFAQ} target=\"_blank\" rel=\"noreferrer\">\n                      <Tooltip title={Tooltips.BacktestDisclaimer}>\n                        <InfoIcon fontSize=\"small\" />\n                      </Tooltip>\n                    </a>\n                  </InputAdornment>\n                ),\n              }}\n            />\n          ) : null}\n        </Hidden>\n      </div>\n      {seriesRebalance && seriesRebalance.length === 0 && (\n        <Alert severity=\"info\"> Loading historical data, this could take a while</Alert>\n      )}\n      <Chart\n        from={startTimestamp}\n        to={endTimestamp}\n        // legend={`${vault} PNL`}\n        options={chartOptions}\n        lineSeries={lineSeries}\n        autoWidth\n        height={300}\n        darkTheme\n      />\n\n      <div className={classes.legendBox}>\n        <div className={classes.legendContainer}>\n          <div style={{ width: '20px', height: '20px', backgroundColor: '#018FFB' }}></div>\n          <div>Compound cUSDC Yield</div>\n        </div>\n        <div className={classes.legendContainer}>\n          <div style={{ width: '20px', height: '20px', backgroundColor: '#00E396' }}></div>\n          <div>Crab PNL</div>\n        </div>\n      </div>\n      {/* <IV /> */}\n      {/* {vault === Vaults.Custom && (\n        <TextField\n          onChange={(event) => setCustomLong(parseFloat(event.target.value))}\n          size=\"small\"\n          value={longAmount}\n          type=\"number\"\n          style={{ width: 300 }}\n          label=\"ETH Long\"\n          variant=\"outlined\"\n        />\n      )} */}\n    </div>\n  )\n}\n\nexport const MemoizedCrabStrategyChart = memo(CrabStrategyChart)\n\n// const convertPNLToPriceChart = (pnlSeries: { time: number; value: number }[], startingCapital: number) => {\n//   return pnlSeries.map(({ value, time }) => {\n//     return {\n//       value: value + startingCapital,\n//       time,\n//     }\n//   })\n// }\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/CrabStrategyV2PnLChart.tsx",
    "content": "import { Box, CircularProgress } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React, { memo, useEffect } from 'react'\nimport useAppMemo from '@hooks/useAppMemo'\nimport {\n  crabv2StrategyFilterEndDateAtom,\n  crabv2StrategyFilterStartDateAtom,\n  useCrabPnLV2ChartData,\n} from 'src/state/crab/atoms'\nimport { pnlGraphOptions } from '@constants/diagram'\nimport HighchartsReact from 'highcharts-react-official'\nimport Highcharts from 'highcharts'\nimport Grid from '@material-ui/core/Grid'\nimport DateFnsUtils from '@date-io/date-fns'\nimport { DatePicker, MuiPickersUtilsProvider } from '@material-ui/pickers'\nimport { CRABV2_START_DATE } from '@constants/index'\nimport { useAtom } from 'jotai'\n\nexport type ChartDataInfo = {\n  timestamp: number\n  crabPnL: number\n}\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(0),\n      marginTop: theme.spacing(4),\n      marginBottom: theme.spacing(1),\n      maxWidth: '640px',\n    },\n    chartContainer: {\n      borderRadius: theme.spacing(1),\n      padding: theme.spacing(1, 0),\n      display: 'flex',\n      marginTop: theme.spacing(2),\n      [theme.breakpoints.up('sm')]: {\n        maxHeight: '310px',\n      },\n      [theme.breakpoints.down('sm')]: {\n        flexDirection: 'column',\n      },\n    },\n    navDiv: {\n      display: 'flex',\n      marginBottom: theme.spacing(2),\n      marginTop: theme.spacing(2),\n      alignItems: 'center',\n    },\n    grid: {\n      rowGap: '24px',\n      columnGap: '24px',\n      marginRight: 'auto',\n      padding: theme.spacing(2),\n    },\n  }),\n)\n\nfunction CrabStrategyV2PnLChart() {\n  const classes = useStyles()\n\n  const minDate = CRABV2_START_DATE\n  const [startDate, setStartDate] = useAtom(crabv2StrategyFilterStartDateAtom)\n  const [endDate, setEndDate] = useAtom(crabv2StrategyFilterEndDateAtom)\n\n  const query = useCrabPnLV2ChartData()\n\n  const crabUsdPnlSeries = query?.data?.data.map((x: ChartDataInfo) => [x.timestamp * 1000, x.crabPnL * 100])\n\n  useEffect(() => {\n    Highcharts.setOptions({\n      lang: {\n        thousandsSep: ',',\n      },\n    })\n  }, [])\n\n  const series = [\n    {\n      name: 'Crab/USD 🦀  % Return',\n      yAxis: 0,\n      data: crabUsdPnlSeries,\n      tooltip: {\n        valueDecimals: 2,\n        valueSuffix: '%',\n      },\n      color: '#70E3F6',\n    }\n  ]\n\n  const axes = {\n    yAxis: [\n      {\n        // Left yAxis\n        title: {\n          text: '',\n        },\n        labels: {\n          style: {\n            color: '#BABBBB',\n          },\n        },\n        gridLineColor: 'rgba(221,221,221,0.1)',\n      }\n    ],\n  }\n\n  const chartOptions = useAppMemo(() => {\n    return {\n      ...pnlGraphOptions,\n      series: series,\n      ...axes,\n    }\n  })\n\n  return (\n    <>\n      <MuiPickersUtilsProvider utils={DateFnsUtils}>\n        <Grid container className={classes.grid}>\n          <DatePicker\n            label=\"Start Date\"\n            placeholder=\"MM/DD/YYYY\"\n            format={'MM/dd/yyyy'}\n            value={startDate}\n            minDate={minDate}\n            onChange={(d) => setStartDate(d || new Date())}\n            animateYearScrolling={false}\n            autoOk={true}\n            clearable\n          />\n\n          <DatePicker\n            label=\"End Date\"\n            placeholder=\"MM/DD/YYYY\"\n            format={'MM/dd/yyyy'}\n            value={endDate}\n            minDate={startDate}\n            onChange={(d) => setEndDate(d || new Date())}\n            animateYearScrolling={false}\n            autoOk={true}\n            clearable\n          />\n        </Grid>\n      </MuiPickersUtilsProvider>\n\n      <div className={classes.chartContainer} style={{ maxHeight: 'none' }}>\n        <div style={{ flex: '1 1 0', marginTop: '8px' }}>\n          {crabUsdPnlSeries ? (\n            <HighchartsReact highcharts={Highcharts} options={chartOptions} />\n          ) : (\n            <Box display=\"flex\" height=\"300px\" width={1} alignItems=\"center\" justifyContent=\"center\">\n              <CircularProgress size={40} color=\"secondary\" />\n            </Box>\n          )}\n        </div>\n      </div>\n    </>\n  )\n}\n\nconst ChartMemoized = memo(CrabStrategyV2PnLChart)\n\nexport { ChartMemoized as CrabStrategyV2PnLChart }\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/FundingChart.tsx",
    "content": "import { memo } from 'react'\nimport { Box, CircularProgress, createStyles, makeStyles, Tooltip } from '@material-ui/core'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport dynamic from 'next/dynamic'\nimport React, { useState } from 'react'\nimport CustomSwitch, { SwitchItem } from '@components/CustomSwitch'\nimport { useNormHistory } from '@hooks/useNormHistory'\nimport { Tooltips } from '@constants/enums'\nimport { NormHistory } from '../../types/index'\nimport { graphOptions } from '../../constants/diagram'\n\nconst Chart = dynamic(() => import('kaktana-react-lightweight-charts'), { ssr: false })\n\nconst useStyles = makeStyles(() =>\n  createStyles({\n    switchWrapper: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      alignItems: 'center',\n      flexWrap: 'wrap',\n    },\n    legendBox: {\n      display: 'flex',\n      gap: '10px',\n      marginTop: '10px',\n      justifyContent: 'center',\n    },\n    legendContainer: {\n      display: 'flex',\n      gap: '5px',\n    },\n    iconWrapper: {\n      display: 'flex',\n      marginLeft: 6,\n    },\n  }),\n)\n\nconst FundingChart = () => {\n  const classes = useStyles()\n\n  const fundingTypes = [\n    { id: 'funding', text: 'Premium' },\n    {\n      id: 'vol',\n      text: 'VOL',\n      itemToAdd: (\n        <div className={classes.iconWrapper}>\n          <Tooltip title={Tooltips.FundingVol}>\n            <InfoIcon fontSize=\"small\" />\n          </Tooltip>\n        </div>\n      ),\n    },\n  ]\n  const fundingDurations = [\n    {\n      id: 'day',\n      text: 'Day',\n      itemToAdd: (\n        <div className={classes.iconWrapper}>\n          <Tooltip title={Tooltips.FundingDaily}>\n            <InfoIcon fontSize=\"small\" />\n          </Tooltip>\n        </div>\n      ),\n    },\n    {\n      id: 'month',\n      text: 'Month',\n      itemToAdd: (\n        <div className={classes.iconWrapper}>\n          <Tooltip title={Tooltips.FundingMonthly}>\n            <InfoIcon fontSize=\"small\" />\n          </Tooltip>\n        </div>\n      ),\n    },\n    {\n      id: 'year',\n      text: 'Annualized',\n      itemToAdd: (\n        <div className={classes.iconWrapper}>\n          <Tooltip title={Tooltips.FundingAnnual}>\n            <InfoIcon fontSize=\"small\" />\n          </Tooltip>\n        </div>\n      ),\n    },\n  ]\n  const [fundingType, setFundingType] = useState<SwitchItem>(fundingTypes[0])\n  const [fundingDuration, setFundingDuration] = useState<SwitchItem>(fundingDurations[0])\n\n  const { normHistory: normFactors, fetchingComplete } = useNormHistory()\n  const graphData = normFactors.map((item) => {\n    const secondsElapsed = Number(item.timestamp) - Number(item.lastModificationTimestamp)\n    const deltaT = secondsElapsed / (420 * 60 * 60)\n    const markIndex = 1 / Math.exp(Math.log(Number(item.newNormFactor) / Number(item.oldNormFactor)) / deltaT)\n    const dayFunding = Math.log(markIndex) / 17.5\n    const monthFunding = dayFunding * 30\n    const yearFunding = dayFunding * 365.25\n    const annualVol = (dayFunding < 0 ? -1 : 1) * Math.sqrt(Math.abs(dayFunding) * 365)\n    const value =\n      (fundingType.id === 'vol'\n        ? annualVol\n        : fundingDuration.id === 'day'\n        ? dayFunding\n        : fundingDuration.id === 'month'\n        ? monthFunding\n        : yearFunding) * 100\n    return { time: Number(item.timestamp), value: parseFloat(value.toFixed(4)) }\n  })\n\n  const chartOptions = {\n    ...graphOptions,\n    localization: {\n      priceFormatter: (num: number) => `${num < 0 ? num.toFixed(3) : num.toFixed(4)}%`,\n    },\n  }\n  const startTimestamp = normFactors.length > 0 ? Number(normFactors[0].timestamp) : undefined\n  const endTimestamp = normFactors.length > 0 ? Number(normFactors[normFactors.length - 1].timestamp) : undefined\n  const legendText =\n    fundingType.id === 'vol'\n      ? 'Annual Vol'\n      : fundingDuration.id === 'day'\n      ? 'Daily Premium'\n      : fundingDuration.id === 'month'\n      ? 'Monthly Premium'\n      : 'Annual Premium'\n\n  return (\n    <>\n      <div style={{ width: '100%' }}>\n        <div className={classes.switchWrapper}>\n          <CustomSwitch items={fundingTypes} value={fundingType} onChange={setFundingType} />\n          {fundingType.id === 'funding' && (\n            <CustomSwitch items={fundingDurations} value={fundingDuration} onChange={setFundingDuration} />\n          )}\n        </div>\n        {fetchingComplete ? (\n          <>\n            <Chart\n              from={startTimestamp}\n              to={endTimestamp}\n              legend=\"\"\n              options={chartOptions}\n              lineSeries={[{ data: graphData, legend: `${legendText} (%) `, options: { color: '#70E3F6' } }]}\n              autoWidth\n              height={300}\n              darkTheme\n            />\n            <div className={classes.legendBox}>\n              <div className={classes.legendContainer}>\n                <div style={{ width: '20px', height: '20px', backgroundColor: '#70E3F6' }}></div>\n                <div>{legendText}</div>\n              </div>\n            </div>\n          </>\n        ) : (\n          <Box display=\"flex\" height=\"300px\" width={1} alignItems=\"center\" justifyContent=\"center\">\n            <CircularProgress size={40} color=\"secondary\" />\n          </Box>\n        )}\n      </div>\n    </>\n  )\n}\n\nexport default memo(FundingChart)\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/LPBuyChart.tsx",
    "content": "import useAppCallback from '@hooks/useAppCallback'\nimport React, { memo, useEffect, useState } from 'react'\nimport { Line } from 'react-chartjs-2'\n\nimport { getBuyAndLPPayOffGraph } from '../../utils'\n\nconst primaryColor = '#2CE6F9'\nconst errorColor = '#EC7987'\n\nconst chartOptions = {\n  maintainAspectRatio: false,\n  responsive: false,\n  title: { display: true },\n  legend: {\n    display: true,\n    labels: {\n      filter: (legendItem: any) => {\n        const label = legendItem.text\n        if (label === '2xLeverage') return false\n        return true\n      },\n    },\n  },\n  scales: {\n    yAxes: [\n      {\n        display: true,\n        gridLines: {\n          zeroLineWidth: 0,\n          lineWidth: 0,\n        },\n        ticks: {\n          display: true,\n        },\n        scaleLabel: {\n          labelString: '% Return',\n          display: true,\n        },\n      },\n    ],\n    xAxes: [\n      {\n        display: true,\n        scaleLabel: {\n          labelString: '% Change in ETH price',\n          display: true,\n        },\n        ticks: {\n          display: true,\n          autoSkip: true,\n          maxTicksLimit: 10,\n        },\n        gridLines: {\n          lineWidth: 0,\n          zeroLineWidth: 0,\n        },\n      },\n    ],\n  },\n  tooltips: {\n    enabled: true,\n    intersect: false,\n    mode: 'index',\n    callbacks: {\n      label: function (tooltipItem: any, data: any) {\n        return `${data.datasets[tooltipItem.datasetIndex].label}: ${tooltipItem.yLabel} %`\n      },\n      title: function (tooltipItem: any) {\n        return `${tooltipItem[0].xLabel} % ETH Change`\n      },\n    },\n  },\n  animation: { duration: 0 },\n  hover: { animationDuration: 0, intersect: false },\n  onHover: (_: any, elements: any) => {\n    if (elements && elements.length) {\n      const chartElem = elements[0]\n      const chart = chartElem._chart\n      const ctx = chart.ctx\n\n      ctx.globalCompositeOperation = 'destination-over'\n      const x = chartElem._view.x\n      const topY = chart.scales['y-axis-0'].top\n      const bottomY = chart.scales['y-axis-0'].bottom\n\n      ctx.save()\n      ctx.beginPath()\n      ctx.setLineDash([5, 5])\n      ctx.moveTo(x, topY)\n      ctx.lineTo(x, bottomY)\n      ctx.lineWidth = 1\n      ctx.strokeStyle = '#77757E80'\n      ctx.stroke()\n      ctx.restore()\n\n      ctx.globalCompositeOperation = 'source-over'\n    }\n  },\n}\n\nconst LongSqueethPayoff: React.FC<{ ethPrice: number }> = ({ ethPrice }) => {\n  const [labels, setLabels] = useState<Array<string>>([])\n  const [values, setValues] = useState<Array<string>>([])\n  const [levValues, setLevValues] = useState<Array<string | null>>([])\n\n  useEffect(() => {\n    const { ethPercents, lpPayout, leveragePayout } = getBuyAndLPPayOffGraph(ethPrice)\n    setLabels(ethPercents)\n    setValues(lpPayout)\n    setLevValues(leveragePayout)\n  }, [ethPrice])\n\n  const getData = useAppCallback(() => {\n    return {\n      labels,\n      datasets: [\n        {\n          label: '%USD return Buy and LP',\n          data: values,\n          fill: false,\n          borderColor: primaryColor,\n          pointHoverBorderColor: primaryColor,\n          pointHoverBackgroundColor: primaryColor,\n          pointBackgroundColor: 'rgba(0, 0, 0, 0)',\n          pointBorderColor: 'rgba(0, 0, 0, 0)',\n          pointHoverRadius: 5,\n          pointHitRadius: 30,\n        },\n        {\n          label: '%USD return 1.5x Leverage',\n          data: levValues,\n          fill: false,\n          borderColor: errorColor,\n          pointHoverBorderColor: errorColor,\n          pointHoverBackgroundColor: errorColor,\n          pointBackgroundColor: 'rgba(0, 0, 0, 0)',\n          pointBorderColor: 'rgba(0, 0, 0, 0)',\n          pointHoverRadius: 5,\n          pointHitRadius: 30,\n        },\n      ],\n    }\n  }, [labels, values, levValues])\n\n  return (\n    <div style={{ width: '350px' }}>\n      <Line data={getData} type=\"line\" height={300} width={380} options={chartOptions} />\n    </div>\n  )\n}\n\nexport default memo(LongSqueethPayoff)\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/LPMintChart.tsx",
    "content": "import useAppCallback from '@hooks/useAppCallback'\nimport useAppEffect from '@hooks/useAppEffect'\nimport React, { memo, useState } from 'react'\nimport { Line } from 'react-chartjs-2'\n\nimport { getMintAndLpPayoffGraph } from '../../utils'\n\nconst primaryColor = '#2CE6F9'\nconst errorColor = '#EC7987'\n\nconst chartOptions = {\n  maintainAspectRatio: false,\n  responsive: false,\n  title: { display: true },\n  legend: {\n    display: true,\n    labels: {\n      filter: (legendItem: any) => {\n        const label = legendItem.text\n        if (label === '2xLeverage') return false\n        return true\n      },\n    },\n  },\n  scales: {\n    yAxes: [\n      {\n        display: true,\n        gridLines: {\n          zeroLineWidth: 0,\n          lineWidth: 0,\n        },\n        ticks: {\n          display: true,\n        },\n        scaleLabel: {\n          labelString: '% Return',\n          display: true,\n        },\n      },\n    ],\n    xAxes: [\n      {\n        display: true,\n        scaleLabel: {\n          labelString: '% Change in ETH price',\n          display: true,\n        },\n        ticks: {\n          display: true,\n          autoSkip: true,\n          maxTicksLimit: 10,\n        },\n        gridLines: {\n          lineWidth: 0,\n          zeroLineWidth: 0,\n        },\n      },\n    ],\n  },\n  tooltips: {\n    enabled: true,\n    intersect: false,\n    mode: 'index',\n    callbacks: {\n      label: function (tooltipItem: any, data: any) {\n        return `${data.datasets[tooltipItem.datasetIndex].label}: ${tooltipItem.yLabel} %`\n      },\n      title: function (tooltipItem: any) {\n        return `${tooltipItem[0].xLabel} % ETH Change`\n      },\n    },\n  },\n  animation: { duration: 0 },\n  hover: { animationDuration: 0, intersect: false },\n  onHover: (_: any, elements: any) => {\n    if (elements && elements.length) {\n      const chartElem = elements[0]\n      const chart = chartElem._chart\n      const ctx = chart.ctx\n\n      ctx.globalCompositeOperation = 'destination-over'\n      const x = chartElem._view.x\n      const topY = chart.scales['y-axis-0'].top\n      const bottomY = chart.scales['y-axis-0'].bottom\n\n      ctx.save()\n      ctx.beginPath()\n      ctx.setLineDash([5, 5])\n      ctx.moveTo(x, topY)\n      ctx.lineTo(x, bottomY)\n      ctx.lineWidth = 1\n      ctx.strokeStyle = '#77757E80'\n      ctx.stroke()\n      ctx.restore()\n\n      ctx.globalCompositeOperation = 'source-over'\n    }\n  },\n}\n\nconst LongSqueethPayoff: React.FC<{ ethPrice: number }> = ({ ethPrice }) => {\n  const [labels, setLabels] = useState<Array<string>>([])\n  const [values, setValues] = useState<Array<string>>([])\n  const [levValues, setLevValues] = useState<Array<string | null>>([])\n\n  useAppEffect(() => {\n    const { ethPercents, lpPayout, leveragePayout } = getMintAndLpPayoffGraph(ethPrice)\n    setLabels(ethPercents)\n    setValues(lpPayout)\n    setLevValues(leveragePayout)\n  }, [ethPrice])\n\n  const getData = useAppCallback(() => {\n    return {\n      labels,\n      datasets: [\n        {\n          label: '%USD return Mint + LP',\n          data: values,\n          fill: false,\n          borderColor: primaryColor,\n          pointHoverBorderColor: primaryColor,\n          pointHoverBackgroundColor: primaryColor,\n          pointBackgroundColor: 'rgba(0, 0, 0, 0)',\n          pointBorderColor: 'rgba(0, 0, 0, 0)',\n          pointHoverRadius: 5,\n          pointHitRadius: 30,\n        },\n        {\n          label: '%USD return 1x Leverage',\n          data: levValues,\n          fill: false,\n          borderColor: errorColor,\n          pointHoverBorderColor: errorColor,\n          pointHoverBackgroundColor: errorColor,\n          pointBackgroundColor: 'rgba(0, 0, 0, 0)',\n          pointBorderColor: 'rgba(0, 0, 0, 0)',\n          pointHoverRadius: 5,\n          pointHitRadius: 30,\n        },\n      ],\n    }\n  }, [labels, values, levValues])\n\n  return (\n    <div style={{ width: '350px' }}>\n      <Line data={getData} type=\"line\" height={300} width={380} options={chartOptions} />\n    </div>\n  )\n}\n\nexport default memo(LongSqueethPayoff)\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/LongChart.tsx",
    "content": "import {\n  Box,\n  createStyles,\n  Hidden,\n  InputAdornment,\n  makeStyles,\n  TextField,\n  Tooltip,\n  Typography,\n  CircularProgress,\n} from '@material-ui/core'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport dynamic from 'next/dynamic'\nimport Image from 'next/image'\nimport { atom, useAtom, useAtomValue } from 'jotai'\nimport React, { memo } from 'react'\n\nimport ComparisonChart from '../../../public/images/ComparisonChart.svg'\nimport { graphOptions } from '../../constants/diagram'\nimport { Links, Tooltips } from '../../constants/enums'\nimport { SqueethTab, SqueethTabs } from '../Tabs'\nimport LongSqueethPayoff from './LongSqueethPayoff'\nimport FundingChart from './FundingChart'\nimport { useETHPrice } from '@hooks/useETHPrice'\nimport { daysAtom, useLongChartData } from 'src/state/ethPriceCharts/atoms'\nimport LegendBox from '@components/LegendBox'\nimport useAppMemo from '@hooks/useAppMemo'\nenum ChartType {\n  PNL = 'LONG PNL',\n  // Price = 'Price Chart',\n  PositionSize = 'Position Size',\n  // Funding = 'Funding Payment',\n  Payoff = 'Payoff',\n  // Comparison = 'Comparison',\n  Details = 'Details',\n  Risks = 'Risks',\n  Funding = 'Premium',\n}\n\nconst Chart = dynamic(() => import('kaktana-react-lightweight-charts'), { ssr: false })\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    navDiv: {\n      display: 'flex',\n      marginBottom: theme.spacing(2),\n      alignItems: 'center',\n    },\n    chartNav: {\n      border: `1px solid ${theme.palette.primary.main}30`,\n    },\n    cardDetail: {\n      color: theme.palette.text.secondary,\n      lineHeight: '1.75rem',\n      fontSize: '16px',\n      marginTop: theme.spacing(1),\n      maxWidth: '800px',\n    },\n    cardTitle: {\n      color: theme.palette.primary.main,\n    },\n    header: {\n      color: theme.palette.primary.main,\n    },\n    payoffContainer: {\n      display: 'flex',\n      [theme.breakpoints.up('sm')]: {\n        maxHeight: '310px',\n      },\n      [theme.breakpoints.down('sm')]: {\n        flexDirection: 'column',\n      },\n    },\n    intro: {\n      marginTop: '2em',\n      [theme.breakpoints.up('md')]: {\n        marginTop: 0,\n        width: '300px',\n        marginLeft: '20px',\n      },\n    },\n    infoIcon: {\n      fontSize: '1rem',\n      marginLeft: theme.spacing(0.5),\n      marginTop: '2px',\n    },\n    legendBox: {\n      display: 'flex',\n      gap: '10px',\n      marginTop: '10px',\n      justifyContent: 'center',\n    },\n    daysInput: {\n      width: '150px',\n      marginLeft: theme.spacing(2),\n      [theme.breakpoints.down('sm')]: {\n        width: 'auto',\n        marginLeft: theme.spacing(1.5),\n      },\n    },\n    daysInputLabel: {\n      fontSize: '1rem',\n      [theme.breakpoints.down('sm')]: {\n        fontSize: '0.9rem',\n      },\n    },\n  }),\n)\n\nconst chartTradeTypeAtom = atom(0)\n\nconst modeAtom = atom<ChartType>((get) => {\n  const tradeType = get(chartTradeTypeAtom)\n\n  if (tradeType === 0) return ChartType.PNL\n  else if (tradeType === 1) return ChartType.Payoff\n  else if (tradeType === 2) return ChartType.Funding\n  else if (tradeType === 3) return ChartType.Risks\n\n  return ChartType.PNL\n})\n\nfunction LongChart() {\n  const classes = useStyles()\n  const ethPrice = useETHPrice()\n  const [days, setDays] = useAtom(daysAtom)\n  const mode = useAtomValue(modeAtom)\n  const [tradeType, setTradeType] = useAtom(chartTradeTypeAtom)\n  const query = useLongChartData()\n\n  const longEthPNL = query.data?.longEthPNL\n  const longSeries = query.data?.longSeries\n  const positionSizeSeries = query.data?.positionSizeSeries\n  const squeethIsLive = query.data?.squeethIsLive\n\n  // plot line data\n  const lineSeries = useAppMemo(() => {\n    if (!longEthPNL || !longSeries || longSeries.length === 0 || !positionSizeSeries || !squeethIsLive) return\n\n    const liveIndex = Math.max(\n      0,\n      squeethIsLive.findIndex((val: boolean) => val),\n    ) // return 0 when there is no live data\n\n    if (mode === ChartType.PNL)\n      return [\n        { data: longEthPNL, legend: 'Long ETH PNL (%)' },\n        {\n          data: longSeries.slice(0, liveIndex),\n          legend: `Long Squeeth PNL (%) Simulated incl. premiums`,\n        },\n        {\n          data: longSeries.slice(liveIndex),\n          legend: `Long Squeeth PNL (%) (incl. premiums)`,\n        },\n      ]\n    if (mode === ChartType.PositionSize) return [{ data: positionSizeSeries, legend: 'Position Size' }]\n    return []\n  }, [longEthPNL, longSeries, mode, positionSizeSeries, squeethIsLive])\n\n  const chartOptions = useAppMemo(() => {\n    // if (mode === ChartType.Funding || mode === ChartType.PositionSize)\n    if (mode === ChartType.PositionSize)\n      return {\n        ...graphOptions,\n        localization: {\n          priceFormatter: (num: number) => num + '%',\n        },\n      }\n    if (mode === ChartType.PNL)\n      return {\n        ...graphOptions,\n        localization: {\n          priceFormatter: (num: number) => num.toFixed(2) + '%',\n        },\n      }\n    return {\n      ...graphOptions,\n      priceScale: { mode: 2 },\n    }\n  }, [mode])\n\n  const startTimestamp = useAppMemo(() => (longSeries && longSeries.length > 0 ? longSeries[0].time : 0), [longSeries])\n\n  const endTimestamp = useAppMemo(\n    () => (longSeries && longSeries.length > 0 ? longSeries[longSeries.length - 1].time : 0),\n    [longSeries],\n  )\n\n  return (\n    <>\n      {/* show button tabs and enable price chart only during research mode */}\n      {/* {researchMode && ( */}\n      <div className={classes.navDiv}>\n        <SqueethTabs\n          style={{ background: 'transparent' }}\n          className={classes.chartNav}\n          value={tradeType}\n          onChange={(evt, val) => setTradeType(val)}\n          aria-label=\"Sub nav tabs\"\n          scrollButtons=\"auto\"\n          variant=\"scrollable\"\n        >\n          <SqueethTab label={`Historical ${days}D PNL`} />\n          {/* <SqueethTab label=\"Price\" /> */}\n          {/* <SqueethTab label=\"Funding\" /> */}\n          <SqueethTab label=\"Payoff\" />\n          {/* <SqueethTab label=\"Comparison\" /> */}\n          {/* <SqueethTab label=\"Details\" /> */}\n          <SqueethTab label=\"Premium\" />\n          <SqueethTab label=\"Risks\" />\n        </SqueethTabs>\n        {/* <Hidden smDown> */}\n        {mode === ChartType.PNL ? (\n          <TextField\n            onChange={(event) => setDays(parseInt(event.target.value))}\n            size=\"small\"\n            value={days}\n            type=\"number\"\n            className={classes.daysInput}\n            label=\"Historical Days\"\n            variant=\"outlined\"\n            InputLabelProps={{ className: classes.daysInputLabel }}\n            // InputProps={{\n            //   endAdornment: (\n            //     <InputAdornment position=\"end\">\n            //       <a href={Links.BacktestFAQ} target=\"_blank\" rel=\"noreferrer\">\n            //         <Tooltip title={Tooltips.BacktestDisclaimer}>\n            //           <InfoIcon fontSize=\"small\" />\n            //         </Tooltip>\n            //       </a>\n            //     </InputAdornment>\n            //   ),\n            // }}\n          />\n        ) : null}\n        {/* </Hidden> */}\n      </div>\n\n      {mode === ChartType.Payoff ? (\n        <div className={classes.payoffContainer}>\n          <LongSqueethPayoff ethPrice={ethPrice.toNumber()} />\n          <Hidden smDown>\n            <Image src={ComparisonChart} alt=\"Comparison Chart\" height={340} width={600} />\n          </Hidden>\n        </div>\n      ) : mode === ChartType.Details ? (\n        <div style={{ overflow: 'auto', maxHeight: '370px' }}>\n          <Typography className={classes.cardTitle} variant=\"h6\">\n            What is squeeth?\n          </Typography>\n          <Typography variant=\"body2\" className={classes.cardDetail}>\n            Long squeeth (ETH&sup2;) gives you a leveraged position with unlimited upside, protected downside, and no\n            liquidations. Compared to a 2x leveraged position, you make more when ETH goes up and lose less when ETH\n            goes down (excluding premiums). Eg. If ETH goes up 5x, squeeth goes up 25x. You pay a premium for this\n            position. Enter the position by purchasing an ERC20 token.{' '}\n            <a\n              className={classes.header}\n              href=\"https://opyn.gitbook.io/squeeth-faq/squeeth/beginner-squeeth-faq\"\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              {' '}\n              Learn more.{' '}\n            </a>\n          </Typography>\n          {/* <Typography className={classes.cardTitle} variant=\"h6\">\n            Risks\n          </Typography>\n          <Typography variant=\"body2\" className={classes.cardDetail}>\n            Funding is paid out of your position, meaning you sell a small amount of squeeth at funding, reducing your\n            position size. Holding the position for a long period of time without upward movements in ETH can lose\n            considerable funds to funding payments.\n            <br /> <br />\n            Squeeth smart contracts are currently unaudited. This is experimental technology and we encourage caution\n            only risking funds you can afford to lose.\n            <br /> <br />\n            If ETH goes down considerably, you may lose some or all of your initial investment.\n          </Typography> */}\n        </div>\n      ) : mode === ChartType.Risks ? (\n        <div>\n          <Typography className={classes.cardTitle} variant=\"h6\">\n            Risks\n          </Typography>\n          <Typography variant=\"body2\" className={classes.cardDetail}>\n            Premiums are paid out of your position, similar to selling a small amount of squeeth as you earn premiums,\n            reducing your position size. Holding the position for a long period of time without upward movements in ETH\n            can lose considerable funds to premium payments.\n            <br /> <br />\n            Squeeth smart contracts have been audited by Trail of Bits, Akira, and Sherlock. However, smart contracts\n            are experimental technology and we encourage caution only risking funds you can afford to lose.\n            <br /> <br />\n            Profitability also depends on the price you enter and exit, which is dependent on implied volatility (the\n            premium of squeeth to ETH). If the squeeth premium to ETH decreases, without a change in ETH price, a long\n            position will incur a loss because it is not worth as much ETH. If ETH goes down considerably, you may lose\n            some or all of your initial investment.\n            <a\n              className={classes.header}\n              href=\"https://opyn.gitbook.io/squeeth-faq/squeeth/risks\"\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              {' '}\n              Learn more.{' '}\n            </a>\n          </Typography>\n        </div>\n      ) : mode === ChartType.Funding ? (\n        <FundingChart />\n      ) : (\n        // : mode === ChartType.Comparison ? (\n        //   <Image src={ComparisonChart} alt=\"Comparison Chart\" height={340} />\n        // )\n        <div className={classes.payoffContainer} style={{ maxHeight: 'none' }}>\n          <div style={{ flex: '1 1 0', marginTop: '8px' }}>\n            {lineSeries ? (\n              <Chart\n                from={startTimestamp}\n                to={endTimestamp}\n                legend={mode}\n                options={chartOptions}\n                lineSeries={lineSeries}\n                autoWidth\n                // width={1000}\n                height={300}\n                darkTheme\n              />\n            ) : (\n              <Box display=\"flex\" height=\"300px\" width={1} alignItems=\"center\" justifyContent=\"center\">\n                <CircularProgress size={40} color=\"secondary\" />\n              </Box>\n            )}\n\n            <div className={classes.legendBox}>\n              {lineSeries && lineSeries[0].data.length > 0 && <LegendBox bgColor=\"#018FFB\" text=\"ETH PNL\" />}\n              {lineSeries && lineSeries[1].data.length > 0 && (\n                <LegendBox\n                  bgColor=\"#00E396\"\n                  text=\"Squeeth Simulated PnL\"\n                  tooltip=\"The Squeeth Simulated PnL comes from using at the money implied vol from Deribit\"\n                />\n              )}\n              {lineSeries && lineSeries[2].data.length > 0 && <LegendBox bgColor=\"#FEB01B\" text=\"Squeeth LIVE PNL\" />}\n            </div>\n          </div>\n\n          <div className={classes.intro}>\n            <Typography className={classes.cardTitle} variant=\"h6\">\n              What is squeeth?\n            </Typography>\n            <Typography variant=\"body2\" className={classes.cardDetail} style={{ fontSize: '14px' }}>\n              Long squeeth (ETH&sup2;) gives you a leveraged position with unlimited upside, protected downside, and no\n              liquidations. Compared to a 2x leveraged position, you make more when ETH goes up and lose less when ETH\n              goes down (excluding premiums). Eg. If ETH goes up 5x, squeeth goes up 25x. You pay premiums for this\n              position. Enter the position by purchasing an ERC20 token.{' '}\n              <a\n                className={classes.header}\n                href=\"https://opyn.gitbook.io/squeeth-faq/squeeth/beginner-squeeth-faq\"\n                target=\"_blank\"\n                rel=\"noreferrer\"\n              >\n                {' '}\n                Learn more.{' '}\n              </a>\n            </Typography>\n          </div>\n        </div>\n      )}\n    </>\n  )\n}\n\nconst LongChartMemoized = memo(LongChart)\n\nexport { LongChartMemoized as LongChart }\n\n// const convertPNLToPriceChart = (pnlSeries: { time: number; value: number }[], startingCapital: number) => {\n//   return pnlSeries.map(({ value, time }) => {\n//     return {\n//       value: value + startingCapital,\n//       time,\n//     }\n//   })\n// }\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/LongChartPayoff.tsx",
    "content": "import {\n  Box,\n  createStyles,\n  makeStyles,\n  CircularProgress,\n  InputLabel,\n  TextFieldProps,\n  TextField,\n  Divider,\n} from '@material-ui/core'\nimport dynamic from 'next/dynamic'\nimport { useAtom } from 'jotai'\nimport React, { memo } from 'react'\nimport Grid from '@material-ui/core/Grid'\nimport DateFnsUtils from '@date-io/date-fns'\nimport { DatePicker, MuiPickersUtilsProvider } from '@material-ui/pickers'\n\nimport { graphOptions } from '@constants/diagram'\nimport {\n  longPayoffFilterEndDateAtom,\n  longPayoffFilterStartDateAtom,\n  useLongChartData,\n} from 'src/state/ethPriceCharts/atoms'\nimport LegendBox from '@components/LegendBox'\nimport useAppMemo from '@hooks/useAppMemo'\n\nconst Chart = dynamic(() => import('kaktana-react-lightweight-charts'), { ssr: false })\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    label: {\n      fontWeight: 500,\n    },\n    payoffContainer: {\n      [theme.breakpoints.up('sm')]: {\n        maxHeight: '310px',\n      },\n    },\n    legendBox: {\n      display: 'flex',\n      gap: '16px',\n      marginTop: '24px',\n      justifyContent: 'center',\n    },\n    daysInput: {\n      width: '200px',\n      [theme.breakpoints.down('sm')]: {\n        width: 'auto',\n      },\n    },\n    daysInputLabel: {\n      fontSize: '1rem',\n      [theme.breakpoints.down('sm')]: {\n        fontSize: '0.9rem',\n      },\n    },\n    grid: {\n      rowGap: '24px',\n      columnGap: '24px',\n      marginRight: 'auto',\n      padding: theme.spacing(1),\n    },\n    divider: {\n      width: '15px',\n      backgroundColor: '#8C8D8D',\n      height: '1.5px',\n      position: 'relative',\n      top: '6px',\n    },\n  }),\n)\n\nconst useTextFieldStyles = makeStyles((theme) =>\n  createStyles({\n    labelRoot: {\n      color: '#8C8D8D',\n      fontSize: '14px',\n      fontWeight: 500,\n    },\n    inputRoot: {\n      padding: '10px 16px',\n      fontSize: '15px',\n      fontWeight: 500,\n      fontFamily: 'DM Mono',\n      width: '14ch',\n      border: '2px solid #303436',\n      borderRadius: '12px',\n    },\n    inputFocused: {\n      borderColor: theme.palette.primary.main,\n    },\n  }),\n)\n\nconst CustomTextField: React.FC<TextFieldProps> = ({ inputRef, label, InputProps, id, variant, ...props }) => {\n  const classes = useTextFieldStyles()\n\n  return (\n    <Box display=\"flex\" flexDirection=\"column\" gridGap=\"4px\">\n      <InputLabel htmlFor={id} classes={{ root: classes.labelRoot }}>\n        {label}\n      </InputLabel>\n      <TextField\n        id={id}\n        InputProps={{\n          classes: {\n            root: classes.inputRoot,\n            focused: classes.inputFocused,\n          },\n          disableUnderline: true,\n          ...InputProps,\n        }}\n        {...props}\n      />\n    </Box>\n  )\n}\n\nfunction LongChartPayoff() {\n  const [startDate, setStartDate] = useAtom(longPayoffFilterStartDateAtom)\n  const [endDate, setEndDate] = useAtom(longPayoffFilterEndDateAtom)\n\n  const query = useLongChartData()\n\n  const longEthPNL = query.data?.longEthPNL\n  const longSeries = query.data?.longSeries\n  const positionSizeSeries = query.data?.positionSizeSeries\n  const squeethIsLive = query.data?.squeethIsLive\n\n  const classes = useStyles()\n\n  // plot line data\n  const lineSeries = useAppMemo(() => {\n    if (!longEthPNL || !longSeries || longSeries.length === 0 || !positionSizeSeries || !squeethIsLive) return\n\n    const liveIndex = Math.max(\n      0,\n      squeethIsLive.findIndex((val: boolean) => val),\n    ) // return 0 when there is no live data\n\n    return [\n      {\n        data: longEthPNL,\n        legend: 'Long ETH PNL (%)',\n        options: {\n          color: '#CDAEFB',\n        },\n      },\n      {\n        data: longSeries.slice(0, liveIndex),\n        legend: `Long Squeeth PNL (%) Simulated incl. premiums`,\n        options: {\n          color: '#00E396',\n        },\n      },\n      {\n        data: longSeries.slice(liveIndex),\n        legend: `Long Squeeth PNL (%) LIVE (incl. premiums)`,\n        options: {\n          color: '#70E3F6',\n        },\n      },\n    ]\n\n    return []\n  }, [longEthPNL, longSeries, positionSizeSeries, squeethIsLive])\n\n  const chartOptions = useAppMemo(() => {\n    return {\n      ...graphOptions,\n      localization: {\n        priceFormatter: (num: number) => (num ? num.toFixed(2) + '%' : ''),\n      },\n    }\n  }, [])\n\n  const startTimestamp = useAppMemo(() => (longSeries && longSeries.length > 0 ? longSeries[0].time : 0), [longSeries])\n\n  const endTimestamp = useAppMemo(\n    () => (longSeries && longSeries.length > 0 ? longSeries[longSeries.length - 1].time : 0),\n    [longSeries],\n  )\n\n  return (\n    <>\n      <MuiPickersUtilsProvider utils={DateFnsUtils}>\n        <Box display=\"flex\" alignItems=\"center\" gridGap=\"16px\" marginTop=\"16px\">\n          <DatePicker\n            label=\"Start Date\"\n            placeholder=\"MM/DD/YYYY\"\n            format={'MM/dd/yyyy'}\n            value={startDate}\n            maxDate={new Date()}\n            onChange={(d) => setStartDate(d || new Date())}\n            animateYearScrolling={false}\n            autoOk={true}\n            clearable\n            TextFieldComponent={CustomTextField}\n          />\n          <Divider orientation=\"horizontal\" className={classes.divider} />\n          <DatePicker\n            label=\"End Date\"\n            placeholder=\"MM/DD/YYYY\"\n            format={'MM/dd/yyyy'}\n            value={endDate}\n            maxDate={new Date()}\n            onChange={(d) => setEndDate(d || new Date())}\n            animateYearScrolling={false}\n            autoOk={true}\n            clearable\n            TextFieldComponent={CustomTextField}\n          />\n        </Box>\n      </MuiPickersUtilsProvider>\n\n      <div className={classes.payoffContainer}>\n        <div style={{ marginTop: '8px' }}>\n          {lineSeries ? (\n            <Chart\n              from={startTimestamp}\n              to={endTimestamp}\n              legend={'LONG PNL'}\n              options={chartOptions}\n              lineSeries={lineSeries}\n              autoWidth\n              height={300}\n              darkTheme\n            />\n          ) : (\n            <Box display=\"flex\" height=\"300px\" width={1} alignItems=\"center\" justifyContent=\"center\">\n              <CircularProgress size={40} color=\"secondary\" />\n            </Box>\n          )}\n\n          <div className={classes.legendBox}>\n            {lineSeries && lineSeries[0].data.length > 0 && <LegendBox bgColor=\"#CDAEFB\" text=\"ETH PNL\" />}\n            {lineSeries && lineSeries[1].data.length > 0 && (\n              <LegendBox\n                bgColor=\"#00E396\"\n                text=\"Squeeth Simulated PnL\"\n                tooltip=\"The Squeeth Simulated PnL comes from using at the money implied vol from Deribit\"\n              />\n            )}\n            {lineSeries && lineSeries[2].data.length > 0 && <LegendBox bgColor=\"#70E3F6\" text=\"Squeeth PNL\" />}\n          </div>\n        </div>\n      </div>\n    </>\n  )\n}\n\nconst LongChartPayoffMemoized = memo(LongChartPayoff)\n\nexport { LongChartPayoffMemoized as LongChartPayoff }\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/LongSqueethPayoff.tsx",
    "content": "import useAppCallback from '@hooks/useAppCallback'\nimport useAppEffect from '@hooks/useAppEffect'\nimport React, { memo, useState } from 'react'\nimport { Line } from 'react-chartjs-2'\n\nimport { getSqueethLongPayOffGraph } from '../../utils'\n\nconst primaryColor = '#2CE6F9'\nconst errorColor = '#EC7987'\n\nconst chartOptions = {\n  maintainAspectRatio: false,\n  responsive: false,\n  title: { display: true },\n  legend: {\n    display: true,\n    labels: {\n      filter: (legendItem: any) => {\n        const label = legendItem.text\n        if (label === '2xLeverage') return false\n        return true\n      },\n    },\n  },\n  scales: {\n    yAxes: [\n      {\n        display: true,\n        gridLines: {\n          zeroLineWidth: 0,\n          lineWidth: 0,\n        },\n        ticks: {\n          display: true,\n        },\n        scaleLabel: {\n          labelString: '% Return',\n          display: true,\n        },\n      },\n    ],\n    xAxes: [\n      {\n        display: true,\n        scaleLabel: {\n          labelString: '% Change in ETH price',\n          display: true,\n        },\n        ticks: {\n          display: true,\n          autoSkip: true,\n          maxTicksLimit: 10,\n        },\n        gridLines: {\n          lineWidth: 0,\n          zeroLineWidth: 0,\n        },\n      },\n    ],\n  },\n  tooltips: {\n    enabled: true,\n    intersect: false,\n    mode: 'index',\n    callbacks: {\n      label: function (tooltipItem: any, data: any) {\n        return `${data.datasets[tooltipItem.datasetIndex].label}: ${tooltipItem.yLabel} %`\n      },\n      title: function (tooltipItem: any) {\n        return `${tooltipItem[0].xLabel} % ETH Change`\n      },\n    },\n  },\n  animation: { duration: 0 },\n  hover: { animationDuration: 0, intersect: false },\n  onHover: (_: any, elements: any) => {\n    if (elements && elements.length) {\n      const chartElem = elements[0]\n      const chart = chartElem._chart\n      const ctx = chart.ctx\n\n      ctx.globalCompositeOperation = 'destination-over'\n      const x = chartElem._view.x\n      const topY = chart.scales['y-axis-0'].top\n      const bottomY = chart.scales['y-axis-0'].bottom\n\n      ctx.save()\n      ctx.beginPath()\n      ctx.setLineDash([5, 5])\n      ctx.moveTo(x, topY)\n      ctx.lineTo(x, bottomY)\n      ctx.lineWidth = 1\n      ctx.strokeStyle = '#77757E80'\n      ctx.stroke()\n      ctx.restore()\n\n      ctx.globalCompositeOperation = 'source-over'\n    }\n  },\n}\n\nconst LongSqueethPayoff: React.FC<{ ethPrice: number }> = ({ ethPrice }) => {\n  const [labels, setLabels] = useState<Array<string>>([])\n  const [values, setValues] = useState<Array<string>>([])\n  const [twoXValues, setTwoXvalues] = useState<Array<number | null>>([])\n  const [twoXImgValues, setTwoXImgvalues] = useState<Array<number | null>>([])\n\n  useAppEffect(() => {\n    const { ethPercents, powerTokenPayout, twoXLeverage, twoXLeverageImaginary } = getSqueethLongPayOffGraph(ethPrice)\n    setLabels(ethPercents)\n    setValues(powerTokenPayout)\n    setTwoXvalues(twoXLeverage)\n    setTwoXImgvalues(twoXLeverageImaginary)\n  }, [ethPrice])\n\n  const getData = useAppCallback(() => {\n    return {\n      labels,\n      datasets: [\n        {\n          label: 'Squeeth',\n          data: values,\n          fill: false,\n          borderColor: primaryColor,\n          pointHoverBorderColor: primaryColor,\n          pointHoverBackgroundColor: primaryColor,\n          pointBackgroundColor: 'rgba(0, 0, 0, 0)',\n          pointBorderColor: 'rgba(0, 0, 0, 0)',\n          pointHoverRadius: 5,\n          pointHitRadius: 30,\n        },\n        {\n          label: '2x Leverage',\n          data: twoXValues,\n          fill: false,\n          borderColor: errorColor,\n          pointHoverBorderColor: errorColor,\n          pointHoverBackgroundColor: errorColor,\n          pointBackgroundColor: 'rgba(0, 0, 0, 0)',\n          pointBorderColor: 'rgba(0, 0, 0, 0)',\n          pointHoverRadius: 5,\n          pointHitRadius: 30,\n        },\n        {\n          label: '2xLeverage',\n          data: twoXImgValues,\n          fill: false,\n          borderDash: [5, 5],\n          borderColor: errorColor,\n          pointHoverBorderColor: errorColor,\n          pointHoverBackgroundColor: errorColor,\n          pointBackgroundColor: 'rgba(0, 0, 0, 0)',\n          pointBorderColor: 'rgba(0, 0, 0, 0)',\n          pointHoverRadius: 5,\n          pointHitRadius: 30,\n        },\n      ],\n    }\n  }, [labels, values, twoXValues, twoXImgValues])\n\n  return (\n    <div style={{ width: '350px' }}>\n      <Line data={getData} type=\"line\" height={300} width={380} options={chartOptions} />\n    </div>\n  )\n}\n\nexport default memo(LongSqueethPayoff)\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/ShortChart.tsx",
    "content": "import { useETHPrice } from '@hooks/useETHPrice'\nimport { createStyles, makeStyles, TextField, Typography } from '@material-ui/core'\nimport Alert from '@material-ui/lab/Alert'\nimport { useAtomValue } from 'jotai'\nimport React, { memo, useState } from 'react'\nimport { collatRatioAtom, useGetVaultPNLWithRebalance } from 'src/state/ethPriceCharts/atoms'\n\nimport { Links, Vaults } from '../../constants'\nimport { SqueethTab, SqueethTabs } from '../Tabs'\nimport FundingChart from './FundingChart'\nimport ShortSqueethPayoff from './ShortSqueethPayoff'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    navDiv: {\n      display: 'flex',\n      marginBottom: theme.spacing(2),\n      alignItems: 'center',\n    },\n    chartNav: {\n      border: `1px solid ${theme.palette.primary.main}30`,\n      [theme.breakpoints.down('sm')]: {\n        width: '100%',\n      },\n    },\n    cardDetail: {\n      color: theme.palette.text.secondary,\n      lineHeight: '1.75rem',\n      fontSize: '14px',\n      marginTop: theme.spacing(2),\n      maxWidth: '800px',\n    },\n    cardTitle: {\n      color: theme.palette.primary.main,\n    },\n    header: {\n      color: theme.palette.primary.main,\n    },\n    payoffContainer: {\n      display: 'grid',\n      gap: '2rem',\n      overflow: 'auto',\n      // maxHeight: '310',\n      [theme.breakpoints.up('md')]: {\n        gridTemplateColumns: '1fr 1fr',\n      },\n    },\n    shortPayoff: {\n      width: '90%',\n      margin: '0 auto',\n      [theme.breakpoints.up('md')]: {\n        width: '100%',\n        margin: 0,\n      },\n    },\n    shortDescription: {\n      [theme.breakpoints.up('md')]: {\n        justifySelf: 'end',\n      },\n    },\n  }),\n)\n\nfunction ShortChart({\n  vault,\n  longAmount,\n  setCustomLong,\n}: {\n  vault?: Vaults\n  longAmount: number\n  setCustomLong: Function\n  showPercentage: boolean\n}) {\n  const ethPrice = useETHPrice()\n  const collatRatio = useAtomValue(collatRatioAtom)\n  const getVaultPNLWithRebalance = useGetVaultPNLWithRebalance()\n\n  const seriesRebalance = getVaultPNLWithRebalance(longAmount)\n  const classes = useStyles()\n  const [chartType, setChartType] = useState(0)\n\n  return (\n    <div>\n      <div className={classes.navDiv}>\n        <SqueethTabs\n          style={{ background: 'transparent' }}\n          className={classes.chartNav}\n          value={chartType}\n          onChange={(evt, val) => setChartType(val)}\n          aria-label=\"Sub nav tabs\"\n        >\n          <SqueethTab label=\"Payoff\" />\n          <SqueethTab label=\"Premium\" />\n          <SqueethTab label=\"Risks\" />\n        </SqueethTabs>\n      </div>\n      {seriesRebalance && seriesRebalance.length === 0 && (\n        <Alert severity=\"info\"> Loading historical data, this could take a while</Alert>\n      )}\n      {chartType === 0 ? (\n        <div className={classes.payoffContainer}>\n          <div className={classes.shortPayoff}>\n            <ShortSqueethPayoff ethPrice={ethPrice.toNumber()} collatRatio={collatRatio} />\n          </div>\n\n          <div className={classes.shortDescription}>\n            <Typography className={classes.cardTitle} variant=\"h6\">\n              What is short squeeth?\n            </Typography>\n            <Typography variant=\"body2\" className={classes.cardDetail}>\n              Short squeeth (ETH&sup2;) is an ETH collateralized short ETH&sup2; position. Your returns will be a\n              combination of being short oSQTH and long ETH collateral. You earn a funding rate for taking on this\n              position. You enter the position by putting down collateral, minting, and selling squeeth. You provide ETH\n              collateral to mint squeeth, and your collateralization ratio determines your exposure. If you become\n              undercollateralized, you could be liquidated.{' '}\n              <a\n                className={classes.header}\n                href=\"https://opyn.gitbook.io/squeeth-faq/squeeth/beginner-squeeth-faq\"\n                target=\"_blank\"\n                rel=\"noreferrer\"\n              >\n                {' '}\n                Learn more.{' '}\n              </a>\n            </Typography>\n          </div>\n        </div>\n      ) : chartType === 1 ? (\n        <FundingChart />\n      ) : (\n        <div>\n          {' '}\n          <Typography className={classes.cardTitle} variant=\"h6\">\n            Risks\n          </Typography>\n          <Typography variant=\"body2\" className={classes.cardDetail}>\n            If you fall below the minimum collateralization threshold (150%), you are at risk of liquidation. This\n            position performs best when ETH price does not move much. If ETH price moves considerably, it is likely\n            unprofitable.\n            <br /> <br />\n            Squeeth smart contracts have been audited by Trail of Bits, Akira, and Sherlock. However, smart contracts\n            are experimental technology and we encourage caution only risking funds you can afford to lose.\n            <a\n              className={classes.header}\n              href=\"https://opyn.gitbook.io/squeeth-faq/squeeth/risks\"\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              {' '}\n              Learn more.{' '}\n            </a>\n          </Typography>\n        </div>\n      )}\n      <br />\n      {vault === Vaults.Custom && (\n        <TextField\n          onChange={(event) => setCustomLong(parseFloat(event.target.value))}\n          size=\"small\"\n          value={longAmount}\n          type=\"number\"\n          style={{ width: 300 }}\n          label=\"ETH Long\"\n          variant=\"outlined\"\n        />\n      )}\n    </div>\n  )\n}\n\nexport const MemoizedShortChart = memo(ShortChart)\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/ShortFundingChart.tsx",
    "content": "import { memo } from 'react'\nimport { Box, CircularProgress, createStyles, makeStyles, Tooltip } from '@material-ui/core'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport dynamic from 'next/dynamic'\nimport React, { useState } from 'react'\nimport CustomSwitch, { SwitchItem } from '@components/CustomSwitch'\nimport { useNormHistory } from '@hooks/useNormHistory'\nimport { Tooltips } from '@constants/enums'\nimport { graphOptions } from '../../constants/diagram'\n\nconst Chart = dynamic(() => import('kaktana-react-lightweight-charts'), { ssr: false })\n\nconst useStyles = makeStyles(() =>\n  createStyles({\n    switchWrapper: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      alignItems: 'center',\n      flexWrap: 'wrap',\n      marginBottom: '16px',\n    },\n    legendBox: {\n      display: 'flex',\n      gap: '16px',\n      marginTop: '24px',\n      justifyContent: 'center',\n    },\n    legendContainer: {\n      display: 'flex',\n      gap: '5px',\n    },\n    iconWrapper: {\n      display: 'flex',\n      marginLeft: 6,\n    },\n  }),\n)\n\nconst FundingChart = () => {\n  const classes = useStyles()\n\n  const fundingTypes = [\n    { id: 'funding', text: 'Premium' },\n    {\n      id: 'vol',\n      text: 'VOL',\n      itemToAdd: (\n        <div className={classes.iconWrapper}>\n          <Tooltip title={Tooltips.FundingVol}>\n            <InfoIcon fontSize=\"small\" />\n          </Tooltip>\n        </div>\n      ),\n    },\n  ]\n  const fundingDurations = [\n    {\n      id: 'day',\n      text: 'Day',\n      itemToAdd: (\n        <div className={classes.iconWrapper}>\n          <Tooltip title={Tooltips.FundingDaily}>\n            <InfoIcon fontSize=\"small\" />\n          </Tooltip>\n        </div>\n      ),\n    },\n    {\n      id: 'month',\n      text: 'Month',\n      itemToAdd: (\n        <div className={classes.iconWrapper}>\n          <Tooltip title={Tooltips.FundingMonthly}>\n            <InfoIcon fontSize=\"small\" />\n          </Tooltip>\n        </div>\n      ),\n    },\n    {\n      id: 'year',\n      text: 'Annualized',\n      itemToAdd: (\n        <div className={classes.iconWrapper}>\n          <Tooltip title={Tooltips.FundingAnnual}>\n            <InfoIcon fontSize=\"small\" />\n          </Tooltip>\n        </div>\n      ),\n    },\n  ]\n  const [fundingType, setFundingType] = useState<SwitchItem>(fundingTypes[0])\n  const [fundingDuration, setFundingDuration] = useState<SwitchItem>(fundingDurations[0])\n\n  const { normHistory: normFactors, fetchingComplete } = useNormHistory()\n  const graphData = normFactors.map((item) => {\n    const secondsElapsed = Number(item.timestamp) - Number(item.lastModificationTimestamp)\n    const deltaT = secondsElapsed / (420 * 60 * 60)\n    const markIndex = 1 / Math.exp(Math.log(Number(item.newNormFactor) / Number(item.oldNormFactor)) / deltaT)\n    const dayFunding = Math.log(markIndex) / 17.5\n    const monthFunding = dayFunding * 30\n    const yearFunding = dayFunding * 365.25\n    const annualVol = (dayFunding < 0 ? -1 : 1) * Math.sqrt(Math.abs(dayFunding) * 365)\n    const value =\n      (fundingType.id === 'vol'\n        ? annualVol\n        : fundingDuration.id === 'day'\n        ? dayFunding\n        : fundingDuration.id === 'month'\n        ? monthFunding\n        : yearFunding) * 100\n    return { time: Number(item.timestamp), value: parseFloat(value.toFixed(4)) }\n  })\n  const chartOptions = {\n    ...graphOptions,\n    localization: {\n      priceFormatter: (num: number) => `${num < 0 ? num.toFixed(3) : num.toFixed(4)}%`,\n    },\n  }\n  const startTimestamp = normFactors.length > 0 ? Number(normFactors[0].timestamp) : undefined\n  const endTimestamp = normFactors.length > 0 ? Number(normFactors[normFactors.length - 1].timestamp) : undefined\n  const legendText =\n    fundingType.id === 'vol'\n      ? 'Annual Vol'\n      : fundingDuration.id === 'day'\n      ? 'Daily Premium'\n      : fundingDuration.id === 'month'\n      ? 'Monthly Premium'\n      : 'Annual Premium'\n\n  return (\n    <>\n      <div style={{ width: '100%' }}>\n        <div className={classes.switchWrapper}>\n          <CustomSwitch items={fundingTypes} value={fundingType} onChange={setFundingType} />\n          {fundingType.id === 'funding' && (\n            <CustomSwitch items={fundingDurations} value={fundingDuration} onChange={setFundingDuration} />\n          )}\n        </div>\n        {fetchingComplete ? (\n          <>\n            <Chart\n              from={startTimestamp}\n              to={endTimestamp}\n              legend=\"Funding\"\n              options={chartOptions}\n              lineSeries={[{ data: graphData, legend: `${legendText} (%) `, options: { color: '#70E3F6' } }]}\n              autoWidth\n              height={300}\n              darkTheme\n            />\n            <div className={classes.legendBox}>\n              <div className={classes.legendContainer}>\n                <div style={{ width: '20px', height: '20px', backgroundColor: '#70E3F6' }}></div>\n                <div>{legendText}</div>\n              </div>\n            </div>\n          </>\n        ) : (\n          <Box display=\"flex\" height=\"300px\" width={1} alignItems=\"center\" justifyContent=\"center\">\n            <CircularProgress size={40} color=\"secondary\" />\n          </Box>\n        )}\n      </div>\n    </>\n  )\n}\n\nexport default memo(FundingChart)\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/ShortSqueethPayoff.tsx",
    "content": "import useSqueethShortPayOffGraph from '@hooks/payOffGraph/useSqueethShortPayOffGraph'\nimport React, { memo, useCallback } from 'react'\nimport { Line } from 'react-chartjs-2'\n\nimport { Vaults } from '../../constants'\n\nconst color0 = '#6df7e7'\nconst color1 = '#6df7e7'\nconst color14 = '#6d78f7'\nconst color28 = '#F5B073'\n\nconst chartOptions = {\n  maintainAspectRatio: false,\n  responsive: false,\n  title: { display: true },\n  legend: {\n    display: true,\n  },\n  scales: {\n    yAxes: [\n      {\n        display: true,\n        gridLines: {\n          zeroLineWidth: 2,\n          lineWidth: 0,\n          zeroLineColor: '#77757E80',\n        },\n        ticks: {\n          display: true,\n        },\n        scaleLabel: {\n          labelString: '% Return',\n          display: true,\n        },\n      },\n    ],\n    xAxes: [\n      {\n        display: true,\n        scaleLabel: {\n          labelString: 'ETH price',\n          display: true,\n        },\n        ticks: {\n          display: true,\n          autoSkip: true,\n          maxTicksLimit: 10,\n        },\n        gridLines: {\n          lineWidth: 0,\n          zeroLineWidth: 0,\n        },\n      },\n    ],\n  },\n  tooltips: {\n    enabled: true,\n    intersect: false,\n    mode: 'index',\n    callbacks: {\n      label: function (tooltipItem: any, data: any) {\n        return `${data.datasets[tooltipItem.datasetIndex].label}: ${tooltipItem.yLabel} %`\n      },\n      title: function (tooltipItem: any) {\n        return `ETH Price: $${tooltipItem[0].xLabel}`\n      },\n    },\n  },\n  animation: { duration: 0 },\n  hover: { animationDuration: 0, intersect: false },\n  onHover: (_: any, elements: any) => {\n    if (elements && elements.length) {\n      const chartElem = elements[0]\n      const chart = chartElem._chart\n      const ctx = chart.ctx\n\n      ctx.globalCompositeOperation = 'destination-over'\n      const x = chartElem._view.x\n      const topY = chart.scales['y-axis-0'].top\n      const bottomY = chart.scales['y-axis-0'].bottom\n\n      ctx.save()\n      ctx.beginPath()\n      ctx.setLineDash([5, 5])\n      ctx.moveTo(x, topY)\n      ctx.lineTo(x, bottomY)\n      ctx.lineWidth = 1\n      ctx.strokeStyle = '#77757E80'\n      ctx.stroke()\n      ctx.restore()\n\n      ctx.globalCompositeOperation = 'source-over'\n    }\n  },\n}\n\nconst ShortSqueethPayoff: React.FC<{ ethPrice: number; collatRatio: number; vaultType?: Vaults }> = ({\n  ethPrice,\n  collatRatio,\n  vaultType,\n}) => {\n  const {\n    ethPrices: labels,\n    payout0: values0,\n    payout1: values1,\n    payout14: values14,\n    payout28: values28,\n  } = useSqueethShortPayOffGraph(ethPrice, collatRatio)\n\n  const getData = useCallback(() => {\n    return {\n      labels,\n      datasets: [\n        {\n          label: '28 day return',\n          data: values28,\n          fill: false,\n          borderColor: color28,\n          pointHoverBorderColor: color28,\n          pointHoverBackgroundColor: color28,\n          pointBackgroundColor: 'rgba(0, 0, 0, 0)',\n          pointBorderColor: 'rgba(0, 0, 0, 0)',\n          pointHoverRadius: 5,\n          pointHitRadius: 30,\n        },\n        {\n          label: '14 day return',\n          data: values14,\n          fill: false,\n          borderColor: color14,\n          pointHoverBorderColor: color14,\n          pointHoverBackgroundColor: color14,\n          pointBackgroundColor: 'rgba(0, 0, 0, 0)',\n          pointBorderColor: 'rgba(0, 0, 0, 0)',\n          pointHoverRadius: 5,\n          pointHitRadius: 30,\n        },\n        {\n          label: '0 day return',\n          data: values0,\n          fill: false,\n          borderColor: color0,\n          pointHoverBorderColor: color0,\n          pointHoverBackgroundColor: color0,\n          pointBackgroundColor: 'rgba(0, 0, 0, 0)',\n          pointBorderColor: 'rgba(0, 0, 0, 0)',\n          pointHoverRadius: 5,\n          pointHitRadius: 30,\n        },\n      ],\n    }\n  }, [labels, values0, values14, values28])\n\n  const getCrabData = useCallback(() => {\n    return {\n      labels,\n      datasets: [\n        {\n          label: '1 day return',\n          data: values1,\n          fill: false,\n          borderColor: color1,\n          pointHoverBorderColor: color1,\n          pointHoverBackgroundColor: color1,\n          pointBackgroundColor: 'rgba(0, 0, 0, 0)',\n          pointBorderColor: 'rgba(0, 0, 0, 0)',\n          pointHoverRadius: 5,\n          pointHitRadius: 30,\n        },\n      ],\n    }\n  }, [labels, values1])\n\n  return (\n    <div style={{ width: '100%' }}>\n      {vaultType === Vaults.CrabVault ? (\n        <Line data={getCrabData} type=\"line\" height={300} width={400} options={chartOptions} />\n      ) : (\n        <Line data={getData} type=\"line\" height={300} width={400} options={chartOptions} />\n      )}\n    </div>\n  )\n}\n\nexport default memo(ShortSqueethPayoff)\n"
  },
  {
    "path": "packages/frontend/src/components/Charts/VaultChart.tsx",
    "content": "import { useETHPrice } from '@hooks/useETHPrice'\nimport { createStyles, makeStyles, TextField, Typography } from '@material-ui/core'\nimport Alert from '@material-ui/lab/Alert'\nimport { useAtomValue } from 'jotai'\n\nimport React, { useState } from 'react'\nimport { collatRatioAtom, useGetVaultPNLWithRebalance } from 'src/state/ethPriceCharts/atoms'\n\nimport { Links, Vaults } from '../../constants'\nimport { SqueethTab, SqueethTabs } from '../Tabs'\nimport ShortSqueethPayoff from './ShortSqueethPayoff'\n\n// const Chart = dynamic(() => import('kaktana-react-lightweight-charts'), { ssr: false })\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    navDiv: {\n      display: 'flex',\n      marginBottom: theme.spacing(2),\n      alignItems: 'center',\n    },\n    chartNav: {\n      border: `1px solid ${theme.palette.primary.main}30`,\n      [theme.breakpoints.down('sm')]: {\n        width: '100%',\n      },\n    },\n    cardDetail: {\n      color: theme.palette.text.secondary,\n      lineHeight: '1.75rem',\n      fontSize: '14px',\n      marginTop: theme.spacing(2),\n      maxWidth: '800px',\n    },\n    cardTitle: {\n      color: theme.palette.primary.main,\n    },\n    header: {\n      color: theme.palette.primary.main,\n    },\n    payoffContainer: {\n      display: 'grid',\n      gap: '2rem',\n      overflow: 'auto',\n      // maxHeight: '310',\n      [theme.breakpoints.up('md')]: {\n        gridTemplateColumns: '1fr 1fr',\n      },\n    },\n    shortPayoff: {\n      width: '90%',\n      margin: '0 auto',\n      [theme.breakpoints.up('md')]: {\n        width: '100%',\n        margin: 0,\n      },\n    },\n    shortDescription: {\n      [theme.breakpoints.up('md')]: {\n        justifySelf: 'end',\n      },\n    },\n  }),\n)\n\nexport function VaultChart({\n  vault,\n  longAmount,\n  setCustomLong,\n}: {\n  vault?: Vaults\n  longAmount: number\n  setCustomLong: Function\n  showPercentage: boolean\n}) {\n  const ethPrice = useETHPrice()\n  const collatRatio = useAtomValue(collatRatioAtom)\n  const getVaultPNLWithRebalance = useGetVaultPNLWithRebalance()\n  const seriesRebalance = getVaultPNLWithRebalance(longAmount)\n  const classes = useStyles()\n  const [chartType, setChartType] = useState(0)\n\n  // const startTimestamp = useMemo(() => (seriesRebalance ? seriesRebalance[0].time : 0), [seriesRebalance])\n  // const endTimestamp = useMemo(\n  //   () => (seriesRebalance.length > 0 ? seriesRebalance[seriesRebalance.length - 1].time : 0),\n  //   [seriesRebalance],\n  // )\n\n  // const lineSeries = useMemo(() => {\n  //   if (vault === Vaults.ETHZenBull)\n  //     return [\n  //       { data: longEthPNL, legend: 'Long ETH' },\n  //       { data: seriesRebalance, legend: 'ETH Bull Strategy (incl. funding)' },\n  //     ]\n  //   if (vault === Vaults.CrabVault)\n  //     return [\n  //       { data: seriesRebalance, legend: 'Crab Strategy PNL (incl. funding)' },\n  //       { data: getStableYieldPNL(longAmount), legend: 'Compound Interest yield' },\n  //     ]\n  //   if (vault === Vaults.ETHBear)\n  //     return [\n  //       { data: shortEthPNL, legend: 'Short ETH' },\n  //       { data: seriesRebalance, legend: 'ETH Bear Strategy (incl. funding)' },\n  //     ]\n  //   if (vault === Vaults.Short)\n  //     return [\n  //       // { data: shortEthPNL, legend: 'Short ETH PNL' },\n  //       // { data: shortSeries, legend: 'Short Squeeth PNL (incl. funding)' },\n  //       { data: convertPNLToPriceChart(shortEthPNL, startingETHPrice), legend: 'Short ETH' },\n  //       { data: convertPNLToPriceChart(shortSeries, startingETHPrice), legend: 'Short Squeeth (incl. funding)' },\n  //     ]\n  //   return [{ data: seriesRebalance, legend: 'PNL' }]\n  // }, [vault, longEthPNL, shortEthPNL, seriesRebalance, getStableYieldPNL, longAmount, shortSeries])\n\n  // const lineSeriesPercentage = useMemo(() => {\n  //   if (vault === Vaults.ETHZenBull)\n  //     return [\n  //       { data: convertPNLToPriceChart(longEthPNL, startingETHPrice), legend: 'Long ETH' },\n  //       {\n  //         data: convertPNLToPriceChart(seriesRebalance, startingETHPrice),\n  //         legend: 'ETH Bull Strategy (incl. funding)',\n  //       },\n  //     ]\n  //   if (vault === Vaults.CrabVault)\n  //     return [\n  //       {\n  //         data: convertPNLToPriceChart(getStableYieldPNL(longAmount), startingETHPrice),\n  //         legend: 'Compound Interest Yield',\n  //       },\n  //       {\n  //         data: convertPNLToPriceChart(seriesRebalance, startingETHPrice),\n  //         legend: 'Crab Strategy PNL (incl. funding)',\n  //       },\n  //     ]\n  //   if (vault === Vaults.ETHBear)\n  //     return [\n  //       { data: convertPNLToPriceChart(shortEthPNL, startingETHPrice), legend: 'Short ETH' },\n  //       {\n  //         data: convertPNLToPriceChart(seriesRebalance, startingETHPrice),\n  //         legend: 'ETH Bear Strategy (incl. funding)',\n  //       },\n  //     ]\n  //   if (vault === Vaults.Short)\n  //     return [\n  //       // { data: shortEthPNL, legend: 'Short ETH PNL' },\n  //       // { data: shortSeries, legend: 'Short Squeeth PNL (incl. funding)' },\n  //       { data: convertPNLToPriceChart(shortEthPNL, startingETHPrice), legend: 'Short ETH' },\n  //       { data: convertPNLToPriceChart(shortSeries, startingETHPrice), legend: 'Short Squeeth (incl. funding)' },\n  //     ]\n  //   return [{ data: seriesRebalance, legend: 'PNL' }]\n  // }, [vault, longEthPNL, shortEthPNL, seriesRebalance, getStableYieldPNL, longAmount, startingETHPrice, shortSeries])\n\n  // const chartOptions = useMemo(() => {\n  //   if (showPercentage)\n  //     return {\n  //       ...graphOptions,\n  //       priceScale: { mode: 2 },\n  //       localization: {\n  //         priceFormatter: (num: number) => num + '%',\n  //       },\n  //     }\n  //   else return graphOptions\n  // }, [showPercentage])\n\n  return (\n    <div>\n      <div className={classes.navDiv}>\n        <SqueethTabs\n          style={{ background: 'transparent' }}\n          className={classes.chartNav}\n          value={chartType}\n          onChange={(evt, val) => setChartType(val)}\n          aria-label=\"Sub nav tabs\"\n        >\n          {/* <SqueethTab label={`Historical ${days}D PNL`} /> */}\n          <SqueethTab label=\"Payoff\" />\n          {/* <SqueethTab label=\"Details\" /> */}\n          <SqueethTab label=\"Risks\" />\n        </SqueethTabs>\n        {/* <Hidden smDown>\n          {chartType === 0 ? (\n            <TextField\n              onChange={(event) => setDays(parseInt(event.target.value))}\n              size=\"small\"\n              value={days}\n              type=\"number\"\n              style={{ width: 150, marginLeft: '16px' }}\n              label=\"Historical Days\"\n              variant=\"outlined\"\n              InputProps={{\n                endAdornment: (\n                  <InputAdornment position=\"end\">\n                    <a href={Links.BacktestFAQ} target=\"_blank\" rel=\"noreferrer\">\n                      <Tooltip title={Tooltips.BacktestDisclaimer}>\n                        <InfoIcon fontSize=\"small\" />\n                      </Tooltip>\n                    </a>\n                  </InputAdornment>\n                ),\n              }}\n            />\n          ) : null}\n        </Hidden> */}\n      </div>\n      {seriesRebalance && seriesRebalance.length === 0 && (\n        <Alert severity=\"info\"> Loading historical data, this could take a while</Alert>\n      )}\n      {chartType === 0 ? (\n        <div className={classes.payoffContainer}>\n          <div className={classes.shortPayoff}>\n            <ShortSqueethPayoff ethPrice={ethPrice.toNumber()} collatRatio={collatRatio} />\n          </div>\n\n          <div className={classes.shortDescription}>\n            <Typography className={classes.cardTitle} variant=\"h6\">\n              What is short squeeth?\n            </Typography>\n            <Typography variant=\"body2\" className={classes.cardDetail}>\n              Short squeeth (ETH&sup2;) is an ETH collateralized short ETH&sup2; position. Your returns will be a\n              combination of being short oSQTH and long ETH collateral. You earn a funding rate for taking on this\n              position. You enter the position by putting down collateral, minting, and selling squeeth. You provide ETH\n              collateral to mint squeeth, and your collateralization ratio determines your exposure. If you become\n              undercollateralized, you could be liquidated.{' '}\n              <a\n                className={classes.header}\n                href=\"https://opyn.gitbook.io/squeeth-faq/squeeth/beginner-squeeth-faq\"\n                target=\"_blank\"\n                rel=\"noreferrer\"\n              >\n                {' '}\n                Learn more.{' '}\n              </a>\n            </Typography>\n          </div>\n        </div>\n      ) : (\n        // <Chart\n        //   from={Math.floor(startTimestamp)}\n        //   to={endTimestamp}\n        //   // legend={`${vault} PNL`}\n        //   options={chartOptions}\n        //   lineSeries={showPercentage ? lineSeriesPercentage : lineSeries}\n        //   autoWidth\n        //   height={290}\n        //   darkTheme\n        // />\n        // )\n        // : chartType === 1 ? (\n        //   <div className={classes.payoffContainer}>\n        //     <ShortSqueethPayoff ethPrice={ethPrice.toNumber()} collatRatio={collatRatio} />\n        //   </div>\n        // chartType === 1 ? (\n        //   <div style={{ overflow: 'auto', maxHeight: '300px' }}>\n        //     <Typography className={classes.cardTitle} variant=\"h6\">\n        //       What is short squeeth?\n        //     </Typography>\n        //     <Typography variant=\"body2\" className={classes.cardDetail}>\n        //       Short squeeth (ETH&sup2;) is short an ETH&sup2; position. You earn a funding rate for taking on this\n        //       position. You enter the position by putting down collateral, minting, and selling squeeth. You provide ETH\n        //       collateral to mint squeeth, and your collateralization ratio determines your exposure. If you become\n        //       undercollateralized, you could be liquidated.{' '}\n        //       <a\n        //         className={classes.header}\n        //         href=\"https://opyn.gitbook.io/squeeth/resources/squeeth-faq\"\n        //         target=\"_blank\"\n        //         rel=\"noreferrer\"\n        //       >\n        //         {' '}\n        //         Learn more.{' '}\n        //       </a>\n        //     </Typography>\n        //   </div>\n        // ) :\n        <div>\n          {' '}\n          <Typography className={classes.cardTitle} variant=\"h6\">\n            Risks\n          </Typography>\n          <Typography variant=\"body2\" className={classes.cardDetail}>\n            If you fall below the minimum collateralization threshold (150%), you are at risk of liquidation. This\n            position performs best when ETH price does not move much. If ETH price moves considerably, it is likely\n            unprofitable.\n            <br /> <br />\n            Squeeth smart contracts have been audited by Trail of Bits, Akira, and Sherlock. However, smart contracts\n            are experimental technology and we encourage caution only risking funds you can afford to lose.\n            <a\n              className={classes.header}\n              href=\"https://opyn.gitbook.io/squeeth-faq/squeeth/risks\"\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              {' '}\n              Learn more.{' '}\n            </a>\n          </Typography>\n        </div>\n      )}\n      <br />\n      {/* <IV /> */}\n      {vault === Vaults.Custom && (\n        <TextField\n          onChange={(event) => setCustomLong(parseFloat(event.target.value))}\n          size=\"small\"\n          value={longAmount}\n          type=\"number\"\n          style={{ width: 300 }}\n          label=\"ETH Long\"\n          variant=\"outlined\"\n        />\n      )}\n    </div>\n  )\n}\n\n// const convertPNLToPriceChart = (pnlSeries: { time: number; value: number }[], startingCapital: number) => {\n//   return pnlSeries.map(({ value, time }) => {\n//     return {\n//       value: value + startingCapital,\n//       time,\n//     }\n//   })\n// }\n"
  },
  {
    "path": "packages/frontend/src/components/Checkbox.tsx",
    "content": "import {\n  FormControlLabel,\n  Checkbox as MaterialCheckbox,\n  CheckboxProps as MaterialCheckboxProps,\n} from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\n\nconst useCheckboxStyles = makeStyles((theme) =>\n  createStyles({\n    root: {\n      padding: 0,\n      marginRight: theme.spacing(0.5),\n    },\n  }),\n)\n\nconst useFormControlLabelStyles = makeStyles({\n  root: {\n    marginRight: 0,\n  },\n  label: {\n    fontWeight: 500,\n  },\n})\n\ninterface CheckboxCustomProps {\n  name: string\n  label: string\n  isChecked: boolean\n  onInputChange: (value: boolean) => void\n}\n\ntype CheckboxProps = MaterialCheckboxProps & CheckboxCustomProps\n\nconst Checkbox: React.FC<CheckboxProps> = ({ name, label, isChecked, onInputChange, ...props }) => {\n  const formControlLabelClasses = useFormControlLabelStyles()\n  const checkboxClasses = useCheckboxStyles()\n\n  return (\n    <FormControlLabel\n      classes={formControlLabelClasses}\n      control={\n        <MaterialCheckbox\n          className={checkboxClasses.root}\n          checked={isChecked}\n          onChange={(event) => onInputChange(event.target.checked)}\n          name={name}\n          {...props}\n        />\n      }\n      label={label}\n    />\n  )\n}\n\nexport default Checkbox\n"
  },
  {
    "path": "packages/frontend/src/components/CollatRange.tsx",
    "content": "import { createStyles, makeStyles, Tooltip, Snackbar, Collapse, styled } from '@material-ui/core'\nimport { yellow } from '@material-ui/core/colors'\nimport Alert from '@material-ui/lab/Alert'\nimport React from 'react'\n\nimport Slider from './CustomSlider'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      width: '300px',\n      marginLeft: 'auto',\n      marginRight: 'auto',\n    },\n    danger: {\n      backgroundColor: theme.palette.error.main,\n    },\n    warning: {\n      backgroundColor: yellow[700],\n    },\n    safe: {\n      backgroundColor: theme.palette.success.main,\n    },\n  }),\n)\n\ntype CollatRangeType = {\n  id?: string\n  collatValue: number\n  onCollatValueChange: (val: number) => void\n  className?: string\n}\n\nconst marks = [\n  {\n    value: 150,\n    label: 'DANGER',\n  },\n  {\n    value: 200,\n    label: 'RISKY',\n  },\n  {\n    value: 225,\n    label: 'SAFE',\n  },\n]\n\nconst CollatRange: React.FC<CollatRangeType> = ({ id, collatValue, onCollatValueChange, className }) => {\n  const classes = useStyles()\n\n  const minCollatRatio = 150\n\n  const changeSlider = (val: number[]) => {\n    if (val[1] < minCollatRatio) return\n\n    onCollatValueChange(val[1])\n  }\n\n  // eslint-disable-next-line react/display-name\n  const ThumbComponent = React.useCallback((props: any) => {\n    if (props['data-index'] === 0) {\n      props.style.backgroundColor = 'grey'\n      props.style.height = 10\n      props.style.marginTop = '-2px'\n\n      return (\n        <Tooltip title=\"Minimum collateralization ratio\">\n          <span {...props}></span>\n        </Tooltip>\n      )\n    }\n\n    return <span {...props}></span>\n  }, [])\n\n  const sliderClass = collatValue < 200 ? classes.danger : collatValue < 225 ? classes.warning : classes.safe\n\n  return (\n    <div className={classes.container} id={id}>\n      {collatValue === 150 && <div style={{ color: 'red' }}></div>}\n      <Slider\n        value={[minCollatRatio, collatValue]}\n        ThumbComponent={ThumbComponent}\n        onChange={(_, val) => changeSlider(val as number[])}\n        step={0.1}\n        style={{ width: '100%' }}\n        classes={{\n          thumb: sliderClass,\n          track: sliderClass,\n        }}\n        className={className}\n        marks={marks}\n        min={150}\n        max={300}\n        id={id + '-slider'}\n      />\n      <div style={{ display: 'flex', flexDirection: 'column', gap: '5px' }}>\n        <Collapse in={collatValue === 150}>\n          <Alert severity=\"error\" id={id + '-alert-text'}>\n            You will get liquidated\n          </Alert>\n        </Collapse>\n        <Collapse in={collatValue !== 150 && collatValue < 175}>\n          <Alert severity=\"warning\" id={id + '-alert-text'}>\n            Collateral ratio is risky. You will get liquidated at 150%.\n          </Alert>\n        </Collapse>\n      </div>\n    </div>\n  )\n}\n\nexport default CollatRange\n"
  },
  {
    "path": "packages/frontend/src/components/CollatRatioSlider.tsx",
    "content": "import { createStyles, makeStyles, Tooltip } from '@material-ui/core'\nimport React, { useCallback } from 'react'\n\nimport Slider from '@components/CustomSlider'\n\nconst HEALTH_CATEGORIES = {\n  DANGER: {\n    label: 'DANGER',\n    value: 150,\n    colors: {\n      LIGHT: '#FA7B67',\n      DARK: '#452C28',\n    },\n  },\n  RISKY: {\n    label: 'RISKY',\n    value: 200,\n    colors: {\n      LIGHT: '#F3FF6C',\n      DARK: '#61662b',\n    },\n  },\n  SAFE: {\n    label: 'SAFE',\n    value: 225,\n    colors: {\n      LIGHT: '#67FABF',\n      DARK: '#284539',\n    },\n  },\n}\n\nconst MARKS = [\n  {\n    value: 150,\n    label: 'Min 150%',\n  },\n  {\n    value: 200,\n    label: '200%',\n  },\n  {\n    value: 225,\n    label: '225%',\n  },\n  {\n    value: 300,\n    label: 'Max 300%',\n  },\n]\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      width: '100%',\n      marginLeft: 'auto',\n      marginRight: 'auto',\n    },\n    rail: {\n      opacity: 0.9,\n      background: `linear-gradient(to right, ${HEALTH_CATEGORIES.DANGER.colors.LIGHT}, ${HEALTH_CATEGORIES.DANGER.colors.LIGHT} 33.4%, ${HEALTH_CATEGORIES.RISKY.colors.LIGHT} 33.4%, ${HEALTH_CATEGORIES.RISKY.colors.LIGHT} 50%,  ${HEALTH_CATEGORIES.SAFE.colors.LIGHT} 50%, ${HEALTH_CATEGORIES.SAFE.colors.LIGHT}  )`,\n    },\n    track: {\n      background: 'transparent',\n    },\n    mark: {\n      background: theme.palette.background.lightStone,\n    },\n    markLabel: {\n      fontFamily: 'DM Mono',\n      color: '#fff !important',\n      marginTop: '6px',\n      '&[data-index=\"0\"]': {\n        transform: 'none',\n        marginLeft: '0 !important',\n      },\n      '&[data-index=\"3\"]': {\n        transform: 'translateX(-100%)',\n      },\n    },\n    thumb: {\n      visibility: 'hidden',\n      '&:focus, &:hover, &.Mui-active': {\n        visibility: 'hidden',\n      },\n    },\n  }),\n)\n\ninterface ValueLabelStylePropsType {\n  value: number\n}\n\nconst useValueLabelStyles = makeStyles(() =>\n  createStyles({\n    popper: {\n      zIndex: 1000,\n    },\n    tooltip: {\n      padding: '4px 8px',\n      fontSize: '12px',\n      fontWeight: 500,\n      backgroundColor: (props: ValueLabelStylePropsType): string =>\n        props.value < HEALTH_CATEGORIES.RISKY.value\n          ? HEALTH_CATEGORIES.DANGER.colors.DARK\n          : props.value < HEALTH_CATEGORIES.SAFE.value\n          ? HEALTH_CATEGORIES.RISKY.colors.DARK\n          : HEALTH_CATEGORIES.SAFE.colors.DARK,\n      color: (props: ValueLabelStylePropsType): string =>\n        props.value < HEALTH_CATEGORIES.RISKY.value\n          ? HEALTH_CATEGORIES.DANGER.colors.LIGHT\n          : props.value < HEALTH_CATEGORIES.SAFE.value\n          ? HEALTH_CATEGORIES.RISKY.colors.LIGHT\n          : HEALTH_CATEGORIES.SAFE.colors.LIGHT,\n    },\n  }),\n)\n\nfunction ValueLabelComponent(props: any) {\n  const { children, open, value } = props\n\n  const classes = useValueLabelStyles({ value })\n  const title = value < 200 ? 'Danger' : value < 225 ? 'Risky' : 'Safe'\n\n  return (\n    <Tooltip\n      open={open}\n      enterTouchDelay={0}\n      placement=\"right-end\"\n      title={title}\n      classes={classes}\n      PopperProps={{\n        modifiers: {\n          offset: {\n            offset: '4,-37',\n          },\n        },\n      }}\n    >\n      {children}\n    </Tooltip>\n  )\n}\n\ninterface CollatRatioSliderPropsType {\n  id?: string\n  collatRatio: number\n  onCollatRatioChange: (val: number) => void\n  minCollatRatio: number\n  className?: string\n}\n\nconst CollatRatioSlider: React.FC<CollatRatioSliderPropsType> = ({\n  id,\n  collatRatio,\n  onCollatRatioChange,\n  minCollatRatio,\n  className,\n}) => {\n  const changeSlider = useCallback(\n    (val: number) => {\n      if (val < minCollatRatio) {\n        return\n      }\n      onCollatRatioChange(val)\n    },\n    [minCollatRatio, onCollatRatioChange],\n  )\n\n  const classes = useStyles()\n\n  return (\n    <div className={classes.container} id={id}>\n      <Slider\n        value={collatRatio}\n        ValueLabelComponent={ValueLabelComponent}\n        valueLabelDisplay=\"on\"\n        onChange={(_, val) => changeSlider(val as number)}\n        step={1}\n        classes={{\n          rail: classes.rail,\n          track: classes.track,\n          mark: classes.mark,\n          markLabel: classes.markLabel,\n          thumb: classes.thumb,\n        }}\n        className={className}\n        marks={MARKS}\n        min={150}\n        max={300}\n        id={id + '-slider'}\n      />\n    </div>\n  )\n}\n\nexport default CollatRatioSlider\n"
  },
  {
    "path": "packages/frontend/src/components/CustomProgress.tsx",
    "content": "import LinearProgress from '@material-ui/core/LinearProgress'\nimport { withStyles, createStyles } from '@material-ui/core/styles'\n\nconst CustomLinearProgress = withStyles((theme) =>\n  createStyles({\n    root: {\n      height: 10,\n      borderRadius: 5,\n    },\n    colorPrimary: {\n      backgroundColor: `${theme.palette.primary.main}10`,\n    },\n    bar: {\n      borderRadius: 5,\n      backgroundColor: `${theme.palette.primary.main}`,\n    },\n  }),\n)(LinearProgress)\n\nexport const CustomLinearProgressNew = withStyles((theme) =>\n  createStyles({\n    root: {\n      height: 10,\n      borderRadius: 5,\n    },\n    colorPrimary: {\n      backgroundColor: `${theme.palette.success.main}10`,\n    },\n    bar: {\n      borderRadius: 5,\n      backgroundColor: `${theme.palette.success.main}`,\n    },\n  }),\n)(LinearProgress)\n\nexport default CustomLinearProgress\n"
  },
  {
    "path": "packages/frontend/src/components/CustomSlider.tsx",
    "content": "import Slider from '@material-ui/core/Slider'\nimport { yellow } from '@material-ui/core/colors'\nimport { withStyles } from '@material-ui/core/styles'\n\nconst CustomSlider = withStyles((theme) => ({\n  thumb: {\n    width: '3px',\n    borderRadius: '20%',\n    marginLeft: 0,\n    height: 15,\n  },\n  markLabel: {\n    fontSize: '.7rem',\n  },\n  rail: {\n    height: 5,\n  },\n  root: {\n    height: 5,\n    color: theme.palette.text.secondary,\n    '& .MuiSlider-markLabel[data-index=\"0\"]': {\n      marginLeft: '22px',\n      color: theme.palette.error.main,\n    },\n    '& .MuiSlider-markLabel[data-index=\"1\"]': {\n      color: yellow[700],\n    },\n    '& .MuiSlider-mark[data-index=\"1\"]': {\n      color: yellow[700],\n    },\n    '& .MuiSlider-markLabel[data-index=\"2\"]': {\n      color: theme.palette.success.main,\n    },\n    '& .MuiSlider-mark[data-index=\"2\"]': {\n      color: theme.palette.success.main,\n    },\n  },\n  track: {\n    height: 5,\n  },\n  mark: {\n    height: 5,\n  },\n}))(Slider)\n\nexport default CustomSlider\n"
  },
  {
    "path": "packages/frontend/src/components/CustomSwitch.tsx",
    "content": "import { createStyles, makeStyles, Typography } from '@material-ui/core'\nimport React from 'react'\nimport clsx from 'clsx'\n\nconst useStyles = makeStyles(() =>\n  createStyles({\n    wrapper: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    switchItem: {\n      padding: '3px 8px',\n      margin: '4px',\n      cursor: 'pointer',\n      display: 'flex',\n      alignItems: 'center',\n      borderRadius: 12,\n      '& p': {\n        fontSize: 14,\n      },\n    },\n    selectedItem: {\n      background: '#ddd',\n      color: '#333',\n    },\n  }),\n)\n\nexport type SwitchItem = {\n  id: string\n  text: string\n  itemToAdd?: React.ReactNode\n  beforeText?: boolean\n}\n\ntype CustomSwitchType = {\n  items: SwitchItem[]\n  value: SwitchItem\n  onChange: (val: SwitchItem) => void\n}\n\nconst CustomSwitch: React.FC<CustomSwitchType> = ({ items, value, onChange }) => {\n  const classes = useStyles()\n\n  return (\n    <div className={classes.wrapper}>\n      {items.map((item) => (\n        <div\n          key={item.id}\n          className={clsx(classes.switchItem, item.id === value.id && classes.selectedItem)}\n          onClick={() => onChange(item)}\n        >\n          {item.beforeText && item.itemToAdd && item.itemToAdd}\n          <Typography>{item.text}</Typography>\n          {!item.beforeText && item.itemToAdd && item.itemToAdd}\n        </div>\n      ))}\n    </div>\n  )\n}\n\nexport default CustomSwitch\n"
  },
  {
    "path": "packages/frontend/src/components/DefaultSiteSeo/DefaultSiteSeo.tsx",
    "content": "import React from 'react'\nimport { NextSeo } from 'next-seo'\nimport { SiteMetaDescription, SiteMetaImage, SiteMetaTitle, SQUEETH_BASE_URL } from '@constants/index'\n\nconst DefaultSiteSeo: React.FC = () => {\n  return (\n    <NextSeo\n      title={SiteMetaTitle}\n      description={SiteMetaDescription}\n      canonical={SQUEETH_BASE_URL}\n      openGraph={{\n        images: [\n          {\n            url: SiteMetaImage,\n            width: 1200,\n            height: 630,\n            alt: 'Opyn',\n          },\n        ],\n      }}\n      twitter={{\n        handle: '@opyn_',\n        site: '@opyn_',\n        cardType: 'summary_large_image',\n      }}\n    />\n  )\n}\n\nexport default DefaultSiteSeo\n"
  },
  {
    "path": "packages/frontend/src/components/Emoji.tsx",
    "content": "import React from 'react'\nimport { Typography, TypographyProps } from '@material-ui/core'\n\nconst Emoji: React.FC<TypographyProps> = (props) => {\n  return <Typography component=\"span\" role=\"img\" {...props} />\n}\n\nexport default Emoji\n"
  },
  {
    "path": "packages/frontend/src/components/HidePnLText.tsx",
    "content": "import { Typography } from '@material-ui/core'\nimport { makeStyles } from '@material-ui/core/styles'\nimport { useAtomValue } from 'jotai'\n\nimport { positionTypeAtom } from '@state/positions/atoms'\nimport { PositionType } from 'src/types'\nimport { LinkWrapper } from './LinkWrapper'\n\nconst useStyles = makeStyles({\n  text: {\n    fontSize: '15px',\n    color: 'rgb(255, 255, 255)',\n  },\n})\n\nexport const HidePnLText: React.FC = () => {\n  const classes = useStyles()\n\n  const positionType = useAtomValue(positionTypeAtom)\n\n  return (\n    <Typography variant=\"body2\" className={classes.text}>\n      {positionType !== PositionType.LONG && <span>Coming soon.</span>} Please use{' '}\n      <LinkWrapper href=\"https://docs.google.com/spreadsheets/d/1iy5N3qy6g2xd2_BcsY_Hv0pKdyceC1h7y269KssOG8s/edit#gid=1267496112\">\n        SqueethLab\n      </LinkWrapper>\n    </Typography>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/IV.tsx",
    "content": "import { InputAdornment, TextField, Tooltip } from '@material-ui/core'\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'\nimport React from 'react'\n\nimport { useAtom } from 'jotai'\nimport { volMultiplierAtom } from 'src/state/ethPriceCharts/atoms'\n\nconst IV: React.FC = () => {\n  const [volMultiplier, setVolMultiplier] = useAtom(volMultiplierAtom)\n\n  return (\n    <div>\n      <TextField\n        variant=\"outlined\"\n        label=\"Vol Multiplier\"\n        value={volMultiplier}\n        style={{ width: 300 }}\n        size=\"small\"\n        onChange={(event) => setVolMultiplier(Number(event.target.value))}\n        InputProps={{\n          endAdornment: (\n            <InputAdornment position=\"end\">\n              <Tooltip title=\"Multiplies the at-the-money vol by this amount\">\n                <InfoOutlinedIcon fontSize=\"small\" />\n              </Tooltip>\n            </InputAdornment>\n          ),\n        }}\n      />\n    </div>\n  )\n}\n\nexport default IV\n"
  },
  {
    "path": "packages/frontend/src/components/Input/NumberInput.tsx",
    "content": "import { Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport clsx from 'clsx'\nimport React from 'react'\n\nimport { LinkButton } from '../Button'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(1),\n      border: `1px solid ${theme.palette.background.stone}`,\n      borderRadius: theme.spacing(1),\n      '&:focus-within': {\n        border: `1px solid ${theme.palette.secondary.main}50`,\n      },\n    },\n    input: {\n      border: 'none',\n      backgroundColor: 'inherit',\n      outline: 'none',\n      fontSize: '18px',\n      color: theme.palette.text.primary,\n      fontWeight: theme.typography.fontWeightBold,\n      fontFamily: theme.typography.fontFamily,\n      width: '100%',\n    },\n    inputContainer: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    spinner: {\n      background: theme.palette.background.lightStone,\n      display: 'flex',\n      justifyContent: 'space-between',\n      borderRadius: theme.spacing(1),\n      marginRight: theme.spacing(1),\n      fontWeight: 600,\n      color: '#000',\n      fontSize: '18px',\n    },\n    plusButton: {\n      background: theme.palette.success.main,\n      border: 'none',\n      borderRadius: '100%',\n      width: '18px',\n      height: '18px',\n      margin: 'auto',\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n      cursor: 'pointer',\n    },\n    errorButton: {\n      background: theme.palette.error.main,\n      border: 'none',\n      width: '18px',\n      height: '18px',\n      borderRadius: '100%',\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n      marginLeft: theme.spacing(0.5),\n      cursor: 'pointer',\n    },\n    minus: {\n      width: '7px',\n      height: '2px',\n      background: '#000',\n    },\n    hint: {\n      marginLeft: theme.spacing(0.5),\n    },\n    error: {\n      border: `1px solid ${theme.palette.error.main}50`,\n    },\n  }),\n)\n\ntype NumberInputType = {\n  placeholder: string\n  unit: string\n  value: string\n  min?: string\n  max?: string\n  onChange: (value: string) => void\n  step?: number\n  hint?: string | React.ReactNode // Used for error as well\n  id?: string\n  error?: boolean\n  actionTxt?: string\n  onActionClicked?: () => void\n}\n\nconst DecimalRegex = RegExp('^[-]?[0-9]*[.]{1}[0-9]*$')\n\n/**\n * Input to handle BigNumber with spinner buttons.\n */\nconst NumberInput: React.FC<NumberInputType> = ({\n  value = '',\n  min,\n  max,\n  onChange,\n  step,\n  placeholder,\n  unit,\n  hint,\n  id,\n  error,\n  actionTxt,\n  onActionClicked,\n}) => {\n  const classes = useStyles()\n\n  const onValueChange = (v: string) => {\n    // To render '-' or emptyString as bigNumber('-').toString() always gives 0\n    if (v === '' || v === '-' || v === '0') {\n      return onChange(v)\n    }\n\n    if (min && Number(min) > Number(v)) {\n      return onChange(min)\n    } else if (max && Number(max) < Number(v)) {\n      return onChange(max)\n    }\n\n    if (Number(v) !== 0) {\n      //if it is integer, remove leading zeros\n      if (!DecimalRegex.test(v)) {\n        v = Number(v).toString()\n      }\n    } else {\n      // remain input box w single zero, but keep zero when have decimal\n      v = v.replace(/^[0]+/g, '0')\n    }\n    return onChange(v)\n  }\n\n  const increment = (step: number) => {\n    const val = parseFloat(value.toString() || '0')\n    onValueChange((val + step).toFixed(1))\n  }\n\n  return (\n    <div>\n      <div className={!error ? classes.container : clsx(classes.container, classes.error)}>\n        <div className={classes.inputContainer}>\n          <input\n            id={id}\n            className={classes.input}\n            value={value}\n            onChange={(event) => onValueChange(event.target.value)}\n            placeholder={placeholder}\n            type=\"number\"\n          />\n          <div className={classes.spinner}>\n            <div className={classes.plusButton} onClick={() => increment(step || 1)}>\n              +\n            </div>\n            <div className={classes.errorButton} onClick={() => increment(-(step || 1))}>\n              <div className={classes.minus}></div>\n            </div>\n          </div>\n          <Typography color=\"textSecondary\">{unit}</Typography>\n        </div>\n      </div>\n      <div className={classes.hint}>\n        <Typography color={error ? 'error' : 'textSecondary'} variant=\"caption\">\n          {hint}\n        </Typography>\n        {actionTxt && onActionClicked ? (\n          <LinkButton\n            size=\"small\"\n            color=\"primary\"\n            onClick={onActionClicked}\n            variant=\"text\"\n            style={{ marginLeft: '250px' }}\n          >\n            {actionTxt}\n          </LinkButton>\n        ) : null}\n      </div>\n    </div>\n  )\n}\n\nexport default NumberInput\n"
  },
  {
    "path": "packages/frontend/src/components/Input/PrimaryInput.tsx",
    "content": "import { CircularProgress, Tooltip, Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'\nimport clsx from 'clsx'\nimport React from 'react'\n\nimport { LinkButton } from '../Button'\nimport { Tooltips } from '@constants/enums'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      width: '300px',\n      backgroundColor: 'inherit',\n      textAlign: 'left',\n      border: `1px solid ${theme.palette.background.stone}`,\n      borderRadius: theme.spacing(1),\n      padding: theme.spacing(1.5),\n      margin: 'auto',\n      marginBottom: '1em',\n      '&:focus-within': {\n        border: `1px solid ${theme.palette.secondary.main}30`,\n      },\n    },\n    errorBorder: {\n      border: `1px solid ${theme.palette.error.main}`,\n      '&:focus-within': {\n        border: `1px solid ${theme.palette.error.main}`,\n      },\n    },\n    innerContainer: {\n      display: 'flex',\n      alignItems: 'flex-end',\n      boxSizing: 'border-box',\n      justifyContent: 'space-between',\n    },\n    rightContainer: {\n      width: '50%',\n    },\n    unitsContainer: {},\n    label: {\n      color: theme.palette.text.secondary,\n    },\n    labelContainer: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    tooltipIcon: {\n      color: theme.palette.text.hint,\n      marginLeft: '6px',\n      fontSize: '14px',\n    },\n    input: {\n      border: 'none',\n      backgroundColor: 'inherit',\n      outline: 'none',\n      fontSize: '22px',\n      color: theme.palette.text.primary,\n      fontWeight: theme.typography.fontWeightBold,\n      fontFamily: theme.typography.fontFamily,\n      width: '100%',\n    },\n    inputContainer: {\n      margin: theme.spacing(0.5, 0),\n    },\n    fullCloseInfo: { display: 'inline-block' },\n    unit: {\n      fontSize: '22px',\n    },\n    notAllowedCursor: {\n      cursor: 'not-allowed',\n    },\n    disabledBackground: {\n      backgroundColor: theme.palette.background.stone,\n    },\n  }),\n)\n\ntype PrimaryInputType = {\n  value: number | string\n  onChange: (value: string) => void\n  label: string\n  unit: string\n  tooltip?: string\n  actionTxt?: string\n  onActionClicked?: () => void\n  convertedValue?: number | string\n  hint?: string | React.ReactNode\n  id?: string\n  error?: boolean\n  isLoading?: boolean\n  isFullClose?: boolean\n  loadingMessage?: string\n}\n\nconst DecimalRegex = RegExp('^[0-9]*[.]{1}[0-9]*$')\n\nexport const PrimaryInput: React.FC<PrimaryInputType> = ({\n  value = '0',\n  onChange,\n  label,\n  tooltip,\n  actionTxt,\n  onActionClicked,\n  unit,\n  convertedValue,\n  hint,\n  id,\n  error = false,\n  isLoading = false,\n  isFullClose = false,\n  loadingMessage = 'Fetching best price',\n}) => {\n  const classes = useStyles()\n\n  return (\n    <div\n      className={clsx(classes.container, error && classes.errorBorder, isFullClose && classes.disabledBackground)}\n      id={id + '-box'}\n    >\n      <div className={classes.innerContainer}>\n        <div className={classes.rightContainer}>\n          <div className={classes.labelContainer}>\n            <Typography variant=\"caption\" className={classes.label}>\n              {label}\n            </Typography>\n            {tooltip ? (\n              <Tooltip title={tooltip}>\n                <InfoOutlinedIcon fontSize=\"small\" className={classes.tooltipIcon} />\n              </Tooltip>\n            ) : null}\n          </div>\n          <div className={classes.inputContainer}>\n            <Tooltip title={isFullClose ? Tooltips.FullcloseInput : ''} className={classes.fullCloseInfo}>\n              <input\n                id={id}\n                className={clsx(classes.input, isFullClose && classes.notAllowedCursor)}\n                // className={classes.input}\n                value={isNaN(Number(value)) ? 0 : value}\n                disabled={isFullClose}\n                onChange={(e) => {\n                  let v = e.target.value\n                  if (Number(v) < 0) return onChange('0')\n                  if (Number(v) !== 0) {\n                    //if it is integer, remove leading zeros\n                    if (!DecimalRegex.test(v)) {\n                      v = Number(v).toString()\n                    }\n                  } else {\n                    // remain input box w single zero, but keep zero when have decimal\n                    v = v.replace(/^[0]+/g, '0')\n                    // if it is no value\n                    if (v.length === 0) {\n                      v = '0'\n                    }\n                  }\n\n                  return onChange(v)\n                }}\n                onWheel={(e) => (e.target as any).blur()}\n                placeholder=\"0\"\n                type=\"number\"\n                min=\"0\"\n              ></input>\n            </Tooltip>\n          </div>\n        </div>\n        {/* <div>\n          {actionTxt && onActionClicked ? (\n            <Button size=\"small\" color=\"primary\" onClick={onActionClicked} variant=\"text\">\n              {actionTxt}\n            </Button>\n          ) : null}\n        </div> */}\n        <div className={classes.unitsContainer}>\n          <Typography variant=\"caption\">{convertedValue ? `$${convertedValue}` : null}</Typography>\n          <Typography className={classes.unit}>{unit}</Typography>\n        </div>\n      </div>\n      {isLoading && (!error || hint === 'Insufficient ETH balance') ? (\n        <div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>\n          <Typography variant=\"caption\" color={error ? 'error' : 'textSecondary'}>\n            {loadingMessage}\n          </Typography>\n          <CircularProgress color=\"primary\" size=\"1rem\" />\n        </div>\n      ) : (\n        <div style={{ display: 'flex', alignItems: 'center' }}>\n          <Typography variant=\"caption\" color={error ? 'error' : 'textSecondary'}>\n            {hint || ''}\n          </Typography>\n          {actionTxt && onActionClicked ? (\n            <LinkButton size=\"small\" color=\"primary\" onClick={onActionClicked} variant=\"text\" id={id + '-action'}>\n              {actionTxt}\n            </LinkButton>\n          ) : null}\n        </div>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/InputNew/InputBase.tsx",
    "content": "import { TextField, StandardTextFieldProps } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport clsx from 'clsx'\nimport React from 'react'\n\nimport useTextStyles from '@styles/useTextStyles'\n\nconst useInputBaseStyles = makeStyles((theme) =>\n  createStyles({\n    labelRoot: {\n      '& ~ $inputRoot': {\n        marginTop: '24px',\n      },\n    },\n    labelFocused: {\n      color: theme.palette.primary.main,\n    },\n    inputRoot: {\n      padding: theme.spacing(0.75, 1.5),\n      fontSize: '14px',\n      fontFamily: 'DM Mono',\n    },\n    inputBorder: {\n      border: '2px solid',\n      borderColor: theme.palette.background.lightStone,\n      borderRadius: '12px',\n    },\n    inputFocused: {\n      borderColor: theme.palette.primary.main,\n    },\n    inputError: {\n      borderColor: theme.palette.error.dark,\n    },\n  }),\n)\n\ninterface InputBaseCustomProps {\n  hasBorder?: boolean\n  readOnly?: boolean\n}\nexport type InputBaseProps = StandardTextFieldProps & InputBaseCustomProps\n\nconst InputBase = React.forwardRef<any, InputBaseProps>(\n  ({ InputProps, InputLabelProps, hasBorder = true, readOnly = false, ...props }, ref) => {\n    const classes = useInputBaseStyles()\n    const textClasses = useTextStyles()\n\n    return (\n      <TextField\n        inputRef={ref}\n        InputLabelProps={{\n          classes: {\n            root: clsx(classes.labelRoot, textClasses.lightestFontColor),\n            focused: clsx(classes.labelFocused, textClasses.lightFontColor),\n          },\n          ...InputLabelProps,\n        }}\n        InputProps={{\n          disableUnderline: true,\n          readOnly,\n          classes: {\n            root: clsx(classes.inputRoot, hasBorder && classes.inputBorder),\n            focused: classes.inputFocused,\n            error: classes.inputError,\n          },\n          ...InputProps,\n        }}\n        {...props}\n      />\n    )\n  },\n)\nInputBase.displayName = 'InputBase'\n\nexport default InputBase\n"
  },
  {
    "path": "packages/frontend/src/components/InputNew/InputNumber.tsx",
    "content": "import React from 'react'\nimport InputBase, { InputBaseProps } from './InputBase'\n\nconst DECIMAL_REGEX = RegExp('^[0-9]*[.]{1}[0-9]*$')\n\ninterface InputNumberCustomProps extends InputBaseProps {\n  onInputChange?: (value: string) => void\n}\nexport type InputNumberProps = InputNumberCustomProps\n\nconst InputNumber = React.forwardRef<any, InputNumberProps>(\n  ({ value, onInputChange = () => {}, inputProps, ...props }, ref) => {\n    const handleChange = (val: string) => {\n      if (isNaN(Number(val))) {\n        return onInputChange('0')\n      }\n\n      if (Number(val) < 0) {\n        return onInputChange('0')\n      }\n\n      if (Number(val) !== 0) {\n        // if it is integer, remove leading zeros\n        if (!DECIMAL_REGEX.test(val)) {\n          val = Number(val).toString()\n        }\n      } else {\n        // remain input box w single zero, but keep zero when have decimal\n        val = val.replace(/^[0]+/g, '0')\n        // if it is no value\n        if (val.length === 0) {\n          val = '0'\n        }\n      }\n\n      return onInputChange(val)\n    }\n\n    return (\n      <InputBase\n        ref={ref}\n        value={value}\n        onChange={(event) => handleChange(event.target.value)}\n        placeholder=\"0\"\n        autoComplete=\"false\"\n        inputProps={{ inputMode: 'numeric', pattern: '[0-9]*', ...inputProps }}\n        {...props}\n      />\n    )\n  },\n)\nInputNumber.displayName = 'InputNumber'\n\nexport default InputNumber\n"
  },
  {
    "path": "packages/frontend/src/components/InputNew/InputToken.tsx",
    "content": "import { Typography, InputAdornment, Box, ButtonBase, CircularProgress, Tooltip } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport clsx from 'clsx'\nimport Image from 'next/image'\nimport BigNumber from 'bignumber.js'\n\nimport { formatBalance, formatCurrency } from '@utils/formatter'\nimport useTextStyles from '@styles/useTextStyles'\nimport InputNumber, { InputNumberProps } from './InputNumber'\n\nconst useInputTokenProps = makeStyles((theme) =>\n  createStyles({\n    container: {\n      backgroundColor: 'inherit',\n      textAlign: 'left',\n      position: 'relative',\n      zIndex: 0,\n      marginBottom: '44px',\n    },\n    inputContainer: {\n      display: 'flex',\n      flexDirection: 'column',\n      justifyContent: 'space-between',\n      border: `2px solid ${theme.palette.background.lightStone}`,\n      borderRadius: '10px',\n      padding: theme.spacing(2),\n      backgroundColor: theme.palette.background.default,\n    },\n    inputRoot: {\n      padding: 0,\n      fontSize: '22px',\n      fontWeight: 500,\n      letterSpacing: '-0.01em',\n    },\n    subSection: {\n      position: 'absolute',\n      right: '0',\n      left: '0',\n      bottom: '-44px',\n      zIndex: -10,\n      display: 'flex',\n      justifyContent: 'space-between',\n      padding: '36px 16px 12px 16px',\n      backgroundColor: theme.palette.background.stone,\n      borderRadius: '10px',\n    },\n    adornmentContainer: {\n      display: 'flex',\n      justifyContent: 'center',\n      padding: '2px 10px',\n      backgroundColor: theme.palette.background.stone,\n      borderRadius: '6px',\n    },\n    logo: {\n      width: '18px',\n      height: '18px',\n      marginRight: theme.spacing(1),\n    },\n    textMonospace: {\n      fontFamily: 'DM Mono',\n    },\n  }),\n)\n\ninterface InputTokenProps extends InputNumberProps {\n  usdPrice?: BigNumber\n  balance: BigNumber\n  logo?: string\n  symbol: string\n  onBalanceClick?: () => void\n  showMaxAction?: boolean\n  isLoading?: boolean\n  loadingMessage?: string\n  readOnlyTooltip?: string\n  isBalanceLoading?: boolean\n  loadingBalanceMessage?: string\n}\n\nexport const InputToken: React.FC<InputTokenProps> = ({\n  value,\n  usdPrice,\n  balance,\n  logo,\n  symbol,\n  onBalanceClick = () => {},\n  showMaxAction = true,\n  isLoading = false,\n  loadingMessage = 'loading...',\n  readOnly = false,\n  readOnlyTooltip = '',\n  isBalanceLoading = false,\n  loadingBalanceMessage = 'loading...',\n  ...props\n}) => {\n  const classes = useInputTokenProps()\n  const textClasses = useTextStyles()\n\n  const usdValue = usdPrice ? usdPrice.multipliedBy(new BigNumber(value as number)).toNumber() : null // value is always \"number\" type\n\n  return (\n    <div className={classes.container}>\n      <div className={classes.inputContainer}>\n        <Tooltip title={readOnlyTooltip} placement=\"bottom\">\n          <InputNumber\n            value={value}\n            fullWidth\n            hasBorder\n            readOnly={readOnly}\n            InputProps={{\n              endAdornment: (\n                <InputAdornment position=\"end\">\n                  <div className={classes.adornmentContainer}>\n                    {logo && (\n                      <div className={classes.logo}>\n                        <Image src={logo} alt=\"logo\" width=\"100%\" height=\"100%\" />\n                      </div>\n                    )}\n\n                    <Typography className={clsx(textClasses.lightestFontColor, textClasses.mediumBold)}>\n                      {symbol}\n                    </Typography>\n                  </div>\n                </InputAdornment>\n              ),\n              classes: {\n                root: clsx(classes.inputRoot, textClasses.monoFont),\n              },\n            }}\n            {...props}\n          />\n        </Tooltip>\n\n        {isLoading ? (\n          <Box display=\"flex\" alignItems=\"center\" gridGap=\"8px\">\n            <CircularProgress color=\"primary\" size=\"1rem\" />\n            <Typography className={clsx(textClasses.lighterFontColor, textClasses.smallFont, textClasses.monoFont)}>\n              {loadingMessage}\n            </Typography>\n          </Box>\n        ) : usdValue ? (\n          <Typography className={clsx(textClasses.lighterFontColor, textClasses.smallFont, textClasses.monoFont)}>\n            {formatCurrency(usdValue)}\n          </Typography>\n        ) : null}\n      </div>\n\n      <div className={classes.subSection}>\n        <Typography variant=\"caption\" className={clsx(textClasses.lightestFontColor, textClasses.smallFont)}>\n          {'Balance'}\n        </Typography>\n\n        <Box display=\"flex\" alignItems=\"center\" gridGap=\"4px\">\n          {isBalanceLoading ? (\n            <Typography variant=\"body2\" className={clsx(textClasses.lightFontColor, textClasses.smallFont)}>\n              {loadingBalanceMessage}\n            </Typography>\n          ) : (\n            <>\n              <Typography variant=\"body2\" className={classes.textMonospace}>\n                {isBalanceLoading ? loadingBalanceMessage : formatBalance(balance.toNumber())}\n              </Typography>\n              <Typography variant=\"body2\">{` ${symbol}`}</Typography>\n\n              {showMaxAction && (\n                <ButtonBase onClick={onBalanceClick}>\n                  <Typography variant=\"subtitle2\" color=\"primary\">\n                    (Max)\n                  </Typography>\n                </ButtonBase>\n              )}\n            </>\n          )}\n        </Box>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/InputNew/index.tsx",
    "content": "import InputBase from './InputBase'\nimport InputNumber from './InputNumber'\nimport { InputToken } from './InputToken'\n\nexport { InputBase, InputNumber, InputToken }\n"
  },
  {
    "path": "packages/frontend/src/components/LabelWithTooltip.test.tsx",
    "content": "import { render, screen } from '@testing-library/react'\nimport LabelWithTooltip from './LabelWithTooltip'\n\ndescribe('LabelWithTooltip', () => {\n  it('renders label text', () => {\n    render(<LabelWithTooltip label=\"Test Label\" />)\n\n    expect(screen.getByText(/Test Label/i)).toBeInTheDocument()\n  })\n\n  it('does not render info icon when tooltip is not defined', () => {\n    render(<LabelWithTooltip label=\"Test Label\" />)\n\n    expect(screen.queryByTestId('info-icon')).toBeNull()\n  })\n\n  it('renders info icon and tooltip when tooltip is defined', () => {\n    render(<LabelWithTooltip label=\"Test Label\" tooltip=\"Custom Tooltip\" />)\n\n    expect(screen.getByTestId('info-icon')).toBeInTheDocument()\n    expect(screen.getByTitle('Custom Tooltip')).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/frontend/src/components/LabelWithTooltip.tsx",
    "content": "import { Box, BoxProps, Tooltip, Typography, TypographyVariant } from '@material-ui/core'\nimport { FC } from 'react'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\n\ninterface Props extends BoxProps {\n  label: string\n  tooltip?: string\n  labelVariant?: TypographyVariant\n}\n\nconst LabelWithTooltip: FC<Props> = ({ label, tooltip, labelVariant, ...props }: Props) => {\n  return (\n    <Box display=\"flex\" alignItems=\"center\" {...props}>\n      <Typography variant={labelVariant} color=\"textSecondary\">\n        {label}\n      </Typography>\n      {tooltip && (\n        <Box clone fontSize={10} ml={0.5}>\n          <Tooltip title={tooltip}>\n            <InfoIcon fontSize=\"small\" data-testid=\"info-icon\" />\n          </Tooltip>\n        </Box>\n      )}\n    </Box>\n  )\n}\n\nexport default LabelWithTooltip\n"
  },
  {
    "path": "packages/frontend/src/components/LandingPage/DesktopLandingPage.tsx",
    "content": "import React, { useEffect } from 'react'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport logo from 'public/images/OpynLogo.svg'\nimport LandingPageBackground from 'public/images/landing/athena1-desktop.png'\nimport LandingPageBackgroundDown from 'public/images/landing-page-background-down.svg'\nimport LandingTitle from 'public/images/landing/landing-title.png'\nimport Squeeth from 'public/images/landing/squeeth.png'\nimport Link from 'next/link'\nimport Strategies from 'public/images/landing/strategies.png'\nimport Auction from 'public/images/landing/auction.png'\nimport Twitter from 'public/images/landing/twitter.svg'\nimport Discord from 'public/images/landing/discord.svg'\nimport Github from 'public/images/landing/github.svg'\nimport Medium from 'public/images/landing/medium.svg'\nimport Image from 'next/image'\nimport clsx from 'clsx'\nimport { Button, Typography } from '@material-ui/core'\nimport { useTVL } from '@hooks/useTVL'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { LANDING_EVENTS, SITE_EVENTS } from '@utils/amplitude'\nimport { ShutdownAlert } from '@components/Alerts/ShutdownAlert'\n\nconst designBaseWidth = 1512\n\nconst vwCalculator = (width: number) => {\n  return `${(width / designBaseWidth) * 100}vw`\n}\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    '*': {\n      overflow: 'hidden',\n    },\n    logo: {\n      cursor: 'pointer',\n    },\n    gradientText: {\n      background: `linear-gradient(180deg, #FFFFFF 0%, #C2C2C2 100%)`,\n      WebkitBackgroundClip: 'text',\n      WebkitTextFillColor: 'transparent',\n    },\n    landing_page_container: {\n      width: '100%',\n      height: '100%',\n      overflow: 'hidden',\n    },\n    nav: {\n      padding: `8px ${vwCalculator(120)}`,\n      borderBottom: '1px solid #333333',\n      display: 'flex',\n      alignItems: 'center',\n    },\n    navLinks: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'flex-end',\n      gap: `${vwCalculator(24)}`,\n      flex: 1,\n    },\n    navLink: {\n      fontFamily: 'DM Sans',\n      fontWeight: 700,\n      fontSize: `16px`,\n      lineHeight: '140%',\n      color: '#F2F2F2',\n      opacity: 0.5,\n      cursor: 'pointer',\n      transitionDuration: '300ms',\n      '&:hover': {\n        opacity: 1,\n      },\n    },\n    navAction: {\n      marginLeft: `${vwCalculator(16)}`,\n    },\n    navStartEarningButton: {\n      backgroundColor: theme.palette.primary.main,\n      padding: `15px ${vwCalculator(18)}`,\n      fontFamily: 'Avenir',\n      fontWeight: 800,\n      fontSize: '18px',\n      lineHeight: '130%',\n      maxWidth: '180px',\n      '&:hover': {\n        backgroundColor: theme.palette.primary.dark,\n      },\n    },\n    background1: {\n      position: 'absolute',\n      backgroundImage: `url(${LandingPageBackground.src})`,\n      height: `70vw`,\n      width: '100%',\n      backgroundRepeat: 'no-repeat',\n      backgroundPosition: 'right',\n      backgroundSize: 'contain',\n      zIndex: -1,\n    },\n    background2: {\n      position: 'absolute',\n      backgroundImage: `url(${LandingPageBackgroundDown.src})`,\n      height: `155vw`,\n      width: '90vw',\n      backgroundRepeat: 'no-repeat',\n      backgroundPosition: 'left',\n      zIndex: -1,\n    },\n    content: {},\n    introSection: {\n      display: 'flex',\n      padding: `80px ${vwCalculator(150)}`,\n      paddingBottom: '28px',\n      alignItems: 'center',\n      [theme.breakpoints.down('md')]: {\n        gap: '30px',\n      },\n    },\n    introSectionLeft: {\n      flex: 1,\n      display: 'flex',\n      justifyContent: 'flex-start',\n    },\n    introSectionHeading: {\n      fontFamily: 'DM Sans',\n      fontWeight: 700,\n      fontSize: '64px',\n      margin: 0,\n      [theme.breakpoints.down('lg')]: {\n        fontSize: '64px',\n      },\n      [theme.breakpoints.down('md')]: {\n        fontSize: '50px',\n      },\n    },\n    introSectionSubHeading: {\n      fontFamily: 'DM Sans',\n      fontWeight: 400,\n      fontSize: '32px',\n      lineHeight: '42px',\n      color: '#BDBDBD',\n      margin: 0,\n      [theme.breakpoints.down('lg')]: {\n        fontSize: '32px',\n      },\n      [theme.breakpoints.down('md')]: {\n        fontSize: '30px',\n      },\n    },\n    imageSectionRight: {\n      flex: 1,\n      display: 'flex',\n      justifyContent: 'flex-end',\n    },\n    imageSection: {\n      maxWidth: `${vwCalculator(610)}`,\n    },\n    statSection: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n      gap: `${vwCalculator(284)}`,\n      marginTop: '68px',\n    },\n    statSectionItem: {\n      display: 'flex',\n      justifyContent: 'center',\n      alignItems: 'center',\n      flexDirection: 'column',\n    },\n    statSectionTitle: {\n      fontFamily: 'DM Sans',\n      fontWeight: 400,\n      fontSize: '56px',\n      lineHeight: '73px',\n    },\n    statSectionSubTitle: {\n      fontFamily: 'DM Sans',\n      fontWeight: 400,\n      fontSize: '22px',\n      lineHeight: '29px',\n      color: '#BDBDBD',\n      textAlign: 'center',\n    },\n    squeethSection: {\n      display: 'flex',\n      padding: `${vwCalculator(120)}`,\n      alignItems: 'center',\n      marginTop: '150px',\n      [theme.breakpoints.down('md')]: {\n        gap: '30px',\n      },\n    },\n    contentSectionHeader: {\n      display: 'flex',\n      alignItems: 'center',\n      gap: `${vwCalculator(29)}`,\n    },\n    contentSectionHeaderImage: {\n      maxWidth: '',\n    },\n    contentSectionHeaderLabel: {\n      fontFamily: 'DM Sans',\n      fontWeight: 500,\n      fontSize: '32px',\n      lineHeight: '42px',\n      marginTop: '-5px',\n    },\n    contentSectionTitle: {\n      fontFamily: 'DM Sans',\n      fontWeight: 700,\n      fontSize: '32px',\n      lineHeight: '42px',\n      [theme.breakpoints.down('md')]: {\n        fontSize: '25px',\n      },\n    },\n    contentSectionSubTitle: {\n      fontFamily: 'DM Sans',\n      fontWeight: 400,\n      fontSize: '24px',\n      lineHeight: '31px',\n      color: '#BDBDBD',\n      [theme.breakpoints.down('md')]: {\n        fontSize: '20px',\n      },\n    },\n    contentSectionButton: {\n      backgroundColor: theme.palette.primary.main,\n      padding: `14px ${vwCalculator(18)}`,\n      fontFamily: 'Avenir',\n      fontWeight: 800,\n      fontSize: '18px',\n      lineHeight: '130%',\n      maxWidth: '180px',\n      '&:hover': {\n        backgroundColor: theme.palette.primary.dark,\n      },\n    },\n    strategiesSection: {\n      display: 'flex',\n      padding: `${vwCalculator(120)}`,\n      alignItems: 'center',\n    },\n    auctionSection: {\n      display: 'flex',\n      padding: `${vwCalculator(120)}`,\n      alignItems: 'center',\n      marginTop: '0px',\n      [theme.breakpoints.down('md')]: {\n        gap: '30px',\n      },\n    },\n    auctionSectionLeft: {\n      flex: 1,\n      display: 'flex',\n      justifyContent: 'center',\n    },\n    auctionSectionRight: {\n      flex: 1,\n      display: 'flex',\n      justifyContent: 'center',\n    },\n    footer: {\n      display: 'flex',\n      alignItems: 'center',\n      padding: `40px ${vwCalculator(120)}`,\n    },\n    footerLinks: {\n      flex: '1',\n      display: 'flex',\n      gap: `${vwCalculator(36)}`,\n    },\n    footerLink: {\n      fontFamily: 'DM Sans',\n      fontWeight: 500,\n      fontSize: '16px',\n      lineHeight: '41px',\n      color: '#BDBDBD',\n      cursor: 'pointer',\n      transitionDuration: '300ms',\n      '&:hover': {\n        color: '#F2F2F2',\n      },\n    },\n    footerSocial: {\n      display: 'flex',\n      alignItems: 'center',\n      gap: `${vwCalculator(9)}`,\n    },\n    socialIcon: {\n      cursor: 'pointer',\n    },\n  }),\n)\n\nconst navLinks = [\n  { label: 'Strategies', link: '/strategies/crab' },\n  { label: 'Squeeth', link: '/squeeth' },\n  { label: 'Auction', link: 'https://squeethportal.xyz', analyticsEvent: SITE_EVENTS.NAV_AUCTION },\n  { label: 'Research', link: 'https://research.opyn.co', analyticsEvent: SITE_EVENTS.NAV_RESEARCH },\n  {\n    label: 'FAQ',\n    link: 'https://opyn.gitbook.io/opyn-hub',\n    analyticsEvent: SITE_EVENTS.NAV_FAQ,\n  },\n]\n\nconst footerLinks = [\n  { label: 'Developers', link: 'https://opyn.gitbook.io/squeeth-1/', analyticsEvent: LANDING_EVENTS.NAV_DEVELOPERS },\n  { label: 'Blog', link: 'https://medium.com/opyn', analyticsEvent: LANDING_EVENTS.NAV_BLOG },\n  {\n    label: 'Security',\n    link: 'https://opyn.gitbook.io/squeeth-faq/squeeth/security',\n    analyticsEvent: LANDING_EVENTS.NAV_SECURITY,\n  },\n]\n\nfunction DesktopLandingPage() {\n  const classes = useStyles()\n  const tvl = useTVL()\n  const { track } = useAmplitude()\n\n  useEffect(() => {\n    track(LANDING_EVENTS.LANDING_VISIT_DESKTOP)\n  }, [track])\n\n  return (\n    <div className={classes.landing_page_container}>\n      <div className={classes.nav}>\n        <div className={classes.logo}>\n          <Link href={'/'} passHref>\n            <Image src={logo} alt=\"logo\" width={97} height={75} />\n          </Link>\n        </div>\n        <div className={classes.navLinks}>\n          {navLinks.map((link) => (\n            <Typography\n              onClick={() => link.analyticsEvent && track(link.analyticsEvent)}\n              variant=\"h3\"\n              className={classes.navLink}\n              key={link.label}\n            >\n              <Link href={link.link} passHref>\n                {link.label}\n              </Link>\n            </Typography>\n          ))}\n          <div className={classes.navAction}>\n            <Link href={'/strategies/crab'} passHref>\n              <Button onClick={() => track(LANDING_EVENTS.NAV_START_EARNING)} className={classes.navStartEarningButton}>\n                Start Earning\n              </Button>\n            </Link>\n          </div>\n        </div>\n      </div>\n      <div className={classes.background1} />\n      <div className={classes.background2} />\n      <div className={classes.content}>\n        <ShutdownAlert />\n\n        <div className={classes.introSection}>\n          <div className={classes.introSectionLeft}>\n            <div>\n              <Typography variant=\"h1\" className={clsx([classes.introSectionHeading, classes.gradientText])}>\n                Stack your ETH\n              </Typography>\n              <Typography variant=\"h1\" className={clsx([classes.introSectionHeading, classes.gradientText])}>\n                & stables.\n              </Typography>\n              <div style={{ marginTop: '24px' }} />\n              <Typography variant=\"h2\" className={classes.introSectionSubHeading}>\n                Investment strategies for DeFi.\n              </Typography>\n              <Typography variant=\"h2\" className={classes.introSectionSubHeading}>\n                Powered by squeeth.\n              </Typography>\n              <div style={{ marginTop: '39px' }} />\n              <Link href={'/strategies/crab'} passHref>\n                <Button\n                  onClick={() => track(LANDING_EVENTS.NAV_HERO_TOP_START_EARNING)}\n                  className={classes.navStartEarningButton}\n                >\n                  Start Earning\n                </Button>\n              </Link>\n            </div>\n          </div>\n          <div className={classes.imageSectionRight}>\n            <div className={classes.imageSection}>\n              <Image src={LandingTitle} alt=\"Title Image\" placeholder=\"blur\" />\n            </div>\n          </div>\n        </div>\n        <div className={classes.statSection}>\n          <div className={classes.statSectionItem}>\n            <div className={clsx([classes.statSectionTitle, classes.gradientText])}>$16b+</div>\n            <div className={classes.statSectionSubTitle}>Total Notional</div>\n            <div className={classes.statSectionSubTitle}>Volume</div>\n          </div>\n          <div className={classes.statSectionItem}>\n            <div className={clsx([classes.statSectionTitle, classes.gradientText])}>${tvl}m+</div>\n            <div className={classes.statSectionSubTitle}>Total Value</div>\n            <div className={classes.statSectionSubTitle}>Locked</div>\n          </div>\n        </div>\n        <div className={classes.squeethSection}>\n          <div className={classes.introSectionLeft}>\n            <div>\n              <div className={classes.contentSectionHeader}>\n                <div className={classes.contentSectionHeaderImage}>\n                  <Image src={logo} alt=\"logo\" width={97} height={75} />\n                </div>\n                <Typography variant=\"h3\" className={clsx([classes.contentSectionHeaderLabel, classes.gradientText])}>\n                  SQUEETH\n                </Typography>\n              </div>\n              <div style={{ marginTop: '25px' }} />\n              <Typography variant=\"h3\" className={classes.contentSectionTitle}>\n                Leverage without liquidations.\n              </Typography>\n              <div style={{ marginTop: '41px' }} />\n              <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n                Bet on ETH with unlimited upside,\n              </Typography>\n              <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n                protected downside, and no liquidations.\n              </Typography>\n              <div style={{ marginTop: '41px' }} />\n              <Link href={'/squeeth'} passHref>\n                <Button onClick={() => track(LANDING_EVENTS.NAV_HERO_SQUEETH)} className={classes.contentSectionButton}>\n                  Trade Squeeth\n                </Button>\n              </Link>\n            </div>\n          </div>\n          <div className={classes.imageSectionRight}>\n            <div className={classes.imageSection}>\n              <Image src={Squeeth} alt=\"Squeeth Image\" placeholder=\"blur\" />\n            </div>\n          </div>\n        </div>\n        <div className={classes.strategiesSection}>\n          <div className={classes.introSectionLeft}>\n            <div>\n              <div className={classes.contentSectionHeader}>\n                <div className={classes.contentSectionHeaderImage}>\n                  <Image src={logo} alt=\"logo\" width={97} height={75} />\n                </div>\n                <Typography variant=\"h3\" className={clsx([classes.contentSectionHeaderLabel, classes.gradientText])}>\n                  STRATEGIES\n                </Typography>\n              </div>\n              <div style={{ marginTop: '25px' }} />\n              <Typography variant=\"h3\" className={classes.contentSectionTitle}>\n                Earn returns on your crypto.\n              </Typography>\n              <div style={{ marginTop: '41px' }} />\n              <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n                ETH and USDC strategies to\n              </Typography>\n              <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n                supercharge your portfolio.\n              </Typography>\n              <div style={{ marginTop: '41px' }} />\n              <Link href={'/strategies/crab'} passHref>\n                <Button\n                  onClick={() => track(LANDING_EVENTS.NAV_HERO_DOWN_START_EARNING)}\n                  className={classes.contentSectionButton}\n                >\n                  Start Earning\n                </Button>\n              </Link>\n            </div>\n          </div>\n          <div className={classes.imageSectionRight}>\n            <div className={classes.imageSection}>\n              <Image src={Strategies} alt=\"Strategies Image\" placeholder=\"blur\" />\n            </div>\n          </div>\n        </div>\n        <div className={classes.auctionSection}>\n          <div className={classes.auctionSectionLeft}>\n            <div className={classes.imageSection}>\n              <Image src={Auction} alt=\"Auction Image\" placeholder=\"blur\" />\n            </div>\n          </div>\n          <div className={classes.auctionSectionRight}>\n            <div>\n              <div className={classes.contentSectionHeader}>\n                <div className={classes.contentSectionHeaderImage}>\n                  <Image src={logo} alt=\"logo\" width={97} height={75} />\n                </div>\n                <Typography variant=\"h3\" className={clsx([classes.contentSectionHeaderLabel, classes.gradientText])}>\n                  AUCTION\n                </Typography>\n              </div>\n              <div style={{ marginTop: '25px' }} />\n              <Typography variant=\"h3\" className={classes.contentSectionTitle}>\n                Trade squeeth in size.\n              </Typography>\n              <div style={{ marginTop: '41px' }} />\n              <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n                Participate in large, regular auctions to trade\n              </Typography>\n              <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n                squeeth in size with low price impact.\n              </Typography>\n              <div style={{ marginTop: '41px' }} />\n              <Link href={'https://squeethportal.xyz'} passHref>\n                <Button onClick={() => track(LANDING_EVENTS.NAV_HERO_AUCTION)} className={classes.contentSectionButton}>\n                  Try Auction\n                </Button>\n              </Link>\n            </div>\n          </div>\n        </div>\n        <div style={{ marginTop: '50px' }} />\n      </div>\n      <div className={classes.footer}>\n        <div className={classes.footerLinks}>\n          {footerLinks.map((link) => (\n            <Typography\n              onClick={() => link.analyticsEvent && track(link.analyticsEvent)}\n              key={link.label}\n              variant=\"h4\"\n              className={classes.footerLink}\n            >\n              <Link href={link.link} passHref>\n                {link.label}\n              </Link>\n            </Typography>\n          ))}\n        </div>\n        <div className={classes.footerSocial}>\n          <div onClick={() => track(LANDING_EVENTS.NAV_SOCIAL_TWITTER)}>\n            <Link href={'https://twitter.com/opyn_'} passHref>\n              <Image className={classes.socialIcon} src={Twitter} alt=\"Opyn Twitter\" />\n            </Link>\n          </div>\n          <div onClick={() => track(LANDING_EVENTS.NAV_SOCIAL_DISCORD)}>\n            <Link href={'https://tiny.cc/opyndiscord'} passHref>\n              <Image className={classes.socialIcon} src={Discord} alt=\"Opyn Discord\" />\n            </Link>\n          </div>\n          <div onClick={() => track(LANDING_EVENTS.NAV_SOCIAL_GITHUB)}>\n            <Link href={'https://github.com/opynfinance/squeeth-monorepo'} passHref>\n              <Image className={classes.socialIcon} src={Github} alt=\"Opyn Github\" />\n            </Link>\n          </div>\n          <div onClick={() => track(LANDING_EVENTS.NAV_SOCIAL_MEDIUM)}>\n            <Link href={'https://medium.com/opyn'} passHref>\n              <Image className={classes.socialIcon} src={Medium} alt=\"Opyn Medium\" />\n            </Link>\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n\nexport default DesktopLandingPage\n"
  },
  {
    "path": "packages/frontend/src/components/LandingPage/MobileLandingPage.tsx",
    "content": "import React, { useEffect, useState } from 'react'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport { Paper } from '@material-ui/core'\nimport Hamburger from 'hamburger-react'\nimport Collapse from '@material-ui/core/Collapse'\nimport logo from 'public/images/OpynLogo.svg'\nimport LandingPageBackgroundOne from 'public/images/landing/athena1.png'\nimport LandingPageBackgroundTwo from 'public/images/landing/athena2.png'\nimport LandingPageBackgroundThree from 'public/images/landing/athena3.png'\nimport LandingPageBackgroundFour from 'public/images/landing/athena4.png'\nimport SqueethMobile from 'public/images/landing/squeeth-mobile.png'\nimport StrategiesMobile from 'public/images/landing/strategies-mobile.png'\nimport AuctionMobile from 'public/images/landing/auction-mobile.png'\nimport Link from 'next/link'\nimport Twitter from 'public/images/landing/twitter.svg'\nimport Discord from 'public/images/landing/discord.svg'\nimport Github from 'public/images/landing/github.svg'\nimport Medium from 'public/images/landing/medium.svg'\nimport Image from 'next/image'\nimport clsx from 'clsx'\nimport { Button, Typography } from '@material-ui/core'\nimport { useTVL } from '@hooks/useTVL'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { LANDING_EVENTS, SITE_EVENTS } from '@utils/amplitude'\nimport { ShutdownAlert } from '@components/Alerts/ShutdownAlert'\n\nconst designBaseWidth = 393\n\nconst vwCalculator = (width: number) => {\n  return `${(width / designBaseWidth) * 100}vw`\n}\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    body: {\n      overflow: 'hidden',\n    },\n    gradientText: {\n      background: `linear-gradient(180deg, #FFFFFF 0%, #C2C2C2 100%)`,\n      WebkitBackgroundClip: 'text',\n      WebkitTextFillColor: 'transparent',\n    },\n    landing_page_container: {\n      width: '100%',\n      height: '100%',\n      overflow: 'hidden',\n    },\n    nav: {\n      padding: `0px ${vwCalculator(10)}`,\n      display: 'flex',\n      alignItems: 'center',\n      boxShadow: '0px 3px 4px rgba(0, 0, 0, 0.2)',\n      background: 'linear-gradient(180deg, #1A1C1D 0%, #191B1C 100%)',\n    },\n    navMenu: {\n      margin: `0 ${vwCalculator(10)}`,\n      position: 'absolute',\n    },\n    navLogo: { flex: 1, alignItems: 'center', justifyContent: 'center', display: 'flex' },\n    navDrawer: {},\n    navDrawerBackground: {\n      backgroundColor: '#191B1C',\n      boxShadow: '1px 1px 5px rgba(255,255,255,.3)',\n      padding: '20px 40px 20px 20px',\n    },\n    backdrop: { marginTop: '20px' },\n    navLinks: {\n      display: 'flex',\n      flexDirection: 'column',\n      gap: `${vwCalculator(15)}`,\n      flex: 1,\n    },\n    drawer: {\n      position: 'absolute',\n      width: '100vw',\n      zIndex: 1,\n    },\n    drawerWrapper: {\n      backgroundColor: '#232526',\n      padding: '20px 20px',\n    },\n    navLink: {\n      fontFamily: 'DM Sans',\n      fontWeight: 700,\n      fontSize: `16px`,\n      lineHeight: '140%',\n      color: '#F2F2F2',\n      opacity: 0.5,\n      cursor: 'pointer',\n      transitionDuration: '300ms',\n      '&:hover': {\n        opacity: 1,\n      },\n    },\n    navAction: {\n      position: 'absolute',\n      right: '10px',\n    },\n    navStartEarningButton: {\n      backgroundColor: theme.palette.primary.main,\n      padding: `10px ${vwCalculator(15)}`,\n      fontFamily: 'Avenir',\n      fontWeight: 800,\n      fontSize: '12px',\n      lineHeight: '130%',\n      maxWidth: '250px',\n      '&:hover': {\n        backgroundColor: theme.palette.primary.dark,\n      },\n    },\n    introStartEarningButton: {\n      padding: `20px ${vwCalculator(20)}`,\n      fontSize: '20px',\n    },\n    athenaGraphicAbsoluteContainer: { position: 'absolute', width: '100vw', zIndex: -1 },\n    background1: {\n      display: 'flex',\n      justifyContent: 'flex-end',\n    },\n    background2: {\n      height: `100%`,\n      marginTop: '-15vh',\n    },\n    background3: {\n      display: 'flex',\n      justifyContent: 'flex-end',\n      marginTop: '-3vh',\n    },\n    background4: {\n      marginTop: '20vh',\n    },\n    content: {},\n    introSection: {\n      display: 'flex',\n      padding: `2vw`,\n      justifyContent: 'center',\n      alignItems: 'center',\n      textAlign: 'center',\n      marginTop: '12vh',\n    },\n    introSectionHeading: {\n      fontFamily: 'DM Sans',\n      fontWeight: 700,\n      fontSize: '48px',\n      margin: 0,\n    },\n    introSectionSubHeading: {\n      fontFamily: 'DM Sans',\n      fontWeight: 500,\n      fontSize: '20px',\n      lineHeight: '26px',\n      color: '#BDBDBD',\n      margin: 0,\n      [theme.breakpoints.down('lg')]: {\n        fontSize: '42px',\n      },\n      [theme.breakpoints.down('md')]: {\n        fontSize: '42px',\n      },\n      [theme.breakpoints.down('sm')]: {\n        fontSize: '30px',\n      },\n      [theme.breakpoints.down('xs')]: {\n        fontSize: '20px',\n      },\n    },\n    verticalImage: {\n      margin: 'auto',\n      width: '65vw',\n    },\n    imageSection: {\n      maxWidth: `${vwCalculator(610)}`,\n    },\n    statSection: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n      gap: `${vwCalculator(50)}`,\n      marginTop: '11vh',\n    },\n    statSectionItem: {\n      display: 'flex',\n      justifyContent: 'center',\n      alignItems: 'center',\n      flexDirection: 'column',\n    },\n    statSectionTitle: {\n      fontFamily: 'DM Sans',\n      fontWeight: 400,\n      fontSize: '44px',\n      lineHeight: '57px',\n    },\n    statSectionSubTitle: {\n      maxWidth: `${vwCalculator(120)}`,\n      fontFamily: 'DM Sans',\n      fontWeight: 400,\n      fontSize: '16px',\n      lineHeight: '21px',\n      color: '#BDBDBD',\n      textAlign: 'center',\n    },\n    squeethSection: {\n      display: 'flex',\n      flexDirection: 'column',\n\n      padding: '0 10vw',\n      marginTop: '3vh',\n    },\n    contentSectionHeader: {\n      display: 'flex',\n      alignItems: 'center',\n      gap: `${vwCalculator(29)}`,\n    },\n    contentSectionHeaderImage: {\n      maxWidth: '',\n    },\n    contentSectionHeaderLabel: {\n      fontFamily: 'DM Sans',\n      fontWeight: 500,\n      fontSize: '28px',\n      lineHeight: '42px',\n      marginTop: '-5px',\n    },\n    contentSectionTitle: {\n      fontFamily: 'DM Sans',\n      fontWeight: 700,\n      fontSize: '28px',\n      lineHeight: '36px',\n    },\n    contentSectionSubTitle: {\n      fontFamily: 'DM Sans',\n      fontWeight: 500,\n      fontSize: '14px',\n      lineHeight: '18px',\n      color: '#BDBDBD',\n    },\n    contentSectionButton: {\n      backgroundColor: theme.palette.primary.main,\n      padding: `15px ${vwCalculator(10)}`,\n      fontFamily: 'Avenir',\n      fontWeight: 800,\n      fontSize: '14px',\n      lineHeight: '130%',\n      maxWidth: '130px',\n      '&:hover': {\n        backgroundColor: theme.palette.primary.dark,\n      },\n    },\n    strategiesSection: {\n      display: 'flex',\n      padding: `${vwCalculator(120)}`,\n      alignItems: 'center',\n    },\n    auctionSection: {\n      display: 'flex',\n      padding: `${vwCalculator(120)}`,\n      alignItems: 'center',\n      marginTop: '100px',\n    },\n    auctionSectionLeft: {\n      flex: 1,\n    },\n    footer: {\n      display: 'flex',\n      alignItems: 'center',\n      padding: `10px 20px`,\n    },\n    footerLinks: {\n      flex: '1',\n      display: 'flex',\n      gap: `15px`,\n    },\n    footerLink: {\n      fontFamily: 'DM Sans',\n      fontWeight: 500,\n      fontSize: '10px',\n      lineHeight: '41px',\n      color: '#BDBDBD',\n      cursor: 'pointer',\n      transitionDuration: '300ms',\n      '&:hover': {\n        color: '#F2F2F2',\n      },\n    },\n    footerSocial: {\n      display: 'flex',\n      alignItems: 'center',\n      gap: `${vwCalculator(9)}`,\n    },\n    socialIcon: {\n      cursor: 'pointer',\n    },\n  }),\n)\n\nconst navLinks = [\n  { label: 'Strategies', link: '/strategies/crab' },\n  { label: 'Squeeth', link: '/squeeth' },\n  { label: 'Auction', link: 'https://squeethportal.xyz', analyticsEvent: SITE_EVENTS.NAV_AUCTION },\n  { label: 'Research', link: 'https://research.opyn.co', analyticsEvent: SITE_EVENTS.NAV_RESEARCH },\n  {\n    label: 'FAQ',\n    link: 'https://opyn.gitbook.io/opyn-hub',\n    analyticsEvent: SITE_EVENTS.NAV_FAQ,\n  },\n]\n\nconst footerLinks = [\n  { label: 'Developers', link: 'https://opyn.gitbook.io/squeeth-1/', analyticsEvent: LANDING_EVENTS.NAV_DEVELOPERS },\n  { label: 'Blog', link: 'https://medium.com/opyn', analyticsEvent: LANDING_EVENTS.NAV_BLOG },\n  {\n    label: 'Security',\n    link: 'https://opyn.gitbook.io/squeeth-faq/squeeth/security',\n    analyticsEvent: LANDING_EVENTS.NAV_SECURITY,\n  },\n]\n\nfunction MobileLandingPage() {\n  const [navOpen, setNavOpen] = useState(false)\n  const classes = useStyles()\n  const tvl = useTVL()\n  const { track } = useAmplitude()\n\n  useEffect(() => {\n    track(LANDING_EVENTS.LANDING_VISIT_MOBILE)\n  }, [track])\n\n  return (\n    <div className={classes.landing_page_container}>\n      <div className={classes.nav}>\n        <div className={classes.navMenu}>\n          <Hamburger size={20} toggled={navOpen} toggle={setNavOpen} />\n        </div>\n        <div className={classes.navLogo}>\n          <Link href={'/'} passHref>\n            <Image src={logo} alt=\"logo\" width={83} height={59} />\n          </Link>\n        </div>\n        <div className={classes.navAction}>\n          <Link href={'/strategies/crab'} passHref>\n            <Button onClick={() => track(LANDING_EVENTS.NAV_START_EARNING)} className={classes.navStartEarningButton}>\n              Launch\n            </Button>\n          </Link>\n        </div>\n      </div>\n\n      <div style={{ position: 'absolute', width: '100vw', zIndex: 1 }}>\n        <Collapse in={navOpen}>\n          <Paper className={classes.drawerWrapper} elevation={2}>\n            <div className={classes.navLinks}>\n              {navLinks.map((link) => (\n                <Typography\n                  onClick={() => link.analyticsEvent && track(link.analyticsEvent)}\n                  variant=\"h3\"\n                  className={classes.navLink}\n                  key={link.label}\n                >\n                  <Link href={link.link} passHref>\n                    {link.label}\n                  </Link>\n                </Typography>\n              ))}\n            </div>\n          </Paper>\n        </Collapse>\n      </div>\n\n      <div className={classes.athenaGraphicAbsoluteContainer}>\n        <div>\n          <div className={classes.background1}>\n            <Image src={LandingPageBackgroundOne} alt=\"Athena 1\" />\n          </div>\n          <div className={classes.background2}>\n            <Image src={LandingPageBackgroundTwo} alt=\"Athena 2\" />\n          </div>\n          <div className={classes.background3}>\n            <Image src={LandingPageBackgroundThree} alt=\"Athena 3\" />\n          </div>\n          <div className={classes.background4}>\n            <Image src={LandingPageBackgroundFour} alt=\"Athena 4\" />\n          </div>\n        </div>\n      </div>\n      <div className={classes.content}>\n        <ShutdownAlert />\n\n        <div className={classes.introSection}>\n          <div>\n            <Typography variant=\"h1\" className={clsx([classes.introSectionHeading, classes.gradientText])}>\n              Stack your ETH\n            </Typography>\n            <Typography variant=\"h1\" className={clsx([classes.introSectionHeading, classes.gradientText])}>\n              & stables.\n            </Typography>\n            <div style={{ marginTop: '15px' }} />\n            <Typography variant=\"h2\" className={classes.introSectionSubHeading}>\n              Powerful investment strategies for DeFi.\n            </Typography>\n            <Typography variant=\"h2\" className={classes.introSectionSubHeading}>\n              Built on squeeth.\n            </Typography>\n            <div style={{ marginTop: '20px' }} />\n            <Link href={'/strategies/crab'} passHref>\n              <Button\n                onClick={() => track(LANDING_EVENTS.NAV_HERO_TOP_START_EARNING)}\n                className={clsx([classes.navStartEarningButton, classes.introStartEarningButton])}\n              >\n                Start Earning\n              </Button>\n            </Link>\n          </div>\n        </div>\n        <div className={classes.statSection}>\n          <div className={classes.statSectionItem}>\n            <div className={clsx([classes.statSectionTitle, classes.gradientText])}>$16b</div>\n            <div className={classes.statSectionSubTitle}>Total Notional Volume</div>\n          </div>\n          <div className={classes.statSectionItem}>\n            <div className={clsx([classes.statSectionTitle, classes.gradientText])}>${tvl}m</div>\n            <div className={classes.statSectionSubTitle}>Total Value Locked</div>\n          </div>\n        </div>\n        <div style={{ marginTop: '11vh' }} />\n        <div className={classes.verticalImage}>\n          <Image src={SqueethMobile} alt=\"Squeeth\" placeholder=\"blur\" />\n        </div>\n        <div className={classes.squeethSection}>\n          <div className={classes.contentSectionHeader}>\n            <div className={classes.contentSectionHeaderImage}>\n              <Image src={logo} alt=\"logo\" width={70} height={53} />\n            </div>\n            <Typography variant=\"h3\" className={clsx([classes.contentSectionHeaderLabel, classes.gradientText])}>\n              SQUEETH\n            </Typography>\n          </div>\n          <div style={{ marginTop: '15px' }} />\n          <Typography variant=\"h3\" className={classes.contentSectionTitle}>\n            Leverage without liquidations.\n          </Typography>\n          <div style={{ marginTop: '15px' }} />\n          <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n            Bet on ETH with unlimited upside,\n          </Typography>\n          <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n            protected downside, and no liquidations.\n          </Typography>\n          <div style={{ marginTop: '15px' }} />\n          <Link href={'/squeeth'} passHref>\n            <Button onClick={() => track(LANDING_EVENTS.NAV_HERO_SQUEETH)} className={classes.contentSectionButton}>\n              Trade Squeeth\n            </Button>\n          </Link>\n        </div>\n        <div style={{ marginTop: '17vh' }} />\n        <div className={classes.verticalImage}>\n          <Image src={StrategiesMobile} alt=\"Strategies\" placeholder=\"blur\" />\n        </div>\n        <div className={classes.squeethSection}>\n          <div className={classes.contentSectionHeader}>\n            <div className={classes.contentSectionHeaderImage}>\n              <Image src={logo} alt=\"logo\" width={70} height={53} />\n            </div>\n            <Typography variant=\"h3\" className={clsx([classes.contentSectionHeaderLabel, classes.gradientText])}>\n              STRATEGIES\n            </Typography>\n          </div>\n          <div style={{ marginTop: '15px' }} />\n          <Typography variant=\"h3\" className={classes.contentSectionTitle}>\n            Earn returns on\n          </Typography>\n          <Typography variant=\"h3\" className={classes.contentSectionTitle}>\n            your crypto.\n          </Typography>\n          <div style={{ marginTop: '15px' }} />\n          <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n            ETH and USDC strategies to supercharge\n          </Typography>\n          <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n            your portfolio.\n          </Typography>\n          <div style={{ marginTop: '15px' }} />\n          <Link href={'/strategies/crab'} passHref>\n            <Button\n              onClick={() => track(LANDING_EVENTS.NAV_HERO_DOWN_START_EARNING)}\n              className={classes.contentSectionButton}\n            >\n              Start Earning\n            </Button>\n          </Link>\n        </div>\n        <div style={{ marginTop: '19vh' }} />\n        <div className={classes.verticalImage}>\n          <Image src={AuctionMobile} alt=\"Auction\" placeholder=\"blur\" />\n        </div>\n        <div className={classes.squeethSection}>\n          <div className={classes.contentSectionHeader}>\n            <div className={classes.contentSectionHeaderImage}>\n              <Image src={logo} alt=\"logo\" width={70} height={53} />\n            </div>\n            <Typography variant=\"h3\" className={clsx([classes.contentSectionHeaderLabel, classes.gradientText])}>\n              AUCTION\n            </Typography>\n          </div>\n          <div style={{ marginTop: '15px' }} />\n          <Typography variant=\"h3\" className={classes.contentSectionTitle}>\n            Trade squeeth in size.\n          </Typography>\n          <div style={{ marginTop: '15px' }} />\n          <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n            Participate in large, regular auctions to trade\n          </Typography>\n          <Typography variant=\"h3\" className={classes.contentSectionSubTitle}>\n            squeeth in size with low price impact.\n          </Typography>\n          <div style={{ marginTop: '15px' }} />\n          <Link href={'https://squeethportal.xyz'} passHref>\n            <Button onClick={() => track(LANDING_EVENTS.NAV_HERO_AUCTION)} className={classes.contentSectionButton}>\n              Try Auction\n            </Button>\n          </Link>\n        </div>\n        <div style={{ marginTop: '5vh' }} />\n        <div className={classes.footer}>\n          <div className={classes.footerLinks}>\n            {footerLinks.map((link) => (\n              <Typography\n                onClick={() => link.analyticsEvent && track(link.analyticsEvent)}\n                key={link.label}\n                variant=\"h4\"\n                className={classes.footerLink}\n              >\n                <Link href={link.link} passHref>\n                  {link.label}\n                </Link>\n              </Typography>\n            ))}\n          </div>\n          <div className={classes.footerSocial}>\n            <div onClick={() => track(LANDING_EVENTS.NAV_SOCIAL_TWITTER)}>\n              <Link href={'https://twitter.com/opyn_'} passHref>\n                <Image className={classes.socialIcon} src={Twitter} alt=\"Opyn Twitter\" />\n              </Link>\n            </div>\n            <div onClick={() => track(LANDING_EVENTS.NAV_SOCIAL_DISCORD)}>\n              <Link href={'https://tiny.cc/opyndiscord'} passHref>\n                <Image className={classes.socialIcon} src={Discord} alt=\"Opyn Discord\" />\n              </Link>\n            </div>\n            <div onClick={() => track(LANDING_EVENTS.NAV_SOCIAL_GITHUB)}>\n              <Link href={'https://github.com/opynfinance/squeeth-monorepo'} passHref>\n                <Image className={classes.socialIcon} src={Github} alt=\"Opyn Github\" />\n              </Link>\n            </div>\n            <div onClick={() => track(LANDING_EVENTS.NAV_SOCIAL_MEDIUM)}>\n              <Link href={'https://medium.com/opyn'} passHref>\n                <Image className={classes.socialIcon} src={Medium} alt=\"Opyn Medium\" />\n              </Link>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n\nexport default MobileLandingPage\n"
  },
  {
    "path": "packages/frontend/src/components/LegendBox.tsx",
    "content": "import { createStyles, makeStyles, Box, Tooltip } from '@material-ui/core'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport React from 'react'\n\nconst useStyles = makeStyles(() =>\n  createStyles({\n    legendContainer: {\n      display: 'flex',\n      gap: '5px',\n    },\n  }),\n)\n\ntype LegendBoxType = {\n  bgColor: string\n  text: string\n  tooltip?: string\n}\n\nconst LegendBox: React.FC<LegendBoxType> = ({ bgColor, text, tooltip }) => {\n  const classes = useStyles()\n\n  return (\n    <Box className={classes.legendContainer}>\n      <Box width={20} height={20} bgcolor={bgColor} />\n      <div>{text}</div>\n      {tooltip && (\n        <Tooltip title={tooltip}>\n          <InfoIcon fontSize=\"small\" />\n        </Tooltip>\n      )}\n    </Box>\n  )\n}\n\nexport default LegendBox\n"
  },
  {
    "path": "packages/frontend/src/components/LinkWrapper.tsx",
    "content": "import { createStyles, makeStyles } from '@material-ui/core/styles'\nimport OpenInNewIcon from '@material-ui/icons/OpenInNew'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    linkWrap: {\n      display: 'inline-flex',\n      alignItems: 'center',\n      color: theme.palette.primary.main,\n      gap: '3px',\n      '&:hover': {\n        opacity: '0.8',\n        textDecoration: 'underline',\n      },\n    },\n  }),\n)\n\ninterface LinkWrapperProps {\n  href: string\n  onClick?: () => void\n}\n\nexport const LinkWrapper: React.FC<LinkWrapperProps> = ({ href, children, onClick }) => {\n  const classes = useStyles()\n  return (\n    <a className={classes.linkWrap} href={href} target=\"_blank\" rel=\"noopener noreferrer\" onClick={onClick}>\n      {children}\n      <OpenInNewIcon style={{ width: '13px' }} />\n    </a>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Lp/GetSqueeth.tsx",
    "content": "import { Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport { motion } from 'framer-motion'\nimport React from 'react'\n\nimport { LPActions, OBTAIN_METHOD, useLPState } from '@context/lp'\nimport Long from '@components/Trade/Long'\nimport MintSqueeth from '@components/Trade/Mint'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    title: {\n      textAlign: 'center',\n      fontSize: '18px',\n      fontWeight: 500,\n      marginBottom: theme.spacing(2),\n    },\n  }),\n)\n\nconst GetSqueeth: React.FC = () => {\n  const classes = useStyles()\n  const { lpState, dispatch } = useLPState()\n\n  const onMint = () => {\n    dispatch({ type: LPActions.GO_TO_PROVIDE_LIQUIDITY })\n  }\n\n  return (\n    <>\n      <Typography className={classes.title}>\n        {lpState.obtainMethod === OBTAIN_METHOD.BUY ? 'Buy Squeeth to LP' : 'Mint Squeeth to LP'}\n      </Typography>\n      <motion.div initial={{ x: '-5%', opacity: 0.8 }} animate={{ x: 0, opacity: 1 }}>\n        {lpState.obtainMethod === OBTAIN_METHOD.BUY ? (\n          <Long isLPage open={true} showTitle={false} />\n        ) : (\n          <MintSqueeth onMint={onMint} />\n        )}\n      </motion.div>\n    </>\n  )\n}\n\nexport default GetSqueeth\n"
  },
  {
    "path": "packages/frontend/src/components/Lp/LPPosition.tsx",
    "content": "import React from 'react'\nimport { Typography, Box } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport { useAtomValue } from 'jotai'\nimport Link from 'next/link'\n\nimport { squeethLiquidityAtom, wethLiquidityAtom } from '@state/positions/atoms'\nimport { useLPPositionsQuery } from '@state/positions/hooks'\nimport Metric from '@components/Metric'\nimport { formatNumber } from '@utils/formatter'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    link: {\n      color: theme.palette.primary.main,\n      fontWeight: 500,\n      fontSize: '14px',\n    },\n    subtitle: {\n      fontSize: '20px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n    },\n  }),\n)\n\nconst LPPosition: React.FC = () => {\n  const classes = useStyles()\n  const squeethLiquidity = useAtomValue(squeethLiquidityAtom)\n  const wethLiquidity = useAtomValue(wethLiquidityAtom)\n  const { loading } = useLPPositionsQuery()\n\n  if (loading) {\n    return <div>{'Fetching LP position...'}</div>\n  }\n\n  if (squeethLiquidity.isZero() && wethLiquidity.isZero()) {\n    return null\n  }\n\n  return (\n    <>\n      <Box display=\"flex\" alignItems=\"center\" gridGap=\"32px\">\n        <Typography variant=\"h4\" className={classes.subtitle}>\n          My Position\n        </Typography>\n        <Typography className={classes.link} id=\"pos-card-manage-vault-link\">\n          <Link href={`/positions`}>Sell full position</Link>\n        </Typography>\n      </Box>\n\n      <Box display=\"flex\" gridGap=\"12px\" marginTop=\"16px\" flexWrap=\"wrap\">\n        <Metric gridGap=\"6px\" label=\"oSQTH Liquidity\" value={formatNumber(squeethLiquidity.toNumber(), 4) + ' oSQTH'} />\n        <Metric gridGap=\"6px\" label=\"WETH Liquidity\" value={formatNumber(wethLiquidity.toNumber(), 4) + ' WETH'} />\n      </Box>\n    </>\n  )\n}\n\nexport default LPPosition\n"
  },
  {
    "path": "packages/frontend/src/components/Lp/LPTable.tsx",
    "content": "import { Chip, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Tooltip } from '@material-ui/core'\nimport Paper from '@material-ui/core/Paper'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport { Pool } from '@uniswap/v3-sdk'\nimport BigNumber from 'bignumber.js'\nimport Link from 'next/link'\nimport * as React from 'react'\nimport { useState } from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { SecondaryTab, SecondaryTabs } from '../../components/Tabs'\nimport { Tooltips, UniswapIFrameOpen } from '@constants/enums'\nimport { inRange } from '@utils/calculations'\nimport { UniswapIframe } from '../Modal/UniswapIframe'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\nimport { useETHPrice } from '@hooks/useETHPrice'\nimport { activePositionsAtom, closedPositionsAtom, isWethToken0Atom } from 'src/state/positions/atoms'\nimport { useGetWSqueethPositionValue } from 'src/state/squeethPool/hooks'\nimport { useLPPositionsQuery } from 'src/state/positions/hooks'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    tableContainer: {\n      flexBasis: '72%',\n      marginRight: '1.5em',\n      marginTop: theme.spacing(2),\n      borderRadius: theme.spacing(1),\n      backgroundColor: `${theme.palette.background.paper}40`,\n      height: '25vh',\n    },\n    isLPageTableContainer: {\n      flexBasis: '72%',\n      marginTop: theme.spacing(2),\n      marginRight: '1.5em',\n    },\n    table: {\n      minWidth: 650,\n    },\n    listLink: {\n      color: '#FF007A',\n    },\n    linkHover: {\n      '&:hover': {\n        opacity: 0.7,\n      },\n    },\n    anchor: {\n      color: '#FF007A',\n      fontSize: '16px',\n    },\n    tokenIdLink: {\n      textDecoration: 'underline',\n      cursor: 'pointer',\n    },\n    inRange: {\n      backgroundColor: theme.palette.success.main,\n    },\n    outRange: {\n      backgroundColor: theme.palette.error.main,\n    },\n    tabBackGround: {\n      position: 'sticky',\n      top: '0',\n      zIndex: 20,\n    },\n    infoIcon: {\n      fontSize: '.75rem',\n      marginLeft: theme.spacing(0.5),\n      marginTop: '2px',\n    },\n  }),\n)\n\ninterface LPTableProps {\n  isLPage?: boolean\n  pool?: Pool | undefined\n}\n\nconst calculatePnL = (\n  depositedToken0: string | undefined,\n  depositedToken1: string | undefined,\n  withdrawToken0: string | undefined,\n  withdrawToken1: string | undefined,\n  ethPrice: BigNumber,\n  squeethPrice: BigNumber,\n  currValue: BigNumber | undefined,\n  isWethToken0: boolean,\n): BigNumber => {\n  if (!depositedToken0 || !depositedToken1 || !currValue) {\n    return new BigNumber(0)\n  }\n  const depToken0 = new BigNumber(depositedToken0)\n  const depToken1 = new BigNumber(depositedToken1)\n\n  const withToken0 = new BigNumber(withdrawToken0 || 0)\n  const withToken1 = new BigNumber(withdrawToken1 || 0)\n\n  const ethDepValue = (isWethToken0 ? depToken0 : depToken1).times(ethPrice)\n  const squeethDepValue = (isWethToken0 ? depToken1 : depToken0).times(squeethPrice)\n  const ethWithdrawValue = (isWethToken0 ? withToken0 : withToken1).times(ethPrice)\n  const squeethWithdrawValue = (isWethToken0 ? withToken1 : withToken0).times(squeethPrice)\n\n  const originalValue = ethDepValue.plus(squeethDepValue).minus(ethWithdrawValue).minus(squeethWithdrawValue)\n  return currValue.minus(originalValue)\n}\n\nexport const LPTable: React.FC<LPTableProps> = ({ isLPage, pool }) => {\n  const classes = useStyles()\n  const activePositions = useAtomValue(activePositionsAtom)\n  const closedPositions = useAtomValue(closedPositionsAtom)\n  const { loading: lpLoading } = useLPPositionsQuery()\n\n  const [activeTab, setActiveTab] = useState(0)\n  const ethPrice = useETHPrice()\n  const getWSqueethPositionValue = useGetWSqueethPositionValue()\n  const networkId = useAtomValue(networkIdAtom)\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n\n  return (\n    <TableContainer component={Paper} className={isLPage ? classes.isLPageTableContainer : classes.tableContainer}>\n      {isLPage ? (\n        <SecondaryTabs\n          value={activeTab}\n          onChange={() => (activeTab === 0 ? setActiveTab(1) : setActiveTab(0))}\n          aria-label=\"simple tabs example\"\n          centered\n          variant=\"fullWidth\"\n          className={classes.tabBackGround}\n        >\n          <SecondaryTab label=\"Active\" />\n          <SecondaryTab label=\"Closed\" />\n        </SecondaryTabs>\n      ) : null}\n      <Table aria-label=\"simple table\" className={classes.table}>\n        <TableHead>\n          <TableRow style={{ fontSize: '0.8rem' }}>\n            <TableCell align=\"left\">Token ID</TableCell>\n            <TableCell align=\"left\">In Range</TableCell>\n            <Tooltip title={Tooltips.PercentOfPool}>\n              <TableCell align=\"left\">% of Pool</TableCell>\n            </Tooltip>\n            <TableCell align=\"left\">Liquidity</TableCell>\n            {/* <TableCell align=\"left\">Collected Fees</TableCell> */}\n            <TableCell align=\"left\">Uncollected Fees</TableCell>\n            <TableCell align=\"left\">Value</TableCell>\n            {\n              //only show PnL on active tab for now until closed is implemented\n              activeTab === 0 ? (\n                <TableCell align=\"left\">\n                  <span>PnL</span>\n                  <Tooltip title={Tooltips.LPPnL}>\n                    <InfoIcon className={classes.infoIcon} />\n                  </Tooltip>\n                </TableCell>\n              ) : null\n            }\n          </TableRow>\n        </TableHead>\n\n        {isLPage && activeTab === 1 ? (\n          <TableBody>\n            {closedPositions?.length === 0 ? (\n              lpLoading ? (\n                <TableRow>\n                  <TableCell colSpan={6} align=\"center\" style={{ textAlign: 'center', fontSize: '16px' }}>\n                    <p>Loading...</p>\n                  </TableCell>\n                </TableRow>\n              ) : (\n                <TableRow>\n                  <TableCell colSpan={6} align=\"center\" style={{ textAlign: 'center', fontSize: '16px' }}>\n                    <p>No Closed LP Positions</p>\n\n                    <div>\n                      <UniswapIframe text={'Close LP Position'} closePosition={true} />\n                    </div>\n                  </TableCell>\n                </TableRow>\n              )\n            ) : (\n              closedPositions?.map((p) => {\n                return (\n                  <TableRow key={p.id}>\n                    <TableCell component=\"th\" align=\"left\" scope=\"row\">\n                      <a\n                        href={\n                          networkId === 3\n                            ? `https://squeeth-uniswap.netlify.app/#/pool/${p.id}`\n                            : `https://app.uniswap.org/#/pool/${p.id}`\n                        }\n                        target=\"_blank\"\n                        rel=\"noreferrer\"\n                        className={classes.tokenIdLink}\n                      >\n                        #{p.id}\n                      </a>\n                    </TableCell>\n                    <TableCell align=\"left\">\n                      <Chip label=\"Closed\" size=\"small\" />\n                    </TableCell>\n                    <TableCell align=\"left\">\n                      {((pool ? p.liquidity / Number(pool?.liquidity) : 0) * 100).toFixed(3)}\n                    </TableCell>\n                    <TableCell align=\"left\">\n                      <span style={{ marginRight: '.5em' }}>\n                        {Number(p.amount0).toFixed(4)} {p.token0.symbol}\n                      </span>\n                      <span>\n                        {Number(p.amount1).toFixed(4)} {p.token1.symbol}\n                      </span>\n                    </TableCell>\n                    {/* <TableCell align=\"left\">\n                <span style={{ marginRight: '.5em' }}>\n                  {p.collectedFeesToken0} {p.token0.symbol}\n                </span>\n                <span>\n                  {p.collectedFeesToken1} {p.token1.symbol}\n                </span>\n              </TableCell> */}\n                    <TableCell align=\"left\">\n                      <span style={{ marginRight: '.5em' }}>\n                        {p.fees0?.toFixed(6)} {p.token0.symbol}\n                      </span>\n                      <span>\n                        {p.fees1?.toFixed(6)} {p.token1.symbol}\n                      </span>\n                    </TableCell>\n                    <TableCell align=\"left\">\n                      <span style={{ marginRight: '.5em' }}>$ {p.dollarValue?.toFixed(2)}</span>\n                    </TableCell>\n                  </TableRow>\n                )\n              })\n            )}\n\n            {closedPositions && closedPositions?.length > 0 && (\n              <TableRow>\n                <TableCell colSpan={7}>\n                  <div style={{ display: 'flex', justifyContent: 'center' }}>\n                    <UniswapIframe text={'Close LP Position'} closePosition={true} />\n                  </div>\n                </TableCell>\n              </TableRow>\n            )}\n          </TableBody>\n        ) : (\n          <TableBody>\n            {activePositions?.length === 0 ? (\n              lpLoading ? (\n                <TableRow>\n                  <TableCell colSpan={7} align=\"center\" style={{ textAlign: 'center', fontSize: '16px' }}>\n                    <p>Loading...</p>\n                  </TableCell>\n                </TableRow>\n              ) : (\n                <TableRow>\n                  <TableCell colSpan={7} align=\"center\" style={{ textAlign: 'center', fontSize: '16px' }}>\n                    <p>No Existing LP Positions</p>\n\n                    <div>\n                      <p>1. Mint or buy squeeth on the right.</p>\n                      <a\n                        href={UniswapIFrameOpen[networkId]}\n                        target={'_blank'}\n                        rel=\"noreferrer\"\n                        style={{ textDecoration: 'underline' }}\n                      >\n                        {' '}\n                        <p>2. Deposit Squeeth and ETH into Uniswap V3 Pool 🦄</p>{' '}\n                      </a>\n                    </div>\n                  </TableCell>\n                </TableRow>\n              )\n            ) : (\n              activePositions?.slice(0, isLPage ? activePositions.length : 3).map((p) => {\n                return (\n                  <TableRow key={p.id}>\n                    <TableCell component=\"th\" align=\"left\" scope=\"row\">\n                      <a\n                        href={\n                          networkId === 3\n                            ? `https://squeeth-uniswap.netlify.app/#/pool/${p.id}`\n                            : `https://app.uniswap.org/#/pool/${p.id}`\n                        }\n                        target=\"_blank\"\n                        rel=\"noreferrer\"\n                        className={classes.tokenIdLink}\n                      >\n                        #{p.id}\n                      </a>\n                    </TableCell>\n                    <TableCell align=\"left\">\n                      {inRange(p.tickLower.tickIdx, p.tickUpper.tickIdx, pool) ? (\n                        <Chip label=\"Yes\" size=\"small\" className={classes.inRange} />\n                      ) : (\n                        <Chip label=\"No\" size=\"small\" className={classes.outRange} />\n                      )}\n                    </TableCell>\n                    <TableCell align=\"left\">\n                      {((pool ? p.liquidity / Number(pool?.liquidity) : 0) * 100).toFixed(3)}\n                    </TableCell>\n                    <TableCell align=\"left\">\n                      <span style={{ marginRight: '.5em' }}>\n                        {Number(p.amount0).toFixed(4)} {p.token0.symbol}\n                      </span>\n                      <span>\n                        {Number(p.amount1).toFixed(4)} {p.token1.symbol}\n                      </span>\n                    </TableCell>\n                    <TableCell align=\"left\">\n                      <span style={{ marginRight: '.5em' }}>\n                        {p.fees0?.toFixed(6)} {p.token0.symbol}\n                      </span>\n                      <span>\n                        {p.fees1?.toFixed(6)} {p.token1.symbol}\n                      </span>\n                    </TableCell>\n                    <TableCell align=\"left\">\n                      <span style={{ marginRight: '.5em' }}>$ {p.dollarValue?.toFixed(2)}</span>\n                    </TableCell>\n                    <TableCell align=\"left\">\n                      <span style={{ marginRight: '.5em' }}>\n                        ${' '}\n                        {calculatePnL(\n                          p.depositedToken0,\n                          p.depositedToken1,\n                          p.withdrawnToken0,\n                          p.withdrawnToken1,\n                          ethPrice,\n                          getWSqueethPositionValue(1),\n                          p.dollarValue,\n                          isWethToken0,\n                        )?.toFixed(3)}\n                      </span>\n                    </TableCell>\n                  </TableRow>\n                )\n              })\n            )}\n            {!isLPage && activePositions?.length > 3 && (\n              <TableRow>\n                <TableCell className={classes.linkHover} colSpan={7} align=\"center\" style={{ fontSize: '1rem' }}>\n                  <Link href=\"/lp\">View more</Link>\n                </TableCell>\n              </TableRow>\n            )}\n\n            {/* {activePositions && activePositions?.length > 0 && (\n              <TableRow>\n                <TableCell colSpan={7}>\n                  <div style={{ display: 'flex', justifyContent: 'center' }}>\n                    <UniswapIframe text={'Deposit Squeeth and ETH into Uniswap V3 Pool 🦄'} />\n                  </div>\n                </TableCell>\n              </TableRow>\n            )} */}\n          </TableBody>\n        )}\n      </Table>\n    </TableContainer>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Lp/ObtainSqueeth.tsx",
    "content": "import { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React from 'react'\n\nimport { Steps, useLPState } from '@context/lp'\nimport GetSqueeth from './GetSqueeth'\nimport ProvideLiquidity from './ProvideLiquidity'\nimport SelectMethod from './SelectMethod'\nimport Stepper from './Stepper'\n\nconst useStyles = makeStyles(() =>\n  createStyles({\n    container: {\n      display: 'flex',\n      justifyContent: 'center',\n      flexDirection: 'column',\n    },\n  }),\n)\n\nconst ObtainSqueeth: React.FC = () => {\n  const classes = useStyles()\n  const { lpState } = useLPState()\n\n  return (\n    <div className={classes.container}>\n      {lpState.step === Steps.SELECT_METHOD ? <SelectMethod /> : null}\n      {lpState.step === Steps.GET_SQUEETH ? <GetSqueeth /> : null}\n      {lpState.step === Steps.PROVIDE_LIQUIDITY ? <ProvideLiquidity /> : null}\n      <Stepper />\n    </div>\n  )\n}\n\nexport default ObtainSqueeth\n"
  },
  {
    "path": "packages/frontend/src/components/Lp/ProvideLiquidity.tsx",
    "content": "import { Typography } from '@material-ui/core'\nimport { orange } from '@material-ui/core/colors'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport OpenInNewIcon from '@material-ui/icons/OpenInNew'\nimport { motion } from 'framer-motion'\nimport React from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { UniswapIFrameOpen } from '@constants/enums'\nimport { networkIdAtom } from '@state/wallet/atoms'\nimport { useRestrictUser } from '@context/restrict-user'\nimport RestrictionInfo from '@components/RestrictionInfo'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      width: '100%',\n      height: '496px',\n      overflow: 'auto',\n    },\n    title: {\n      textAlign: 'center',\n      fontSize: '18px',\n      fontWeight: 500,\n      marginBottom: theme.spacing(2),\n    },\n    iframeBox: {\n      width: '100%',\n      height: '450px',\n      border: 0,\n      borderRadius: theme.spacing(2),\n      display: 'block',\n      zIndex: 1,\n      marginTop: theme.spacing(1),\n    },\n    warning: {\n      color: orange[600],\n      fontWeight: 500,\n      fontSize: 14,\n    },\n    headerDiv: {\n      display: 'flex',\n      flexDirection: 'column',\n      padding: theme.spacing(0, 1),\n    },\n    uniOpenBtn: {\n      display: 'flex',\n      alignItems: 'center',\n      color: theme.palette.primary.main,\n    },\n    restrictionInfo: {\n      marginTop: theme.spacing(5),\n    },\n  }),\n)\n\nconst ProvideLiquidity: React.FC = () => {\n  const classes = useStyles()\n  const networkId = useAtomValue(networkIdAtom)\n  const { isRestricted, isWithdrawAllowed } = useRestrictUser()\n\n  return (\n    <>\n      <Typography className={classes.title}>Provide Liquidity</Typography>\n\n      <motion.div initial={{ x: '-5%', opacity: 0.8 }} animate={{ x: 0, opacity: 1 }} className={classes.container}>\n        <div className={classes.headerDiv}>\n          <Typography variant=\"caption\" className={classes.warning}>\n            Make sure your wallet is connected to Uniswap\n          </Typography>\n          <a\n            className={classes.uniOpenBtn}\n            id=\"open-in-uniswap-to-lp\"\n            href={UniswapIFrameOpen[networkId]}\n            target=\"_blank\"\n            rel=\"noreferrer\"\n          >\n            <Typography variant=\"caption\">Open in Uniswap</Typography>\n            <OpenInNewIcon style={{ fontSize: 16, marginLeft: '4px' }} fontSize=\"small\" />\n          </a>\n        </div>\n        {isRestricted ? (\n          <div className={classes.restrictionInfo}>\n            <RestrictionInfo />\n          </div>\n        ) : (\n          <iframe className={classes.iframeBox} src={UniswapIFrameOpen[networkId]}></iframe>\n        )}\n      </motion.div>\n    </>\n  )\n}\n\nexport default ProvideLiquidity\n"
  },
  {
    "path": "packages/frontend/src/components/Lp/SelectMethod.tsx",
    "content": "import { Typography, Box } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport { motion } from 'framer-motion'\nimport Image from 'next/image'\nimport React from 'react'\n\nimport Logo from '../../../public/images/mint-squeeth.svg'\nimport UniswapLogo from '../../../public/images/uniswap-uni-logo.svg'\nimport { LPActions, OBTAIN_METHOD, useLPState } from '@context/lp'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    title: {\n      textAlign: 'center',\n      fontSize: '18px',\n      fontWeight: 500,\n      marginBottom: theme.spacing(2),\n    },\n    obtainItemContainer: {\n      display: 'flex',\n      flexDirection: 'column',\n      gap: '12px',\n    },\n    obtainItem: {\n      display: 'flex',\n      alignItems: 'center',\n      gap: '12px',\n\n      background: theme.palette.background.stone,\n      borderRadius: theme.spacing(1),\n      padding: theme.spacing(4, 2),\n      cursor: 'pointer',\n      border: `1px solid ${theme.palette.background.lightStone}`,\n      // boxShadow: `${theme.palette.primary.main} 1px 5px 47px 5px`,\n      '&:hover': {\n        border: `1px solid ${theme.palette.primary.main}`,\n      },\n    },\n    obtainItemTitle: {\n      color: 'rgba(255, 255, 255)',\n      fontSize: '20px',\n      fontWeight: 500,\n    },\n\n    obtainItemDetail: {\n      color: 'rgba(255, 255, 255, 0.5)',\n      fontSize: '15px',\n      fontWeight: 500,\n    },\n  }),\n)\n\nconst SelectMethod: React.FC = () => {\n  const classes = useStyles()\n  const { dispatch } = useLPState()\n\n  return (\n    <>\n      <Typography className={classes.title}>Obtain Squeeth</Typography>\n      <div className={classes.obtainItemContainer}>\n        <motion.div\n          initial={{ x: '-5%', opacity: 0.8 }}\n          animate={{ x: 0, opacity: 1 }}\n          className={classes.obtainItem}\n          id=\"mint-sqth-to-lp-btn\"\n          onClick={() => dispatch({ type: LPActions.SELECT_METHOD, payload: OBTAIN_METHOD.MINT })}\n        >\n          <Image src={Logo} alt=\"Comparison Chart\" height={60} width={60} />\n          <Box>\n            <Typography className={classes.obtainItemTitle} variant=\"h6\">\n              Mint Squeeth to LP\n            </Typography>\n            <Typography className={classes.obtainItemDetail}>Mint by depositing ETH as collateral</Typography>\n          </Box>\n        </motion.div>\n        <motion.div\n          initial={{ x: '-5%', opacity: 0.8 }}\n          animate={{ x: 0, opacity: 1 }}\n          className={classes.obtainItem}\n          id=\"buy-sqth-to-lp-btn\"\n          onClick={() => dispatch({ type: LPActions.SELECT_METHOD, payload: OBTAIN_METHOD.BUY })}\n        >\n          <Image src={UniswapLogo} alt=\"Comparison Chart\" height={60} width={60} />\n          <Box>\n            <Typography className={classes.obtainItemTitle} variant=\"h6\">\n              Buy Squeeth to LP\n            </Typography>\n            <Typography className={classes.obtainItemDetail}>Buy directly from Uniswap</Typography>\n          </Box>\n        </motion.div>\n      </div>\n    </>\n  )\n}\n\nexport default SelectMethod\n"
  },
  {
    "path": "packages/frontend/src/components/Lp/SqueethInfo.tsx",
    "content": "import { Box, BoxProps } from '@material-ui/core'\nimport React from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { Tooltips } from '@constants/enums'\nimport { BIG_ZERO } from '@constants/index'\nimport { toTokenAmount } from '@utils/calculations'\nimport {\n  impliedVolAtom,\n  indexAtom,\n  markAtom,\n  osqthRefVolAtom,\n  currentImpliedFundingAtom,\n  impliedVolatilityShutdownAtom,\n  currentImpliedFundingShutdownAtom,\n} from '@state/controller/atoms'\nimport Metric, { MetricLabel } from '@components/Metric'\nimport { formatCurrency, formatNumber } from '@utils/formatter'\nimport { useOSQTHPrice } from '@hooks/useOSQTHPrice'\n\nconst SqueethInfo: React.FC<BoxProps> = (props) => {\n  const mark = useAtomValue(markAtom)\n  const index = useAtomValue(indexAtom)\n  const impliedVolatilityShutdown = useAtomValue(impliedVolatilityShutdownAtom)\n  const osqthRefVol = useAtomValue(osqthRefVolAtom)\n  const currentImpliedFundingShutdown = useAtomValue(currentImpliedFundingShutdownAtom)\n  const { data: osqthPrice } = useOSQTHPrice()\n\n  const eth2Price = toTokenAmount(index, 18)\n  const ethPrice = eth2Price.sqrt()\n  const markPrice = toTokenAmount(mark, 18)\n  const impliedVolatilityShutdownPercent = impliedVolatilityShutdown * 100\n  const currentImpliedPremiumShutdown =\n    currentImpliedFundingShutdown === 0 ? 'loading' : formatNumber(currentImpliedFundingShutdown * 100) + '%'\n\n  const osqthPriceInETH = ethPrice.isZero() ? BIG_ZERO : osqthPrice.div(ethPrice)\n\n  return (\n    <Box display=\"flex\" alignItems=\"center\" flexWrap=\"wrap\" gridGap=\"12px\" {...props}>\n      <Metric\n        label={<MetricLabel label=\"ETH Price\" tooltipTitle={Tooltips.SpotPrice} />}\n        value={formatCurrency(ethPrice.toNumber())}\n      />\n\n      <Metric\n        label={<MetricLabel label=\"ETH&sup2; Price\" tooltipTitle={Tooltips.SpotPrice} />}\n        value={formatCurrency(eth2Price.toNumber())}\n      />\n\n      <Metric\n        label={<MetricLabel label=\"Mark Price\" tooltipTitle={`${Tooltips.Mark}. ${Tooltips.SpotPrice}`} />}\n        value={formatCurrency(markPrice.toNumber())}\n      />\n\n      <Metric\n        label={<MetricLabel label=\"oSQTH Price\" tooltipTitle={`${Tooltips.oSQTHPrice}. ${Tooltips.SpotPrice}`} />}\n        value={`${formatCurrency(osqthPrice.toNumber())}  (${formatNumber(osqthPriceInETH.toNumber(), 4)} ETH)`}\n      />\n\n      <Metric\n        label={<MetricLabel label=\"Implied Volatility \" tooltipTitle={Tooltips.ImplVol} />}\n        value={`${formatNumber(impliedVolatilityShutdownPercent)}%`}\n      />\n\n      <Metric\n        label={<MetricLabel label=\"Reference Volatility\" tooltipTitle={Tooltips.osqthRefVol} />}\n        value={`${formatNumber(osqthRefVol)}%`}\n      />\n\n      <Metric\n        label={<MetricLabel label=\"Current Implied Premium \" tooltipTitle={Tooltips.CurrentImplFunding} />}\n        value={currentImpliedPremiumShutdown}\n      />\n    </Box>\n  )\n}\n\nexport default SqueethInfo\n"
  },
  {
    "path": "packages/frontend/src/components/Lp/Stepper.tsx",
    "content": "import { IconButton, Typography } from '@material-ui/core'\nimport { createStyles, makeStyles, withStyles } from '@material-ui/core/styles'\nimport ArrowBackIcon from '@material-ui/icons/ArrowBack'\nimport ArrowForwardIcon from '@material-ui/icons/ArrowForward'\nimport React from 'react'\n\nimport { LPActions, useLPState } from '@context/lp'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n      marginTop: theme.spacing(3),\n    },\n    stepData: {\n      marginLeft: theme.spacing(1),\n      fontFamily: 'DM Mono',\n    },\n    stepButton: {\n      margin: theme.spacing(0, 0.5),\n      '&:disabled': {\n        background: theme.palette.background.lightStone,\n        opacity: '0.5',\n      },\n    },\n    disabled: {\n      backgroundColor: theme.palette.background.lightStone,\n      opacity: '1',\n    },\n  }),\n)\n\nconst StepperIconButton = withStyles((theme) => ({\n  root: {\n    background: theme.palette.background.stone,\n  },\n  disabled: {\n    background: theme.palette.background.stone,\n    opacity: '1',\n  },\n}))(IconButton)\n\nconst Stepper: React.FC = () => {\n  const classes = useStyles()\n  const { lpState, dispatch } = useLPState()\n\n  return (\n    <div className={classes.container}>\n      <StepperIconButton\n        id=\"lp-prev-step-btn\"\n        className={classes.stepButton}\n        disabled={!lpState.canGoBack}\n        classes={{ disabled: classes.disabled }}\n        onClick={() => dispatch({ type: LPActions.GO_BACK })}\n      >\n        <ArrowBackIcon />\n      </StepperIconButton>\n      <StepperIconButton\n        id=\"lp-next-step-btn\"\n        className={classes.stepButton}\n        disabled={!lpState.canGoForward}\n        classes={{ disabled: classes.disabled }}\n        onClick={() => dispatch({ type: LPActions.GO_FORWARD })}\n      >\n        <ArrowForwardIcon />\n      </StepperIconButton>\n      <Typography className={classes.stepData}>\n        0<span id=\"current-lp-step\">{lpState.step}</span> / 03\n      </Typography>{' '}\n    </div>\n  )\n}\n\nexport default Stepper\n"
  },
  {
    "path": "packages/frontend/src/components/MarkdownPage.tsx",
    "content": "import ReactMarkdown from 'markdown-to-jsx'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport Box from '@material-ui/core/Box'\nimport Link from '@material-ui/core/Link'\nimport Typography from '@material-ui/core/Typography'\n\nimport Nav from '@components/Nav'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      width: '90%',\n      margin: '7em auto 3em',\n      maxWidth: '900px',\n      paddingBottom: '1em',\n    },\n    subHeading: {\n      fontWeight: theme.typography.fontWeightBold,\n    },\n  }),\n)\n\nfunction MarkdownListItem(props: any) {\n  return <Box component=\"li\" sx={{ mt: 1, fontSize: 15 }} {...props} />\n}\n\nconst options = {\n  overrides: {\n    h1: {\n      component: Typography,\n      props: {\n        gutterBottom: true,\n        variant: 'h4',\n        component: 'h1',\n      },\n    },\n    h2: {\n      component: Typography,\n      props: { gutterBottom: true, component: 'h2' },\n    },\n    h3: {\n      component: Typography,\n      props: { gutterBottom: true, variant: 'h5', component: 'div' },\n    },\n    h4: {\n      component: Typography,\n      props: {\n        gutterBottom: true,\n        variant: 'h6',\n        paragraph: true,\n      },\n    },\n    h5: {\n      component: Typography,\n      props: {\n        gutterBottom: true,\n        // variant: 'h6',\n        paragraph: true,\n        fontSize: 10,\n        fontWeight: 600,\n      },\n    },\n    p: {\n      component: Typography,\n      props: { paragraph: true },\n    },\n    a: { component: Link },\n    li: {\n      component: MarkdownListItem,\n    },\n  },\n}\n\ninterface Props {\n  markdown: string\n}\n\nexport default function MarkdownPage({ markdown }: Props) {\n  const classes = useStyles()\n  return (\n    <>\n      <Nav />\n      <main>\n        <div className={classes.container}>\n          <ReactMarkdown options={options}>{markdown}</ReactMarkdown>\n        </div>\n      </main>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Metric.tsx",
    "content": "import React from 'react'\nimport { Typography, Box, BoxProps, Tooltip } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport clsx from 'clsx'\n\ninterface StyleProps {\n  isSmall: boolean\n}\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: (props: StyleProps): string => (props.isSmall ? '16px 16px' : '20px 24px'),\n      backgroundColor: theme.palette.background.stone,\n      borderRadius: '12px',\n    },\n    label: {\n      color: 'rgba(255, 255, 255, 0.5)',\n      fontSize: (props: StyleProps): string => (props.isSmall ? '14px' : '15px'),\n      fontWeight: 500,\n      width: 'max-content',\n    },\n    value: {\n      color: 'rgba(255, 255, 255)',\n      fontSize: (props: StyleProps): string => (props.isSmall ? '15px' : '18px'),\n      fontWeight: 500,\n      width: 'max-content',\n      fontFamily: 'DM Mono',\n    },\n    success: {\n      color: theme.palette.success.main,\n    },\n    error: {\n      color: theme.palette.error.main,\n    },\n  }),\n)\n\ninterface MetricProps {\n  label: string | React.ReactNode\n  value: string | React.ReactNode\n  textColor?: 'success' | 'error'\n  isSmall?: boolean\n}\n\nconst Metric: React.FC<MetricProps & BoxProps> = ({ label, value, isSmall = false, textColor, ...props }) => {\n  const classes = useStyles({ isSmall })\n\n  return (\n    <Box className={classes.container} flex=\"1\" display=\"flex\" flexDirection=\"column\" {...props}>\n      {typeof label === 'string' ? <Typography className={classes.label}>{label}</Typography> : label}\n      {typeof value === 'string' ? (\n        <Typography className={clsx(classes.value, textColor && classes[textColor])}>{value}</Typography>\n      ) : (\n        value\n      )}\n    </Box>\n  )\n}\n\nexport default Metric\n\nconst useLabelStyles = makeStyles((theme) =>\n  createStyles({\n    labelContainer: {\n      display: 'flex',\n      alignItems: 'center',\n      color: 'rgba(255, 255, 255, 0.5)',\n    },\n    label: {\n      fontSize: (props: StyleProps): string => (props.isSmall ? '14px' : '15px'),\n      fontWeight: 500,\n      width: 'max-content',\n    },\n    infoIcon: {\n      fontSize: (props: StyleProps): string => (props.isSmall ? '14px' : '15px'),\n      marginLeft: theme.spacing(0.5),\n    },\n  }),\n)\n\ninterface MetricLabelProps {\n  label: string\n  tooltipTitle?: string\n  isSmall?: boolean\n}\n\nexport const MetricLabel: React.FC<MetricLabelProps> = ({ label, tooltipTitle, isSmall = false }) => {\n  const classes = useLabelStyles({ isSmall })\n\n  return (\n    <div className={classes.labelContainer}>\n      <Typography className={classes.label}>{label}</Typography>\n      {tooltipTitle ? (\n        <Tooltip title={tooltipTitle}>\n          <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n        </Tooltip>\n      ) : null}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Modal/MobileModal.tsx",
    "content": "import { Drawer, IconButton, Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport KeyboardBackspaceIcon from '@material-ui/icons/KeyboardBackspace'\nimport React from 'react'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      width: '100%',\n      background: theme.palette.background.default,\n    },\n    paper: {\n      background: theme.palette.background.default,\n      height: '100vh',\n    },\n    nav: {\n      height: '64px',\n      position: 'fixed',\n      display: 'flex',\n      alignItems: 'center',\n      top: 0,\n      backdropFilter: 'blur(30px)',\n      zIndex: 30,\n      width: '100%',\n    },\n    title: {\n      marginLeft: theme.spacing(2),\n      fontSize: '18px',\n    },\n    body: {\n      padding: theme.spacing(2),\n      marginTop: '64px',\n    },\n  }),\n)\n\ntype MobileModalType = {\n  isOpen: boolean\n  onClose: () => void\n  title: string\n}\n\nconst MobileModal: React.FC<MobileModalType> = ({ isOpen, onClose, children, title }) => {\n  const classes = useStyles()\n\n  return (\n    <Drawer\n      anchor=\"bottom\"\n      open={isOpen}\n      onClose={onClose}\n      className={classes.container}\n      classes={{ paper: classes.paper }}\n    >\n      <div className={classes.nav}>\n        <IconButton onClick={onClose}>\n          <KeyboardBackspaceIcon />\n        </IconButton>\n        <Typography className={classes.title} variant=\"body1\" color=\"primary\">\n          {title}\n        </Typography>\n      </div>\n      <div className={classes.body}>{children}</div>\n    </Drawer>\n  )\n}\n\nexport default MobileModal\n"
  },
  {
    "path": "packages/frontend/src/components/Modal/Modal.tsx",
    "content": "import { createStyles, IconButton, makeStyles } from '@material-ui/core'\nimport Dialog from '@material-ui/core/Dialog'\nimport DialogContent from '@material-ui/core/DialogContent'\nimport DialogTitle from '@material-ui/core/DialogTitle'\nimport CloseIcon from '@material-ui/icons/Close'\nimport * as React from 'react'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    dialogTitle: {\n      // color: '#000',\n      background: theme.palette.background.default,\n      padding: '15px 20px 0',\n      '&>*': {\n        display: 'flex',\n        justifyContent: 'space-between',\n        alignItems: 'center',\n        gap: '20px',\n      },\n      fontSize: '1.75rem',\n    },\n    dialogContent: {\n      padding: '10px 20px 25px',\n      background: theme.palette.background.default,\n      display: 'flex',\n      flexDirection: 'column',\n      alignItems: 'center',\n      gap: '10px',\n    },\n  }),\n)\nexport interface ModalProps {\n  title: string\n  open: boolean\n  handleClose?: () => void\n}\n\nexport const Modal: React.FC<ModalProps> = ({ open, handleClose, title, children }) => {\n  const classes = useStyles()\n\n  return (\n    <Dialog\n      PaperProps={{\n        style: { borderRadius: 20, maxWidth: 600 },\n      }}\n      BackdropProps={{\n        style: { backdropFilter: 'blur(20px)' },\n      }}\n      maxWidth={'lg'}\n      open={open}\n      onClose={handleClose}\n      aria-labelledby=\"alert-dialog-title\"\n      aria-describedby=\"alert-dialog-description\"\n      style={{ maxWidth: '500' }}\n    >\n      <DialogTitle className={classes.dialogTitle} id=\"alert-dialog-title\">\n        {title}\n        {handleClose && (\n          <IconButton edge=\"start\" onClick={handleClose} aria-label=\"close\">\n            <CloseIcon style={{ color: '#fff' }} />\n          </IconButton>\n        )}\n      </DialogTitle>\n      <DialogContent className={classes.dialogContent}>{children}</DialogContent>\n    </Dialog>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Modal/UniswapIframe.tsx",
    "content": "import { createStyles, IconButton, makeStyles, Tooltip } from '@material-ui/core'\nimport Button from '@material-ui/core/Button'\nimport { orange } from '@material-ui/core/colors'\nimport Dialog from '@material-ui/core/Dialog'\nimport DialogContent from '@material-ui/core/DialogContent'\nimport DialogTitle from '@material-ui/core/DialogTitle'\nimport CloseIcon from '@material-ui/icons/Close'\nimport OpenInNewIcon from '@material-ui/icons/OpenInNew'\nimport * as React from 'react'\n\nimport { Tooltips, UniswapIFrameOpen, UniswapIFrameClose } from '@constants/enums'\nimport useCopyClipboard from '@hooks/useCopyClipboard'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\nimport { useAtomValue } from 'jotai'\nimport { addressesAtom } from 'src/state/positions/atoms'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    dialog: {\n      textAlign: 'center',\n    },\n    dialogTitle: {\n      // color: '#000',\n      background: theme.palette.background.default,\n      paddingTop: '0px',\n      paddingBottom: '0px',\n      '&>*': {\n        display: 'flex',\n        justifyContent: 'space-between',\n        alignItems: 'center',\n      },\n    },\n    dialogContent: {\n      padding: '0 20px',\n      background: theme.palette.background.default,\n    },\n    iframeBox: {\n      width: '800px',\n      height: '80vh',\n      border: 0,\n      borderRadius: '30px',\n      margin: '0 auto 20px',\n      display: 'block',\n      zIndex: 1,\n    },\n    uniswapWarning: {\n      color: orange[700],\n      fontWeight: 600,\n      fontSize: 15,\n    },\n    uniswapHeaderDiv: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      paddingRight: '20px',\n      paddingLeft: '5px',\n    },\n    uniOpenBtn: {\n      display: 'flex',\n      alignItems: 'center',\n      color: theme.palette.primary.main,\n    },\n    btn: {\n      margin: '20px 0',\n      textTransform: 'none',\n      textAlign: 'center',\n      color: '#000',\n      cursor: 'pointer',\n      backgroundColor: theme.palette.primary.main,\n      '&:hover': {\n        backgroundColor: theme.palette.primary.dark,\n      },\n    },\n  }),\n)\ninterface UniswapIframeProps {\n  text?: string\n  closePosition?: boolean\n}\n\nexport const UniswapIframe: React.FC<UniswapIframeProps> = ({ text, closePosition }) => {\n  const classes = useStyles()\n  const { oSqueeth } = useAtomValue(addressesAtom)\n\n  const networkId = useAtomValue(networkIdAtom)\n  const [isCopied, setCopied] = useCopyClipboard()\n\n  const [open, setOpen] = React.useState(false)\n\n  const handleClickOpen = () => {\n    setOpen(true)\n  }\n\n  const handleClose = () => {\n    setOpen(false)\n  }\n\n  return (\n    <div>\n      <Tooltip title={Tooltips.UniswapLoading}>\n        <Button className={classes.btn} variant={'outlined'} onClick={handleClickOpen}>\n          <>{text}</>\n        </Button>\n      </Tooltip>\n\n      <Dialog\n        PaperProps={{\n          style: { borderRadius: 20 },\n        }}\n        BackdropProps={{\n          style: { backdropFilter: 'blur(20px)' },\n        }}\n        maxWidth={'lg'}\n        open={open}\n        onClose={handleClose}\n        aria-labelledby=\"alert-dialog-title\"\n        aria-describedby=\"alert-dialog-description\"\n      >\n        <DialogTitle className={classes.dialogTitle} id=\"alert-dialog-title\">\n          <p>Deposit Squeeth and ETH into Uniswap V3 Pool 🦄</p>\n          <Button\n            variant=\"outlined\"\n            color=\"primary\"\n            onClick={() => {\n              setCopied(oSqueeth)\n            }}\n          >\n            {' '}\n            {isCopied ? (\n              <>Copied</>\n            ) : (\n              <>\n                oSQTH: {oSqueeth?.substring(0, 6)}...{oSqueeth?.substring(oSqueeth.length - 4)}\n              </>\n            )}\n          </Button>\n          <IconButton edge=\"start\" onClick={handleClose} aria-label=\"close\">\n            <CloseIcon style={{ color: '#fff' }} />\n          </IconButton>\n        </DialogTitle>\n        <DialogContent className={classes.dialogContent}>\n          <div className={classes.uniswapHeaderDiv}>\n            <p className={classes.uniswapWarning}>Make sure your wallet is connected to Uniswap</p>\n            <a\n              className={classes.uniOpenBtn}\n              href={closePosition ? UniswapIFrameClose[networkId] : UniswapIFrameOpen[networkId]}\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              <p>Open in Uniswap</p>\n              <OpenInNewIcon style={{ fontSize: 16, marginLeft: '4px' }} fontSize=\"small\" />\n            </a>\n          </div>\n          <iframe\n            className={classes.iframeBox}\n            src={closePosition ? UniswapIFrameClose[networkId] : UniswapIFrameOpen[networkId]}\n          ></iframe>\n        </DialogContent>\n      </Dialog>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Nav.tsx",
    "content": "import { Button, Drawer, IconButton, Menu, MenuItem, ButtonBase } from '@material-ui/core'\nimport Hidden from '@material-ui/core/Hidden'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport Typography from '@material-ui/core/Typography'\nimport { darken, Box } from '@material-ui/core/'\nimport { Modal } from './Modal/Modal'\nimport MenuIcon from '@material-ui/icons/Menu'\nimport Image from 'next/image'\nimport Link from 'next/link'\nimport { Link as MUILink } from '@material-ui/core'\nimport { useRouter } from 'next/router'\nimport React, { useEffect, useState } from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport useCopyClipboard from '@hooks/useCopyClipboard'\nimport { useWalletBalance } from '@state/wallet/hooks'\nimport { addressesAtom } from '@state/positions/atoms'\nimport { toTokenAmount } from '@utils/calculations'\nimport { truncateText } from '@utils/formatter'\nimport { BIG_ZERO } from '@constants/index'\nimport logo from 'public/images/OpynLogo.svg'\nimport WalletButton from './Button/WalletButton'\nimport SettingMenu from './SettingsMenu'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { SITE_EVENTS } from '@utils/amplitude'\nimport { ShutdownAlert } from './Alerts/ShutdownAlert'\n\nconst ukLegalPayload =\n  'UK Disclaimer: This web application is provided as a tool for users to interact with the Squeeth Protocol on their own initiative, with no endorsement or recommendation of crypto asset trading activities. In doing so, Opyn is not recommending that users or potential users engage in crypto asset trading activity, and users or potential users of the web application should not regard this webpage or its contents as involving any form of recommendation, invitation, or inducement to deal in crypto assets.'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    root: {\n      borderBottom: `1px solid ${theme.palette.background.stone}`,\n      position: 'sticky',\n      top: '0px',\n      backdropFilter: 'blur(30px)',\n      zIndex: theme.zIndex.appBar,\n    },\n    banner: {\n      padding: '20px',\n      boxSizing: 'border-box',\n      [theme.breakpoints.down('sm')]: {\n        padding: '10px',\n      },\n    },\n    bannerContent: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n      [theme.breakpoints.down('sm')]: {\n        flexDirection: 'column',\n        alignItems: 'flex-start',\n      },\n    },\n    bannerText: {\n      fontSize: '15px',\n      fontWeight: 500,\n      [theme.breakpoints.up('md')]: {\n        whiteSpace: 'nowrap',\n        overflow: 'hidden',\n        textOverflow: 'ellipsis',\n        maxWidth: 'calc(100% - 80px)',\n      },\n    },\n    bannerDivider: {\n      borderBottom: `1px solid ${theme.palette.divider}`,\n      width: '100%',\n    },\n    readMoreButton: {\n      fontSize: '15px',\n      background: 'none',\n      border: 'none',\n      color: theme.palette.primary.main,\n      padding: 0,\n      font: 'inherit',\n      cursor: 'pointer',\n      outline: 'inherit',\n      marginLeft: '5px',\n      '&:hover': {\n        color: darken(theme.palette.primary.main, 0.2),\n      },\n    },\n    content: {\n      maxWidth: '1280px',\n      width: '80%',\n      padding: theme.spacing(0, 2.5),\n      margin: '0 auto',\n      height: '64px',\n      display: 'flex',\n      alignItems: 'center',\n      [theme.breakpoints.down('lg')]: {\n        maxWidth: 'none',\n        width: '90%',\n      },\n      [theme.breakpoints.down('md')]: {\n        width: '100%',\n      },\n      [theme.breakpoints.down('sm')]: {\n        padding: theme.spacing(0, 2),\n      },\n      [theme.breakpoints.down('xs')]: {\n        padding: theme.spacing(0, 1),\n      },\n    },\n    logo: {\n      marginRight: 'auto',\n      marginTop: theme.spacing(1.75),\n      marginLeft: theme.spacing(-1),\n      cursor: 'pointer',\n    },\n    navDiv: {\n      display: 'flex',\n      alignItems: 'center',\n      position: 'absolute',\n      marginLeft: theme.spacing(12),\n      [theme.breakpoints.down(1042)]: {\n        marginLeft: theme.spacing(18),\n      },\n    },\n    navLink: {\n      margin: theme.spacing(0, 2),\n      textDecoration: 'none',\n      cursor: 'pointer',\n      color: theme.palette.text.secondary,\n      fontWeight: 400,\n      letterSpacing: '-0.02em',\n      [theme.breakpoints.down('md')]: {\n        margin: theme.spacing(1, 1.5, 1),\n      },\n      [theme.breakpoints.down(1042)]: {\n        margin: theme.spacing(1, 1, 1),\n      },\n      [theme.breakpoints.down('sm')]: {\n        margin: theme.spacing(1, 0),\n      },\n    },\n    navActive: {\n      color: theme.palette.primary.main,\n    },\n    wallet: {\n      display: 'flex',\n      marginRight: theme.spacing(2),\n    },\n    navDrawer: {\n      padding: theme.spacing(2, 4),\n      '& > *': {\n        marginBottom: theme.spacing(1),\n      },\n    },\n  }),\n)\n\nexport const NavLink: React.FC<{ path: string; name: string; highlightForPaths?: string[] }> = ({\n  path,\n  name,\n  highlightForPaths,\n}) => {\n  const classes = useStyles()\n  const router = useRouter()\n\n  return (\n    <Typography\n      className={\n        router.pathname === path || highlightForPaths?.includes(router.pathname)\n          ? `${classes.navLink} ${classes.navActive}`\n          : classes.navLink\n      }\n      variant=\"h6\"\n    >\n      <Link href={path}>{name}</Link>\n    </Typography>\n  )\n}\n\nconst Nav: React.FC = () => {\n  const classes = useStyles()\n  const router = useRouter()\n  const userLocation = router.query?.ct\n  const { data: balance } = useWalletBalance()\n\n  const { oSqueeth } = useAtomValue(addressesAtom)\n  const [navOpen, setNavOpen] = useState(false)\n  const [isCopied, setCopied] = useCopyClipboard()\n  const { track } = useAmplitude()\n\n  const [anchorEl, setAnchorEl] = React.useState(null)\n  const [showBanner, setShowBanner] = useState(false)\n  const [modalOpen, setModalOpen] = useState(false)\n  const handleModalToggle = () => {\n    setModalOpen(!modalOpen)\n  }\n  const handleClick = (event: any) => {\n    setAnchorEl(event.currentTarget)\n  }\n  const handleClose = () => {\n    setAnchorEl(null)\n  }\n\n  useEffect(() => {\n    if (userLocation === 'GB') {\n      // 'GB' is the country code for the United Kingdom\n      setShowBanner(true)\n    } else {\n      setShowBanner(false)\n    }\n  }, [userLocation])\n\n  return (\n    <>\n      <div className={classes.root}>\n        {showBanner && (\n          <>\n            <div className={classes.banner}>\n              <div className={classes.bannerContent}>\n                <Typography className={classes.bannerText}>{truncateText(ukLegalPayload, 150)}</Typography>\n                <button className={classes.readMoreButton} onClick={handleModalToggle}>\n                  Read more\n                </button>\n              </div>\n            </div>\n            <div className={classes.bannerDivider}></div>\n          </>\n        )}\n        <div className={classes.content}>\n          <div className={classes.logo}>\n            <Link href={'/'} passHref>\n              <Image src={logo} alt=\"logo\" width={102} height={44} />\n            </Link>\n          </div>\n          {/*For Desktop view*/}\n          <Hidden smDown>\n            <div className={classes.navDiv}>\n              <div style={{ display: 'flex' }}>\n                <NavLink\n                  highlightForPaths={['/strategies/crab', '/strategies/bull']}\n                  path=\"/strategies/crab\"\n                  name=\"Strategies\"\n                />\n                <NavLink path=\"/squeeth\" name=\"Squeeth\" />\n                <NavLink path=\"/positions\" name=\"Positions\" />\n                <a\n                  href=\"https://squeethportal.xyz\"\n                  target=\"_blank\"\n                  rel=\"noreferrer\"\n                  onClick={() => track(SITE_EVENTS.NAV_AUCTION)}\n                >\n                  <Typography className={classes.navLink} variant=\"h6\">\n                    Auction\n                  </Typography>\n                </a>\n                <NavLink path=\"/lp\" name=\"LP\" />\n                <ButtonBase aria-controls=\"docs-menu\" aria-haspopup=\"true\" onClick={handleClick} className=\"\">\n                  <Typography className={classes.navLink} variant=\"h6\">\n                    Docs\n                  </Typography>\n                </ButtonBase>\n                <Menu id=\"docs-menu\" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleClose}>\n                  <MenuItem onClick={handleClose}>\n                    <a href=\"https://research.opyn.co\" onClick={() => track(SITE_EVENTS.NAV_RESEARCH)}>\n                      Research\n                    </a>\n                  </MenuItem>\n                  <MenuItem onClick={handleClose}>\n                    <a\n                      href=\"https://opyn.gitbook.io/opyn-hub\"\n                      target=\"_blank\"\n                      rel=\"noreferrer\"\n                      onClick={() => track(SITE_EVENTS.NAV_FAQ)}\n                    >\n                      FAQ\n                    </a>\n                  </MenuItem>\n                </Menu>\n              </div>\n            </div>\n            <div className={classes.wallet}>\n              <Hidden mdDown>\n                <Button\n                  variant=\"outlined\"\n                  color=\"primary\"\n                  onClick={() => {\n                    setCopied(oSqueeth)\n                  }}\n                >\n                  {isCopied ? (\n                    <>Copied</>\n                  ) : (\n                    <>\n                      <span style={{ textTransform: 'none' }}>oSQTH</span>: {oSqueeth?.substring(0, 6)}...\n                      {oSqueeth?.substring(oSqueeth.length - 4)}\n                    </>\n                  )}\n                </Button>\n              </Hidden>\n              <WalletButton />\n              <SettingMenu />\n            </div>\n          </Hidden>\n          <Hidden mdUp>\n            <Typography color=\"primary\">{toTokenAmount(balance ?? BIG_ZERO, 18).toFixed(4)} ETH</Typography>\n            <IconButton onClick={() => setNavOpen(true)}>\n              <MenuIcon />\n            </IconButton>\n            <Drawer anchor=\"right\" open={navOpen} onClose={() => setNavOpen(false)}>\n              <div className={classes.navDrawer}>\n                <div style={{ display: 'flex', justifyContent: 'flex-start' }}>\n                  <WalletButton />\n                  <SettingMenu />\n                </div>\n                <Button\n                  variant=\"outlined\"\n                  color=\"primary\"\n                  onClick={() => {\n                    setCopied(oSqueeth)\n                  }}\n                  style={{\n                    marginTop: '8px',\n                    width: '200px',\n                  }}\n                >\n                  {isCopied ? (\n                    <>Copied</>\n                  ) : (\n                    <>\n                      <span style={{ textTransform: 'none' }}>oSQTH</span>: {oSqueeth?.substring(0, 6)}...\n                      {oSqueeth?.substring(oSqueeth.length - 4)}\n                    </>\n                  )}\n                </Button>\n                <NavLink\n                  highlightForPaths={['/strategies/crab', '/strategies/bull']}\n                  path=\"/strategies/crab\"\n                  name=\"Strategies\"\n                />\n                <NavLink path=\"/squeeth\" name=\"Squeeth\" />\n                <NavLink path=\"/positions\" name=\"Positions\" />\n                <a\n                  href=\"https://squeethportal.xyz\"\n                  target=\"_blank\"\n                  rel=\"noreferrer\"\n                  onClick={() => track(SITE_EVENTS.NAV_AUCTION)}\n                >\n                  <Typography className={classes.navLink} variant=\"h6\">\n                    Auction\n                  </Typography>\n                </a>\n                <NavLink path=\"/lp\" name=\"LP\" />\n                <a href=\"https://research.opyn.co\" onClick={() => track(SITE_EVENTS.NAV_RESEARCH)}>\n                  <Typography className={classes.navLink} variant=\"h6\">\n                    Research\n                  </Typography>\n                </a>\n                <a\n                  href=\"https://opyn.gitbook.io/opyn-hub\"\n                  target=\"_blank\"\n                  rel=\"noreferrer\"\n                  onClick={() => track(SITE_EVENTS.NAV_FAQ)}\n                >\n                  <Typography className={classes.navLink} variant=\"h6\">\n                    FAQ\n                  </Typography>\n                </a>\n              </div>\n            </Drawer>\n          </Hidden>\n        </div>\n      </div>\n\n      <ShutdownAlert />\n      <Modal\n        open={modalOpen}\n        handleClose={handleModalToggle}\n        aria-labelledby=\"legal-modal-title\"\n        aria-describedby=\"legal-modal-description\"\n        title=\"Disclaimer for UK Residents\"\n      >\n        <Box px=\"4px\">\n          {ukLegalPayload}\n          <br />\n          <br />\n          Please review our{' '}\n          <MUILink href=\"https://opyn.co/terms-of-service\" target=\"_blank\">\n            Terms of Service\n          </MUILink>{' '}\n          for more details.\n        </Box>\n      </Modal>\n    </>\n  )\n}\n\nexport default Nav\n"
  },
  {
    "path": "packages/frontend/src/components/PnLTooltip.tsx",
    "content": "import { Tooltips } from '@constants/enums'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport Tooltip from '@material-ui/core/Tooltip'\nimport HelpOutline from '@material-ui/icons/HelpOutline'\nimport { PnLType } from '../types/index'\nimport { LinkWrapper } from './LinkWrapper'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    infoIcon: {\n      fontSize: '16px',\n      marginLeft: theme.spacing(0.5),\n    },\n  }),\n)\n\ninterface PnLTooltipProps {\n  pnlType: PnLType\n}\n\nexport const PnLTooltip: React.FC<PnLTooltipProps> = ({ pnlType }) => {\n  const classes = useStyles()\n  const pnlText = pnlType === PnLType.Unrealized ? Tooltips.UnrealizedPnL : Tooltips.RealizedPnL\n  return (\n    <Tooltip\n      interactive\n      title={\n        <>\n          {pnlText} <br />\n          <br /> {Tooltips.PnLExplanation}\n          <br />\n          <LinkWrapper href=\"https://twitter.com/wadepros/status/1507008456766595081?s=20&t=BwhOBHz5azrdn0KsAb8TSA\">\n            Learn more\n          </LinkWrapper>\n        </>\n      }\n    >\n      <HelpOutline fontSize=\"small\" className={classes.infoIcon} />\n    </Tooltip>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Popup.tsx",
    "content": "import Button from '@material-ui/core/Button'\nimport Dialog from '@material-ui/core/Dialog'\nimport DialogActions from '@material-ui/core/DialogActions'\nimport DialogContent from '@material-ui/core/DialogContent'\nimport DialogContentText from '@material-ui/core/DialogContentText'\nimport DialogTitle from '@material-ui/core/DialogTitle'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React from 'react'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      width: '100%',\n      background: theme.palette.background.default,\n    },\n    paper: {\n      background: theme.palette.background.default,\n      height: '100vh',\n    },\n    nav: {\n      height: '64px',\n      position: 'fixed',\n      display: 'flex',\n      alignItems: 'center',\n      top: 0,\n      backdropFilter: 'blur(30px)',\n      zIndex: 30,\n      width: '100%',\n    },\n    title: {\n      marginLeft: theme.spacing(2),\n      fontSize: '18px',\n    },\n    body: {\n      padding: theme.spacing(2),\n      marginTop: '64px',\n    },\n  }),\n)\n\ntype PopupType = {\n  dialogTitle: string\n  dialogContent: string\n  isOpen: boolean\n  onClose: () => void\n  title: string\n}\n\nexport const Popup: React.FC<PopupType> = ({ isOpen, onClose, dialogTitle, dialogContent, children, title }) => {\n  const classes = useStyles()\n\n  return (\n    <Dialog\n      open={isOpen}\n      onClose={onClose}\n      aria-labelledby=\"alert-dialog-title\"\n      aria-describedby=\"alert-dialog-description\"\n    >\n      <DialogTitle id=\"alert-dialog-title\">{dialogTitle}</DialogTitle>\n      <DialogContent>\n        <DialogContentText id=\"alert-dialog-description\">{dialogContent}</DialogContentText>\n      </DialogContent>\n      <DialogActions>\n        <Button onClick={onClose} color=\"primary\" autoFocus>\n          Got it\n        </Button>\n      </DialogActions>\n    </Dialog>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/PositionCard.tsx",
    "content": "import { Typography, Box } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport ArrowRightAltIcon from '@material-ui/icons/ArrowRightAlt'\nimport BigNumber from 'bignumber.js'\nimport clsx from 'clsx'\nimport Link from 'next/link'\nimport React, { memo, useState } from 'react'\nimport { useAtom, useAtomValue } from 'jotai'\n\nimport { PositionType, TradeType } from '../types'\nimport { useVaultLiquidations } from '@hooks/contracts/useLiquidations'\nimport { usePrevious } from 'react-use'\nimport {\n  useComputeSwaps,\n  useFirstValidVault,\n  useLongRealizedPnl,\n  useLPPositionsQuery,\n  useShortRealizedPnl,\n  useSwaps,\n} from 'src/state/positions/hooks'\nimport { isLPAtom, positionTypeAtom, swapsAtom, isToHidePnLAtom } from 'src/state/positions/atoms'\nimport {\n  actualTradeTypeAtom,\n  isOpenPositionAtom,\n  sqthTradeAmountAtom,\n  tradeCompletedAtom,\n  tradeSuccessAtom,\n  tradeTypeAtom,\n} from 'src/state/trade/atoms'\nimport { useCurrentLongPositionValue, useCurrentShortPositionValue } from 'src/state/pnl/hooks'\nimport { loadingAtom } from 'src/state/pnl/atoms'\nimport { useVaultData } from '@hooks/useVaultData'\nimport useAppEffect from '@hooks/useAppEffect'\nimport useAppCallback from '@hooks/useAppCallback'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { HidePnLText } from './HidePnLText'\nimport Metric from '@components/Metric'\nimport {\n  getSqueethPriceShutdown,\n  getSqueethImpliedVolatilityShutdown,\n  getDaysToShutdown,\n  getCurrentImpliedFundingShutdown,\n  getDailyHistoricalFunding,\n} from '@state/controller/utils'\nimport {\n  currentImpliedFundingAtom,\n  currentImpliedFundingShutdownAtom,\n  dailyHistoricalFundingShutdownAtom,\n  impliedVolatilityShutdownAtom,\n  impliedVolAtom,\n  normFactorAtom,\n} from '@state/controller/atoms'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(2),\n      marginTop: '16px',\n      width: '420px',\n      alignSelf: 'flex-start',\n      background: theme.palette.background.stone,\n      borderRadius: theme.spacing(1),\n      display: 'flex',\n      flexDirection: 'column',\n      [theme.breakpoints.down('sm')]: {\n        width: '100%',\n      },\n      fontWeight: 700,\n    },\n    header: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'space-between',\n      marginBottom: '5px',\n    },\n    posTypeChange: {\n      display: 'flex',\n      alignItems: 'center',\n      gap: '6px',\n    },\n    title: {\n      padding: theme.spacing(0.8, 1.5),\n      fontSize: '15px',\n      fontWeight: 500,\n      borderRadius: theme.spacing(1),\n      // marginLeft: theme.spacing(2),\n    },\n    subtitle: {\n      fontSize: '20px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n    },\n    positionTitle: {\n      color: (props: any): any =>\n        props.positionType === PositionType.LONG\n          ? theme.palette.success.main\n          : props.positionType === PositionType.SHORT\n          ? theme.palette.error.main\n          : 'inherit',\n      backgroundColor: (props: any): any =>\n        props.positionType === PositionType.LONG\n          ? `${theme.palette.success.main}20`\n          : props.positionType === PositionType.SHORT\n          ? `${theme.palette.error.main}20`\n          : '#DCDAE920',\n    },\n\n    postpositionTitle: {\n      color: (props: any): any =>\n        props.postPosition === PositionType.LONG\n          ? theme.palette.success.main\n          : props.postPosition === PositionType.SHORT && theme.palette.error.main,\n      backgroundColor: (props: any): any =>\n        props.postPosition === PositionType.LONG\n          ? `${theme.palette.success.main}20`\n          : props.postPosition === PositionType.SHORT\n          ? `${theme.palette.error.main}20`\n          : '#DCDAE920',\n    },\n    redPosition: {\n      color: theme.palette.error.main,\n      backgroundColor: `${theme.palette.error.main}20`,\n    },\n    posBg: {\n      background: (props: any): any => {\n        const positionColor =\n          props.positionType === PositionType.LONG\n            ? '#375F4290'\n            : props.positionType === PositionType.SHORT\n            ? '#68373D40'\n            : theme.palette.background.stone\n        const postColor =\n          props.postPosition === PositionType.LONG\n            ? '#375F42'\n            : props.postPosition === PositionType.SHORT\n            ? '#68373D90'\n            : theme.palette.background.stone\n        return `linear-gradient(to right, ${positionColor} 0%,${postColor} 75%)`\n      },\n    },\n    assetDiv: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      flexWrap: 'wrap',\n      marginTop: '16px',\n    },\n    red: {\n      color: theme.palette.error.main,\n    },\n    green: {\n      color: theme.palette.success.main,\n    },\n    grey: {\n      color: theme.palette.text.secondary,\n    },\n    floatingContainer: {\n      position: 'fixed',\n      bottom: '30px',\n      left: theme.spacing(4),\n      background: theme.palette.background.lightStone,\n      padding: theme.spacing(1, 2),\n      width: '200px',\n      borderRadius: theme.spacing(1),\n      backdropFilter: 'blur(50px)',\n      zIndex: 10,\n    },\n    pnl: {\n      display: 'flex',\n      alignItems: 'baseline',\n    },\n    postTrade: {\n      display: 'flex',\n      justifyContent: 'center',\n    },\n    postAmount: {\n      display: 'flex',\n      alignItems: 'center',\n      gap: '6px',\n    },\n    arrow: {\n      color: theme.palette.grey[600],\n    },\n    link: {\n      color: theme.palette.primary.main,\n      fontWeight: 500,\n      fontSize: 14,\n    },\n    pnlTitle: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    amountText: {\n      fontFamily: 'DM Mono',\n      fontSize: '22px',\n      fontWeight: 500,\n      lineHeight: '1em',\n    },\n    amountUnit: {\n      fontSize: '20px',\n    },\n    positionUsdValue: {\n      color: 'rgba(255, 255, 255, 0.6)',\n      marginLeft: '12px',\n    },\n    labelContainer: {\n      display: 'flex',\n      justifyContent: 'space-between',\n    },\n    label: {\n      color: 'rgba(255, 255, 255, 0.5)',\n      fontSize: '15px',\n      fontWeight: 500,\n      width: 'max-content',\n    },\n  }),\n)\n\nconst pnlClass = (positionType: string, long: number | BigNumber, short: number | BigNumber, classes: any) => {\n  if (positionType === PositionType.LONG) return Number(long?.toFixed(2)) > 0 ? classes.green : classes.red\n  if (positionType === PositionType.SHORT) return Number(short?.toFixed(2)) > 0 ? classes.green : classes.red\n\n  return ''\n}\n\nconst PositionCard: React.FC = () => {\n  // const shortGain = useShortGain()\n  // const longGain = useLongGain()\n  // const longUnrealizedPNL = useLongUnrealizedPNL()\n  // const shortUnrealizedPNL = useShortUnrealizedPNL()\n  const longPositionValue = useCurrentLongPositionValue()\n  const shortPositionValue = useCurrentShortPositionValue()\n  const loading = useAtomValue(loadingAtom)\n  const isToHidePnL = useAtomValue(isToHidePnLAtom)\n\n  const positionType = useAtomValue(positionTypeAtom)\n  const { startPolling, stopPolling } = useSwaps()\n  const swapsData = useAtomValue(swapsAtom)\n  const swaps = swapsData.swaps\n  const { squeethAmount } = useComputeSwaps()\n  const { validVault: vault, vaultId } = useFirstValidVault()\n  const { existingCollat } = useVaultData(vault)\n  const { loading: isPositionLoading } = useLPPositionsQuery()\n  const isLP = useAtomValue(isLPAtom)\n  const isOpenPosition = useAtomValue(isOpenPositionAtom)\n  const [tradeSuccess, setTradeSuccess] = useAtom(tradeSuccessAtom)\n  const [tradeCompleted, setTradeCompleted] = useAtom(tradeCompletedAtom)\n\n  const longRealizedPNL = useLongRealizedPnl()\n  const shortRealizedPNL = useShortRealizedPnl()\n  const { liquidations } = useVaultLiquidations(Number(vaultId))\n  const actualTradeType = useAtomValue(actualTradeTypeAtom)\n  const tradeAmountInput = useAtomValue(sqthTradeAmountAtom)\n  const tradeType = useAtomValue(tradeTypeAtom)\n  const prevSwapsData = usePrevious(swaps)\n  const tradeAmount = useAppMemo(() => new BigNumber(tradeAmountInput), [tradeAmountInput])\n  const [fetchingNew, setFetchingNew] = useState(false)\n  const [postTradeAmt, setPostTradeAmt] = useState(new BigNumber(0))\n  const [postPosition, setPostPosition] = useState(PositionType.NONE)\n  const classes = useStyles({ positionType, postPosition })\n\n  useAppEffect(() => {\n    if (tradeSuccess && prevSwapsData?.length === swaps?.length) {\n      //if trade success and number of swaps is still the same, start swaps polling\n      startPolling(500)\n      setFetchingNew(true)\n    } else {\n      setTradeCompleted(false)\n      setTradeSuccess(false)\n      stopPolling()\n      setFetchingNew(false)\n    }\n  }, [swaps, prevSwapsData, tradeSuccess, setTradeCompleted, startPolling, stopPolling, setTradeSuccess])\n\n  const fullyLiquidated = useAppMemo(() => {\n    return Boolean(vault && vault.shortAmount.isZero() && liquidations.length > 0)\n  }, [vault, liquidations])\n\n  const isDollarValueLoading = useAppMemo(() => {\n    if (positionType === PositionType.LONG || positionType === PositionType.SHORT) {\n      return loading\n    } else {\n      return null\n    }\n  }, [positionType, loading])\n\n  const getPositionBasedValue = useAppCallback(\n    (long: any, short: any, none: any, loadingMsg?: any) => {\n      if (loadingMsg && loading) return loadingMsg\n      if (positionType === PositionType.LONG) {\n        return long\n      }\n      if (positionType === PositionType.SHORT) {\n        return short\n      }\n      return none\n    },\n    [loading, positionType],\n  )\n\n  const getRealizedPNLBasedValue = useAppCallback(\n    (long: any, short: any, none: any, loadingMsg?: any) => {\n      if (isToHidePnL) return none\n      if (loadingMsg && loading) return loadingMsg\n      if (longRealizedPNL.isEqualTo(0) && shortRealizedPNL.isEqualTo(0)) return none\n      if (positionType === PositionType.LONG) return long\n      if (positionType === PositionType.SHORT) return short\n      return none\n    },\n    [isToHidePnL, positionType, loading, longRealizedPNL, shortRealizedPNL],\n  )\n\n  useAppEffect(() => {\n    if (isPositionLoading) return\n\n    let _postTradeAmt = new BigNumber(0)\n    let _postPosition = PositionType.NONE\n    if (actualTradeType === TradeType.LONG && positionType !== PositionType.SHORT) {\n      if (isOpenPosition) {\n        _postTradeAmt = squeethAmount.plus(tradeAmount)\n      } else {\n        _postTradeAmt = squeethAmount.minus(tradeAmount)\n      }\n      if (_postTradeAmt.gt(0)) _postPosition = PositionType.LONG\n    } else if (actualTradeType === TradeType.SHORT && positionType !== PositionType.LONG) {\n      if (isOpenPosition) {\n        _postTradeAmt = squeethAmount.isGreaterThan(0) ? squeethAmount.plus(tradeAmount) : tradeAmount\n      } else {\n        _postTradeAmt = squeethAmount.isGreaterThan(0) ? squeethAmount.minus(tradeAmount) : new BigNumber(0)\n      }\n      if (_postTradeAmt.gt(0)) {\n        _postPosition = PositionType.SHORT\n      }\n    }\n\n    setPostTradeAmt(_postTradeAmt)\n    setPostPosition(_postPosition)\n  }, [actualTradeType, isOpenPosition, isPositionLoading, positionType, squeethAmount, tradeAmount])\n\n  // const pnlLoading = useAppMemo(() => {\n  //   if (positionType === PositionType.LONG) {\n  //     return longUnrealizedPNL.loading\n  //   }\n  //   if (positionType === PositionType.SHORT) {\n  //     return shortUnrealizedPNL.loading\n  //   }\n  // }, [longUnrealizedPNL.loading, positionType, shortUnrealizedPNL.loading])\n\n  return (\n    <div>\n      <Box display=\"flex\" alignItems=\"center\" gridGap=\"24px\">\n        <Typography variant=\"h4\" className={classes.subtitle}>\n          My Position\n        </Typography>\n\n        {fullyLiquidated ? (\n          <span className={clsx(classes.title, classes.redPosition)}>Fully Liquidated</span>\n        ) : (\n          <div className={classes.posTypeChange}>\n            <span className={clsx(classes.title, classes.positionTitle)}>{positionType}</span>\n\n            {postPosition === positionType ||\n            (tradeType === TradeType.LONG && positionType === PositionType.SHORT) ||\n            (tradeType === TradeType.SHORT && positionType === PositionType.LONG) ? null : (\n              <>\n                <ArrowRightAltIcon className={classes.arrow} />\n                <span className={clsx(classes.title, classes.postpositionTitle)}>{postPosition}</span>\n              </>\n            )}\n          </div>\n        )}\n      </Box>\n      <div>\n        {fullyLiquidated ? (\n          <Box display=\"flex\" alignItems=\"center\" gridGap=\"12px\" marginTop=\"16px\" flexWrap=\"wrap\">\n            <Metric\n              label=\"Position value\"\n              gridGap=\"4px\"\n              value={\n                <div className={classes.postAmount}>\n                  <Typography component=\"span\" className={classes.amountText} id=\"position-card-positive-value\">\n                    0 oSQTH\n                  </Typography>\n                  <Typography component=\"span\" className={clsx(classes.amountText, classes.positionUsdValue)}>\n                    {Number(0).toFixed(2)}%\n                  </Typography>\n                </div>\n              }\n            />\n            <Metric\n              gridGap=\"4px\"\n              label=\"Redeemable collateral\"\n              value={\n                <Typography variant=\"body1\" className={classes.amountText}>\n                  {isPositionLoading && existingCollat.isEqualTo(0) ? 'loading' : existingCollat.toFixed(4)} ETH\n                </Typography>\n              }\n            />\n          </Box>\n        ) : (\n          <Box display=\"flex\" gridGap=\"12px\" marginTop=\"16px\" flexWrap=\"wrap\">\n            <Metric\n              gridGap=\"6px\"\n              label={\n                <div className={classes.labelContainer}>\n                  <Typography className={classes.label}>Position value</Typography>\n                  {positionType === PositionType.SHORT ? (\n                    <Typography className={classes.link} id=\"pos-card-manage-vault-link\">\n                      <Link href={`vault/${vaultId}`}>Manage</Link>\n                    </Typography>\n                  ) : null}\n                </div>\n              }\n              value={\n                <div className={classes.postAmount}>\n                  <Box display=\"flex\" alignItems=\"center\" gridGap=\"4px\">\n                    <Typography component=\"span\" className={classes.amountText} id=\"position-card-before-trade-balance\">\n                      {getPositionBasedValue(squeethAmount.toFixed(6), squeethAmount.toFixed(6), '0', '0')}\n                    </Typography>\n\n                    {(tradeType === TradeType.SHORT && positionType === PositionType.LONG) ||\n                    (tradeType === TradeType.LONG && positionType === PositionType.SHORT) ||\n                    tradeAmount.isLessThanOrEqualTo(0) ||\n                    tradeAmount.isNaN() ||\n                    tradeCompleted ? null : (\n                      <>\n                        <ArrowRightAltIcon className={classes.arrow} />\n                        <Typography\n                          component=\"span\"\n                          className={classes.amountText}\n                          id=\"position-card-post-trade-balance\"\n                          style={{\n                            color: postTradeAmt.gte(getPositionBasedValue(squeethAmount, squeethAmount, 0))\n                              ? '#49D273'\n                              : '#f5475c',\n                          }}\n                        >\n                          {postTradeAmt.lte(0) ? 0 : postTradeAmt.toFixed(6)}\n                        </Typography>\n                      </>\n                    )}\n                  </Box>\n                  <Typography component=\"span\" className={clsx(classes.amountText, classes.amountUnit)} variant=\"body2\">\n                    oSQTH\n                  </Typography>\n\n                  {!isDollarValueLoading && (\n                    <Typography component=\"span\" className={clsx(classes.amountText, classes.positionUsdValue)}>\n                      ${getPositionBasedValue(longPositionValue, shortPositionValue, new BigNumber(0)).toFixed(2)}\n                    </Typography>\n                  )}\n                </div>\n              }\n            />\n\n            {/* {isToHidePnL || (tradeType === TradeType.SHORT && positionType != PositionType.LONG) ? (\n              <Metric label=\"PnL\" value={<HidePnLText />} gridGap=\"6px\" />\n            ) : (\n              <>\n                <Metric\n                  gridGap=\"6px\"\n                  label=\"Unrealized PnL\"\n                  value={\n                    <div className={classes.pnl} id=\"unrealized-pnl-value\">\n                      {!pnlLoading ? (\n                        <Box display=\"flex\" alignItems=\"center\" gridGap=\"12px\">\n                          <Typography\n                            className={clsx(pnlClass(positionType, longGain, shortGain, classes), classes.amountText)}\n                            id=\"unrealized-pnl-usd-value\"\n                          >\n                            {getPositionBasedValue(\n                              `$${longUnrealizedPNL.usd.toFixed(2)}`,\n                              `$${shortUnrealizedPNL.usd.toFixed(2)}`,\n                              '$0',\n                              'loading',\n                            )}\n                          </Typography>\n                          <Typography\n                            variant=\"caption\"\n                            className={clsx(\n                              pnlClass(positionType, longGain, shortGain, classes),\n                              classes.amountText,\n                              classes.positionUsdValue,\n                            )}\n                            id=\"unrealized-pnl-perct-value\"\n                          >\n                            {getPositionBasedValue(`(${longGain.toFixed(2)}%)`, `(${shortGain.toFixed(2)}%)`, '', ' ')}\n                          </Typography>\n                        </Box>\n                      ) : (\n                        'loading'\n                      )}\n                    </div>\n                  }\n                />\n                <Metric\n                  gridGap=\"6px\"\n                  label=\"Realized PnL\"\n                  value={\n                    <div className={classes.pnl} id=\"realized-pnl-value\">\n                      <Typography\n                        className={clsx(\n                          classes.amountText,\n                          pnlClass(positionType, longRealizedPNL, shortRealizedPNL, classes),\n                        )}\n                      >\n                        {getRealizedPNLBasedValue(\n                          `$${longRealizedPNL.toFixed(2)}`,\n                          `$${shortRealizedPNL.toFixed(2)}`,\n                          '$0',\n                          'loading',\n                        )}\n                      </Typography>\n                    </div>\n                  }\n                />\n              </>\n            )} */}\n          </Box>\n        )}\n      </div>\n\n      <Typography variant=\"caption\" color=\"textSecondary\">\n        {fetchingNew ? 'Fetching latest position...' : ' '}\n      </Typography>\n    </div>\n  )\n}\n\nconst MemoizedPositionCard = memo(PositionCard)\n\nexport default MemoizedPositionCard\n// function getPositionBasedValue(amountOut: BigNumber, buyQuote: BigNumber, arg2: BigNumber) {\n//   throw new Error('Function not implemented.')\n// }\n"
  },
  {
    "path": "packages/frontend/src/components/RestrictionInfo.tsx",
    "content": "import { createStyles, makeStyles } from '@material-ui/core/styles'\nimport { Typography, BoxProps } from '@material-ui/core'\nimport Link from 'next/link'\nimport { useRouter } from 'next/router'\nimport clsx from 'clsx'\n\nimport Alert from './Alert'\nimport { useRestrictUser } from '@context/restrict-user'\n\nconst useStyles = makeStyles(() =>\n  createStyles({\n    text: { fontWeight: 500, fontSize: '15px', color: '#fff' },\n    link: { textDecoration: 'underline' },\n  }),\n)\n\nconst restrictedCountries: Record<string, string> = {\n  US: 'the United States',\n  BY: 'Belarus',\n  CU: 'Cuba',\n  IR: 'Iran',\n  IQ: 'Iraq',\n  CI: `Cote d'Ivoire`,\n  LR: 'Liberia',\n  KP: 'North Korea',\n  SD: 'Sudan',\n  SY: 'Syria',\n  ZW: 'Zimbabwe',\n  CA: 'Canada',\n}\n\ntype RestrictionInfoProps = BoxProps & { withdrawAllowed?: boolean }\n\nconst RestrictionInfo: React.FC<RestrictionInfoProps> = (props) => {\n  const classes = useStyles()\n  const router = useRouter()\n  const userLocation = router.query?.ct\n  const { isBlockedUser } = useRestrictUser()\n\n  return (\n    <Alert severity=\"warning\" showIcon={false} {...props}>\n      <Typography className={classes.text}>\n        {isBlockedUser\n          ? 'Your wallet address is blocked for violating our terms of service.'\n          : `This app is not available in ${\n              userLocation ? restrictedCountries[String(userLocation)] : 'your country'\n            }. ${\n              props.withdrawAllowed ? 'Only withdrawals are still available.' : null\n            } More details can be found in our `}\n\n        <Typography className={clsx(classes.text, classes.link)} component=\"span\">\n          <Link href=\"/terms-of-service\">\n            <a target=\"_blank\"> Terms of service. </a>\n          </Link>\n        </Typography>\n      </Typography>\n    </Alert>\n  )\n}\n\nexport default RestrictionInfo\n"
  },
  {
    "path": "packages/frontend/src/components/SettingsMenu.tsx",
    "content": "import { Backdrop, Button, Link as MatLink, Switch } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport Typography from '@material-ui/core/Typography'\nimport MoreHorizIcon from '@material-ui/icons/MoreHorizOutlined'\nimport NorthEastOutlinedIcon from '@material-ui/icons/CallMade'\nimport Menu from '@material-ui/core/Menu'\nimport MenuItem from '@material-ui/core/MenuItem'\nimport Modal from '@material-ui/core/Modal'\nimport Box from '@material-ui/core/Box'\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'\nimport List from '@material-ui/core/List'\nimport ListItem from '@material-ui/core/ListItem'\nimport ListItemText from '@material-ui/core/ListItemText'\nimport Link from 'next/link'\nimport { useEffect, useState } from 'react'\nimport { canStoreCookies, CookieNames, setCookie } from '@utils/cookies'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { SITE_EVENTS } from '@utils/amplitude'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    navMenuStyle: {\n      borderRadius: 6,\n      marginTop: theme.spacing(1),\n      minWidth: 180,\n    },\n    link: {\n      display: 'flex',\n      width: '100%',\n    },\n    legalModal: {\n      margin: '8em auto 0px',\n      width: '90%',\n      maxWidth: '450px',\n      background: '#181B1C',\n      padding: '1em',\n      borderRadius: 15,\n      boxShadow: '5px 3px 32px -6px rgba(14,103,112,0.56)',\n    },\n    thirdPartyItems: {\n      display: 'flex',\n      flexDirection: 'column',\n      alignItems: 'flex-start',\n    },\n    thirdPartyTitle: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    legalLinks: {\n      border: `1px solid ${theme.palette.primary.main}`,\n      borderRadius: '20px',\n      color: theme.palette.primary.main,\n      backgroundColor: 'rgba(44, 230, 249, 0.1)',\n      display: 'flex',\n      justifyContent: 'space-between',\n      alignItems: 'center',\n    },\n  }),\n)\n\nconst discordLink = 'https://tiny.cc/opyndiscord'\nconst docsLink = 'https://opyn.gitbook.io/opyn-hub/'\n\nconst SettingMenu = () => {\n  const classes = useStyles()\n  const [anchorEl, setAnchorEl] = useState(null)\n  const [isOver, setIsOver] = useState(false)\n  const [currentlyOver, setCurrentlyOver] = useState('')\n  const [openModal, setOpenModal] = useState(false)\n  const [openCookieModal, setOpenCookieModal] = useState(false)\n  const [consent, setCookieConsent] = useState(canStoreCookies())\n  const { track } = useAmplitude()\n  const open = Boolean(anchorEl)\n  const handleClick = (event: any) => {\n    setAnchorEl(event.currentTarget)\n  }\n  const handleClose = () => {\n    setAnchorEl(null)\n  }\n\n  const handleModal = () => {\n    handleClose()\n    setOpenModal((prevState) => {\n      return !prevState\n    })\n  }\n\n  useEffect(() => {\n    document.body.style.overflow = openModal ? 'hidden' : 'none'\n  }, [openModal])\n\n  const handleMouseOver = (current: string, isOver: boolean) => {\n    setCurrentlyOver(current)\n    setIsOver(isOver)\n  }\n\n  const handleCookieModal = () => {\n    handleClose()\n    setCookieConsent(canStoreCookies())\n    setOpenCookieModal((prevState) => !prevState)\n  }\n\n  const acceptCookie = () => {\n    setCookieConsent(true)\n    setCookie(CookieNames.Consent, 'true')\n  }\n\n  const handleCookieConsentChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n    track(SITE_EVENTS.TOGGLE_COOKIE_CONSENT, { status: event.target.checked })\n    setCookieConsent(event.target.checked)\n    setCookie(CookieNames.Consent, event.target.checked.toString())\n  }\n\n  return (\n    <>\n      <Button\n        id=\"nav-menu-button\"\n        aria-controls={open ? 'nav-menu' : undefined}\n        aria-haspopup=\"true\"\n        aria-expanded={open ? 'true' : undefined}\n        onClick={handleClick}\n      >\n        <MoreHorizIcon color=\"primary\" />\n      </Button>\n      <Menu\n        className={classes.navMenuStyle}\n        id=\"nav-menu\"\n        anchorEl={anchorEl}\n        open={open}\n        onClose={handleClose}\n        MenuListProps={{\n          'aria-labelledby': 'nav-menu-button',\n        }}\n      >\n        <MenuItem onClick={handleClose} key=\"discord\">\n          <a\n            href={discordLink}\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            className={classes.link}\n            onClick={() => track(SITE_EVENTS.CLICK_DISCORD, { link: discordLink })}\n          >\n            Discord\n          </a>\n        </MenuItem>\n        <MenuItem onClick={handleClose}>\n          <a\n            href={docsLink}\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            className={classes.link}\n            onClick={() => track(SITE_EVENTS.CLICK_DOCS, { link: docsLink })}\n          >\n            Docs\n          </a>\n        </MenuItem>\n        <MenuItem onClick={handleModal}>Legal & Privacy</MenuItem>\n      </Menu>\n\n      <Modal\n        open={openModal}\n        onClose={handleModal}\n        aria-labelledby=\"modal-modal-title\"\n        aria-describedby=\"modal-modal-description\"\n        BackdropComponent={Backdrop}\n        disableScrollLock\n      >\n        <Box className={classes.legalModal}>\n          <Typography id=\"modal-modal-title\" variant=\"h6\" component=\"h2\">\n            Legal & Privacy\n          </Typography>\n          <List style={{ marginBottom: '2em' }}>\n            <ListItem\n              className={classes.legalLinks}\n              style={{ marginBottom: '.75em' }}\n              onMouseOver={() => handleMouseOver('tos', true)}\n              onMouseOut={() => handleMouseOver('tos', false)}\n            >\n              <Typography style={{ display: 'flex', alignItems: 'center' }}>\n                <InfoOutlinedIcon style={{ marginRight: '.25em' }} />\n\n                <Link href=\"/terms-of-service\">\n                  <a\n                    target=\"_blank\"\n                    style={{ textDecoration: isOver && currentlyOver === 'tos' ? 'underline' : 'none' }}\n                    onClick={() => track(SITE_EVENTS.CLICK_TERMS_OF_SERVICE)}\n                  >\n                    Squeeth User Terms of Service\n                  </a>\n                </Link>\n              </Typography>\n              <Link href=\"/terms-of-service\">\n                <a target=\"_blank\" onClick={() => track(SITE_EVENTS.CLICK_TERMS_OF_SERVICE)}>\n                  <NorthEastOutlinedIcon />\n                </a>\n              </Link>\n            </ListItem>\n            <ListItem\n              className={classes.legalLinks}\n              style={{ marginBottom: '.75em' }}\n              onMouseOver={() => handleMouseOver('pp', true)}\n              onMouseOut={() => handleMouseOver('pp', false)}\n            >\n              <Typography style={{ display: 'flex', alignItems: 'center' }}>\n                <InfoOutlinedIcon style={{ marginRight: '.25em' }} />\n                <Link href=\"/privacy-policy\">\n                  <a\n                    target=\"_blank\"\n                    style={{ textDecoration: isOver && currentlyOver === 'pp' ? 'underline' : 'none' }}\n                    onClick={() => track(SITE_EVENTS.CLICK_PRIVACY_POLICY)}\n                  >\n                    Opyn Privacy Policy\n                  </a>\n                </Link>\n              </Typography>\n              <Link href=\"/privacy-policy\">\n                <a target=\"_blank\" onClick={() => track(SITE_EVENTS.CLICK_PRIVACY_POLICY)}>\n                  <NorthEastOutlinedIcon />\n                </a>\n              </Link>\n            </ListItem>\n          </List>\n          <Typography>This app uses the following third-party APIs:</Typography>\n          <List style={{ maxHeight: '400px', overflow: 'auto' }}>\n            <ListItem className={classes.thirdPartyItems}>\n              <Typography className={classes.thirdPartyTitle}>\n                <InfoOutlinedIcon style={{ marginRight: '.5em' }} />\n                <ListItemText>Alchemy</ListItemText>\n              </Typography>\n              <ListItemText>The app fetches on-chain data and constructs contract calls with Alchemy API</ListItemText>\n            </ListItem>\n            <ListItem className={classes.thirdPartyItems}>\n              <Typography className={classes.thirdPartyTitle}>\n                <InfoOutlinedIcon style={{ marginRight: '.5em' }} />\n                <ListItemText>Chainalysis</ListItemText>\n              </Typography>\n              <ListItemText>\n                The app securely reviews your wallet address using the Chainalysis, Inc. API for risk and compliance\n                reasons.{' '}\n                <MatLink href={`${location.origin}/terms-of-service-faq`} target=\"_blank\">\n                  Learn More\n                </MatLink>\n              </ListItemText>\n            </ListItem>\n            <ListItem className={classes.thirdPartyItems}>\n              <Typography className={classes.thirdPartyTitle}>\n                <InfoOutlinedIcon style={{ marginRight: '.5em' }} />\n                <ListItemText>Fathom</ListItemText>\n              </Typography>\n              <ListItemText>The app logs anonymized usage data to make improvements</ListItemText>\n            </ListItem>\n            <ListItem className={classes.thirdPartyItems}>\n              <Typography className={classes.thirdPartyTitle}>\n                <InfoOutlinedIcon style={{ marginRight: '.5em' }} />\n                <ListItemText>Amplitude</ListItemText>\n              </Typography>\n              <ListItemText>The app logs anonymized usage statistics to improve over time</ListItemText>\n            </ListItem>\n            <ListItem className={classes.thirdPartyItems}>\n              <Typography className={classes.thirdPartyTitle}>\n                <InfoOutlinedIcon style={{ marginRight: '.5em' }} />\n                <ListItemText>Sentry</ListItemText>\n              </Typography>\n              <ListItemText>The app logs blocked address events using the Sentry</ListItemText>\n            </ListItem>\n            <ListItem className={classes.thirdPartyItems}>\n              <Typography className={classes.thirdPartyTitle}>\n                <InfoOutlinedIcon style={{ marginRight: '.5em' }} />\n                <ListItemText>The Graph</ListItemText>\n              </Typography>\n              <ListItemText>{`The app fetches blockchain data from the Graph's hosted service`}</ListItemText>\n            </ListItem>\n          </List>\n        </Box>\n      </Modal>\n\n      <Modal\n        open={openCookieModal}\n        onClose={handleCookieModal}\n        aria-labelledby=\"modal-modal-title\"\n        aria-describedby=\"modal-modal-description\"\n      >\n        <Box className={classes.legalModal}>\n          <Typography style={{ marginBottom: '1em' }} id=\"modal-modal-title\" variant=\"h6\" component=\"h2\">\n            Cookies Settings\n          </Typography>\n          <Typography style={{ marginBottom: '.75em', fontSize: '13px' }}>\n            We use cookies to support technical features that enhance your user experience and analyze frontend traffic.\n            To learn more about these methods, including how to disable them, view our{' '}\n            <MatLink href={`${location.origin}/privacy-policy`} target=\"_blank\">\n              Privacy Policy.\n            </MatLink>\n          </Typography>\n\n          {consent ? (\n            <Switch\n              checked={consent}\n              onChange={handleCookieConsentChange}\n              inputProps={{ 'aria-label': 'controlled' }}\n            />\n          ) : (\n            <Button variant=\"outlined\" color=\"primary\" onClick={acceptCookie}>\n              I Accept Cookies\n            </Button>\n          )}\n        </Box>\n      </Modal>\n    </>\n  )\n}\n\nexport default SettingMenu\n"
  },
  {
    "path": "packages/frontend/src/components/SharePnl/PnlChart.tsx",
    "content": "import { Typography, CircularProgress } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport clsx from 'clsx'\nimport { intervalToDuration, format } from 'date-fns'\nimport { useQuery } from 'react-query'\nimport HighchartsReact from 'highcharts-react-official'\nimport Highcharts from 'highcharts'\n\nimport { getCrabPnlV2ChartData, getBullChartData } from '@utils/pricer'\n\ntype StrategyType = 'crab' | 'zenbull'\n\nconst formatDuration = (duration: Duration) => {\n  const { years, months, days, hours } = duration\n  const formattedDuration = []\n\n  if (years) {\n    formattedDuration.push(`${years}y`)\n  }\n  if (months) {\n    formattedDuration.push(`${months}m`)\n  }\n  if (days) {\n    formattedDuration.push(`${days}d`)\n  }\n  if (hours) {\n    formattedDuration.push(`${hours}h`)\n  }\n\n  return formattedDuration.join(' ')\n}\n\nconst pnlGraphOptions = {\n  chart: {\n    backgroundColor: 'none',\n    zoomType: 'xy',\n    height: '346',\n    marginTop: '20',\n    marginLeft: '40',\n    style: {\n      fontFamily: 'DM Mono',\n    },\n  },\n  title: {\n    text: '',\n  },\n  legend: {\n    enabled: false,\n    backgroundColor: '#343738',\n    borderRadius: 10,\n    itemStyle: {\n      color: '#BABBBB',\n    },\n  },\n  xAxis: {\n    type: 'datetime',\n    tickWidth: 0,\n    lineWidth: 1,\n    lineColor: '#8c8c8c',\n    showFirstLabel: true,\n    showLastLabel: true,\n    plotLines: [\n      {\n        dashStyle: 'dot',\n      },\n    ],\n    crosshair: {\n      color: '#999',\n    },\n    labels: {\n      enabled: false,\n      style: {\n        color: '#BABBBB',\n      },\n    },\n  },\n  yAxis: {\n    title: {\n      text: '',\n    },\n    labels: {\n      style: {\n        color: '#BABBBB',\n      },\n    },\n    gridLineColor: 'rgba(221,221,221,0.1)',\n  },\n  tooltip: {\n    shared: true,\n    borderColor: 'none',\n    style: {\n      fontFamily: 'DM Mono',\n    },\n  },\n  credits: {\n    enabled: false,\n  },\n  exporting: {\n    enabled: true,\n  },\n}\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    flex: {\n      display: 'flex',\n    },\n    alignCenter: {\n      alignItems: 'center',\n    },\n    alignStart: {\n      alignItems: 'flex-start',\n    },\n    loadingContainer: {\n      height: '368px',\n    },\n    loadingSpinner: {\n      color: '#BABBBB',\n      lineHeight: '130%',\n    },\n    loadingText: {\n      fontSize: '18px',\n      color: '#BABBBB',\n      lineHeight: '130%',\n    },\n    textMargin: {\n      marginLeft: theme.spacing(2),\n    },\n    chartLabel: {\n      color: '#BABBBB',\n      fontSize: '15px',\n      fontWeight: 500,\n      lineHeight: '140%',\n      fontFamily: 'DM Mono',\n      marginLeft: '36px',\n      [theme.breakpoints.down('xs')]: {\n        marginLeft: '0px',\n        fontSize: '14px',\n      },\n    },\n  }),\n)\n\nconst useFetchPnlChartData = (strategy: StrategyType, depositTimestamp: number) => {\n  return useQuery(\n    ['pnlChartData', strategy, depositTimestamp],\n    async () => {\n      const endTimestamp = Math.floor(Date.now() / 1000)\n\n      if (strategy === 'crab') {\n        return getCrabPnlV2ChartData(depositTimestamp, endTimestamp).then((response) => {\n          return response.data?.map((x: Record<string, number>) => [x.timestamp * 1000, x.crabPnL * 100])\n        })\n      } else {\n        return getBullChartData(depositTimestamp, endTimestamp).then((response) => {\n          return response.data?.map((x: Record<string, number>) => [x.timestamp * 1000, x.bullEthPnl])\n        })\n      }\n    },\n    {\n      staleTime: Infinity,\n      refetchOnWindowFocus: true,\n    },\n  )\n}\n\nconst PnlChart = ({ strategy, depositedAt }: { strategy: StrategyType; depositedAt: number }) => {\n  const depositDate = new Date(depositedAt * 1000)\n  const query = useFetchPnlChartData(strategy, depositedAt)\n\n  const { isLoading, data } = query\n  const classes = useStyles()\n\n  if (isLoading) {\n    return (\n      <div className={clsx(classes.flex, classes.alignStart, classes.loadingContainer)}>\n        <div className={clsx(classes.flex, classes.alignCenter)}>\n          <CircularProgress size={15} className={classes.loadingSpinner} />\n          <Typography className={clsx(classes.loadingText, classes.textMargin)}>Fetching data...</Typography>\n        </div>\n      </div>\n    )\n  }\n\n  const isCrab = strategy === 'crab'\n\n  const series = [\n    {\n      name: isCrab ? 'Crab/USDC 🦀  % Return' : 'Bull/ETH 🧘🐂 % Return',\n      yAxis: 0,\n      data: data || [],\n      tooltip: {\n        valueDecimals: 2,\n        valueSuffix: '%',\n      },\n      color: '#70E3F6',\n    },\n  ]\n\n  const chartOptions = {\n    ...pnlGraphOptions,\n    series: series,\n  }\n\n  const strategyDuration = intervalToDuration({ start: new Date(), end: depositDate })\n  const formattedDuration = formatDuration(strategyDuration)\n\n  return (\n    <>\n      <HighchartsReact highcharts={Highcharts} options={chartOptions} />\n      <Typography className={classes.chartLabel}>\n        {format(depositDate, 'MM/dd/yy')} (deposited {formattedDuration} ago)\n      </Typography>\n    </>\n  )\n}\n\nexport default PnlChart\n"
  },
  {
    "path": "packages/frontend/src/components/SqueethCard.tsx",
    "content": "import { Box, BoxProps, useTheme } from '@material-ui/core'\nimport { FC } from 'react'\n\nconst SqueethCard: FC<BoxProps> = ({ children, ...props }) => {\n  const theme = useTheme()\n  return (\n    <Box\n      p={2}\n      bgcolor={`${theme.palette.background.paper}40`}\n      borderRadius={theme.spacing(1)}\n      display=\"flex\"\n      {...props}\n    >\n      {children}\n    </Box>\n  )\n}\n\nexport default SqueethCard\n"
  },
  {
    "path": "packages/frontend/src/components/StepperBox.tsx",
    "content": "import Step from '@material-ui/core/Step'\nimport StepLabel from '@material-ui/core/StepLabel'\nimport Stepper from '@material-ui/core/Stepper'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React from 'react'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    stepper: {\n      width: '100%',\n      marginBottom: theme.spacing(1),\n    },\n  }),\n)\n\ntype StepperBoxProps = {\n  activeStep: number\n  steps?: Array<string>\n}\n\nexport const StepperBox: React.FC<StepperBoxProps> = ({\n  activeStep = 0,\n  steps = ['Buy Squeeth to LP', 'LP the SQTH-ETH Uniswap Pool'],\n}) => {\n  const classes = useStyles()\n\n  return (\n    <Stepper activeStep={activeStep} className={classes.stepper}>\n      {steps.map((label) => (\n        <Step key={label}>\n          <StepLabel>{label}</StepLabel>\n        </Step>\n      ))}\n    </Stepper>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/About/AdvancedMetrics.tsx",
    "content": "import React, { useState } from 'react'\nimport { Box, Fade, Typography } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp'\nimport KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown'\nimport { useAtomValue } from 'jotai'\n\nimport Metric, { MetricLabel } from '@components/Metric'\nimport { TextButton } from '@components/Button'\nimport { impliedVolAtom, impliedVolatilityShutdownAtom, osqthRefVolAtom } from '@state/controller/atoms'\nimport { formatNumber } from '@utils/formatter'\nimport { Tooltips } from '@constants/enums'\nimport { bullCurrentFundingAtom } from '@state/bull/atoms'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { SITE_EVENTS } from '@utils/amplitude'\n\nconst useStyles = makeStyles(() =>\n  createStyles({\n    button: {\n      color: 'rgba(255, 255, 255, 0.5)',\n    },\n    buttonText: {\n      color: 'rgba(255, 255, 255, 0.5)',\n      fontSize: '15px',\n      fontWeight: 500,\n      marginRight: '4px',\n    },\n  }),\n)\n\nconst AdvancedMetrics: React.FC = () => {\n  const [showAdvanced, setShowAdvanced] = useState(false)\n\n  const impliedVolatilityShutdown = useAtomValue(impliedVolatilityShutdownAtom)\n  const osqthRefVol = useAtomValue(osqthRefVolAtom)\n  const currentImpliedFunding = useAtomValue(bullCurrentFundingAtom)\n  const { track } = useAmplitude()\n\n  const classes = useStyles()\n\n  const impliedVolShutdownPercent = impliedVolatilityShutdown * 100\n\n  return (\n    <div>\n      <TextButton\n        className={classes.button}\n        onClick={() => {\n          setShowAdvanced(!showAdvanced)\n          !showAdvanced ? track(SITE_EVENTS.SEE_ADVANCED_METRICS_BULL) : null\n        }}\n      >\n        <Typography className={classes.buttonText}>Advanced</Typography>{' '}\n        {showAdvanced ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}\n      </TextButton>\n\n      <Fade in={showAdvanced}>\n        {showAdvanced ? (\n          <Box display=\"flex\" justifyContent=\"space-between\" gridGap=\"12px\" marginTop=\"16px\" flexWrap=\"wrap\">\n            <Metric\n              label={\n                <MetricLabel\n                  label=\"Daily Premium\"\n                  tooltipTitle={`${Tooltips.StrategyEarnFunding}. ${Tooltips.CurrentImplFunding}`}\n                />\n              }\n              gridGap=\"4px\"\n              value={\n                currentImpliedFunding && currentImpliedFunding != Infinity\n                  ? `${formatNumber(currentImpliedFunding * 100)}%`\n                  : '-'\n              }\n            />\n            <Metric\n              label={<MetricLabel label=\"Implied Volatility \" tooltipTitle={Tooltips.ImplVol} />}\n              gridGap=\"4px\"\n              value={`${formatNumber(impliedVolShutdownPercent)}%`}\n            />\n            <Metric\n              label={<MetricLabel label=\"Reference Volatility\" tooltipTitle={Tooltips.osqthRefVol} />}\n              gridGap=\"4px\"\n              value={`${formatNumber(osqthRefVol)}%`}\n            />\n          </Box>\n        ) : (\n          <div></div>\n        )}\n      </Fade>\n    </div>\n  )\n}\n\nexport default AdvancedMetrics\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/About/NextRebalanceTimer.tsx",
    "content": "import React, { useEffect, useState } from 'react'\nimport { Typography } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport { intervalToDuration } from 'date-fns'\nimport { sortBy } from 'lodash'\n\nconst padZero = (number: number, padding: number): String => {\n  return `${number}`.padStart(padding, '0')\n}\n\nconst getNextHedgeDate = (now: Date): Date => {\n  // hedges every monday, wednesday, friday at 16:30 UTC\n\n  // next monday at 16:30 UTC\n  const nextMondayHedge = new Date(now)\n  nextMondayHedge.setUTCDate(nextMondayHedge.getUTCDate() + ((1 + 7 - nextMondayHedge.getUTCDay()) % 7 || 7))\n  nextMondayHedge.setUTCHours(16, 30, 0, 0)\n\n  // next wednesday at 16:30 UTC\n  const nextWednesdayHedge = new Date(now)\n  nextWednesdayHedge.setUTCDate(nextWednesdayHedge.getUTCDate() + ((3 + 7 - nextWednesdayHedge.getUTCDay()) % 7 || 7))\n  nextWednesdayHedge.setUTCHours(16, 30, 0, 0)\n\n  // next wednesday at 16:30 UTC\n  const nextFridayHedge = new Date(now)\n  nextFridayHedge.setUTCDate(nextFridayHedge.getUTCDate() + ((5 + 7 - nextFridayHedge.getUTCDay()) % 7 || 7))\n  nextFridayHedge.setUTCHours(16, 30, 0, 0)\n\n  // today at 16:30 UTC\n  const todayHedge = new Date(now)\n  todayHedge.setUTCDate(todayHedge.getUTCDate())\n  todayHedge.setUTCHours(16, 30, 0, 0)\n\n  const isMondayInUTC = now.getUTCDay() === 1\n  const isWednesdayInUTC = now.getUTCDay() === 3\n  const isFridayInUTC = now.getUTCDay() === 5\n  const hasHedgeTimePassedInUTC = now.getUTCHours() > 16 || (now.getUTCHours() === 16 && now.getUTCMinutes() >= 30)\n\n  // if today is monday, wednesday, friday and time is before 16:30 UTC, use today's hedge date\n  const comingMondayHedge = isMondayInUTC && !hasHedgeTimePassedInUTC ? todayHedge : nextMondayHedge\n  const comingWednesdayHedge = isWednesdayInUTC && !hasHedgeTimePassedInUTC ? todayHedge : nextWednesdayHedge\n  const comingFridayHedge = isFridayInUTC && !hasHedgeTimePassedInUTC ? todayHedge : nextFridayHedge\n\n  // find closest hedge date\n  const nextHedges = sortBy([comingMondayHedge, comingWednesdayHedge, comingFridayHedge], (date) => date.getTime())\n  return nextHedges[0]\n}\n\nconst useStyles = makeStyles(() =>\n  createStyles({\n    label: {\n      fontSize: '15px',\n      color: 'rgba(255, 255, 255, 0.5)',\n      fontWeight: 500,\n      textAlign: 'right',\n    },\n    value: {\n      fontSize: '20px',\n      color: 'rgba(255, 255, 255, 1)',\n      fontWeight: 500,\n      fontFamily: 'DM Mono',\n      textAlign: 'right',\n    },\n  }),\n)\n\nconst NextRebalanceTimer: React.FC = () => {\n  const [timeLeft, setTimeLeft] = useState('')\n  const classes = useStyles()\n\n  useEffect(() => {\n    const interval = setInterval(() => {\n      const now = new Date()\n      const nextHedgeDate = getNextHedgeDate(now)\n\n      const duration = intervalToDuration({ start: now, end: nextHedgeDate })\n      const days = padZero(duration.days ?? 0, 2)\n      const hours = padZero(duration.hours ?? 0, 2)\n      const minutes = padZero(duration.minutes ?? 0, 2)\n      const seconds = padZero(duration.seconds ?? 0, 2)\n\n      const result = `${days}D ${hours}H ${minutes}M ${seconds}S`\n      setTimeLeft(result)\n    }, 1000)\n\n    return () => clearInterval(interval)\n  }, [])\n\n  return (\n    <div>\n      <Typography className={classes.label}>Next hedge in</Typography>\n      <Typography className={classes.value} variant=\"subtitle2\">\n        {timeLeft}\n      </Typography>\n    </div>\n  )\n}\n\nexport default NextRebalanceTimer\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/About/ProfitabilityChart.tsx",
    "content": "import React, { useMemo } from 'react'\nimport { useAtomValue } from 'jotai'\nimport {\n  LineChart,\n  Line,\n  XAxis,\n  YAxis,\n  ResponsiveContainer,\n  ReferenceDot,\n  ReferenceArea,\n  Label,\n  Tooltip,\n  TooltipProps,\n} from 'recharts'\nimport { Box, useTheme, Fade, Typography, useMediaQuery } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport { makeStyles } from '@material-ui/core/styles'\nimport { Skeleton } from '@material-ui/lab'\n\nimport { bullCurrentFundingAtom } from '@state/bull/atoms'\nimport { ethPriceAtLastHedgeAtomV2 } from '@state/crab/atoms'\nimport { toTokenAmount } from '@utils/calculations'\nimport { useOnChainETHPrice } from '@hooks/useETHPrice'\nimport { formatNumber } from '@utils/formatter'\n\nconst useTooltipStyles = makeStyles(() => ({\n  root: {\n    backgroundColor: 'rgba(247,247,247,0.85)',\n    padding: '4px 8px',\n  },\n  label: {\n    fontSize: '12px',\n    fontFamily: 'DM Mono',\n    color: 'rgb(51, 51, 51)',\n  },\n  value: {\n    fontSize: '12px',\n    fontFamily: 'DM Mono',\n    color: 'rgb(51, 51, 51)',\n  },\n}))\n\ninterface CustomTooltipCustomProps {\n  ethPriceAtLastHedge: number\n}\ntype CustomTooltipProps = TooltipProps<any, any> & CustomTooltipCustomProps\n\nconst CustomTooltip: React.FC<CustomTooltipProps> = ({ active, payload, ethPriceAtLastHedge }) => {\n  const classes = useTooltipStyles()\n\n  if (active && payload && payload.length) {\n    const strategyReturn = payload[0].payload.strategyReturn\n    const ethPrice = payload[0].payload.ethPrice\n    const ethReturn = (ethPrice - ethPriceAtLastHedge) / ethPriceAtLastHedge\n\n    return (\n      <div className={classes.root}>\n        <Typography className={classes.label}>\n          {`ETH return: `}\n          <b>{formatNumber(ethReturn * 100)}%</b>\n        </Typography>\n        <Typography className={classes.value}>\n          {`Zen Bull return: `}\n          <b>{formatNumber(strategyReturn)}%</b>\n        </Typography>\n      </div>\n    )\n  }\n\n  return null\n}\n\nconst CustomActiveDot = (props: any) => {\n  const { cx, cy, value, fill } = props\n\n  if (!value) {\n    return null\n  }\n  return <rect x={cx - 1.5} y={cy - 7} width={3} height={14} strokeWidth={0} fill={fill} />\n}\n\nconst CandyBar = (props: any) => {\n  const { x, y, width, height, fill, stroke } = props\n\n  const barX = x\n  const barY = height < 0 ? y + height : y\n  const barWidth = width\n  const barHeight = Math.abs(height)\n\n  return (\n    <>\n      <rect x={barX} y={barY} width={barWidth} height={barHeight} fill={fill} />\n      <rect x={barX} y={barY} width={1} height={barHeight} fill={stroke} />\n      <rect x={barX + barWidth} y={barY} width={1} height={barHeight} fill={stroke} />\n    </>\n  )\n}\n\nfunction getStrategyReturn(funding: number, ethReturn: number) {\n  return (funding - Math.pow(ethReturn, 2)) * 100 * 0.5\n}\n\n// generate data from -percentRange to +percentRange\nconst getDataPoints = (funding: number, ethPriceAtLastHedge: number, percentRange: number) => {\n  const dataPoints = []\n\n  const starting = new BigNumber(-percentRange)\n  const increment = new BigNumber(0.05)\n  const ending = new BigNumber(percentRange)\n\n  let current = starting\n  while (current.lte(ending)) {\n    const ethReturn = current.div(100).toNumber()\n\n    const strategyReturn = getStrategyReturn(funding, ethReturn)\n    const strategyReturnPositive = strategyReturn >= 0 ? strategyReturn : null\n    const strategyReturnNegative = strategyReturn < 0 ? strategyReturn : null\n\n    dataPoints.push({\n      ethPrice: ethPriceAtLastHedge + ethReturn * ethPriceAtLastHedge,\n      strategyReturn,\n      strategyReturnPositive,\n      strategyReturnNegative,\n    })\n\n    current = current.plus(increment)\n  }\n\n  return dataPoints\n}\n\nconst Chart: React.FC<{ currentFunding: number }> = ({ currentFunding }) => {\n  const ethPriceAtLastHedgeValue = useAtomValue(ethPriceAtLastHedgeAtomV2)\n  const ethPrice = useOnChainETHPrice()\n\n  const impliedFunding = 2 * currentFunding // for 2 days\n  const ethPriceAtLastHedge = Number(toTokenAmount(ethPriceAtLastHedgeValue, 18))\n  const currentEthPrice = Number(ethPrice)\n\n  const profitableBoundsPercent = Math.sqrt(impliedFunding)\n  const lowerPriceBandForProfitability = ethPriceAtLastHedge - profitableBoundsPercent * ethPriceAtLastHedge\n  const upperPriceBandForProfitability = ethPriceAtLastHedge + profitableBoundsPercent * ethPriceAtLastHedge\n\n  const data = useMemo(() => {\n    const percentRange = profitableBoundsPercent * 4 * 100 // 4x the profitable move percent\n    return getDataPoints(impliedFunding, ethPriceAtLastHedge, percentRange)\n  }, [impliedFunding, ethPriceAtLastHedge, profitableBoundsPercent])\n\n  const getStrategyReturnForETHPrice = (ethPriceValue: number) => {\n    const ethReturn = (ethPriceValue - ethPriceAtLastHedge) / ethPriceAtLastHedge\n    return getStrategyReturn(impliedFunding, ethReturn)\n  }\n\n  const theme = useTheme()\n  const successColor = theme.palette.success.main\n  const errorColor = theme.palette.error.main\n\n  const isMobileBreakpoint = useMediaQuery(theme.breakpoints.down('xs'))\n  const currentStrategyReturn = getStrategyReturnForETHPrice(currentEthPrice)\n\n  return (\n    <Fade in={true}>\n      <Box height={300} width=\"100%\" display=\"flex\" justifyContent=\"flex-start\">\n        <ResponsiveContainer width=\"100%\" height=\"100%\">\n          <LineChart data={data}>\n            <defs>\n              <marker id=\"arrowhead\" markerWidth=\"10\" markerHeight=\"10\" refX=\"5\" refY=\"5\" orient=\"auto-start-reverse\">\n                <polygon points=\"0 0, 10 5, 0 10\" fill=\"#fff\" opacity=\"0.5\" />\n              </marker>\n\n              <marker id=\"dot\" viewBox=\"0 0 16 16\" refX=\"8\" refY=\"8\" markerWidth=\"8\" markerHeight=\"8\">\n                <circle cx=\"8\" cy=\"8\" r=\"8\" fill=\"#ffffff80\" />\n              </marker>\n\n              {/* https://stackoverflow.com/a/12263962/5733330 */}\n              <filter x=\"0\" y=\"0\" width=\"1\" height=\"1\" id=\"removebackground\">\n                <feFlood floodColor={theme.palette.background.default} />\n                <feComposite in=\"SourceGraphic\" />\n              </filter>\n            </defs>\n\n            <XAxis\n              height={1}\n              type=\"number\"\n              dataKey=\"ethPrice\"\n              domain={isMobileBreakpoint ? ['dataMin - 20', 'dataMax + 20'] : ['dataMin - 40', 'dataMax + 200']}\n              tick={false}\n              strokeDasharray=\"5,5\"\n              strokeOpacity=\"0.5\"\n              stroke=\"#fff\"\n              markerEnd=\"url(#arrowhead)\"\n              markerStart=\"url(#dot)\"\n            >\n              <Label\n                value=\"ETH Return\"\n                position=\"insideBottomRight\"\n                offset={14}\n                fill=\"#ffffff80\"\n                enableBackground={'fill'}\n              />\n            </XAxis>\n            <YAxis\n              width={1}\n              type=\"number\"\n              dataKey=\"strategyReturn\"\n              tick={false}\n              domain={isMobileBreakpoint ? ['dataMin - 1.25', 'dataMax + 1.25'] : ['dataMin - 0.5', 'dataMax + 0.5']}\n              strokeDasharray=\"5,5\"\n              strokeOpacity=\"0.5\"\n              stroke=\"#fff\"\n              markerStart=\"url(#arrowhead)\"\n              yAxisId=\"0\"\n            >\n              <Label\n                value={isMobileBreakpoint ? 'Zen Bull' : 'Zen Bull Strategy'}\n                position=\"insideTopLeft\"\n                offset={14}\n                fill=\"#ffffff80\"\n              />\n            </YAxis>\n\n            <ReferenceArea\n              shape={<CandyBar />}\n              x1={lowerPriceBandForProfitability}\n              x2={upperPriceBandForProfitability}\n              fill={successColor + '16'}\n              stroke={successColor}\n            />\n\n            <Tooltip\n              wrapperStyle={{ outline: 'none' }}\n              cursor={{ stroke: '#fff', strokeOpacity: '0.5', strokeWidth: 1 }}\n              content={<CustomTooltip ethPriceAtLastHedge={ethPriceAtLastHedge} />}\n            />\n\n            <Line\n              type=\"monotone\"\n              dataKey=\"strategyReturnNegative\"\n              stroke={errorColor}\n              strokeWidth={1}\n              dot={false}\n              isAnimationActive={false}\n              activeDot={<CustomActiveDot />}\n            />\n            <Line\n              type=\"monotone\"\n              dataKey=\"strategyReturnPositive\"\n              stroke={successColor}\n              strokeWidth={1}\n              dot={false}\n              isAnimationActive={false}\n              activeDot={<CustomActiveDot />}\n            />\n\n            <ReferenceDot\n              x={lowerPriceBandForProfitability}\n              y={getStrategyReturnForETHPrice(lowerPriceBandForProfitability)}\n              r={0}\n            >\n              <Label\n                fontFamily={'DM Mono'}\n                fontWeight={500}\n                value={'$' + formatNumber(lowerPriceBandForProfitability, 0)}\n                position=\"insideBottomRight\"\n                offset={8}\n                fill=\"#ffffffcc\"\n              />\n            </ReferenceDot>\n            <ReferenceDot\n              x={upperPriceBandForProfitability}\n              y={getStrategyReturnForETHPrice(upperPriceBandForProfitability)}\n              r={0}\n            >\n              <Label\n                fontFamily={'DM Mono'}\n                fontWeight={500}\n                value={'$' + formatNumber(upperPriceBandForProfitability, 0)}\n                position=\"insideBottomLeft\"\n                offset={8}\n                fill=\"#ffffffcc\"\n              />\n            </ReferenceDot>\n\n            <ReferenceDot\n              x={currentEthPrice}\n              y={currentStrategyReturn}\n              r={5}\n              fill={currentStrategyReturn < 0 ? errorColor : successColor}\n              strokeWidth={0}\n            >\n              <Label\n                fontFamily=\"DM Mono\"\n                fontWeight={500}\n                value={'$' + formatNumber(currentEthPrice, 0)}\n                position=\"insideTop\"\n                offset={20}\n                fill={currentStrategyReturn < 0 ? errorColor : successColor}\n                filter=\"url(#removebackground)\"\n              />\n            </ReferenceDot>\n          </LineChart>\n        </ResponsiveContainer>\n      </Box>\n    </Fade>\n  )\n}\n\nfunction ChartWrapper() {\n  const currentFunding = useAtomValue(bullCurrentFundingAtom)\n\n  const isLoading = currentFunding === 0 || isNaN(currentFunding) || !isFinite(currentFunding)\n  if (isLoading) {\n    return (\n      <Box display=\"flex\" height=\"300px\" alignItems=\"center\" justifyContent=\"center\">\n        <Skeleton width={'100%'} height={300} />\n      </Box>\n    )\n  }\n\n  return <Chart currentFunding={currentFunding} />\n}\n\nexport default ChartWrapper\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/About/index.tsx",
    "content": "import React from 'react'\nimport { Box, Typography } from '@material-ui/core'\nimport clsx from 'clsx'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\n\nimport NextRebalanceTimer from './NextRebalanceTimer'\nimport ProfitabilityChart from './ProfitabilityChart'\nimport AdvancedMetrics from './AdvancedMetrics'\nimport useStyles from '@components/Strategies/styles'\nimport { LinkWrapper } from '@components/LinkWrapper'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { SITE_EVENTS } from '@utils/amplitude'\n\nconst useAboutStyles = makeStyles((theme) =>\n  createStyles({\n    timerContainer: {\n      position: 'absolute',\n      top: '10px',\n      right: '0',\n\n      [theme.breakpoints.down('sm')]: {\n        position: 'relative',\n        top: '0px',\n        right: '0',\n        marginBottom: '16px',\n      },\n    },\n  }),\n)\n\nconst gitBookLink = 'https://opyn.gitbook.io/opyn-strategies/zen-bull/introduction'\n\nconst About: React.FC = () => {\n  const classes = useStyles()\n  const aboutClasses = useAboutStyles()\n  const { track } = useAmplitude()\n\n  return (\n    <div>\n      <Box display=\"flex\" flexDirection=\"column\" gridGap=\"8px\">\n        <Typography variant=\"h3\" className={classes.sectionTitle}>\n          About Zen Bull\n        </Typography>\n        <Typography variant=\"h2\" className={classes.heading}>\n          Stack ETH when ETH increases slow and steady\n        </Typography>\n\n        <Typography className={clsx(classes.text, classes.textMargin)}>\n          Zen bull makes money when ETH goes up, slow and steady. It stacks ETH if ETH is within the below bands at the\n          next rebalance.{' '}\n          <LinkWrapper\n            href={gitBookLink}\n            onClick={() => track(SITE_EVENTS.CLICK_LEARN_MORE_BULL, { link: gitBookLink })}\n          >\n            Learn more\n          </LinkWrapper>\n        </Typography>\n      </Box>\n\n      {/* <Box position=\"relative\" marginTop=\"32px\">\n        <div className={aboutClasses.timerContainer}>\n          <NextRebalanceTimer />\n        </div>\n        <ProfitabilityChart />\n      </Box> */}\n\n      <Box marginTop=\"16px\">\n        <AdvancedMetrics />\n      </Box>\n    </div>\n  )\n}\n\nexport default About\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/BullTrade/Deposit.tsx",
    "content": "import { Box, Typography, Tooltip, CircularProgress } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport { useAtom, useAtomValue } from 'jotai'\nimport { useMemo, useRef, useState, useCallback } from 'react'\nimport InfoIcon from '@material-ui/icons/Info'\nimport debounce from 'lodash/debounce'\n\nimport { PrimaryButtonNew } from '@components/Button'\nimport { InputToken } from '@components/InputNew'\nimport { LinkWrapper } from '@components/LinkWrapper'\nimport Metric from '@components/Metric'\nimport RestrictionInfo from '@components/RestrictionInfo'\nimport { TradeSettings } from '@components/TradeSettings'\nimport {\n  BIG_ZERO,\n  FUNDING_PERIOD,\n  INDEX_SCALE,\n  VOL_PERCENT_FIXED,\n  VOL_PERCENT_SCALAR,\n  YEAR,\n  WETH_DECIMALS,\n} from '@constants/index'\nimport { useGetFlashBulldepositParams, useBullFlashDeposit } from '@state/bull/hooks'\nimport { impliedVolAtom, indexAtom, normFactorAtom, osqthRefVolAtom } from '@state/controller/atoms'\nimport { useSelectWallet, useWalletBalance } from '@state/wallet/hooks'\nimport { toTokenAmount } from '@utils/calculations'\nimport { formatNumber } from '@utils/formatter'\nimport ethLogo from 'public/images/eth-logo.svg'\nimport { connectedWalletAtom, supportedNetworkAtom } from '@state/wallet/atoms'\nimport { useRestrictUser } from '@context/restrict-user'\nimport { crabStrategySlippageAtomV2, crabStrategyVaultAtomV2, maxCapAtomV2 } from '@state/crab/atoms'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { bullCapAtom, bullDepositedEthInEulerAtom } from '@state/bull/atoms'\nimport { BULL_EVENTS } from '@utils/amplitude'\nimport useExecuteOnce from '@hooks/useExecuteOnce'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { useZenBullStyles } from './styles'\nimport { BullTradeType, BullTransactionConfirmation } from './index'\n\nconst BullDeposit: React.FC<{ onTxnConfirm: (txn: BullTransactionConfirmation) => void }> = ({ onTxnConfirm }) => {\n  const classes = useZenBullStyles()\n\n  const depositAmountRef = useRef('0')\n  const [depositAmount, setDepositAmount] = useState('0')\n  const depositAmountBN = useMemo(() => new BigNumber(depositAmount), [depositAmount])\n\n  const ongoingTransactionAmountRef = useRef(new BigNumber(0))\n  const [txLoading, setTxLoading] = useState(false)\n\n  const [slippage, setSlippage] = useAtom(crabStrategySlippageAtomV2)\n  const [quoteLoading, setQuoteLoading] = useState(false)\n\n  const negativeReturnsError = false\n  const { isRestricted, isWithdrawAllowed } = useRestrictUser()\n  const connected = useAtomValue(connectedWalletAtom)\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n\n  const selectWallet = useSelectWallet()\n\n  const index = useAtomValue(indexAtom)\n  const normFactor = useAtomValue(normFactorAtom)\n  const impliedVol = useAtomValue(impliedVolAtom)\n  const ethIndexPrice = toTokenAmount(index, 18).sqrt()\n  const bullCap = useAtomValue(bullCapAtom)\n  const bullDepositedEth = useAtomValue(bullDepositedEthInEulerAtom)\n  const crabCap = useAtomValue(maxCapAtomV2)\n  const crabDepositedEth = useAtomValue(crabStrategyVaultAtomV2)?.collateralAmount || BIG_ZERO\n  const osqthRefVol = useAtomValue(osqthRefVolAtom)\n\n  const [quote, setQuote] = useState({\n    ethToCrab: BIG_ZERO,\n    minEthFromSqth: BIG_ZERO,\n    minEthFromUsdc: BIG_ZERO,\n    ethOutForSqth: BIG_ZERO,\n    ethOutForUsdc: BIG_ZERO,\n    oSqthIn: BIG_ZERO,\n    usdcIn: BIG_ZERO,\n    wPowerPerpPoolFee: 0,\n    usdcPoolFee: 0,\n    priceImpact: 0,\n    wethToLend: BIG_ZERO,\n    poolFee: 0,\n  })\n\n  const { data: balance } = useWalletBalance()\n\n  const getFlashBullDepositParams = useGetFlashBulldepositParams()\n  const bullFlashDeposit = useBullFlashDeposit()\n  const { track } = useAmplitude()\n\n  const trackUserEnteredDepositAmount = useCallback(\n    (amount: BigNumber) => track(BULL_EVENTS.DEPOSIT_BULL_AMOUNT_ENTERED, { amount: amount.toNumber() }),\n    [track],\n  )\n\n  const [trackDepositAmountEnteredOnce, resetTracking] = useExecuteOnce(trackUserEnteredDepositAmount)\n\n  const debouncedDepositQuote = debounce(async (ethToDeposit: string) => {\n    setQuoteLoading(true)\n    getFlashBullDepositParams(new BigNumber(ethToDeposit))\n      .then((_quote) => {\n        console.log(\n          '',\n          ethToDeposit.toString(),\n          depositAmountRef.current,\n          _quote.ethOutForSqth.toString(),\n          _quote.ethOutForUsdc.toString(),\n        )\n        if (ethToDeposit === depositAmountRef.current) {\n          let quotePriceImpact = _quote.priceImpact\n          if (_quote.poolFee) quotePriceImpact = _quote.priceImpact - _quote.poolFee\n          setQuote({ ..._quote, priceImpact: quotePriceImpact })\n        }\n      })\n      .finally(() => {\n        if (ethToDeposit === depositAmountRef.current) setQuoteLoading(false)\n      })\n  }, 500)\n\n  const onInputChange = useCallback(\n    (ethToDeposit: string) => {\n      const depositEthBN = new BigNumber(ethToDeposit)\n      depositEthBN.isGreaterThan(0) ? trackDepositAmountEnteredOnce(depositEthBN) : null\n      setDepositAmount(ethToDeposit)\n      depositAmountRef.current = ethToDeposit\n      debouncedDepositQuote(ethToDeposit)\n    },\n    [trackDepositAmountEnteredOnce, debouncedDepositQuote],\n  )\n\n  const onTxnConfirmed = useCallback(\n    (id?: string) => {\n      onInputChange('0')\n      onTxnConfirm({\n        status: true,\n        amount: ongoingTransactionAmountRef.current,\n        tradeType: BullTradeType.Deposit,\n        txId: id,\n      })\n      resetTracking()\n      ongoingTransactionAmountRef.current = new BigNumber(0)\n    },\n    [onTxnConfirm, resetTracking, onInputChange],\n  )\n\n  const depositFundingWarning = useAppMemo(() => {\n    const impliedVolDiff = new BigNumber(-VOL_PERCENT_SCALAR)\n    const impliedVolDiffLowVol = new BigNumber(-VOL_PERCENT_FIXED)\n    const threshold = BigNumber.max(\n      new BigNumber(osqthRefVol / 100).times(new BigNumber(1).plus(impliedVolDiff)),\n      new BigNumber(osqthRefVol / 100).plus(impliedVolDiffLowVol),\n    )\n\n    const showFundingWarning = new BigNumber(impliedVol).lt(threshold) ? true : false\n    return showFundingWarning\n  }, [osqthRefVol, impliedVol])\n\n  const depositPriceImpactWarning = useAppMemo(() => {\n    const squeethPrice = quote.ethOutForSqth.div(quote.oSqthIn).times(1.003) // Adding Fee\n\n    const scalingFactor = new BigNumber(INDEX_SCALE)\n    const fundingPeriod = new BigNumber(FUNDING_PERIOD).div(YEAR)\n    const log = Math.log(scalingFactor.times(squeethPrice).div(normFactor.times(ethIndexPrice)).toNumber())\n    const executionVol = new BigNumber(log).div(fundingPeriod).sqrt()\n\n    const showPriceImpactWarning =\n      log < 0 ||\n      executionVol\n        .minus(impliedVol)\n        .abs()\n        .gt(BigNumber.max(new BigNumber(impliedVol).times(VOL_PERCENT_SCALAR), VOL_PERCENT_FIXED))\n    return showPriceImpactWarning\n  }, [quote.ethOutForSqth, quote.oSqthIn, normFactor, ethIndexPrice, impliedVol])\n\n  const depositError = useAppMemo(() => {\n    if (depositAmountBN.gt(toTokenAmount(balance ?? BIG_ZERO, 18))) {\n      return 'Insufficient ETH balance'\n    }\n    if (quote.ethToCrab.plus(crabDepositedEth).gt(crabCap) || quote.wethToLend.plus(bullDepositedEth).gt(bullCap)) {\n      return 'Deposit amount exceeds cap. Try a smaller amount.'\n    }\n  }, [\n    balance,\n    bullCap,\n    bullDepositedEth,\n    crabCap,\n    crabDepositedEth,\n    depositAmountBN,\n    quote.ethToCrab,\n    quote.wethToLend,\n  ])\n\n  const onDepositClick = useCallback(async () => {\n    setTxLoading(true)\n    try {\n      ongoingTransactionAmountRef.current = new BigNumber(depositAmountRef.current)\n      const dataToTrack = {\n        priceImpact: quote.poolFee + quote.priceImpact,\n        isPriceImpactHigh: depositPriceImpactWarning,\n        amount: new BigNumber(depositAmountRef.current).toNumber(),\n      }\n      await bullFlashDeposit(\n        quote.ethToCrab,\n        quote.minEthFromSqth,\n        quote.minEthFromUsdc,\n        quote.wPowerPerpPoolFee,\n        quote.usdcPoolFee,\n        new BigNumber(depositAmountRef.current),\n        dataToTrack,\n        onTxnConfirmed,\n      )\n    } catch (e) {\n      resetTracking()\n      console.log(e)\n    }\n    setTxLoading(false)\n  }, [\n    bullFlashDeposit,\n    quote.ethToCrab,\n    quote.minEthFromSqth,\n    quote.minEthFromUsdc,\n    quote.wPowerPerpPoolFee,\n    quote.usdcPoolFee,\n    quote.poolFee,\n    quote.priceImpact,\n    onTxnConfirmed,\n    resetTracking,\n    depositPriceImpactWarning,\n  ])\n\n  const setDepositMax = () => {\n    track(BULL_EVENTS.DEPOSIT_BULL_SET_AMOUNT_MAX, {\n      amount: toTokenAmount(balance ?? BIG_ZERO, WETH_DECIMALS).toNumber(),\n    })\n    onInputChange(toTokenAmount(balance ?? BIG_ZERO, WETH_DECIMALS).toString())\n  }\n\n  const onChangeSlippage = useCallback(\n    (amount: BigNumber) => {\n      track(BULL_EVENTS.DEPOSIT_BULL_CHANGE_SLIPPAGE, { percent: amount.toNumber() })\n      setSlippage(amount.toNumber())\n      onInputChange(depositAmount)\n    },\n    [track, setSlippage, depositAmount, onInputChange],\n  )\n\n  return (\n    <>\n      <Box marginTop=\"32px\" display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" gridGap=\"12px\">\n        <Typography variant=\"h3\" className={classes.subtitle}>\n          Strategy Deposit\n        </Typography>\n      </Box>\n\n      <div className={classes.tradeContainer}>\n        <InputToken\n          id=\"bull-deposit-eth-input\"\n          value={depositAmount}\n          onInputChange={onInputChange}\n          balance={toTokenAmount(balance ?? BIG_ZERO, 18)}\n          logo={ethLogo}\n          symbol={'ETH'}\n          usdPrice={ethIndexPrice}\n          error={!!depositError}\n          helperText={depositError}\n          onBalanceClick={setDepositMax}\n        />\n\n        {negativeReturnsError ? (\n          <div className={classes.notice}>\n            <div className={classes.infoIcon}>\n              <Tooltip title={'Negative returns warning'}>\n                <InfoIcon fontSize=\"medium\" />\n              </Tooltip>\n            </div>\n            <Typography variant=\"caption\" className={classes.infoText}>\n              Negative returns warning\n            </Typography>\n          </div>\n        ) : null}\n\n        {depositFundingWarning ? (\n          <div className={classes.notice}>\n            <div className={classes.infoIcon}>\n              <Tooltip\n                title={\n                  'The strategy sells squeeth to earn premium. Premium is currently lower than usual. You can still deposit, but you may be more likely to have negative returns.'\n                }\n              >\n                <InfoIcon fontSize=\"medium\" />\n              </Tooltip>\n            </div>\n            <Typography variant=\"caption\" className={classes.infoText}>\n              Zen bull premium is currently lower than usual. Consider depositing later.\n            </Typography>\n          </div>\n        ) : null}\n\n        {depositPriceImpactWarning ? (\n          <div className={classes.notice}>\n            <div className={classes.infoIcon}>\n              <Tooltip\n                title={\n                  'High price impact means that you are losing a significant amount of value due to the size of your trade. Depositing a smaller size can reduce your price impact.'\n                }\n              >\n                <InfoIcon fontSize=\"medium\" />\n              </Tooltip>\n            </div>\n            <Typography variant=\"caption\" className={classes.infoText}>\n              High price impact. Try multiple smaller transactions or contact us through{' '}\n              <LinkWrapper href=\"https://tiny.cc/opyndiscord\">discord</LinkWrapper> about OTC\n            </Typography>\n          </div>\n        ) : null}\n\n        <Box display=\"flex\" flexDirection=\"column\" gridGap=\"12px\" marginTop=\"24px\">\n          <Box\n            display=\"flex\"\n            alignItems=\"center\"\n            justifyContent=\"space-between\"\n            gridGap=\"12px\"\n            className={classes.slippageContainer}\n          >\n            <Metric\n              label=\"Uniswap Fee\"\n              value={formatNumber(quote.poolFee) + '%'}\n              isSmall\n              flexDirection=\"row\"\n              justifyContent=\"space-between\"\n              gridGap=\"12px\"\n            />\n\n            <Box display=\"flex\" alignItems=\"center\" gridGap=\"12px\" flex=\"1\">\n              <Metric\n                label=\"Price Impact\"\n                value={formatNumber(quote.priceImpact < 0 ? 0 : quote.priceImpact) + '%'}\n                isSmall\n                flexDirection=\"row\"\n                justifyContent=\"space-between\"\n                gridGap=\"12px\"\n              />\n              <TradeSettings setSlippage={onChangeSlippage} slippage={new BigNumber(slippage)} />\n            </Box>\n          </Box>\n        </Box>\n\n        {isRestricted && <RestrictionInfo withdrawAllowed={isWithdrawAllowed} marginTop=\"24px\" />}\n\n        <Box marginTop=\"24px\">\n          {isRestricted ? (\n            <PrimaryButtonNew\n              fullWidth\n              variant=\"contained\"\n              onClick={selectWallet}\n              disabled={true}\n              id=\"bull-restricted-btn\"\n            >\n              {'Unavailable'}\n            </PrimaryButtonNew>\n          ) : !connected ? (\n            <PrimaryButtonNew\n              fullWidth\n              variant=\"contained\"\n              onClick={selectWallet}\n              disabled={false}\n              id=\"bull-select-wallet-btn\"\n            >\n              {'Connect Wallet'}\n            </PrimaryButtonNew>\n          ) : !supportedNetwork ? (\n            <PrimaryButtonNew fullWidth variant=\"contained\" disabled={true} id=\"bull-unsupported-network-btn\">\n              {'Unsupported Network'}\n            </PrimaryButtonNew>\n          ) : (\n            <PrimaryButtonNew\n              fullWidth\n              id=\"bull-deposit-btn\"\n              variant={'contained'}\n              onClick={onDepositClick}\n              disabled={quoteLoading || txLoading || depositAmount === '0' || !!depositError}\n            >\n              {!txLoading && !quoteLoading ? 'Deposit' : <CircularProgress color=\"primary\" size=\"1.5rem\" />}\n            </PrimaryButtonNew>\n          )}\n        </Box>\n      </div>\n    </>\n  )\n}\n\nexport default BullDeposit\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/BullTrade/EmergencyWithdraw.tsx",
    "content": "import React, { useCallback, useState, useRef, useMemo } from 'react'\nimport { Box, Typography, Link, CircularProgress, Tooltip, withStyles, IconButton } from '@material-ui/core'\nimport HelpOutlineIcon from '@material-ui/icons/InfoOutlined'\nimport InfoIcon from '@material-ui/icons/Info'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport { useAtom, useAtomValue } from 'jotai'\nimport BigNumber from 'bignumber.js'\nimport debounce from 'lodash/debounce'\nimport ArrowBackIcon from '@material-ui/icons/ArrowBack'\nimport ArrowForwardIcon from '@material-ui/icons/ArrowForward'\n\nimport { InputToken } from '@components/InputNew'\nimport Metric from '@components/Metric'\nimport { TradeSettings } from '@components/TradeSettings'\nimport { PrimaryButtonNew } from '@components/Button'\nimport RestrictionInfo from '@components/RestrictionInfo'\nimport { crabStrategySlippageAtomV2 } from '@state/crab/atoms'\nimport { indexAtom, impliedVolAtom, normFactorAtom } from '@state/controller/atoms'\nimport { useSelectWallet } from '@state/wallet/hooks'\nimport { connectedWalletAtom, supportedNetworkAtom } from '@state/wallet/atoms'\nimport { addressesAtom } from '@state/positions/atoms'\nimport { bullCrabPositionValueInEth, bullCrabValueInEth } from '@state/bull/atoms'\nimport { useGetEmergencyWithdrawParams, useBullEmergencyWithdrawEthFromCrab } from '@state/bull/hooks'\nimport useAppCallback from '@hooks/useAppCallback'\nimport { useUserAllowance } from '@hooks/contracts/useAllowance'\nimport useTrackTransactionFlow from '@hooks/useTrackTransactionFlow'\nimport useExecuteOnce from '@hooks/useExecuteOnce'\nimport useAmplitude from '@hooks/useAmplitude'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { useRestrictUser } from '@context/restrict-user'\nimport { toTokenAmount } from '@utils/calculations'\nimport { formatNumber } from '@utils/formatter'\nimport { BULL_EVENTS } from '@utils/amplitude'\nimport {\n  BIG_ZERO,\n  UNI_POOL_FEES,\n  FUNDING_PERIOD,\n  YEAR,\n  INDEX_SCALE,\n  VOL_PERCENT_FIXED,\n  VOL_PERCENT_SCALAR,\n} from '@constants/index'\nimport ethLogo from 'public/images/eth-logo.svg'\nimport { useZenBullStyles } from './styles'\nimport { BullTradeType, BullTransactionConfirmation } from './index'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    description: {\n      marginTop: theme.spacing(1),\n      marginBottom: theme.spacing(1),\n    },\n    subDescription: {\n      marginTop: theme.spacing(2),\n      display: 'flex',\n      alignItems: 'center',\n      color: theme.palette.text.secondary,\n    },\n    infoIcon: {\n      color: theme.palette.text.hint,\n      fontSize: 14,\n      marginLeft: theme.spacing(0.75),\n    },\n  }),\n)\n\nconst TooltipTitle = () => (\n  <>\n    <Typography variant=\"caption\">\n      The recovery contract has undergone internal testing and an external peer review, but not audited. Use at your own\n      discretion.\n      <Link href=\"https://opyn.gitbook.io/zen-bull-euler-exploit-faq/\" target=\"_blank\" style={{ marginLeft: '4px' }}>\n        Learn more.\n      </Link>\n    </Typography>\n  </>\n)\n\nenum Step {\n  OPYN = 1,\n  EULER = 2,\n}\n\nconst EmergencyWithdraw: React.FC<{\n  onTxnConfirm: (txn: BullTransactionConfirmation) => void\n  isLoadingBalance: boolean\n  bullBalance: BigNumber\n}> = ({ onTxnConfirm, isLoadingBalance, bullBalance }) => {\n  const zenBullClasses = useZenBullStyles()\n  const classes = useStyles()\n\n  const [step, setStep] = useState(Step.OPYN)\n\n  const [ethToWithdrawInput, setEthToWithdrawInput] = useState('0')\n  const [quoteLoading, setQuoteLoading] = useState(false)\n  const [quote, setQuote] = useState({\n    maxEthForWPowerPerp: BIG_ZERO,\n    ethInForOsqth: BIG_ZERO,\n    osqthOut: BIG_ZERO,\n    wPowerPerpPoolFee: 0,\n    priceImpact: 0,\n  })\n  const [txLoading, setTxLoading] = useState(false)\n\n  const [slippage, setSlippage] = useAtom(crabStrategySlippageAtomV2)\n  const index = useAtomValue(indexAtom)\n  const connected = useAtomValue(connectedWalletAtom)\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n  const { bullStrategy, bullEmergencyWithdraw } = useAtomValue(addressesAtom)\n  const bullValueInEth = useAtomValue(bullCrabValueInEth)\n  const bullPositionValueInEth = useAtomValue(bullCrabPositionValueInEth)\n  const impliedVol = useAtomValue(impliedVolAtom)\n  const normFactor = useAtomValue(normFactorAtom)\n\n  const { track } = useAmplitude()\n  const getEmergencyWithdrawParams = useGetEmergencyWithdrawParams()\n  const bullEmergencyWithdrawEthFromCrab = useBullEmergencyWithdrawEthFromCrab()\n\n  const trackUserEnteredWithdrawAmount = useCallback(\n    (amount: BigNumber) => track(BULL_EVENTS.EMERGENCY_WITHDRAW_BULL_AMOUNT_ENTERED, { amount: amount.toNumber() }),\n    [track],\n  )\n\n  const bullWithdrawAmountRef = useRef(BIG_ZERO)\n  const ongoingTransactionEthAmountRef = useRef(BIG_ZERO)\n\n  const { allowance: bullAllowance, approve: approveBull } = useUserAllowance(bullStrategy, bullEmergencyWithdraw)\n  const logAndRunTransaction = useTrackTransactionFlow()\n  const [trackWithdrawAmountEnteredOnce, resetTracking] = useExecuteOnce(trackUserEnteredWithdrawAmount)\n  const ethToWithdrawInputBN = useMemo(() => new BigNumber(ethToWithdrawInput), [ethToWithdrawInput])\n\n  const debouncedGetWithdrawQuote = debounce(async (bullToWithdraw: BigNumber) => {\n    // ignore if its not the most recent request\n    if (!bullWithdrawAmountRef.current.isEqualTo(bullToWithdraw)) {\n      return\n    }\n\n    setQuoteLoading(true)\n    getEmergencyWithdrawParams(bullToWithdraw)\n      .then((_quote) => {\n        setQuote(_quote)\n      })\n      .finally(() => {\n        setQuoteLoading(false)\n      })\n  }, 500)\n\n  const onInputChange = useAppCallback(\n    (ethToWithdraw: string) => {\n      setEthToWithdrawInput(ethToWithdraw)\n\n      const ethToWithdrawBN = new BigNumber(ethToWithdraw)\n      ethToWithdrawBN.isGreaterThan(0) ? trackWithdrawAmountEnteredOnce(ethToWithdrawBN) : null\n\n      const _bullToWithdraw = ethToWithdrawBN.div(bullPositionValueInEth).times(bullBalance)\n      bullWithdrawAmountRef.current = _bullToWithdraw\n      debouncedGetWithdrawQuote(_bullToWithdraw)\n    },\n    [bullBalance, bullPositionValueInEth, debouncedGetWithdrawQuote, trackWithdrawAmountEnteredOnce],\n  )\n\n  const setWithdrawMax = () => {\n    track(BULL_EVENTS.EMERGENCY_WITHDRAW_BULL_SET_AMOUNT_MAX, {\n      amount: bullPositionValueInEth.toNumber(),\n    })\n    onInputChange(bullPositionValueInEth.toString())\n  }\n\n  const onChangeSlippage = useCallback(\n    (amount: BigNumber) => {\n      track(BULL_EVENTS.EMERGENCY_WITHDRAW_BULL_CHANGE_SLIPPAGE, { percent: amount.toNumber() })\n      setSlippage(amount.toNumber())\n      onInputChange(ethToWithdrawInput)\n    },\n    [setSlippage, onInputChange, ethToWithdrawInput, track],\n  )\n\n  const onApproveClick = async () => {\n    setTxLoading(true)\n    try {\n      await logAndRunTransaction(async () => {\n        await approveBull(() => console.log('Approved'))\n      }, BULL_EVENTS.APPROVE_EMERGENCY_WITHDRAW_BULL)\n    } catch (e) {\n      console.log(e)\n    }\n    setTxLoading(false)\n  }\n\n  const onTxnConfirmed = useCallback(\n    (id?: string) => {\n      onInputChange('0')\n\n      onTxnConfirm({\n        status: true,\n        amount: ongoingTransactionEthAmountRef.current,\n        tradeType: BullTradeType.Withdraw,\n        txId: id,\n      })\n      resetTracking()\n      ongoingTransactionEthAmountRef.current = new BigNumber(0)\n    },\n    [onTxnConfirm, resetTracking, onInputChange],\n  )\n\n  const onWithdrawClick = async () => {\n    setTxLoading(true)\n    try {\n      ongoingTransactionEthAmountRef.current = ethToWithdrawInputBN\n\n      const dataToTrack = {\n        amount: bullWithdrawAmountRef.current.toNumber(),\n        isPriceImpactHigh: showPriceImpactWarning,\n        priceImpact: quote.priceImpact,\n      }\n\n      await bullEmergencyWithdrawEthFromCrab(\n        bullWithdrawAmountRef.current,\n        quote.maxEthForWPowerPerp,\n        dataToTrack,\n        onTxnConfirmed,\n      )\n    } catch (e) {\n      console.log(e)\n    }\n    setTxLoading(false)\n  }\n\n  const ethIndexPrice = toTokenAmount(index, 18).sqrt()\n\n  const withdrawError = useAppMemo(() => {\n    if (ethToWithdrawInputBN.gt(bullPositionValueInEth)) {\n      return 'Withdraw amount greater than strategy balance'\n    }\n  }, [ethToWithdrawInputBN, bullPositionValueInEth])\n\n  const showPriceImpactWarning = useAppMemo(() => {\n    const squeethPriceFromTrade = quote.ethInForOsqth.div(quote.osqthOut).times(1 - UNI_POOL_FEES / 1000_000)\n    const scalingFactor = new BigNumber(INDEX_SCALE)\n    const fundingPeriod = new BigNumber(FUNDING_PERIOD).div(YEAR)\n    const executionVol = new BigNumber(\n      Math.log(scalingFactor.times(squeethPriceFromTrade).div(normFactor.times(ethIndexPrice)).toNumber()),\n    )\n      .div(fundingPeriod)\n      .sqrt()\n\n    const showWarning = executionVol\n      .minus(impliedVol)\n      .abs()\n      .gt(BigNumber.max(new BigNumber(impliedVol).times(VOL_PERCENT_SCALAR), VOL_PERCENT_FIXED))\n\n    return showWarning\n  }, [quote.ethInForOsqth, quote.osqthOut, normFactor, ethIndexPrice, impliedVol])\n\n  const { isRestricted, isWithdrawAllowed } = useRestrictUser()\n  const selectWallet = useSelectWallet()\n\n  const bullAllowanceInEth = bullAllowance.times(bullValueInEth)\n\n  const isInputEmpty = ethToWithdrawInputBN.isZero()\n\n  return (\n    <>\n      <Stepper step={step} setStep={setStep} />\n\n      {step === Step.OPYN ? (\n        <>\n          <Typography style={{ marginTop: '16px' }} variant=\"h3\" className={zenBullClasses.subtitle}>\n            Recovery Withdrawal - Crab\n          </Typography>\n\n          <Typography variant=\"body2\" className={classes.description}>\n            Use recovery withdrawal to withdraw the Crab portion of a Zen Bull position.{' '}\n            <Link href=\"https://opyn.gitbook.io/zen-bull-euler-exploit-faq/\" target=\"_blank\">\n              Learn more.\n            </Link>\n          </Typography>\n\n          <div className={classes.subDescription}>\n            <Typography variant=\"body2\">Recovery contract has been peer reviewed</Typography>\n            <Tooltip title={<TooltipTitle />} interactive>\n              <HelpOutlineIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n          </div>\n\n          <div className={zenBullClasses.tradeContainer}>\n            <InputToken\n              id=\"bull-withdraw-eth-input\"\n              value={ethToWithdrawInput}\n              onInputChange={onInputChange}\n              isBalanceLoading={isLoadingBalance}\n              balance={bullPositionValueInEth}\n              logo={ethLogo}\n              symbol={'ETH'}\n              usdPrice={ethIndexPrice}\n              error={!!withdrawError}\n              helperText={withdrawError}\n              onBalanceClick={setWithdrawMax}\n            />\n\n            {showPriceImpactWarning ? (\n              <div className={zenBullClasses.notice}>\n                <div className={zenBullClasses.infoIcon}>\n                  <Tooltip\n                    title={\n                      'High price impact means that you are losing a significant amount of value due to the size of your trade. Withdrawing a smaller size can reduce your price impact.'\n                    }\n                  >\n                    <InfoIcon fontSize=\"medium\" />\n                  </Tooltip>\n                </div>\n                <Typography variant=\"caption\" className={zenBullClasses.infoText}>\n                  High price impact. Try multiple smaller transactions.\n                </Typography>\n              </div>\n            ) : null}\n\n            <Box display=\"flex\" flexDirection=\"column\" gridGap=\"12px\" marginTop=\"24px\">\n              <Box\n                display=\"flex\"\n                alignItems=\"center\"\n                justifyContent=\"space-between\"\n                gridGap=\"12px\"\n                className={zenBullClasses.slippageContainer}\n              >\n                <Metric\n                  label=\"Slippage\"\n                  value={formatNumber(slippage) + '%'}\n                  isSmall\n                  flexDirection=\"row\"\n                  justifyContent=\"space-between\"\n                  gridGap=\"12px\"\n                />\n\n                <Box display=\"flex\" alignItems=\"center\" gridGap=\"12px\" flex=\"1\">\n                  <Metric\n                    label=\"Price Impact\"\n                    value={formatNumber(quote.priceImpact) + '%'}\n                    isSmall\n                    flexDirection=\"row\"\n                    justifyContent=\"space-between\"\n                    gridGap=\"12px\"\n                  />\n                  <TradeSettings setSlippage={onChangeSlippage} slippage={new BigNumber(slippage)} />\n                </Box>\n              </Box>\n            </Box>\n\n            {isRestricted && <RestrictionInfo withdrawAllowed={isWithdrawAllowed} marginTop=\"24px\" />}\n\n            <Box marginTop=\"24px\">\n              {isRestricted && !isWithdrawAllowed ? (\n                <PrimaryButtonNew\n                  fullWidth\n                  variant=\"contained\"\n                  onClick={selectWallet}\n                  disabled={true}\n                  id=\"bull-restricted-btn\"\n                >\n                  {'Unavailable'}\n                </PrimaryButtonNew>\n              ) : !connected ? (\n                <PrimaryButtonNew\n                  fullWidth\n                  variant=\"contained\"\n                  onClick={selectWallet}\n                  disabled={false}\n                  id=\"bull-select-wallet-btn\"\n                >\n                  {'Connect Wallet'}\n                </PrimaryButtonNew>\n              ) : !supportedNetwork ? (\n                <PrimaryButtonNew fullWidth variant=\"contained\" disabled={true} id=\"bull-unsupported-network-btn\">\n                  {'Unsupported Network'}\n                </PrimaryButtonNew>\n              ) : bullAllowanceInEth.lt(ethToWithdrawInputBN) ? (\n                <PrimaryButtonNew\n                  fullWidth\n                  id=\"bull-withdraw-btn\"\n                  variant={'contained'}\n                  onClick={onApproveClick}\n                  disabled={quoteLoading || txLoading || !!withdrawError || isInputEmpty}\n                >\n                  {!txLoading && !quoteLoading ? 'Approve' : <CircularProgress color=\"primary\" size=\"2rem\" />}\n                </PrimaryButtonNew>\n              ) : (\n                <PrimaryButtonNew\n                  fullWidth\n                  id=\"bull-withdraw-btn\"\n                  variant=\"contained\"\n                  onClick={onWithdrawClick}\n                  disabled={quoteLoading || txLoading || !!withdrawError || isInputEmpty}\n                >\n                  {!txLoading && !quoteLoading ? 'Withdraw' : <CircularProgress color=\"primary\" size=\"2rem\" />}\n                </PrimaryButtonNew>\n              )}\n            </Box>\n          </div>\n        </>\n      ) : (\n        <>\n          <Typography variant=\"h3\" style={{ marginTop: '16px' }} className={zenBullClasses.subtitle}>\n            Recovery Withdrawal - Euler\n          </Typography>\n          <Typography variant=\"body2\" className={classes.description}>\n            Go to Euler&apos;s redemption page to claim funds from Euler.{' '}\n            <Link href=\"https://opyn.gitbook.io/zen-bull-euler-exploit-faq/\" target=\"_blank\">\n              Learn more.\n            </Link>\n          </Typography>\n          <div className={zenBullClasses.tradeContainer}>\n            <a style={{ width: '100%' }} href=\"https://redemptions.euler.finance/\" target=\"_blank\" rel=\"noreferrer\">\n              <PrimaryButtonNew style={{ marginTop: '16px', width: '100%' }}>Go to Redemption page</PrimaryButtonNew>\n            </a>\n          </div>\n        </>\n      )}\n    </>\n  )\n}\n\nconst useStepperStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n      marginBottom: theme.spacing(1),\n    },\n    stepData: {\n      marginTop: theme.spacing(0),\n      fontFamily: 'DM Mono',\n      textAlign: 'center',\n      fontSize: '14px',\n    },\n    stepButton: {\n      padding: theme.spacing(0.5),\n      margin: theme.spacing(0, 0.5),\n      '&:disabled': {\n        background: theme.palette.background.lightStone,\n        opacity: '0.5',\n      },\n    },\n    disabled: {\n      backgroundColor: theme.palette.background.lightStone,\n      opacity: '1',\n    },\n  }),\n)\n\nconst StepperIconButton = withStyles((theme) => ({\n  root: {\n    background: theme.palette.background.stone,\n  },\n  disabled: {\n    background: theme.palette.background.stone,\n    opacity: '1',\n  },\n}))(IconButton)\n\nconst Stepper: React.FC<{ step: number; setStep: (step: number) => void }> = ({ setStep, step }) => {\n  const classes = useStepperStyles()\n\n  return (\n    <div>\n      <div className={classes.container}>\n        <StepperIconButton\n          id=\"lp-prev-step-btn\"\n          className={classes.stepButton}\n          classes={{ disabled: classes.disabled }}\n          disabled={step === 1}\n          onClick={() => setStep(step - 1)}\n        >\n          <ArrowBackIcon fontSize=\"small\" />\n        </StepperIconButton>\n        <StepperIconButton\n          id=\"lp-next-step-btn\"\n          className={classes.stepButton}\n          classes={{ disabled: classes.disabled }}\n          disabled={step === 2}\n          onClick={() => setStep(step + 1)}\n        >\n          <ArrowForwardIcon fontSize=\"small\" />\n        </StepperIconButton>\n      </div>\n      <Typography className={classes.stepData}>\n        0<span id=\"current-lp-step\">{step}</span> / 02\n      </Typography>{' '}\n    </div>\n  )\n}\n\nexport default EmergencyWithdraw\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/BullTrade/ShutdownEmergencyWithdraw.tsx",
    "content": "import React, { useState, useEffect } from 'react'\nimport { Box, Typography, CircularProgress, Collapse, Link } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport { useAtomValue } from 'jotai'\nimport InfoIcon from '@material-ui/icons/Info'\n\nimport { PrimaryButtonNew } from '@components/Button'\nimport { InputToken } from '@components/InputNew'\nimport Metric from '@components/Metric'\nimport Alert from '@components/Alert'\nimport { useUserAllowance } from '@hooks/contracts/useAllowance'\nimport { addressesAtom } from '@state/positions/atoms'\nimport { connectedWalletAtom, supportedNetworkAtom } from '@state/wallet/atoms'\nimport { useSelectWallet } from '@state/wallet/hooks'\nimport useTrackTransactionFlow from '@hooks/useTrackTransactionFlow'\nimport { formatNumber } from '@utils/formatter'\nimport { BULL_EVENTS } from '@utils/amplitude'\nimport { BIG_ZERO } from '@constants/index'\nimport { useZenBullStyles } from './styles'\nimport { BullTradeType, BullTransactionConfirmation } from './index'\nimport { useBullShutdownEmergencyWithdrawState, useZenBullRedeem, useCalculateWethToReceive } from '@state/bull/hooks'\nimport { useRestrictUser } from '@context/restrict-user'\nimport RestrictionInfo from '@components/RestrictionInfo'\n\ntype Callback = () => void\n\ninterface ShutdownEmergencyWithdrawProps {\n  onTxnConfirm: (txn: BullTransactionConfirmation) => void\n  isLoadingBalance: boolean\n  bullBalance: BigNumber\n  refetchBullBalance: (cb?: Callback) => void\n}\n\nexport const ShutdownEmergencyWithdraw: React.FC<ShutdownEmergencyWithdrawProps> = ({\n  onTxnConfirm,\n  isLoadingBalance,\n  bullBalance,\n  refetchBullBalance,\n}) => {\n  const classes = useZenBullStyles()\n  const [isRedeemTxnLoading, setIsRedeemTxnLoading] = useState(false)\n  const [hasJustApprovedZenBull, setHasJustApprovedZenBull] = useState(false)\n  const [isWethToReceiveLoading, setIsWethToReceiveLoading] = useState(false)\n  const [estimatedWethToReceive, setEstimatedWethToReceive] = useState(BIG_ZERO)\n\n  // Contract state & recovery hooks\n  const { bullStrategy, bullShutdownEmergencyWithdraw } = useAtomValue(addressesAtom)\n  const { isContractReadyForRedemption } = useBullShutdownEmergencyWithdrawState()\n\n  const calculateWethToReceive = useCalculateWethToReceive(bullBalance)\n  const redeemZenBull = useZenBullRedeem()\n\n  // Common hooks\n  const connected = useAtomValue(connectedWalletAtom)\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n  const selectWallet = useSelectWallet()\n  const { allowance: zenBullAllowance, approve: approveZenBull } = useUserAllowance(\n    bullStrategy,\n    bullShutdownEmergencyWithdraw,\n  )\n\n  const { isRestricted, isWithdrawAllowed } = useRestrictUser()\n\n  const logAndRunTransaction = useTrackTransactionFlow()\n\n  // Update estimated WETH on balance changes with loading state\n  useEffect(() => {\n    let mounted = true\n\n    const updateEstimate = async () => {\n      if (!bullBalance.isZero()) {\n        setIsWethToReceiveLoading(true)\n        try {\n          const wethAmount = await calculateWethToReceive()\n          if (mounted) {\n            setEstimatedWethToReceive(wethAmount)\n          }\n        } catch (error) {\n          console.error('Error calculating WETH to receive:', error)\n        } finally {\n          if (mounted) {\n            setIsWethToReceiveLoading(false)\n          }\n        }\n      } else {\n        if (mounted) {\n          setEstimatedWethToReceive(BIG_ZERO)\n          setIsWethToReceiveLoading(false)\n        }\n      }\n    }\n\n    updateEstimate()\n\n    return () => {\n      mounted = false\n    }\n  }, [bullBalance?.toString()])\n\n  const onApproveClick = async () => {\n    setIsRedeemTxnLoading(true)\n    try {\n      await logAndRunTransaction(async () => {\n        await approveZenBull(() => {\n          setHasJustApprovedZenBull(true)\n          console.log('Approved ZenBull')\n        })\n      }, BULL_EVENTS.APPROVE_ZENBULL_REDEMPTION)\n    } catch (e) {\n      console.error(e)\n    }\n    setIsRedeemTxnLoading(false)\n  }\n\n  const onRedeemClick = async () => {\n    setIsRedeemTxnLoading(true)\n    try {\n      await redeemZenBull(bullBalance, (wethReceived) => {\n        onTxnConfirm({\n          status: true,\n          amount: wethReceived,\n          tradeType: BullTradeType.Redeem,\n        })\n\n        refetchBullBalance()\n      })\n    } catch (e) {\n      console.error(e)\n    }\n    setIsRedeemTxnLoading(false)\n  }\n\n  // Check for redemption errors\n  const [isShutdownRedemptionContractActive, setIsShutdownRedemptionContractActive] = useState(false)\n  useEffect(() => {\n    const checkEmergency = async () => {\n      const active = await isContractReadyForRedemption()\n      setIsShutdownRedemptionContractActive(active)\n    }\n    checkEmergency()\n  }, [isContractReadyForRedemption])\n\n  const redeemError = !isShutdownRedemptionContractActive\n    ? 'Shutdown redemption contract not ready'\n    : !isLoadingBalance && bullBalance.lte(0)\n    ? 'No ZenBull to redeem'\n    : undefined\n\n  const needsApproval = zenBullAllowance.lt(bullBalance) && !hasJustApprovedZenBull\n\n  return (\n    <>\n      <Typography variant=\"h3\" className={classes.subtitle} style={{ marginTop: '16px' }}>\n        Shutdown Redemption\n      </Typography>\n\n      <Typography variant=\"body2\" style={{ marginTop: '8px', marginBottom: '24px' }}>\n        Redeem ZenBull tokens for WETH after protocol shutdown\n      </Typography>\n\n      <Alert severity=\"warning\">\n        <Typography variant=\"body2\">\n          Haven't claimed your Euler funds yet? Visit the{' '}\n          <Link href=\"https://redemptions.euler.finance/\" target=\"_blank\">\n            Euler redemption page\n          </Link>{' '}\n          or{' '}\n          <Link href=\"https://opyn.gitbook.io/zen-bull-euler-exploit-faq/\" target=\"_blank\">\n            learn more\n          </Link>\n        </Typography>\n      </Alert>\n\n      <div className={classes.tradeContainer}>\n        <InputToken\n          id=\"zenbull-redeem-input\"\n          value={bullBalance.toString()}\n          balance={bullBalance}\n          symbol=\"ZenBull\"\n          isBalanceLoading={isLoadingBalance}\n          showMaxAction={false}\n          error={!!redeemError}\n          helperText={redeemError}\n          readOnly={true}\n          readOnlyTooltip=\"Only full redemption is allowed\"\n        />\n\n        <Box display=\"flex\" justifyContent=\"space-between\" marginTop=\"24px\">\n          <Metric\n            label=\"WETH to Receive\"\n            value={isWethToReceiveLoading ? 'Loading...' : formatNumber(estimatedWethToReceive.toNumber(), 4) + ' WETH'}\n            isSmall\n            flexDirection=\"row\"\n            justifyContent=\"space-between\"\n            gridGap=\"12px\"\n          />\n        </Box>\n\n        <Collapse in={!!redeemError}>\n          <Alert severity=\"error\" marginTop=\"24px\">\n            {redeemError}\n          </Alert>\n        </Collapse>\n\n        {isRestricted && <RestrictionInfo withdrawAllowed={isWithdrawAllowed} marginTop=\"24px\" />}\n\n        <Box marginTop=\"24px\">\n          {!connected ? (\n            <PrimaryButtonNew fullWidth variant=\"contained\" onClick={selectWallet} id=\"zenbull-connect-wallet-btn\">\n              Connect Wallet\n            </PrimaryButtonNew>\n          ) : !supportedNetwork ? (\n            <PrimaryButtonNew fullWidth variant=\"contained\" disabled={true} id=\"zenbull-unsupported-network-btn\">\n              Unsupported Network\n            </PrimaryButtonNew>\n          ) : needsApproval ? (\n            <PrimaryButtonNew\n              fullWidth\n              variant=\"contained\"\n              onClick={onApproveClick}\n              disabled={isRedeemTxnLoading || isWethToReceiveLoading || !!redeemError}\n              id=\"zenbull-approve-btn\"\n            >\n              {!isRedeemTxnLoading ? 'Approve ZenBull' : <CircularProgress color=\"primary\" size=\"2rem\" />}\n            </PrimaryButtonNew>\n          ) : (\n            <PrimaryButtonNew\n              fullWidth\n              variant=\"contained\"\n              onClick={onRedeemClick}\n              disabled={isRedeemTxnLoading || isWethToReceiveLoading || !!redeemError}\n              id=\"zenbull-redeem-btn\"\n            >\n              {!isRedeemTxnLoading ? 'Redeem ZenBull' : <CircularProgress color=\"primary\" size=\"2rem\" />}\n            </PrimaryButtonNew>\n          )}\n        </Box>\n      </div>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/BullTrade/Withdraw.tsx",
    "content": "import { Box, Typography, Tooltip, CircularProgress } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport { useAtom, useAtomValue } from 'jotai'\nimport { useCallback, useRef, useState, useMemo } from 'react'\nimport InfoIcon from '@material-ui/icons/Info'\nimport debounce from 'lodash/debounce'\n\nimport { PrimaryButtonNew } from '@components/Button'\nimport { InputToken } from '@components/InputNew'\nimport { LinkWrapper } from '@components/LinkWrapper'\nimport Metric from '@components/Metric'\nimport RestrictionInfo from '@components/RestrictionInfo'\nimport { TradeSettings } from '@components/TradeSettings'\nimport {\n  BIG_ZERO,\n  FUNDING_PERIOD,\n  INDEX_SCALE,\n  UNI_POOL_FEES,\n  VOL_PERCENT_FIXED,\n  VOL_PERCENT_SCALAR,\n  WETH_DECIMALS,\n  YEAR,\n} from '@constants/index'\nimport { useGetFlashWithdrawParams, useBullFlashWithdraw } from '@state/bull/hooks'\nimport { impliedVolAtom, indexAtom, normFactorAtom, osqthRefVolAtom } from '@state/controller/atoms'\nimport { useSelectWallet } from '@state/wallet/hooks'\nimport { toTokenAmount } from '@utils/calculations'\nimport { formatNumber } from '@utils/formatter'\nimport ethLogo from 'public/images/eth-logo.svg'\nimport { crabStrategySlippageAtomV2 } from '@state/crab/atoms'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport { addressesAtom } from '@state/positions/atoms'\nimport { useUserAllowance } from '@hooks/contracts/useAllowance'\nimport { useRestrictUser } from '@context/restrict-user'\nimport { connectedWalletAtom, supportedNetworkAtom } from '@state/wallet/atoms'\nimport { bullCurrentETHPositionAtom } from '@state/bull/atoms'\nimport useAppMemo from '@hooks/useAppMemo'\nimport useAppCallback from '@hooks/useAppCallback'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { BULL_EVENTS } from '@utils/amplitude'\nimport useExecuteOnce from '@hooks/useExecuteOnce'\nimport { useZenBullStyles } from './styles'\nimport { BullTradeType, BullTransactionConfirmation } from './index'\nimport useTrackTransactionFlow from '@hooks/useTrackTransactionFlow'\n\nconst BullWithdraw: React.FC<{ onTxnConfirm: (txn: BullTransactionConfirmation) => void }> = ({ onTxnConfirm }) => {\n  const classes = useZenBullStyles()\n\n  const withdrawAmountRef = useRef('0')\n  const ongoingTransactionAmountRef = useRef(new BigNumber(0))\n  const [withdrawAmount, setWithdrawAmount] = useState('0')\n  const withdrawAmountBN = useMemo(() => new BigNumber(withdrawAmount), [withdrawAmount])\n  const [txLoading, setTxLoading] = useState(false)\n\n  const [slippage, setSlippage] = useAtom(crabStrategySlippageAtomV2)\n  const [quoteLoading, setQuoteLoading] = useState(false)\n\n  const negativeReturnsError = false\n  const highDepositWarning = false\n  const { isRestricted } = useRestrictUser()\n  const connected = useAtomValue(connectedWalletAtom)\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n  const bullPositionValueInEth = useAtomValue(bullCurrentETHPositionAtom)\n  const osqthRefVol = useAtomValue(osqthRefVolAtom)\n\n  const selectWallet = useSelectWallet()\n\n  const index = useAtomValue(indexAtom)\n  const ethIndexPrice = toTokenAmount(index, 18).sqrt()\n  const impliedVol = useAtomValue(impliedVolAtom)\n  const normFactor = useAtomValue(normFactorAtom)\n\n  const { bullStrategy, flashBull } = useAtomValue(addressesAtom)\n  const { value: bullBalance } = useTokenBalance(bullStrategy, 15, WETH_DECIMALS)\n  const { allowance: bullAllowance, approve: approveBull } = useUserAllowance(bullStrategy, flashBull)\n\n  const [quote, setQuote] = useState({\n    maxEthForWPowerPerp: BIG_ZERO,\n    maxEthForUsdc: BIG_ZERO,\n    wPowerPerpPoolFee: 0,\n    usdcPoolFee: 0,\n    priceImpact: 0,\n    ethInForSqth: BIG_ZERO,\n    ethInForUsdc: BIG_ZERO,\n    oSqthOut: BIG_ZERO,\n    usdcOut: BIG_ZERO,\n    poolFee: 0,\n  })\n\n  const getFlashBullWithdrawParams = useGetFlashWithdrawParams()\n  const bullFlashWithdraw = useBullFlashWithdraw()\n  const { track } = useAmplitude()\n  const logAndRunTransaction = useTrackTransactionFlow()\n\n  const trackUserEnteredWithdrawAmount = useCallback(\n    (amount: BigNumber) => track(BULL_EVENTS.WITHDRAW_BULL_AMOUNT_ENTERED, { amount: amount.toNumber() }),\n    [track],\n  )\n  const [trackWithdrawAmountEnteredOnce, resetTracking] = useExecuteOnce(trackUserEnteredWithdrawAmount)\n\n  const showPriceImpactWarning = useAppMemo(() => {\n    const squeethPrice = quote.ethInForSqth.div(quote.oSqthOut).times(1 - UNI_POOL_FEES / 1000_000)\n    const scalingFactor = new BigNumber(INDEX_SCALE)\n    const fundingPeriod = new BigNumber(FUNDING_PERIOD).div(YEAR)\n    const executionVol = new BigNumber(\n      Math.log(scalingFactor.times(squeethPrice).div(normFactor.times(ethIndexPrice)).toNumber()),\n    )\n      .div(fundingPeriod)\n      .sqrt()\n    const showPriceImpactWarning = executionVol\n      .minus(impliedVol)\n      .abs()\n      .gt(BigNumber.max(new BigNumber(impliedVol).times(VOL_PERCENT_SCALAR), VOL_PERCENT_FIXED))\n\n    return showPriceImpactWarning\n  }, [quote.ethInForSqth, quote.oSqthOut, normFactor, ethIndexPrice, impliedVol])\n\n  const withdrawFundingWarning = useAppMemo(() => {\n    const impliedVolDiff = new BigNumber(VOL_PERCENT_SCALAR)\n    const impliedVolDiffLowVol = new BigNumber(VOL_PERCENT_FIXED)\n\n    const threshold = BigNumber.max(\n      new BigNumber(osqthRefVol / 100).times(new BigNumber(1).plus(impliedVolDiff)),\n      new BigNumber(osqthRefVol / 100).plus(impliedVolDiffLowVol),\n    )\n\n    const fundingWarning = new BigNumber(impliedVol).gt(threshold) ? true : false\n    return fundingWarning\n  }, [impliedVol, osqthRefVol])\n\n  const debouncedWithdrawQuote = debounce(async (bullToWithdraw: string) => {\n    setQuoteLoading(true)\n    getFlashBullWithdrawParams(new BigNumber(bullToWithdraw))\n      .then((_quote) => {\n        if (bullToWithdraw === withdrawAmountRef.current) {\n          let quotePriceImpact = _quote.priceImpact\n          if (_quote.poolFee) quotePriceImpact = _quote.priceImpact - _quote.poolFee\n          setQuote({ ..._quote, priceImpact: quotePriceImpact })\n        }\n      })\n      .finally(() => {\n        if (bullToWithdraw === withdrawAmountRef.current) setQuoteLoading(false)\n      })\n  }, 500)\n\n  const onInputChange = useAppCallback(\n    (ethToWithdraw: string) => {\n      const withdrawEthBN = new BigNumber(ethToWithdraw)\n      withdrawEthBN.isGreaterThan(0) ? trackWithdrawAmountEnteredOnce(withdrawEthBN) : null\n      const _bullToWithdraw = new BigNumber(ethToWithdraw).div(bullPositionValueInEth).times(bullBalance)\n      setWithdrawAmount(ethToWithdraw)\n      withdrawAmountRef.current = _bullToWithdraw.toString()\n      debouncedWithdrawQuote(_bullToWithdraw.toString())\n    },\n    [trackWithdrawAmountEnteredOnce, debouncedWithdrawQuote, bullBalance, bullPositionValueInEth],\n  )\n\n  const onTxnConfirmed = useCallback(\n    (id?: string) => {\n      onInputChange('0')\n      onTxnConfirm({\n        status: true,\n        amount: ongoingTransactionAmountRef.current,\n        tradeType: BullTradeType.Withdraw,\n        txId: id,\n      })\n      resetTracking()\n      ongoingTransactionAmountRef.current = new BigNumber(0)\n    },\n    [onTxnConfirm, resetTracking, onInputChange],\n  )\n\n  const onWithdrawClick = async () => {\n    setTxLoading(true)\n    try {\n      ongoingTransactionAmountRef.current = new BigNumber(withdrawAmount)\n      const dataToTrack = {\n        amount: new BigNumber(withdrawAmountRef.current).toNumber(),\n        isPriceImpactHigh: showPriceImpactWarning,\n        priceImpact: quote.poolFee + quote.priceImpact,\n      }\n      await bullFlashWithdraw(\n        new BigNumber(withdrawAmountRef.current),\n        quote.maxEthForWPowerPerp,\n        quote.maxEthForUsdc,\n        quote.wPowerPerpPoolFee,\n        quote.usdcPoolFee,\n        dataToTrack,\n        onTxnConfirmed,\n      )\n    } catch (e) {\n      resetTracking()\n      console.log(e)\n    }\n    setTxLoading(false)\n  }\n\n  const onApproveClick = async () => {\n    setTxLoading(true)\n    try {\n      await logAndRunTransaction(async () => {\n        await approveBull(() => console.log('Approved'))\n      }, BULL_EVENTS.APPROVE_WITHDRAW_BULL)\n    } catch (e) {\n      console.log(e)\n    }\n    setTxLoading(false)\n  }\n\n  const withdrawError = useAppMemo(() => {\n    if (withdrawAmountBN.gt(bullPositionValueInEth)) {\n      return 'Withdraw amount greater than strategy balance'\n    }\n  }, [bullPositionValueInEth, withdrawAmountBN])\n\n  const setWithdrawMax = () => {\n    track(BULL_EVENTS.WITHDRAW_BULL_SET_AMOUNT_MAX, {\n      amount: bullPositionValueInEth.toNumber(),\n    })\n    onInputChange(bullPositionValueInEth.toString())\n  }\n\n  const onChangeSlippage = useCallback(\n    (amount: BigNumber) => {\n      track(BULL_EVENTS.WITHDRAW_BULL_CHANGE_SLIPPAGE, { percent: amount.toNumber() })\n      setSlippage(amount.toNumber())\n      onInputChange(withdrawAmount)\n    },\n    [withdrawAmount, setSlippage, onInputChange, track],\n  )\n\n  return (\n    <>\n      <Box marginTop=\"32px\" display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" gridGap=\"12px\">\n        <Typography variant=\"h3\" className={classes.subtitle}>\n          Strategy Withdraw\n        </Typography>\n      </Box>\n\n      <div className={classes.tradeContainer}>\n        <InputToken\n          id=\"bull-deposit-eth-input\"\n          value={withdrawAmount}\n          onInputChange={onInputChange}\n          balance={bullPositionValueInEth}\n          logo={ethLogo}\n          symbol={'ETH'}\n          usdPrice={ethIndexPrice}\n          error={!!withdrawError}\n          helperText={withdrawError}\n          onBalanceClick={setWithdrawMax}\n        />\n\n        {negativeReturnsError ? (\n          <div className={classes.notice}>\n            <div className={classes.infoIcon}>\n              <Tooltip title={'Negative returns warning'}>\n                <InfoIcon fontSize=\"medium\" />\n              </Tooltip>\n            </div>\n            <Typography variant=\"caption\" className={classes.infoText}>\n              Negative returns warning\n            </Typography>\n          </div>\n        ) : null}\n        {withdrawFundingWarning ? (\n          <div className={classes.notice}>\n            <div className={classes.infoIcon}>\n              <Tooltip\n                title={\n                  'Squeeth is currently more expensive than usual. The strategy buys back squeeth to withdraw. You can still withdraw, but you will pay more.'\n                }\n              >\n                <InfoIcon fontSize=\"medium\" />\n              </Tooltip>\n            </div>\n            <Typography variant=\"caption\" className={classes.infoText}>\n              It is currently costly to withdraw. Consider withdrawing later.\n            </Typography>\n          </div>\n        ) : null}\n\n        {showPriceImpactWarning ? (\n          <div className={classes.notice}>\n            <div className={classes.infoIcon}>\n              <Tooltip\n                title={\n                  'High price impact means that you are losing a significant amount of value due to the size of your trade. Withdrawing a smaller size can reduce your price impact.'\n                }\n              >\n                <InfoIcon fontSize=\"medium\" />\n              </Tooltip>\n            </div>\n            <Typography variant=\"caption\" className={classes.infoText}>\n              High price impact. Try multiple smaller transactions or contact us through{' '}\n              <LinkWrapper href=\"https://tiny.cc/opyndiscord\">discord</LinkWrapper> about OTC\n            </Typography>\n          </div>\n        ) : null}\n\n        <Box display=\"flex\" flexDirection=\"column\" gridGap=\"12px\" marginTop=\"24px\">\n          <Box\n            display=\"flex\"\n            alignItems=\"center\"\n            justifyContent=\"space-between\"\n            gridGap=\"12px\"\n            className={classes.slippageContainer}\n          >\n            <Metric\n              label=\"Uniswap Fee\"\n              value={formatNumber(quote.poolFee) + '%'}\n              isSmall\n              flexDirection=\"row\"\n              justifyContent=\"space-between\"\n              gridGap=\"12px\"\n            />\n\n            <Box display=\"flex\" alignItems=\"center\" gridGap=\"12px\" flex=\"1\">\n              <Metric\n                label=\"Price Impact\"\n                value={formatNumber(quote.priceImpact) + '%'}\n                isSmall\n                flexDirection=\"row\"\n                justifyContent=\"space-between\"\n                gridGap=\"12px\"\n              />\n              <TradeSettings setSlippage={onChangeSlippage} slippage={new BigNumber(slippage)} />\n            </Box>\n          </Box>\n        </Box>\n\n        {isRestricted && <RestrictionInfo marginTop=\"24px\" />}\n\n        <Box marginTop=\"24px\">\n          {isRestricted ? (\n            <PrimaryButtonNew\n              fullWidth\n              variant=\"contained\"\n              onClick={selectWallet}\n              disabled={true}\n              id=\"bull-restricted-btn\"\n            >\n              {'Unavailable'}\n            </PrimaryButtonNew>\n          ) : !connected ? (\n            <PrimaryButtonNew\n              fullWidth\n              variant=\"contained\"\n              onClick={selectWallet}\n              disabled={false}\n              id=\"bull-select-wallet-btn\"\n            >\n              {'Connect Wallet'}\n            </PrimaryButtonNew>\n          ) : !supportedNetwork ? (\n            <PrimaryButtonNew fullWidth variant=\"contained\" disabled={true} id=\"bull-unsupported-network-btn\">\n              {'Unsupported Network'}\n            </PrimaryButtonNew>\n          ) : bullAllowance.lt(withdrawAmount) ? (\n            <PrimaryButtonNew\n              fullWidth\n              id=\"bull-deposit-btn\"\n              variant={'contained'}\n              onClick={onApproveClick}\n              disabled={quoteLoading || txLoading || !!withdrawError}\n            >\n              {!txLoading ? 'Approve' : <CircularProgress color=\"primary\" size=\"2rem\" />}\n            </PrimaryButtonNew>\n          ) : (\n            <PrimaryButtonNew\n              fullWidth\n              id=\"bull-deposit-btn\"\n              variant={'contained'}\n              onClick={onWithdrawClick}\n              disabled={quoteLoading || txLoading || !!withdrawError}\n            >\n              {!txLoading && !quoteLoading ? 'Withdraw' : <CircularProgress color=\"primary\" size=\"2rem\" />}\n            </PrimaryButtonNew>\n          )}\n        </Box>\n      </div>\n    </>\n  )\n}\n\nexport default BullWithdraw\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/BullTrade/index.tsx",
    "content": "import BigNumber from 'bignumber.js'\nimport React, { useCallback, useState } from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { PrimaryButtonNew } from '@components/Button'\nimport Confirmed, { ConfirmType } from '@components/Trade/Confirmed'\nimport { useTransactionStatus } from '@state/wallet/hooks'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport { addressesAtom } from '@state/positions/atoms'\nimport { ShutdownEmergencyWithdraw } from './ShutdownEmergencyWithdraw'\n\nexport enum BullTradeType {\n  Deposit = 'Deposit',\n  Withdraw = 'Withdraw',\n  Redeem = 'Redeem',\n}\n\nexport interface BullTransactionConfirmation {\n  status: boolean\n  amount: BigNumber\n  tradeType: BullTradeType\n  txId?: string\n}\n\nconst BullTrade: React.FC = () => {\n  const [confirmedTransactionData, setConfirmedTransactionData] = useState<BullTransactionConfirmation | undefined>()\n\n  const { confirmed, transactionData, resetTransactionData } = useTransactionStatus()\n  const { bullStrategy } = useAtomValue(addressesAtom)\n  const {\n    value: bullBalance,\n    loading: isBullBalanceLoading,\n    refetch: refetchBullBalance,\n  } = useTokenBalance(bullStrategy, 30, 18)\n\n  const onTxnConfirm = useCallback(\n    (data: BullTransactionConfirmation | undefined) => {\n      console.log('Tx on confirm', data, transactionData?.hash)\n      setConfirmedTransactionData(data)\n      refetchBullBalance()\n    },\n    [transactionData?.hash, refetchBullBalance],\n  )\n\n  const onClose = useCallback(() => {\n    setConfirmedTransactionData(undefined)\n    resetTransactionData()\n  }, [setConfirmedTransactionData, resetTransactionData])\n\n  const getConfirmationMessage = (data?: BullTransactionConfirmation) => {\n    if (!data) return ''\n\n    switch (data.tradeType) {\n      case BullTradeType.Deposit:\n        return `Deposited ${data.amount.toFixed(4)} ETH`\n      case BullTradeType.Withdraw:\n        return `Withdrawn ${data.amount.toFixed(4)} ETH`\n      case BullTradeType.Redeem:\n        return `Redeemed ZenBull for ${data.amount.toFixed(4)} WETH`\n      default:\n        return ''\n    }\n  }\n\n  return (\n    <>\n      {confirmed && confirmedTransactionData?.status ? (\n        <>\n          <Confirmed\n            confirmationMessage={getConfirmationMessage(confirmedTransactionData)}\n            txnHash={transactionData?.hash ?? ''}\n            confirmType={ConfirmType.BULL}\n          />\n          <PrimaryButtonNew fullWidth id=\"bull-close-btn\" variant=\"contained\" onClick={onClose}>\n            Close\n          </PrimaryButtonNew>\n        </>\n      ) : (\n        <ShutdownEmergencyWithdraw\n          onTxnConfirm={onTxnConfirm}\n          isLoadingBalance={isBullBalanceLoading}\n          bullBalance={bullBalance}\n          refetchBullBalance={refetchBullBalance}\n        />\n      )}\n    </>\n  )\n}\n\nexport default BullTrade\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/BullTrade/styles.ts",
    "content": "import { makeStyles, createStyles } from '@material-ui/core'\n\nexport const useZenBullStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(2),\n    },\n    tradeContainer: {\n      display: 'flex',\n      flexDirection: 'column',\n      marginTop: theme.spacing(2),\n    },\n    tabBackGround: {\n      position: 'sticky',\n      top: '0',\n      zIndex: 20,\n    },\n    notice: {\n      marginTop: theme.spacing(2.5),\n      padding: theme.spacing(2),\n      border: `1px solid #F3FF6C`,\n      borderRadius: theme.spacing(1),\n      display: 'flex',\n      background: 'rgba(243, 255, 108, 0.1)',\n      alignItems: 'center',\n    },\n    infoIcon: {\n      marginRight: theme.spacing(2),\n      color: '#F3FF6C',\n    },\n    subtitle: {\n      fontSize: '18px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n      lineHeight: '130%',\n    },\n    infoText: {\n      fontWeight: 500,\n      fontSize: '13px',\n    },\n    slippageContainer: {\n      [theme.breakpoints.down('xs')]: {\n        flexWrap: 'wrap',\n      },\n    },\n  }),\n)\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/MyPosition/PnL.tsx",
    "content": "import { Typography, Box, CircularProgress } from '@material-ui/core'\nimport React from 'react'\nimport clsx from 'clsx'\nimport ArrowDropUpIcon from '@material-ui/icons/ArrowDropUp'\nimport ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown'\nimport BigNumber from 'bignumber.js'\n\nimport useStyles from '@components/Strategies/styles'\nimport { formatNumber } from '@utils/formatter'\n\ninterface PnLProps {\n  isPnlLoading: Boolean\n  bullEthPnl: BigNumber\n  bullEthPnlPercent: BigNumber\n}\n\nconst PnL: React.FC<PnLProps> = ({ isPnlLoading, bullEthPnl, bullEthPnlPercent }) => {\n  const classes = useStyles()\n\n  if (isPnlLoading) {\n    return (\n      <Box display=\"flex\" alignItems=\"center\" gridGap=\"8px\">\n        <CircularProgress size=\"1rem\" className={classes.loadingSpinner} />\n        <Typography className={classes.text}>fetching pnl...</Typography>\n      </Box>\n    )\n  }\n\n  const isPnlPositive = bullEthPnl.isGreaterThanOrEqualTo(0)\n  const textClassName = clsx(\n    classes.description,\n    classes.textSemibold,\n    classes.textMonospace,\n    isPnlPositive ? classes.colorSuccess : classes.colorError,\n  )\n\n  return (\n    <Box display=\"flex\" gridGap=\"8px\" flexWrap=\"wrap\" position=\"relative\" top=\"2px\">\n      <Box display=\"flex\" gridGap=\"8px\">\n        <Box display=\"flex\" marginLeft=\"-6px\">\n          {isPnlPositive ? (\n            <ArrowDropUpIcon fontSize=\"small\" className={classes.colorSuccess} />\n          ) : (\n            <ArrowDropDownIcon fontSize=\"small\" className={classes.colorError} />\n          )}\n          <Typography className={textClassName}>{formatNumber(bullEthPnlPercent.toNumber()) + '%'}</Typography>\n        </Box>\n\n        <Typography className={textClassName}>\n          ({isPnlPositive && '+'}\n          {formatNumber(bullEthPnl.toNumber(), 4) + ' ETH'})\n        </Typography>\n      </Box>\n      <Typography className={classes.description}>since deposit</Typography>\n    </Box>\n  )\n}\n\nexport default PnL\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/MyPosition/index.tsx",
    "content": "import { Typography, Box } from '@material-ui/core'\nimport React, { memo } from 'react'\nimport clsx from 'clsx'\nimport { useAtomValue } from 'jotai'\nimport { Skeleton } from '@material-ui/lab'\n\nimport {\n  bullCurrentETHPositionAtom,\n  bullCurrentUSDCPositionAtom,\n  bullEthPnlAtom,\n  bullEthPnlPerctAtom,\n  bullPositionLoadedAtom,\n  isBullPositionRefetchingAtom,\n  bullFirstDepositTimestampAtom,\n} from '@state/bull/atoms'\nimport { formatCurrency, formatNumber } from '@utils/formatter'\nimport SharePnl from '@components/Strategies/SharePnl'\nimport PnL from './PnL'\nimport useStyles from '@components/Strategies/styles'\n\nconst BullPosition: React.FC = () => {\n  const bullPosition = useAtomValue(bullCurrentETHPositionAtom)\n  const bullUsdcPosition = useAtomValue(bullCurrentUSDCPositionAtom)\n  const bullEthPnL = useAtomValue(bullEthPnlAtom)\n  const bullEthPnlPerct = useAtomValue(bullEthPnlPerctAtom)\n  const firstDepositTimestamp = useAtomValue(bullFirstDepositTimestampAtom)\n\n  const classes = useStyles()\n\n  const loading = !useAtomValue(bullPositionLoadedAtom)\n  const isPositionRefetching = useAtomValue(isBullPositionRefetchingAtom)\n  const isPnlLoading = !bullEthPnL.isFinite()\n\n  if (bullPosition.isZero() && !isPositionRefetching) {\n    return null\n  }\n\n  if (loading || isPositionRefetching || isPnlLoading) {\n    return (\n      <Box display=\"flex\" flexDirection=\"column\" gridGap=\"12px\">\n        <Typography variant=\"h4\" className={classes.sectionTitle}>\n          My Zen Bull Position\n        </Typography>\n        <Skeleton width={'100%'} height={'80px'} style={{ transform: 'none' }} />\n      </Box>\n    )\n  }\n\n  return (\n    <Box display=\"flex\" flexDirection=\"column\" gridGap=\"12px\">\n      <div>\n        <Typography variant=\"h4\" className={classes.sectionTitle}>\n          My Zen Bull Position\n        </Typography>\n\n        <Box display=\"flex\" alignItems=\"baseline\" gridColumnGap=\"12px\" gridRowGap=\"2px\" flexWrap=\"wrap\" marginTop=\"6px\">\n          <Typography className={clsx(classes.heading, classes.textMonospace)}>\n            {formatNumber(bullPosition.toNumber(), 4) + ' ETH'}\n          </Typography>\n\n          <Typography className={clsx(classes.description, classes.textMonospace)}>\n            {formatCurrency(bullUsdcPosition.toNumber())}\n          </Typography>\n\n          <PnL isPnlLoading={isPnlLoading} bullEthPnl={bullEthPnL} bullEthPnlPercent={bullEthPnlPerct} />\n        </Box>\n      </div>\n\n      <SharePnl\n        isPnlLoading={isPnlLoading}\n        strategy=\"zenbull\"\n        pnl={bullEthPnlPerct.toNumber()}\n        firstDepositTimestamp={firstDepositTimestamp}\n      />\n    </Box>\n  )\n}\n\nexport default memo(BullPosition)\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/StrategyPerformance.tsx",
    "content": "import React, { useMemo } from 'react'\nimport { Box, Typography, Tooltip, TextField, InputLabel, TextFieldProps, Divider } from '@material-ui/core'\nimport HelpOutlineIcon from '@material-ui/icons/HelpOutline'\nimport { Skeleton } from '@material-ui/lab'\nimport clsx from 'clsx'\nimport { useAtom } from 'jotai'\nimport { useAtomValue } from 'jotai/utils'\nimport { DatePicker, MuiPickersUtilsProvider } from '@material-ui/pickers'\nimport DateFnsUtils from '@date-io/date-fns'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport HighchartsReact from 'highcharts-react-official'\nimport Highcharts from 'highcharts'\nimport differenceInCalendarDays from 'date-fns/differenceInCalendarDays'\n\nimport useStyles from '@components/Strategies/styles'\nimport {\n  bullStrategyFilterEndDateAtom,\n  bullStrategyFilterStartDateAtom,\n  useBullPnLChartData,\n  bullDepositedEthInEulerAtom,\n  bullCrabBalanceAtom,\n  bullEulerUSDCDebtAtom,\n} from '@state/bull/atoms'\nimport { crabStrategyVaultAtomV2, crabTotalSupplyV2Atom, crabUSDValueAtom } from '@state/crab/atoms'\nimport { BULL_START_DATE } from '@constants/index'\nimport { formatNumber } from '@utils/formatter'\nimport { pnlGraphOptions } from '@constants/diagram'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { useOnChainETHPrice } from '@hooks/useETHPrice'\nimport { toTokenAmount } from '@utils/calculations'\n\nconst useTextFieldStyles = makeStyles((theme) =>\n  createStyles({\n    labelRoot: {\n      color: '#8C8D8D',\n      fontSize: '14px',\n      fontWeight: 500,\n    },\n    inputRoot: {\n      padding: '10px 16px',\n      fontSize: '15px',\n      fontWeight: 500,\n      fontFamily: 'DM Mono',\n      width: '14ch',\n      border: '2px solid #303436',\n      borderRadius: '12px',\n    },\n    inputFocused: {\n      borderColor: theme.palette.primary.main,\n    },\n  }),\n)\n\nexport type ChartDataInfo = {\n  timestamp: number\n  bullEthPnl: number\n}\n\nconst CustomTextField: React.FC<TextFieldProps> = ({ inputRef, label, InputProps, id, variant, ...props }) => {\n  const classes = useTextFieldStyles()\n\n  return (\n    <Box display=\"flex\" flexDirection=\"column\" gridGap=\"4px\">\n      <InputLabel htmlFor={id} classes={{ root: classes.labelRoot }}>\n        {label}\n      </InputLabel>\n      <TextField\n        id={id}\n        InputProps={{\n          classes: {\n            root: classes.inputRoot,\n            focused: classes.inputFocused,\n          },\n          disableUnderline: true,\n          ...InputProps,\n        }}\n        {...props}\n      />\n    </Box>\n  )\n}\n\nconst PerformanceMetric: React.FC<{ label: string; value: number }> = ({ label, value }) => {\n  const classes = useStyles()\n\n  return (\n    <Box display=\"flex\" justifyContent=\"flex-end\" gridGap=\"6px\">\n      <Typography className={classes.textSmall}>{label}</Typography>\n\n      <Box minWidth=\"6ch\" display=\"flex\" justifyContent=\"flex-end\">\n        <Typography\n          className={clsx(\n            classes.textSmall,\n            classes.textMonospace,\n            value >= 0 ? classes.colorSuccess : classes.colorError,\n          )}\n        >\n          {value >= 0 && '+'}\n          {formatNumber(value)}%\n        </Typography>\n      </Box>\n    </Box>\n  )\n}\n\nconst TooltipTitle = () => (\n  <>\n    {'Annualized return based on selected dates.'}\n    <br />\n    {'Past performance does not indicate future returns.'}\n  </>\n)\n\ninterface StrategyPerformanceProps {\n  strategyPnLSeries: Array<[number, number]>\n  tvl: number\n}\n\nconst StrategyPerformance: React.FC<StrategyPerformanceProps> = ({ strategyPnLSeries, tvl }) => {\n  const [startDate, setStartDate] = useAtom(bullStrategyFilterStartDateAtom)\n  const [endDate, setEndDate] = useAtom(bullStrategyFilterEndDateAtom)\n\n  const series = [\n    {\n      name: 'Bull/ETH 🧘🐂 % Return',\n      yAxis: 0,\n      data: strategyPnLSeries,\n      tooltip: {\n        valueDecimals: 2,\n        valueSuffix: '%',\n      },\n      color: '#70E3F6',\n    },\n  ]\n\n  const axes = {\n    yAxis: [\n      {\n        // Left yAxis\n        title: {\n          text: '',\n        },\n        labels: {\n          style: {\n            color: '#BABBBB',\n          },\n        },\n        gridLineColor: 'rgba(221,221,221,0.1)',\n      },\n    ],\n  }\n\n  const chartOptions = useAppMemo(() => {\n    const { chart, ...restOptions } = pnlGraphOptions\n\n    return {\n      ...restOptions,\n      ...axes,\n      chart: {\n        ...chart,\n        marginLeft: '48',\n      },\n      series: series,\n    }\n  })\n\n  const classes = useStyles()\n\n  const numberOfDays = differenceInCalendarDays(endDate, startDate)\n  const hasData = strategyPnLSeries?.length > 0\n\n  const historicalReturns = hasData ? strategyPnLSeries[strategyPnLSeries.length - 1][1] : 0\n  const annualizedReturns = useMemo(() => {\n    return (Math.pow(1 + historicalReturns / 100, 365 / numberOfDays) - 1) * 100\n  }, [historicalReturns, numberOfDays])\n\n  return (\n    <>\n      <Box display=\"flex\" alignItems=\"baseline\" gridColumnGap=\"12px\" gridRowGap=\"4px\" flexWrap=\"wrap\">\n        <Typography\n          variant=\"h2\"\n          className={clsx(\n            classes.heading,\n            classes.textMonospace,\n            annualizedReturns >= 0 ? classes.colorSuccess : classes.colorError,\n          )}\n        >\n          {annualizedReturns >= 0 && '+'}\n          {formatNumber(annualizedReturns)}%\n        </Typography>\n\n        <Box display=\"flex\" alignItems=\"baseline\" gridGap=\"12px\">\n          <Typography className={classes.description}>Annualized ETH Return</Typography>\n\n          <Box position=\"relative\" top=\"3px\">\n            <Tooltip title={<TooltipTitle />}>\n              <HelpOutlineIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n          </Box>\n        </Box>\n      </Box>\n\n      <Box display=\"flex\" gridGap=\"12px\">\n        <Typography className={clsx(classes.description, classes.textMonospace)}>\n          {formatNumber(tvl, 0) + ' ETH'}\n        </Typography>\n        <Typography className={classes.description}>Open Interest</Typography>\n      </Box>\n\n      <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"flex-end\" gridGap=\"12px\" flexWrap=\"wrap\">\n        <div>\n          <MuiPickersUtilsProvider utils={DateFnsUtils}>\n            <Box display=\"flex\" alignItems=\"center\" gridGap=\"16px\" marginTop=\"16px\">\n              <DatePicker\n                id=\"start-date-strategy-performance\"\n                label=\"Start Date\"\n                placeholder=\"MM/DD/YYYY\"\n                format={'MM/dd/yyyy'}\n                value={startDate}\n                minDate={BULL_START_DATE}\n                onChange={(d) => setStartDate(d || new Date())}\n                animateYearScrolling={false}\n                autoOk={true}\n                clearable\n                TextFieldComponent={CustomTextField}\n              />\n\n              <Divider orientation=\"horizontal\" className={classes.divider} />\n\n              <DatePicker\n                id=\"end-date-strategy-performance\"\n                label=\"End Date\"\n                placeholder=\"MM/DD/YYYY\"\n                format={'MM/dd/yyyy'}\n                value={endDate}\n                minDate={startDate}\n                onChange={(d) => setEndDate(d || new Date())}\n                animateYearScrolling={false}\n                autoOk={true}\n                clearable\n                TextFieldComponent={CustomTextField}\n              />\n            </Box>\n          </MuiPickersUtilsProvider>\n        </div>\n\n        <Box display=\"flex\" flexDirection=\"column\" gridGap=\"4px\" flex=\"1\" flexBasis=\"200px\">\n          <PerformanceMetric label=\"Historical Returns\" value={historicalReturns} />\n          <PerformanceMetric label=\"Annualized\" value={annualizedReturns} />\n        </Box>\n      </Box>\n\n      <Box marginTop=\"12px\">\n        <HighchartsReact highcharts={Highcharts} options={chartOptions} />\n      </Box>\n    </>\n  )\n}\n\nconst Wrapper: React.FC = () => {\n  const ethDepositedInEuler = useAtomValue(bullDepositedEthInEulerAtom)\n  const bullCrabBalance = useAtomValue(bullCrabBalanceAtom)\n  const vault = useAtomValue(crabStrategyVaultAtomV2)\n  const crabSupply = useAtomValue(crabTotalSupplyV2Atom)\n  const eulerUSDCDebt = useAtomValue(bullEulerUSDCDebtAtom)\n  const crabUSDValue = useAtomValue(crabUSDValueAtom)\n  const ethPrice = useOnChainETHPrice()\n  const query = useBullPnLChartData()\n\n  const strategyPnLSeries = query?.data?.data.map((x: ChartDataInfo) => [x.timestamp * 1000, x.bullEthPnl])\n  const isLoadingPnLSeries = typeof strategyPnLSeries === 'undefined'\n\n  // tvl = ethInEuler + (crabInBull * crabPriceInETH) - (debtInEuler / ethPrice)\n  const crabPriceInETH = toTokenAmount(crabUSDValue, 18).div(ethPrice)\n  const collateralValue = ethDepositedInEuler.plus(vault?.collateralAmount.times(bullCrabBalance).div(crabSupply) ?? 0)\n  const tvl = collateralValue.integerValue()\n  const isLoadingTVL = crabUSDValue.isZero() || ethPrice.isZero()\n\n  const isLoading = isLoadingPnLSeries || isLoadingTVL\n\n  const classes = useStyles()\n\n  return (\n    <Box display=\"flex\" flexDirection=\"column\" gridGap=\"8px\">\n      <Typography variant=\"h3\" className={classes.sectionTitle}>\n        Strategy Performance\n      </Typography>\n\n      {isLoading ? (\n        <div className={classes.shimmer}>\n          <Skeleton width={'100%'} height={25} style={{ transform: 'none' }} />\n          <Skeleton width={'100%'} height={30} style={{ transform: 'none' }} />\n          <Skeleton width={'100%'} height={300} style={{ transform: 'none' }} />\n        </div>\n      ) : (\n        <StrategyPerformance strategyPnLSeries={strategyPnLSeries} tvl={tvl.toNumber()} />\n      )}\n    </Box>\n  )\n}\n\nexport default Wrapper\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Bull/index.tsx",
    "content": "import React, { useEffect } from 'react'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\n\nimport { useInitBullRecoveryStrategy } from '@state/bull/hooks'\nimport { useSetStrategyDataV2, useCurrentCrabPositionValueV2 } from '@state/crab/hooks'\nimport { useDisconnectWallet } from '@state/wallet/hooks'\nimport About from './About'\nimport BullTrade from './BullTrade'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      marginTop: '32px',\n      display: 'flex',\n      justifyContent: 'center',\n      gridGap: '96px',\n      flexWrap: 'wrap',\n      [theme.breakpoints.down('md')]: {\n        gridGap: '40px',\n      },\n    },\n    leftColumn: {\n      flex: 1,\n      minWidth: '480px',\n      [theme.breakpoints.down('xs')]: {\n        minWidth: '320px',\n      },\n    },\n    rightColumn: {\n      flexBasis: '452px',\n      [theme.breakpoints.down('xs')]: {\n        flex: '1',\n      },\n    },\n    infoContainer: {\n      display: 'flex',\n      flexDirection: 'column',\n      gap: '72px',\n    },\n    tradeSection: {\n      border: '1px solid #242728',\n      boxShadow: '0px 4px 40px rgba(0, 0, 0, 0.25)',\n      borderRadius: theme.spacing(1),\n      padding: '32px 24px',\n    },\n  }),\n)\n\nconst Bull: React.FC = () => {\n  const setStrategyDataV2 = useSetStrategyDataV2()\n  const disconnectWallet = useDisconnectWallet()\n  const classes = useStyles()\n\n  useCurrentCrabPositionValueV2()\n  useInitBullRecoveryStrategy()\n\n  useEffect(() => {\n    setStrategyDataV2()\n  }, [setStrategyDataV2])\n\n  useEffect(() => {\n    // make sure user has specifically connected the wallet to zenbull before\n    const hasConnectedToZenbullBefore = window.localStorage.getItem('walletConnectedToZenbull') === 'true'\n    if (!hasConnectedToZenbullBefore) {\n      disconnectWallet()\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [])\n\n  return (\n    <>\n      <div className={classes.container}>\n        <div className={classes.leftColumn}>\n          <div className={classes.infoContainer}>\n            {/* <MyPosition /> */}\n            {/* <StrategyPerformance /> */}\n            <About />\n          </div>\n        </div>\n        <div className={classes.rightColumn}>\n          <div className={classes.tradeSection}>\n            <BullTrade />\n          </div>\n        </div>\n      </div>\n    </>\n  )\n}\n\nexport default Bull\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/About/AdvancedMetrics.tsx",
    "content": "import React, { useState } from 'react'\nimport { Box, Fade, Typography } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp'\nimport KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown'\nimport { useAtomValue } from 'jotai'\n\nimport Metric, { MetricLabel } from '@components/Metric'\nimport { TextButton } from '@components/Button'\nimport {\n  impliedVolAtom,\n  osqthRefVolAtom,\n  currentImpliedFundingAtom,\n  impliedVolatilityShutdownAtom,\n  currentImpliedFundingShutdownAtom,\n} from '@state/controller/atoms'\nimport { formatNumber } from '@utils/formatter'\nimport { Tooltips } from '@constants/enums'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { SITE_EVENTS } from '@utils/amplitude'\n\nconst useStyles = makeStyles(() =>\n  createStyles({\n    button: {\n      color: 'rgba(255, 255, 255, 0.5)',\n    },\n    buttonText: {\n      color: 'rgba(255, 255, 255, 0.5)',\n      fontSize: '15px',\n      fontWeight: 500,\n      marginRight: '4px',\n    },\n  }),\n)\n\nconst AdvancedMetrics: React.FC = () => {\n  const [showAdvanced, setShowAdvanced] = useState(false)\n\n  const impliedVolatilityShutdown = useAtomValue(impliedVolatilityShutdownAtom)\n  const osqthRefVol = useAtomValue(osqthRefVolAtom)\n  const currentImpliedFundingShutdown = useAtomValue(currentImpliedFundingShutdownAtom)\n  const { track } = useAmplitude()\n\n  const classes = useStyles()\n\n  const impliedVolatilityShutdownPercent = impliedVolatilityShutdown * 100\n\n  return (\n    <div>\n      <TextButton\n        className={classes.button}\n        onClick={() => {\n          setShowAdvanced(!showAdvanced)\n          !showAdvanced ? track(SITE_EVENTS.SEE_ADVANCED_METRICS_CRAB) : null\n        }}\n      >\n        <Typography className={classes.buttonText}>Advanced</Typography>{' '}\n        {showAdvanced ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}\n      </TextButton>\n\n      <Fade in={showAdvanced}>\n        {showAdvanced ? (\n          <Box display=\"flex\" justifyContent=\"space-between\" gridGap=\"12px\" marginTop=\"16px\" flexWrap=\"wrap\">\n            <Metric\n              label={\n                <MetricLabel\n                  label=\"Daily Premium \"\n                  tooltipTitle={`${Tooltips.StrategyEarnFunding}. ${Tooltips.CurrentImplFunding}`}\n                />\n              }\n              gridGap=\"4px\"\n              value={formatNumber(currentImpliedFundingShutdown * 100) + '%'}\n            />\n            <Metric\n              label={<MetricLabel label=\"Implied Volatility \" tooltipTitle={Tooltips.ImplVol} />}\n              gridGap=\"4px\"\n              value={`${formatNumber(impliedVolatilityShutdownPercent)}%`}\n            />\n            <Metric\n              label={<MetricLabel label=\"Reference Volatility\" tooltipTitle={Tooltips.osqthRefVol} />}\n              gridGap=\"4px\"\n              value={`${formatNumber(osqthRefVol)}%`}\n            />\n          </Box>\n        ) : (\n          <div></div>\n        )}\n      </Fade>\n    </div>\n  )\n}\n\nexport default AdvancedMetrics\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/About/NextRebalanceTimer.tsx",
    "content": "import React, { useEffect, useState } from 'react'\nimport { Typography } from '@material-ui/core'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport { intervalToDuration } from 'date-fns'\nimport { sortBy } from 'lodash'\n\nconst padZero = (number: number, padding: number): String => {\n  return `${number}`.padStart(padding, '0')\n}\n\nconst getNextHedgeDate = (now: Date): Date => {\n  // hedges every monday, wednesday, friday at 16:30 UTC\n\n  // next monday at 16:30 UTC\n  const nextMondayHedge = new Date(now)\n  nextMondayHedge.setUTCDate(nextMondayHedge.getUTCDate() + ((1 + 7 - nextMondayHedge.getUTCDay()) % 7 || 7))\n  nextMondayHedge.setUTCHours(16, 30, 0, 0)\n\n  // next wednesday at 16:30 UTC\n  const nextWednesdayHedge = new Date(now)\n  nextWednesdayHedge.setUTCDate(nextWednesdayHedge.getUTCDate() + ((3 + 7 - nextWednesdayHedge.getUTCDay()) % 7 || 7))\n  nextWednesdayHedge.setUTCHours(16, 30, 0, 0)\n\n  // next wednesday at 16:30 UTC\n  const nextFridayHedge = new Date(now)\n  nextFridayHedge.setUTCDate(nextFridayHedge.getUTCDate() + ((5 + 7 - nextFridayHedge.getUTCDay()) % 7 || 7))\n  nextFridayHedge.setUTCHours(16, 30, 0, 0)\n\n  // today at 16:30 UTC\n  const todayHedge = new Date(now)\n  todayHedge.setUTCDate(todayHedge.getUTCDate())\n  todayHedge.setUTCHours(16, 30, 0, 0)\n\n  const isMondayInUTC = now.getUTCDay() === 1\n  const isWednesdayInUTC = now.getUTCDay() === 3\n  const isFridayInUTC = now.getUTCDay() === 5\n  const hasHedgeTimePassedInUTC = now.getUTCHours() > 16 || (now.getUTCHours() === 16 && now.getUTCMinutes() >= 30)\n\n  // if today is monday, wednesday, friday and time is before 16:30 UTC, use today's hedge date\n  const comingMondayHedge = isMondayInUTC && !hasHedgeTimePassedInUTC ? todayHedge : nextMondayHedge\n  const comingWednesdayHedge = isWednesdayInUTC && !hasHedgeTimePassedInUTC ? todayHedge : nextWednesdayHedge\n  const comingFridayHedge = isFridayInUTC && !hasHedgeTimePassedInUTC ? todayHedge : nextFridayHedge\n\n  // find closest hedge date\n  const nextHedges = sortBy([comingMondayHedge, comingWednesdayHedge, comingFridayHedge], (date) => date.getTime())\n  return nextHedges[0]\n}\n\nconst useStyles = makeStyles(() =>\n  createStyles({\n    label: {\n      fontSize: '15px',\n      color: 'rgba(255, 255, 255, 0.5)',\n      fontWeight: 500,\n      textAlign: 'right',\n    },\n    value: {\n      fontSize: '20px',\n      color: 'rgba(255, 255, 255, 1)',\n      fontWeight: 500,\n      fontFamily: 'DM Mono',\n      textAlign: 'right',\n    },\n  }),\n)\n\nconst NextRebalanceTimer: React.FC = () => {\n  const [timeLeft, setTimeLeft] = useState('')\n  const classes = useStyles()\n\n  useEffect(() => {\n    const interval = setInterval(() => {\n      const now = new Date()\n      const nextHedgeDate = getNextHedgeDate(now)\n\n      const duration = intervalToDuration({ start: now, end: nextHedgeDate })\n      const days = padZero(duration.days ?? 0, 2)\n      const hours = padZero(duration.hours ?? 0, 2)\n      const minutes = padZero(duration.minutes ?? 0, 2)\n      const seconds = padZero(duration.seconds ?? 0, 2)\n\n      const result = `${days}D ${hours}H ${minutes}M ${seconds}S`\n      setTimeLeft(result)\n    }, 1000)\n\n    return () => clearInterval(interval)\n  }, [])\n\n  return (\n    <div>\n      <Typography className={classes.label}>Next hedge in</Typography>\n      <Typography className={classes.value} variant=\"subtitle2\">\n        {timeLeft}\n      </Typography>\n    </div>\n  )\n}\n\nexport default NextRebalanceTimer\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/About/ProfitabilityChart.tsx",
    "content": "import React, { useMemo } from 'react'\nimport { useAtomValue } from 'jotai'\nimport {\n  LineChart,\n  Line,\n  XAxis,\n  YAxis,\n  ResponsiveContainer,\n  ReferenceDot,\n  ReferenceArea,\n  Label,\n  Tooltip,\n  TooltipProps,\n} from 'recharts'\nimport { Box, useTheme, Fade, Typography, useMediaQuery } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport { makeStyles } from '@material-ui/core/styles'\nimport { Skeleton } from '@material-ui/lab'\n\nimport { currentImpliedFundingAtom, currentImpliedFundingShutdownAtom } from '@state/controller/atoms'\nimport { ethPriceAtLastHedgeAtomV2 } from '@state/crab/atoms'\nimport { toTokenAmount } from '@utils/calculations'\nimport { useOnChainETHPrice } from '@hooks/useETHPrice'\nimport { formatNumber, formatCurrency } from '@utils/formatter'\n\nconst useTooltipStyles = makeStyles(() => ({\n  root: {\n    backgroundColor: 'rgba(247,247,247,0.85)',\n    padding: '4px 8px',\n  },\n  label: {\n    fontSize: '12px',\n    fontFamily: 'DM Mono',\n    color: 'rgb(51, 51, 51)',\n  },\n  value: {\n    fontSize: '12px',\n    fontFamily: 'DM Mono',\n    color: 'rgb(51, 51, 51)',\n  },\n}))\n\nconst CustomTooltip: React.FC<TooltipProps<any, any>> = ({ active, payload }) => {\n  const classes = useTooltipStyles()\n\n  if (active && payload && payload.length) {\n    const strategyReturn = payload[0].payload.strategyReturn\n    const ethPrice = payload[0].payload.ethPrice\n\n    return (\n      <div className={classes.root}>\n        <Typography className={classes.label}>\n          <b>{formatCurrency(ethPrice)}</b> {`ETH/USDC`}\n        </Typography>\n        <Typography className={classes.value}>\n          {`Crab return: `}\n          <b>{formatNumber(strategyReturn)}%</b>\n        </Typography>\n      </div>\n    )\n  }\n\n  return null\n}\n\nconst CustomActiveDot = (props: any) => {\n  const { cx, cy, value, fill } = props\n\n  if (!value) {\n    return null\n  }\n  return <rect x={cx - 1.5} y={cy - 7} width={3} height={14} strokeWidth={0} fill={fill} />\n}\n\nconst CandyBar = (props: any) => {\n  const { x, y, width, height, fill, stroke } = props\n\n  const barX = x\n  const barY = height < 0 ? y + height : y\n  const barWidth = width\n  const barHeight = Math.abs(height)\n\n  return (\n    <>\n      <rect x={barX} y={barY} width={barWidth} height={barHeight} fill={fill} />\n      <rect x={barX} y={barY} width={1} height={barHeight} fill={stroke} />\n      <rect x={barX + barWidth} y={barY} width={1} height={barHeight} fill={stroke} />\n    </>\n  )\n}\n\nfunction getStrategyReturn(funding: number, ethReturn: number) {\n  return (funding - Math.pow(ethReturn, 2)) * 100\n}\n\n// generate data from -percentRange to +percentRange\nconst getDataPoints = (funding: number, ethPriceAtLastHedge: number, percentRange: number) => {\n  const dataPoints = []\n\n  const starting = new BigNumber(-percentRange)\n  const increment = new BigNumber(0.05)\n  const ending = new BigNumber(percentRange)\n\n  let current = starting\n  while (current.lte(ending)) {\n    const ethReturn = current.div(100).toNumber()\n\n    const strategyReturn = getStrategyReturn(funding, ethReturn)\n    const strategyReturnPositive = strategyReturn >= 0 ? strategyReturn : null\n    const strategyReturnNegative = strategyReturn < 0 ? strategyReturn : null\n\n    dataPoints.push({\n      ethPrice: ethPriceAtLastHedge + ethReturn * ethPriceAtLastHedge,\n      strategyReturn,\n      strategyReturnPositive,\n      strategyReturnNegative,\n    })\n\n    current = current.plus(increment)\n  }\n\n  return dataPoints\n}\n\nconst Chart: React.FC<{ currentImpliedFunding: number }> = ({ currentImpliedFunding }) => {\n  const ethPriceAtLastHedgeValue = useAtomValue(ethPriceAtLastHedgeAtomV2)\n  const ethPrice = useOnChainETHPrice()\n\n  const funding = 2 * currentImpliedFunding // for 2 days\n  const ethPriceAtLastHedge = Number(toTokenAmount(ethPriceAtLastHedgeValue, 18))\n  const currentEthPrice = Number(ethPrice)\n  const profitableBoundsPercent = Math.sqrt(funding)\n  const lowerPriceBandForProfitability = ethPriceAtLastHedge - profitableBoundsPercent * ethPriceAtLastHedge\n  const upperPriceBandForProfitability = ethPriceAtLastHedge + profitableBoundsPercent * ethPriceAtLastHedge\n\n  const data = useMemo(() => {\n    const percentRange = profitableBoundsPercent * 4 * 100 // 4x the profitable move percent\n    return getDataPoints(funding, ethPriceAtLastHedge, percentRange)\n  }, [funding, ethPriceAtLastHedge, profitableBoundsPercent])\n\n  const getStrategyReturnForETHPrice = (ethPriceVal: number) => {\n    const ethReturn = (ethPriceVal - ethPriceAtLastHedge) / ethPriceAtLastHedge\n    return getStrategyReturn(funding, ethReturn)\n  }\n\n  const theme = useTheme()\n  const successColor = theme.palette.success.main\n  const errorColor = theme.palette.error.main\n\n  const isMobileBreakpoint = useMediaQuery(theme.breakpoints.down('xs'))\n\n  const currentStrategyReturn = getStrategyReturnForETHPrice(currentEthPrice)\n\n  return (\n    <Fade in={true}>\n      <Box height={300} width=\"100%\" display=\"flex\" justifyContent=\"flex-start\">\n        <ResponsiveContainer width=\"100%\" height=\"100%\">\n          <LineChart data={data}>\n            <defs>\n              <marker id=\"arrowhead\" markerWidth=\"10\" markerHeight=\"10\" refX=\"5\" refY=\"5\" orient=\"auto-start-reverse\">\n                <polygon points=\"0 0, 10 5, 0 10\" fill=\"#fff\" opacity=\"0.5\" />\n              </marker>\n\n              <marker id=\"dot\" viewBox=\"0 0 16 16\" refX=\"8\" refY=\"8\" markerWidth=\"8\" markerHeight=\"8\">\n                <circle cx=\"8\" cy=\"8\" r=\"8\" fill=\"#ffffff80\" />\n              </marker>\n\n              {/* https://stackoverflow.com/a/12263962/5733330 */}\n              <filter x=\"0\" y=\"0\" width=\"1\" height=\"1\" id=\"removebackground\">\n                <feFlood floodColor={theme.palette.background.default} />\n                <feComposite in=\"SourceGraphic\" />\n              </filter>\n            </defs>\n\n            <XAxis\n              height={1}\n              type=\"number\"\n              dataKey=\"ethPrice\"\n              domain={isMobileBreakpoint ? ['dataMin - 20', 'dataMax + 20'] : ['dataMin - 40', 'dataMax + 200']}\n              tick={false}\n              strokeDasharray=\"5,5\"\n              strokeOpacity=\"0.5\"\n              stroke=\"#fff\"\n              markerEnd=\"url(#arrowhead)\"\n              markerStart=\"url(#dot)\"\n            >\n              <Label\n                value=\"ETH Price\"\n                position=\"insideBottomRight\"\n                offset={14}\n                fill=\"#ffffff80\"\n                enableBackground={'fill'}\n              />\n            </XAxis>\n            <YAxis\n              width={1}\n              type=\"number\"\n              dataKey=\"strategyReturn\"\n              tick={false}\n              domain={isMobileBreakpoint ? ['dataMin - 1.25', 'dataMax + 1.25'] : ['dataMin - 0.5', 'dataMax + 0.5']}\n              strokeDasharray=\"5,5\"\n              strokeOpacity=\"0.5\"\n              stroke=\"#fff\"\n              markerStart=\"url(#arrowhead)\"\n              yAxisId=\"0\"\n            >\n              <Label\n                value={isMobileBreakpoint ? 'Crab' : 'Crab Strategy'}\n                position=\"insideTopLeft\"\n                offset={14}\n                fill=\"#ffffff80\"\n              />\n            </YAxis>\n\n            <ReferenceArea\n              shape={<CandyBar />}\n              x1={lowerPriceBandForProfitability}\n              x2={upperPriceBandForProfitability}\n              fill={successColor + '16'}\n              stroke={successColor}\n            />\n\n            <Tooltip\n              wrapperStyle={{ outline: 'none' }}\n              cursor={{ stroke: '#fff', strokeOpacity: '0.5', strokeWidth: 1 }}\n              content={<CustomTooltip />}\n            />\n\n            <Line\n              type=\"monotone\"\n              dataKey=\"strategyReturnNegative\"\n              stroke={errorColor}\n              strokeWidth={1}\n              dot={false}\n              isAnimationActive={false}\n              activeDot={<CustomActiveDot />}\n            />\n            <Line\n              type=\"monotone\"\n              dataKey=\"strategyReturnPositive\"\n              stroke={successColor}\n              strokeWidth={1}\n              dot={false}\n              isAnimationActive={false}\n              activeDot={<CustomActiveDot />}\n            />\n\n            <ReferenceDot\n              x={lowerPriceBandForProfitability}\n              y={getStrategyReturnForETHPrice(lowerPriceBandForProfitability)}\n              r={0}\n            >\n              <Label\n                fontFamily={'DM Mono'}\n                fontWeight={500}\n                value={'$' + formatNumber(lowerPriceBandForProfitability, 0)}\n                position=\"insideBottomRight\"\n                offset={8}\n                fill=\"#ffffffcc\"\n              />\n            </ReferenceDot>\n            <ReferenceDot\n              x={upperPriceBandForProfitability}\n              y={getStrategyReturnForETHPrice(upperPriceBandForProfitability)}\n              r={0}\n            >\n              <Label\n                fontFamily={'DM Mono'}\n                fontWeight={500}\n                value={'$' + formatNumber(upperPriceBandForProfitability, 0)}\n                position=\"insideBottomLeft\"\n                offset={8}\n                fill=\"#ffffffcc\"\n              />\n            </ReferenceDot>\n\n            <ReferenceDot\n              x={currentEthPrice}\n              y={currentStrategyReturn}\n              r={5}\n              fill={currentStrategyReturn < 0 ? errorColor : successColor}\n              strokeWidth={0}\n            >\n              <Label\n                fontFamily=\"DM Mono\"\n                fontWeight={500}\n                value={'$' + formatNumber(currentEthPrice, 0)}\n                position=\"insideTop\"\n                offset={20}\n                fill={currentStrategyReturn < 0 ? errorColor : successColor}\n                filter=\"url(#removebackground)\"\n              />\n            </ReferenceDot>\n          </LineChart>\n        </ResponsiveContainer>\n      </Box>\n    </Fade>\n  )\n}\n\nfunction ChartWrapper() {\n  const currentImpliedFunding = useAtomValue(currentImpliedFundingShutdownAtom)\n\n  if (currentImpliedFunding === 0) {\n    return (\n      <Box display=\"flex\" alignItems=\"center\" justifyContent=\"center\">\n        <Skeleton height={300} width={'100%'} />\n      </Box>\n    )\n  }\n  return <Chart currentImpliedFunding={currentImpliedFunding} />\n}\n\nexport default ChartWrapper\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/About/index.tsx",
    "content": "import React from 'react'\nimport { Box, Typography } from '@material-ui/core'\nimport clsx from 'clsx'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\n\nimport NextRebalanceTimer from './NextRebalanceTimer'\nimport ProfitabilityChart from './ProfitabilityChart'\nimport AdvancedMetrics from './AdvancedMetrics'\nimport useStyles from '@components/Strategies/styles'\nimport { LinkWrapper } from '@components/LinkWrapper'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { SITE_EVENTS } from '@utils/amplitude'\n\nconst useAboutStyles = makeStyles((theme) =>\n  createStyles({\n    timerContainer: {\n      position: 'absolute',\n      top: '10px',\n      right: '0',\n\n      [theme.breakpoints.down('sm')]: {\n        position: 'relative',\n        top: '0px',\n        right: '0',\n        marginBottom: '16px',\n      },\n    },\n  }),\n)\nconst gitBookLink = 'https://opyn.gitbook.io/opyn-strategies/crab-strategy/introduction'\nconst About: React.FC = () => {\n  const classes = useStyles()\n  const aboutClasses = useAboutStyles()\n  const { track } = useAmplitude()\n\n  return (\n    <div>\n      <Box display=\"flex\" flexDirection=\"column\" gridGap=\"8px\">\n        <Typography variant=\"h3\" className={classes.sectionTitle}>\n          About Crab\n        </Typography>\n        <Typography variant=\"h2\" className={classes.heading}>\n          Stack USDC when ETH is calm\n        </Typography>\n\n        <Typography className={clsx(classes.text, classes.textMargin)}>\n          In general, Crab earns USDC returns except when there is high ETH volatility in the market, when it may draw\n          down. Most often, the strategy stacks USDC if ETH is within the below bands at the next hedge.{' '}\n          <LinkWrapper\n            href={gitBookLink}\n            onClick={() => track(SITE_EVENTS.CLICK_LEARN_MORE_CRAB, { link: gitBookLink })}\n          >\n            Learn more\n          </LinkWrapper>\n        </Typography>\n      </Box>\n\n      {/* <Box position=\"relative\" marginTop=\"32px\">\n        <div className={aboutClasses.timerContainer}>\n          <NextRebalanceTimer />\n        </div>\n        <ProfitabilityChart />\n      </Box> */}\n\n      <Box marginTop=\"16px\">\n        <AdvancedMetrics />\n      </Box>\n    </div>\n  )\n}\n\nexport default About\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CapDetails.tsx",
    "content": "import CustomLinearProgress from '@components/CustomProgress'\nimport { Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport BigNumber from 'bignumber.js'\nimport React from 'react'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(2, 5),\n      background: theme.palette.background.stone,\n      borderRadius: theme.spacing(2),\n      width: '100%',\n    },\n    vaultDetails: {\n      display: 'flex',\n      justifyContent: 'space-between',\n    },\n    vaultProgress: {\n      marginTop: theme.spacing(2),\n    },\n  }),\n)\n\ntype CapType = {\n  maxCap: BigNumber\n  depositedAmount: BigNumber\n}\n\nconst CapDetails: React.FC<CapType> = ({ maxCap, depositedAmount }) => {\n  const classes = useStyles()\n\n  return (\n    <div className={classes.container}>\n      <div className={classes.vaultDetails}>\n        <div>\n          <Typography variant=\"body2\" color=\"textSecondary\">\n            Strategy Deposits\n          </Typography>\n          <Typography variant=\"h6\">\n            {depositedAmount.gt(maxCap)\n              ? Number(maxCap.toFixed(4)).toLocaleString()\n              : Number(depositedAmount.toFixed(4)).toLocaleString()}{' '}\n            ETH\n          </Typography>\n        </div>\n        <div>\n          <Typography variant=\"body2\" color=\"textSecondary\">\n            Strategy Capacity\n          </Typography>\n          <Typography variant=\"h6\">{Number(maxCap.toFixed(4)).toLocaleString()} ETH</Typography>\n        </div>\n      </div>\n      <div className={classes.vaultProgress}>\n        <CustomLinearProgress\n          variant=\"determinate\"\n          value={\n            depositedAmount.gt(maxCap)\n              ? maxCap.div(maxCap).times(100).toNumber()\n              : depositedAmount.div(maxCap).times(100).toNumber()\n          }\n        />\n      </div>\n    </div>\n  )\n}\n\nexport default CapDetails\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CapDetailsV2.tsx",
    "content": "import { Typography, Box } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport BigNumber from 'bignumber.js'\nimport React from 'react'\nimport clsx from 'clsx'\n\nimport { CustomLinearProgressNew } from '@components/CustomProgress'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      width: '100%',\n    },\n    label: {\n      fontSize: '14px',\n      fontWeight: 400,\n    },\n    value: {\n      fontFamily: 'DM Mono',\n    },\n    green: {\n      color: theme.palette.success.main,\n    },\n  }),\n)\n\ntype CapType = {\n  maxCap: BigNumber\n  depositedAmount: BigNumber\n}\n\nconst CapDetails: React.FC<CapType> = ({ maxCap, depositedAmount }) => {\n  const classes = useStyles()\n\n  return (\n    <div className={classes.container}>\n      <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" marginBottom=\"8px\">\n        <Typography className={clsx(classes.label, classes.value, classes.green)}>\n          {depositedAmount.gt(maxCap)\n            ? Number(maxCap.toFixed(4)).toLocaleString()\n            : Number(depositedAmount.toFixed(4)).toLocaleString()}{' '}\n          ETH\n        </Typography>\n\n        <Typography className={clsx(classes.label, classes.value)}>\n          {Number(maxCap.toFixed(4)).toLocaleString()} ETH\n        </Typography>\n      </Box>\n      <div>\n        <CustomLinearProgressNew\n          variant=\"determinate\"\n          value={\n            depositedAmount.gt(maxCap)\n              ? maxCap.div(maxCap).times(100).toNumber()\n              : depositedAmount.div(maxCap).times(100).toNumber()\n          }\n        />\n        <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" marginTop=\"8px\">\n          <Typography className={clsx(classes.label, classes.green)}>Deposits</Typography>\n          <Typography className={classes.label}>Cap</Typography>\n        </Box>\n      </div>\n    </div>\n  )\n}\n\nexport default CapDetails\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CrabMetricsV2.tsx",
    "content": "import React from 'react'\nimport { Box } from '@material-ui/core'\nimport { useAtomValue } from 'jotai'\n\nimport Metric, { MetricLabel } from '@components/Metric'\nimport { formatNumber, formatCurrency } from '@utils/formatter'\nimport { toTokenAmount } from '@utils/calculations'\nimport { Tooltips } from '@constants/enums'\nimport { currentImpliedFundingAtom, dailyHistoricalFundingAtom } from '@state/controller/atoms'\nimport { useSetProfitableMovePercentV2 } from '@state/crab/hooks'\nimport { ethPriceAtLastHedgeAtomV2, timeAtLastHedgeAtomV2, crabStrategyCollatRatioAtomV2 } from '@state/crab/atoms'\nimport { useOnChainETHPrice } from '@hooks/useETHPrice'\n\nconst CrabMetricsV2: React.FC = () => {\n  const ethPrice = useOnChainETHPrice()\n  const currentImpliedFunding = useAtomValue(currentImpliedFundingAtom)\n  const dailyHistoricalFunding = useAtomValue(dailyHistoricalFundingAtom)\n  const timeAtLastHedge = useAtomValue(timeAtLastHedgeAtomV2)\n  const ethPriceAtLastHedgeValue = useAtomValue(ethPriceAtLastHedgeAtomV2)\n  const collatRatio = useAtomValue(crabStrategyCollatRatioAtomV2)\n\n  const profitableMovePercentV2 = useSetProfitableMovePercentV2()\n  const ethPriceAtLastHedge = Number(toTokenAmount(ethPriceAtLastHedgeValue, 18))\n  const lowerPriceBandForProfitability = ethPriceAtLastHedge - profitableMovePercentV2 * ethPriceAtLastHedge\n  const upperPriceBandForProfitability = ethPriceAtLastHedge + profitableMovePercentV2 * ethPriceAtLastHedge\n\n  return (\n    <Box display=\"flex\" alignItems=\"center\" flexWrap=\"wrap\" gridGap=\"12px\" marginTop=\"32px\">\n      <Metric\n        flexBasis=\"250px\"\n        label={<MetricLabel label=\"ETH Price\" tooltipTitle={Tooltips.SpotPrice} />}\n        value={formatCurrency(ethPrice.toNumber())}\n      />\n      <Metric\n        flexBasis=\"250px\"\n        label={\n          <MetricLabel\n            label=\"Current Implied Premium\"\n            tooltipTitle={`${Tooltips.StrategyEarnFunding}. ${Tooltips.CurrentImplFunding}`}\n          />\n        }\n        value={formatNumber(currentImpliedFunding * 100) + '%'}\n      />\n      <Metric\n        flexBasis=\"250px\"\n        label={\n          <MetricLabel\n            label=\"Historical Daily Premium\"\n            tooltipTitle={`${\n              Tooltips.StrategyEarnFunding\n            }. ${`Historical daily premium based on the last ${dailyHistoricalFunding.period} hours. Calculated using a ${dailyHistoricalFunding.period} hour TWAP of Mark - Index`}`}\n          />\n        }\n        value={formatNumber(dailyHistoricalFunding.funding * 100) + '%'}\n      />\n      <Metric\n        flexBasis=\"250px\"\n        label={\n          <MetricLabel\n            label=\"Last hedged at\"\n            tooltipTitle={\n              'Last hedged at ' +\n              new Date(timeAtLastHedge * 1000).toLocaleString(undefined, {\n                day: 'numeric',\n                month: 'long',\n                hour: 'numeric',\n                minute: 'numeric',\n                timeZoneName: 'long',\n              }) +\n              '. Hedges approximately 3 times a week (on MWF) or every 20% ETH price move'\n            }\n          />\n        }\n        value={new Date(timeAtLastHedge * 1000).toLocaleString(undefined, {\n          day: 'numeric',\n          month: 'numeric',\n          hour: 'numeric',\n          minute: 'numeric',\n        })}\n      />\n      <Metric\n        flexBasis=\"250px\"\n        label={\n          <MetricLabel\n            label={`Approx Profitable (${formatNumber(profitableMovePercentV2 * 100)}%)`}\n            tooltipTitle={Tooltips.StrategyProfitThreshold}\n          />\n        }\n        value={formatCurrency(lowerPriceBandForProfitability) + ' - ' + formatCurrency(upperPriceBandForProfitability)}\n      />\n      <Metric\n        flexBasis=\"250px\"\n        label={<MetricLabel label=\"Collateralization Ratio\" tooltipTitle={Tooltips.StrategyCollRatio} />}\n        value={formatNumber(collatRatio === Infinity ? 0 : collatRatio) + '%'}\n      />\n    </Box>\n  )\n}\n\nexport default CrabMetricsV2\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CrabMigrate.tsx",
    "content": "import { PrimaryButton } from '@components/Button'\nimport { PrimaryInput } from '@components/Input/PrimaryInput'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport { Step, Stepper, StepLabel } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React, { memo, useCallback, useEffect, useMemo, useState } from 'react'\nimport { CircularProgress } from '@material-ui/core'\nimport { LinkWrapper } from '@components/LinkWrapper'\nimport { useUserAllowance } from '@hooks/contracts/useAllowance'\nimport { useAtomValue } from 'jotai'\nimport { addressesAtom } from 'src/state/positions/atoms'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport useAppEffect from '@hooks/useAppEffect'\nimport BigNumber from 'bignumber.js'\nimport useAppCallback from '@hooks/useAppCallback'\nimport { useInitCrabMigration, useQueueMigrate } from 'src/state/crabMigration/hooks'\nimport { currentCrabPositionValueAtom, currentCrabPositionValueInETHAtom } from 'src/state/crab/atoms'\nimport TradeInfoItem from '@components/TradeOld/TradeInfoItem'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      // paddingTop: theme.spacing(1),\n    },\n    infoBox: {\n      background: '#8282821A',\n      border: '1px solid #828282',\n      borderRadius: theme.spacing(1),\n      padding: theme.spacing(1, 2),\n      marginTop: theme.spacing(1),\n      display: 'flex',\n      alignItems: 'top',\n    },\n    infoIcon: {\n      color: theme.palette.text.secondary,\n      fontSize: '14px',\n      marginTop: theme.spacing(0.5),\n    },\n    position: {\n      marginTop: theme.spacing(1),\n    },\n    stepper: {\n      backgroundColor: 'transparent',\n    },\n  }),\n)\n\nenum MIGRATION_STEP {\n  APPROVE,\n  MIGRATE,\n}\n\nconst getAction = (action: MIGRATION_STEP) => {\n  if (action === MIGRATION_STEP.APPROVE) return 'Approve crab to transfer funds to v2 at launch'\n\n  return 'Secure spot in Crab v2'\n}\n\nconst CrabMigration: React.FC = () => {\n  const classes = useStyles()\n  const { crabMigration, crabStrategy } = useAtomValue(addressesAtom)\n  const positionInEth = useAtomValue(currentCrabPositionValueInETHAtom)\n  const positionInUsd = useAtomValue(currentCrabPositionValueAtom)\n  const { value: userCrabBalance } = useTokenBalance(crabStrategy, 15, 18)\n  const { allowance, isLoadingAllowance, approve } = useUserAllowance(crabStrategy, crabMigration)\n  const queueMigrate = useQueueMigrate()\n\n  const [action, setAction] = useState(MIGRATION_STEP.APPROVE)\n  const [loadingTx, setLoadingTx] = useState(false)\n\n  const steps = ['Approve Crab Contract', 'Secure spot in Crab v2']\n\n  useAppEffect(() => {\n    if (allowance.gte(userCrabBalance)) {\n      setAction(MIGRATION_STEP.MIGRATE)\n    } else {\n      setAction(MIGRATION_STEP.APPROVE)\n    }\n  }, [allowance, userCrabBalance])\n\n  const executeAction = useCallback(\n    async (action: MIGRATION_STEP) => {\n      setLoadingTx(true)\n      if (action === MIGRATION_STEP.APPROVE) {\n        try {\n          await approve(() => null)\n        } catch (e) {\n          console.log(e)\n        }\n      } else if (action === MIGRATION_STEP.MIGRATE) {\n        try {\n          await queueMigrate(userCrabBalance)\n        } catch (e) {\n          console.log(e)\n        }\n      }\n      setLoadingTx(false)\n    },\n    [userCrabBalance, approve, queueMigrate],\n  )\n\n  const loading = useMemo(() => {\n    return isLoadingAllowance || loadingTx\n  }, [isLoadingAllowance, loadingTx])\n\n  return (\n    <div className={classes.container}>\n      <Stepper\n        className={classes.stepper}\n        activeStep={getAction(action) === 'Secure spot in Crab v2' ? 1 : 0}\n        alternativeLabel\n      >\n        {steps.map((label) => (\n          <Step key={label}>\n            <StepLabel>{label}</StepLabel>\n          </Step>\n        ))}\n      </Stepper>\n      {/* <div className={classes.infoBox}>\n        <InfoIcon className={classes.infoIcon} />\n        <Typography color=\"textSecondary\" variant=\"caption\" style={{ marginLeft: '4px' }}>\n          Your position is still participating in crab v1 until crab v2 drops. When crab v2 drops, your position will\n          automatically be transferred to crab v2.{' '}\n          <LinkWrapper href=\"https://www.notion.so/opynopyn/Crab-Migration-FAQ-Draft-1b79e3c2b98641b08745d5cc72c94a5c\">\n            {' '}\n            Learn more.\n          </LinkWrapper>\n        </Typography>\n      </div> */}\n      <div className={classes.position}>\n        <TradeInfoItem\n          label=\"Crab v1 Position\"\n          value={`${positionInEth.toFixed(4)} ETH`}\n          unit={`$${positionInUsd.toFixed(1)}`}\n          tooltip={\n            ' Your position is still participating in crab v1 until crab v2 drops. When crab v2 drops, your position will automatically be transferred to crab v2.'\n          }\n        />\n        {/* <Typography variant=\"body2\" color=\"textSecondary\">\n          Crab Position\n        </Typography>\n        <Typography variant=\"body2\">{positionInEth.toFixed(6)} ETH</Typography> */}\n      </div>\n      <PrimaryButton\n        variant=\"contained\"\n        style={{ marginTop: '16px' }}\n        disabled={loading || userCrabBalance.isZero()}\n        onClick={() => executeAction(action)}\n      >\n        {loading ? <CircularProgress color=\"primary\" size=\"1.5rem\" /> : getAction(action)}\n      </PrimaryButton>\n    </div>\n  )\n}\n\nexport default memo(CrabMigration)\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CrabPosition.tsx",
    "content": "import { useCrabPosition } from '@hooks/useCrabPosition'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React, { memo } from 'react'\nimport { useAtomValue } from 'jotai'\nimport { Typography, Tooltip, Box } from '@material-ui/core'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport { Tooltips } from '@constants/enums'\nimport { addressAtom } from 'src/state/wallet/atoms'\nimport { useCurrentCrabPositionValue } from 'src/state/crab/hooks'\nimport { pnlInPerct } from 'src/lib/pnl'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { userMigratedSharesAtom } from 'src/state/crabMigration/atom'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(1),\n      backgroundColor: theme.palette.background.lightStone,\n      borderRadius: theme.spacing(1),\n      marginTop: theme.spacing(2),\n    },\n    green: {\n      color: theme.palette.success.main,\n    },\n    red: {\n      color: theme.palette.error.main,\n    },\n    infoIcon: {\n      fontSize: '10px',\n      marginLeft: theme.spacing(0.5),\n    },\n  }),\n)\n\nconst CrabPosition: React.FC = () => {\n  const address = useAtomValue(addressAtom)\n  const { loading: isCrabPositonLoading, depositedUsd } = useCrabPosition(address || '')\n  const { currentCrabPositionValue, isCrabPositionValueLoading } = useCurrentCrabPositionValue()\n  const userMigratedShares = useAtomValue(userMigratedSharesAtom)\n\n  const classes = useStyles()\n  const pnl = useAppMemo(() => {\n    return pnlInPerct(currentCrabPositionValue, depositedUsd)\n  }, [currentCrabPositionValue, depositedUsd])\n\n  const loading = useAppMemo(() => {\n    return isCrabPositonLoading || isCrabPositionValueLoading\n  }, [isCrabPositonLoading, isCrabPositionValueLoading])\n\n  const isMigrated = useAppMemo(() => {\n    return userMigratedShares.gt(0)\n  }, [userMigratedShares])\n\n  if (loading) {\n    return (\n      <Box mt={2}>\n        <Typography>Loading</Typography>\n      </Box>\n    )\n  }\n\n  if ((currentCrabPositionValue.isZero() || depositedUsd.isZero()) && !isMigrated) {\n    return null\n  }\n\n  return (\n    <div className={classes.container}>\n      <Typography color=\"primary\" variant=\"subtitle1\">\n        {isMigrated ? 'Position secured in Crab V2' : 'Position'}\n      </Typography>\n      <div style={{ display: 'flex', alignItems: 'center' }}>\n        <Typography variant=\"h6\" id=\"crab-pos-bal\">\n          {loading ? 'Loading' : `${currentCrabPositionValue.toFixed(2)} USD`}\n        </Typography>\n        {!loading && pnl.isFinite() ? (\n          <Typography\n            variant=\"body2\"\n            style={{ marginLeft: '4px', fontWeight: 600 }}\n            className={pnl.isNegative() ? classes.red : classes.green}\n          >\n            ({pnl.toFixed(2)} %)\n          </Typography>\n        ) : null}\n        <Tooltip title={Tooltips.CrabPnL}>\n          <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n        </Tooltip>\n      </div>\n    </div>\n  )\n}\n\nexport default memo(CrabPosition)\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CrabPositionV2.tsx",
    "content": "import { Typography, Box, CircularProgress, Button } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React, { memo, useState } from 'react'\nimport { useAtom, useAtomValue } from 'jotai'\nimport clsx from 'clsx'\n\nimport { addressAtom } from '@state/wallet/atoms'\nimport { useCurrentCrabPositionValueV2, useDeQueueDepositUSDC, useDeQueueWithdrawCrab } from '@state/crab/hooks'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { useCrabPositionV2 } from '@hooks/useCrabPosition/useCrabPosition'\nimport Metric, { MetricLabel } from '@components/Metric'\nimport { formatCurrency, formatNumber } from '@utils/formatter'\nimport { pnlInPerctv2 } from 'src/lib/pnl'\nimport {\n  crabQueuedAtom,\n  crabQueuedInUsdAtom,\n  crabUSDValueAtom,\n  usdcQueuedAtom,\n  isNettingAuctionLiveAtom,\n} from '@state/crab/atoms'\nimport { toTokenAmount } from '@utils/calculations'\nimport { BIG_ZERO, USDC_DECIMALS } from '@constants/index'\nimport { useTransactionStatus } from '@state/wallet/hooks'\nimport { Tooltips } from '@constants/enums'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      marginTop: theme.spacing(2),\n    },\n    subtitle: {\n      fontSize: '22px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n    },\n    green: {\n      color: theme.palette.success.main,\n    },\n    red: {\n      color: theme.palette.error.main,\n    },\n    white: {\n      color: 'rgba(255, 255, 255)',\n    },\n    infoIcon: {\n      fontSize: '10px',\n      marginLeft: theme.spacing(0.5),\n    },\n    metricValue: {\n      fontSize: '20px',\n      fontWeight: 500,\n      width: 'max-content',\n      fontFamily: 'DM Mono',\n    },\n    metricSubValue: {\n      fontSize: '18px',\n      fontWeight: 500,\n      width: 'max-content',\n      fontFamily: 'DM Mono',\n    },\n    queuedPosition: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n  }),\n)\n\nconst CrabPosition: React.FC = () => {\n  const address = useAtomValue(addressAtom)\n  const { loading: isCrabPositionLoading, depositedUsd } = useCrabPositionV2(address || '')\n  const { currentCrabPositionValue, isCrabPositionValueLoading } = useCurrentCrabPositionValueV2()\n\n  const [usdcQueued, setUsdcQueued] = useAtom(usdcQueuedAtom)\n  const [crabQueued, setCrabQueued] = useAtom(crabQueuedAtom)\n  const crabV2QueuedInUsd = useAtomValue(crabQueuedInUsdAtom)\n  const isNettingAuctionLive = useAtomValue(isNettingAuctionLiveAtom)\n\n  const classes = useStyles()\n  const pnl = useAppMemo(() => {\n    console.log(currentCrabPositionValue.toString(), depositedUsd.toString(), 'Position value')\n    return pnlInPerctv2(currentCrabPositionValue.plus(crabV2QueuedInUsd), depositedUsd)\n  }, [currentCrabPositionValue, depositedUsd, crabV2QueuedInUsd])\n\n  const loading = useAppMemo(() => {\n    return isCrabPositionLoading || isCrabPositionValueLoading\n  }, [isCrabPositionLoading, isCrabPositionValueLoading])\n\n  const crabUsdValue = useAtomValue(crabUSDValueAtom)\n\n  const [usdcLoading, setUSDCLoading] = useState(false)\n  const [crabLoading, setCrabLoading] = useState(false)\n\n  const dequeueUSDC = useDeQueueDepositUSDC()\n  const dequeueCRAB = useDeQueueWithdrawCrab()\n\n  const { resetTransactionData } = useTransactionStatus()\n\n  const onDeQueueUSDC = async () => {\n    setUSDCLoading(true)\n    try {\n      await dequeueUSDC(usdcQueued, resetTransactionData)\n      setUsdcQueued(BIG_ZERO)\n    } catch (e) {\n      console.log(e)\n    }\n    setUSDCLoading(false)\n  }\n\n  const onDeQueueCrab = async () => {\n    setCrabLoading(true)\n    try {\n      await dequeueCRAB(crabQueued, resetTransactionData)\n      setCrabQueued(BIG_ZERO)\n    } catch (e) {\n      console.log(e)\n    }\n    setCrabLoading(false)\n  }\n\n  if (currentCrabPositionValue.isZero() && usdcQueued.isZero() && crabQueued.isZero()) return null\n\n  return (\n    <Box>\n      <Typography variant=\"h4\" className={classes.subtitle}>\n        My Position\n      </Typography>\n\n      {loading ? (\n        <Box mt={2} display=\"flex\" alignItems=\"flex-start\" gridGap=\"20px\" height=\"94px\">\n          <CircularProgress color=\"primary\" size=\"1rem\" />\n          <Typography>Fetching current position...</Typography>\n        </Box>\n      ) : (\n        <Box display=\"flex\" alignItems=\"center\" gridGap=\"20px\" marginTop=\"16px\" flexWrap=\"wrap\">\n          {/* hide position for dust amount */}\n          {usdcQueued.isGreaterThan('100') ? (\n            <Metric\n              label={<MetricLabel label=\"Initiated Deposit\" tooltipTitle={Tooltips.InitiatedDeposit} />}\n              value={\n                <Box className={classes.queuedPosition}>\n                  <Typography className={clsx(classes.metricValue, classes.white)}>\n                    {formatCurrency(Number(toTokenAmount(usdcQueued, USDC_DECIMALS)))}\n                  </Typography>\n                  {!isNettingAuctionLive && (\n                    <Button\n                      style={{ marginLeft: '8px' }}\n                      color=\"primary\"\n                      disabled={usdcLoading}\n                      onClick={onDeQueueUSDC}\n                    >\n                      {!usdcLoading ? 'Cancel' : <CircularProgress color=\"primary\" size=\"1.5rem\" />}\n                    </Button>\n                  )}\n                </Box>\n              }\n            />\n          ) : null}\n          {/* hide position for dust amount */}\n          {crabQueued.isGreaterThan('10000000000') ? (\n            <Metric\n              label={<MetricLabel label=\"Initiated Withdrawal\" tooltipTitle={Tooltips.InitiatedWithdrawal} />}\n              value={\n                <Box className={classes.queuedPosition}>\n                  <Typography className={clsx(classes.metricValue, classes.white)}>\n                    {formatCurrency(Number(toTokenAmount(crabQueued, 18).times(toTokenAmount(crabUsdValue, 18))))}\n                  </Typography>\n                  {!isNettingAuctionLive && (\n                    <Button\n                      style={{ marginLeft: '8px' }}\n                      color=\"primary\"\n                      disabled={crabLoading}\n                      onClick={onDeQueueCrab}\n                    >\n                      {!crabLoading ? 'Cancel' : <CircularProgress color=\"primary\" size=\"1.5rem\" />}\n                    </Button>\n                  )}\n                </Box>\n              }\n            />\n          ) : null}\n          {currentCrabPositionValue.isGreaterThan(0) ? (\n            <Metric\n              label=\"Position value\"\n              value={\n                <Typography className={clsx(classes.metricValue, classes.white)}>\n                  {formatCurrency(currentCrabPositionValue.toNumber())}\n                </Typography>\n              }\n            />\n          ) : null}\n          {pnl.isFinite() && (\n            <Metric\n              label=\"PnL\"\n              value={\n                <Box display=\"flex\" alignItems=\"center\" gridGap=\"12px\">\n                  <Typography className={clsx(classes.metricValue, classes.white)}>\n                    {formatCurrency(depositedUsd.times(pnl).div(100).toNumber())}\n                  </Typography>\n                  <Typography className={clsx(classes.metricSubValue, pnl.isPositive() ? classes.green : classes.red)}>\n                    {formatNumber(pnl.toNumber()) + '%'}\n                  </Typography>\n                </Box>\n              }\n            />\n          )}\n        </Box>\n      )}\n    </Box>\n  )\n}\n\nexport default memo(CrabPosition)\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CrabTrade.tsx",
    "content": "import { PrimaryButton } from '@components/Button'\nimport { PrimaryInput } from '@components/Input/PrimaryInput'\nimport { SecondaryTabs, SecondaryTab } from '@components/Tabs'\nimport Confirmed, { ConfirmType } from '@components/TradeOld/Confirmed'\nimport TradeInfoItem from '@components/TradeOld/TradeInfoItem'\nimport { TradeSettings } from '@components/TradeSettings'\nimport { useRestrictUser } from '@context/restrict-user'\nimport RestrictionInfo from '@components/RestrictionInfo'\nimport { CircularProgress, Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport { toTokenAmount } from '@utils/calculations'\nimport BigNumber from 'bignumber.js'\nimport React, { useEffect, useMemo, useState } from 'react'\nimport CrabPosition from './CrabPosition'\nimport { useAtom, useAtomValue } from 'jotai'\nimport { addressAtom, connectedWalletAtom } from 'src/state/wallet/atoms'\nimport { useTransactionStatus, useWalletBalance } from 'src/state/wallet/hooks'\nimport { BIG_ZERO } from '../../../constants'\nimport { readyAtom } from 'src/state/squeethPool/atoms'\nimport {\n  crabStrategySlippageAtom,\n  currentCrabPositionValueInETHAtom,\n  isPriceHedgeAvailableAtom,\n  isTimeHedgeAvailableAtom,\n} from 'src/state/crab/atoms'\nimport {\n  useFlashDeposit,\n  useCalculateETHtoBorrowFromUniswap,\n  useCalculateEthWillingToPay,\n  useFlashWithdrawEth,\n  useSetStrategyData,\n} from 'src/state/crab/hooks'\nimport { useUserCrabTxHistory } from '@hooks/useUserCrabTxHistory'\nimport { usePrevious } from 'react-use'\nimport { currentImpliedFundingAtom, dailyHistoricalFundingAtom, indexAtom } from 'src/state/controller/atoms'\nimport CrabMigration from './CrabMigrate'\nimport { isQueuedAtom } from 'src/state/crabMigration/atom'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(2),\n    },\n    confirmedBox: {\n      display: 'flex',\n      justifyContent: 'center',\n      textAlign: 'center',\n      flexDirection: 'column',\n      padding: theme.spacing(2, 3),\n    },\n    settingsButton: {\n      marginTop: theme.spacing(0.5),\n      marginLeft: theme.spacing(37),\n      justifyContent: 'right',\n      alignSelf: 'center',\n    },\n    tradeContainer: {\n      display: 'flex',\n      flexDirection: 'column',\n      padding: theme.spacing(1, 3),\n      paddingBottom: theme.spacing(3),\n    },\n    tabBackGround: {\n      position: 'sticky',\n      top: '0',\n      zIndex: 20,\n      // background: '#2A2D2E',\n    },\n  }),\n)\n\ntype CrabTradeType = {\n  maxCap: BigNumber\n  depositedAmount: BigNumber\n}\n\nconst CrabTrade: React.FC<CrabTradeType> = ({ maxCap, depositedAmount }) => {\n  const classes = useStyles()\n  const [ethAmount, setEthAmount] = useState(new BigNumber(0))\n  const [withdrawAmount, setWithdrawAmount] = useState(new BigNumber(0))\n  const [depositOption, setDepositOption] = useState(0)\n  const [txLoading, setTxLoading] = useState(false)\n  const [depositPriceImpact, setDepositPriceImpact] = useState('0')\n  const [withdrawPriceImpact, setWithdrawPriceImpact] = useState('0')\n  const [borrowEth, setBorrowEth] = useState(new BigNumber(0))\n\n  const connected = useAtomValue(connectedWalletAtom)\n  const currentEthValue = useAtomValue(currentCrabPositionValueInETHAtom)\n  const isTimeHedgeAvailable = useAtomValue(isTimeHedgeAvailableAtom)\n  const isPriceHedgeAvailable = useAtomValue(isPriceHedgeAvailableAtom)\n  const [slippage, setSlippage] = useAtom(crabStrategySlippageAtom)\n  const isQueued = useAtomValue(isQueuedAtom)\n  const { data: balance } = useWalletBalance()\n  const setStrategyData = useSetStrategyData()\n  const flashWithdrawEth = useFlashWithdrawEth()\n  const calculateEthWillingToPay = useCalculateEthWillingToPay()\n  const calculateETHtoBorrowFromUniswap = useCalculateETHtoBorrowFromUniswap()\n  const flashDeposit = useFlashDeposit(calculateETHtoBorrowFromUniswap)\n  const index = useAtomValue(indexAtom)\n  const ethIndexPrice = toTokenAmount(index, 18).sqrt()\n\n  const { confirmed, resetTransactionData, transactionData } = useTransactionStatus()\n\n  const ready = useAtomValue(readyAtom)\n  const { isRestricted } = useRestrictUser()\n\n  const dailyHistoricalFunding = useAtomValue(dailyHistoricalFundingAtom)\n  const currentImpliedFunding = useAtomValue(currentImpliedFundingAtom)\n\n  const address = useAtomValue(addressAtom)\n  const { data, startPolling, stopPolling } = useUserCrabTxHistory(address ?? '')\n\n  const prevCrabTxData = usePrevious(data)\n\n  useEffect(() => {\n    if (confirmed && prevCrabTxData?.length === data?.length) {\n      startPolling(500)\n    } else {\n      stopPolling()\n    }\n  }, [confirmed, prevCrabTxData?.length, data?.length])\n\n  useEffect(() => {\n    setStrategyData()\n  }, [])\n\n  const { depositError, warning, withdrawError } = useMemo(() => {\n    let depositError: string | undefined\n    let withdrawError: string | undefined\n    let warning: string | undefined\n\n    if (connected) {\n      if (ethAmount.plus(depositedAmount).gte(maxCap)) {\n        depositError = 'Amount greater than strategy cap'\n      } else if (ethAmount.plus(depositedAmount).plus(borrowEth).gte(maxCap)) {\n        depositError = `Amount greater than strategy cap since it flash borrows ${borrowEth.toFixed(\n          2,\n        )} ETH. Input a smaller amount`\n      } else if (toTokenAmount(balance ?? BIG_ZERO, 18).lt(ethAmount)) {\n        depositError = 'Insufficient ETH balance'\n      }\n      if (withdrawAmount.gt(currentEthValue)) {\n        withdrawError = 'Withdraw amount greater than strategy balance'\n      }\n      if (isTimeHedgeAvailable || isPriceHedgeAvailable) {\n        depositError = 'Deposits and withdraws available after the hedge auction'\n        withdrawError = 'Deposits and withdraws available after the hedge auction'\n      }\n      if (currentImpliedFunding <= 0.75 * dailyHistoricalFunding.funding) {\n        warning = `Current implied premiums is 75% lower than the last ${dailyHistoricalFunding.period} hours. Consider if you want to deposit now or later`\n      }\n    }\n\n    return { depositError, warning, withdrawError }\n  }, [\n    connected,\n    ethAmount.toString(),\n    depositedAmount.toString(),\n    maxCap.toString(),\n    borrowEth.toString(),\n    balance?.toString(),\n    withdrawAmount.toString(),\n    currentEthValue.toString(),\n    currentImpliedFunding.toString(),\n    dailyHistoricalFunding.funding,\n    dailyHistoricalFunding.period,\n    isTimeHedgeAvailable,\n    isPriceHedgeAvailable,\n  ])\n\n  useEffect(() => {\n    if (!ready || depositOption !== 0) return\n\n    calculateETHtoBorrowFromUniswap(ethAmount, slippage).then((q) => {\n      setDepositPriceImpact(q.priceImpact)\n      setBorrowEth(q.ethBorrow)\n    })\n  }, [ready, ethAmount.toString(), slippage])\n\n  useEffect(() => {\n    if (!ready || depositOption === 0) return\n\n    calculateEthWillingToPay(withdrawAmount, slippage).then((q) => setWithdrawPriceImpact(q.priceImpact))\n  }, [ready, withdrawAmount.toString(), slippage])\n\n  const deposit = async () => {\n    setTxLoading(true)\n    try {\n      await flashDeposit(ethAmount, slippage, () => {\n        setTxLoading(false)\n        setStrategyData()\n      })\n    } catch (e) {\n      console.log(e)\n      setTxLoading(false)\n    }\n  }\n\n  const withdraw = async () => {\n    setTxLoading(true)\n    try {\n      await flashWithdrawEth(withdrawAmount, slippage, () => {\n        setTxLoading(false)\n        setStrategyData()\n      })\n    } catch (e) {\n      console.log(e)\n      setTxLoading(false)\n    }\n  }\n\n  if (isRestricted) {\n    return <RestrictionInfo />\n  }\n\n  const isApprovalCall = useMemo(() => {\n    return transactionData?.contractCall?.methodName === 'approve'\n  }, [transactionData])\n\n  if (currentEthValue.isZero()) {\n    return null\n  }\n\n  return (\n    <>\n      {confirmed && !isApprovalCall ? (\n        <div className={classes.confirmedBox}>\n          <Confirmed\n            confirmationMessage={\n              depositOption === 0\n                ? `Woohoo! You're guaranteed a spot in crab v2 `\n                : `Withdrawn ${withdrawAmount.toFixed(4)} ETH`\n            }\n            txnHash={transactionData?.hash ?? ''}\n            confirmType={ConfirmType.CRAB}\n          />\n          <PrimaryButton\n            id=\"crab-close-btn\"\n            variant=\"contained\"\n            style={{ marginTop: '16px' }}\n            onClick={() => {\n              resetTransactionData()\n              setWithdrawAmount(new BigNumber(0))\n              setEthAmount(new BigNumber(0))\n            }}\n          >\n            Close\n          </PrimaryButton>\n        </div>\n      ) : (\n        <>\n          {!isQueued ? (\n            <SecondaryTabs\n              value={depositOption}\n              onChange={(evt, val) => setDepositOption(val)}\n              aria-label=\"simple tabs example\"\n              centered\n              variant=\"fullWidth\"\n              className={classes.tabBackGround}\n            >\n              <SecondaryTab id=\"crab-deposit-tab\" label=\"Migrate to v2\" />\n              <SecondaryTab id=\"crab-withdraw-tab\" label=\"Withdraw\" />\n            </SecondaryTabs>\n          ) : null}\n          {depositOption === 0 ? null : (\n            <div className={classes.settingsButton}>\n              <TradeSettings setSlippage={(amt) => setSlippage(amt.toNumber())} slippage={new BigNumber(slippage)} />\n            </div>\n          )}\n          <div className={classes.tradeContainer}>\n            {depositOption === 0 ? (\n              !currentEthValue.isZero() ? (\n                <Typography variant=\"body2\" color=\"textSecondary\" style={{ marginTop: '20px' }}>\n                  Didn't migrate from Crab V1 during early access? Migration to V2 coming soon.\n                </Typography>\n              ) : (\n                <>\n                  <Typography variant=\"body2\" color=\"textSecondary\" style={{ marginTop: '8px' }}>\n                    You don't have a Crab v1 position to migrate\n                  </Typography>\n                </>\n              )\n            ) : (\n              <>\n                {depositOption === 0 ? (\n                  <PrimaryInput\n                    id=\"crab-deposit-eth-input\"\n                    value={ethAmount.toString()}\n                    onChange={(v) => setEthAmount(new BigNumber(v))}\n                    label=\"Amount\"\n                    tooltip=\"ETH Amount to deposit\"\n                    actionTxt=\"Max\"\n                    unit=\"ETH\"\n                    hint={\n                      depositError\n                        ? depositError\n                        : warning\n                          ? warning\n                          : `Balance ${toTokenAmount(balance ?? BIG_ZERO, 18).toFixed(6)} ETH`\n                    }\n                    convertedValue={ethIndexPrice.times(ethAmount).toFixed(2)}\n                    onActionClicked={() => setEthAmount(toTokenAmount(balance ?? BIG_ZERO, 18))}\n                    error={!!depositError}\n                  />\n                ) : (\n                  <PrimaryInput\n                    id=\"crab-withdraw-eth-input\"\n                    value={withdrawAmount.toString()}\n                    onChange={(v) => setWithdrawAmount(new BigNumber(v))}\n                    label=\"Amount\"\n                    tooltip=\"Amount of ETH to withdraw\"\n                    actionTxt=\"Max\"\n                    unit=\"ETH\"\n                    convertedValue={ethIndexPrice.times(withdrawAmount).toFixed(2)}\n                    hint={\n                      withdrawError ? (\n                        withdrawError\n                      ) : (\n                        <span>\n                          Position{' '}\n                          <span id=\"current-crab-eth-bal-input\">\n                            {(isQueued ? BIG_ZERO : currentEthValue).toFixed(6)}\n                          </span>{' '}\n                          ETH\n                        </span>\n                      )\n                    }\n                    onActionClicked={() => setWithdrawAmount(currentEthValue)}\n                    error={!!withdrawError}\n                  />\n                )}\n                <TradeInfoItem\n                  label=\"Slippage\"\n                  value={slippage.toString()}\n                  tooltip=\"The strategy uses a uniswap flashswap to make a deposit. You can adjust slippage for this swap by clicking the gear icon\"\n                  unit=\"%\"\n                />\n                {depositOption === 0 ? (\n                  <TradeInfoItem\n                    label=\"Price Impact\"\n                    value={depositPriceImpact}\n                    unit=\"%\"\n                    color={\n                      Number(depositPriceImpact) > 3 ? 'red' : Number(depositPriceImpact) < 1 ? 'green' : undefined\n                    }\n                  />\n                ) : (\n                  <TradeInfoItem\n                    label=\"Price Impact\"\n                    value={withdrawPriceImpact}\n                    unit=\"%\"\n                    color={\n                      Number(withdrawPriceImpact) > 3 ? 'red' : Number(depositPriceImpact) < 1 ? 'green' : undefined\n                    }\n                  />\n                )}\n\n                {depositOption === 0 ? (\n                  <PrimaryButton\n                    id=\"crab-deposit-btn\"\n                    variant={Number(depositPriceImpact) > 3 || !!warning ? 'outlined' : 'contained'}\n                    onClick={() => deposit()}\n                    disabled={txLoading || !!depositError}\n                    style={\n                      Number(depositPriceImpact) > 3 || !!warning\n                        ? { color: '#f5475c', backgroundColor: 'transparent', borderColor: '#f5475c', marginTop: '8px' }\n                        : { marginTop: '8px' }\n                    }\n                  >\n                    {!txLoading ? 'Deposit' : <CircularProgress color=\"primary\" size=\"1.5rem\" />}\n                  </PrimaryButton>\n                ) : (\n                  <PrimaryButton\n                    id=\"crab-withdraw-btn\"\n                    variant={Number(withdrawPriceImpact) > 3 ? 'outlined' : 'contained'}\n                    style={\n                      Number(withdrawPriceImpact) > 3\n                        ? { color: '#f5475c', backgroundColor: 'transparent', borderColor: '#f5475c', marginTop: '8px' }\n                        : { marginTop: '8px' }\n                    }\n                    onClick={() => withdraw()}\n                    disabled={txLoading || !!withdrawError || isQueued}\n                  >\n                    {!txLoading ? 'Withdraw' : <CircularProgress color=\"primary\" size=\"1.5rem\" />}\n                  </PrimaryButton>\n                )}\n              </>\n            )}\n            <CrabPosition />\n          </div>\n        </>\n      )}\n    </>\n  )\n}\n\nexport default CrabTrade\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CrabTradeV2/Deposit.tsx",
    "content": "import { Box, CircularProgress, Tooltip, Typography } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport React, { useEffect, useMemo, useState, useCallback, useRef } from 'react'\nimport { useAtom, useAtomValue } from 'jotai'\nimport { useDebounce } from 'use-debounce'\nimport InfoIcon from '@material-ui/icons/Info'\nimport { PrimaryButtonNew, RoundedButton } from '@components/Button'\nimport { TradeSettings } from '@components/TradeSettings'\nimport RestrictionInfo from '@components/RestrictionInfo'\nimport { InputToken } from '@components/InputNew'\nimport Metric, { MetricLabel } from '@components/Metric'\nimport { connectedWalletAtom, networkIdAtom, supportedNetworkAtom } from '@state/wallet/atoms'\nimport { useTransactionStatus, useSelectWallet } from '@state/wallet/hooks'\nimport {\n  crabStrategySlippageAtomV2,\n  usdcQueuedAtom,\n  minUSDCAmountAtom,\n  maxCapAtomV2,\n  crabStrategyVaultAtomV2,\n  totalUsdcQueuedAtom,\n  totalCrabQueueInUsddAtom,\n} from '@state/crab/atoms'\nimport {\n  useSetStrategyDataV2,\n  useCalculateETHtoBorrowFromUniswapV2,\n  useFlashDepositUSDC,\n  useQueueDepositUSDC,\n} from '@state/crab/hooks'\nimport { readyAtom } from '@state/squeethPool/atoms'\nimport { impliedVolAtom, indexAtom, normFactorAtom, osqthRefVolAtom } from '@state/controller/atoms'\nimport { addressesAtom } from '@state/positions/atoms'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport { useUniswapQuoter } from '@hooks/useUniswapQuoter'\nimport { useUserAllowance } from '@hooks/contracts/useAllowance'\nimport useStateWithReset from '@hooks/useStateWithReset'\nimport {\n  BIG_ZERO,\n  FUNDING_PERIOD,\n  INDEX_SCALE,\n  USDC_DECIMALS,\n  VOL_PERCENT_FIXED,\n  VOL_PERCENT_SCALAR,\n  WETH_DECIMALS,\n  YEAR,\n  AVERAGE_AUCTION_PRICE_IMPACT,\n  NETTING_PRICE_IMPACT,\n  STRATEGY_DEPOSIT_LIMIT,\n} from '@constants/index'\nimport { useRestrictUser } from '@context/restrict-user'\nimport { fromTokenAmount, getUSDCPoolFee, toTokenAmount } from '@utils/calculations'\nimport { formatNumber } from '@utils/formatter'\nimport usdcLogo from 'public/images/usdc-logo.svg'\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'\nimport HelpOutlineIcon from '@material-ui/icons/HelpOutline'\nimport { useStyles } from './styles'\nimport { CrabTradeTransactionType, CrabTradeType, CrabTransactionConfirmation, OngoingTransaction } from './types'\nimport { CRAB_EVENTS } from '@utils/amplitude'\nimport useAmplitude from '@hooks/useAmplitude'\nimport useExecuteOnce from '@hooks/useExecuteOnce'\nimport useTrackTransactionFlow from '@hooks/useTrackTransactionFlow'\n\ntype CrabDepositProps = {\n  onTxnConfirm: (txn: CrabTransactionConfirmation) => void\n}\n\nenum DepositSteps {\n  APPROVE = 'Approve USDC',\n  DEPOSIT = 'Deposit',\n}\n\nconst OTC_PRICE_IMPACT_THRESHOLD = Number(process.env.NEXT_PUBLIC_OTC_PRICE_IMPACT_THRESHOLD) || 1\n\nconst CrabDeposit: React.FC<CrabDepositProps> = ({ onTxnConfirm }) => {\n  const classes = useStyles()\n  const [depositAmount, setDepositAmount] = useState('0')\n  const [debouncedDepositAmount] = useDebounce(depositAmount, 500)\n  const ongoingTransaction = useRef<OngoingTransaction | undefined>()\n  const depositAmountBN = useMemo(() => new BigNumber(debouncedDepositAmount), [debouncedDepositAmount])\n\n  const [txLoading, setTxLoading] = useState(false)\n  const [depositPriceImpact, setDepositPriceImpact, resetDepositPriceImpact] = useStateWithReset('0')\n  const [borrowEth, setBorrowEth, resetBorrowEth] = useStateWithReset(new BigNumber(0))\n  const [uniswapFee, setUniswapFee, resetUniswapFee] = useStateWithReset('0')\n  const [squeethAmountInFromDeposit, setSqueethAmountInFromDeposit, resetSqueethAmountInFromDeposit] =\n    useStateWithReset(new BigNumber(0))\n  const [ethAmountOutFromDeposit, setEthAmountOutFromDeposit, resetEthAmountOutFromDeposit] = useStateWithReset(\n    new BigNumber(0),\n  )\n  const [depositEthAmount, setDepositEthAmount] = useState(new BigNumber(0))\n  const [queueOptionAvailable, setQueueOptionAvailable] = useState(false)\n  const [useQueue, setUseQueue] = useState(false)\n  const [depositStep, setDepositStep] = useState(DepositSteps.DEPOSIT)\n  const [userOverrode, setUserOverrode] = useState(false)\n\n  const minUSDCAmountValue = useAtomValue(minUSDCAmountAtom)\n\n  const connected = useAtomValue(connectedWalletAtom)\n  const [slippage, setSlippage] = useAtom(crabStrategySlippageAtomV2)\n  const network = useAtomValue(networkIdAtom)\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n  const selectWallet = useSelectWallet()\n\n  const { usdc, weth, crabHelper, crabNetting } = useAtomValue(addressesAtom)\n  const { value: usdcBalance, refetch: refetchUsdcBalance } = useTokenBalance(usdc, 15, USDC_DECIMALS)\n  const { getExactIn } = useUniswapQuoter()\n  const setStrategyData = useSetStrategyDataV2()\n  const calculateETHtoBorrowFromUniswap = useCalculateETHtoBorrowFromUniswapV2()\n  const flashDepositUSDC = useFlashDepositUSDC(calculateETHtoBorrowFromUniswap)\n  const queueUSDC = useQueueDepositUSDC()\n  const [usdcQueued, setUsdcQueued] = useAtom(usdcQueuedAtom)\n\n  const index = useAtomValue(indexAtom)\n  const ethIndexPrice = toTokenAmount(index, 18).sqrt()\n  const { resetTransactionData } = useTransactionStatus()\n\n  const ready = useAtomValue(readyAtom)\n  const { isRestricted, isWithdrawAllowed } = useRestrictUser()\n\n  const { allowance: usdcAllowance, approve: approveUsdc } = useUserAllowance(usdc, crabHelper, USDC_DECIMALS)\n  const { allowance: usdcQueueAllowance, approve: approveQueueUsdc } = useUserAllowance(\n    usdc,\n    crabNetting,\n    USDC_DECIMALS,\n  )\n\n  const maxCap = useAtomValue(maxCapAtomV2)\n  const vault = useAtomValue(crabStrategyVaultAtomV2)\n  const impliedVol = useAtomValue(impliedVolAtom)\n  const normFactor = useAtomValue(normFactorAtom)\n  const osqthRefVol = useAtomValue(osqthRefVolAtom)\n  const { track } = useAmplitude()\n\n  const trackUserEnteredDepositAmount = useCallback(\n    (amount: BigNumber) => track(CRAB_EVENTS.DEPOSIT_CRAB_AMOUNT_ENTERED, { amount: amount.toNumber() }),\n    [track],\n  )\n\n  const [trackDepositAmountEnteredOnce, resetTracking] = useExecuteOnce(trackUserEnteredDepositAmount)\n  const logAndRunTransaction = useTrackTransactionFlow()\n\n  const onInputChange = useCallback(\n    (amount: string) => {\n      setDepositAmount(amount)\n      const deposit = new BigNumber(amount)\n      deposit.isGreaterThan(0) ? trackDepositAmountEnteredOnce(deposit) : null\n    },\n    [setDepositAmount, trackDepositAmountEnteredOnce],\n  )\n\n  const depositedAmount = vault?.collateralAmount ?? BIG_ZERO\n\n  const depositPriceImpactWarning = useAppMemo(() => {\n    if (useQueue) return false\n\n    const squeethPrice = ethAmountOutFromDeposit.div(squeethAmountInFromDeposit).times(1.003)\n    const scalingFactor = new BigNumber(INDEX_SCALE)\n    const fundingPeriod = new BigNumber(FUNDING_PERIOD).div(YEAR)\n    const log = Math.log(scalingFactor.times(squeethPrice).div(normFactor.times(ethIndexPrice)).toNumber())\n    const executionVol = new BigNumber(log).div(fundingPeriod).sqrt()\n\n    const showPriceImpactWarning =\n      log < 0 ||\n      executionVol\n        .minus(impliedVol)\n        .abs()\n        .gt(BigNumber.max(new BigNumber(impliedVol).times(VOL_PERCENT_SCALAR), VOL_PERCENT_FIXED))\n    return showPriceImpactWarning\n  }, [impliedVol, ethAmountOutFromDeposit, squeethAmountInFromDeposit, useQueue, ethIndexPrice, normFactor])\n\n  const depositFundingWarning = useAppMemo(() => {\n    const impliedVolDiff = new BigNumber(-VOL_PERCENT_SCALAR)\n    const impliedVolDiffLowVol = new BigNumber(-VOL_PERCENT_FIXED)\n    // const dailyHistoricalImpliedVol = new BigNumber(dailyHistoricalFunding.funding).times(YEAR).sqrt()\n    const threshold = BigNumber.max(\n      new BigNumber(osqthRefVol / 100).times(new BigNumber(1).plus(impliedVolDiff)),\n      new BigNumber(osqthRefVol / 100).plus(impliedVolDiffLowVol),\n    )\n\n    const showFundingWarning = new BigNumber(impliedVol).lt(threshold) ? true : false\n    return showFundingWarning\n  }, [osqthRefVol, impliedVol])\n\n  const depositError = useAppMemo(() => {\n    let inputError\n\n    if (connected) {\n      if (depositEthAmount.plus(depositedAmount).gte(maxCap)) {\n        inputError = 'Amount greater than strategy cap'\n      } else if (depositEthAmount.plus(depositedAmount).plus(borrowEth).gte(maxCap)) {\n        inputError = `Amount greater than strategy cap since it flash borrows ${borrowEth.toFixed(\n          2,\n        )} ETH. Input a smaller amount`\n      } else if (usdcBalance.lt(depositAmountBN)) {\n        inputError = 'Insufficient USDC balance'\n      }\n    }\n\n    return inputError\n  }, [connected, depositEthAmount, depositAmountBN, depositedAmount, maxCap, borrowEth, usdcBalance])\n\n  useEffect(() => {\n    if (!ready) {\n      return\n    }\n\n    if (depositAmountBN.isZero()) {\n      resetDepositPriceImpact()\n      resetUniswapFee()\n      resetBorrowEth()\n      resetEthAmountOutFromDeposit()\n      resetSqueethAmountInFromDeposit()\n      return\n    }\n\n    const fee = getUSDCPoolFee(network)\n    getExactIn(usdc, weth, fromTokenAmount(depositAmountBN, USDC_DECIMALS), fee, slippage).then((usdcq) => {\n      setDepositEthAmount(toTokenAmount(usdcq.amountOut, WETH_DECIMALS))\n      calculateETHtoBorrowFromUniswap(toTokenAmount(usdcq.minAmountOut, WETH_DECIMALS), slippage).then((q) => {\n        setBorrowEth(q.ethBorrow)\n        setEthAmountOutFromDeposit(q.amountOut)\n        setSqueethAmountInFromDeposit(q.initialWSqueethDebt)\n        let quotePriceImpact = q.priceImpact\n        if (q.poolFee) quotePriceImpact = (Number(q.priceImpact) - Number(q.poolFee)).toFixed(2)\n\n        setDepositPriceImpact(quotePriceImpact)\n        setUniswapFee(q.poolFee)\n      })\n    })\n  }, [ready, depositAmountBN, slippage, network, usdc, weth])\n\n  const recordAnalytics = useCallback(\n    (events: string[]) => {\n      events.forEach((event) => track(event))\n    },\n    [track],\n  )\n\n  const onTxnConfirmed = useCallback(\n    (id?: string) => {\n      if (!ongoingTransaction.current) return\n      const transaction = ongoingTransaction.current\n      if (transaction.queuedTransaction)\n        setUsdcQueued(usdcQueued.plus(fromTokenAmount(transaction.amount, USDC_DECIMALS)))\n      else {\n        setStrategyData()\n      }\n      onTxnConfirm({\n        status: true,\n        amount: transaction.amount,\n        tradeType: CrabTradeType.Deposit,\n        transactionType: transaction.queuedTransaction\n          ? CrabTradeTransactionType.Queued\n          : CrabTradeTransactionType.Instant,\n        token: transaction.token,\n        id,\n      })\n      transaction.analytics ? recordAnalytics(transaction.analytics) : null\n      onInputChange('0')\n      resetTracking()\n      refetchUsdcBalance()\n      ongoingTransaction.current = undefined\n    },\n    [\n      usdcQueued,\n      setUsdcQueued,\n      setStrategyData,\n      onTxnConfirm,\n      onInputChange,\n      refetchUsdcBalance,\n      recordAnalytics,\n      resetTracking,\n    ],\n  )\n\n  const depositTX = async () => {\n    setTxLoading(true)\n    try {\n      if (depositStep === DepositSteps.APPROVE) {\n        if (useQueue) {\n          await logAndRunTransaction(async () => {\n            await approveQueueUsdc(() => resetTransactionData())\n          }, CRAB_EVENTS.APPROVE_DEPOSIT_STN_CRAB_USDC)\n        } else {\n          await logAndRunTransaction(async () => {\n            await approveUsdc(() => resetTransactionData())\n          }, CRAB_EVENTS.APPROVE_DEPOSIT_CRAB_USDC)\n        }\n      } else {\n        const userForceInstantAnalytics = queueOptionAvailable && !useQueue\n        ongoingTransaction.current = {\n          amount: depositAmountBN,\n          queuedTransaction: useQueue,\n          token: 'USDC',\n          analytics: userForceInstantAnalytics ? [CRAB_EVENTS.USER_FORCE_INSTANT_DEP_CRAB] : undefined,\n        }\n        if (useQueue) {\n          await queueUSDC(depositAmountBN, onTxnConfirmed)\n        } else {\n          await flashDepositUSDC(depositAmountBN, slippage, onTxnConfirmed)\n        }\n      }\n    } catch (e) {\n      console.log(e)\n      resetTracking()\n      setTxLoading(false)\n    }\n    setTxLoading(false)\n  }\n\n  const setDepositMax = () => {\n    track(CRAB_EVENTS.DEPOSIT_CRAB_SET_AMOUNT_MAX, { amount: usdcBalance.toNumber() })\n    onInputChange(usdcBalance.toString())\n  }\n\n  // Update deposit step\n  useEffect(() => {\n    if (useQueue) {\n      if (usdcQueueAllowance.lt(depositAmountBN)) {\n        setDepositStep(DepositSteps.APPROVE)\n      } else {\n        setDepositStep(DepositSteps.DEPOSIT)\n      }\n    } else {\n      if (usdcAllowance.lt(depositAmountBN)) {\n        setDepositStep(DepositSteps.APPROVE)\n      } else {\n        setDepositStep(DepositSteps.DEPOSIT)\n      }\n    }\n  }, [usdcAllowance, depositAmountBN, useQueue, usdcQueueAllowance])\n\n  const minUSDCAmount = toTokenAmount(minUSDCAmountValue, USDC_DECIMALS)\n  const isDepositAmountLessThanMinAllowed = depositAmountBN.lt(minUSDCAmount)\n\n  useEffect(() => {\n    if (isDepositAmountLessThanMinAllowed) {\n      setQueueOptionAvailable(false)\n      setUseQueue(false)\n      return\n    }\n\n    if (Number(depositPriceImpact) + Number(uniswapFee) > OTC_PRICE_IMPACT_THRESHOLD) {\n      setQueueOptionAvailable(true)\n      if (userOverrode) return\n      setUseQueue(true)\n    } else {\n      setQueueOptionAvailable(false)\n      if (userOverrode) return\n      setUseQueue(false)\n    }\n  }, [depositPriceImpact, isDepositAmountLessThanMinAllowed, uniswapFee, userOverrode])\n\n  const totalDepositsQueued = useAtomValue(totalUsdcQueuedAtom)\n  const totalWithdrawsQueued = useAtomValue(totalCrabQueueInUsddAtom)\n\n  const depositPriceImpactNumber = useAppMemo(() => {\n    if (!useQueue) return Number(depositPriceImpact)\n\n    const totalWithdraws = totalWithdrawsQueued.minus(totalDepositsQueued).isNegative()\n      ? new BigNumber(0)\n      : totalWithdrawsQueued.minus(totalDepositsQueued)\n\n    const nettingDepositAmount = totalWithdraws.gt(depositAmountBN) ? depositAmountBN : totalWithdraws\n    const remainingDeposit = depositAmountBN.minus(nettingDepositAmount)\n\n    const priceImpact = nettingDepositAmount\n      .times(NETTING_PRICE_IMPACT)\n      .plus(remainingDeposit.times(AVERAGE_AUCTION_PRICE_IMPACT))\n      .div(depositAmountBN)\n      .toNumber()\n\n    return priceImpact\n  }, [depositAmountBN, depositPriceImpact, totalDepositsQueued, totalWithdrawsQueued, useQueue])\n\n  const depositBtnVariant =\n    depositPriceImpactNumber > 3 || depositFundingWarning || depositPriceImpactWarning ? 'outlined' : 'contained'\n  const depositBtnClassName =\n    depositPriceImpactNumber > 3\n      ? classes.btnDanger\n      : depositFundingWarning || depositPriceImpactWarning\n      ? classes.btnWarning\n      : ''\n\n  const onChangeSlippage = useCallback(\n    (amount: BigNumber) => {\n      track(CRAB_EVENTS.DEPOSIT_CRAB_CHANGE_SLIPPAGE, { percent: amount.toNumber() })\n      setSlippage(amount.toNumber())\n    },\n    [track, setSlippage],\n  )\n\n  return (\n    <>\n      <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" gridGap=\"12px\">\n        <Typography variant=\"h3\" className={classes.subtitle}>\n          Strategy Deposit\n        </Typography>\n      </Box>\n\n      <Box display=\"flex\" alignItems=\"center\" gridGap=\"12px\" marginTop=\"16px\">\n        <RoundedButton\n          disabled={Number(depositAmount) >= STRATEGY_DEPOSIT_LIMIT || !Number(depositAmount)}\n          variant=\"outlined\"\n          size=\"small\"\n          onClick={() => {\n            setUseQueue(false)\n            setUserOverrode(true)\n          }}\n          className={!useQueue ? classes.btnActive : classes.btnDefault}\n        >\n          Instant\n        </RoundedButton>\n        <RoundedButton\n          disabled={!queueOptionAvailable}\n          variant={!queueOptionAvailable ? 'contained' : 'outlined'}\n          size=\"small\"\n          onClick={() => {\n            setUseQueue(true)\n            setUserOverrode(true)\n          }}\n          className={useQueue ? classes.btnActive : classes.btnDefault}\n        >\n          Standard\n        </RoundedButton>\n        <Box className={classes.infoIconGray} display=\"flex\" alignItems=\"center\">\n          <Tooltip\n            title={`Standard attempts to reduce price impact and gas costs, but will not get into the strategy immediately. Instant gets in immediately.`}\n          >\n            <HelpOutlineIcon fontSize=\"medium\" />\n          </Tooltip>\n        </Box>\n      </Box>\n\n      <div className={classes.tradeContainer}>\n        <InputToken\n          id=\"crab-deposit-usdc-input\"\n          value={depositAmount}\n          onInputChange={onInputChange}\n          balance={usdcBalance}\n          logo={usdcLogo}\n          symbol={'USDC'}\n          usdPrice={new BigNumber(1)}\n          onBalanceClick={setDepositMax}\n          error={!!depositError}\n          helperText={depositError}\n        />\n        {depositFundingWarning && !useQueue && (\n          <div className={classes.notice}>\n            <div className={classes.infoIcon}>\n              <Tooltip\n                title={\n                  'The strategy sells squeeth to earn premium. Premium is currently lower than usual. You can still deposit, but you may be more likely to have negative returns.'\n                }\n              >\n                <InfoIcon fontSize=\"medium\" />\n              </Tooltip>\n            </div>\n            <Typography variant=\"caption\" className={classes.infoText}>\n              Crab premium is currently lower than usual. Consider depositing later.\n            </Typography>\n          </div>\n        )}\n        {depositPriceImpactWarning && (\n          <div className={classes.notice}>\n            <div className={classes.infoIcon}>\n              <Tooltip\n                title={\n                  'High price impact means that you are losing a significant amount of value due to the size of your trade. Depositing a smaller size can reduce your price impact.'\n                }\n              >\n                <InfoIcon fontSize=\"medium\" />\n              </Tooltip>\n            </div>\n            <Typography variant=\"caption\" className={classes.infoText}>\n              High price impact. Try multiple smaller transactions or standard deposit\n            </Typography>\n          </div>\n        )}\n        <Box marginTop=\"24px\">\n          <Box display=\"flex\" alignItems=\"center\" justifyContent=\"space-between\" gridGap=\"12px\" flexWrap=\"wrap\">\n            <Metric\n              label=\"Uniswap Fee\"\n              value={useQueue ? '0%' : formatNumber(Number(uniswapFee)) + '%'}\n              isSmall\n              flexDirection=\"row\"\n              justifyContent=\"space-between\"\n              gridGap=\"8px\"\n            />\n\n            <Box display=\"flex\" alignItems=\"center\" gridGap=\"6px\" flex=\"1\">\n              <Metric\n                isSmall\n                label={\n                  <MetricLabel\n                    isSmall\n                    label={useQueue ? 'Est. Price Impact' : 'Price Impact'}\n                    tooltipTitle={useQueue ? 'Average price impact based on historical standard deposits' : undefined}\n                  />\n                }\n                value={formatNumber(depositPriceImpactNumber) + '%'}\n                textColor={depositPriceImpactNumber > 3 ? 'error' : undefined}\n                flexDirection=\"row\"\n                justifyContent=\"space-between\"\n                gridGap=\"8px\"\n              />\n\n              {!useQueue && <TradeSettings setSlippage={onChangeSlippage} slippage={new BigNumber(slippage)} />}\n            </Box>\n          </Box>\n        </Box>\n        <div className={classes.ctaSection}>\n          {/* {useQueue && (\n            <div className={classes.queueNotice}>\n              <Typography variant=\"subtitle2\" color=\"primary\">\n                To reduce price impact, your deposit may take up until Tuesday to enter the strategy\n              </Typography>\n            </div>\n          )} */}\n\n          {isRestricted && <RestrictionInfo withdrawAllowed={isWithdrawAllowed} />}\n\n          <div>\n            {isRestricted ? (\n              <PrimaryButtonNew\n                fullWidth\n                variant=\"contained\"\n                onClick={selectWallet}\n                disabled={true}\n                id=\"open-long-restricted-btn\"\n              >\n                {'Unavailable'}\n              </PrimaryButtonNew>\n            ) : !connected ? (\n              <PrimaryButtonNew\n                fullWidth\n                variant=\"contained\"\n                onClick={selectWallet}\n                disabled={!!txLoading}\n                id=\"crab-select-wallet-btn\"\n              >\n                {'Connect Wallet'}\n              </PrimaryButtonNew>\n            ) : !supportedNetwork ? (\n              <PrimaryButtonNew\n                fullWidth\n                variant=\"contained\"\n                onClick={() => {}}\n                disabled={true}\n                id=\"crab-unsupported-network-btn\"\n              >\n                {'Unsupported Network'}\n              </PrimaryButtonNew>\n            ) : (\n              <PrimaryButtonNew\n                fullWidth\n                id=\"crab-deposit-btn\"\n                variant={depositBtnVariant}\n                className={depositBtnClassName}\n                onClick={depositTX}\n                disabled={txLoading || !!depositError}\n              >\n                {!txLoading && useQueue && depositStep === DepositSteps.DEPOSIT ? (\n                  <>\n                    Standard deposit\n                    <Tooltip\n                      title={\n                        <div>\n                          Your deposit will be submitted via auction to reduce price impact. This may take until\n                          Tuesday.\n                        </div>\n                      }\n                      style={{ marginLeft: '8' }}\n                    >\n                      <InfoOutlinedIcon fontSize=\"small\" />\n                    </Tooltip>\n                  </>\n                ) : !txLoading &&\n                  (depositFundingWarning || depositPriceImpactWarning) &&\n                  depositStep === DepositSteps.DEPOSIT ? (\n                  'Deposit anyway'\n                ) : !txLoading ? (\n                  depositStep\n                ) : (\n                  <CircularProgress color=\"primary\" size=\"1.5rem\" />\n                )}\n              </PrimaryButtonNew>\n            )}\n          </div>\n        </div>\n      </div>\n    </>\n  )\n}\n\nexport default CrabDeposit\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CrabTradeV2/Withdraw.tsx",
    "content": "import { Box, CircularProgress, Typography, Stepper, Step, StepLabel, Collapse, Tooltip } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport React, { useEffect, useState, useCallback, useRef, useMemo } from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { PrimaryButtonNew } from '@components/Button'\nimport RestrictionInfo from '@components/RestrictionInfo'\nimport { InputToken } from '@components/InputNew'\nimport Metric from '@components/Metric'\nimport { connectedWalletAtom, supportedNetworkAtom } from '@state/wallet/atoms'\nimport { useTransactionStatus, useSelectWallet } from '@state/wallet/hooks'\nimport {\n  useSetStrategyData,\n  useSetStrategyDataV2,\n  useCalculateEthToReceiveShutdown,\n  useClaimV2Shares,\n  useWithdrawShutdown,\n} from '@state/crab/hooks'\nimport { addressesAtom } from '@state/positions/atoms'\nimport { userMigratedSharesAtom } from '@state/crabMigration/atom'\nimport { useUpdateSharesData } from '@state/crabMigration/hooks'\nimport { useUserAllowance } from '@hooks/contracts/useAllowance'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport { formatNumber } from '@utils/formatter'\nimport { useStyles } from './styles'\nimport { CrabTradeTransactionType, CrabTradeType, CrabTransactionConfirmation, OngoingTransaction } from './types'\nimport { CRAB_EVENTS } from '@utils/amplitude'\nimport useAmplitude from '@hooks/useAmplitude'\nimport Alert from '@components/Alert'\nimport { useRestrictUser } from '@context/restrict-user'\nimport { SqueethTabsNew, SqueethTabNew } from '@components/Tabs'\n\nenum RedeemStepsV1 {\n  // APPROVE = 'Approve CRAB', // Not needed since contract is token\n  REDEEM = 'Redeem ETH',\n}\n\nenum RedeemStepsV2 {\n  CLAIM = 'Claim CRAB',\n  // APPROVE = 'Approve CRAB', // Not needed since contract is token\n  REDEEM = 'Redeem ETH',\n}\n\nconst CrabWithdraw: React.FC<{ onTxnConfirm: (txn: CrabTransactionConfirmation) => void }> = ({ onTxnConfirm }) => {\n  const classes = useStyles()\n\n  // loading states\n  const [isInitialLoading, setIsInitialLoading] = useState(true)\n  const [isEthToReceiveLoading, setIsEthToReceiveLoading] = useState(false)\n  const [txLoading, setTxLoading] = useState(false)\n\n  const [selectedVersion, setSelectedVersion] = useState<'v1' | 'v2'>('v2')\n  const [currentStepV1, setCurrentStepV1] = useState<RedeemStepsV1>(RedeemStepsV1.REDEEM)\n  const [currentStepV2, setCurrentStepV2] = useState<RedeemStepsV2>(RedeemStepsV2.CLAIM)\n  const [ethToReceive, setEthToReceive] = useState(new BigNumber(0))\n\n  const ongoingTransaction = useRef<OngoingTransaction | undefined>()\n\n  const connected = useAtomValue(connectedWalletAtom)\n  const { isRestricted, isWithdrawAllowed } = useRestrictUser()\n\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n\n  const { crabStrategy, crabStrategy2 } = useAtomValue(addressesAtom)\n  const {\n    value: currentCrabV1Balance,\n    refetch: refetchCrabV1Balance,\n    loading: isCrabV1BalanceLoading,\n  } = useTokenBalance(crabStrategy, 30, 18)\n  const {\n    value: currentCrabV2Balance,\n    refetch: refetchCrabV2Balance,\n    loading: isCrabV2BalanceLoading,\n  } = useTokenBalance(crabStrategy2, 30, 18)\n  const migratedCrabBalance = useAtomValue(userMigratedSharesAtom)\n\n  const { resetTransactionData } = useTransactionStatus()\n  const selectWallet = useSelectWallet()\n  const { track } = useAmplitude()\n\n  const claimV2Shares = useClaimV2Shares()\n  const calculateEthToReceive = useCalculateEthToReceiveShutdown(selectedVersion)\n  const withdrawShutdown = useWithdrawShutdown(selectedVersion)\n\n  const updateMigrationSharesData = useUpdateSharesData()\n  const setStrategyDataV1 = useSetStrategyData()\n  const setStrategyDataV2 = useSetStrategyDataV2()\n\n  useEffect(() => {\n    const loading = selectedVersion === 'v1' ? isCrabV1BalanceLoading : isCrabV2BalanceLoading\n    if (!loading) {\n      setIsInitialLoading(false)\n    }\n  }, [selectedVersion, isCrabV1BalanceLoading, isCrabV2BalanceLoading])\n\n  // Determine initial step for V1\n  useEffect(() => {\n    if (!currentCrabV1Balance) return\n\n    setCurrentStepV1(RedeemStepsV1.REDEEM)\n  }, [currentCrabV1Balance?.toString()])\n\n  // Determine initial step based on migrated balance and allowance\n  useEffect(() => {\n    if (!currentCrabV2Balance) return\n\n    if (migratedCrabBalance.gt(0)) {\n      setCurrentStepV2(RedeemStepsV2.CLAIM)\n    } else {\n      setCurrentStepV2(RedeemStepsV2.REDEEM)\n    }\n  }, [currentCrabV2Balance?.toString(), migratedCrabBalance?.toString()])\n\n  useEffect(() => {\n    let mounted = true\n\n    const getEthToReceive = async () => {\n      const balance = selectedVersion === 'v1' ? currentCrabV1Balance : currentCrabV2Balance\n\n      if (balance.eq(0)) {\n        if (mounted) {\n          setEthToReceive(new BigNumber(0))\n          setIsEthToReceiveLoading(false)\n        }\n        return\n      }\n\n      setIsEthToReceiveLoading(true)\n      try {\n        const ethAmount = await calculateEthToReceive(balance)\n        if (mounted) {\n          setEthToReceive(ethAmount || new BigNumber(0))\n          setIsEthToReceiveLoading(false)\n        }\n      } catch (error) {\n        console.error('Error calculating ETH to receive:', error)\n        if (mounted) {\n          setIsEthToReceiveLoading(false)\n        }\n      }\n    }\n\n    getEthToReceive()\n\n    return () => {\n      mounted = false\n    }\n  }, [selectedVersion, calculateEthToReceive, currentCrabV1Balance?.toString(), currentCrabV2Balance?.toString()])\n\n  const handleClaimV2Shares = async () => {\n    setTxLoading(true)\n    try {\n      await claimV2Shares()\n      setCurrentStepV2(RedeemStepsV2.REDEEM)\n      track(CRAB_EVENTS.CLAIM_CRABV2_SUCCESS)\n\n      updateMigrationSharesData()\n      setStrategyDataV2()\n      refetchCrabV2Balance()\n    } catch (e) {\n      console.error(e)\n      track(CRAB_EVENTS.CLAIM_CRABV2_FAILED)\n    }\n    setTxLoading(false)\n  }\n\n  const handleRedeemCrabV1 = async () => {\n    setTxLoading(true)\n    try {\n      ongoingTransaction.current = {\n        amount: currentCrabV1Balance,\n        token: 'ETH',\n        queuedTransaction: false,\n        analytics: [CRAB_EVENTS.REDEEM_CRABV1],\n      }\n\n      await withdrawShutdown(currentCrabV1Balance, onRedeemTxnConfirmed)\n      track(CRAB_EVENTS.REDEEM_CRABV1_SUCCESS)\n\n      setStrategyDataV1()\n      refetchCrabV1Balance()\n\n      // Switch to V2 tab after successful redemption\n      setSelectedVersion('v2')\n    } catch (e) {\n      console.error(e)\n      track(CRAB_EVENTS.REDEEM_CRABV1_FAILED)\n    }\n    setTxLoading(false)\n  }\n\n  const handleRedeemCrabV2 = async () => {\n    setTxLoading(true)\n    try {\n      ongoingTransaction.current = {\n        amount: currentCrabV2Balance,\n        token: 'ETH',\n        queuedTransaction: false,\n        analytics: [CRAB_EVENTS.REDEEM_CRABV2],\n      }\n\n      await withdrawShutdown(currentCrabV2Balance, onRedeemTxnConfirmed)\n      track(CRAB_EVENTS.REDEEM_CRABV2_SUCCESS)\n\n      setStrategyDataV2()\n      refetchCrabV2Balance()\n    } catch (e) {\n      console.error(e)\n      track(CRAB_EVENTS.REDEEM_CRABV2_FAILED)\n    }\n    setTxLoading(false)\n  }\n\n  const buttonText = useMemo(() => {\n    if (isInitialLoading || txLoading) {\n      return <CircularProgress color=\"primary\" size=\"1.5rem\" />\n    }\n\n    if (selectedVersion === 'v1') {\n      switch (currentStepV1) {\n        case RedeemStepsV1.REDEEM:\n          return 'Redeem ETH'\n        default:\n          return 'Redeem'\n      }\n    } else {\n      switch (currentStepV2) {\n        case RedeemStepsV2.CLAIM:\n          return 'Claim CRAB'\n        case RedeemStepsV2.REDEEM:\n          return 'Redeem ETH'\n        default:\n          return 'Redeem'\n      }\n    }\n  }, [isInitialLoading, txLoading, currentStepV1, currentStepV2, selectedVersion])\n\n  const handleAction = () => {\n    if (selectedVersion === 'v1') {\n      switch (currentStepV1) {\n        case RedeemStepsV1.REDEEM:\n          return handleRedeemCrabV1()\n      }\n    } else {\n      switch (currentStepV2) {\n        case RedeemStepsV2.CLAIM:\n          return handleClaimV2Shares()\n\n        case RedeemStepsV2.REDEEM:\n          return handleRedeemCrabV2()\n      }\n    }\n  }\n\n  const recordAnalytics = useCallback(\n    (events: string[]) => {\n      events.forEach((event) => track(event))\n    },\n    [track],\n  )\n\n  const onRedeemTxnConfirmed = useCallback(\n    (id?: string) => {\n      if (!ongoingTransaction.current) return\n      const transaction = ongoingTransaction.current\n\n      onTxnConfirm({\n        status: true,\n        amount: transaction.amount,\n        tradeType: CrabTradeType.Redeem,\n        transactionType: CrabTradeTransactionType.Instant,\n        token: transaction.token,\n        id,\n      })\n      transaction.analytics ? recordAnalytics(transaction.analytics) : null\n\n      ongoingTransaction.current = undefined\n    },\n    [onTxnConfirm, recordAnalytics],\n  )\n\n  // Memoize error state\n  const redeemError = useMemo(() => {\n    if (!connected) {\n      return undefined\n    }\n    if (isInitialLoading) {\n      return undefined\n    }\n\n    if (selectedVersion === 'v1') {\n      if (currentCrabV1Balance.lte(0)) {\n        return 'No V1 position to redeem'\n      }\n    } else {\n      const isRedeemStep = currentStepV2 === RedeemStepsV2.REDEEM\n      if (isRedeemStep && currentCrabV2Balance.lte(0)) {\n        return 'No position to redeem'\n      }\n    }\n    return undefined\n  }, [\n    connected,\n    selectedVersion,\n    isInitialLoading,\n    currentCrabV1Balance?.toString(),\n    currentStepV2,\n    currentCrabV2Balance?.toString(),\n  ])\n\n  // Get current balance based on version and step\n  const currentBalance = useMemo(() => {\n    if (selectedVersion === 'v1') {\n      return currentCrabV1Balance\n    } else {\n      return currentStepV2 === RedeemStepsV2.CLAIM ? migratedCrabBalance : currentCrabV2Balance\n    }\n  }, [selectedVersion, currentStepV2, currentCrabV1Balance, currentCrabV2Balance, migratedCrabBalance])\n\n  // Get loading state based on version\n  const isBalanceLoading = useMemo(() => {\n    return selectedVersion === 'v1' ? isCrabV1BalanceLoading : isCrabV2BalanceLoading\n  }, [selectedVersion, isCrabV1BalanceLoading, isCrabV2BalanceLoading])\n\n  // Show tabs only if there's a V1 balance before redemption\n  const showVersionTabs = currentCrabV1Balance.gt(0)\n\n  // Set v1 as default tab if there's a V1 balance\n  useEffect(() => {\n    if (showVersionTabs) {\n      setSelectedVersion('v1')\n    }\n  }, [showVersionTabs])\n\n  return (\n    <>\n      <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" gridGap=\"12px\">\n        <Typography variant=\"h3\" className={classes.subtitle}>\n          Strategy Redeem\n        </Typography>\n      </Box>\n\n      <div className={classes.tradeContainer}>\n        {showVersionTabs && (\n          <SqueethTabsNew\n            value={selectedVersion}\n            onChange={(_, newValue) => setSelectedVersion(newValue)}\n            aria-label=\"crab-version-tab\"\n            centered\n            variant=\"fullWidth\"\n            style={{ marginBottom: '1rem' }}\n          >\n            <SqueethTabNew label=\"Crab V1\" value=\"v1\" />\n            <SqueethTabNew label=\"Crab V2\" value=\"v2\" />\n          </SqueethTabsNew>\n        )}\n\n        {selectedVersion === 'v2' && (\n          <RedeemStepperV2 migratedCrabBalance={migratedCrabBalance} currentStepV2={currentStepV2} />\n        )}\n\n        <InputToken\n          id=\"crab-redeem-input\"\n          label=\"Crab Position\"\n          value={currentBalance}\n          balance={currentBalance}\n          isBalanceLoading={isBalanceLoading}\n          symbol=\"CRAB\"\n          showMaxAction={false}\n          error={!!redeemError}\n          helperText={redeemError}\n          readOnly={true}\n          readOnlyTooltip=\"Only full redemption is allowed\"\n        />\n\n        {/* Show ETH to receive for both V1 and V2 */}\n        {(selectedVersion === 'v1' || (selectedVersion === 'v2' && currentStepV2 === RedeemStepsV2.REDEEM)) && (\n          <Box display=\"flex\" alignItems=\"center\" justifyContent=\"space-between\" marginTop=\"12px\">\n            <Metric\n              label=\"ETH you will receive\"\n              value={isEthToReceiveLoading ? 'Loading...' : formatNumber(ethToReceive.toNumber(), 4) + ' ETH'}\n              isSmall\n              flexDirection=\"row\"\n              justifyContent=\"space-between\"\n              gridGap=\"12px\"\n            />\n          </Box>\n        )}\n\n        <Collapse in={!!redeemError}>\n          <Alert severity=\"error\" marginTop=\"24px\">\n            {redeemError}\n          </Alert>\n        </Collapse>\n\n        <div className={classes.ctaSection}>\n          {isRestricted && <RestrictionInfo withdrawAllowed={isWithdrawAllowed} marginTop=\"24px\" />}\n\n          {!connected ? (\n            <PrimaryButtonNew\n              fullWidth\n              variant=\"contained\"\n              onClick={selectWallet}\n              id=\"crab-connect-wallet-btn\"\n              disabled={!!txLoading}\n            >\n              Connect Wallet\n            </PrimaryButtonNew>\n          ) : !supportedNetwork ? (\n            <PrimaryButtonNew fullWidth variant=\"contained\" disabled={true} id=\"crab-unsupported-network-btn\">\n              Unsupported Network\n            </PrimaryButtonNew>\n          ) : (\n            <PrimaryButtonNew\n              fullWidth\n              id=\"crab-redeem-btn\"\n              variant=\"contained\"\n              onClick={handleAction}\n              disabled={txLoading || !!redeemError || isBalanceLoading || isEthToReceiveLoading}\n            >\n              {buttonText}\n            </PrimaryButtonNew>\n          )}\n        </div>\n      </div>\n    </>\n  )\n}\n\nconst RedeemStepperV2: React.FC<{\n  migratedCrabBalance: BigNumber\n  currentStepV2: RedeemStepsV2\n}> = ({ migratedCrabBalance, currentStepV2 }) => {\n  const classes = useStyles()\n\n  // Only show stepper if there's migrated balance\n  if (migratedCrabBalance.eq(0)) {\n    return null\n  }\n\n  const getActiveStep = () => {\n    if (migratedCrabBalance.gt(0)) {\n      // If there's migrated balance, count from all three steps\n      switch (currentStepV2) {\n        case RedeemStepsV2.CLAIM:\n          return 0\n        case RedeemStepsV2.REDEEM:\n          return 1\n        default:\n          return 0\n      }\n    } else {\n      // If no migrated balance, count from approve and redeem only\n      switch (currentStepV2) {\n        case RedeemStepsV2.REDEEM:\n          return 0\n        default:\n          return 0\n      }\n    }\n  }\n\n  return (\n    <div className={classes.stepperContainer}>\n      <Collapse in={migratedCrabBalance.gt(0)}>\n        <Alert severity=\"warning\">\n          {'You have unclaimed Crab v2 tokens from CrabMigration. Claim them before redeeming for ETH.'}\n        </Alert>\n      </Collapse>\n\n      <Stepper activeStep={getActiveStep()} className={classes.stepper}>\n        <Step key=\"claim\">\n          <StepLabel>\n            <Tooltip title=\"Claim CrabV2 tokens from CrabMigration contract\" placement=\"top\">\n              <Typography>Claim CRAB</Typography>\n            </Tooltip>\n          </StepLabel>\n        </Step>\n        <Step key=\"redeem\">\n          <StepLabel>\n            <Tooltip title=\"Redeem CrabV2 tokens to get ETH\" placement=\"top\">\n              <Typography>Redeem ETH</Typography>\n            </Tooltip>\n          </StepLabel>\n        </Step>\n      </Stepper>\n    </div>\n  )\n}\n\nexport default CrabWithdraw\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CrabTradeV2/index.tsx",
    "content": "import { Box } from '@material-ui/core'\nimport React, { useState, useCallback } from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport Withdraw from './Withdraw'\nimport { useTransactionStatus } from '@state/wallet/hooks'\nimport Confirmed, { ConfirmType } from '@components/Trade/Confirmed'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { PrimaryButtonNew } from '@components/Button'\nimport { CrabTransactionConfirmation, CrabTradeType, CrabTradeTransactionType } from './types'\nimport { useCrabPositionV2 } from '@hooks/useCrabPosition/useCrabPosition'\nimport { addressAtom } from '@state/wallet/atoms'\nimport { addressesAtom } from '@state/positions/atoms'\nimport BigNumber from 'bignumber.js'\n\nconst CrabTradeV2: React.FC<{ refetchCrabTokenBalance: (cb?: (newBalance: BigNumber) => void | undefined) => void }> =\n  ({ refetchCrabTokenBalance }) => {\n    const address = useAtomValue(addressAtom)\n    const [confirmedTransactionData, setConfirmedTransactionData] = useState<CrabTransactionConfirmation | undefined>()\n    const { confirmed, resetTransactionData, transactionData } = useTransactionStatus()\n    const { pollForNewTx } = useCrabPositionV2(address ?? '')\n\n    const confirmationMessage = useAppMemo(() => {\n      if (!confirmedTransactionData?.status) return ``\n      if (confirmedTransactionData.tradeType === CrabTradeType.Deposit) {\n        return confirmedTransactionData.transactionType === CrabTradeTransactionType.Queued\n          ? `Initiated ${confirmedTransactionData.amount.toFixed(4)} ${confirmedTransactionData.token} deposit`\n          : `Deposited ${confirmedTransactionData.amount.toFixed(4)} ${confirmedTransactionData.token}`\n      }\n      if (confirmedTransactionData.tradeType === CrabTradeType.Withdraw) {\n        return confirmedTransactionData.transactionType === CrabTradeTransactionType.Queued\n          ? `Initiated ${confirmedTransactionData.amount.toFixed(4)} ${confirmedTransactionData.token} withdraw`\n          : `Withdrawn ${confirmedTransactionData.amount.toFixed(4)} ${confirmedTransactionData.token}`\n      }\n      if (confirmedTransactionData.tradeType === CrabTradeType.Redeem) {\n        return confirmedTransactionData.transactionType === CrabTradeTransactionType.Queued\n          ? `Initiated ${confirmedTransactionData.amount.toFixed(4)} ${confirmedTransactionData.token} redeem`\n          : `Redeemed ${confirmedTransactionData.amount.toFixed(4)} ${confirmedTransactionData.token}`\n      }\n      return ``\n    }, [confirmedTransactionData])\n\n    const onClose = useCallback(() => {\n      setConfirmedTransactionData(undefined)\n      resetTransactionData()\n    }, [resetTransactionData, setConfirmedTransactionData])\n\n    const onTxnConfirm = useCallback(\n      (confirm?: CrabTransactionConfirmation) => {\n        setConfirmedTransactionData(confirm)\n        confirm?.id ? pollForNewTx(confirm?.id) : null\n        refetchCrabTokenBalance()\n      },\n      [setConfirmedTransactionData, pollForNewTx, refetchCrabTokenBalance],\n    )\n\n    if (confirmed && confirmedTransactionData?.status) {\n      return (\n        <>\n          <Confirmed\n            confirmationMessage={confirmationMessage}\n            txnHash={transactionData?.hash ?? ''}\n            confirmType={ConfirmType.CRAB}\n          />\n          <PrimaryButtonNew fullWidth id=\"crab-close-btn\" variant=\"contained\" onClick={onClose}>\n            Close\n          </PrimaryButtonNew>\n        </>\n      )\n    }\n\n    return <Withdraw onTxnConfirm={onTxnConfirm} />\n  }\n\nexport default CrabTradeV2\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CrabTradeV2/styles.ts",
    "content": "import { makeStyles, createStyles } from '@material-ui/core/styles'\n\nexport const useStyles = makeStyles((theme) =>\n  createStyles({\n    link: {\n      color: theme.palette.primary.main,\n    },\n    tradeContainer: {\n      display: 'flex',\n      flexDirection: 'column',\n      marginTop: theme.spacing(3),\n    },\n    notice: {\n      marginTop: theme.spacing(2.5),\n      padding: theme.spacing(2),\n      border: `1px solid #F3FF6C`,\n      borderRadius: theme.spacing(1),\n      display: 'flex',\n      background: 'rgba(243, 255, 108, 0.1)',\n      alignItems: 'center',\n    },\n    infoIcon: {\n      marginRight: theme.spacing(2),\n      color: '#F3FF6C',\n    },\n    noticeGray: {\n      marginTop: theme.spacing(2.5),\n      padding: theme.spacing(2.5),\n      border: `1px solid ${theme.palette.background.stone}`,\n      borderRadius: theme.spacing(1),\n      display: 'flex',\n      background: theme.palette.background.lightStone,\n      alignItems: 'center',\n    },\n    infoIconGray: {\n      marginRight: theme.spacing(2),\n      color: theme.palette.text.hint,\n    },\n    tokenSelectBox: {\n      display: 'flex',\n      alignItems: 'center',\n      gridGap: theme.spacing(0.5),\n    },\n    tokenChoice: {\n      fontWeight: 500,\n      fontSize: '14px',\n    },\n    subtitle: {\n      fontSize: '18px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n      lineHeight: '130%',\n    },\n    infoText: {\n      fontWeight: 500,\n      fontSize: '13px',\n    },\n    ctaSection: {\n      marginTop: theme.spacing(3),\n      display: 'flex',\n      flexDirection: 'column',\n      gap: '16px',\n    },\n    queueNotice: {\n      background: theme.palette.background.stone,\n      borderRadius: theme.spacing(1.5),\n      padding: theme.spacing(2),\n      textAlign: 'center',\n    },\n    btnDefault: {\n      color: 'rgba(255, 255, 255, 0.4)',\n      border: '2px solid transparent',\n    },\n    btnActive: {\n      color: theme.palette.primary.main,\n      border: `2px solid ${theme.palette.primary.main}`,\n    },\n    btnDanger: {\n      color: theme.palette.error.main,\n      borderColor: theme.palette.error.main,\n      backgroundColor: 'transparent',\n\n      '&:hover': {\n        color: theme.palette.error.main,\n        borderColor: theme.palette.error.main,\n        backgroundColor: 'transparent',\n      },\n    },\n    btnWarning: {\n      color: theme.palette.warning.main,\n      borderColor: theme.palette.warning.main,\n      backgroundColor: 'transparent',\n\n      '&:hover': {\n        color: theme.palette.warning.main,\n        borderColor: theme.palette.warning.main,\n        backgroundColor: 'transparent',\n      },\n    },\n    withdrawStepsContainer: {\n      marginBottom: theme.spacing(2),\n    },\n    stepperContainer: {\n      marginBottom: theme.spacing(2),\n      display: 'flex',\n      flexDirection: 'column',\n      gap: theme.spacing(2),\n    },\n    stepper: {\n      width: '100%',\n      backgroundColor: theme.palette.background.stone,\n      borderRadius: '12px',\n\n      '& .MuiStepIcon-active .MuiStepIcon-text': {\n        // Black color for active step number\n        fill: theme.palette.common.black,\n      },\n    },\n  }),\n)\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/CrabTradeV2/types.ts",
    "content": "import BigNumber from 'bignumber.js'\n\nexport enum CrabTradeType {\n  Deposit = 'Deposit',\n  Withdraw = 'Withdraw',\n  Redeem = 'Redeem',\n}\n\nexport enum CrabTradeTransactionType {\n  Instant = 'Instant',\n  Queued = 'Queued',\n}\n\nexport interface CrabTransactionConfirmation {\n  status: boolean\n  amount: BigNumber\n  tradeType: CrabTradeType\n  transactionType: CrabTradeTransactionType\n  token: 'USDC' | 'ETH'\n  id?: string\n}\n\nexport interface OngoingTransaction {\n  amount: BigNumber\n  queuedTransaction: boolean\n  token: 'ETH' | 'USDC'\n  analytics?: string[]\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/MigrationNotice.tsx",
    "content": "import { Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport clsx from 'clsx'\nimport React from 'react'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(2),\n      border: '1px solid rgba(19, 131, 17)',\n      borderRadius: theme.spacing(2),\n      display: 'flex',\n    },\n  }),\n)\n\nconst MigrationNotice: React.FC = () => {\n  const classes = useStyles()\n\n  return (\n    <div className={clsx(classes.container, 'crab-notice')}>\n      <div>\n        <Typography variant=\"h6\">🦀</Typography>\n      </div>\n      <div style={{ marginLeft: '8px' }}>\n        <Typography variant=\"body1\">Crab V2 Early Access: guarantee your spot </Typography>\n        <Typography component=\"p\" variant=\"caption\" style={{ marginTop: '4px', lineHeight: 1.5 }} color=\"textSecondary\">\n          As OG crabbers, you get to be included v2 before anyone else. Guarantee your spot in Crab v2 right when it\n          drops!\n        </Typography>\n      </div>\n    </div>\n  )\n}\n\nexport default MigrationNotice\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/MyPosition/CrabPosition.tsx",
    "content": "import React from 'react'\nimport { Box, Typography } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport clsx from 'clsx'\n\nimport { formatCurrency } from '@utils/formatter'\nimport useStyles from '@components/Strategies/styles'\nimport SharePnl from '@components/Strategies/SharePnl'\nimport PnL from './PnL'\n\ninterface CrabPositionProps {\n  depositedUsd: BigNumber\n  currentPosition: BigNumber\n  pnl: BigNumber\n  firstDepositTimestamp: number\n}\n\nconst CrabPosition: React.FC<CrabPositionProps> = ({ depositedUsd, currentPosition, pnl, firstDepositTimestamp }) => {\n  const classes = useStyles()\n\n  const isPnlLoading = !pnl.isFinite()\n\n  return (\n    <Box display=\"flex\" flexDirection=\"column\" gridGap=\"12px\">\n      <div>\n        <Typography variant=\"h4\" className={classes.sectionTitle}>\n          My Crab Position\n        </Typography>\n\n        <Box display=\"flex\" alignItems=\"baseline\" gridColumnGap=\"12px\" gridRowGap=\"2px\" flexWrap=\"wrap\" marginTop=\"6px\">\n          <Typography className={clsx(classes.heading, classes.textMonospace)}>\n            {formatCurrency(currentPosition.toNumber())}\n          </Typography>\n\n          <PnL isPnlLoading={isPnlLoading} depositedUsd={depositedUsd} pnl={pnl} />\n        </Box>\n      </div>\n\n      <SharePnl\n        isPnlLoading={isPnlLoading}\n        strategy=\"crab\"\n        pnl={pnl.toNumber()}\n        firstDepositTimestamp={firstDepositTimestamp}\n      />\n    </Box>\n  )\n}\n\nexport default CrabPosition\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/MyPosition/PnL.tsx",
    "content": "import { Typography, Box, CircularProgress } from '@material-ui/core'\nimport React, { memo } from 'react'\nimport clsx from 'clsx'\nimport ArrowDropUpIcon from '@material-ui/icons/ArrowDropUp'\nimport ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown'\nimport BigNumber from 'bignumber.js'\n\nimport useStyles from '@components/Strategies/styles'\nimport { formatNumber, formatCurrency } from '@utils/formatter'\n\ninterface PnLProps {\n  isPnlLoading: Boolean\n  depositedUsd: BigNumber\n  pnl: BigNumber\n}\n\nconst PnL: React.FC<PnLProps> = ({ isPnlLoading, depositedUsd, pnl }) => {\n  const classes = useStyles()\n\n  if (isPnlLoading) {\n    return (\n      <Box display=\"flex\" alignItems=\"center\" gridGap=\"8px\">\n        <CircularProgress size=\"1rem\" className={classes.loadingSpinner} />\n        <Typography className={classes.text}>fetching pnl...</Typography>\n      </Box>\n    )\n  }\n\n  const isPnlPositive = pnl.isGreaterThanOrEqualTo(0)\n  const textClassName = clsx(\n    classes.description,\n    classes.textSemibold,\n    classes.textMonospace,\n    isPnlPositive ? classes.colorSuccess : classes.colorError,\n  )\n\n  return (\n    <Box display=\"flex\" flexDirection=\"column\" gridGap=\"12px\" position=\"relative\" top=\"2px\">\n      <Box display=\"flex\" gridGap=\"8px\">\n        <Box display=\"flex\" marginLeft=\"-6px\">\n          <div>\n            {isPnlPositive ? (\n              <ArrowDropUpIcon fontSize=\"small\" className={classes.colorSuccess} />\n            ) : (\n              <ArrowDropDownIcon fontSize=\"small\" className={classes.colorError} />\n            )}\n          </div>\n\n          <Typography className={textClassName}>{formatNumber(pnl.toNumber()) + '%'}</Typography>\n        </Box>\n\n        <Typography className={textClassName}>\n          ({isPnlPositive && '+'}\n          {formatCurrency(depositedUsd.times(pnl).div(100).toNumber())})\n        </Typography>\n        <Typography className={classes.description}>since deposit</Typography>\n      </Box>\n    </Box>\n  )\n}\n\nexport default PnL\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/MyPosition/QueuedPosition.tsx",
    "content": "import React, { useState } from 'react'\nimport { Box, Typography, CircularProgress } from '@material-ui/core'\nimport { useAtom, useAtomValue } from 'jotai'\nimport clsx from 'clsx'\n\nimport { formatCurrency } from '@utils/formatter'\nimport useStyles from '@components/Strategies/styles'\nimport { BIG_ZERO, USDC_DECIMALS, CRAB_TOKEN_DECIMALS } from '@constants/index'\nimport { crabQueuedAtom, crabUSDValueAtom, usdcQueuedAtom, isNettingAuctionLiveAtom } from '@state/crab/atoms'\nimport { useDeQueueDepositUSDC, useDeQueueWithdrawCrab } from '@state/crab/hooks'\nimport { useTransactionStatus } from '@state/wallet/hooks'\nimport { toTokenAmount } from '@utils/calculations'\nimport { TextButton } from '@components/Button'\n\nconst DepositQueued: React.FC = () => {\n  const [usdcQueued, setUsdcQueued] = useAtom(usdcQueuedAtom)\n  const isNettingAuctionLive = useAtomValue(isNettingAuctionLiveAtom)\n  const [usdcLoading, setUSDCLoading] = useState(false)\n\n  const dequeueUSDC = useDeQueueDepositUSDC()\n  const { resetTransactionData } = useTransactionStatus()\n\n  const onDeQueueUSDC = async () => {\n    setUSDCLoading(true)\n    try {\n      await dequeueUSDC(usdcQueued, resetTransactionData)\n      setUsdcQueued(BIG_ZERO)\n    } catch (e) {\n      console.log(e)\n    }\n    setUSDCLoading(false)\n  }\n\n  const classes = useStyles()\n\n  return (\n    <Box display=\"flex\" flexDirection=\"column\" gridGap=\"8px\">\n      <Typography variant=\"h4\" className={classes.sectionTitle}>\n        Initiated Deposit\n      </Typography>\n\n      <Box display=\"flex\" alignItems=\"baseline\" gridGap=\"8px\">\n        <Typography className={clsx(classes.heading, classes.textMonospace)}>\n          {formatCurrency(Number(toTokenAmount(usdcQueued, USDC_DECIMALS)))}\n        </Typography>\n        {!isNettingAuctionLive && (\n          <TextButton color=\"primary\" disabled={usdcLoading} onClick={onDeQueueUSDC}>\n            {!usdcLoading ? 'Cancel' : <CircularProgress color=\"primary\" size=\"1.5rem\" />}\n          </TextButton>\n        )}\n      </Box>\n    </Box>\n  )\n}\n\nconst WithdrawQueued: React.FC = () => {\n  const [crabQueued, setCrabQueued] = useAtom(crabQueuedAtom)\n  const isNettingAuctionLive = useAtomValue(isNettingAuctionLiveAtom)\n  const crabUsdValue = useAtomValue(crabUSDValueAtom)\n  const [crabLoading, setCrabLoading] = useState(false)\n\n  const dequeueCRAB = useDeQueueWithdrawCrab()\n  const { resetTransactionData } = useTransactionStatus()\n\n  const onDeQueueCrab = async () => {\n    setCrabLoading(true)\n    try {\n      await dequeueCRAB(crabQueued, resetTransactionData)\n      setCrabQueued(BIG_ZERO)\n    } catch (e) {\n      console.log(e)\n    }\n    setCrabLoading(false)\n  }\n\n  const classes = useStyles()\n\n  return (\n    <Box display=\"flex\" flexDirection=\"column\" gridGap=\"8px\">\n      <Typography variant=\"h4\" className={classes.sectionTitle}>\n        Initiated Withdraw\n      </Typography>\n\n      <Box display=\"flex\" alignItems=\"baseline\" gridGap=\"8px\">\n        <Typography className={clsx(classes.heading, classes.textMonospace)}>\n          {formatCurrency(\n            Number(\n              toTokenAmount(crabQueued, CRAB_TOKEN_DECIMALS).times(toTokenAmount(crabUsdValue, CRAB_TOKEN_DECIMALS)),\n            ),\n          )}\n        </Typography>\n        {!isNettingAuctionLive && (\n          <TextButton color=\"primary\" disabled={crabLoading} onClick={onDeQueueCrab}>\n            {!crabLoading ? 'Cancel' : <CircularProgress color=\"primary\" size=\"1.5rem\" />}\n          </TextButton>\n        )}\n      </Box>\n    </Box>\n  )\n}\n\nconst QueuedPosition: React.FC = () => {\n  const usdcQueued = useAtomValue(usdcQueuedAtom)\n  const crabQueued = useAtomValue(crabQueuedAtom)\n\n  // ignore dust amount\n  const showQueuedDeposit = usdcQueued.isGreaterThan('100')\n  const showQueuedWithdraw = crabQueued.isGreaterThan('10000000000')\n\n  if (!showQueuedDeposit && !showQueuedWithdraw) {\n    return null\n  }\n\n  return (\n    <Box display=\"flex\" gridRowGap=\"40px\" gridColumnGap=\"80px\" flexWrap=\"wrap\">\n      {showQueuedDeposit && <DepositQueued />}\n      {showQueuedWithdraw && <WithdrawQueued />}\n    </Box>\n  )\n}\n\nexport default QueuedPosition\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/MyPosition/index.tsx",
    "content": "import { Typography, Box } from '@material-ui/core'\nimport { Skeleton } from '@material-ui/lab'\nimport React, { memo } from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { addressAtom } from '@state/wallet/atoms'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { useCrabPositionV2 } from '@hooks/useCrabPosition/useCrabPosition'\nimport { pnlInPerctv2 } from 'src/lib/pnl'\nimport { crabQueuedInUsdAtom, crabQueuedAtom, usdcQueuedAtom } from '@state/crab/atoms'\nimport useStyles from '@components/Strategies/styles'\nimport { BIG_ZERO } from '@constants/index'\nimport CrabPosition from './CrabPosition'\nimport QueuedPosition from './QueuedPosition'\nimport BigNumber from 'bignumber.js'\n\nconst MyPosition: React.FC<{ currentCrabPositionValue: BigNumber; isCrabPositionValueLoading: boolean }> = ({\n  currentCrabPositionValue,\n  isCrabPositionValueLoading,\n}) => {\n  const usdcQueued = useAtomValue(usdcQueuedAtom)\n  const crabQueued = useAtomValue(crabQueuedAtom)\n  const address = useAtomValue(addressAtom)\n  const { loading: isCrabPositionLoading, depositedUsd, firstDepositTimestamp } = useCrabPositionV2(address || '')\n\n  const crabV2QueuedInUsd = useAtomValue(crabQueuedInUsdAtom)\n\n  const pnl = useAppMemo(() => {\n    console.log(currentCrabPositionValue.toString(), depositedUsd.toString(), 'Position value')\n    return pnlInPerctv2(currentCrabPositionValue.plus(crabV2QueuedInUsd), depositedUsd)\n  }, [currentCrabPositionValue, depositedUsd, crabV2QueuedInUsd])\n\n  const loading = useAppMemo(() => {\n    return isCrabPositionLoading || isCrabPositionValueLoading\n  }, [isCrabPositionLoading, isCrabPositionValueLoading])\n\n  const classes = useStyles()\n\n  const currentPositionValue = currentCrabPositionValue.isGreaterThan(0) ? currentCrabPositionValue : BIG_ZERO\n  if (currentPositionValue.isZero() && usdcQueued.isZero() && crabQueued.isZero()) {\n    return null\n  }\n\n  if (loading) {\n    return (\n      <Box display=\"flex\" flexDirection=\"column\" gridGap={'12px'}>\n        <Typography variant=\"h4\" className={classes.sectionTitle}>\n          My Crab Position\n        </Typography>\n        <Skeleton width={'100%'} height={'80px'} style={{ transform: 'none' }} />\n      </Box>\n    )\n  }\n\n  return (\n    <Box display=\"flex\" flexDirection=\"column\" gridGap=\"40px\">\n      <CrabPosition\n        depositedUsd={depositedUsd}\n        currentPosition={currentPositionValue}\n        pnl={pnl}\n        firstDepositTimestamp={firstDepositTimestamp}\n      />\n      <QueuedPosition />\n    </Box>\n  )\n}\n\nexport default memo(MyPosition)\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/StrategyChartsV2.tsx",
    "content": "import { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React, { memo } from 'react'\nimport { atom, useAtom, useAtomValue } from 'jotai'\n\nimport { SqueethTabNew, SqueethTabsNew } from '@components/Tabs'\nimport FundingChart from '@components/Charts/FundingChart'\nimport { CrabStrategyV2PnLChart } from '@components/Charts/CrabStrategyV2PnLChart'\n\nenum ChartType {\n  PNL = 'PNL',\n  Funding = 'Premium',\n}\n\nconst chartTradeTypeAtom = atom(0)\n\nconst modeAtom = atom<ChartType>((get) => {\n  const tradeType = get(chartTradeTypeAtom)\n\n  if (tradeType === 0) return ChartType.PNL\n  else if (tradeType === 1) return ChartType.Funding\n\n  return ChartType.PNL\n})\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(0),\n      maxWidth: '640px',\n    },\n    navDiv: {\n      display: 'flex',\n      marginBottom: theme.spacing(2),\n      marginTop: theme.spacing(2),\n      alignItems: 'center',\n    },\n    chartNav: {\n      border: `1px solid ${theme.palette.primary.main}30`,\n    },\n  }),\n)\n\nfunction StrategyChartsV2() {\n  const classes = useStyles()\n  const [tradeType, setTradeType] = useAtom(chartTradeTypeAtom)\n  const mode = useAtomValue(modeAtom)\n\n  return (\n    <>\n      <div className={classes.container}>\n        <div className={classes.navDiv}>\n          <SqueethTabsNew\n            style={{ background: 'transparent' }}\n            className={classes.chartNav}\n            value={tradeType}\n            onChange={(evt, val) => setTradeType(val)}\n            aria-label=\"Sub nav tabs\"\n            scrollButtons=\"auto\"\n            variant=\"scrollable\"\n          >\n            <SqueethTabNew label=\"PnL\" style={{ width: '140px' }} />\n            <SqueethTabNew label=\"Premium\" style={{ width: '140px' }} />\n          </SqueethTabsNew>\n        </div>\n\n        {mode === ChartType.PNL ? <CrabStrategyV2PnLChart /> : mode === ChartType.Funding ? <FundingChart /> : null}\n      </div>\n    </>\n  )\n}\n\nconst ChartMemoized = memo(StrategyChartsV2)\n\nexport { ChartMemoized as StrategyChartsV2 }\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/StrategyHistory.tsx",
    "content": "import { useCrabStrategyTxHistory } from '@hooks/useCrabAuctionHistory'\nimport { IconButton, Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React, { useState } from 'react'\nimport { EtherscanPrefix } from '../../../constants'\nimport OpenInNewIcon from '@material-ui/icons/OpenInNew'\nimport Menu from '@material-ui/core/Menu'\nimport MenuItem from '@material-ui/core/MenuItem'\nimport KeyboardArrowDownOutlinedIcon from '@material-ui/icons/KeyboardArrowDownOutlined'\nimport { GreyButton } from '@components/Button'\nimport { useUserCrabTxHistory } from '@hooks/useUserCrabTxHistory'\nimport { CrabStrategyTxType, Networks } from '../../../types/index'\nimport clsx from 'clsx'\nimport { useAtomValue } from 'jotai'\nimport { addressAtom, networkIdAtom } from 'src/state/wallet/atoms'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      marginTop: theme.spacing(10),\n      marginBottom: theme.spacing(10),\n    },\n    txItem: {\n      background: theme.palette.background.stone,\n      borderRadius: theme.spacing(1),\n      padding: theme.spacing(1, 2),\n      marginTop: theme.spacing(3),\n      display: 'flex',\n    },\n    txSubItemTitle: {\n      width: '37%',\n    },\n    txSubItem: {\n      display: 'flex',\n      alignItems: 'center',\n      width: '30%',\n    },\n    txLink: {\n      display: 'flex',\n      alignItems: 'center',\n      width: '3%',\n    },\n    green: {\n      color: theme.palette.success.main,\n    },\n    red: {\n      color: theme.palette.error.main,\n    },\n  }),\n)\n\nenum TxType {\n  HEDGES = 'Hedges',\n  MY_TX = 'My Transactions',\n}\n\nexport const CrabStrategyHistory: React.FC = () => {\n  const classes = useStyles()\n  const { data } = useCrabStrategyTxHistory()\n\n  const address = useAtomValue(addressAtom)\n  const networkId = useAtomValue(networkIdAtom)\n\n  const [txType, setTxType] = useState(TxType.HEDGES)\n  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)\n\n  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n    setAnchorEl(event.currentTarget)\n  }\n\n  const handleClose = () => {\n    setAnchorEl(null)\n  }\n\n  const handleItemClick = (type: TxType) => {\n    setTxType(type)\n    setAnchorEl(null)\n  }\n\n  return (\n    <div className={classes.container}>\n      <div style={{ display: 'flex', marginTop: '32px' }}>\n        <Typography variant=\"h5\" color=\"primary\" style={{}}>\n          Strategy History\n        </Typography>\n        <GreyButton\n          aria-controls=\"simple-menu\"\n          aria-haspopup=\"true\"\n          style={{ marginLeft: '16px', width: '200px' }}\n          onClick={handleClick}\n          endIcon={<KeyboardArrowDownOutlinedIcon color=\"primary\" />}\n        >\n          {txType}\n        </GreyButton>\n        <Menu id=\"simple-menu\" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleClose}>\n          <MenuItem onClick={() => handleItemClick(TxType.HEDGES)}>Hedges</MenuItem>\n          {!!address ? <MenuItem onClick={() => handleItemClick(TxType.MY_TX)}>My Transactions</MenuItem> : null}\n        </Menu>\n      </div>\n      {!!address && txType === TxType.MY_TX ? <UserCrabHistory user={address} networkId={networkId} /> : null}\n      {txType === TxType.HEDGES ? (\n        <div>\n          {data?.map((d) => {\n            return (\n              <div className={classes.txItem} key={d.id}>\n                <div className={classes.txSubItemTitle}>\n                  <Typography variant=\"subtitle1\">Hedge</Typography>\n                  <Typography variant=\"caption\" color=\"textSecondary\">\n                    {new Date(d.timestamp * 1000).toLocaleString(undefined, {\n                      day: 'numeric',\n                      month: 'short',\n                      hour: 'numeric',\n                      minute: 'numeric',\n                    })}\n                  </Typography>\n                </div>\n                <div className={clsx(classes.txSubItem, d.isSellingSqueeth ? classes.red : classes.green)}>\n                  <Typography variant=\"subtitle1\">\n                    <b style={{ fontWeight: 600 }}>{d.oSqueethAmount.toFixed(6)}</b> oSQTH\n                  </Typography>\n                </div>\n                <div className={clsx(classes.txSubItem, d.isSellingSqueeth ? classes.green : classes.red)}>\n                  <Typography variant=\"subtitle1\">\n                    <b style={{ fontWeight: 600 }}>{d.ethAmount.toFixed(6)}</b> ETH\n                  </Typography>\n                </div>\n                <div className={classes.txLink}>\n                  <IconButton size=\"small\" href={`${EtherscanPrefix[networkId]}/${d.id}`} target=\"_blank\">\n                    <OpenInNewIcon style={{ fontSize: '16px' }} color=\"secondary\" />\n                  </IconButton>\n                </div>\n              </div>\n            )\n          })}\n        </div>\n      ) : null}\n    </div>\n  )\n}\n\nconst UserCrabHistory: React.FC<{ user: string; networkId: Networks }> = ({ user, networkId }) => {\n  const classes = useStyles()\n  const { data } = useUserCrabTxHistory(user, true)\n\n  return (\n    <>\n      {data?.map((d) => {\n        return (\n          <div className={classes.txItem} key={d.id}>\n            <div className={classes.txSubItemTitle}>\n              <Typography variant=\"subtitle1\">{d.txTitle}</Typography>\n              <Typography variant=\"caption\" color=\"textSecondary\">\n                {new Date(d.timestamp * 1000).toLocaleString(undefined, {\n                  day: 'numeric',\n                  month: 'short',\n                  hour: 'numeric',\n                  minute: 'numeric',\n                })}\n              </Typography>\n            </div>\n            <div className={classes.txSubItem}>\n              <Typography\n                variant=\"subtitle1\"\n                className={d.type === CrabStrategyTxType.FLASH_DEPOSIT ? classes.red : classes.green}\n              >\n                <b style={{ fontWeight: 600 }}>{d.ethAmount.toFixed(6)}</b> ETH\n              </Typography>\n              <Typography variant=\"caption\" color=\"textSecondary\">\n                ${d.ethUsdValue.toFixed(2)}\n              </Typography>\n            </div>\n            <div className={classes.txSubItem} />\n            <div className={classes.txLink}>\n              <IconButton size=\"small\" href={`${EtherscanPrefix[networkId]}/${d.id}`} target=\"_blank\">\n                <OpenInNewIcon style={{ fontSize: '16px' }} color=\"secondary\" />\n              </IconButton>\n            </div>\n          </div>\n        )\n      })}\n    </>\n  )\n}\n\nexport default CrabStrategyHistory\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/StrategyHistoryV2.tsx",
    "content": "import { IconButton, Typography, Link, Button } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport OpenInNewIcon from '@material-ui/icons/OpenInNew'\nimport React, { useRef, useCallback } from 'react'\nimport clsx from 'clsx'\nimport { useAtom, useAtomValue } from 'jotai'\n\nimport { EtherscanPrefix } from '@constants/index'\nimport { useCrabStrategyV2TxHistory } from '@hooks/useCrabV2AuctionHistory'\nimport { networkIdAtom } from '@state/wallet/atoms'\nimport { formatNumber } from '@utils/formatter'\nimport { visibleStrategyHedgesAtom } from '@state/crab/atoms'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {},\n    statContainer: {\n      background: theme.palette.background.stone,\n      borderRadius: theme.spacing(1),\n      padding: theme.spacing(1, 2),\n      marginBottom: theme.spacing(1.5),\n      display: 'flex',\n      gap: '24px',\n      flexWrap: 'wrap',\n      flexDirection: 'row',\n      [theme.breakpoints.down('xs')]: {\n        flexDirection: 'column',\n      },\n    },\n    statHeader: {\n      flexBasis: '25%',\n      minWidth: 'max-content',\n    },\n    statHeaderTitle: {\n      color: 'rgba(255, 255, 255)',\n      fontSize: '15px',\n      fontWeight: 500,\n      width: 'max-content',\n      fontFamily: 'DM Sans',\n    },\n    stat: {\n      display: 'flex',\n      flexDirection: 'column',\n      flex: 1,\n      minWidth: 'max-content',\n    },\n    label: {\n      color: 'rgba(255, 255, 255, 0.5)',\n      fontSize: '14px',\n      fontWeight: 500,\n      width: 'max-content',\n    },\n    value: {\n      color: 'rgba(255, 255, 255)',\n      fontSize: '15px',\n      fontWeight: 500,\n      width: 'max-content',\n      fontFamily: 'DM Mono',\n    },\n    txLink: {\n      display: 'flex',\n      alignItems: 'center',\n      flexBasis: 'max-content',\n    },\n    moreButtonContainer: {\n      display: 'flex',\n      justifyContent: 'center',\n      marginBottom: '24px',\n    },\n    moreButton: {\n      textTransform: 'none',\n    },\n  }),\n)\n\nexport const CrabStrategyV2History: React.FC = () => {\n  const classes = useStyles()\n  const [visibleHedges, setVisibleHedges] = useAtom(visibleStrategyHedgesAtom)\n  const { data, showMore } = useCrabStrategyV2TxHistory()\n  const bottomRef = useRef<HTMLDivElement>(null)\n  const networkId = useAtomValue(networkIdAtom)\n\n  const onClickLoadMore = useCallback(() => {\n    setVisibleHedges(visibleHedges + 3)\n    setTimeout(() => {\n      bottomRef.current?.scrollIntoView({ behavior: 'smooth' })\n    }, 200)\n  }, [visibleHedges, setVisibleHedges])\n\n  return (\n    <div className={classes.container}>\n      {data?.map((d) => {\n        return (\n          <div className={classes.statContainer} key={d.id}>\n            <div className={classes.statHeader}>\n              <Typography className={clsx(classes.statHeaderTitle)}>\n                {d.isBuying ? 'Bought oSQTH' : 'Sold oSQTH'}\n              </Typography>\n              <Typography className={classes.label}>\n                {new Date(d.timestamp * 1000).toLocaleString(undefined, {\n                  day: 'numeric',\n                  month: 'short',\n                  hour: 'numeric',\n                  minute: 'numeric',\n                })}\n              </Typography>\n            </div>\n\n            <div className={classes.stat}>\n              <Typography className={classes.label}>Size</Typography>\n              <Typography className={classes.value}>{formatNumber(d.oSqueethAmount.toNumber(), 2)} oSQTH</Typography>\n            </div>\n            <div className={classes.stat}>\n              <Typography className={classes.label}>Clearing price</Typography>\n              <Typography className={classes.value}>{formatNumber(d.ethAmount.toNumber(), 2)} WETH</Typography>\n            </div>\n\n            <Link href={`${EtherscanPrefix[networkId]}${d.id}`} target=\"_blank\" className={classes.txLink}>\n              <Typography color=\"primary\">View Transaction</Typography>\n              <IconButton size=\"small\">\n                <OpenInNewIcon style={{ fontSize: '16px' }} color=\"primary\" />\n              </IconButton>\n            </Link>\n          </div>\n        )\n      })}\n      <div ref={bottomRef} />\n      {showMore && (\n        <div className={classes.moreButtonContainer}>\n          <Button\n            size=\"large\"\n            className={classes.moreButton}\n            onClick={onClickLoadMore}\n            color=\"primary\"\n            variant=\"outlined\"\n          >\n            Load More\n          </Button>\n        </div>\n      )}\n    </div>\n  )\n}\n\nexport default CrabStrategyV2History\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/StrategyInfoV1.tsx",
    "content": "import ShortSqueethPayoff from '@components/Charts/ShortSqueethPayoff'\nimport { Typography, Radio, RadioGroup, FormControl, FormControlLabel, FormLabel } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React from 'react'\nimport { Links, Vaults } from '@constants/enums'\nimport CrabProfit_Flat from '../../../../public/images/CrabProfit_Flat.svg'\nimport CrabProfit_Increase from '../../../../public/images/CrabProfit_Increase.svg'\nimport CrabProfit_Decrease from '../../../../public/images/CrabProfit_Decrease.svg'\nimport CrabSteps from '../../../../public/images/CrabSteps.svg'\nimport Image from 'next/image'\nimport { MemoizedCrabStrategyChart as CrabStrategyChart } from '@components/Charts/CrabStrategyChart'\nimport { useETHPrice } from '@hooks/useETHPrice'\nimport { useSetProfitableMovePercent } from 'src/state/crab/hooks'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(0),\n      margin: '0 auto',\n      marginTop: theme.spacing(4),\n      maxWidth: '840px',\n    },\n    content: {\n      marginTop: theme.spacing(1),\n    },\n    title: {\n      marginTop: theme.spacing(8),\n    },\n    link: {\n      color: theme.palette.primary.main,\n    },\n    profitImage: {\n      marginTop: theme.spacing(2),\n      borderRadius: theme.spacing(1),\n    },\n    stepsImage: {\n      marginTop: theme.spacing(2),\n      marginBottom: theme.spacing(4),\n    },\n    caption: {\n      marginTop: theme.spacing(1),\n      marginBottom: theme.spacing(4),\n    },\n    chartTitle: {\n      marginTop: theme.spacing(2),\n      marginBottom: theme.spacing(4),\n    },\n    radioTitle: {\n      marginTop: theme.spacing(2),\n    },\n  }),\n)\n\nexport const StrategyInfo: React.FC = () => {\n  const classes = useStyles()\n  const ethPrice = useETHPrice()\n  const profitableMovePercent = useSetProfitableMovePercent()\n\n  const [profitToggle, setProfitToggle] = React.useState('flat')\n\n  return (\n    <div className={classes.container}>\n      {/* <Typography variant=\"h5\" color=\"primary\" className={classes.chartTitle}>\n        Historical PnL Simulation\n      </Typography> */}\n      {/* <CrabStrategyChart vault={Vaults.Short} longAmount={0} /> */}\n      <Typography variant=\"h5\" color=\"primary\" className={classes.title}>\n        1 Day Profitability\n      </Typography>\n      <FormControl className={classes.radioTitle}>\n        <FormLabel>At the end of one day, if ETH approximately</FormLabel>\n        <RadioGroup\n          row\n          name=\"At the end of one day, if ETH approximately\"\n          value={profitToggle}\n          onChange={(event) => setProfitToggle(event.target.value)}\n        >\n          <FormControlLabel\n            value=\"increase\"\n            control={<Radio />}\n            label={`increases ~${(profitableMovePercent * 100).toFixed(2)}%`}\n          />\n          <FormControlLabel\n            value=\"flat\"\n            control={<Radio />}\n            label={`moves less than ~${(profitableMovePercent * 100).toFixed(2)}%`}\n          />\n          <FormControlLabel\n            value=\"descrease\"\n            control={<Radio />}\n            label={`decreases ~${(profitableMovePercent * 100).toFixed(2)}%`}\n          />\n        </RadioGroup>\n      </FormControl>\n      <div className={classes.profitImage}>\n        {profitToggle === 'flat' ? (\n          <Image src={CrabProfit_Flat} alt=\"1 Day Profitability Flat\" />\n        ) : profitToggle === 'increase' ? (\n          <Image src={CrabProfit_Increase} alt=\"1 Day Profitability Increase\" />\n        ) : (\n          <Image src={CrabProfit_Decrease} alt=\"1 Day Profitability Decrease\" />\n        )}\n      </div>\n      <Typography color=\"textSecondary\" variant=\"subtitle1\" className={classes.caption}>\n        Based on current premiums, crab strategy would be unprofitable if ETH moves more than the profit threshold of\n        approximately <b>{(profitableMovePercent * 100).toFixed(2)}%</b> in either direction each day. Crab aims to be\n        profitable in USD terms.\n      </Typography>\n      {/* <Typography variant=\"h5\" color=\"primary\" className={classes.title}>\n        Payoff\n      </Typography>\n      <ShortSqueethPayoff ethPrice={ethPrice.toNumber()} collatRatio={2} /> */}\n      <Typography variant=\"h5\" color=\"primary\" className={classes.title}>\n        Steps\n      </Typography>\n      <div className={classes.stepsImage}>\n        <Image src={CrabSteps} alt=\"Steps\" />\n      </div>\n      <Typography variant=\"h5\" color=\"primary\" className={classes.title}>\n        Risk\n      </Typography>\n      <Typography color=\"textSecondary\" variant=\"subtitle1\" className={classes.content}>\n        If the Crab Strategy falls below the safe collateralization threshold (150%), the strategy is at risk of\n        liquidation. Rebalancing based on large ETH price changes helps prevent a liquidation from occurring.\n        <br /> <br />\n        Based on current premiums, crab strategy would be unprofitable if ETH moves more than approximately{' '}\n        {(profitableMovePercent * 100).toFixed(2)}% in either direction each day. The implied premium at which you\n        deposit at impacts your profitability. Depositing at a high premium increases likelihood of profitability.\n        <br /> <br />\n        If the Squeeth premium to ETH increases, the strategy will incur a loss because it will be more expensive to\n        close the position. Crab aims to be profitable in USD terms.\n        <a\n          className={classes.link}\n          href=\"https://opyn.gitbook.io/opyn-strategies/crab-strategy/risks-and-fees\"\n          target=\"_blank\"\n          rel=\"noreferrer\"\n        >\n          {' '}\n          Learn more.{' '}\n        </a>\n        <br /> <br />\n        Crab smart contracts have been audited by Trail of Bits, Akira, and Sherlock. However, smart contracts are\n        experimental technology and we encourage caution only risking funds you can afford to lose.\n      </Typography>\n    </div>\n  )\n}\n\nexport default StrategyInfo\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/StrategyInfoV2.tsx",
    "content": "import { Typography, Radio, RadioGroup, FormControl, FormControlLabel, FormLabel } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React from 'react'\nimport Image from 'next/image'\nimport clsx from 'clsx'\n\nimport { Links } from '@constants/enums'\nimport CrabProfit_Flat from 'public/images/CrabProfit_Flat_v2.svg'\nimport CrabProfit_Increase from 'public/images/CrabProfit_Increase_v2.svg'\nimport CrabProfit_Decrease from 'public/images/CrabProfit_Decrease_v2.svg'\nimport { useSetProfitableMovePercentV2 } from '@state/crab/hooks'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      padding: theme.spacing(0),\n      maxWidth: '840px',\n    },\n    content: {\n      marginTop: theme.spacing(1),\n    },\n    title: {\n      marginTop: theme.spacing(8),\n    },\n    link: {\n      color: theme.palette.primary.main,\n    },\n    profitImage: {\n      marginTop: theme.spacing(2),\n      borderRadius: theme.spacing(1),\n    },\n    stepsImage: {\n      marginTop: theme.spacing(2),\n      marginBottom: theme.spacing(4),\n    },\n    caption: {\n      marginTop: theme.spacing(1),\n      marginBottom: theme.spacing(4),\n    },\n    chartTitle: {\n      marginTop: theme.spacing(2),\n      marginBottom: theme.spacing(4),\n    },\n    radioTitle: {\n      marginTop: theme.spacing(2),\n    },\n    fontColor: {\n      color: '#bdbdbd',\n    },\n    subtitle: {\n      fontSize: '20px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n    },\n  }),\n)\n\nexport const StrategyInfo: React.FC = () => {\n  const classes = useStyles()\n  const profitableMovePercent = useSetProfitableMovePercentV2()\n\n  const [profitToggle, setProfitToggle] = React.useState('flat')\n\n  return (\n    <div className={classes.container}>\n      <FormControl className={classes.radioTitle}>\n        <FormLabel>Before the next hedge, if ETH approximately</FormLabel>\n        <RadioGroup\n          row\n          name=\"At the end of one day, if ETH approximately\"\n          value={profitToggle}\n          onChange={(event) => setProfitToggle(event.target.value)}\n        >\n          <FormControlLabel\n            value=\"increase\"\n            control={<Radio />}\n            label={`increases ~${(profitableMovePercent * 100).toFixed(2)}%`}\n          />\n          <FormControlLabel\n            value=\"flat\"\n            control={<Radio />}\n            label={`moves less than ~${(profitableMovePercent * 100).toFixed(2)}%`}\n          />\n          <FormControlLabel\n            value=\"descrease\"\n            control={<Radio />}\n            label={`decreases ~${(profitableMovePercent * 100).toFixed(2)}%`}\n          />\n        </RadioGroup>\n      </FormControl>\n      <div className={classes.profitImage}>\n        {profitToggle === 'flat' ? (\n          <Image src={CrabProfit_Flat} alt=\"Profitability Flat\" />\n        ) : profitToggle === 'increase' ? (\n          <Image src={CrabProfit_Increase} alt=\"Profitability Increase\" />\n        ) : (\n          <Image src={CrabProfit_Decrease} alt=\"Profitability Decrease\" />\n        )}\n      </div>\n      <Typography variant=\"subtitle1\" className={clsx(classes.caption, classes.fontColor)}>\n        Based on current premiums, crab strategy would be unprofitable if ETH moves more than the profit threshold of\n        approximately <b>{(profitableMovePercent * 100).toFixed(2)}%</b> in either direction between 2 day hedges. Crab\n        hedges approximately three times a week (on MWF). Crab aims to be profitable in USD terms.\n      </Typography>\n\n      <Typography variant=\"h4\" className={classes.subtitle}>\n        Risk\n      </Typography>\n      <Typography variant=\"subtitle1\" className={clsx(classes.content, classes.fontColor)}>\n        If the Crab Strategy falls below the safe collateralization threshold (150%), the strategy is at risk of\n        liquidation. Rebalancing based on large ETH price changes helps prevent a liquidation from occurring.\n        <br /> <br />\n        Based on current premiums, crab strategy would be unprofitable if ETH moves more than approximately{' '}\n        {(profitableMovePercent * 100).toFixed(2)}% in either direction before the next hedge. The implied premium which\n        you deposit at impacts your profitability. Depositing at a high premium increases likelihood of profitability.\n        <br /> <br />\n        If the Squeeth premium to ETH increases, the strategy will incur a loss because it will be more expensive to\n        close the position. Crab aims to be profitable in USD terms.\n        <a\n          className={classes.link}\n          href=\"https://opyn.gitbook.io/opyn-strategies/crab-strategy/risks-and-fees\"\n          target=\"_blank\"\n          rel=\"noreferrer\"\n        >\n          {' '}\n          Learn more.{' '}\n        </a>\n        <br /> <br />\n        Crab smart contracts have been audited by Sherlock. However, smart contracts are experimental technology and we\n        encourage caution only risking funds you can afford to lose.\n      </Typography>\n    </div>\n  )\n}\n\nexport default StrategyInfo\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/StrategyPerformance.tsx",
    "content": "import React, { useMemo } from 'react'\nimport { Box, Typography, Tooltip, TextField, InputLabel, TextFieldProps, Divider } from '@material-ui/core'\nimport HelpOutlineIcon from '@material-ui/icons/HelpOutline'\nimport clsx from 'clsx'\nimport { useAtom } from 'jotai'\nimport { useAtomValue } from 'jotai/utils'\nimport { DatePicker, MuiPickersUtilsProvider } from '@material-ui/pickers'\nimport DateFnsUtils from '@date-io/date-fns'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport HighchartsReact from 'highcharts-react-official'\nimport Highcharts from 'highcharts'\nimport differenceInCalendarDays from 'date-fns/differenceInCalendarDays'\nimport { Skeleton } from '@material-ui/lab'\n\nimport useStyles from '@components/Strategies/styles'\nimport {\n  crabStrategyVaultAtomV2,\n  useCrabPnLV2ChartData,\n  crabv2StrategyFilterEndDateAtom,\n  crabv2StrategyFilterStartDateAtom,\n} from '@state/crab/atoms'\nimport { BIG_ZERO, CRABV2_START_DATE } from '@constants/index'\nimport { useETHPrice } from '@hooks/useETHPrice'\nimport { useOSQTHPrice } from '@hooks/useOSQTHPrice'\nimport { formatCurrency, formatNumber } from '@utils/formatter'\nimport { pnlGraphOptions } from '@constants/diagram'\nimport useAppMemo from '@hooks/useAppMemo'\n\nconst useTextFieldStyles = makeStyles((theme) =>\n  createStyles({\n    labelRoot: {\n      color: '#8C8D8D',\n      fontSize: '14px',\n      fontWeight: 500,\n    },\n    inputRoot: {\n      padding: '10px 16px',\n      fontSize: '15px',\n      fontWeight: 500,\n      fontFamily: 'DM Mono',\n      width: '14ch',\n      border: '2px solid #303436',\n      borderRadius: '12px',\n    },\n    inputFocused: {\n      borderColor: theme.palette.primary.main,\n    },\n  }),\n)\n\nexport type ChartDataInfo = {\n  timestamp: number\n  crabPnL: number\n}\n\nconst CustomTextField: React.FC<TextFieldProps> = ({ inputRef, label, InputProps, id, variant, ...props }) => {\n  const classes = useTextFieldStyles()\n\n  return (\n    <Box display=\"flex\" flexDirection=\"column\" gridGap=\"4px\">\n      <InputLabel htmlFor={id} classes={{ root: classes.labelRoot }}>\n        {label}\n      </InputLabel>\n      <TextField\n        id={id}\n        InputProps={{\n          classes: {\n            root: classes.inputRoot,\n            focused: classes.inputFocused,\n          },\n          disableUnderline: true,\n          ...InputProps,\n        }}\n        {...props}\n      />\n    </Box>\n  )\n}\n\nconst PerformanceMetric: React.FC<{ label: string; value: number }> = ({ label, value }) => {\n  const classes = useStyles()\n\n  return (\n    <Box display=\"flex\" justifyContent=\"flex-end\" gridGap=\"6px\">\n      <Typography className={classes.textSmall}>{label}</Typography>\n\n      <Box minWidth=\"6ch\" display=\"flex\" justifyContent=\"flex-end\">\n        <Typography\n          className={clsx(\n            classes.textSmall,\n            classes.textMonospace,\n            value >= 0 ? classes.colorSuccess : classes.colorError,\n          )}\n        >\n          {value >= 0 && '+'}\n          {formatNumber(value)}%\n        </Typography>\n      </Box>\n    </Box>\n  )\n}\n\nconst TooltipTitle = () => (\n  <>\n    {'Annualized return based on selected dates.'}\n    <br />\n    {'Past performance does not indicate future returns.'}\n  </>\n)\n\ninterface StrategyPerformanceProps {\n  strategyPnLSeries: Array<[number, number]>\n  tvl: number\n}\n\nconst StrategyPerformance: React.FC<StrategyPerformanceProps> = ({ strategyPnLSeries, tvl }) => {\n  const [startDate, setStartDate] = useAtom(crabv2StrategyFilterStartDateAtom)\n  const [endDate, setEndDate] = useAtom(crabv2StrategyFilterEndDateAtom)\n\n  const series = [\n    {\n      name: 'Crab/USDC 🦀  % Return',\n      yAxis: 0,\n      data: strategyPnLSeries,\n      tooltip: {\n        valueDecimals: 2,\n        valueSuffix: '%',\n      },\n      color: '#70E3F6',\n    },\n  ]\n\n  const axes = {\n    yAxis: [\n      {\n        // Left yAxis\n        title: {\n          text: '',\n        },\n        labels: {\n          style: {\n            color: '#BABBBB',\n          },\n        },\n        gridLineColor: 'rgba(221,221,221,0.1)',\n      },\n    ],\n  }\n\n  const chartOptions = useAppMemo(() => {\n    const { chart, ...restOptions } = pnlGraphOptions\n\n    return {\n      ...restOptions,\n      ...axes,\n      chart: {\n        ...chart,\n        marginLeft: '40',\n      },\n      series: series,\n    }\n  })\n  const classes = useStyles()\n\n  const numberOfDays = differenceInCalendarDays(endDate, startDate)\n  const hasData = strategyPnLSeries.length > 0\n\n  const historicalReturns = hasData ? strategyPnLSeries[strategyPnLSeries.length - 1][1] : 0\n  const annualizedReturns = useMemo(() => {\n    // compounded annually\n    return (Math.pow(1 + historicalReturns / 100, 365 / numberOfDays) - 1) * 100\n  }, [historicalReturns, numberOfDays])\n\n  return (\n    <>\n      <Box display=\"flex\" alignItems=\"baseline\" gridColumnGap=\"12px\" gridRowGap=\"4px\" flexWrap=\"wrap\">\n        <Typography\n          variant=\"h2\"\n          className={clsx(\n            classes.heading,\n            classes.textMonospace,\n            annualizedReturns >= 0 ? classes.colorSuccess : classes.colorError,\n          )}\n        >\n          {annualizedReturns >= 0 && '+'}\n          {formatNumber(annualizedReturns)}%\n        </Typography>\n\n        <Box display=\"flex\" alignItems=\"baseline\" gridGap=\"12px\">\n          <Typography className={classes.description}>Annualized USDC Return</Typography>\n\n          <Box position=\"relative\" top=\"3px\">\n            <Tooltip title={<TooltipTitle />}>\n              <HelpOutlineIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n          </Box>\n        </Box>\n      </Box>\n\n      <Box display=\"flex\" gridGap=\"12px\">\n        <Typography className={clsx(classes.description, classes.textMonospace)}>{formatCurrency(tvl, 0)}</Typography>\n        <Typography className={classes.description}>Open Interest</Typography>\n      </Box>\n\n      <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"flex-end\" gridGap=\"12px\" flexWrap=\"wrap\">\n        <div>\n          <MuiPickersUtilsProvider utils={DateFnsUtils}>\n            <Box display=\"flex\" alignItems=\"center\" gridGap=\"16px\" marginTop=\"16px\">\n              <DatePicker\n                id=\"start-date-strategy-performance\"\n                label=\"Start Date\"\n                placeholder=\"MM/DD/YYYY\"\n                format={'MM/dd/yyyy'}\n                value={startDate}\n                minDate={CRABV2_START_DATE}\n                onChange={(d) => setStartDate(d || new Date())}\n                animateYearScrolling={false}\n                autoOk={true}\n                clearable\n                TextFieldComponent={CustomTextField}\n              />\n\n              <Divider orientation=\"horizontal\" className={classes.divider} />\n\n              <DatePicker\n                id=\"end-date-strategy-performance\"\n                label=\"End Date\"\n                placeholder=\"MM/DD/YYYY\"\n                format={'MM/dd/yyyy'}\n                value={endDate}\n                minDate={startDate}\n                onChange={(d) => setEndDate(d || new Date())}\n                animateYearScrolling={false}\n                autoOk={true}\n                clearable\n                TextFieldComponent={CustomTextField}\n              />\n            </Box>\n          </MuiPickersUtilsProvider>\n        </div>\n\n        <Box display=\"flex\" flexDirection=\"column\" gridGap=\"4px\" flex=\"1\" flexBasis=\"200px\">\n          <PerformanceMetric label=\"Historical Returns\" value={historicalReturns} />\n          <PerformanceMetric label=\"Annualized\" value={annualizedReturns} />\n        </Box>\n      </Box>\n\n      <Box marginTop=\"12px\">\n        <HighchartsReact highcharts={Highcharts} options={chartOptions} />\n      </Box>\n    </>\n  )\n}\n\nconst Wrapper: React.FC = () => {\n  const vault = useAtomValue(crabStrategyVaultAtomV2)\n  const ethPrice = useETHPrice()\n  const query = useCrabPnLV2ChartData()\n\n  const strategyPnLSeries = query?.data?.data.map((x: ChartDataInfo) => [x.timestamp * 1000, x.crabPnL * 100])\n  const isLoadingPnLSeries = typeof strategyPnLSeries === 'undefined'\n\n  const vaultCollateral = vault?.collateralAmount ?? BIG_ZERO\n\n  const collateralValue = vaultCollateral.multipliedBy(ethPrice)\n  const tvl = collateralValue.integerValue()\n  const isLoadingTVL = tvl.isZero()\n\n  const isLoading = isLoadingPnLSeries || isLoadingTVL\n\n  const classes = useStyles()\n\n  return (\n    <Box display=\"flex\" flexDirection=\"column\" gridGap=\"8px\">\n      <Typography variant=\"h3\" className={classes.sectionTitle}>\n        Strategy Performance\n      </Typography>\n\n      {isLoading ? (\n        <div className={classes.shimmer}>\n          <Skeleton width={'100%'} height={25} style={{ transform: 'none' }} />\n          <Skeleton width={'100%'} height={30} style={{ transform: 'none' }} />\n          <Skeleton width={'100%'} height={300} style={{ transform: 'none' }} />\n        </div>\n      ) : (\n        <StrategyPerformance strategyPnLSeries={strategyPnLSeries} tvl={tvl.toNumber()} />\n      )}\n    </Box>\n  )\n}\n\nexport default Wrapper\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/Crab/util.ts",
    "content": "export const makeItCrabRain = function () {\n  //clear out everything\n  const rainRoot = document.getElementById('rain')\n  const rainFront = document.createElement('div')\n  rainFront.id = 'rain-front'\n  const rainBack = document.createElement('div')\n  rainBack.id = 'rain-back'\n\n  rainRoot?.appendChild(rainFront)\n  rainRoot?.appendChild(rainBack)\n\n  let increment = 0\n  let drops = ''\n  let backDrops = ''\n\n  while (increment < 100) {\n    //couple random numbers to use for various randomizations\n    //random number between 98 and 1\n    const randoHundo = Math.floor(Math.random() * (100 - 1 + 1) + 1)\n    //random number between 5 and 2\n    const randoFiver = Math.floor(Math.random() * (5 - 2 + 1) + 2)\n    //increment\n    increment += randoFiver\n\n    const emojis = ['🐱', '🦀']\n    const randEmoji = emojis[Math.floor(Math.random() * emojis.length)]\n    //add in a new raindrop with various randomizations to certain CSS properties\n    drops +=\n      '<div class=\"drop\" style=\"left: ' +\n      increment +\n      '%; bottom: ' +\n      (randoFiver + randoFiver - 1 + 100) +\n      '%; animation-delay: 0.' +\n      randoHundo +\n      's; animation-duration: 2.' +\n      randoHundo +\n      's;\"><div class=\"stem\" style=\"animation-delay: 0.' +\n      randoHundo +\n      's; animation-duration: 0.5' +\n      randoHundo +\n      's;\"></div>' +\n      randEmoji +\n      '<div class=\"splat\" style=\"animation-delay: 0.' +\n      randoHundo +\n      's; animation-duration: 0.5' +\n      randoHundo +\n      's;\"></div></div>'\n    backDrops +=\n      '<div class=\"drop\" style=\"right: ' +\n      increment +\n      '%; bottom: ' +\n      (randoFiver + randoFiver - 1 + 100) +\n      '%; animation-delay: 0.' +\n      randoHundo +\n      's; animation-duration: 2.' +\n      randoHundo +\n      's;\"><div class=\"stem\" style=\"animation-delay: 0.' +\n      randoHundo +\n      's; animation-duration: 0.5' +\n      randoHundo +\n      's;\"></div>' +\n      randEmoji +\n      '<div class=\"splat\" style=\"animation-delay: 0.' +\n      randoHundo +\n      's; animation-duration: 0.5' +\n      randoHundo +\n      's;\"></div></div>'\n  }\n\n  if (document.getElementById('rain-front')) {\n    document.getElementById('rain-front')!.innerHTML = drops\n  }\n  if (document.getElementById('rain-back')) {\n    document.getElementById('rain-back')!.innerHTML = backDrops\n  }\n\n  setTimeout(stopRain, 10000)\n}\n\nexport const stopRain = () => {\n  document.getElementById('rain')!.innerHTML = ''\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/SharePnl.tsx",
    "content": "import { Box, ButtonBase, Tooltip } from '@material-ui/core'\nimport React from 'react'\nimport TwitterIcon from '@material-ui/icons/Twitter'\nimport TelegramIcon from '@material-ui/icons/Telegram'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport formatDistanceToNowStrict from 'date-fns/formatDistanceToNowStrict'\n\nimport { formatNumber } from '@utils/formatter'\nimport { SQUEETH_BASE_URL } from '@constants/index'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { SITE_EVENTS } from '@utils/amplitude'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    buttonRoot: {\n      display: 'flex',\n      justifyContent: 'center',\n      alignItems: 'center',\n      border: '1px solid #fff',\n      borderRadius: '100%',\n      width: '26px',\n      height: '26px',\n      backgroundColor: '#101010',\n      '&:hover': {\n        backgroundColor: theme.palette.background.lightStone,\n      },\n      transition: 'background-color 0.1s ease-in',\n    },\n    icon: {\n      width: '13px',\n      height: '13px',\n    },\n  }),\n)\n\ninterface SharePnlProps {\n  isPnlLoading: Boolean\n  strategy: 'crab' | 'zenbull'\n  pnl: number\n  firstDepositTimestamp: number\n}\n\nconst SharePnl: React.FC<SharePnlProps> = ({ isPnlLoading, strategy, pnl, firstDepositTimestamp }) => {\n  const classes = useStyles()\n  const { track } = useAmplitude()\n\n  if (isPnlLoading) {\n    return null\n  }\n\n  const pnlFormatted = formatNumber(pnl)\n  const pnlText = pnl > 0 ? `+${pnlFormatted}%` : `${pnlFormatted}%`\n  const timeframe = firstDepositTimestamp ? formatDistanceToNowStrict(firstDepositTimestamp * 1000) : ''\n\n  const isCrab = strategy === 'crab'\n\n  const strategyEmoji = isCrab ? '🦀' : '🧘🐂 '\n  const text = isCrab\n    ? `I've earned ${pnlText} on my USDC in the past ${timeframe} with the Opyn's Crab Strategy!`\n    : `I've earned ${pnlText} on my ETH in the past ${timeframe} with the Opyn's Zen Bull Strategy!`\n  const twitterText = isCrab\n    ? `I've earned ${pnlText} on my USDC in the past ${timeframe} with the @opyn_'s Crab Strategy!`\n    : `I've earned ${pnlText} on my ETH in the past ${timeframe} with the @opyn_'s Zen Bull Strategy!`\n  const pageUrl = `${SQUEETH_BASE_URL}/share-pnl/${strategy}/${firstDepositTimestamp}/${pnlFormatted}`\n\n  const postText = encodeURIComponent(`${text} ${strategyEmoji}`)\n  const tweetText = encodeURIComponent(`${twitterText} ${strategyEmoji}`)\n  const encodedUrl = encodeURIComponent(pageUrl)\n\n  const tweetHref = `https://twitter.com/intent/tweet?text=${tweetText}&url=${encodedUrl}`\n  const telegramHref = `https://t.me/share/url?text=${postText}&url=${encodedUrl}`\n\n  return (\n    <Box display=\"flex\" gridGap=\"8px\" alignItems=\"center\">\n      <Tooltip title=\"Share your PnL on Twitter\" placement=\"bottom\">\n        <ButtonBase\n          classes={{ root: classes.buttonRoot }}\n          href={tweetHref}\n          target=\"_blank\"\n          onClick={() => track(SITE_EVENTS.CLICK_SHARE_PNL, { platform: 'twitter', strategy })}\n        >\n          <TwitterIcon className={classes.icon} />\n        </ButtonBase>\n      </Tooltip>\n\n      <Tooltip title=\"Share your PnL on Telegram\" placement=\"bottom\">\n        <ButtonBase\n          classes={{ root: classes.buttonRoot }}\n          href={telegramHref}\n          target=\"_blank\"\n          onClick={() => track(SITE_EVENTS.CLICK_SHARE_PNL, { platform: 'telegram', strategy })}\n        >\n          <TelegramIcon className={classes.icon} />\n        </ButtonBase>\n      </Tooltip>\n    </Box>\n  )\n}\n\nexport default SharePnl\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/StrategyInfoItem.tsx",
    "content": "import { Typography } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport React from 'react'\nimport AccessTimeIcon from '@material-ui/icons/AccessTime'\nimport FiberManualRecordIcon from '@material-ui/icons/FiberManualRecord'\nimport { Tooltip } from '@material-ui/core'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      display: 'flex',\n      flexDirection: 'column',\n      background: theme.palette.background.stone,\n      borderRadius: theme.spacing(2),\n      padding: theme.spacing(2, 3),\n      width: '100%',\n    },\n    overviewTitle: {\n      fontSize: '14px',\n      color: theme.palette.text.secondary,\n      fontWeight: 600,\n    },\n    overviewValue: {\n      fontSize: '22px',\n    },\n    infoIcon: {\n      fontSize: '1rem',\n      marginLeft: theme.spacing(0.5),\n      marginTop: '2px',\n      color: theme.palette.text.secondary,\n    },\n    infoLabel: {\n      display: 'flex',\n    },\n  }),\n)\n\ntype StrategyProps = {\n  value?: string\n  label: string\n  tooltip?: React.ReactNode\n  priceType?: string\n  link?: string\n}\n\nconst StrategyInfoItem: React.FC<StrategyProps> = ({ value, label, tooltip, priceType, link }) => {\n  const classes = useStyles()\n\n  if (link) {\n    return (\n      <div className={classes.container}>\n        <a href={link}>\n          <Typography className={classes.overviewValue}>{value}</Typography>\n          <div className={classes.infoLabel}>\n            <Typography className={classes.overviewTitle}>{label} </Typography>\n            {tooltip ? (\n              <Tooltip title={tooltip}>\n                {priceType === 'twap' ? (\n                  <AccessTimeIcon className={classes.infoIcon} />\n                ) : priceType === 'spot' ? (\n                  <FiberManualRecordIcon className={classes.infoIcon} />\n                ) : (\n                  <InfoIcon className={classes.infoIcon} />\n                )}\n              </Tooltip>\n            ) : null}\n          </div>\n        </a>\n      </div>\n    )\n  } else {\n    return (\n      <div className={classes.container}>\n        <Typography className={classes.overviewValue}>{value}</Typography>\n        <div className={classes.infoLabel}>\n          <Typography className={classes.overviewTitle}>{label} </Typography>\n          {tooltip ? (\n            <Tooltip title={tooltip}>\n              {priceType === 'twap' ? (\n                <AccessTimeIcon className={classes.infoIcon} />\n              ) : priceType === 'spot' ? (\n                <FiberManualRecordIcon className={classes.infoIcon} />\n              ) : (\n                <InfoIcon className={classes.infoIcon} />\n              )}\n            </Tooltip>\n          ) : null}\n        </div>\n      </div>\n    )\n  }\n}\n\nexport default StrategyInfoItem\n"
  },
  {
    "path": "packages/frontend/src/components/Strategies/styles.ts",
    "content": "import { makeStyles, createStyles } from '@material-ui/core/styles'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    heading: {\n      fontSize: '32px',\n      fontWeight: 700,\n      letterSpacing: '-0.02em',\n      lineHeight: '130%',\n    },\n    description: {\n      fontSize: '18px',\n      color: 'rgba(255, 255, 255, 0.6)',\n      fontWeight: 400,\n      lineHeight: '130%',\n    },\n    sectionTitle: {\n      fontSize: '18px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n      lineHeight: '130%',\n    },\n    text: {\n      fontSize: '18px',\n      color: '#BDBDBD',\n      lineHeight: '130%',\n    },\n    textSmall: {\n      fontSize: '14px',\n      color: 'rgba(255, 255, 255, 0.5)',\n      fontWeight: 500,\n    },\n    textMargin: {\n      marginTop: '8px',\n    },\n    textSemibold: {\n      fontWeight: 500,\n    },\n    colorSuccess: {\n      color: theme.palette.success.main,\n    },\n    colorError: {\n      color: theme.palette.error.main,\n    },\n    infoIcon: {\n      color: theme.palette.text.hint,\n    },\n    loadingSpinner: {\n      color: '#BDBDBD',\n      lineHeight: '130%',\n    },\n    textMonospace: {\n      fontFamily: 'DM Mono',\n    },\n    divider: {\n      width: '15px',\n      backgroundColor: '#8C8D8D',\n      height: '1.5px',\n      position: 'relative',\n      top: '6px',\n    },\n    shimmer: { display: 'flex', flexDirection: 'column', gap: '8px', height: '500px' },\n  }),\n)\n\nexport default useStyles\n"
  },
  {
    "path": "packages/frontend/src/components/StrategyLayout/StrategyLayout.tsx",
    "content": "import React, { useEffect, useState } from 'react'\nimport { Typography, Tab, Tabs, Link } from '@material-ui/core'\nimport Image from 'next/image'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport { useRouter } from 'next/router'\n\nimport Nav from '@components/Nav'\nimport { Vaults, VaultSubtitle } from '@constants/enums'\nimport crabStrategyImg from 'public/images/crab_strategy.svg'\nimport bearStrategyImg from 'public/images/bear_strategy.svg'\nimport bullStrategyImg from 'public/images/bull_strategy.png'\nimport { ZenBullAlert } from '@components/Alerts/ZenBullAlert'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      maxWidth: '1280px',\n      width: '80%',\n      margin: '0 auto',\n      padding: theme.spacing(1, 5, 7, 5),\n\n      [theme.breakpoints.down('lg')]: {\n        maxWidth: 'none',\n        width: '90%',\n      },\n      [theme.breakpoints.down('md')]: {\n        width: '100%',\n      },\n      [theme.breakpoints.down('sm')]: {\n        padding: theme.spacing(1, 4, 5, 4),\n      },\n      [theme.breakpoints.down('xs')]: {\n        padding: theme.spacing(1, 3, 4, 3),\n      },\n    },\n  }),\n)\n\nconst useTabStyles = makeStyles((theme) =>\n  createStyles({\n    tabsRoot: {\n      borderBottom: '1px solid #333333',\n      marginTop: '16px',\n    },\n    tabsIndicator: {\n      backgroundColor: '#26E6F8',\n    },\n    tabRoot: {\n      paddingTop: '12px',\n      paddingBottom: '12px',\n      width: '240px',\n      [theme.breakpoints.down('md')]: {\n        width: '30%',\n      },\n    },\n    labelTitle: {\n      textTransform: 'initial',\n      fontSize: '24px',\n      fontWeight: 700,\n\n      lineHeight: '2rem',\n      [theme.breakpoints.down('xs')]: {\n        fontSize: '20px',\n        lineHeight: '1.5rem',\n      },\n    },\n    labelSubtitle: {\n      textTransform: 'initial',\n      fontSize: '16px',\n      fontWeight: 400,\n      [theme.breakpoints.down('xs')]: {\n        fontSize: '13px',\n      },\n    },\n    strategyImgContainer: {\n      width: '20px',\n      height: '20px',\n    },\n\n    strategyImg: {\n      width: '100%',\n    },\n  }),\n)\n\nconst STRATEGIES_PATH = '/strategies'\n\nconst CRAB_PATH = `${STRATEGIES_PATH}/crab`\nconst BULL_PATH = `${STRATEGIES_PATH}/bull`\nconst BEAR_PATH = `${STRATEGIES_PATH}/bear`\n\nconst allowedPaths = [CRAB_PATH, BULL_PATH, BEAR_PATH]\n\nconst routeMap = {\n  [CRAB_PATH]: 0,\n  [BULL_PATH]: 1,\n}\n\nconst StrategyLabel: React.FC<{ title: Vaults; subtitle?: VaultSubtitle }> = ({ title, subtitle = '' }) => {\n  const classes = useTabStyles()\n\n  return (\n    <div>\n      <Typography className={classes.labelTitle}>{title}</Typography>\n      <Typography className={classes.labelSubtitle}>{subtitle}</Typography>\n    </div>\n  )\n}\n\ninterface StrategyImageProps {\n  img: any\n  imgAlt?: string\n}\n\nconst StrategyImage: React.FC<StrategyImageProps> = ({ img, imgAlt }) => {\n  const classes = useTabStyles()\n\n  return (\n    <div className={classes.strategyImgContainer}>\n      <Image className={classes.strategyImg} src={img} alt={imgAlt ?? ''} />\n    </div>\n  )\n}\n\nconst StrategyLayout: React.FC<{ children: any }> = ({ children }) => {\n  const router = useRouter()\n  const [selectedIdx, setSelectedIdx] = useState(() => routeMap[router.pathname])\n\n  const classes = useStyles()\n  const tabClasses = useTabStyles()\n\n  useEffect(() => {\n    setSelectedIdx(routeMap[router.pathname])\n  }, [router.pathname])\n\n  if (!allowedPaths.includes(router.pathname)) {\n    return children\n  }\n\n  const isBullPage = router.pathname === BULL_PATH\n\n  return (\n    <div>\n      <Nav />\n      {isBullPage && <ZenBullAlert />}\n\n      <Tabs\n        centered\n        classes={{ root: tabClasses.tabsRoot, indicator: tabClasses.tabsIndicator }}\n        value={selectedIdx}\n        indicatorColor=\"primary\"\n        textColor=\"primary\"\n        onChange={(_, value) => {\n          if (routeMap[BULL_PATH] === value) router.push(BULL_PATH)\n          if (routeMap[CRAB_PATH] === value) router.push(CRAB_PATH)\n        }}\n        aria-label=\"strategy tabs\"\n      >\n        <Tab\n          classes={{ root: tabClasses.tabRoot }}\n          label={<StrategyLabel title={Vaults.CrabVault} subtitle={VaultSubtitle.CrabVault} />}\n          icon={<StrategyImage img={crabStrategyImg} imgAlt=\"Crab USDC strategy\" />}\n        />\n        <Tab\n          classes={{ root: tabClasses.tabRoot }}\n          label={<StrategyLabel title={Vaults.ETHZenBull} subtitle={VaultSubtitle.ETHZenBull} />}\n          icon={<StrategyImage img={bullStrategyImg} imgAlt=\"Zen Bull ETH strategy\" />}\n        />\n      </Tabs>\n\n      <div className={classes.container}>{children}</div>\n    </div>\n  )\n}\n\nexport default StrategyLayout\n"
  },
  {
    "path": "packages/frontend/src/components/StrikeWarning.tsx",
    "content": "import { useRouter } from 'next/router'\nimport { Box, Link } from '@material-ui/core'\nimport { useAtomValue, useAtom } from 'jotai'\nimport { useState, useEffect } from 'react'\n\nimport { useRestrictUser } from '@context/restrict-user'\nimport { Modal } from './Modal/Modal'\nimport { connectedWalletAtom, isStrikeCountModalOpenAtom, addressStrikeCountAtom } from '@state/wallet/atoms'\nimport { LEGAL_PAGES } from '@constants/index'\n\ninterface StrikeWarningModalProps {\n  setIsStrikeModalShownOnce: (value: boolean) => void\n}\n\nconst StrikeWarningModal: React.FC<StrikeWarningModalProps> = ({ setIsStrikeModalShownOnce }) => {\n  const [isOpen, setIsOpen] = useState(true)\n\n  const onClose = () => {\n    setIsOpen(false)\n    setIsStrikeModalShownOnce(true)\n  }\n\n  return (\n    <Modal title=\"You are accessing from a restricted territory\" open={isOpen} handleClose={onClose}>\n      <Box px=\"4px\">\n        Any attempt to connect your wallet, including page refreshes, will be considered a strike. After three strikes,\n        your wallet address will be blocked.\n        <br />\n        <br />\n        Please be aware that refreshing the page will not resolve the issue, but will instead count towards your\n        strikes. Review our{' '}\n        <Link href=\"https://squeeth.opyn.co/terms-of-service\" target=\"_blank\">\n          Terms of Service\n        </Link>{' '}\n        for more details.\n      </Box>\n    </Modal>\n  )\n}\n\ninterface StrikeCountModalProps {\n  setIsStrikeModalShownOnce: (value: boolean) => void\n}\n\nconst StrikeCountModal: React.FC<StrikeCountModalProps> = ({ setIsStrikeModalShownOnce }) => {\n  const addressStrikeCount = useAtomValue(addressStrikeCountAtom)\n  const [isStrikeCountModalOpen, setIsStrikeCountModalOpen] = useAtom(isStrikeCountModalOpenAtom)\n\n  const onClose = () => {\n    setIsStrikeCountModalOpen(false)\n    setIsStrikeModalShownOnce(true)\n  }\n  if (addressStrikeCount < 3) {\n    return (\n      <Modal title=\"Strike Count Warning\" open={isStrikeCountModalOpen} handleClose={onClose}>\n        <Box px=\"4px\">\n          You have attempted to access opyn.co from a restricted territory. You currently have {addressStrikeCount}{' '}\n          strike(s). After three strikes your wallet address will be blocked.\n          <br />\n          <br />\n          Please review our{' '}\n          <Link href=\"https://squeeth.opyn.co/terms-of-service\" target=\"_blank\">\n            Terms of Service\n          </Link>{' '}\n          for more details.\n        </Box>\n      </Modal>\n    )\n  } else {\n    return (\n      <Modal title=\"Account blocked\" open={isStrikeCountModalOpen} handleClose={onClose}>\n        <Box px=\"4px\">\n          You have attempted to access opyn.co from a restricted territory 3 times. Your wallet address is blocked for\n          violating our terms of service. You cannot open any new positions. You can still close positions and remove\n          collateral from vaults.\n          <br />\n          <br />\n          Please review our{' '}\n          <Link href=\"https://opyn.co/terms-of-service\" target=\"_blank\">\n            Terms of Service\n          </Link>{' '}\n          for more details.\n        </Box>\n      </Modal>\n    )\n  }\n}\n\nexport default function StrikeModalManager() {\n  const [showModal, setShowModal] = useState(false)\n  const isWalletConnected = useAtomValue(connectedWalletAtom)\n  const [isStrikeModalShownOnce, setIsStrikeModalShownOnce] = useState(false)\n  const { isRestricted } = useRestrictUser()\n  const router = useRouter()\n\n  // Check if the current page is exempt from restriction (e.g., legal pages)\n  const isLegalPage = LEGAL_PAGES.includes(router.pathname)\n\n  // delayed state change - show modal after 2 seconds\n  // this is because it takes some time to automatically connect the wallet (incase previously connected)\n  useEffect(() => {\n    if (isRestricted && !isLegalPage) {\n      const timerId = setTimeout(() => setShowModal(true), 2_000)\n      // cleanup function to clear the timeout if the component is unmounted before the delay is over.\n      return () => clearTimeout(timerId)\n    }\n  }, [isRestricted, isLegalPage])\n\n  if (showModal) {\n    if (isWalletConnected) {\n      return <StrikeCountModal setIsStrikeModalShownOnce={setIsStrikeModalShownOnce} />\n    }\n    if (!isStrikeModalShownOnce) {\n      return <StrikeWarningModal setIsStrikeModalShownOnce={setIsStrikeModalShownOnce} />\n    }\n  }\n  return null\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Tabs.tsx",
    "content": "import { Tab, Tabs } from '@material-ui/core'\nimport { withStyles } from '@material-ui/core/styles'\n\nexport const SqueethTabs = withStyles((theme) => {\n  return {\n    root: {\n      borderRadius: theme.spacing(1),\n      background: theme.palette.background.lightStone,\n      padding: theme.spacing(0.75),\n    },\n    indicator: {\n      height: '100%',\n      borderRadius: theme.spacing(0.7),\n      background: theme.palette.primary.main,\n      opacity: '.1',\n    },\n  }\n})(Tabs)\n\nexport const SqueethTab = withStyles((theme) => {\n  return {\n    root: {\n      textTransform: 'initial',\n      minWidth: theme.spacing(10),\n      minHeight: 'auto',\n      '&$selected': {\n        color: theme.palette.primary.main,\n        fontWeight: theme.typography.fontWeightMedium,\n      },\n    },\n    selected: {\n      color: theme.palette.primary.main,\n    },\n  }\n})(Tab)\n\nexport const SqueethTabsNew = withStyles((theme) => {\n  return {\n    root: {\n      borderRadius: theme.spacing(1),\n      border: '2px solid',\n      borderColor: theme.palette.background.lightStone,\n      padding: theme.spacing(0.75),\n    },\n    indicator: {\n      height: '100%',\n      borderRadius: theme.spacing(1),\n      background: theme.palette.primary.main,\n    },\n  }\n})(Tabs)\n\nexport const SqueethTabNew = withStyles((theme) => {\n  return {\n    root: {\n      textTransform: 'initial',\n      minWidth: theme.spacing(10),\n      minHeight: 'auto',\n      width: '50%',\n      fontWeight: 700,\n      fontSize: '16px',\n      opacity: 1,\n      color: theme.palette.primary.contrastText,\n    },\n    selected: {\n      color: theme.palette.background.default,\n      zIndex: 10,\n    },\n  }\n})(Tab)\n\nexport const SecondaryTabs = withStyles((theme) => {\n  return {\n    root: {\n      background: 'transparent',\n      padding: theme.spacing(0),\n      borderRadius: theme.spacing(2, 2, 0, 0),\n    },\n    indicator: {\n      height: '0px',\n      width: '100%',\n      padding: theme.spacing(0),\n      background: 'transparent',\n    },\n  }\n})(Tabs)\n\nexport const SecondaryTab = withStyles((theme) => {\n  return {\n    root: {\n      textTransform: 'initial',\n      color: theme.palette.text.secondary,\n      backgroundColor: theme.palette.background.lightStone,\n      '&$selected': {\n        color: theme.palette.text.primary,\n        fontWeight: theme.typography.fontWeightMedium,\n        backgroundColor: 'transparent',\n      },\n    },\n    selected: {\n      color: theme.palette.primary.main,\n    },\n  }\n})(Tab)\n"
  },
  {
    "path": "packages/frontend/src/components/Trade/Cancelled.tsx",
    "content": "import { createStyles, makeStyles, Typography } from '@material-ui/core'\nimport React from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { EtherscanPrefix } from '@constants/index'\nimport { networkIdAtom } from '@state/wallet/atoms'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      textAlign: 'center',\n      marginBottom: theme.spacing(4),\n    },\n    etherscan: {\n      color: theme.palette.primary.main,\n      marginTop: theme.spacing(1),\n    },\n    thirdHeading: {\n      marginTop: theme.spacing(3),\n      paddingLeft: theme.spacing(1),\n      paddingRight: theme.spacing(1),\n    },\n    confMsg: {\n      marginTop: theme.spacing(1),\n    },\n    squeethCat: {\n      marginTop: theme.spacing(6),\n      marginBottom: theme.spacing(6),\n    },\n    uniswapLink: {\n      marginTop: theme.spacing(6),\n      marginBottom: theme.spacing(6),\n      display: 'flex',\n      alignItems: 'center',\n    },\n    uniLP: {\n      color: '#FF007A',\n      marginLeft: theme.spacing(3),\n      // textDecoration: 'underline',\n    },\n    infoIcon: {\n      fontSize: '1rem',\n      marginLeft: theme.spacing(0.5),\n      marginTop: '2px',\n    },\n    img: {\n      borderRadius: theme.spacing(2),\n    },\n  }),\n)\n\ntype ConfirmedProps = {\n  txnHash: string\n}\n\nconst Cancelled: React.FC<ConfirmedProps> = ({ txnHash }) => {\n  const classes = useStyles()\n  const networkId = useAtomValue(networkIdAtom)\n\n  return (\n    <div className={classes.container}>\n      <div>\n        <Typography variant=\"body1\" className={classes.confMsg}>\n          You cancelled the transaction\n        </Typography>\n        <a\n          className={classes.etherscan}\n          href={`${EtherscanPrefix[networkId]}${txnHash}`}\n          target=\"_blank\"\n          rel=\"noreferrer\"\n        >\n          View on Etherscan\n        </a>\n      </div>\n    </div>\n  )\n}\n\nexport default Cancelled\n"
  },
  {
    "path": "packages/frontend/src/components/Trade/Confirmed.tsx",
    "content": "import { createStyles, makeStyles, Typography } from '@material-ui/core'\nimport Image from 'next/image'\nimport React from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { EtherscanPrefix } from '@constants/index'\nimport { networkIdAtom } from '@state/wallet/atoms'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      textAlign: 'center',\n      marginBottom: theme.spacing(4),\n    },\n    etherscan: {\n      color: theme.palette.primary.main,\n      marginTop: theme.spacing(1),\n    },\n    thirdHeading: {\n      marginTop: theme.spacing(3),\n      paddingLeft: theme.spacing(1),\n      paddingRight: theme.spacing(1),\n    },\n    confMsg: {\n      marginTop: theme.spacing(1),\n    },\n    uniswapLink: {\n      marginTop: theme.spacing(6),\n      marginBottom: theme.spacing(6),\n      display: 'flex',\n      alignItems: 'center',\n    },\n    uniLP: {\n      color: '#FF007A',\n      marginLeft: theme.spacing(3),\n    },\n    infoIcon: {\n      fontSize: '1rem',\n      marginLeft: theme.spacing(0.5),\n      marginTop: '2px',\n    },\n  }),\n)\n\nconst useConfirmGraphicStyles = makeStyles((theme) =>\n  createStyles({\n    graphic: {\n      marginTop: theme.spacing(4),\n    },\n    img: {\n      borderRadius: theme.spacing(2),\n    },\n  }),\n)\n\nconst ConfirmGraphic: React.FC<{ type?: ConfirmType }> = ({ type }) => {\n  const classes = useConfirmGraphicStyles()\n  if (type === ConfirmType.CRAB)\n    return (\n      <div className={classes.graphic}>\n        <Image\n          src=\"https://media.giphy.com/media/ukLCGEh7kXDJ5wNWT7/giphy.gif\"\n          alt=\"squeeth crab cat\"\n          width={120}\n          height={120}\n          className={classes.img}\n        />\n        <Typography variant=\"body1\" component=\"div\">\n          Stay Crabby!\n        </Typography>\n      </div>\n    )\n  if (type === ConfirmType.TRADE)\n    return (\n      <div className={classes.graphic}>\n        <Image\n          src=\"https://media.giphy.com/media/eYU60NpFPCONDEItBa/giphy.gif\"\n          alt=\"squeeth cat\"\n          width={120}\n          height={120}\n          className={classes.img}\n        />\n        <Typography variant=\"body1\" component=\"div\">\n          Stay Squeethy!\n        </Typography>\n      </div>\n    )\n\n  if (type === ConfirmType.BULL)\n    return (\n      <div className={classes.graphic}>\n        <Image\n          src=\"https://media.giphy.com/media/j2VvomNXigtS1MfeT8/giphy.gif\"\n          alt=\"squeeth bull cat\"\n          width={120}\n          height={120}\n          className={classes.img}\n        />\n        <Typography variant=\"body1\" component=\"div\">\n          Stay Bullish!\n        </Typography>\n      </div>\n    )\n  return <></>\n}\n\nexport enum ConfirmType {\n  TRADE,\n  CRAB,\n  BULL,\n}\n\ntype ConfirmedProps = {\n  confirmationMessage: string\n  txnHash: string\n  confirmType: ConfirmType\n}\n\nconst Confirmed: React.FC<ConfirmedProps> = ({ confirmationMessage, txnHash, confirmType }) => {\n  const classes = useStyles()\n  const networkId = useAtomValue(networkIdAtom)\n\n  return (\n    <div className={classes.container}>\n      <div>\n        <Typography variant=\"body1\" className={classes.confMsg} id=\"conf-msg\">\n          {' '}\n          {confirmationMessage}{' '}\n        </Typography>\n        <a\n          className={classes.etherscan}\n          href={`${EtherscanPrefix[networkId]}${txnHash}`}\n          target=\"_blank\"\n          rel=\"noreferrer\"\n        >\n          {' '}\n          View on Etherscan{' '}\n        </a>\n      </div>\n      {/* <ConfirmGraphic type={confirmType} /> */}\n    </div>\n  )\n}\n\nexport default Confirmed\n"
  },
  {
    "path": "packages/frontend/src/components/Trade/Long/index.tsx",
    "content": "import { CircularProgress, createStyles, makeStyles, Typography, Box, Collapse } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport { useAtom, useAtomValue } from 'jotai'\nimport { useResetAtom, useUpdateAtom } from 'jotai/utils'\nimport React, { useState } from 'react'\n\nimport { PrimaryButtonNew } from '@components/Button'\nimport { InputToken } from '@components/InputNew'\nimport Alert from '@components/Alert'\nimport useAppCallback from '@hooks/useAppCallback'\nimport useAppEffect from '@hooks/useAppEffect'\nimport { useShutdownLongHelper } from '@hooks/contracts/useLongHelper'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { LONG_SQUEETH_EVENTS } from '@utils/amplitude'\n\nimport { addressesAtom } from '@state/positions/atoms'\n\nimport {\n  confirmedAmountAtom,\n  ethTradeAmountAtom,\n  sqthTradeAmountAtom,\n  tradeCompletedAtom,\n  tradeSuccessAtom,\n} from '@state/trade/atoms'\nimport { connectedWalletAtom, isTransactionFirstStepAtom, supportedNetworkAtom } from '@state/wallet/atoms'\nimport { useSelectWallet, useTransactionStatus } from '@state/wallet/hooks'\nimport { OSQUEETH_DECIMALS } from '@constants/index'\nimport { formatNumber } from '@utils/formatter'\nimport osqthLogo from 'public/images/osqth-logo.svg'\nimport Cancelled from '../Cancelled'\nimport Confirmed, { ConfirmType } from '../Confirmed'\nimport Metric from '@components/Metric'\nimport RestrictionInfo from '@components/RestrictionInfo'\nimport { useRestrictUser } from '@context/restrict-user'\nimport { useGetOSqthSettlementAmount } from '@state/controller/hooks'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    header: {\n      color: theme.palette.primary.main,\n    },\n    title: {\n      fontSize: '20px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n      marginBottom: '24px',\n    },\n    sectionTitle: {\n      fontSize: '20px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n      marginBottom: '16px',\n    },\n    body: {\n      padding: theme.spacing(2, 12),\n      margin: 'auto',\n      display: 'flex',\n      justifyContent: 'space-around',\n    },\n    subHeading: {\n      color: theme.palette.text.secondary,\n    },\n    thirdHeading: {\n      marginTop: theme.spacing(2),\n      paddingLeft: theme.spacing(1),\n      paddingRight: theme.spacing(1),\n    },\n    explainer: {\n      marginTop: theme.spacing(2),\n      paddingLeft: theme.spacing(1),\n      paddingRight: theme.spacing(1),\n      marginLeft: theme.spacing(1),\n      width: '200px',\n      justifyContent: 'left',\n    },\n    caption: {\n      marginTop: theme.spacing(1),\n      fontSize: '13px',\n    },\n    divider: {\n      margin: theme.spacing(2, 0),\n      width: '300px',\n      marginLeft: 'auto',\n      marginRight: 'auto',\n    },\n    details: {\n      marginTop: theme.spacing(4),\n      width: '65%',\n    },\n    buyCard: {\n      marginTop: theme.spacing(4),\n      marginLeft: theme.spacing(2),\n    },\n    cardTitle: {\n      color: theme.palette.primary.main,\n      marginTop: theme.spacing(4),\n    },\n    cardSubTxt: {\n      color: theme.palette.text.secondary,\n      lineHeight: '1.75rem',\n      fontSize: '16px',\n      width: '90%',\n    },\n    payoff: {\n      color: theme.palette.text.secondary,\n      lineHeight: '1.75rem',\n      fontSize: '16px',\n    },\n    cardDetail: {\n      color: theme.palette.text.secondary,\n      lineHeight: '1.75rem',\n      fontSize: '16px',\n      marginTop: theme.spacing(4),\n    },\n    amountInput: {\n      backgroundColor: theme.palette.success.main,\n      '&:hover': {\n        backgroundColor: theme.palette.success.dark,\n      },\n    },\n    innerCard: {\n      textAlign: 'center',\n      padding: theme.spacing(2),\n      paddingBottom: theme.spacing(8),\n      background: theme.palette.background.default,\n      border: `1px solid ${theme.palette.background.stone}`,\n    },\n    expand: {\n      transform: 'rotate(270deg)',\n      color: theme.palette.primary.main,\n      transition: theme.transitions.create('transform', {\n        duration: theme.transitions.duration.shortest,\n      }),\n      marginTop: theme.spacing(6),\n    },\n    expandOpen: {\n      transform: 'rotate(180deg)',\n      color: theme.palette.primary.main,\n    },\n    dialog: {\n      padding: theme.spacing(2),\n    },\n    dialogHeader: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    dialogIcon: {\n      marginRight: theme.spacing(1),\n      color: theme.palette.warning.main,\n    },\n    txItem: {\n      marginTop: theme.spacing(1),\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n    },\n    squeethExp: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      borderRadius: theme.spacing(1),\n      padding: theme.spacing(1.5),\n      width: '300px',\n      marginLeft: 'auto',\n      marginRight: 'auto',\n      marginTop: theme.spacing(2),\n      textAlign: 'left',\n      backgroundColor: theme.palette.background.stone,\n    },\n    squeethExpTxt: {\n      fontSize: '20px',\n    },\n    closePosition: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      padding: theme.spacing(0, 1),\n    },\n    closeBtn: {\n      color: theme.palette.error.main,\n    },\n    paper: {\n      backgroundColor: theme.palette.background.paper,\n      boxShadow: theme.shadows[5],\n      borderRadius: theme.spacing(1),\n      width: '350px',\n      textAlign: 'center',\n      paddingBottom: theme.spacing(2),\n    },\n    modal: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n    },\n    buttonDiv: {\n      position: 'sticky',\n      bottom: '0',\n      backgroundColor: theme.palette.background.default,\n      zIndex: 1500,\n    },\n    hint: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    arrowIcon: {\n      marginLeft: '4px',\n      marginRight: '4px',\n      fontSize: '20px',\n    },\n    hintTextContainer: {\n      display: 'flex',\n    },\n    hintTitleText: {\n      marginRight: '.5em',\n    },\n    linkHover: {\n      '&:hover': {\n        opacity: 0.7,\n      },\n    },\n    anchor: {\n      color: '#FF007A',\n      fontSize: '16px',\n    },\n    settingsContainer: {\n      display: 'flex',\n      justify: 'space-between',\n      alignItems: 'center',\n    },\n    settingsButton: {\n      marginTop: theme.spacing(2),\n      marginLeft: theme.spacing(10),\n      justifyContent: 'right',\n      alignSelf: 'center',\n    },\n    displayBlock: {\n      display: 'block',\n    },\n    displayNone: {\n      display: 'none',\n    },\n    lightStoneBackground: {\n      backgroundColor: theme.palette.background.lightStone,\n    },\n    txStatus: {\n      marginTop: theme.spacing(4),\n    },\n    labelContainer: {\n      display: 'flex',\n      alignItems: 'center',\n      color: 'rgba(255, 255, 255, 0.5)',\n    },\n    label: {\n      fontSize: '15px',\n      fontWeight: 500,\n      width: 'max-content',\n    },\n    infoIcon: {\n      fontSize: '15px',\n      marginLeft: theme.spacing(0.5),\n    },\n  }),\n)\n\nconst RedeemLong: React.FC<BuyProps> = () => {\n  const [isRedeemTxnLoading, setIsRedeemTxnLoading] = useState(false)\n  const [isEthToReceiveLoading, setIsEthToReceiveLoading] = useState(false)\n  const [ethToReceive, setEthToReceive] = useState<BigNumber>(new BigNumber(0))\n\n  const classes = useStyles()\n  const {\n    cancelled,\n    confirmed,\n    loading: transactionInProgress,\n    transactionData,\n    resetTxCancelled,\n    resetTransactionData,\n  } = useTransactionStatus()\n\n  const { oSqueeth, controller } = useAtomValue(addressesAtom)\n  const { redeemLongHelper } = useShutdownLongHelper()\n\n  const [confirmedAmount, setConfirmedAmount] = useAtom(confirmedAmountAtom)\n  const setTradeSuccess = useUpdateAtom(tradeSuccessAtom)\n  const setTradeCompleted = useUpdateAtom(tradeCompletedAtom)\n\n  const { isRestricted, isWithdrawAllowed } = useRestrictUser()\n\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n  const connected = useAtomValue(connectedWalletAtom)\n  const selectWallet = useSelectWallet()\n  const {\n    value: oSqueethBalance,\n    loading: isOSqueethBalanceLoading,\n    refetch: refetchOSqueethBalance,\n  } = useTokenBalance(oSqueeth, 30, OSQUEETH_DECIMALS)\n\n  const getOSqthSettlementAmount = useGetOSqthSettlementAmount()\n\n  const resetEthTradeAmount = useResetAtom(ethTradeAmountAtom)\n  const resetSqthTradeAmount = useResetAtom(sqthTradeAmountAtom)\n\n  const { track } = useAmplitude()\n\n  useAppEffect(() => {\n    if (transactionInProgress) {\n      setIsRedeemTxnLoading(false)\n    }\n  }, [transactionInProgress])\n\n  // Update the effect to handle loading state\n  useAppEffect(() => {\n    let mounted = true\n\n    const fetchEthToReceive = async () => {\n      if (oSqueethBalance.isGreaterThan(0)) {\n        setIsEthToReceiveLoading(true)\n\n        try {\n          const settlementAmount = await getOSqthSettlementAmount(oSqueethBalance)\n          if (mounted) {\n            setEthToReceive(settlementAmount)\n          }\n        } catch (e) {\n          console.log(e)\n        } finally {\n          if (mounted) {\n            setIsEthToReceiveLoading(false)\n          }\n        }\n      } else {\n        if (mounted) {\n          setEthToReceive(new BigNumber(0))\n          setIsEthToReceiveLoading(false)\n        }\n      }\n    }\n\n    fetchEthToReceive()\n\n    return () => {\n      mounted = false\n    }\n  }, [oSqueethBalance.toString(), getOSqthSettlementAmount])\n\n  const redeemLong = useAppCallback(async () => {\n    setIsRedeemTxnLoading(true)\n    try {\n      track(LONG_SQUEETH_EVENTS.REDEEM_LONG_OSQTH_CLICK)\n\n      await redeemLongHelper(oSqueethBalance, () => {\n        setTradeSuccess(true)\n        setTradeCompleted(true)\n        setConfirmedAmount(oSqueethBalance.toFixed(6))\n        resetEthTradeAmount()\n        resetSqthTradeAmount()\n        refetchOSqueethBalance()\n\n        track(LONG_SQUEETH_EVENTS.REDEEM_LONG_OSQTH_SUCCESS, {\n          amount: oSqueethBalance.toNumber(),\n          ethReceived: ethToReceive.toNumber(),\n        })\n      })\n    } catch (e) {\n      console.log(e)\n      setIsRedeemTxnLoading(false)\n      track(LONG_SQUEETH_EVENTS.REDEEM_LONG_OSQTH_FAILED, {\n        amount: oSqueethBalance.toNumber(),\n      })\n    }\n  }, [\n    oSqueethBalance?.toString(),\n    resetEthTradeAmount,\n    resetSqthTradeAmount,\n    redeemLongHelper,\n    setTradeCompleted,\n    setTradeSuccess,\n    setConfirmedAmount,\n    ethToReceive?.toString(),\n  ])\n\n  // let openError: string | undefined\n  let redeemError: string | undefined\n\n  if (connected) {\n    if (!isOSqueethBalanceLoading && oSqueethBalance.lte(0)) {\n      redeemError = 'No position to redeem'\n    }\n  }\n\n  return (\n    <div id=\"redeem-long-card\">\n      {confirmed ? (\n        <>\n          <Confirmed\n            confirmationMessage={`Redeemed ${confirmedAmount} Squeeth`}\n            txnHash={transactionData?.hash ?? ''}\n            confirmType={ConfirmType.TRADE}\n          />\n          <div className={classes.buttonDiv}>\n            <PrimaryButtonNew\n              fullWidth\n              id=\"redeem-long-close-btn\"\n              variant=\"contained\"\n              onClick={() => {\n                resetTransactionData()\n              }}\n            >\n              {'Close'}\n            </PrimaryButtonNew>\n          </div>\n        </>\n      ) : cancelled ? (\n        <>\n          <Cancelled txnHash={transactionData?.hash ?? ''} />\n          <div className={classes.buttonDiv}>\n            <PrimaryButtonNew\n              fullWidth\n              variant=\"contained\"\n              onClick={() => {\n                resetTransactionData()\n                resetTxCancelled()\n              }}\n            >\n              {'Close'}\n            </PrimaryButtonNew>\n          </div>\n        </>\n      ) : (\n        <>\n          <Typography variant=\"h4\" className={classes.title}>\n            Redeem oSQTH Position\n          </Typography>\n\n          <Box display=\"flex\" flexDirection=\"column\" gridGap=\"16px\">\n            <InputToken\n              id=\"redeem-long-osqth-input\"\n              label=\"oSQTH position\"\n              value={oSqueethBalance.toString()}\n              balance={oSqueethBalance}\n              isBalanceLoading={isOSqueethBalanceLoading}\n              symbol=\"oSQTH\"\n              logo={osqthLogo}\n              showMaxAction={false}\n              error={!!redeemError}\n              helperText={redeemError}\n              readOnly={true}\n              readOnlyTooltip={'Only full redemption is allowed'}\n            />\n          </Box>\n\n          <Collapse in={!!redeemError}>\n            <Alert severity=\"error\" marginTop=\"24px\">\n              {redeemError}\n            </Alert>\n          </Collapse>\n\n          <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" flexWrap=\"wrap\" marginTop=\"12px\">\n            <Metric\n              label=\"ETH you will receive\"\n              value={isEthToReceiveLoading ? 'Loading...' : formatNumber(ethToReceive.toNumber(), 4) + ' ETH'}\n              isSmall\n              flexDirection=\"row\"\n              justifyContent=\"space-between\"\n              gridGap=\"12px\"\n            />\n          </Box>\n\n          {isRestricted && <RestrictionInfo withdrawAllowed={isWithdrawAllowed} marginTop=\"24px\" />}\n\n          <Box marginTop=\"24px\" className={classes.buttonDiv}>\n            {isRestricted && !isWithdrawAllowed ? (\n              <PrimaryButtonNew\n                fullWidth\n                variant=\"contained\"\n                onClick={selectWallet}\n                disabled={true}\n                id=\"redeem-long-restricted-btn\"\n              >\n                {'Unavailable'}\n              </PrimaryButtonNew>\n            ) : !connected ? (\n              <PrimaryButtonNew\n                fullWidth\n                variant=\"contained\"\n                onClick={selectWallet}\n                disabled={!!isRedeemTxnLoading}\n                id=\"redeem-long-connect-wallet-btn\"\n              >\n                {'Connect Wallet'}\n              </PrimaryButtonNew>\n            ) : (\n              <PrimaryButtonNew\n                fullWidth\n                onClick={redeemLong}\n                disabled={\n                  !supportedNetwork ||\n                  isOSqueethBalanceLoading ||\n                  isRedeemTxnLoading ||\n                  transactionInProgress ||\n                  !!redeemError ||\n                  oSqueethBalance.isZero() ||\n                  isEthToReceiveLoading\n                }\n                id=\"redeem-long-submit-tx-btn\"\n              >\n                {!supportedNetwork ? (\n                  'Unsupported Network'\n                ) : isOSqueethBalanceLoading || isRedeemTxnLoading || transactionInProgress || isEthToReceiveLoading ? (\n                  <CircularProgress color=\"primary\" size=\"1.5rem\" />\n                ) : (\n                  'Redeem oSQTH'\n                )}\n              </PrimaryButtonNew>\n            )}\n          </Box>\n        </>\n      )}\n    </div>\n  )\n}\n\ntype BuyProps = {\n  open?: boolean\n  isLPage?: boolean\n  activeStep?: number\n  showTitle?: boolean\n}\n\nconst Long: React.FC<BuyProps> = ({ open, isLPage = false, activeStep = 0, showTitle = true }) => {\n  return <RedeemLong isLPage={isLPage} activeStep={activeStep} showTitle={showTitle} />\n}\n\nexport default Long\n"
  },
  {
    "path": "packages/frontend/src/components/Trade/Mint.tsx",
    "content": "import { CircularProgress, InputAdornment, Typography, Box, Collapse } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport BigNumber from 'bignumber.js'\nimport React, { useState, useEffect, useMemo } from 'react'\nimport { useAtomValue } from 'jotai'\nimport Link from 'next/link'\n\nimport {\n  BIG_ZERO,\n  MIN_COLLATERAL_AMOUNT,\n  OSQUEETH_DECIMALS,\n  Tooltips,\n  DEFAULT_COLLATERAL_RATIO,\n} from '@constants/index'\nimport { toTokenAmount } from '@utils/calculations'\nimport { PrimaryButtonNew } from '@components/Button'\nimport { InputToken, InputNumber } from '@components/InputNew'\nimport CollatRatioSlider from '@components/CollatRatioSlider'\nimport { useVaultManager } from '@hooks/contracts/useVaultManager'\nimport { useWalletBalance, useSelectWallet } from '@state/wallet/hooks'\nimport { connectedWalletAtom, supportedNetworkAtom } from '@state/wallet/atoms'\nimport { addressesAtom } from '@state/positions/atoms'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport { useGetCollatRatioAndLiqPrice, useGetShortAmountFromDebt, useOpenDepositAndMint } from '@state/controller/hooks'\nimport { useFirstValidVault } from '@state/positions/hooks'\nimport { useVaultData } from '@hooks/useVaultData'\nimport useAppEffect from '@hooks/useAppEffect'\nimport { useETHPrice } from '@hooks/useETHPrice'\nimport ethLogo from 'public/images/eth-logo.svg'\nimport osqthLogo from 'public/images/osqth-logo.svg'\nimport Alert from '@components/Alert'\nimport Checkbox from '@components/Checkbox'\nimport useAppCallback from '@hooks/useAppCallback'\nimport { useOSQTHPrice } from '@hooks/useOSQTHPrice'\nimport Metric, { MetricLabel } from '@components/Metric'\nimport { formatNumber, formatCurrency } from '@utils/formatter'\nimport RestrictionInfo from '@components/RestrictionInfo'\nimport { useRestrictUser } from '@context/restrict-user'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    link: {\n      color: theme.palette.primary.main,\n      marginBottom: theme.spacing(2),\n      textDecoration: 'underline',\n    },\n    label: {\n      fontSize: '18px',\n      fontWeight: 700,\n    },\n  }),\n)\n\ninterface MintProps {\n  onMint: () => void\n  showManageLink?: boolean\n}\n\nconst MintSqueeth: React.FC<MintProps> = ({ onMint, showManageLink }) => {\n  const classes = useStyles()\n  const { oSqueeth } = useAtomValue(addressesAtom)\n  const { value: oSqueethBal } = useTokenBalance(oSqueeth, 15, OSQUEETH_DECIMALS)\n  const { data } = useWalletBalance()\n  const connected = useAtomValue(connectedWalletAtom)\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n  const { loading: vaultIDLoading } = useVaultManager()\n  const openDepositAndMint = useOpenDepositAndMint()\n  const getShortAmountFromDebt = useGetShortAmountFromDebt()\n  const getCollatRatioAndLiqPrice = useGetCollatRatioAndLiqPrice()\n  const { validVault: vault, vaultId } = useFirstValidVault()\n  const { existingCollat, existingCollatPercent } = useVaultData(vault)\n  const ethPrice = useETHPrice()\n  const { data: osqthPrice } = useOSQTHPrice()\n  const { isRestricted, isWithdrawAllowed } = useRestrictUser()\n  const selectWallet = useSelectWallet()\n\n  const [mintAmount, setMintAmount] = useState(new BigNumber(0))\n  const [collatAmount, setCollatAmount] = useState('0')\n  const collatAmountBN = useMemo(() => new BigNumber(collatAmount), [collatAmount])\n  const [collatPercent, setCollatPercent] = useState(200)\n  const [loading, setLoading] = useState(false)\n  const [mintMinCollatError, setMintMinCollatError] = useState('')\n  const [minCollRatioError, setMinCollRatioError] = useState('')\n  const [liqPrice, setLiqPrice] = useState(BIG_ZERO)\n  const [usingDefaultCollatRatio, setUsingDefaultCollatRatio] = useState(true)\n\n  const balance = toTokenAmount(data ?? BIG_ZERO, 18)\n\n  const mint = async () => {\n    setLoading(true)\n    try {\n      if (vaultIDLoading) return\n      await openDepositAndMint(Number(vaultId), mintAmount, collatAmountBN)\n      onMint()\n    } catch (e) {\n      console.log(e)\n    }\n    setLoading(false)\n  }\n\n  useAppEffect(() => {\n    let isMounted = true\n\n    if (collatAmountBN.isNaN() || collatAmountBN.isZero()) {\n      //if no collateral is being inputted and user is not trying to only adjust vault collateral\n      if (isMounted) setMintAmount(new BigNumber(0))\n      return\n    }\n    const debt = collatAmountBN.times(100).div(collatPercent)\n    getShortAmountFromDebt(debt).then((s) => {\n      if (isMounted) setMintAmount(s)\n    })\n    return () => {\n      isMounted = false\n    }\n  }, [collatPercent, collatAmountBN.toString()])\n\n  useAppEffect(() => {\n    if (collatPercent < 150) {\n      setMinCollRatioError('Minimum collateral ratio is 150%')\n    } else {\n      setMinCollRatioError('')\n    }\n\n    if (connected && collatAmountBN.isGreaterThan(balance)) {\n      setMintMinCollatError('Insufficient ETH balance')\n    } else if (connected && collatAmountBN.plus(existingCollat).lt(MIN_COLLATERAL_AMOUNT)) {\n      setMintMinCollatError('Minimum collateral is 6.9 ETH')\n    }\n  }, [balance.toString(), connected, existingCollat.toString(), collatAmountBN.toString(), collatPercent])\n\n  const handleDefaultCollatRatioToggle = useAppCallback(\n    (value: boolean) => {\n      if (value) {\n        setCollatPercent(DEFAULT_COLLATERAL_RATIO)\n      }\n      setUsingDefaultCollatRatio(value)\n    },\n    [setCollatPercent],\n  )\n\n  useEffect(() => {\n    if (collatPercent !== DEFAULT_COLLATERAL_RATIO) {\n      setUsingDefaultCollatRatio(false)\n    }\n  }, [collatPercent])\n\n  useAppEffect(() => {\n    getCollatRatioAndLiqPrice(collatAmountBN, mintAmount).then(({ liquidationPrice }) => {\n      setLiqPrice(liquidationPrice)\n    })\n  }, [collatAmountBN, mintAmount, getCollatRatioAndLiqPrice, vault?.shortAmount])\n\n  const error = mintMinCollatError ? mintMinCollatError : minCollRatioError ? minCollRatioError : ''\n\n  return (\n    <div>\n      {vaultId && showManageLink ? (\n        <Typography className={classes.link}>\n          <Link href={`vault/${vaultId}`}>Manage Vault</Link>\n        </Typography>\n      ) : null}\n\n      <Box display=\"flex\" flexDirection=\"column\">\n        <InputToken\n          id=\"lp-page-mint-eth-input\"\n          value={collatAmount}\n          onInputChange={(v) => setCollatAmount(v)}\n          symbol=\"ETH\"\n          logo={ethLogo}\n          balance={balance}\n          usdPrice={ethPrice}\n          onBalanceClick={() => setCollatAmount(balance.toString())}\n          error={!!mintMinCollatError}\n          helperText={mintMinCollatError}\n        />\n      </Box>\n\n      <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" marginTop=\"24px\">\n        <Typography variant=\"h4\" className={classes.label}>\n          Collateral ratio\n        </Typography>\n\n        <Box display=\"flex\" alignItems=\"center\" gridGap=\"16px\">\n          <Checkbox\n            name=\"priceRangeDefault\"\n            label=\"Default\"\n            isChecked={usingDefaultCollatRatio}\n            onInputChange={handleDefaultCollatRatioToggle}\n          />\n\n          <InputNumber\n            id=\"collateral-ratio-input\"\n            value={collatPercent}\n            onInputChange={(value) => setCollatPercent(Number(value))}\n            InputProps={{\n              endAdornment: (\n                <InputAdornment position=\"end\" style={{ opacity: '0.5' }}>\n                  %\n                </InputAdornment>\n              ),\n            }}\n            style={{ width: '80px' }}\n          />\n        </Box>\n      </Box>\n\n      <Box marginTop=\"24px\">\n        <CollatRatioSlider\n          collatRatio={collatPercent}\n          onCollatRatioChange={(value) => setCollatPercent(value)}\n          minCollatRatio={150}\n        />\n\n        <Box marginTop=\"12px\">\n          <Collapse in={collatPercent <= 150}>\n            <Alert severity=\"error\" id={'collat-ratio-slider-alert-text'}>\n              You will get liquidated.\n            </Alert>\n          </Collapse>\n          <Collapse in={collatPercent > 150 && collatPercent < 200}>\n            <Alert severity=\"warning\" id={'collat-ratio-slider-alert-text'}>\n              Collateral ratio is too low. You will get liquidated at 150%.\n            </Alert>\n          </Collapse>\n\n          <Collapse in={collatPercent >= 200 && collatPercent < 225}>\n            <Alert severity=\"warning\" id={'collat-ratio-slider-alert-text'}>\n              Collateral ratio is risky.\n            </Alert>\n          </Collapse>\n        </Box>\n      </Box>\n\n      <Box marginTop=\"24px\">\n        <InputToken\n          id=\"lp-page-mint-trade-details\"\n          label=\"Mint\"\n          value={mintAmount.toFixed(6)}\n          symbol=\"oSQTH\"\n          logo={osqthLogo}\n          balance={oSqueethBal}\n          usdPrice={osqthPrice}\n          showMaxAction={false}\n          readOnly\n        />\n      </Box>\n\n      <Collapse in={!!error}>\n        <Alert severity=\"error\" marginTop=\"24px\">\n          {error}\n        </Alert>\n      </Collapse>\n\n      <Box\n        display=\"flex\"\n        justifyContent=\"space-between\"\n        alignItems=\"center\"\n        gridGap=\"12px\"\n        marginTop=\"24px\"\n        flexWrap=\"wrap\"\n      >\n        <Metric\n          isSmall\n          label={\n            <MetricLabel\n              isSmall\n              label=\"Liquidation Price\"\n              tooltipTitle={`${Tooltips.LiquidationPrice}. ${Tooltips.Twap}`}\n            />\n          }\n          value={formatCurrency(liqPrice.toNumber())}\n        />\n        <Metric\n          isSmall\n          label={<MetricLabel isSmall label=\"Current collateral ratio\" tooltipTitle={Tooltips.CurrentCollRatio} />}\n          value={formatNumber(existingCollatPercent) + '%'}\n        />\n      </Box>\n\n      {isRestricted && <RestrictionInfo withdrawAllowed={isRestricted} marginTop=\"24px\" />}\n\n      <Box marginTop=\"24px\">\n        {isRestricted ? (\n          <PrimaryButtonNew fullWidth variant=\"contained\" disabled={true} id=\"mint-to-lp-restricted-btn\">\n            {'Unavailable'}\n          </PrimaryButtonNew>\n        ) : !connected ? (\n          <PrimaryButtonNew fullWidth variant=\"contained\" onClick={selectWallet} id=\"mint-to-lp-connect-wallet-btn\">\n            {'Connect Wallet'}\n          </PrimaryButtonNew>\n        ) : (\n          <PrimaryButtonNew\n            id=\"mint-to-lp-btn\"\n            variant=\"contained\"\n            onClick={mint}\n            fullWidth\n            disabled={\n              !supportedNetwork ||\n              (connected && collatAmountBN.plus(existingCollat).lt(MIN_COLLATERAL_AMOUNT)) ||\n              loading\n            }\n          >\n            {!supportedNetwork ? (\n              'Unsupported Network'\n            ) : loading ? (\n              <CircularProgress color=\"primary\" size=\"1.5rem\" />\n            ) : (\n              'Mint'\n            )}\n          </PrimaryButtonNew>\n        )}\n      </Box>\n    </div>\n  )\n}\n\nexport default MintSqueeth\n"
  },
  {
    "path": "packages/frontend/src/components/Trade/Short/index.tsx",
    "content": "import { makeStyles, createStyles } from '@material-ui/core/styles'\nimport { Box, Typography, CircularProgress, Collapse } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport React, { memo, useState } from 'react'\nimport { useAtom, useAtomValue } from 'jotai'\nimport { atomWithStorage, useUpdateAtom } from 'jotai/utils'\n\nimport { useShutdownShortHelper } from '@hooks/contracts/useShortHelper'\nimport { useVaultManager } from '@hooks/contracts/useVaultManager'\nimport { PrimaryButtonNew } from '@components/Button'\nimport { InputToken } from '@components/InputNew'\nimport Alert from '@components/Alert'\nimport Confirmed, { ConfirmType } from '@components/Trade/Confirmed'\nimport { connectedWalletAtom, supportedNetworkAtom, addressAtom } from '@state/wallet/atoms'\nimport { useSelectWallet, useTransactionStatus } from '@state/wallet/hooks'\nimport { vaultHistoryUpdatingAtom } from '@state/positions/atoms'\nimport { useOSQTHPrice } from '@hooks/useOSQTHPrice'\nimport { useGetOSqthSettlementAmount, useGetUniNFTDetails } from '@state/controller/hooks'\nimport { useFirstValidVault } from '@state/positions/hooks'\nimport { tradeCompletedAtom, tradeSuccessAtom } from '@state/trade/atoms'\nimport Cancelled from '../Cancelled'\nimport useAppEffect from '@hooks/useAppEffect'\nimport useAppCallback from '@hooks/useAppCallback'\nimport { useVaultHistoryQuery } from '@hooks/useVaultHistory'\nimport Metric from '@components/Metric'\nimport osqthLogo from 'public/images/osqth-logo.svg'\nimport { formatNumber } from '@utils/formatter'\nimport RestrictionInfo from '@components/RestrictionInfo'\nimport { useRestrictUser } from '@context/restrict-user'\nimport useAmplitude from '@hooks/useAmplitude'\nimport { SHORT_SQUEETH_EVENTS } from '@utils/amplitude'\nimport useVault from '@hooks/useVault'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    title: {\n      fontSize: '20px',\n      fontWeight: 700,\n      letterSpacing: '-0.01em',\n      marginBottom: '24px',\n    },\n    label: {\n      fontSize: '18px',\n      fontWeight: 700,\n    },\n    cardTitle: {\n      color: theme.palette.primary.main,\n      marginTop: theme.spacing(4),\n    },\n    cardHeader: {\n      color: theme.palette.primary.main,\n      marginTop: theme.spacing(2),\n    },\n    cardSubTxt: {\n      color: theme.palette.text.secondary,\n      lineHeight: '1.75rem',\n      fontSize: '16px',\n    },\n    innerCard: {\n      paddingBottom: theme.spacing(0),\n    },\n    amountInput: {\n      backgroundColor: `${theme.palette.error.main}aa`,\n      '&:hover': {\n        backgroundColor: theme.palette.error.dark,\n      },\n    },\n    thirdHeading: {\n      marginTop: theme.spacing(2),\n    },\n    explainer: {\n      marginTop: theme.spacing(2),\n      paddingLeft: theme.spacing(1),\n      paddingRight: theme.spacing(1),\n      marginLeft: theme.spacing(1),\n      width: '200px',\n      justifyContent: 'left',\n    },\n    caption: {\n      marginTop: theme.spacing(1),\n      fontSize: '13px',\n    },\n    txItem: {\n      display: 'flex',\n      padding: theme.spacing(0, 1),\n      marginTop: theme.spacing(1),\n      justifyContent: 'center',\n      alignItems: 'center',\n    },\n    txLabel: {\n      fontSize: '14px',\n      color: theme.palette.text.secondary,\n    },\n    txUnit: {\n      fontSize: '12px',\n      color: theme.palette.text.secondary,\n      marginLeft: theme.spacing(1),\n    },\n    infoIcon: {\n      fontSize: '1rem',\n      marginLeft: theme.spacing(0.5),\n      color: theme.palette.text.secondary,\n    },\n    squeethExp: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      borderRadius: theme.spacing(1),\n      padding: theme.spacing(1.5),\n      width: '300px',\n      marginLeft: 'auto',\n      marginRight: 'auto',\n      marginTop: theme.spacing(2),\n      textAlign: 'left',\n      backgroundColor: theme.palette.background.stone,\n    },\n    squeethExpTxt: {\n      fontSize: '20px',\n    },\n    divider: {\n      margin: theme.spacing(2, 0),\n      width: '300px',\n      marginLeft: 'auto',\n      marginRight: 'auto',\n    },\n    closePosition: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      padding: theme.spacing(0, 1),\n    },\n    closeBtn: {\n      color: theme.palette.error.main,\n    },\n    paper: {\n      backgroundColor: theme.palette.background.paper,\n      boxShadow: theme.shadows[5],\n      borderRadius: theme.spacing(1),\n      width: '350px',\n      textAlign: 'center',\n      paddingBottom: theme.spacing(2),\n    },\n    modal: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n    },\n    buttonDiv: {\n      position: 'sticky',\n      bottom: '0',\n      backgroundColor: theme.palette.background.default,\n      zIndex: 1500,\n    },\n    hint: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    arrowIcon: {\n      marginLeft: '4px',\n      marginRight: '4px',\n      fontSize: '20px',\n    },\n    hintTextContainer: {\n      display: 'flex',\n    },\n    hintTitleText: {\n      marginRight: '.5em',\n    },\n    settingsContainer: {\n      display: 'flex',\n      justify: 'space-between',\n    },\n    settingsButton: {\n      marginTop: theme.spacing(2),\n      marginLeft: theme.spacing(10),\n      justifyContent: 'right',\n    },\n    formHelperText: {\n      marginLeft: 0,\n      marginRight: 0,\n    },\n    displayBlock: {\n      display: 'block',\n    },\n    displayNone: {\n      display: 'none',\n    },\n    vaultCollatInfo: {\n      display: 'flex',\n      alignItems: 'center',\n      pointerEvents: 'auto',\n    },\n    select: {\n      '&.MuiSelect-select:focus': {\n        backgroundColor: 'transparent',\n      },\n    },\n  }),\n)\n\nexport const collatPercentAtom = atomWithStorage('collatPercent', 0)\n\nconst RedeemShort: React.FC<SellType> = () => {\n  const [confirmedAmount, setConfirmedAmount] = useState('')\n  const [existingCollatInETH, setExistingCollatInETH] = useState(new BigNumber(0))\n  const [existingDebtInETH, setExistingDebtInETH] = useState(new BigNumber(0))\n  const [isCollatAndDebtLoading, setIsCollatAndDebtLoading] = useState(false)\n  const [isLpDetailsLoading, setIsLpDetailsLoading] = useState(false)\n\n  // Add these new LP tracking variables\n  const [lpedEth, setLpedEth] = useState(new BigNumber(0))\n  const [lpedSqueethInEth, setLpedSqueethInEth] = useState(new BigNumber(0))\n  const [lpedSqueethAmount, setLpedSqueethAmount] = useState(new BigNumber(0))\n\n  const [shortAmount, setShortAmount] = useState(new BigNumber(0))\n  const [isTxnLoading, setIsTxnLoading] = useState(false)\n\n  const classes = useStyles()\n  const {\n    cancelled,\n    confirmed,\n    loading: transactionInProgress,\n    transactionData,\n    resetTransactionData,\n    resetTxCancelled,\n  } = useTransactionStatus()\n\n  const { redeemShortPosition } = useShutdownShortHelper()\n  const connected = useAtomValue(connectedWalletAtom)\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n  const address = useAtomValue(addressAtom)\n\n  const selectWallet = useSelectWallet()\n  const getOSqthSettlementAmount = useGetOSqthSettlementAmount()\n  const getUniNFTDetails = useGetUniNFTDetails()\n  const setTradeCompleted = useUpdateAtom(tradeCompletedAtom)\n\n  const setTradeSuccess = useUpdateAtom(tradeSuccessAtom)\n\n  const { vaultId, isVaultLoading: isLoadingValidVault } = useFirstValidVault()\n  const { vault, loading: isLoadingVaultDetails, updateVault } = useVault(vaultId)\n\n  // Combine vault loading states\n  const isVaultLoading = isLoadingValidVault || isLoadingVaultDetails\n\n  const [isVaultHistoryUpdating, setVaultHistoryUpdating] = useAtom(vaultHistoryUpdatingAtom)\n  const vaultHistoryQuery = useVaultHistoryQuery(Number(vaultId), isVaultHistoryUpdating)\n  const { isRestricted, isWithdrawAllowed } = useRestrictUser()\n\n  const { track } = useAmplitude()\n\n  console.log({ address, vaultId })\n\n  useAppEffect(() => {\n    if (!isVaultLoading && vault) {\n      const contractShort = vault?.shortAmount?.isFinite() ? vault?.shortAmount : new BigNumber(0)\n      setShortAmount(contractShort)\n    }\n  }, [vault?.shortAmount, isVaultLoading])\n\n  useAppEffect(() => {\n    if (!isVaultLoading && shortAmount.isEqualTo(0)) {\n      setExistingCollatInETH(new BigNumber(0))\n      setExistingDebtInETH(new BigNumber(0))\n      setIsCollatAndDebtLoading(false)\n      return\n    }\n\n    const fetchCollatAndDebt = async () => {\n      if (!isVaultLoading && vault && !shortAmount.isEqualTo(0)) {\n        setIsCollatAndDebtLoading(true)\n        try {\n          const collateralInETH: BigNumber = vault?.collateralAmount ?? new BigNumber(0)\n          setExistingCollatInETH(collateralInETH)\n\n          const shortAmount = vault.shortAmount ?? new BigNumber(0)\n          const debt = await getOSqthSettlementAmount(shortAmount)\n          setExistingDebtInETH(debt)\n        } catch (error) {\n          console.error('Error fetching collateral and debt:', error)\n        } finally {\n          setIsCollatAndDebtLoading(false)\n        }\n      }\n    }\n\n    fetchCollatAndDebt()\n  }, [shortAmount, getOSqthSettlementAmount, vault, isVaultLoading])\n\n  // fetch LP details\n  useAppEffect(() => {\n    const getLPValues = async () => {\n      if (!isVaultLoading && vault && Number(vault?.NFTCollateralId) !== 0) {\n        setIsLpDetailsLoading(true)\n        try {\n          const { ethAmount, squeethValueInEth, squeethAmount } = await getUniNFTDetails(Number(vault?.NFTCollateralId))\n          setLpedEth(ethAmount)\n          setLpedSqueethInEth(squeethValueInEth)\n          setLpedSqueethAmount(squeethAmount)\n        } catch (err) {\n          console.error('Error getting LP values:', err)\n          setLpedEth(new BigNumber(0))\n          setLpedSqueethInEth(new BigNumber(0))\n          setLpedSqueethAmount(new BigNumber(0))\n        } finally {\n          setIsLpDetailsLoading(false)\n        }\n      } else {\n        setLpedEth(new BigNumber(0))\n        setLpedSqueethInEth(new BigNumber(0))\n        setLpedSqueethAmount(new BigNumber(0))\n        setIsLpDetailsLoading(false)\n      }\n    }\n\n    getLPValues()\n  }, [vault?.NFTCollateralId, isVaultLoading])\n\n  useAppEffect(() => {\n    if (transactionInProgress) {\n      setIsTxnLoading(false)\n    }\n  }, [transactionInProgress])\n\n  const handleRedeemShort = useAppCallback(async () => {\n    setIsTxnLoading(true)\n\n    try {\n      track(SHORT_SQUEETH_EVENTS.REDEEM_SHORT_OSQTH_CLICK)\n      await redeemShortPosition(Number(vaultId), async () => {\n        setConfirmedAmount(shortAmount.toFixed(6).toString())\n        setTradeSuccess(true)\n        setTradeCompleted(true)\n        setShortAmount(new BigNumber(0))\n\n        setVaultHistoryUpdating(true)\n        updateVault()\n        vaultHistoryQuery.refetch({ vaultId })\n\n        track(SHORT_SQUEETH_EVENTS.REDEEM_SHORT_OSQTH_SUCCESS, {\n          vaultId: Number(vaultId),\n          ethReceived: ethToReceive.toNumber(),\n        })\n      })\n    } catch (e) {\n      console.log(e)\n      setIsTxnLoading(false)\n\n      track(SHORT_SQUEETH_EVENTS.REDEEM_SHORT_OSQTH_FAILED)\n    }\n  }, [\n    shortAmount?.toString(),\n    updateVault,\n    redeemShortPosition,\n    setConfirmedAmount,\n    setTradeSuccess,\n    setTradeCompleted,\n    setShortAmount,\n    setVaultHistoryUpdating,\n    vaultHistoryQuery,\n    vaultId,\n    track,\n  ])\n\n  // Calculate final values only when data is loaded\n  const isCalculationsLoading = isVaultLoading || isCollatAndDebtLoading || isLpDetailsLoading\n\n  const totalCollateralInEth = existingCollatInETH.plus(lpedEth)\n  const remainingDebtInEth = lpedSqueethInEth.gte(existingDebtInETH)\n    ? new BigNumber(0)\n    : existingDebtInETH.minus(lpedSqueethInEth)\n  const ethToReceive = totalCollateralInEth.minus(remainingDebtInEth)\n\n  let redeemError: string | undefined\n\n  if (connected && !isVaultLoading) {\n    if (shortAmount.lte(0)) {\n      redeemError = 'No position to redeem'\n    } else if (ethToReceive.lte(0)) {\n      redeemError = `Insolvent vault. Your collateral (${formatNumber(\n        totalCollateralInEth.toNumber(),\n      )} ETH) is less than your debt (${formatNumber(\n        remainingDebtInEth.toNumber(),\n      )} ETH). You will not receive any ETH back.`\n    }\n  }\n\n  return (\n    <div id=\"redeem-short-card\">\n      {confirmed ? (\n        <div>\n          <Confirmed\n            confirmationMessage={`Redeemed ${confirmedAmount} Squeeth Short Position`}\n            txnHash={transactionData?.hash ?? ''}\n            confirmType={ConfirmType.TRADE}\n          />\n          <div className={classes.buttonDiv}>\n            <PrimaryButtonNew\n              fullWidth\n              variant=\"contained\"\n              onClick={() => {\n                resetTransactionData()\n              }}\n              className={classes.amountInput}\n              id=\"redeem-short-close-btn\"\n            >\n              {'Close'}\n            </PrimaryButtonNew>\n          </div>\n        </div>\n      ) : cancelled ? (\n        <div>\n          <Cancelled txnHash={transactionData?.hash ?? ''} />\n          <div className={classes.buttonDiv}>\n            <PrimaryButtonNew\n              fullWidth\n              variant=\"contained\"\n              onClick={() => {\n                resetTransactionData()\n                resetTxCancelled()\n              }}\n              className={classes.amountInput}\n            >\n              {'Close'}\n            </PrimaryButtonNew>\n          </div>\n        </div>\n      ) : (\n        <>\n          <Typography variant=\"h4\" className={classes.title}>\n            Redeem Short Vault\n          </Typography>\n\n          <Box display=\"flex\" flexDirection=\"column\">\n            <InputToken\n              id=\"redeem-short-osqth-input\"\n              label=\"Short oSQTH position\"\n              value={shortAmount.toString()}\n              balance={shortAmount}\n              isBalanceLoading={isVaultLoading}\n              symbol=\"oSQTH\"\n              logo={osqthLogo}\n              showMaxAction={false}\n              error={!!redeemError}\n              helperText={redeemError}\n              readOnly={true}\n              readOnlyTooltip={'Only full redemption is allowed'}\n            />\n\n            <Box\n              display=\"flex\"\n              justifyContent=\"space-between\"\n              alignItems=\"center\"\n              gridGap=\"12px\"\n              marginTop=\"24px\"\n              flexWrap=\"wrap\"\n            >\n              <Metric\n                label=\"Current collateral\"\n                value={\n                  isCollatAndDebtLoading\n                    ? 'Loading...'\n                    : formatNumber(existingCollatInETH.isPositive() ? existingCollatInETH.toNumber() : 0, 4) + ' ETH'\n                }\n                isSmall\n              />\n              <Metric\n                label=\"Current debt\"\n                value={\n                  isCollatAndDebtLoading\n                    ? 'Loading...'\n                    : formatNumber(existingDebtInETH.isPositive() ? existingDebtInETH.toNumber() : 0, 4) + ' ETH'\n                }\n                isSmall\n              />\n            </Box>\n\n            {(lpedEth.isGreaterThan(0) || lpedSqueethAmount.isGreaterThan(0)) && (\n              <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" flexWrap=\"wrap\" marginTop=\"12px\">\n                <Metric\n                  label=\"LP Position\"\n                  value={\n                    isLpDetailsLoading\n                      ? 'Loading...'\n                      : `${formatNumber(lpedEth.toNumber())} ETH + ${formatNumber(\n                          lpedSqueethAmount.toNumber(),\n                          4,\n                        )} oSQTH`\n                  }\n                  isSmall\n                />\n              </Box>\n            )}\n\n            <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" flexWrap=\"wrap\" marginTop=\"24px\">\n              <Metric\n                label=\"ETH you will receive\"\n                value={\n                  isCalculationsLoading\n                    ? 'Loading...'\n                    : formatNumber(existingCollatInETH.minus(existingDebtInETH).toNumber(), 4) + ' ETH'\n                }\n              />\n            </Box>\n\n            <Collapse in={!!redeemError}>\n              <Alert severity=\"error\" marginTop=\"24px\">\n                {redeemError}\n              </Alert>\n            </Collapse>\n\n            {isRestricted && <RestrictionInfo withdrawAllowed={isWithdrawAllowed} marginTop=\"24px\" />}\n\n            <Box marginTop=\"24px\" className={classes.buttonDiv}>\n              {isRestricted && !isWithdrawAllowed ? (\n                <PrimaryButtonNew\n                  fullWidth\n                  variant=\"contained\"\n                  onClick={selectWallet}\n                  disabled={true}\n                  id=\"redeem-short-restricted-btn\"\n                >\n                  {'Unavailable'}\n                </PrimaryButtonNew>\n              ) : !connected ? (\n                <PrimaryButtonNew\n                  fullWidth\n                  variant=\"contained\"\n                  onClick={selectWallet}\n                  className={classes.amountInput}\n                  disabled={!!isTxnLoading}\n                  id=\"redeem-short-connect-wallet-btn\"\n                >\n                  {'Connect Wallet'}\n                </PrimaryButtonNew>\n              ) : (\n                <PrimaryButtonNew\n                  fullWidth\n                  onClick={handleRedeemShort}\n                  className={classes.amountInput}\n                  disabled={\n                    !supportedNetwork ||\n                    isTxnLoading ||\n                    isVaultLoading ||\n                    isCalculationsLoading ||\n                    transactionInProgress ||\n                    !!redeemError ||\n                    (vault && vault.shortAmount.isZero())\n                  }\n                  id=\"redeem-short-submit-tx-btn\"\n                >\n                  {!supportedNetwork ? (\n                    'Unsupported Network'\n                  ) : isTxnLoading || isVaultLoading || isCalculationsLoading || transactionInProgress ? (\n                    <CircularProgress color=\"primary\" size=\"1.5rem\" />\n                  ) : (\n                    'Redeem Short Vault'\n                  )}\n                </PrimaryButtonNew>\n              )}\n            </Box>\n          </Box>\n        </>\n      )}\n    </div>\n  )\n}\n\ntype SellType = {\n  open: boolean\n}\n\nconst Short: React.FC<SellType> = ({ open }) => {\n  return <RedeemShort open={open} />\n}\n\nexport default memo(Short)\n"
  },
  {
    "path": "packages/frontend/src/components/Trade/SqueethMetrics.tsx",
    "content": "import React from 'react'\nimport { Box, BoxProps } from '@material-ui/core'\nimport { useAtomValue } from 'jotai'\n\nimport { normFactorAtom, indexForSettlementAtom } from '@state/controller/atoms'\nimport { formatCurrency, formatNumber } from '@utils/formatter'\nimport Metric, { MetricLabel } from '@components/Metric'\nimport { Tooltips } from '@constants/enums'\nimport { INDEX_SCALE } from '@constants/index'\n\nconst SqueethMetrics: React.FC<BoxProps> = (props) => {\n  const normFactor = useAtomValue(normFactorAtom)\n  const indexForSettlement = useAtomValue(indexForSettlementAtom)\n\n  return (\n    <Box display=\"flex\" alignItems=\"center\" flexWrap=\"wrap\" gridGap=\"12px\" {...props}>\n      <Metric\n        label={<MetricLabel label=\"ETH Settlement Price\" tooltipTitle={'ETH Settlement Price'} />}\n        value={formatCurrency(indexForSettlement.times(INDEX_SCALE).toNumber())}\n      />\n\n      <Metric\n        label={<MetricLabel label=\"Norm Factor\" tooltipTitle={Tooltips.NormFactor} />}\n        value={normFactor.isFinite() ? formatNumber(normFactor.toNumber(), 4) : '-'}\n      />\n    </Box>\n  )\n}\n\nexport default SqueethMetrics\n"
  },
  {
    "path": "packages/frontend/src/components/Trade/WelcomeModal.tsx",
    "content": "import { Button, createStyles, makeStyles, Typography } from '@material-ui/core'\nimport Image from 'next/image'\nimport React from 'react'\n\nimport { Modal, ModalProps } from '@components/Modal/Modal'\nimport discordIcon from 'public/images/discord.svg'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      height: '100vh',\n      display: 'flex',\n      flexDirection: 'column',\n      justifyContent: 'center',\n      alignItems: 'center',\n      gap: '10px',\n      padding: theme.spacing(4),\n    },\n    logoTitle: {\n      marginLeft: theme.spacing(1),\n      [theme.breakpoints.down('sm')]: {\n        fontSize: 18,\n      },\n    },\n    info: {\n      display: 'flex',\n      justifyContent: 'center',\n      alignItems: 'center',\n      gap: '10px',\n    },\n  }),\n)\n\nexport const WelcomeModal: React.FC<Omit<ModalProps, 'title'>> = (props) => {\n  const classes = useStyles()\n\n  return (\n    <Modal title=\"Welcome to Squeeth Testnet!\" {...props}>\n      <Typography variant=\"subtitle1\">We invite you to squeeth around! 🐱</Typography>\n      <div className={classes.info}>\n        <a href=\"https://faucet.ropsten.be/\" target=\"_blank\" rel=\"noopener noreferrer\">\n          <Button style={{ color: '#000', textTransform: 'none' }} variant=\"contained\" color=\"primary\">\n            <span>Get test ETH </span>\n          </Button>\n        </a>\n      </div>\n      <div className={classes.info}>\n        <a href=\"https://discord.gg/ztEuhjyaBF\" target=\"_blank\" rel=\"noopener noreferrer\">\n          <Button style={{ color: '#000', textTransform: 'none' }} variant=\"contained\" color=\"primary\">\n            <span>Squeeth Together</span>\n            <span style={{ display: 'flex', marginLeft: '5px' }}>\n              <Image src={discordIcon} alt=\"discord\" width={27} height={27} />\n            </span>\n          </Button>\n        </a>\n      </div>\n    </Modal>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/Trade/index.tsx",
    "content": "import React from 'react'\nimport { Box, BoxProps } from '@material-ui/core'\nimport { useAtom, useAtomValue } from 'jotai'\n\nimport { openPositionAtom, tradeTypeAtom } from '@state/trade/atoms'\nimport { TradeType } from 'src/types'\nimport Long from './Long'\nimport Short from './Short'\n\nconst Trade: React.FC<BoxProps> = (props) => {\n  const tradeType = useAtomValue(tradeTypeAtom)\n  const [openPosition, setOpenPosition] = useAtom(openPositionAtom)\n\n  return (\n    <Box id=\"trade-card\" {...props}>\n      {/* <SqueethTabsNew\n        value={openPosition}\n        onChange={(evt, val) => {\n          setOpenPosition(val)\n\n          if (!transactionInProgress || !isTxFirstStep) {\n            resetEthTradeAmount()\n            resetSqthTradeAmount()\n            resetTransactionData()\n          }\n        }}\n        aria-label=\"simple tabs example\"\n        centered\n        variant=\"fullWidth\"\n      >\n        <SqueethTabNew label=\"Open\" id=\"open-btn\" />\n        <SqueethTabNew label=\"Close\" id=\"close-btn\" />\n      </SqueethTabsNew> */}\n\n      <Box>{tradeType === TradeType.LONG ? <Long /> : <Short open={openPosition === 0} />}</Box>\n    </Box>\n  )\n}\n\nexport default Trade\n"
  },
  {
    "path": "packages/frontend/src/components/TradeOld/Cancelled.tsx",
    "content": "import { createStyles, makeStyles, Typography } from '@material-ui/core'\nimport React from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { EtherscanPrefix } from '../../constants'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    etherscan: {\n      color: theme.palette.primary.main,\n      marginTop: theme.spacing(1),\n      marginBottom: theme.spacing(3),\n    },\n    thirdHeading: {\n      marginTop: theme.spacing(3),\n      paddingLeft: theme.spacing(1),\n      paddingRight: theme.spacing(1),\n    },\n    confMsg: {\n      marginTop: theme.spacing(1),\n    },\n    squeethCat: {\n      marginTop: theme.spacing(6),\n      marginBottom: theme.spacing(6),\n    },\n    uniswapLink: {\n      marginTop: theme.spacing(6),\n      marginBottom: theme.spacing(6),\n      display: 'flex',\n      alignItems: 'center',\n    },\n    uniLP: {\n      color: '#FF007A',\n      marginLeft: theme.spacing(3),\n      // textDecoration: 'underline',\n    },\n    infoIcon: {\n      fontSize: '1rem',\n      marginLeft: theme.spacing(0.5),\n      marginTop: '2px',\n    },\n    img: {\n      borderRadius: theme.spacing(2),\n    },\n  }),\n)\n\ntype ConfirmedProps = {\n  txnHash: string\n}\n\nconst Cancelled: React.FC<ConfirmedProps> = ({ txnHash }) => {\n  const classes = useStyles()\n  const networkId = useAtomValue(networkIdAtom)\n\n  return (\n    <div>\n      <div>\n        <Typography variant=\"body1\" className={classes.confMsg}>\n          You cancelled the transaction\n        </Typography>\n        <a\n          className={classes.etherscan}\n          href={`${EtherscanPrefix[networkId]}${txnHash}`}\n          target=\"_blank\"\n          rel=\"noreferrer\"\n        >\n          View on Etherscan\n        </a>\n      </div>\n    </div>\n  )\n}\n\nexport default Cancelled\n"
  },
  {
    "path": "packages/frontend/src/components/TradeOld/Confirmed.tsx",
    "content": "import { createStyles, makeStyles, Typography } from '@material-ui/core'\nimport Image from 'next/image'\nimport React from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { EtherscanPrefix } from '../../constants'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    etherscan: {\n      color: theme.palette.primary.main,\n      marginTop: theme.spacing(1),\n      marginBottom: theme.spacing(3),\n    },\n    thirdHeading: {\n      marginTop: theme.spacing(3),\n      paddingLeft: theme.spacing(1),\n      paddingRight: theme.spacing(1),\n    },\n    confMsg: {\n      marginTop: theme.spacing(1),\n    },\n    squeethCat: {\n      marginTop: theme.spacing(6),\n      marginBottom: theme.spacing(6),\n    },\n    uniswapLink: {\n      marginTop: theme.spacing(6),\n      marginBottom: theme.spacing(6),\n      display: 'flex',\n      alignItems: 'center',\n    },\n    uniLP: {\n      color: '#FF007A',\n      marginLeft: theme.spacing(3),\n      // textDecoration: 'underline',\n    },\n    infoIcon: {\n      fontSize: '1rem',\n      marginLeft: theme.spacing(0.5),\n      marginTop: '2px',\n    },\n    img: {\n      borderRadius: theme.spacing(2),\n    },\n  }),\n)\n\nexport enum ConfirmType {\n  TRADE,\n  CRAB,\n}\n\ntype ConfirmedProps = {\n  confirmationMessage: string\n  txnHash: string\n  confirmType: ConfirmType\n}\n\nconst Confirmed: React.FC<ConfirmedProps> = ({ confirmationMessage, txnHash, confirmType }) => {\n  const classes = useStyles()\n  const networkId = useAtomValue(networkIdAtom)\n\n  return (\n    <div>\n      <div>\n        <Typography variant=\"body1\" className={classes.confMsg} id=\"conf-msg\">\n          {' '}\n          {confirmationMessage}{' '}\n        </Typography>\n        <a\n          className={classes.etherscan}\n          href={`${EtherscanPrefix[networkId]}${txnHash}`}\n          target=\"_blank\"\n          rel=\"noreferrer\"\n        >\n          {' '}\n          View on Etherscan{' '}\n        </a>\n      </div>\n      {confirmType === ConfirmType.CRAB ? (\n        <div className={classes.squeethCat}>\n          <Image\n            src=\"https://media.giphy.com/media/ukLCGEh7kXDJ5wNWT7/giphy.gif\"\n            alt=\"squeeth crab cat\"\n            width={120}\n            height={120}\n            className={classes.img}\n          />\n          <Typography variant=\"body1\" component=\"div\">\n            Stay Crabby!\n          </Typography>\n        </div>\n      ) : (\n        <div className={classes.squeethCat}>\n          <Image\n            src=\"https://media.giphy.com/media/eYU60NpFPCONDEItBa/giphy.gif\"\n            alt=\"squeeth cat\"\n            width={120}\n            height={120}\n            className={classes.img}\n          />\n          <Typography variant=\"body1\" component=\"div\">\n            Stay Squeethy!\n          </Typography>\n        </div>\n      )}\n    </div>\n  )\n}\n\nexport default Confirmed\n"
  },
  {
    "path": "packages/frontend/src/components/TradeOld/Long/BreakEven.tsx",
    "content": "import useAppMemo from '@hooks/useAppMemo'\nimport { getBreakEvenForLongSqueeth, toTokenAmount } from '@utils/calculations'\nimport { useAtomValue } from 'jotai'\nimport React from 'react'\nimport { currentImpliedFundingAtom, indexAtom, markAtom, normFactorAtom } from 'src/state/controller/atoms'\nimport TradeInfoItem from '../TradeInfoItem'\n\nconst BreakEven: React.FC = () => {\n  const mark = useAtomValue(markAtom)\n  const index = useAtomValue(indexAtom)\n  const days = 1\n  const normFactor = useAtomValue(normFactorAtom)\n  const currentFunding = useAtomValue(currentImpliedFundingAtom)\n\n  const breakEven = useAppMemo(() => {\n    const breakEvenValue = getBreakEvenForLongSqueeth(mark, index, normFactor, days)\n    const ethPrice = toTokenAmount(index, 18).sqrt()\n    return (breakEvenValue / ethPrice.toNumber() - 1) * 100\n  }, [index, mark, normFactor])\n\n  return (\n    <div>\n      <TradeInfoItem\n        label=\"ETH move to breakeven\"\n        value={breakEven.toFixed(3)}\n        tooltip={`To breakeven ETH to needs to move to ${breakEven.toFixed(3)}% in one day, since current premiums are \n        ${(currentFunding * 100).toFixed(2)}%`}\n        unit=\"%\"\n        id=\"open-long-eth-breakdown\"\n      />\n    </div>\n  )\n}\n\nexport default BreakEven\n"
  },
  {
    "path": "packages/frontend/src/components/TradeOld/Long/index.tsx",
    "content": "import { PrimaryButton } from '@components/Button'\nimport { PrimaryInput } from '@components/Input/PrimaryInput'\nimport { UniswapIframe } from '@components/Modal/UniswapIframe'\nimport { TradeSettings } from '@components/TradeSettings'\nimport { useUserAllowance } from '@hooks/contracts/useAllowance'\nimport useAppCallback from '@hooks/useAppCallback'\nimport useAppEffect from '@hooks/useAppEffect'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { useETHPrice } from '@hooks/useETHPrice'\nimport { CircularProgress, createStyles, makeStyles, Typography } from '@material-ui/core'\nimport ArrowRightAltIcon from '@material-ui/icons/ArrowRightAlt'\nimport { toTokenAmount } from '@utils/calculations'\nimport BigNumber from 'bignumber.js'\nimport { useAtom, useAtomValue } from 'jotai'\nimport { useResetAtom, useUpdateAtom } from 'jotai/utils'\nimport React, { useState } from 'react'\nimport { currentImpliedFundingAtom, dailyHistoricalFundingAtom } from 'src/state/controller/atoms'\nimport { addressesAtom, isShortAtom } from 'src/state/positions/atoms'\nimport { useComputeSwaps, useShortDebt } from 'src/state/positions/hooks'\nimport {\n  useAutoRoutedBuyAndRefund,\n  useAutoRoutedSell,\n  useAutoRoutedGetSellQuote,\n  useGetBuyQuote,\n  useGetBuyQuoteForETH,\n  useGetSellQuoteForETH,\n  useGetWSqueethPositionValue,\n} from 'src/state/squeethPool/hooks'\nimport {\n  confirmedAmountAtom,\n  ethTradeAmountAtom,\n  inputQuoteLoadingAtom,\n  quoteAtom,\n  slippageAmountAtom,\n  sqthTradeAmountAtom,\n  tradeCompletedAtom,\n  tradeSuccessAtom,\n  tradeTypeAtom,\n} from 'src/state/trade/atoms'\nimport { connectedWalletAtom, isTransactionFirstStepAtom, supportedNetworkAtom } from 'src/state/wallet/atoms'\nimport { useSelectWallet, useTransactionStatus, useWalletBalance } from 'src/state/wallet/hooks'\nimport { BIG_ZERO, Links } from '../../../constants'\nimport { TradeType } from '../../../types'\nimport Cancelled from '../Cancelled'\nimport Confirmed, { ConfirmType } from '../Confirmed'\nimport TradeInfoItem from '../TradeInfoItem'\nimport UniswapData from '../UniswapData'\nimport BreakEven from './BreakEven'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    header: {\n      color: theme.palette.primary.main,\n    },\n    body: {\n      padding: theme.spacing(2, 12),\n      margin: 'auto',\n      display: 'flex',\n      justifyContent: 'space-around',\n    },\n    subHeading: {\n      color: theme.palette.text.secondary,\n    },\n    thirdHeading: {\n      marginTop: theme.spacing(2),\n      paddingLeft: theme.spacing(1),\n      paddingRight: theme.spacing(1),\n    },\n    explainer: {\n      marginTop: theme.spacing(2),\n      paddingLeft: theme.spacing(1),\n      paddingRight: theme.spacing(1),\n      marginLeft: theme.spacing(1),\n      width: '200px',\n      justifyContent: 'left',\n    },\n    caption: {\n      marginTop: theme.spacing(1),\n      fontSize: '13px',\n    },\n    divider: {\n      margin: theme.spacing(2, 0),\n      width: '300px',\n      marginLeft: 'auto',\n      marginRight: 'auto',\n    },\n    details: {\n      marginTop: theme.spacing(4),\n      width: '65%',\n    },\n    buyCard: {\n      marginTop: theme.spacing(4),\n      marginLeft: theme.spacing(2),\n    },\n    cardTitle: {\n      color: theme.palette.primary.main,\n      marginTop: theme.spacing(4),\n    },\n    cardSubTxt: {\n      color: theme.palette.text.secondary,\n      lineHeight: '1.75rem',\n      fontSize: '16px',\n      width: '90%',\n    },\n    payoff: {\n      color: theme.palette.text.secondary,\n      lineHeight: '1.75rem',\n      fontSize: '16px',\n    },\n    cardDetail: {\n      color: theme.palette.text.secondary,\n      lineHeight: '1.75rem',\n      fontSize: '16px',\n      marginTop: theme.spacing(4),\n    },\n    amountInput: {\n      marginTop: theme.spacing(1),\n      backgroundColor: theme.palette.success.main,\n      '&:hover': {\n        backgroundColor: theme.palette.success.dark,\n      },\n    },\n    innerCard: {\n      textAlign: 'center',\n      padding: theme.spacing(2),\n      paddingBottom: theme.spacing(8),\n      background: theme.palette.background.default,\n      border: `1px solid ${theme.palette.background.stone}`,\n    },\n    expand: {\n      transform: 'rotate(270deg)',\n      color: theme.palette.primary.main,\n      transition: theme.transitions.create('transform', {\n        duration: theme.transitions.duration.shortest,\n      }),\n      marginTop: theme.spacing(6),\n    },\n    expandOpen: {\n      transform: 'rotate(180deg)',\n      color: theme.palette.primary.main,\n    },\n    dialog: {\n      padding: theme.spacing(2),\n    },\n    dialogHeader: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    dialogIcon: {\n      marginRight: theme.spacing(1),\n      color: theme.palette.warning.main,\n    },\n    txItem: {\n      marginTop: theme.spacing(1),\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n    },\n    infoIcon: {\n      marginLeft: theme.spacing(0.5),\n      color: theme.palette.text.secondary,\n    },\n    squeethExp: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      borderRadius: theme.spacing(1),\n      padding: theme.spacing(1.5),\n      width: '300px',\n      marginLeft: 'auto',\n      marginRight: 'auto',\n      marginTop: theme.spacing(2),\n      textAlign: 'left',\n      backgroundColor: theme.palette.background.stone,\n    },\n    squeethExpTxt: {\n      fontSize: '20px',\n    },\n    closePosition: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      padding: theme.spacing(0, 1),\n    },\n    closeBtn: {\n      color: theme.palette.error.main,\n    },\n    paper: {\n      backgroundColor: theme.palette.background.paper,\n      boxShadow: theme.shadows[5],\n      borderRadius: theme.spacing(1),\n      width: '350px',\n      textAlign: 'center',\n      paddingBottom: theme.spacing(2),\n    },\n    modal: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n    },\n    buttonDiv: {\n      position: 'sticky',\n      bottom: '0',\n      background: '#2A2D2E',\n      paddingBottom: theme.spacing(3),\n    },\n    hint: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    arrowIcon: {\n      marginLeft: '4px',\n      marginRight: '4px',\n      fontSize: '20px',\n    },\n    hintTextContainer: {\n      display: 'flex',\n    },\n    hintTitleText: {\n      marginRight: '.5em',\n    },\n    linkHover: {\n      '&:hover': {\n        opacity: 0.7,\n      },\n    },\n    anchor: {\n      color: '#FF007A',\n      fontSize: '16px',\n    },\n    settingsContainer: {\n      display: 'flex',\n      justify: 'space-between',\n      alignItems: 'center',\n    },\n    settingsButton: {\n      marginTop: theme.spacing(2),\n      marginLeft: theme.spacing(10),\n      justifyContent: 'right',\n      alignSelf: 'center',\n    },\n    displayBlock: {\n      display: 'block',\n    },\n    displayNone: {\n      display: 'none',\n    },\n  }),\n)\n\nconst FUNDING_MOVE_THRESHOLD = 1.3\n\nconst OpenLong: React.FC<BuyProps> = ({ activeStep = 0, open }) => {\n  const [buyLoading, setBuyLoading] = useState(false)\n  const getBuyQuoteForETH = useGetBuyQuoteForETH()\n  const getBuyQuote = useGetBuyQuote()\n  const { data } = useWalletBalance()\n  const balance = Number(toTokenAmount(data ?? BIG_ZERO, 18).toFixed(4))\n\n  const classes = useStyles()\n  const {\n    cancelled,\n    confirmed,\n    loading: transactionInProgress,\n    transactionData,\n    resetTxCancelled,\n    resetTransactionData,\n  } = useTransactionStatus()\n  // const buyAndRefund = useBuyAndRefund()\n  const buyAndRefund = useAutoRoutedBuyAndRefund()\n  const getWSqueethPositionValue = useGetWSqueethPositionValue()\n  const [confirmedAmount, setConfirmedAmount] = useAtom(confirmedAmountAtom)\n  const [inputQuoteLoading, setInputQuoteLoading] = useAtom(inputQuoteLoadingAtom)\n  const setTradeSuccess = useUpdateAtom(tradeSuccessAtom)\n  const [slippageAmount, setSlippage] = useAtom(slippageAmountAtom)\n  const ethPrice = useETHPrice()\n  const tradeType = useAtomValue(tradeTypeAtom)\n\n  const connected = useAtomValue(connectedWalletAtom)\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n  const isShort = useAtomValue(isShortAtom)\n  const selectWallet = useSelectWallet()\n  const { squeethAmount } = useComputeSwaps()\n  const dailyHistoricalFunding = useAtomValue(dailyHistoricalFundingAtom)\n  const currentImpliedFunding = useAtomValue(currentImpliedFundingAtom)\n\n  const [ethTradeAmount, setEthTradeAmount] = useAtom(ethTradeAmountAtom)\n  const [sqthTradeAmount, setSqthTradeAmount] = useAtom(sqthTradeAmountAtom)\n\n  const [squeethExposure, setSqueethExposure] = useState(0)\n  const [quote, setQuote] = useAtom(quoteAtom)\n\n  const resetEthTradeAmount = useResetAtom(ethTradeAmountAtom)\n  const resetSqthTradeAmount = useResetAtom(sqthTradeAmountAtom)\n  const setTradeCompleted = useUpdateAtom(tradeCompletedAtom)\n\n  useAppEffect(() => {\n    if (open && tradeType === TradeType.LONG) {\n      getBuyQuoteForETH(new BigNumber(ethTradeAmount), slippageAmount).then((val) => {\n        if (val) setQuote(val)\n      })\n    }\n  }, [slippageAmount, ethTradeAmount, getBuyQuoteForETH, open, setQuote, tradeType])\n\n  const handleEthChange = useAppCallback(\n    (value: string) => {\n      setEthTradeAmount(value)\n      setInputQuoteLoading(true)\n\n      getBuyQuoteForETH(new BigNumber(value), slippageAmount).then((val) => {\n        if (val) {\n          setSqthTradeAmount(val.amountOut.toString())\n          setConfirmedAmount(val.amountOut.toFixed(6).toString())\n          setSqueethExposure(Number(getWSqueethPositionValue(val.amountOut)))\n          setInputQuoteLoading(false)\n        }\n      })\n    },\n    [\n      getBuyQuoteForETH,\n      getWSqueethPositionValue,\n      slippageAmount,\n      setConfirmedAmount,\n      setEthTradeAmount,\n      setInputQuoteLoading,\n      setSqthTradeAmount,\n    ],\n  )\n\n  const handleSqthChange = useAppCallback(\n    (value: string) => {\n      setSqthTradeAmount(value)\n      setInputQuoteLoading(true)\n\n      getBuyQuote(new BigNumber(value), slippageAmount).then((val) => {\n        setEthTradeAmount(val.amountIn.toString())\n\n        setInputQuoteLoading(false)\n      })\n    },\n    [getBuyQuote, slippageAmount, setEthTradeAmount, setInputQuoteLoading, setSqthTradeAmount],\n  )\n\n  let openError: string | undefined\n  // let closeError: string | undefined\n  let existingShortError: string | undefined\n  let priceImpactWarning: string | undefined\n  let highVolError: string | undefined\n\n  if (connected) {\n    if (new BigNumber(ethTradeAmount).gt(balance)) {\n      openError = 'Insufficient ETH balance'\n    }\n    if (isShort) {\n      existingShortError = 'Close your short position to open a long'\n    }\n    if (new BigNumber(quote.priceImpact).gt(3)) {\n      priceImpactWarning = 'High Price Impact'\n    }\n\n    if (\n      currentImpliedFunding >= FUNDING_MOVE_THRESHOLD * dailyHistoricalFunding.funding &&\n      Number(ethTradeAmount) > 0\n    ) {\n      const fundingPercent = (currentImpliedFunding / dailyHistoricalFunding.funding - 1) * 100\n      highVolError = `Premiums are ${fundingPercent.toFixed(0)}% above yesterday. Consider buying later`\n    }\n  }\n\n  const longOpenPriceImpactErrorState = priceImpactWarning && !buyLoading && !openError && !isShort\n\n  useAppEffect(() => {\n    if (transactionInProgress) {\n      setBuyLoading(false)\n    }\n  }, [transactionInProgress])\n\n  const transact = useAppCallback(async () => {\n    setBuyLoading(true)\n    try {\n      await buyAndRefund(new BigNumber(ethTradeAmount), () => {\n        setTradeSuccess(true)\n        setTradeCompleted(true)\n\n        resetEthTradeAmount()\n        resetSqthTradeAmount()\n      })\n    } catch (e) {\n      console.log(e)\n      setBuyLoading(false)\n    }\n  }, [buyAndRefund, ethTradeAmount, resetEthTradeAmount, resetSqthTradeAmount, setTradeCompleted, setTradeSuccess])\n\n  return (\n    <div id=\"open-long-card\">\n      {confirmed ? (\n        <div>\n          <Confirmed\n            confirmationMessage={`Bought ${confirmedAmount} Squeeth`}\n            txnHash={transactionData?.hash ?? ''}\n            confirmType={ConfirmType.TRADE}\n          />\n          <div className={classes.buttonDiv}>\n            <PrimaryButton\n              id=\"open-long-close-btn\"\n              variant=\"contained\"\n              onClick={() => {\n                resetTransactionData()\n              }}\n              className={classes.amountInput}\n              style={{ width: '300px' }}\n            >\n              {'Close'}\n            </PrimaryButton>\n          </div>\n        </div>\n      ) : cancelled ? (\n        <div>\n          <Cancelled txnHash={transactionData?.hash ?? ''} />\n          <div className={classes.buttonDiv}>\n            <PrimaryButton\n              variant=\"contained\"\n              onClick={() => {\n                resetTransactionData()\n                resetTxCancelled()\n              }}\n              className={classes.amountInput}\n              style={{ width: '300px' }}\n            >\n              {'Close'}\n            </PrimaryButton>\n          </div>\n        </div>\n      ) : (\n        <div>\n          {activeStep === 0 ? (\n            <>\n              <div className={classes.settingsContainer}>\n                <Typography variant=\"caption\" className={classes.explainer} component=\"div\" id=\"open-long-header-box\">\n                  Pay ETH to buy squeeth ERC20\n                </Typography>\n                <span className={classes.settingsButton}>\n                  <TradeSettings setSlippage={(amt) => setSlippage(amt)} slippage={slippageAmount} />\n                </span>\n              </div>\n              <div className={classes.thirdHeading} />\n              <PrimaryInput\n                value={ethTradeAmount}\n                onChange={(v) => handleEthChange(v)}\n                label=\"Amount\"\n                tooltip=\"Amount of ETH you want to spend to get Squeeth exposure\"\n                actionTxt=\"Max\"\n                onActionClicked={() => handleEthChange(balance.toString())}\n                unit=\"ETH\"\n                convertedValue={new BigNumber(ethTradeAmount).times(ethPrice).toFixed(2).toLocaleString()}\n                error={!!existingShortError || !!priceImpactWarning || !!openError || !!highVolError}\n                isLoading={inputQuoteLoading}\n                hint={\n                  openError ? (\n                    openError\n                  ) : existingShortError ? (\n                    existingShortError\n                  ) : priceImpactWarning ? (\n                    priceImpactWarning\n                  ) : highVolError ? (\n                    highVolError\n                  ) : (\n                    <div className={classes.hint}>\n                      <span>\n                        Balance <span id=\"open-long-eth-before-trade-balance\">{balance.toFixed(4)}</span>\n                      </span>\n                      {new BigNumber(ethTradeAmount).toNumber() ? (\n                        <>\n                          <ArrowRightAltIcon className={classes.arrowIcon} />\n                          <span id=\"open-long-eth-post-trade-balance\">\n                            {new BigNumber(balance).minus(new BigNumber(ethTradeAmount)).toFixed(6)}\n                          </span>\n                        </>\n                      ) : null}{' '}\n                      <span style={{ marginLeft: '4px' }}>ETH</span>\n                    </div>\n                  )\n                }\n                id=\"open-long-eth-input\"\n              />\n              <PrimaryInput\n                value={sqthTradeAmount}\n                onChange={(v) => handleSqthChange(v)}\n                label=\"Amount\"\n                tooltip=\"Amount of Squeeth exposure\"\n                actionTxt=\"Max\"\n                unit=\"oSQTH\"\n                convertedValue={getWSqueethPositionValue(new BigNumber(sqthTradeAmount)).toFixed(2).toLocaleString()}\n                error={!!existingShortError || !!priceImpactWarning || !!openError}\n                isLoading={inputQuoteLoading}\n                hint={\n                  openError ? (\n                    openError\n                  ) : existingShortError ? (\n                    existingShortError\n                  ) : priceImpactWarning ? (\n                    priceImpactWarning\n                  ) : highVolError ? (\n                    highVolError\n                  ) : (\n                    <div className={classes.hint}>\n                      <span className={classes.hintTextContainer}>\n                        <span className={classes.hintTitleText}>Balance </span>\n                        <span id=\"open-long-osqth-before-trade-balance\">{squeethAmount.toFixed(4)}</span>\n                      </span>\n                      {quote.amountOut.gt(0) ? (\n                        <>\n                          <ArrowRightAltIcon className={classes.arrowIcon} />\n                          <span id=\"open-long-osqth-post-trade-balance\">\n                            {squeethAmount.plus(new BigNumber(sqthTradeAmount)).toFixed(6)}\n                          </span>{' '}\n                        </>\n                      ) : null}{' '}\n                      <span style={{ marginLeft: '4px' }}>oSQTH</span>\n                    </div>\n                  )\n                }\n                id=\"open-long-osqth-input\"\n              />\n\n              <div className={classes.divider}>\n                <TradeInfoItem\n                  label=\"Value if ETH up 2x\"\n                  value={Number((squeethExposure * 4).toFixed(2)).toLocaleString()}\n                  tooltip=\"The value of your position if ETH goes up 2x, not including premiums\"\n                  frontUnit=\"$\"\n                  id=\"open-short-eth-up-2x\"\n                />\n                {/* if ETH down 50%, squeeth down 75%, so multiply amount by 0.25 to get what would remain  */}\n                <TradeInfoItem\n                  label=\"Value if ETH down 50%\"\n                  value={Number((squeethExposure * 0.25).toFixed(2)).toLocaleString()}\n                  tooltip=\"The value of your position if ETH goes down 50%, not including premiums\"\n                  frontUnit=\"$\"\n                  id=\"open-short-eth-down-50%\"\n                />\n                <BreakEven />\n                <div style={{ marginTop: '10px' }}>\n                  <UniswapData\n                    slippage={isNaN(Number(slippageAmount)) ? '0' : slippageAmount.toString()}\n                    priceImpact={quote.priceImpact}\n                    minReceived={quote.minimumAmountOut.toFixed(6)}\n                    minReceivedUnit=\"oSQTH\"\n                    pools={quote.pools}\n                  />\n                </div>\n              </div>\n              <div className={classes.buttonDiv}>\n                {!connected ? (\n                  <PrimaryButton\n                    variant=\"contained\"\n                    onClick={selectWallet}\n                    className={classes.amountInput}\n                    disabled={!!buyLoading}\n                    style={{ width: '300px' }}\n                    id=\"open-long-connect-wallet-btn\"\n                  >\n                    {'Connect Wallet'}\n                  </PrimaryButton>\n                ) : (\n                  <PrimaryButton\n                    variant={longOpenPriceImpactErrorState || !!highVolError ? 'outlined' : 'contained'}\n                    onClick={transact}\n                    className={classes.amountInput}\n                    disabled={\n                      !supportedNetwork ||\n                      !!buyLoading ||\n                      transactionInProgress ||\n                      !!openError ||\n                      !!existingShortError ||\n                      sqthTradeAmount === '0'\n                    }\n                    style={\n                      longOpenPriceImpactErrorState || !!highVolError\n                        ? { width: '300px', color: '#f5475c', backgroundColor: 'transparent', borderColor: '#f5475c' }\n                        : { width: '300px' }\n                    }\n                    id=\"open-long-submit-tx-btn\"\n                  >\n                    {!supportedNetwork ? (\n                      'Unsupported Network'\n                    ) : buyLoading || transactionInProgress ? (\n                      <CircularProgress color=\"primary\" size=\"1.5rem\" />\n                    ) : longOpenPriceImpactErrorState ? (\n                      'Buy Anyway'\n                    ) : (\n                      'Buy'\n                    )}\n                  </PrimaryButton>\n                )}\n                <Typography variant=\"caption\" className={classes.caption} component=\"div\">\n                  <a href={Links.UniswapSwap} target=\"_blank\" rel=\"noreferrer\">\n                    {' '}\n                    Trades on Uniswap\n                  </a>\n\n                  <a href={Links.AutoRouter} target=\"_blank\" rel=\"noreferrer\">\n                    {' '}\n                    via Auto Router 🦄{' '}\n                  </a>\n                </Typography>\n              </div>\n            </>\n          ) : (\n            <div style={{ display: 'flex', justifyContent: 'center', margin: '20px 0' }}>\n              <UniswapIframe />\n            </div>\n          )}\n        </div>\n      )}\n    </div>\n  )\n}\n\nconst CloseLong: React.FC<BuyProps> = () => {\n  const [sellLoading, setSellLoading] = useState(false)\n  const [hasJustApprovedSqueeth, setHasJustApprovedSqueeth] = useState(false)\n\n  const classes = useStyles()\n  const {\n    cancelled,\n    confirmed,\n    loading: transactionInProgress,\n    transactionData,\n    resetTxCancelled,\n    resetTransactionData,\n  } = useTransactionStatus()\n  const { swapRouter2, oSqueeth } = useAtomValue(addressesAtom)\n  const sell = useAutoRoutedSell()\n  const getWSqueethPositionValue = useGetWSqueethPositionValue()\n  const getSellQuoteForETH = useGetSellQuoteForETH()\n  const getSellQuote = useAutoRoutedGetSellQuote()\n  const { data } = useWalletBalance()\n  const balance = Number(toTokenAmount(data ?? BIG_ZERO, 18).toFixed(4))\n\n  const [confirmedAmount, setConfirmedAmount] = useAtom(confirmedAmountAtom)\n  const [inputQuoteLoading, setInputQuoteLoading] = useAtom(inputQuoteLoadingAtom)\n  const [quote, setQuote] = useAtom(quoteAtom)\n  const [ethTradeAmount, setEthTradeAmount] = useAtom(ethTradeAmountAtom)\n  const [sqthTradeAmount, setSqthTradeAmount] = useAtom(sqthTradeAmountAtom)\n  const setTradeSuccess = useUpdateAtom(tradeSuccessAtom)\n  const setTradeCompleted = useUpdateAtom(tradeCompletedAtom)\n  const [slippageAmount, setSlippage] = useAtom(slippageAmountAtom)\n  const ethPrice = useETHPrice()\n  const amount = useAppMemo(() => new BigNumber(sqthTradeAmount), [sqthTradeAmount])\n  const altTradeAmount = new BigNumber(ethTradeAmount)\n  const { allowance: squeethAllowance, approve: squeethApprove } = useUserAllowance(oSqueeth, swapRouter2)\n  const [isTxFirstStep, setIsTxFirstStep] = useAtom(isTransactionFirstStepAtom)\n\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n  const connected = useAtomValue(connectedWalletAtom)\n  const selectWallet = useSelectWallet()\n  const { squeethAmount } = useComputeSwaps()\n\n  const shortDebt = useShortDebt()\n  const isShort = shortDebt.gt(0)\n\n  const resetEthTradeAmount = useResetAtom(ethTradeAmountAtom)\n  const resetSqthTradeAmount = useResetAtom(sqthTradeAmountAtom)\n\n  useAppEffect(() => {\n    //if it's insufficient amount them set it to it's maximum\n    if (squeethAmount.lt(amount)) {\n      setSqthTradeAmount(squeethAmount.toString())\n      getSellQuote(squeethAmount).then((val) => {\n        if (val) {\n          setEthTradeAmount(val.amountOut.toString())\n          setConfirmedAmount(squeethAmount.toFixed(6))\n        }\n      })\n    }\n  }, [squeethAmount, amount, getSellQuote, setConfirmedAmount, setEthTradeAmount, setSqthTradeAmount])\n\n  // let openError: string | undefined\n  let closeError: string | undefined\n  let existingShortError: string | undefined\n  let priceImpactWarning: string | undefined\n\n  if (connected) {\n    if (squeethAmount.lt(amount)) {\n      closeError = 'Insufficient oSQTH balance'\n    }\n    // if (amount.gt(balance)) {\n    //   openError = 'Insufficient ETH balance'\n    // }\n    if (isShort) {\n      existingShortError = 'Close your short position to open a long'\n    }\n    if (new BigNumber(quote.priceImpact).gt(3)) {\n      priceImpactWarning = 'High Price Impact'\n    }\n  }\n\n  const longClosePriceImpactErrorState =\n    priceImpactWarning && !closeError && !sellLoading && !squeethAmount.isZero() && !isShort\n\n  const sellAndClose = useAppCallback(async () => {\n    setSellLoading(true)\n    try {\n      if (squeethAllowance.lt(amount) && !hasJustApprovedSqueeth) {\n        setIsTxFirstStep(true)\n        await squeethApprove(() => {\n          setHasJustApprovedSqueeth(true)\n          setSellLoading(false)\n        })\n      } else {\n        await sell(amount, () => {\n          setIsTxFirstStep(false)\n          setTradeSuccess(true)\n          setTradeCompleted(true)\n\n          resetEthTradeAmount()\n          resetSqthTradeAmount()\n        })\n      }\n    } catch (e) {\n      console.log(e)\n      setSellLoading(false)\n    }\n  }, [\n    amount,\n    hasJustApprovedSqueeth,\n    resetEthTradeAmount,\n    resetSqthTradeAmount,\n    sell,\n    setIsTxFirstStep,\n    setTradeCompleted,\n    setTradeSuccess,\n    squeethAllowance,\n    squeethApprove,\n  ])\n\n  useAppEffect(() => {\n    if (transactionInProgress) {\n      setSellLoading(false)\n    }\n  }, [transactionInProgress])\n\n  useAppEffect(() => {\n    getSellQuote(new BigNumber(sqthTradeAmount), slippageAmount).then((val) => {\n      if (val) {\n        setQuote(val)\n      }\n    })\n  }, [slippageAmount, sqthTradeAmount, getSellQuote, setQuote])\n\n  const handleSqthChange = useAppCallback(\n    (value: string) => {\n      setInputQuoteLoading(true)\n      setSqthTradeAmount(value)\n      getSellQuote(new BigNumber(value), slippageAmount).then((val) => {\n        if (val) {\n          if (value !== '0') setConfirmedAmount(Number(value).toFixed(6))\n          setEthTradeAmount(val.amountOut.toString())\n          setInputQuoteLoading(false)\n        }\n      })\n    },\n    [getSellQuote, slippageAmount, setConfirmedAmount, setEthTradeAmount, setInputQuoteLoading, setSqthTradeAmount],\n  )\n\n  const handleEthChange = useAppCallback(\n    (value: string) => {\n      setInputQuoteLoading(true)\n      setEthTradeAmount(value)\n      getSellQuoteForETH(new BigNumber(value), slippageAmount).then((val) => {\n        if (value !== '0') setConfirmedAmount(val.amountIn.toFixed(6).toString())\n        setSqthTradeAmount(val.amountIn.toString())\n        setInputQuoteLoading(false)\n      })\n    },\n    [\n      getSellQuoteForETH,\n      slippageAmount,\n      setConfirmedAmount,\n      setEthTradeAmount,\n      setInputQuoteLoading,\n      setSqthTradeAmount,\n    ],\n  )\n\n  return (\n    <div id=\"close-long-card\">\n      {confirmed && !isTxFirstStep ? (\n        <div>\n          <Confirmed\n            confirmationMessage={`Sold ${confirmedAmount} Squeeth`}\n            txnHash={transactionData?.hash ?? ''}\n            confirmType={ConfirmType.TRADE}\n          />\n          <div className={classes.buttonDiv}>\n            <PrimaryButton\n              id=\"close-long-close-btn\"\n              variant=\"contained\"\n              onClick={() => {\n                resetTransactionData()\n              }}\n              className={classes.amountInput}\n              style={{ width: '300px' }}\n            >\n              {'Close'}\n            </PrimaryButton>\n          </div>\n        </div>\n      ) : cancelled ? (\n        <div>\n          <Cancelled txnHash={transactionData?.hash ?? ''} />\n          <div className={classes.buttonDiv}>\n            <PrimaryButton\n              variant=\"contained\"\n              onClick={() => {\n                resetTransactionData()\n                resetTxCancelled()\n              }}\n              className={classes.amountInput}\n              style={{ width: '300px' }}\n            >\n              {'Close'}\n            </PrimaryButton>\n          </div>\n        </div>\n      ) : (\n        <div>\n          <div className={classes.settingsContainer} id=\"close-long-header-box\">\n            <Typography variant=\"caption\" className={classes.explainer} component=\"div\">\n              Sell squeeth ERC20 to get ETH\n            </Typography>\n            <span className={classes.settingsButton}>\n              <TradeSettings setSlippage={(amt) => setSlippage(amt)} slippage={slippageAmount} />\n            </span>\n          </div>\n\n          <div className={classes.thirdHeading} />\n          <PrimaryInput\n            value={sqthTradeAmount}\n            onChange={(v) => handleSqthChange(v)}\n            label=\"Amount\"\n            tooltip=\"Amount of oSqueeth you want to close\"\n            actionTxt=\"Max\"\n            onActionClicked={() => handleSqthChange(squeethAmount.toString())}\n            unit=\"oSQTH\"\n            convertedValue={getWSqueethPositionValue(amount).toFixed(2).toLocaleString()}\n            error={!!existingShortError || !!priceImpactWarning || !!closeError}\n            isLoading={inputQuoteLoading}\n            hint={\n              existingShortError ? (\n                existingShortError\n              ) : closeError ? (\n                closeError\n              ) : priceImpactWarning ? (\n                priceImpactWarning\n              ) : (\n                <div className={classes.hint}>\n                  <span className={classes.hintTextContainer}>\n                    <span className={classes.hintTitleText}>Position</span>{' '}\n                    <span id=\"close-long-osqth-before-trade-balance\">{squeethAmount.toFixed(6)}</span>{' '}\n                  </span>\n                  {quote.amountOut.gt(0) ? (\n                    <>\n                      <ArrowRightAltIcon className={classes.arrowIcon} />\n                      <span id=\"close-long-osqth-post-trade-balance\">{squeethAmount.minus(amount).toFixed(6)}</span>\n                    </>\n                  ) : null}{' '}\n                  <span style={{ marginLeft: '4px' }}>oSQTH</span>\n                </div>\n              )\n            }\n            id=\"close-long-osqth-input\"\n          />\n          <PrimaryInput\n            value={ethTradeAmount}\n            onChange={(v) => handleEthChange(v)}\n            label=\"Amount\"\n            tooltip=\"Amount of oSqueeth you want to close in eth\"\n            unit=\"ETH\"\n            convertedValue={altTradeAmount.times(ethPrice).toFixed(2).toLocaleString()}\n            error={!!existingShortError || !!priceImpactWarning || !!closeError}\n            isLoading={inputQuoteLoading}\n            hint={\n              existingShortError ? (\n                existingShortError\n              ) : closeError ? (\n                closeError\n              ) : priceImpactWarning ? (\n                priceImpactWarning\n              ) : (\n                <div className={classes.hint}>\n                  <span>\n                    Balance <span id=\"close-long-eth-before-trade-balance\">{balance}</span>{' '}\n                  </span>{' '}\n                  {amount.toNumber() ? (\n                    <>\n                      <ArrowRightAltIcon className={classes.arrowIcon} />\n                      <span id=\"close-long-eth-post-trade-balance\">\n                        {new BigNumber(balance).plus(altTradeAmount).toFixed(4)}\n                      </span>\n                    </>\n                  ) : null}{' '}\n                  <span style={{ marginLeft: '4px' }}>ETH</span>\n                </div>\n              )\n            }\n            id=\"close-long-eth-input\"\n          />\n          <div className={classes.divider}>\n            <UniswapData\n              slippage={isNaN(Number(slippageAmount)) ? '0' : slippageAmount.toString()}\n              priceImpact={quote.priceImpact}\n              minReceived={quote.minimumAmountOut.toFixed(4)}\n              minReceivedUnit=\"ETH\"\n              pools={quote.pools}\n            />\n          </div>\n          <div className={classes.buttonDiv}>\n            {!connected ? (\n              <PrimaryButton\n                variant=\"contained\"\n                onClick={selectWallet}\n                className={classes.amountInput}\n                disabled={!!sellLoading}\n                style={{ width: '300px' }}\n                id=\"close-long-connect-wallet-btn\"\n              >\n                {'Connect Wallet'}\n              </PrimaryButton>\n            ) : (\n              <PrimaryButton\n                variant={longClosePriceImpactErrorState ? 'outlined' : 'contained'}\n                onClick={sellAndClose}\n                className={classes.amountInput}\n                disabled={\n                  !supportedNetwork ||\n                  !!sellLoading ||\n                  transactionInProgress ||\n                  !!closeError ||\n                  !!existingShortError ||\n                  squeethAmount.isZero() ||\n                  sqthTradeAmount === '0'\n                }\n                style={\n                  longClosePriceImpactErrorState\n                    ? { width: '300px', color: '#f5475c', backgroundColor: 'transparent', borderColor: '#f5475c' }\n                    : { width: '300px' }\n                }\n                id=\"close-long-submit-tx-btn\"\n              >\n                {!supportedNetwork ? (\n                  'Unsupported Network'\n                ) : sellLoading || transactionInProgress ? (\n                  <CircularProgress color=\"primary\" size=\"1.5rem\" />\n                ) : squeethAllowance.lt(amount) && !hasJustApprovedSqueeth ? (\n                  'Approve oSQTH (1/2)'\n                ) : longClosePriceImpactErrorState ? (\n                  'Sell Anyway'\n                ) : hasJustApprovedSqueeth ? (\n                  'Sell to close (2/2)'\n                ) : (\n                  'Sell to close'\n                )}\n              </PrimaryButton>\n            )}\n            <Typography variant=\"caption\" className={classes.caption} component=\"div\">\n              <a href={Links.UniswapSwap} target=\"_blank\" rel=\"noreferrer\">\n                {' '}\n                Trades on Uniswap\n              </a>\n\n              <a href={Links.AutoRouter} target=\"_blank\" rel=\"noreferrer\">\n                {' '}\n                via Auto Router 🦄{' '}\n              </a>\n            </Typography>\n          </div>\n        </div>\n      )}\n    </div>\n  )\n}\n\ntype BuyProps = {\n  open?: boolean\n  isLPage?: boolean\n  activeStep?: number\n}\n\nconst Long: React.FC<BuyProps> = ({ open, isLPage = false, activeStep = 0 }) => {\n  return open ? (\n    <OpenLong open={open} isLPage={isLPage} activeStep={activeStep} />\n  ) : (\n    <CloseLong isLPage={isLPage} activeStep={activeStep} />\n  )\n}\n\nexport default Long\n"
  },
  {
    "path": "packages/frontend/src/components/TradeOld/TradeDetails.tsx",
    "content": "import { createStyles, makeStyles, Typography } from '@material-ui/core'\nimport React, { ReactNode } from 'react'\nimport clsx from 'clsx'\n\ntype TradeDetailsType = {\n  actionTitle: string\n  amount: string\n  unit: string\n  value: string\n  id?: string\n  hint: ReactNode\n}\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      borderRadius: theme.spacing(1),\n      padding: theme.spacing(1.5),\n      width: '300px',\n      marginLeft: 'auto',\n      marginRight: 'auto',\n      marginTop: theme.spacing(2),\n      backgroundColor: theme.palette.background.stone,\n      textAlign: 'left',\n    },\n    squeethExp: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      textAlign: 'left',\n    },\n    squeethExpTxt: {\n      fontSize: '20px',\n    },\n  }),\n)\n\nconst TradeDetails: React.FC<TradeDetailsType> = ({ actionTitle, amount, id, unit, value, hint }) => {\n  const classes = useStyles()\n\n  return (\n    <div className={classes.container} id={id}>\n      <div className={classes.squeethExp}>\n        <div>\n          <Typography variant=\"caption\">{actionTitle}</Typography>\n          <Typography className={classes.squeethExpTxt}>{amount}</Typography>\n        </div>\n        <div>\n          <Typography variant=\"caption\">${value}</Typography>\n          <Typography className={clsx(classes.squeethExpTxt, 'trade-details-amount')}>{amount}</Typography>\n        </div>\n      </div>\n      <Typography variant=\"caption\" color=\"textSecondary\">\n        {hint}\n      </Typography>\n    </div>\n  )\n}\n\nexport default TradeDetails\n"
  },
  {
    "path": "packages/frontend/src/components/TradeOld/TradeInfoItem.tsx",
    "content": "import { Tooltip, useTheme } from '@material-ui/core'\nimport { createStyles, makeStyles } from '@material-ui/core/styles'\nimport Typography from '@material-ui/core/Typography'\nimport AccessTimeIcon from '@material-ui/icons/AccessTime'\nimport FiberManualRecordIcon from '@material-ui/icons/FiberManualRecord'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport React, { useMemo } from 'react'\nimport clsx from 'clsx'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    txItem: {\n      display: 'flex',\n      // marginTop: theme.spacing(1),\n      justifyContent: 'space-between',\n      alignItems: 'center',\n      width: '100%',\n      marginRight: 'auto',\n      marginLeft: 'auto',\n    },\n    txLabel: {\n      fontSize: '.9rem',\n      color: theme.palette.text.secondary,\n      display: 'flex',\n      alignItems: 'center',\n    },\n    txUnit: {\n      fontSize: '12px',\n      color: theme.palette.text.secondary,\n      marginLeft: theme.spacing(1),\n    },\n    txLabelDiv: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    infoIcon: {\n      fontSize: '1rem',\n      marginLeft: theme.spacing(0.5),\n      marginTop: '2px',\n    },\n    red: {\n      color: theme.palette.error.main,\n    },\n    green: {\n      color: theme.palette.success.main,\n    },\n    primary: {\n      color: theme.palette.primary.main,\n    },\n  }),\n)\n\ntype tradeType = {\n  value?: string | number\n  unit?: string\n  frontUnit?: string\n  label: string\n  id?: string\n  tooltip?: React.ReactNode\n  color?: 'primary' | 'red' | 'green' | string\n  priceType?: string\n}\n\nconst TradeInfoItem: React.FC<tradeType> = ({ value, unit, id, frontUnit, label, tooltip, color, priceType }) => {\n  const classes = useStyles()\n  const theme = useTheme()\n\n  const colorCode = useMemo(() => {\n    if (color === 'primary') return theme.palette.primary.main\n    if (color === 'green') return theme.palette.success.main\n    if (color === 'red') return theme.palette.error.main\n    return color\n  }, [color, theme.palette.error.main, theme.palette.primary.main, theme.palette.success.main])\n\n  return (\n    <div className={classes.txItem} id={id}>\n      <Typography variant=\"body1\" className={classes.txLabel}>\n        {label}\n        {tooltip ? (\n          <Tooltip title={tooltip}>\n            {priceType === 'twap' ? (\n              <AccessTimeIcon className={classes.infoIcon} />\n            ) : priceType === 'spot' ? (\n              <FiberManualRecordIcon className={classes.infoIcon} />\n            ) : (\n              <InfoIcon className={classes.infoIcon} />\n            )}\n          </Tooltip>\n        ) : null}\n      </Typography>\n      <div>\n        <Typography component=\"span\" variant=\"caption\" className={classes.txUnit}>\n          {frontUnit}\n        </Typography>\n        <Typography\n          component=\"span\"\n          style={{ marginLeft: '8px', fontSize: '.9rem', color: colorCode }}\n          className={'trade-info-item-value'}\n        >\n          {value}\n        </Typography>\n        <Typography component=\"span\" variant=\"caption\" className={classes.txUnit}>\n          {unit}\n        </Typography>\n      </div>\n    </div>\n  )\n}\n\nexport default TradeInfoItem\n"
  },
  {
    "path": "packages/frontend/src/components/TradeOld/UniswapData.tsx",
    "content": "import {\n  Accordion,\n  AccordionDetails,\n  AccordionSummary,\n  createStyles,\n  makeStyles,\n  Typography,\n  useTheme,\n} from '@material-ui/core'\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore'\nimport React, { useMemo } from 'react'\n\nimport TradeInfoItem from './TradeInfoItem'\n\ntype UniswapDataType = {\n  slippage: string\n  priceImpact: string\n  minReceived: string\n  minReceivedUnit: string\n  isMaxSent?: boolean\n  pools?: Array<any>\n}\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    pi: {\n      marginLeft: theme.spacing(2),\n    },\n    container: {\n      border: `1px solid ${theme.palette.background.stone}`,\n      borderRadius: theme.spacing(1),\n    },\n    accordionRoot: {\n      backgroundColor: 'transparent',\n      borderRadius: theme.spacing(4),\n      boxShadow: 'none',\n      padding: theme.spacing(0),\n    },\n    accordionExpanded: {\n      minHeight: '0px',\n    },\n    detailsRoot: {\n      padding: theme.spacing(0, 2, 2, 2),\n    },\n  }),\n)\n\nconst UniswapData: React.FC<UniswapDataType> = ({\n  slippage,\n  priceImpact,\n  minReceived,\n  minReceivedUnit,\n  isMaxSent,\n  pools,\n}) => {\n  const classes = useStyles()\n  const theme = useTheme()\n  const [expanded, setExpanded] = React.useState(false)\n\n  const priceImpactColor = useMemo(() => {\n    const priceImpactNum = Number(priceImpact)\n    if (priceImpactNum > 2) return theme.palette.error.main\n    if (priceImpactNum < 1) return theme.palette.success.main\n    return theme.palette.warning.main\n  }, [priceImpact, theme.palette.error.main, theme.palette.success.main, theme.palette.warning.main])\n\n  const poolData = useMemo(\n    () =>\n      pools && pools?.length > 1\n        ? pools.map((poolInfo, index) => (\n            <TradeInfoItem\n              label={poolInfo[2] + '% in ' + poolInfo[0] + ' Pool ' + (index + 1)}\n              value={poolInfo[1] / 10000}\n              unit=\"%\"\n              tooltip=\"Pool selected by Uniswap Auto Router by optimizing swap price via split routes, multiple hops, and gas\"\n            />\n          ))\n        : pools\n        ? pools.map((poolInfo, index) => (\n            <TradeInfoItem\n              label={'LP Fee (' + poolInfo[0] + ')'}\n              value={poolInfo[1] / 10000}\n              unit=\"%\"\n              tooltip=\"Pool selected by Uniswap Auto Router by optimizing swap price via split routes, multiple hops, and gas\"\n            />\n          ))\n        : null,\n    [pools],\n  )\n\n  return (\n    <div className={classes.container}>\n      <Accordion\n        classes={{ root: classes.accordionRoot, expanded: classes.accordionExpanded }}\n        square={false}\n        onChange={(_, e) => setExpanded(e)}\n        expanded={expanded}\n      >\n        <AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls=\"panel1a-content\" id=\"panel1a-header\">\n          <div>\n            {expanded ? (\n              <Typography variant=\"caption\">Uniswap transaction details</Typography>\n            ) : (\n              <>\n                <Typography variant=\"caption\" color=\"textSecondary\">\n                  Slippage:{' '}\n                </Typography>\n                <Typography variant=\"caption\">{slippage}%</Typography>\n                <Typography variant=\"caption\" color=\"textSecondary\" className={classes.pi}>\n                  Price impact:{' '}\n                </Typography>\n                <Typography variant=\"caption\" style={{ color: priceImpactColor, fontWeight: 600 }}>\n                  {priceImpact}%\n                </Typography>\n              </>\n            )}\n          </div>\n        </AccordionSummary>\n        <AccordionDetails classes={{ root: classes.detailsRoot }}>\n          <div style={{ width: '100%' }}>\n            <TradeInfoItem label=\"Allowed Slippage\" value={slippage} unit=\"%\" />\n            <TradeInfoItem label=\"Price Impact\" value={priceImpact} unit=\"%\" color={priceImpactColor} />\n            <TradeInfoItem\n              label={isMaxSent ? 'Maxmium sent' : 'Min received'}\n              value={minReceived}\n              unit={minReceivedUnit}\n            />\n            {poolData}\n          </div>\n        </AccordionDetails>\n      </Accordion>\n    </div>\n  )\n}\n\nexport default UniswapData\n"
  },
  {
    "path": "packages/frontend/src/components/TradeSettings.tsx",
    "content": "import { createStyles, IconButton, InputAdornment, makeStyles, TextField, Typography } from '@material-ui/core'\nimport Dialog from '@material-ui/core/Dialog'\nimport DialogContent from '@material-ui/core/DialogContent'\nimport DialogTitle from '@material-ui/core/DialogTitle'\nimport SettingsIcon from '@material-ui/icons/Settings'\nimport BigNumber from 'bignumber.js'\nimport * as React from 'react'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    dialogTitle: {\n      // color: '#000',\n      background: theme.palette.background.default,\n      paddingTop: '0px',\n      paddingBottom: '0px',\n      '&>*': {\n        display: 'flex',\n        justifyContent: 'space-between',\n        alignItems: 'center',\n      },\n    },\n    dialogContent: {\n      padding: '0 20px',\n      background: theme.palette.background.default,\n    },\n    uniswapHeaderDiv: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      paddingRight: '20px',\n      paddingLeft: '5px',\n    },\n    uniOpenBtn: {\n      display: 'flex',\n      alignItems: 'center',\n      color: theme.palette.primary.main,\n    },\n    settingsButton: {\n      color: theme.palette.text.secondary,\n    },\n    slippageInput: {\n      width: 300,\n      marginBottom: theme.spacing(4),\n    },\n  }),\n)\n\ntype TradeSettingsProps = {\n  setSlippage: (amt: BigNumber) => void\n  slippage: BigNumber\n}\n\nexport const TradeSettings: React.FC<TradeSettingsProps> = ({ setSlippage, slippage }) => {\n  const classes = useStyles()\n\n  const [slippageAmount, setSlippageAmount] = React.useState(slippage.toString())\n\n  const [open, setOpen] = React.useState(false)\n\n  const handleOpen = () => {\n    setOpen(true)\n  }\n\n  const handleClose = () => {\n    setOpen(false)\n    setSlippage(new BigNumber(slippageAmount))\n  }\n\n  return (\n    <div>\n      <IconButton onClick={handleOpen} className={classes.settingsButton} size={'small'}>\n        <SettingsIcon />\n      </IconButton>\n\n      <Dialog\n        PaperProps={{\n          style: { borderRadius: 20 },\n        }}\n        BackdropProps={{\n          style: { backdropFilter: 'blur(5px)' },\n        }}\n        maxWidth={'lg'}\n        open={open}\n        onClose={handleClose}\n        aria-labelledby=\"alert-dialog-title\"\n        aria-describedby=\"alert-dialog-description\"\n        disableScrollLock\n      >\n        <DialogTitle className={classes.dialogTitle} id=\"alert-dialog-title\">\n          <p>Slippage Tolerance</p>\n        </DialogTitle>\n        <DialogContent className={classes.dialogContent}>\n          <TextField\n            size=\"small\"\n            value={slippageAmount}\n            type=\"number\"\n            className={classes.slippageInput}\n            margin=\"dense\"\n            onChange={(event) => setSlippageAmount(event.target.value)}\n            id=\"filled-basic\"\n            label=\"Slippage Tolerance\"\n            variant=\"outlined\"\n            error={Number(slippageAmount) < 0.05 || Number(slippageAmount) > 1}\n            helperText={\n              Number(slippageAmount) < 0.05\n                ? 'Your transaction may fail'\n                : Number(slippageAmount) > 1\n                ? 'Your transaction may be frontrun'\n                : null\n            }\n            InputProps={{\n              endAdornment: (\n                <InputAdornment position=\"end\">\n                  <Typography variant=\"caption\">%</Typography>\n                </InputAdornment>\n              ),\n            }}\n            inputProps={{\n              min: '0',\n            }}\n          />\n        </DialogContent>\n      </Dialog>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/components/WalletFailModal.tsx",
    "content": "import { Box, Link } from '@material-ui/core'\nimport { useAtom } from 'jotai'\nimport { walletFailVisibleAtom } from 'src/state/wallet/atoms'\nimport { Modal } from './Modal/Modal'\n\nexport default function WalletFailModal() {\n  const [visible, setVisible] = useAtom(walletFailVisibleAtom)\n\n  return (\n    <Modal title=\"Wallet connect failed\" open={visible} handleClose={() => setVisible(false)}>\n      <Box px=\"10px\">\n        Unable to connect wallet for failure to comply with the{' '}\n        <Link href=\"https://squeeth.opyn.co/terms-of-service\" target=\"_blank\">\n          Terms of Service\n        </Link>\n        .\n        <br />\n        For more information see the{' '}\n        <Link href=\"https://opyn.gitbook.io/squeeth/resources/squeeth-faq\" target=\"_blank\">\n          Updated Terms FAQ\n        </Link>\n        .\n      </Box>\n    </Modal>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/constants/address.ts",
    "content": "import { Networks } from '../types'\n\ntype Address = { [key in Networks]: string }\n\nexport const CONTROLLER: Address = {\n  1: '0x64187ae08781B09368e6253F9E94951243A493D5',\n  3: '0x59F0c781a6eC387F09C40FAA22b7477a2950d209',\n  5: '0x6fc3f76f8a2d256cc091bd58bab8c2bc3f51d508',\n  11155111: '0xEd11C64CBcCc1e7744143Ff7453e8980B7f37Fd1',\n  421611: '0x6FBbc7eBd7E421839915e8e4fAcC9947dC32F4dE',\n  31337: '0xa513E6E4b8f2a923D98304ec87F64353C4D5C853',\n}\n\n//ShortPowerPerp\nexport const VAULT_MANAGER: Address = {\n  1: '0xa653e22A963ff0026292Cc8B67941c0ba7863a38',\n  3: '0x49721ED2d693F3653BC1216b8E330fA53CFC80eD',\n  5: '0xe85595e810b77cf606d0afd7eb575bb025323bee',\n  11155111: '0x25aCc7A1E3095F7D6533e95FA7Dc52F7A53dA070',\n  421611: '0x40FA4273a739667D7dBf1C46755C27338eAa0728',\n  31337: '0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6',\n}\n\n//WPowerPerp\nexport const OSQUEETH: Address = {\n  1: '0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B',\n  3: '0xa4222f78d23593e82Aa74742d25D06720DCa4ab7',\n  5: '0x9421c968d28dd789363fbd8c9aa5cf2090f0a656',\n  11155111: '0xBb8d3Eb6A7fcFC17DDfB2bFb192156f2CD57dA4B',\n  421611: '0xEC0db8766bc003C14861af996e411beA6Bf800aB',\n  31337: '0x8A791620dd6260079BF849Dc5567aDC3F2FdC318',\n}\n\nexport const WETH: Address = {\n  1: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',\n  3: '0xc778417e063141139fce010982780140aa0cd5ab',\n  5: '0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103',\n  11155111: '0x05ff8ADe428a6d40C3EB96035F5dC2b974f8Ec98',\n  421611: '0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681',\n  31337: '0x5FbDB2315678afecb367f032d93F642f64180aa3',\n}\n\nexport const USDC: Address = {\n  1: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',\n  3: '0x27415c30d8c87437becbd4f98474f26e712047f4',\n  5: '0x306bf03b689f7d7e5e9D3aAC87a068F16AFF9482',\n  11155111: '0x3c5E427E0EEc0018CD30754bd9f1cDBF084cC070',\n  421611: '0xc4D15025D49a88D70B023870d810f4cAa5c18a63',\n  31337: '0x8dF057949E6717B6f28962f30e8415b148241e16',\n}\n\nexport const UNI_V3_FACTORY: Address = {\n  1: '0x1F98431c8aD98523631AE4a59f267346ea31F984',\n  3: '0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc',\n  5: '0x55c0cef3cc64f511c34b18c720bcf38fec6c6ffa',\n  11155111: '0xC2e1DCdE268f155a1e1B27474C128f7B24B54050',\n  421611: '0x1F98431c8aD98523631AE4a59f267346ea31F984',\n  31337: '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512',\n}\n\nexport const SWAP_ROUTER: Address = {\n  1: '0xE592427A0AEce92De3Edee1F18E0157C05861564',\n  3: '0x528a19A3e88861E7298C86fE5490B8Ec007a4204',\n  5: '0x833a158da5cebc44901211427e9df936023ec0d3',\n  11155111: '0x0BD708d7619aa1B68A1c3615f3104AE9214B767f',\n  421611: '0xE592427A0AEce92De3Edee1F18E0157C05861564',\n  31337: '0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9',\n}\n\n// check this one!\nexport const SWAP_ROUTER_02: Address = {\n  1: '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45',\n  3: '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45',\n  5: '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45',\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n\nexport const SQUEETH_UNI_POOL: Address = {\n  1: '0x82c427AdFDf2d245Ec51D8046b41c4ee87F0d29C',\n  3: '0x921c384F79de1BAe96d6f33E3E5b8d0B2B34cb68',\n  5: '0xc3c29372b5138d48993f0699a129b9eadf5191bf',\n  11155111: '0x79a3403957F1bc6BeCEF145acEBA065d4beE3DaC',\n  421611: '0x0567A9C01990a4C7EE096F077A05CeEbA87db07f',\n  31337: '0x8dF057949E6717B6f28962f30e8415b148241e16',\n}\n\nexport const QUOTER: Address = {\n  1: '0xC8d3a4e6BB4952E3658CCA5081c358e6935Efa43',\n  3: '0x267aEB76BEb6DC7Ab0D88FeEaC8A948e237e2d69',\n  5: '0x759442726c06f7938cd2cb63ac9ae373dc1decf6',\n  11155111: '0xDEB8979D94268FcBA2059d6a5f2bF23f37b11607',\n  421611: '0x8f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D',\n  31337: '0x5FC8d32690cc91D4c39d9d3abcBD16989F875707',\n}\n\nexport const SHORT_HELPER: Address = {\n  1: '0x3b4095D5ff0e629972CAAa50bd3004B09a1632C5',\n  3: '0x8903918DFE74476E90B63061E5b9c3E63b65d3F4',\n  5: '0xE3606363ABE8fdE4A7f1A2058361976A4590e1e9',\n  11155111: '0x13A196A60Ccf53eaC175bd191b4E0fEE7D45ff60',\n  421611: '0x5A30a1E3873A2B5Fc9DB9b2b52491C4b6086FAe0',\n  31337: '0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE',\n}\n\nexport const ORACLE: Address = {\n  1: '0x65D66c76447ccB45dAf1e8044e918fA786A483A1',\n  3: '0xBD9F4bE886653177D22fA9c79FD0DFc41407fC89',\n  5: '0xf7f94b4607bcd1235212803be8fd1b54d1d01b77',\n  11155111: '0x8B1e2F5a9e16EAa5348e11adc4A2378bde7665CF',\n  421611: '0xe790Afe86c0bdc4Dd7C6CBb7dB087552Ec85F6fB',\n  31337: '0x0165878A594ca255338adfa4d48449f69242Eb8F',\n}\n\nexport const ETH_USDC_POOL: Address = {\n  1: '0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8',\n  3: '0x8356AbC730a218c24446C2c85708F373f354F0D8',\n  5: '0x5d3EfE9157003f05be0d4031F00D43F952d6F6b7',\n  11155111: '0xc3f9441319aE8749A45309Db4867758633e5D2D5',\n  421611: '0xe7715b01a0B16E3e38A7d9b78F6Bd2b163D7f319',\n  31337: '0x8dF057949E6717B6f28962f30e8415b148241e16',\n}\n\nexport const NFT_MANAGER: Address = {\n  1: '0xC36442b4a4522E871399CD717aBDD847Ab11FE88',\n  3: '0x8c7c1f786da4dee7d4bb49697a9b0c0c8fb328e0',\n  5: '0x24a66308bab3bebc2821480ada395bf1c4ff8bf2',\n  11155111: '0xa315999B13D2eaeD6Fc5f09900f7856AfD54193b',\n  421611: '',\n  31337: '',\n}\n\nexport const CRAB_STRATEGY: Address = {\n  1: '0xf205ad80bb86ac92247638914265887a8baa437d',\n  3: '0xbffBD99cFD9d77c49595dFe8eB531715906ca4Cf',\n  5: '',\n  11155111: '0x459161f2B3FF3d992eDb28E9CAC0Be55b4CFABb9',\n  421611: '',\n  31337: '',\n}\n\nexport const CRAB_MIGRATION: Address = {\n  1: '0xa1cab67a4383312718a5799eaa127906e9d4b19e',\n  3: '0xD0fb9d47B5F65d76C6bDf1b9E43a4A2345080B2f',\n  5: '', // this is a wrong address, ignore for now\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n\nexport const CRAB_STRATEGY2: Address = {\n  1: '0x3B960E47784150F5a63777201ee2B15253D713e8',\n  3: '0xdD1e9c25115e0d6e531d9F9E6ab7dbbEd15158Ce',\n  5: '0x3fF39f6BF8156bdA997D93E3EFF6904c2bc4481f',\n  11155111: '0x67ECf432858e94C412D4A266BB40824cEcB6aeF1',\n  421611: '',\n  31337: '',\n}\n\nexport const ZERO_ADDR = '0x0000000000000000000000000000000000000000'\n\nexport const CONTROLLER_HELPER: Address = {\n  1: '0xfa86d43b41Fa7a759c606130cc81970A955ff816',\n  3: '0x7e9C5490e91F93529c6480B46a59D738F6bcEa43',\n  5: '0xef0f6f951f0e62774597eb29b86065498bb7ac32',\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n\nexport const CRAB_HELPER: Address = {\n  1: '0x2f55e27e669f070def7b5771db72f6b31a6d4df8',\n  3: '',\n  5: '0xFB02DBd2f3803d660413335789291186A0390E35',\n  11155111: '0x2e228958Ea37a5FfF1F613bff64c5b2d066868e1',\n  421611: '',\n  31337: '',\n}\n\nexport const CRAB_NETTING: Address = {\n  1: '0x6E536adDB53d1b47d357cdca83BCF460194A395F',\n  3: '',\n  5: '0xa168df7B65093Cb54c88194eD070677cE34F551B',\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n\nexport const FLASH_BULL_STRATEGY: Address = {\n  1: '0x11A56a3A7A6Eb768A9125798B1eABE9EBD9EcE02',\n  3: '',\n  5: '0x3876aF971560FD4c4ba3FB18632AcC0570B745b1',\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n\nexport const BULL_STRATEGY: Address = {\n  1: '0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507',\n  3: '',\n  5: '0x2a5AD7582a9e42944Ee32671436593D16999c70a',\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n\nexport const WETH_E_TOKEN: Address = {\n  1: '0x1b808F49ADD4b8C6b5117d9681cF7312Fcf0dC1D',\n  3: '',\n  5: '0xef5e087d827194732bc1843351cca80982e154eb',\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n\nexport const USDC_D_TOKEN: Address = {\n  1: '0x84721A3dB22EB852233AEAE74f9bC8477F8bcc42',\n  3: '',\n  5: '0x356079240635b276a63065478471d89340443c49',\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n\nexport const AUCTION_BULL: Address = {\n  1: '0x6cd0890054d308264cD68B0b6ba38A36860593ec',\n  3: '',\n  5: '0xE5E4302933aef104Bb93181Ae9E8A664E42c8d9C',\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n\nexport const EULER_SIMPLE_LENS: Address = {\n  1: '0x5077B7642abF198b4a5b7C4BdCE4f03016C7089C',\n  3: '',\n  5: '0x62626a0f051B547b3182e55D1Eba667138790D8D',\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n\nexport const BULL_EMERGENCY_WITHDRAW: Address = {\n  1: '0x3ddc956b08c0a6da2249f8c528ff0594f5aea381',\n  3: '',\n  5: '0xe65c10a6d74c1724ced08d5873596fe55511ba05',\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n\nexport const BULL_SHUTDOWN_EMERGENCY_WITHDRAW: Address = {\n  1: '0xc7b7bffccb4d499d6899da88cec3ef283aa6108d',\n  3: '',\n  5: '',\n  11155111: '',\n  421611: '',\n  31337: '',\n}\n"
  },
  {
    "path": "packages/frontend/src/constants/diagram.ts",
    "content": "export const graphOptions = {\n  alignLabels: true,\n  priceScale: {\n    scaleMargins: {\n      top: 0.2,\n      bottom: 0.15,\n    },\n    mode: 0,\n  },\n  timeScale: {\n    rightOffset: 5,\n    barSpacing: 3,\n    fixLeftEdge: false, // false: can move before starting point\n    lockVisibleTimeRangeOnResize: true,\n    rightBarStaysOnScroll: true,\n    borderVisible: false,\n    borderColor: '#fff000',\n    visible: true,\n    timeVisible: true,\n    secondsVisible: false,\n  },\n  localization: {\n    priceFormatter: function (price: any) {\n      return '$' + Number(price.toFixed(2)).toLocaleString()\n    },\n    locale: 'en-US',\n  },\n  grid: {\n    vertLines: {\n      color: 'rgba(255, 255, 255, 0.12)',\n      visible: false,\n    },\n    horzLines: {\n      color: 'rgba(255, 255, 255, 0.12)',\n      visible: false,\n    },\n  },\n  layout: {\n    fontSize: 12,\n    backgroundColor: '#181B1C00',\n    lineColor: '#2B2B43',\n  },\n}\n\nexport const pnlGraphOptions = {\n  chart: {\n    backgroundColor: 'none',\n    zoomType: 'xy',\n    height: '346',\n    marginLeft: '48',\n    style: {\n      fontFamily: 'DM Mono',\n    },\n  },\n  title: {\n    text: '',\n  },\n  legend: {\n    enabled: false,\n    backgroundColor: '#343738',\n    borderRadius: 10,\n    itemStyle: {\n      color: '#BABBBB',\n    },\n  },\n  xAxis: {\n    type: 'datetime',\n    tickWidth: 0,\n    lineWidth: 0,\n    showFirstLabel: true,\n    showLastLabel: true,\n    crosshair: {\n      color: '#999',\n    },\n    labels: {\n      style: {\n        color: '#BABBBB',\n      },\n    },\n  },\n  tooltip: {\n    shared: true,\n    borderColor: 'none',\n    style: {\n      fontFamily: 'DM Mono',\n    },\n  },\n  credits: {\n    enabled: false,\n  },\n  exporting: {\n    enabled: true,\n  },\n}\n"
  },
  {
    "path": "packages/frontend/src/constants/enums.ts",
    "content": "import { OSQUEETH } from './address'\n\nexport enum TradeMode {\n  Buy,\n  Sell,\n}\n\nexport enum Vaults {\n  ETHBear = 'Bear', // long 1 eth + short squeeth\n  CrabVault = 'Crab USDC', // long 2 eth + short squeeth\n  ETHZenBull = 'Zen Bull ETH', // long 3 eth + short squeeth\n  Custom = 'Custom Strategy', // long x eth + short squeeth\n  Short = 'Short Squeeth', //pure short squeeth\n}\n\nexport enum VaultSubtitle {\n  ETHBear = 'Coming Soon',\n  CrabVault = 'Stack USDC',\n  ETHZenBull = 'Stack ETH',\n}\n\nexport enum TransactionType {\n  BUY = 'Bought',\n  SELL = 'Sold',\n  MINT_SHORT = 'Minted and sold',\n  BURN_SHORT = 'Bought back and burned',\n  ADD_LIQUIDITY = 'Added Liquidity',\n  REMOVE_LIQUIDITY = 'Removed Liquidity',\n  CRAB_FLASH_DEPOSIT = 'Deposit in crab',\n  CRAB_FLASH_WITHDRAW = 'Withdraw from crab',\n  CRAB_V2_FLASH_DEPOSIT = 'Deposit to crab V2',\n  CRAB_V2_FLASH_WITHDRAW = 'Withdraw from crab V2',\n  CRAB_V2_USDC_FLASH_DEPOSIT = 'Deposit USDC to crab V2',\n  CRAB_V2_USDC_FLASH_WITHDRAW = 'Withdraw USDC from crab V2',\n  OTC_DEPOSIT = 'Deposit USDC to crab v2',\n  OTC_WITHDRAW = 'Withdraw USDC from crab V2',\n  BULL_FLASH_DEPOSIT = 'Deposit in bull',\n  BULL_FLASH_WITHDRAW = 'Withdraw from bull',\n}\n\nexport enum CloseType {\n  PARTIAL = 'PartialClose',\n  FULL = 'FullClose',\n}\n\nexport enum InputType {\n  ETH = 'ETH',\n  SQTH = 'SQTH',\n}\n\nexport enum Tooltips {\n  ImplVol = 'Implied Volatility (IV) is a market forecast of ETH price movement implied by squeeth',\n  UnrealizedPnL = 'Total profit / loss if you were to fully close your position at the current oSQTH price on Uniswap. Resets if you close your position or change position sides (long to short, or vice versa)',\n  RealizedPnL = 'Total realized profit / loss for this position through partial closes. Resets if you fully close your position or change position sides (long to short, or vice versa)',\n  PnLExplanation = 'Squeeth performance is affected by implied volatility, premiums, ETH price, and price impact.',\n  ShortCollateral = 'Takes ETH collateral into account.',\n  Mark = 'The price squeeth is trading at. Because squeeth has convexity, Mark should be greater than ETH^2',\n  Last30MinAvgFunding = 'Historical daily premium based on the last 30min. Calculated using a 30min TWAP of Mark - Index',\n  CurrentImplFunding = 'Expected daily premium based on current price, calculated using current Mark - Index',\n  FundingPayments = 'Premiums are paid / received every time the contract is touched',\n  NormFactor = 'The variable that adjusts the value of your position based on premiums',\n  oSQTHPrice = 'Price of oSQTH on Uniswap',\n  LPPnL = 'PnL = Value of current LP underlying tokens including uncollected fees - Value of tokens deposited (at current price)',\n  UniswapLoading = 'When you click the Uniswap link, the Uniswap LP page may take a few moments to load. Please wait for it to fully load so it can prefill LP token data.',\n  Operator = 'The wrapper contract mints squeeth, deposits collateral and sells squeeth in single TX. Similarly it also buys back + burns squeeth and withdraws collateral in single TX',\n  SellCloseAmount = 'Amount of oSQTH to buy',\n  CurrentCollRatio = 'Collateral ratio for current short position',\n  SellOpenAmount = 'Minimum collateral amount is 6.9 ETH to ensure system solvency with sufficient liquidation incentive',\n  LiquidationPrice = 'Price of ETH when liquidation occurs.',\n  InitialPremium = 'Initial payment you get for selling squeeth on Uniswap',\n  BacktestDisclaimer = 'This is historical backtest data and does not show the actual performance of squeeth. See the FAQ to learn more.',\n  PercentOfPool = 'The amount of your liquidity compared to all current active liquidity',\n  SpotPrice = 'This is a spot price from Uniswap',\n  Twap = 'This is a 7 min TWAP from Uniswap.',\n  MintBurnInput = 'Input a negative number (with a minus sign on the extreme left) to burn, and a positive number (no sign needed) to mint.',\n  CollatRemoveAdd = 'Input a negative number (with a minus sign on the extreme left) to remove, and a positive number (no sign needed) to add.',\n  LPDebt = 'This is squeeth debt for which you have put down collateral to LP.',\n  MintedDebt = 'This is squeeth debt for which you have put down collateral to acquire.',\n  ShortDebt = 'This is squeeth that you acquired and sold',\n  TotalDebt = 'Debt of the vault',\n  VaultLiquidations = 'The strategy is subject to liquidations if it goes below 150% collateral, but rebalancing based on large ETH price changes helps prevent a liquidation from occurring.',\n  CrabPnL = 'Expected total profit/ loss if you were to fully withdraw from the Crab Strategy. Includes price impact from trading on uniswap. Resets if you close your position. Note that if you migrated from v1, your PnL is reset with the migrated amount as your initial crab v2 deposit.',\n  CrabMigratedDeposit = 'Your current share ratio of the total amount deposited in strategy. Note that if you migrated from v1, your PnL is reset with your initial deposited amount as the amount migrated from v1.',\n  StrategyLiquidations = 'The strategy is subject to liquidations if it goes below 150% collateral, but rebalancing based on large ETH price changes helps prevent a liquidation from occurring.',\n  StrategyShort = 'The amount of oSQTH the whole strategy is short',\n  StrategyCollRatio = 'The collateralization ratio for the whole strategy',\n  StrategyEarnFunding = 'You earn premiums by depositing into the strategy',\n  StrategyProfitThreshold = 'Based on current premiums, crab strategy would be unprofitable if ETH moves more than approximately the profit threshold in either direction before the next hedge. This profitable price range is based on the current premium and will change continuously as the premium changes',\n  BullStrategyProfitThreshold = 'Based on current premiums, zen bull strategy would be unprofitable if ETH moves more than approximately the profit threshold in either direction before the next hedge. This profitable price range is based on the current premium and will change continuously as the premium changes',\n  FullcloseInput = 'Select partial close to edit input',\n  FundingVol = 'VOL is calculated as \"sqrt(Daily Premium * 365)\"',\n  FundingDaily = 'Daily premium is calculated as ln(mark / index) * 17.5. Mark and Index spot values are taken at points in the past and scaled to one day.',\n  FundingMonthly = 'Monthly premium is calculated as (Daily Premium * 30)',\n  FundingAnnual = 'Annual Premium is calculated as (Daily Premium * 365.25)',\n  VaultCollatRatio = `You'll be adjusting the collateral ratio for the whole vault and not just this trade.`,\n  osqthRefVol = 'Squeeth reference volatility based on deribit options and squeeth replicating portfolio. Squeeth ref vol is calculated/refreshed every 5 minutes.',\n  ETHUp2x = 'The value of your position if ETH goes up 2x, not including premiums',\n  ETHDown50 = 'The value of your position if ETH goes down 50%, not including premiums',\n  InitiatedDeposit = 'Your deposit has been initiated and will be submitted via auction to reduce price impact. This may take up until Tuesday',\n  InitiatedWithdrawal = 'Your withdrawal has been initiated and will be submitted via auction to reduce price impact. This may take up until Tuesday',\n}\n\nexport enum Links {\n  BacktestFAQ = 'https://opyn.gitbook.io/squeeth/resources/squeeth-faq#what-is-the-historical-365d-pnl',\n  GitBook = 'https://opyn.gitbook.io/squeeth/',\n  UniswapSwap = 'https://app.uniswap.org/#/swap?inputCurrency=ETH&outputCurrency=0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B',\n  CrabFAQ = 'https://opyn.gitbook.io/squeeth/resources/squeeth-strategies-faq',\n  AutoRouter = 'https://uniswap.org/blog/auto-router',\n}\n\nexport const UniswapIFrameOpen = {\n  1: `https://app.uniswap.org/#/add/ETH/${OSQUEETH[1]}/3000`,\n  3: `https://squeeth-uniswap.netlify.app/#/add/ETH/${OSQUEETH[3]}/3000`,\n  5: `https://squeeth-uniswap.netlify.app/#/add/ETH/${OSQUEETH[5]}/3000`,\n  11155111: `https://squeeth-uniswap.netlify.app/#/add/ETH/${OSQUEETH[11155111]}/3000`,\n  31337: 'https://app.uniswap.org/#/add/ETH/0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B/3000', // Should be replaced with arbitrum subgraph\n  421611: 'https://app.uniswap.org/#/add/ETH/0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B/3000', // Should be replaced with arbitrum subgraph\n}\n\nexport const UniswapIFrameClose = {\n  1: 'https://app.uniswap.org/#/pool',\n  3: 'https://squeeth-uniswap.netlify.app/#/pool',\n  5: 'https://squeeth-uniswap.netlify.app/#/pool',\n  11155111: `https://squeeth-uniswap.netlify.app/#/pool`,\n  31337: 'https://app.uniswap.org/#/add/ETH/0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B/3000', // Should be replaced with arbitrum subgraph\n  421611: 'https://app.uniswap.org/#/add/ETH/0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B/3000', // Should be replaced with arbitrum subgraph\n}\n\nexport enum Action {\n  MINT = 'MINT',\n  BURN = 'BURN',\n  OPEN_SHORT = 'OPEN_SHORT',\n  CLOSE_SHORT = 'CLOSE_SHORT',\n  DEPOSIT_COLLAT = 'DEPOSIT_COLLAT',\n  LIQUIDATE = 'LIQUIDATE',\n  WITHDRAW_COLLAT = 'WITHDRAW_COLLAT',\n}\n"
  },
  {
    "path": "packages/frontend/src/constants/index.ts",
    "content": "import BigNumber from 'bignumber.js'\n\nexport * from './diagram'\nexport * from './enums'\n\nexport const UNI_POOL_FEES = 3000\nexport const ETH_USDC_POOL_FEES = 500\n\nexport const REVERTED_TRANSACTION_CODE = 4001\n\n//17.5 days, 420 hours\nexport const FUNDING_PERIOD = 17.5\n\nexport const DEFAULT_SLIPPAGE = 0.25\n\nexport const MIN_COLLATERAL_AMOUNT = 6.9\n\nexport const MIN_COLLATERAL_RATIO = 150\n\nexport const DEFAULT_COLLATERAL_RATIO = 225\n\nexport const YEAR = 365\n\nexport const VOL_PERCENT_FIXED = 0.1\n\nexport const VOL_PERCENT_SCALAR = 0.1\n\nexport const AVERAGE_AUCTION_PRICE_IMPACT = 0.79\n\nexport const NETTING_PRICE_IMPACT = 0.2\n\n//7min, 420 seconds\nexport const TWAP_PERIOD = 420\n\nexport const SHUTDOWN_DATE = '2024-11-04T16:00:00Z'\n\nexport const EtherscanPrefix = {\n  1: 'https://etherscan.io/tx/',\n  3: 'https://ropsten.etherscan.io/tx/',\n  5: 'https://goerli.etherscan.io/tx/',\n  11155111: 'https://sepolia.etherscan.io/tx/',\n  421611: 'https://rinkeby-explorer.arbitrum.io/tx/',\n  31337: '/',\n}\nexport const INDEX_SCALE = 10000\nexport const OSQUEETH_DECIMALS = 18\nexport const WETH_DECIMALS = 18\nexport const USDC_DECIMALS = 6\nexport const CRAB_TOKEN_DECIMALS = 18\nexport const BULL_TOKEN_DECIMALS = 18\n\nexport const SWAP_EVENT_TOPIC = '0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67'\n\nexport const BIG_ZERO = new BigNumber(0)\nexport const BIG_ONE = new BigNumber(10).pow(18)\nexport const TWELVEDATA_NO_PRICEDATA_DURATION = 62\nexport const BLOCKED_COUNTRIES = [\n  'US',\n  'BY',\n  'CU',\n  'IR',\n  'IQ',\n  'CI',\n  'LR',\n  'KP',\n  'SD',\n  'SY',\n  'ZW',\n  'CA',\n  'MM',\n  'CD',\n  'UA',\n]\nexport const ALLOW_WITHDRAWALS = ['CA']\n\nexport const BLOCKED_IP_VALUE = 'BLOCKED'\n\n// V2 Migration details\nexport const V2_MIGRATION_ETH_PRICE = 1611.71\nexport const V2_MIGRATION_OSQTH_PRICE = 0.0897\nexport const V2_MIGRATION_ETH_AMOUNT = 790.186510787310292814\nexport const V2_MIGRATION_OSQTH_AMOUNT = 4604.57349514942255453\nexport const V2_MIGRATION_SUPPLY = 519.994374902152348633\n\nexport const squeethRefVolDocLink = 'https://colab.research.google.com/drive/1HTM_2j0jmda9tzN_uskBPz9Rpma8Lp3C'\nexport const CRABV2_START_DATE = '2022-07-28'\nexport const BULL_START_DATE = '2022-12-19'\n\nexport const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'\n\nexport const STRATEGY_DEPOSIT_LIMIT = 1000_000\nexport const SQUEETH_BASE_URL = 'https://squeeth.opyn.co'\n\nexport const SiteMetaTitle = 'Opyn - Stack your ETH and Stables'\nexport const SiteMetaDescription = 'DeFi Investment Strategies Powered by Squeeth'\nexport const SiteMetaImage = SQUEETH_BASE_URL + '/images/previews/opyn.png'\n\nexport const TOS_UPDATE_DATE = '2023-04-21'\n\nexport const LEGAL_PAGES = ['/terms-of-service', '/privacy-policy']\n"
  },
  {
    "path": "packages/frontend/src/context/lp.tsx",
    "content": "import React, { useContext, useReducer, Reducer } from 'react'\n\nimport { useAtomValue } from 'jotai'\nimport { addressesAtom } from 'src/state/positions/atoms'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport { OSQUEETH_DECIMALS } from '@constants/index'\nimport useAppEffect from '@hooks/useAppEffect'\n\nexport enum Steps {\n  SELECT_METHOD = 1,\n  GET_SQUEETH,\n  PROVIDE_LIQUIDITY,\n}\n\nexport enum OBTAIN_METHOD {\n  MINT = 1,\n  BUY,\n}\n\ntype LPType = {\n  step: Steps\n  mostForwardStep: Steps\n  obtainMethod: OBTAIN_METHOD\n  canGoBack: boolean\n  canGoForward: boolean\n}\n\ntype LPContextType = {\n  lpState: LPType\n  dispatch: React.Dispatch<ActionType>\n}\n\nconst initialState: LPType = {\n  step: Steps.SELECT_METHOD,\n  mostForwardStep: Steps.SELECT_METHOD,\n  obtainMethod: OBTAIN_METHOD.MINT,\n  canGoBack: false,\n  canGoForward: false,\n}\n\nexport enum LPActions {\n  SELECT_METHOD,\n  GO_BACK,\n  GO_FORWARD,\n  GO_TO_PROVIDE_LIQUIDITY,\n}\n\nexport type ActionType = {\n  type: LPActions\n  payload?: any\n}\n\nconst updateBoundary = (newState: LPType) => {\n  const canGoBack = newState.step > Steps.SELECT_METHOD\n  const canGoForward = newState.step < newState.mostForwardStep\n\n  return { ...newState, canGoBack, canGoForward }\n}\n\nconst tradeReducer: (state: LPType, action: any) => LPType = (state, action: ActionType) => {\n  console.log(state)\n  switch (action.type) {\n    case LPActions.SELECT_METHOD:\n      return updateBoundary({\n        ...state,\n        step: Steps.GET_SQUEETH,\n        mostForwardStep: state.mostForwardStep === Steps.SELECT_METHOD ? Steps.GET_SQUEETH : state.mostForwardStep,\n        obtainMethod: action.payload,\n      })\n    case LPActions.GO_BACK:\n      if (!state.canGoBack) return state\n      return updateBoundary({ ...state, step: state.step - 1 })\n    case LPActions.GO_FORWARD:\n      if (!state.canGoForward) return state\n      return updateBoundary({ ...state, step: state.step + 1 })\n    case LPActions.GO_TO_PROVIDE_LIQUIDITY:\n      return updateBoundary({ ...state, step: Steps.PROVIDE_LIQUIDITY, mostForwardStep: Steps.PROVIDE_LIQUIDITY })\n    default:\n      return state\n  }\n}\n\nconst LPContext = React.createContext<LPContextType>({ lpState: initialState, dispatch: () => null })\nconst useLPState = () => useContext<LPContextType>(LPContext)\n\nconst LPProvider: React.FC = ({ children }) => {\n  const [lpState, dispatch] = useReducer<Reducer<LPType, ActionType>>(tradeReducer, initialState)\n\n  const { oSqueeth } = useAtomValue(addressesAtom)\n  const { value: oSqueethBal } = useTokenBalance(oSqueeth, 15, OSQUEETH_DECIMALS)\n\n  useAppEffect(() => {\n    if (oSqueethBal.isZero() || lpState.step === Steps.PROVIDE_LIQUIDITY) return\n\n    dispatch({ type: LPActions.GO_TO_PROVIDE_LIQUIDITY })\n  }, [oSqueethBal])\n\n  return <LPContext.Provider value={{ lpState, dispatch }}>{children}</LPContext.Provider>\n}\n\nexport { LPProvider, useLPState }\n"
  },
  {
    "path": "packages/frontend/src/context/restrict-user.tsx",
    "content": "import React, { useContext, useState, useCallback, useEffect } from 'react'\nimport { useAtomValue } from 'jotai'\nimport { useRouter } from 'next/router'\n\nimport { Networks } from '../types'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\nimport { BLOCKED_COUNTRIES } from '../constants/index'\n\ntype restrictUserContextType = {\n  isRestricted: boolean\n  isWithdrawAllowed: boolean\n  isBlockedUser: boolean\n  handleRestrictUser: (isRestricted: boolean, isWithdrawAllowed: boolean) => void\n  blockUser: () => void\n}\n\nconst initialState: restrictUserContextType = {\n  isRestricted: false,\n  isWithdrawAllowed: true,\n  isBlockedUser: false,\n  handleRestrictUser: () => null,\n  blockUser: () => null,\n}\n\nconst restrictUserContext = React.createContext<restrictUserContextType>(initialState)\nconst useRestrictUser = () => useContext(restrictUserContext)\n\nconst RestrictUserProvider: React.FC = ({ children }) => {\n  const router = useRouter()\n  const networkId = useAtomValue(networkIdAtom)\n  const userLocation = router.query?.ct\n  const [isBlockedUser, setIsBlockedUser] = useState(false)\n  const [isRestricted, setIsRestricted] = useState(false)\n\n  const handleRestrictUser = useCallback((isRestrictedFlag: boolean) => {\n    setIsRestricted(isRestrictedFlag)\n  }, [])\n\n  const blockUser = useCallback(() => {\n    setIsBlockedUser(true)\n  }, [])\n\n  const isUserRestricted = BLOCKED_COUNTRIES.includes(String(userLocation)) || isBlockedUser\n  useEffect(() => {\n    if (isUserRestricted && networkId === Networks.MAINNET) {\n      handleRestrictUser(true)\n    } else {\n      handleRestrictUser(false)\n    }\n  }, [handleRestrictUser, networkId, isUserRestricted])\n\n  return (\n    <restrictUserContext.Provider\n      value={{\n        handleRestrictUser,\n        isRestricted,\n        isWithdrawAllowed: true,\n        blockUser,\n        isBlockedUser,\n      }}\n    >\n      {children}\n    </restrictUserContext.Provider>\n  )\n}\n\nexport { RestrictUserProvider, useRestrictUser }\n"
  },
  {
    "path": "packages/frontend/src/hooks/__tests__/useAppCallback.test.ts",
    "content": "import useAppCallback from '@hooks/useAppCallback'\nimport { renderHook } from '@testing-library/react-hooks'\nimport BigNumber from 'bignumber.js'\nimport { useCallback } from 'react'\n\njest.mock('react', () => ({\n  ...jest.requireActual('react'),\n  useCallback: jest.fn(),\n}))\n\ndescribe('useAppCallback', () => {\n  const mockedCallback = jest.fn()\n\n  it('calls useCallback with stringified dependencies', () => {\n    renderHook(() =>\n      useAppCallback(mockedCallback, [\n        3,\n        'test',\n        new BigNumber(5),\n        [\n          { id: 1, value: 'test' },\n          { id: 2, value: 'example' },\n        ],\n      ]),\n    )\n\n    expect(useCallback).toHaveBeenCalledWith(mockedCallback, [3, 'test', '5', '1,2'])\n  })\n})\n"
  },
  {
    "path": "packages/frontend/src/hooks/__tests__/useAppEffect.test.ts",
    "content": "import useAppEffect from '@hooks/useAppEffect'\nimport { renderHook } from '@testing-library/react-hooks'\nimport BigNumber from 'bignumber.js'\n\nbeforeEach(() => {\n  jest.clearAllMocks()\n})\n\ndescribe('useAppEffect', () => {\n  const mockedEffect = jest.fn()\n\n  it('runs effect initially', () => {\n    const deps = [3, 'test']\n\n    renderHook(() => useAppEffect(mockedEffect, deps))\n\n    expect(mockedEffect).toHaveBeenCalled()\n  })\n\n  it('runs effect when depedency is changed', () => {\n    const { rerender } = renderHook(({ deps }) => useAppEffect(mockedEffect, deps), {\n      initialProps: { deps: [3, 'test'] },\n    })\n\n    rerender({ deps: [3, 'test changed'] })\n\n    expect(mockedEffect).toHaveBeenCalledTimes(2)\n  })\n\n  it('does not run effect when big number string is not changed', () => {\n    const { rerender } = renderHook(({ deps }) => useAppEffect(mockedEffect, deps), {\n      initialProps: { deps: [new BigNumber(3), 'test'] },\n    })\n\n    rerender({ deps: [new BigNumber(3), 'test'] })\n\n    expect(mockedEffect).toHaveBeenCalledTimes(1)\n  })\n\n  it('runs effect when big number string is changed', () => {\n    const { rerender } = renderHook(({ deps }) => useAppEffect(mockedEffect, deps), {\n      initialProps: { deps: [new BigNumber(3), 'test'] },\n    })\n\n    rerender({ deps: [new BigNumber(3.5), 'test'] })\n\n    expect(mockedEffect).toHaveBeenCalledTimes(2)\n  })\n\n  it('does not run effect when ids of array are not changed', () => {\n    const { rerender } = renderHook(({ deps }) => useAppEffect(mockedEffect, deps), {\n      initialProps: {\n        deps: [\n          [\n            { id: 3, value: '232' },\n            { id: 4, value: '456' },\n          ],\n          'test',\n        ],\n      },\n    })\n\n    rerender({\n      deps: [\n        [\n          { id: 3, value: '232' },\n          { id: 4, value: '456' },\n        ],\n        'test',\n      ],\n    })\n\n    expect(mockedEffect).toHaveBeenCalledTimes(1)\n  })\n\n  it('runs effect when ids of array are changed', () => {\n    const { rerender } = renderHook(({ deps }) => useAppEffect(mockedEffect, deps), {\n      initialProps: {\n        deps: [\n          [\n            { id: 3, value: '232' },\n            { id: 4, value: '456' },\n          ],\n          'test',\n        ],\n      },\n    })\n\n    rerender({\n      deps: [\n        [\n          { id: 4, value: '232' },\n          { id: 4, value: '456' },\n        ],\n        'test',\n      ],\n    })\n\n    expect(mockedEffect).toHaveBeenCalledTimes(2)\n  })\n})\n"
  },
  {
    "path": "packages/frontend/src/hooks/__tests__/useAppMemo.test.ts",
    "content": "import useAppMemo from '@hooks/useAppMemo'\nimport { renderHook } from '@testing-library/react-hooks'\nimport BigNumber from 'bignumber.js'\nimport { useMemo } from 'react'\n\njest.mock('react', () => ({\n  ...jest.requireActual('react'),\n  useMemo: jest.fn(),\n}))\n\ndescribe('useAppMemo', () => {\n  const mockedFactory = jest.fn()\n\n  it('calls useMemo with stringified dependencies', () => {\n    renderHook(() =>\n      useAppMemo(mockedFactory, [\n        3,\n        'test',\n        new BigNumber(5),\n        [\n          { id: 1, value: 'test' },\n          { id: 2, value: 'example' },\n        ],\n      ]),\n    )\n\n    expect(useMemo).toHaveBeenCalledWith(mockedFactory, [3, 'test', '5', '1,2'])\n  })\n})\n"
  },
  {
    "path": "packages/frontend/src/hooks/contracts/useAllowance.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { useState } from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport abi from '../../abis/erc20.json'\nimport { toTokenAmount } from '@utils/calculations'\nimport { useHandleTransaction } from 'src/state/wallet/hooks'\nimport { addressAtom, web3Atom } from 'src/state/wallet/atoms'\nimport useAppCallback from '@hooks/useAppCallback'\nimport useAppEffect from '@hooks/useAppEffect'\n\nconst MAX_UINT = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'\n\nexport function useUserAllowance(token: string, spenderAddess: string | null, decimals?: number) {\n  const handleTransaction = useHandleTransaction()\n  const web3 = useAtomValue(web3Atom)\n  const address = useAtomValue(addressAtom)\n\n  const [allowance, setAllowance] = useState(new BigNumber(0))\n  const [isLoadingAllowance, setIsLoadingAllowance] = useState(true)\n\n  const approve = useAppCallback(\n    async (onTxConfirmed: () => void) => {\n      if (!web3 || !address) return\n\n      const erc = new web3.eth.Contract(abi as any, token)\n      const approveAmount = MAX_UINT\n\n      if (spenderAddess === '') throw new Error('Unkown Spender')\n\n      await handleTransaction(erc.methods.approve(spenderAddess, approveAmount).send({ from: address }), async () => {\n        onTxConfirmed()\n      })\n      const newAllowance = await erc.methods.allowance(address, spenderAddess).call()\n      setAllowance(toTokenAmount(new BigNumber(newAllowance.toString()), decimals || 18))\n    },\n    [web3, token, address, spenderAddess, handleTransaction, decimals],\n  )\n\n  useAppEffect(() => {\n    if (!address || !web3) return\n    const erc = new web3.eth.Contract(abi as any, token)\n    erc.methods\n      .allowance(address, spenderAddess)\n      .call()\n      .then((allowance: any) => {\n        setAllowance(toTokenAmount(new BigNumber(allowance.toString()), decimals || 18))\n        setIsLoadingAllowance(false)\n      })\n      .catch(() => {\n        setIsLoadingAllowance(false)\n      })\n  }, [web3, spenderAddess, token, address, decimals])\n\n  return { allowance, isLoadingAllowance, approve }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/contracts/useERC721.ts",
    "content": "import { useState } from 'react'\nimport { Contract } from 'web3-eth-contract'\nimport { useAtomValue } from 'jotai'\n\nimport erc721Abi from '../../abis/erc721.json'\nimport { useHandleTransaction } from 'src/state/wallet/hooks'\nimport { addressAtom, web3Atom } from 'src/state/wallet/atoms'\nimport useAppEffect from '@hooks/useAppEffect'\n\nexport const useERC721 = (token: string) => {\n  const [contract, setContract] = useState<Contract>()\n\n  const handleTransaction = useHandleTransaction()\n  const web3 = useAtomValue(web3Atom)\n  const address = useAtomValue(addressAtom)\n\n  useAppEffect(() => {\n    if (!web3 || !token) return\n    setContract(new web3.eth.Contract(erc721Abi as any, token))\n  }, [web3, token])\n\n  const approve = async (toAddress: string, tokenId: number) => {\n    if (!contract || !address) return\n\n    await handleTransaction(\n      contract.methods.approve(toAddress, tokenId).send({\n        from: address,\n      }),\n    )\n  }\n\n  const getApproved = async (tokenId: number) => {\n    if (!contract || !address) return\n\n    const approveAddress = await contract.methods.getApproved(tokenId).call()\n    return approveAddress\n  }\n\n  return {\n    approve,\n    getApproved,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/contracts/useLiquidations.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport { useState } from 'react'\nimport { Contract } from 'web3-eth-contract'\nimport { useAtomValue } from 'jotai'\n\nimport controllerABI from '../../abis/controller.json'\nimport { OSQUEETH_DECIMALS } from '../../constants'\nimport { liquidations } from '../../queries/squeeth/__generated__/liquidations'\nimport { LIQUIDATIONS_QUERY } from '../../queries/squeeth/liquidationsQuery'\nimport { squeethClient } from '../../utils/apollo-client'\nimport { toTokenAmount } from '@utils/calculations'\nimport { networkIdAtom /* web3Atom */ } from 'src/state/wallet/atoms'\n// import { addressesAtom } from 'src/state/positions/atoms'\nimport useAppEffect from '@hooks/useAppEffect'\n\n/**\n * get vault liquidations.\n * @param vaultId\n * @param refetchIntervalSec refetch interval in seconds\n * @returns {Vault[]}\n */\nexport const useVaultLiquidations = (vaultId: number /* refetchIntervalSec = 30 */) => {\n  const [liquidations, setLiquidations] = useState<Array<any>>([])\n  // const [contract, setContract] = useState<Contract>()\n\n  // const web3 = useAtomValue(web3Atom)\n  const networkId = useAtomValue(networkIdAtom)\n  // const { controller } = useAtomValue(addressesAtom)\n\n  // useAppEffect(() => {\n  //   if (!web3 || !controller) return\n  //   setContract(new web3.eth.Contract(controllerABI as any, controller))\n  // }, [web3])\n\n  const { data, loading } = useQuery<liquidations>(LIQUIDATIONS_QUERY, {\n    client: squeethClient[networkId],\n    variables: {\n      vaultId,\n    },\n    fetchPolicy: 'cache-and-network',\n  })\n\n  useAppEffect(() => {\n    if (!data?.liquidations) return\n    const _liquidations = data?.liquidations.map((l) => {\n      return {\n        ...l,\n        debtAmount: toTokenAmount(l.debtAmount.toString(), OSQUEETH_DECIMALS),\n        collateralPaid: toTokenAmount(l.collateralPaid.toString(), 18),\n      }\n    })\n    setLiquidations(_liquidations)\n  }, [data?.liquidations])\n\n  return { liquidations, loading }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/contracts/useLongHelper.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { useAtomValue } from 'jotai'\n\nimport { OSQUEETH_DECIMALS } from '../../constants'\nimport { fromTokenAmount } from '@utils/calculations'\nimport { addressAtom } from 'src/state/wallet/atoms'\nimport { useHandleTransaction } from 'src/state/wallet/hooks'\nimport { controllerContractAtom } from '../../state/contracts/atoms'\n\nexport const useShutdownLongHelper = () => {\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const contract = useAtomValue(controllerContractAtom)\n\n  /**\n   * Redeem vault\n   * @param vaultId\n   * @returns\n   */\n  const redeemLongHelper = async (osqthAmount: BigNumber, onTxConfirmed?: () => void) => {\n    if (!contract || !address) {\n      return\n    }\n\n    // redeem vault\n    const result = await handleTransaction(\n      contract.methods.redeemLong(fromTokenAmount(osqthAmount, OSQUEETH_DECIMALS).toFixed(0)).send({\n        from: address,\n      }),\n      onTxConfirmed,\n    )\n\n    return result\n  }\n\n  return {\n    redeemLongHelper,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/contracts/useOracle.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { useState, useCallback } from 'react'\nimport { Contract } from 'web3-eth-contract'\nimport { useAtomValue } from 'jotai'\n\nimport abi from '../../abis/oracle.json'\nimport { toTokenAmount } from '@utils/calculations'\nimport { web3Atom } from 'src/state/wallet/atoms'\nimport { addressesAtom } from 'src/state/positions/atoms'\nimport useAppEffect from '@hooks/useAppEffect'\n\nexport const useOracle = () => {\n  const web3 = useAtomValue(web3Atom)\n  const { oracle } = useAtomValue(addressesAtom)\n  const [contract, setContract] = useState<Contract>()\n\n  useAppEffect(() => {\n    if (!web3) return\n    setContract(new web3.eth.Contract(abi as any, oracle))\n  }, [oracle, web3])\n\n  const getTwapSafe = useCallback(\n    async (pool: string, base: string, quote: string, period = 300) => {\n      if (!contract) return new BigNumber(0)\n\n      const _price = await contract.methods.getTwap(pool, base, quote, period, true).call()\n      return toTokenAmount(_price, 18)\n    },\n    [contract],\n  )\n\n  return {\n    getTwapSafe,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/contracts/useShortHelper.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { useAtomValue } from 'jotai'\n\nimport { WETH_DECIMALS, OSQUEETH_DECIMALS } from '../../constants'\nimport { fromTokenAmount } from '@utils/calculations'\nimport { addressAtom } from 'src/state/wallet/atoms'\nimport { useHandleTransaction } from 'src/state/wallet/hooks'\nimport { addressesAtom } from 'src/state/positions/atoms'\nimport { useGetBuyParam, useGetSellParam } from 'src/state/squeethPool/hooks'\nimport { shortHelperContractAtom, controllerContractAtom } from '../../state/contracts/atoms'\nimport { normFactorAtom } from 'src/state/controller/atoms'\n\nexport const useShortHelper = () => {\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const { shortHelper } = useAtomValue(addressesAtom)\n\n  const getSellParam = useGetSellParam()\n  const getBuyParam = useGetBuyParam()\n  const contract = useAtomValue(shortHelperContractAtom)\n\n  const normalizationFactor = useAtomValue(normFactorAtom)\n\n  /**\n   * deposit collat, mint squeeth and sell it in uniSwap\n   * @param vaultId - 0 to create new\n   * @param amount - Amount of squeeth to mint\n   * @param vaultType\n   * @returns\n   */\n  const openShort = async (vaultId: number, amount: BigNumber, collatAmount: BigNumber, onTxConfirmed?: () => void) => {\n    if (!contract || !address) return\n\n    const _exactInputParams = await getSellParam(amount)\n    _exactInputParams.recipient = shortHelper\n\n    const _amount = fromTokenAmount(amount, OSQUEETH_DECIMALS).multipliedBy(normalizationFactor)\n    const ethAmt = fromTokenAmount(collatAmount, 18)\n    const result = await handleTransaction(\n      contract.methods.openShort(vaultId, _amount.toFixed(0), 0, _exactInputParams).send({\n        from: address,\n        value: ethAmt.toString(), // Already scaled to 14 so multiplied with 10000\n      }),\n      onTxConfirmed,\n    )\n\n    return result\n  }\n\n  /**\n   * Buy back and close vault, withdraw collateral\n   * @param vaultId\n   * @param amount - Amount of squeeth to buy back\n   * @returns\n   */\n  const closeShort = async (vaultId: number, amount: BigNumber, withdrawAmt: BigNumber, onTxConfirmed?: () => void) => {\n    if (!contract || !address) return\n\n    const _amount = fromTokenAmount(amount, OSQUEETH_DECIMALS)\n    const _withdrawAmt = fromTokenAmount(withdrawAmt.isPositive() ? withdrawAmt : 0, WETH_DECIMALS)\n    const _exactOutputParams = await getBuyParam(amount)\n\n    _exactOutputParams.recipient = shortHelper\n\n    // _burnSqueethAmount and _withdrawAmount will be same as we are putting 1:1 collat now\n    const result = await handleTransaction(\n      contract.methods.closeShort(vaultId, _amount.toString(), _withdrawAmt.toFixed(0), _exactOutputParams).send({\n        from: address,\n        value: _exactOutputParams.amountInMaximum,\n      }),\n      onTxConfirmed,\n    )\n\n    return result\n  }\n\n  return {\n    openShort,\n    closeShort,\n  }\n}\n\nexport const useShutdownShortHelper = () => {\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const contract = useAtomValue(controllerContractAtom)\n\n  /**\n   * Redeem vault\n   * @param vaultId\n   * @returns\n   */\n  const redeemShortPosition = async (vaultId: number, onTxConfirmed?: () => void) => {\n    if (!contract || !address) {\n      return\n    }\n\n    // redeem vault\n    const result = await handleTransaction(\n      contract.methods.redeemShort(vaultId).send({\n        from: address,\n      }),\n      onTxConfirmed,\n    )\n\n    return result\n  }\n\n  return {\n    redeemShortPosition,\n  }\n}\n\nexport default useShortHelper\n"
  },
  {
    "path": "packages/frontend/src/hooks/contracts/useTokenBalance.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { useCallback, useEffect, useRef, useState, useMemo } from 'react'\nimport { usePrevious } from 'react-use'\nimport { Contract } from 'web3-eth-contract'\nimport { useQuery } from 'react-query'\nimport { useAtomValue } from 'jotai'\n\nimport erc20Abi from '../../abis/erc20.json'\nimport { toTokenAmount } from '@utils/calculations'\nimport { addressAtom, connectedWalletAtom, networkIdAtom, web3Atom } from 'src/state/wallet/atoms'\n\ntype Callback = (newBalance: BigNumber) => void\n\ninterface TokenQueryKeyParams {\n  token: string\n  connected: boolean\n  address: string | null\n  decimals: number\n  refetchIntervalSec: number\n  network: number\n}\nconst tokenBalanceQueryKeys = {\n  userTokenBalance: (params: TokenQueryKeyParams) => ['userTokenBalance', params],\n}\n/**\n * get token balance.\n * @param token token address\n * @param refetchIntervalSec refetch interval in seconds\n * @returns {BigNumber} raw balance\n */\nexport const useTokenBalance = (token: string, refetchIntervalSec = 30, decimals = 18) => {\n  const [poll, setPoll] = useState(false)\n\n  const web3 = useAtomValue(web3Atom)\n  const address = useAtomValue(addressAtom)\n  const connected = useAtomValue(connectedWalletAtom)\n  const network = useAtomValue(networkIdAtom)\n\n  const onRefetchCallback = useRef<Callback>()\n\n  // Contract being state mess up if the network is ropsten\n  // It take one rerender to update the correct contract ie) mainnet => ropsten\n  // updateBalance returns 0 as it use mainnet contract. Since it's useQuery the value is cached always\n  const contract = useMemo(() => {\n    if (!web3 || !token) return undefined\n    return new web3.eth.Contract(erc20Abi as any, token)\n  }, [web3, token])\n\n  const balanceQuery = useQuery(\n    tokenBalanceQueryKeys.userTokenBalance({ address, connected, decimals, refetchIntervalSec, token, network }),\n    () => updateBalance(token, connected, contract, address, decimals),\n    {\n      enabled: Boolean(token) && Boolean(connected) && Boolean(contract),\n      refetchInterval: poll ? 500 : refetchIntervalSec * 15000,\n    },\n  )\n\n  const prevBalance = usePrevious(balanceQuery.data?.toString())\n\n  useEffect(() => {\n    if (poll && prevBalance && balanceQuery.data && prevBalance !== balanceQuery.data?.toString()) {\n      setPoll(false)\n      onRefetchCallback.current?.(balanceQuery.data)\n    }\n  }, [balanceQuery.data?.toString(), poll, prevBalance])\n\n  const refetch = useCallback((cb?: Callback) => {\n    onRefetchCallback.current = cb\n    setPoll(true)\n  }, [])\n\n  return {\n    value: balanceQuery.data ?? new BigNumber(0),\n    loading: balanceQuery.isLoading || balanceQuery.isRefetching || poll,\n    error: balanceQuery.error || balanceQuery.isRefetchError || !balanceQuery.data,\n    refetch,\n  }\n}\n\nasync function updateBalance(\n  token: string,\n  connected: boolean,\n  contract: Contract | undefined,\n  address: string | null,\n  decimals: number,\n) {\n  if (!token || !connected || !contract || !address) return new BigNumber(0)\n  const _bal = await contract.methods.balanceOf(address).call({\n    from: address,\n  })\n  const balance = toTokenAmount(new BigNumber(_bal.toString()), decimals)\n\n  return balance\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/contracts/useVaultManager.ts",
    "content": "import { useCallback, useState } from 'react'\nimport { useQuery } from '@apollo/client'\nimport BigNumber from 'bignumber.js'\nimport { useAtomValue } from 'jotai'\n\nimport { toTokenAmount } from '@utils/calculations'\nimport { OSQUEETH_DECIMALS } from '../../constants/'\nimport { VAULTS_QUERY, VAULTS_SUBSCRIPTION } from '../../queries/squeeth/vaultsQuery'\nimport { Vaults } from '../../queries/squeeth/__generated__/Vaults'\nimport { squeethClient } from '../../utils/apollo-client'\nimport { addressAtom, networkIdAtom } from 'src/state/wallet/atoms'\nimport useAppEffect from '@hooks/useAppEffect'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { usePrevious } from 'react-use'\n\n/**\n * get user vaults.\n * @param token token address\n * @param refetchIntervalSec refetch interval in seconds\n * @returns {Vault[]}\n */\nexport const useVaultManager = () => {\n  const address = useAtomValue(addressAtom)\n  const networkId = useAtomValue(networkIdAtom)\n  const [isPolling, setIsPolling] = useState(false)\n\n  const { data, loading, subscribeToMore, startPolling, stopPolling } = useQuery<Vaults>(VAULTS_QUERY, {\n    client: squeethClient[networkId],\n    fetchPolicy: 'cache-and-network',\n    variables: {\n      ownerId: address ?? '',\n    },\n  })\n\n  const currentVault = data?.vaults.find((vault) => new BigNumber(vault.collateralAmount).isGreaterThan(0))\n  const prevVault = usePrevious(currentVault)\n\n  const updateVault = useCallback(() => {\n    setIsPolling(true)\n  }, [])\n\n  useAppEffect(() => {\n    if (isPolling && !prevVault && !currentVault) {\n      startPolling(500)\n    } else if (\n      isPolling &&\n      (new BigNumber(prevVault?.shortAmount).isEqualTo(new BigNumber(currentVault?.shortAmount)) ||\n        new BigNumber(prevVault?.collateralAmount).isEqualTo(new BigNumber(currentVault?.collateralAmount)))\n    ) {\n      startPolling(500)\n    } else {\n      stopPolling()\n      setIsPolling(false)\n    }\n  }, [\n    currentVault?.shortAmount.toString(),\n    currentVault?.collateralAmount.toString(),\n    isPolling,\n    prevVault?.shortAmount.toString(),\n    prevVault?.collateralAmount.toString(),\n    startPolling,\n    stopPolling,\n  ])\n\n  useAppEffect(() => {\n    subscribeToMore({\n      document: VAULTS_SUBSCRIPTION,\n      variables: {\n        ownerId: address ?? '',\n      },\n      updateQuery(prev, { subscriptionData }) {\n        if (!subscriptionData.data || subscriptionData.data.vaults.length === data?.vaults.length) return prev\n        const newVaults = subscriptionData.data.vaults\n        return { vaults: newVaults }\n      },\n    })\n  }, [address, subscribeToMore, data?.vaults.length])\n\n  const vaultsData = data?.vaults\n    .filter((v) => {\n      return new BigNumber(v?.collateralAmount ?? 0).gt(0)\n    })\n    .map(({ id, NftCollateralId, collateralAmount, shortAmount, operator }) => ({\n      id,\n      NFTCollateralId: NftCollateralId,\n      collateralAmount: toTokenAmount(new BigNumber(collateralAmount), 18),\n      shortAmount: toTokenAmount(new BigNumber(shortAmount), OSQUEETH_DECIMALS),\n      operator,\n    }))\n\n  return useAppMemo(\n    () => ({ vaults: vaultsData, loading: loading || isPolling, updateVault }),\n    [vaultsData, loading, isPolling, updateVault],\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/contracts/useWeth.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { useState } from 'react'\nimport { Contract } from 'web3-eth-contract'\nimport { useAtomValue } from 'jotai'\n\nimport wethAbi from '../../abis/weth.json'\nimport { fromTokenAmount } from '@utils/calculations'\nimport { useHandleTransaction } from 'src/state/wallet/hooks'\nimport { addressAtom, web3Atom } from 'src/state/wallet/atoms'\nimport { addressesAtom } from 'src/state/positions/atoms'\nimport useAppEffect from '@hooks/useAppEffect'\n\n/**\n * Hook to interact with WETH contract\n */\nexport const useWeth = () => {\n  const [contract, setContract] = useState<Contract>()\n\n  const web3 = useAtomValue(web3Atom)\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const { weth } = useAtomValue(addressesAtom)\n\n  useAppEffect(() => {\n    if (!web3 || !weth) return\n    setContract(new web3.eth.Contract(wethAbi as any, weth))\n  }, [web3, weth])\n\n  /**\n   *\n   * Wrap ETH to WETH\n   * @param amount - Amount to wrap\n   * @returns\n   */\n  const wrap = (amount: BigNumber): Promise<any> => {\n    if (!contract || !address) return Promise.resolve()\n\n    const _amount = fromTokenAmount(amount, 18)\n    return handleTransaction(\n      contract.methods.deposit().send({\n        from: address,\n        value: _amount,\n      }),\n    )\n  }\n\n  // const getAllowance = async (spenderAddress: string) => {\n  //   if (!contract || !address) return\n\n  //   const allowance = await contract.methods.allowance(address, spenderAddress).call()\n  //   retur(new BigNumber(allowance.toString()), 18)\n  // }\n\n  return {\n    wrap,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/payOffGraph/useCrabVaultPayoff.ts",
    "content": "import useShortParams from './useShortParams'\n\nexport default function useCrabVaultPayoff(ethPrice: number, collatRatio: number) {\n  const { markRatio, initialCollat, depositValue, cuNF0, cuNF14, cuNF28, ethPrices } = useShortParams(\n    ethPrice,\n    collatRatio,\n  )\n\n  const payout0 = ethPrices.map((p) => {\n    return (\n      ((-(cuNF0 + (initialCollat - 2 * cuNF0 * ethPrice) / ethPrice) * p ** 2 * markRatio +\n        (initialCollat + ((initialCollat - 2 * cuNF0 * ethPrice) / ethPrice) * markRatio * ethPrice) * p) /\n        depositValue -\n        1) *\n      100\n    ).toFixed(2)\n  })\n\n  const payout14 = ethPrices.map((p) => {\n    return (\n      ((-(cuNF14 + (initialCollat - 2 * cuNF14 * ethPrice) / ethPrice) * p ** 2 * markRatio +\n        (initialCollat + ((initialCollat - 2 * cuNF14 * ethPrice) / ethPrice) * markRatio * ethPrice) * p) /\n        depositValue -\n        1) *\n      100\n    ).toFixed(2)\n  })\n\n  const payout28 = ethPrices.map((p) => {\n    return (\n      ((-(cuNF28 + (initialCollat - 2 * cuNF28 * ethPrice) / ethPrice) * p ** 2 * markRatio +\n        (initialCollat + ((initialCollat - 2 * cuNF28 * ethPrice) / ethPrice) * markRatio * ethPrice) * p) /\n        depositValue -\n        1) *\n      100\n    ).toFixed(2)\n  })\n\n  return {\n    ethPrices,\n    payout0,\n    payout14,\n    payout28,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/payOffGraph/useShortParams.ts",
    "content": "import { useAtomValue } from 'jotai'\nimport { indexAtom, markAtom } from 'src/state/controller/atoms'\n\nexport default function useShortParams(ethPrice: number, collatRatio: number) {\n  const squeethIndex = ethPrice ** 2\n  const mark = useAtomValue(markAtom)\n  const index = useAtomValue(indexAtom)\n  const markRatio = Number(mark.div(index).toString())\n  const squeethMark = squeethIndex * markRatio\n  const dailyNormFactor = Math.exp((-1 * Math.log(markRatio)) / 17.5)\n  const initialCollat = collatRatio * ethPrice\n  const depositValue = initialCollat * ethPrice - squeethMark\n\n  const cuNF0 = dailyNormFactor ** 0\n  const cuNF1 = dailyNormFactor ** 1\n  const cuNF14 = dailyNormFactor ** 14\n  const cuNF28 = dailyNormFactor ** 28\n\n  const getEthPrices = () => {\n    let inc = Math.floor(ethPrice / 2)\n    return Array(120)\n      .fill(0)\n      .map((_, i) => {\n        if (i === 0) return inc\n        inc += 30\n        return inc\n      })\n  }\n  const getCrabEthPrices = () => {\n    let inc = Math.floor(ethPrice / 2)\n    return Array(100)\n      .fill(0)\n      .map((_, i) => {\n        if (i === 0) return inc\n        inc += 30\n        return inc\n      })\n  }\n\n  return {\n    squeethIndex,\n    markRatio,\n    squeethMark,\n    initialCollat,\n    depositValue,\n    cuNF0,\n    cuNF1,\n    cuNF14,\n    cuNF28,\n    ethPrices: getEthPrices(),\n    crabEthPrices: getCrabEthPrices(),\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/payOffGraph/useSqueethShortPayOffGraph.ts",
    "content": "import useShortParams from './useShortParams'\n\nexport default function useSqueethShortPayOffGraph(ethPrice: number, collatRatio: number) {\n  const { markRatio, initialCollat, depositValue, cuNF0, cuNF1, cuNF14, cuNF28, ethPrices, crabEthPrices } =\n    useShortParams(ethPrice, collatRatio)\n\n  const payout0 = ethPrices.map((p) => {\n    return (((-1 * cuNF0 * p ** 2 * markRatio + initialCollat * p) / depositValue - 1) * 100).toFixed(2)\n  })\n\n  const payout1 = crabEthPrices.map((p) => {\n    return (((-1 * cuNF1 * p ** 2 * markRatio + initialCollat * p) / depositValue - 1) * 100).toFixed(2)\n  })\n\n  const payout14 = ethPrices.map((p) => {\n    return (((-1 * cuNF14 * p ** 2 * markRatio + initialCollat * p) / depositValue - 1) * 100).toFixed(2)\n  })\n\n  const payout28 = ethPrices.map((p) => {\n    return (((-1 * cuNF28 * p ** 2 * markRatio + initialCollat * p) / depositValue - 1) * 100).toFixed(2)\n  })\n\n  return {\n    ethPrices,\n    payout0,\n    payout1,\n    payout14,\n    payout28,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useAmplitude.ts",
    "content": "import { Networks } from '../types'\nimport { trackEvent } from '@utils/amplitude'\nimport { useAtomValue } from 'jotai'\nimport { useCallback } from 'react'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\n\nconst useAmplitude = () => {\n  const networkId = useAtomValue(networkIdAtom)\n\n  const track = useCallback(\n    (eventName: string, eventProps?: Record<string, unknown>) => {\n      if (networkId === Networks.MAINNET) {\n        return trackEvent(eventName, eventProps)\n      }\n      console.log(`Analytics: ${eventName}`, JSON.stringify(eventProps))\n    },\n    [networkId],\n  )\n\n  return {\n    track,\n  }\n}\n\nexport default useAmplitude\n"
  },
  {
    "path": "packages/frontend/src/hooks/useAppCallback.tsx",
    "content": "import stringifyDeps from '@utils/stringifyDeps'\nimport { useCallback } from 'react'\nimport { DependencyList } from 'react'\n\nexport default function useAppCallback<T extends (...args: any[]) => any>(\n  callback: T,\n  deps: DependencyList,\n  lengthAsArrDep?: boolean,\n) {\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  return useCallback(callback, stringifyDeps(deps, lengthAsArrDep) ?? [])\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useAppEffect.tsx",
    "content": "import stringifyDeps from '@utils/stringifyDeps'\nimport { useEffect } from 'react'\nimport { DependencyList } from 'react'\nimport { EffectCallback } from 'react'\n\nexport default function useAppEffect(effect: EffectCallback, deps?: DependencyList, lengthAsArrDep?: boolean) {\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  useEffect(effect, stringifyDeps(deps, lengthAsArrDep))\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useAppMemo.tsx",
    "content": "import stringifyDeps from '@utils/stringifyDeps'\nimport { useMemo } from 'react'\nimport { DependencyList } from 'react'\n\nexport default function useAppMemo<T>(factory: () => T, deps?: DependencyList, lengthAsArrDep?: boolean) {\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  return useMemo(factory, stringifyDeps(deps, lengthAsArrDep))\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useAsyncMemo.tsx",
    "content": "import { useEffect, useMemo, useState } from 'react'\n\nexport function useAsyncMemo<T>(\n  callback: () => Promise<T>,\n  init: T,\n  dependencies: any[] = [],\n  onError?: (e: Error) => void,\n): T {\n  const [output, setOutput] = useState<T>(init)\n\n  // eslint-disable-next-line\n  const _callback = useMemo(callback, dependencies)\n\n  useEffect(() => {\n    let isNotCancelled = true\n\n    _callback.then((payload) => {\n      if (isNotCancelled) {\n        setOutput(payload)\n      }\n    })\n\n    return () => {\n      isNotCancelled = false\n    }\n  }, [_callback])\n\n  useEffect(() => {\n    _callback.catch(onError)\n  }, [_callback, onError])\n\n  return output\n}\n\nexport default useAsyncMemo\n"
  },
  {
    "path": "packages/frontend/src/hooks/useBullHedgeHistory.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport BULL_REBALANCE_QUERY from '@queries/squeeth/bullHedgeQuery'\nimport { bullHedges } from '@queries/squeeth/__generated__/bullHedges'\nimport { networkIdAtom } from '@state/wallet/atoms'\nimport { BullRebalanceType } from '../types'\nimport { squeethClient } from '@utils/apollo-client'\nimport { useAtomValue } from 'jotai'\nimport { useMemo } from 'react'\n\nexport const useBullHedgeHistory = () => {\n  const networkId = useAtomValue(networkIdAtom)\n\n  const { data, loading } = useQuery<bullHedges>(BULL_REBALANCE_QUERY, {\n    fetchPolicy: 'cache-and-network',\n    client: squeethClient[networkId],\n  })\n\n  const uiData = useMemo(() => {\n    if (loading || !data) return []\n\n    const fullRebalances = data.fullRebalances.map((tx) => ({\n      tx: tx.id,\n      type: BullRebalanceType.FULL_REBALANCE,\n      id: tx.id,\n      wPowerPerpAmount: tx.wPowerPerpAmount,\n      isDepositingInCrab: tx.isDepositingInCrab,\n      timestamp: tx.timestamp,\n      isSellingUsdc: undefined,\n    }))\n\n    const leverageRebalances = data.leverageRebalances.map((tx) => ({\n      tx: tx.id,\n      type: BullRebalanceType.LEVERAGE_REBALANCE,\n      id: tx.id,\n      isSellingUsdc: tx.isSellingUsdc,\n      usdcAmount: tx.usdcAmount,\n      timestamp: tx.timestamp,\n      isDepositingInCrab: undefined,\n    }))\n\n    return [...fullRebalances, ...leverageRebalances].sort((a, b) => b.timestamp - a.timestamp)\n  }, [data, loading])\n\n  return {\n    loading,\n    transactions: uiData,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useBullPosition/index.ts",
    "content": "export { useBullPosition } from './useBullPosition'\n"
  },
  {
    "path": "packages/frontend/src/hooks/useBullPosition/mocks.ts",
    "content": "// Mocks Placeholder\n\nexport const testMock = null\n"
  },
  {
    "path": "packages/frontend/src/hooks/useBullPosition/useBullPosition.ts",
    "content": "import { BIG_ZERO } from '../../constants'\nimport { useEffect, useState } from 'react'\nimport { CrabStrategyV2TxType } from '../../types'\nimport { useAtomValue, useSetAtom } from 'jotai'\nimport useAppCallback from '../useAppCallback'\nimport useAppMemo from '../useAppMemo'\nimport BigNumber from 'bignumber.js'\nimport {\n  bullCurrentETHPositionAtom,\n  bullDepositedETHAtom,\n  bullDepositedUSDCAtom,\n  bullEthPnlAtom,\n  bullEthPnlPerctAtom,\n  bullPositionLoadedAtom,\n  isBullPositionRefetchingAtom,\n  isBullReadyAtom,\n  bullFirstDepositTimestampAtom,\n} from '@state/bull/atoms'\nimport { useUserBullTxHistory } from '@hooks/useUserBullTxHistory'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport { addressesAtom } from '@state/positions/atoms'\n\n/*\n  depositedEth = Sum of deposited ethAmount - Sum of withdrawn ethAmount\n  depositedUsd = Sum of deposited ethUsed - Sum of withdrawn ethUsd\n  minCurrentEth = currentEth \n  minCurrentUsd = currentEth * indexPrice\n  minPnlUsd = minCurrentUsd - depositedUsd\n  minPnL = minPnlUsd / depositedUsd * 100\n*/\nexport const useBullPosition = (user: string) => {\n  const { bullStrategy } = useAtomValue(addressesAtom)\n  const { refetch } = useTokenBalance(bullStrategy)\n\n  const [txToSearch, setTxToSearch] = useState<string | undefined>(undefined)\n\n  const isBullReady = useAtomValue(isBullReadyAtom)\n  const bullCurrentEthValue = useAtomValue(bullCurrentETHPositionAtom)\n\n  const setEthPnl = useSetAtom(bullEthPnlAtom)\n  const setEthPnlPerct = useSetAtom(bullEthPnlPerctAtom)\n  const setDepositedEth = useSetAtom(bullDepositedETHAtom)\n  const setDepositedUsdc = useSetAtom(bullDepositedUSDCAtom)\n  const setPositionLoaded = useSetAtom(bullPositionLoadedAtom)\n  const setIsPositionRefetching = useSetAtom(isBullPositionRefetchingAtom)\n  const setBullFirstDepositTimestamp = useSetAtom(bullFirstDepositTimestampAtom)\n\n  const { loading: txHistoryLoading, data: txHistoryData, startPolling, stopPolling } = useUserBullTxHistory(user, true)\n\n  const { remainingDepositEth: depositedEth, remainingDepositUsd: depositedUsd } = useAppMemo(() => {\n    if (txHistoryLoading || !txHistoryData) {\n      return { remainingDepositUsd: BIG_ZERO, remainingDepositEth: BIG_ZERO }\n    }\n\n    const { totalSharesDeposited, totalSharesWithdrawn, totalUSDDeposit, totalETHDeposit } = txHistoryData?.reduce(\n      (acc, tx) => {\n        if (tx.type === CrabStrategyV2TxType.FLASH_DEPOSIT) {\n          acc.totalSharesDeposited = acc.totalSharesDeposited.plus(tx.bullAmount)\n          acc.totalUSDDeposit = acc.totalUSDDeposit.plus(tx.ethUsdValue)\n          acc.totalETHDeposit = acc.totalETHDeposit.plus(tx.ethAmount)\n        } else if (tx.type === CrabStrategyV2TxType.FLASH_WITHDRAW) {\n          acc.totalSharesWithdrawn = acc.totalSharesWithdrawn.plus(tx.bullAmount)\n        }\n\n        return acc\n      },\n      {\n        totalSharesDeposited: BIG_ZERO,\n        totalSharesWithdrawn: BIG_ZERO,\n        totalUSDDeposit: BIG_ZERO,\n        totalETHDeposit: BIG_ZERO,\n      },\n    )\n\n    const remainingShares = new BigNumber(1).minus(totalSharesWithdrawn.div(totalSharesDeposited))\n    const remainingDepositUsd = remainingShares.multipliedBy(totalUSDDeposit)\n    const remainingDepositEth = remainingShares.multipliedBy(totalETHDeposit)\n\n    return { remainingDepositUsd, remainingDepositEth }\n  }, [txHistoryData, txHistoryLoading])\n\n  const setPnL = useAppCallback(() => {\n    const _ethPnl = bullCurrentEthValue.minus(depositedEth)\n    const _ethPnlInPerct = bullCurrentEthValue.dividedBy(depositedEth).minus(1).times(100)\n    setEthPnl(_ethPnl)\n    setEthPnlPerct(_ethPnlInPerct)\n    setDepositedEth(depositedEth)\n    setDepositedUsdc(depositedUsd)\n    setBullFirstDepositTimestamp(txHistoryData[0]?.timestamp)\n    setPositionLoaded(true)\n  }, [bullCurrentEthValue, depositedEth, depositedUsd, txHistoryData])\n\n  useEffect(() => {\n    if (!txToSearch) stopPolling()\n\n    const match = txHistoryData?.find((tx) => tx.id.toLowerCase() === txToSearch)\n    if (match) {\n      refetch(() => {\n        setIsPositionRefetching(false)\n      })\n      setTxToSearch(undefined)\n    }\n  }, [refetch, setIsPositionRefetching, stopPolling, txHistoryData, txToSearch])\n\n  const pollForNewTx = useAppCallback(\n    (tx: string) => {\n      setIsPositionRefetching(true)\n      setTxToSearch(tx)\n      startPolling(500)\n    },\n    [setIsPositionRefetching, startPolling],\n  )\n\n  useEffect(() => {\n    if (isBullReady && !txHistoryLoading) setPnL()\n  }, [isBullReady, setPnL, txHistoryLoading])\n\n  return {\n    pollForNewTx,\n  }\n}\n\n/*\nAC:\nloading\n  should be true if either transaction history or crab is loading.\n  should be false if both of them are loaded\n\ndepositedEth and depositedUsd\n  should be zero if transaction history is loading.\n  should be caculated as correct values if transaction history is loaded\n\nminCurrentEth and minCurrentUsd\n  should be zero if either transaction history or crab is loading.\n  should be caculated as correct values if both of them are loaded\n\nminPnL and minPnlUsd\n  same as above\n\n\nDependencies:\n  crabLoadingAtom\n  currentEthValueAtom\n  indexAtom\n  useUserCrabTxHistory\n*/\n"
  },
  {
    "path": "packages/frontend/src/hooks/useCopyClipboard.ts",
    "content": "import copy from 'copy-to-clipboard'\nimport { useCallback, useEffect, useState } from 'react'\n\nexport default function useCopyClipboard(timeout = 500): [boolean, (toCopy: string) => void] {\n  const [isCopied, setIsCopied] = useState(false)\n\n  const staticCopy = useCallback((text) => {\n    const didCopy = copy(text)\n    setIsCopied(didCopy)\n  }, [])\n\n  useEffect(() => {\n    if (isCopied) {\n      const hide = setTimeout(() => {\n        setIsCopied(false)\n      }, timeout)\n\n      return () => {\n        clearTimeout(hide)\n      }\n    }\n    return undefined\n  }, [isCopied, setIsCopied, timeout])\n\n  return [isCopied, staticCopy]\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useCrabAuctionHistory.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport { useAtomValue } from 'jotai'\n\nimport { crabAuctions } from '../queries/squeeth/__generated__/crabAuctions'\nimport CRAB_AUCTION_QUERY from '../queries/squeeth/crabAuctionQuery'\nimport { toTokenAmount } from '@utils/calculations'\nimport { WETH_DECIMALS, OSQUEETH_DECIMALS } from '../constants'\nimport { squeethClient } from '@utils/apollo-client'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\n\nexport const useCrabStrategyTxHistory = () => {\n  const networkId = useAtomValue(networkIdAtom)\n  const { data, loading } = useQuery<crabAuctions>(CRAB_AUCTION_QUERY, {\n    fetchPolicy: 'cache-and-network',\n    client: squeethClient[networkId],\n  })\n\n  const uiData = data?.crabAuctions.map((tx) => {\n    const ethAmount = toTokenAmount(tx.ethAmount, WETH_DECIMALS)\n    const oSqueethAmount = toTokenAmount(tx.squeethAmount, OSQUEETH_DECIMALS)\n\n    return {\n      ...tx,\n      ethAmount,\n      oSqueethAmount,\n    }\n  })\n\n  return {\n    loading,\n    data: uiData,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useCrabPosition/index.ts",
    "content": "export { useCrabPosition } from './useCrabPosition'\n"
  },
  {
    "path": "packages/frontend/src/hooks/useCrabPosition/mocks.ts",
    "content": "import { atom } from 'jotai'\nimport BigNumber from 'bignumber.js'\nimport { ZERO_ADDR } from '@constants/address'\n\nexport const mockedCrabLoadingAtom = atom(true)\nexport const mockedCrabPositionValueLoadingAtom = atom(true)\n\nexport const mockedCurrentEthValueAtom = atom(new BigNumber(31.502381757505464))\n\nexport const mockedIndexAtom = atom(new BigNumber(1.096035041905758e25))\n\nexport const mockedUserCrabTxHistoryData = [\n  {\n    __typename: 'CrabStrategyTx' as const,\n    ethAmount: new BigNumber(29.686306442273224),\n    id: '0x468ab39dedabebb84e8245dd4a5b2e74a7f7866bad58b2cf9abf7410baa01438',\n    lpAmount: new BigNumber(167.1950754262323),\n    timestamp: '1646839085',\n    type: 'FLASH_DEPOSIT',\n    wSqueethAmount: '93257202421547735264',\n    oSqueethAmount: new BigNumber(93.25720242154773),\n    ethUsdValue: new BigNumber(81181.4599647523),\n    txTitle: 'Flash Deposit',\n  },\n]\n\nexport const addressesAtom = atom({ zero: '0x000000000000000000000000000000000000000' })\n"
  },
  {
    "path": "packages/frontend/src/hooks/useCrabPosition/useCrabPosition.test.tsx",
    "content": "import { renderHook } from '@testing-library/react-hooks'\nimport { useCrabPosition } from './useCrabPosition'\nimport { Wrapper, writeAtom } from '@utils/atomTester'\nimport { mockedCrabLoadingAtom, mockedUserCrabTxHistoryData, mockedCrabPositionValueLoadingAtom } from './mocks'\nimport { useUserCrabTxHistory } from '@hooks/useUserCrabTxHistory'\nimport { act } from 'react-dom/test-utils'\n\njest.mock('src/state/crab/atoms', () => ({\n  crabLoadingAtom: jest.requireActual('./mocks').mockedCrabLoadingAtom,\n  currentCrabPositionValueInETHAtom: jest.requireActual('./mocks').mockedCurrentEthValueAtom,\n  crabPositionValueLoadingAtom: jest.requireActual('./mocks').mockedCrabPositionValueLoadingAtom,\n}))\n\njest.mock('src/state/controller/atoms', () => ({\n  indexAtom: jest.requireActual('./mocks').mockedIndexAtom,\n}))\n\njest.mock('src/state/positions/atoms', () => ({\n  addressesAtom: jest.requireActual('./mocks').addressesAtom,\n}))\n\njest.mock('../useUserCrabTxHistory', () => ({\n  useUserCrabTxHistory: jest.fn(),\n}))\n\nafterEach(() => {\n  jest.clearAllMocks()\n\n  // Reset crab loading\n  act(() => {\n    writeAtom(mockedCrabLoadingAtom, true)\n    writeAtom(mockedCrabPositionValueLoadingAtom, true)\n  })\n})\n\ndescribe('useCrabPosition', () => {\n  const mockTransactionHistory = (mockedUserCrabTxHistory: Partial<ReturnType<typeof useUserCrabTxHistory>>) => {\n    ;(useUserCrabTxHistory as jest.Mock).mockReturnValue(mockedUserCrabTxHistory)\n  }\n\n  const setup = () => {\n    return renderHook(() => useCrabPosition(''), { wrapper: Wrapper })\n  }\n\n  describe('loading', () => {\n    it('returns true if crab is loading', () => {\n      mockTransactionHistory({ loading: false, data: mockedUserCrabTxHistoryData })\n\n      const { result } = setup()\n\n      expect(result.current.loading).toBe(true)\n    })\n\n    it('returns true if transaction history is loading', () => {\n      mockTransactionHistory({ loading: true, data: [] })\n\n      const { result, rerender } = setup()\n\n      // Make sure crab is not loading\n      act(() => {\n        writeAtom(mockedCrabLoadingAtom, false)\n      })\n\n      rerender()\n\n      expect(result.current.loading).toBe(true)\n    })\n\n    it('returns false if crab and transaction history are loaded', () => {\n      mockTransactionHistory({ loading: false, data: mockedUserCrabTxHistoryData })\n\n      const { result, rerender } = setup()\n\n      act(() => {\n        writeAtom(mockedCrabLoadingAtom, false)\n      })\n      rerender()\n\n      expect(result.current.loading).toBe(false)\n    })\n  })\n\n  describe('depositedEth and depositedUsd', () => {\n    it('returns 0 if user crab history is loading', () => {\n      mockTransactionHistory({ loading: true, data: [] })\n\n      const { result } = setup()\n\n      expect(result.current.depositedEth.toNumber()).toBe(0)\n      expect(result.current.depositedUsd.toNumber()).toBe(0)\n    })\n\n    it('returns correct value after user crab history is loaded', () => {\n      mockTransactionHistory({ loading: true, data: [] })\n\n      const { result, rerender } = setup()\n\n      mockTransactionHistory({ loading: false, data: mockedUserCrabTxHistoryData })\n      rerender()\n\n      expect(result.current.depositedEth.toNumber()).toBe(29.686306442273224)\n      expect(result.current.depositedUsd.toNumber()).toBe(81181.4599647523)\n    })\n  })\n\n  describe('minCurrentEth and minCurrentUsd', () => {\n    it('returns 0 if crab is loading', () => {\n      mockTransactionHistory({ loading: false, data: mockedUserCrabTxHistoryData })\n\n      const { result } = setup()\n\n      expect(result.current.minCurrentEth.toNumber()).toBe(0)\n      expect(result.current.minCurrentUsd.toNumber()).toBe(0)\n    })\n\n    it('returns 0 if user crab history is loading', () => {\n      mockTransactionHistory({ loading: true, data: [] })\n\n      const { result, rerender } = setup()\n\n      act(() => {\n        writeAtom(mockedCrabLoadingAtom, false)\n      })\n      rerender()\n\n      expect(result.current.minCurrentEth.toNumber()).toBe(0)\n      expect(result.current.minCurrentUsd.toNumber()).toBe(0)\n    })\n\n    it('returns correct value after crab and user crab history are loaded', () => {\n      mockTransactionHistory({ loading: true, data: [] })\n\n      const { result, rerender } = setup()\n\n      act(() => {\n        writeAtom(mockedCrabLoadingAtom, false)\n        writeAtom(mockedCrabPositionValueLoadingAtom, false)\n      })\n      rerender()\n\n      mockTransactionHistory({ loading: false, data: mockedUserCrabTxHistoryData })\n      rerender()\n\n      expect(result.current.minCurrentEth.toNumber()).toBe(31.502381757505464)\n      expect(result.current.minCurrentUsd.toNumber()).toBe(104293.1079889195)\n    })\n  })\n\n  describe('minPnL and minPnlUsd', () => {\n    it('returns 0 if crab is loading', () => {\n      mockTransactionHistory({ loading: false, data: mockedUserCrabTxHistoryData })\n\n      const { result } = setup()\n\n      expect(result.current.minPnL.toNumber()).toBe(0)\n      expect(result.current.minPnlUsd.toNumber()).toBe(0)\n    })\n\n    it('returns 0 if user crab history is loading', () => {\n      mockTransactionHistory({ loading: true, data: [] })\n\n      const { result, rerender } = setup()\n\n      act(() => {\n        writeAtom(mockedCrabLoadingAtom, false)\n      })\n      rerender()\n\n      expect(result.current.minPnL.toNumber()).toBe(0)\n      expect(result.current.minPnlUsd.toNumber()).toBe(0)\n    })\n\n    it('returns correct value after crab and user crab history are loaded', () => {\n      mockTransactionHistory({ loading: true, data: [] })\n\n      const { result, rerender } = setup()\n\n      act(() => {\n        writeAtom(mockedCrabLoadingAtom, false)\n        writeAtom(mockedCrabPositionValueLoadingAtom, false)\n      })\n      rerender()\n\n      mockTransactionHistory({ loading: false, data: mockedUserCrabTxHistoryData })\n      rerender()\n\n      expect(result.current.minPnL.toNumber()).toBe(28.469120947322093)\n      expect(result.current.minPnlUsd.toNumber()).toBe(23111.648024167196)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/frontend/src/hooks/useCrabPosition/useCrabPosition.ts",
    "content": "import { BIG_ZERO } from '../../constants'\nimport { useEffect, useState } from 'react'\nimport { useUserCrabTxHistory } from '../useUserCrabTxHistory'\nimport { useUserCrabV2TxHistory } from '../useUserCrabV2TxHistory'\nimport { CrabStrategyTxType, CrabStrategyV2TxType } from '../../types'\nimport { toTokenAmount } from '@utils/calculations'\nimport { useAtom, useAtomValue } from 'jotai'\nimport { indexAtom } from 'src/state/controller/atoms'\nimport useAppCallback from '../useAppCallback'\nimport useAppMemo from '../useAppMemo'\nimport {\n  crabLoadingAtom,\n  crabLoadingAtomV2,\n  crabPositionValueLoadingAtom,\n  crabPositionValueLoadingAtomV2,\n  crabQueuedInEthAtom,\n  currentCrabPositionValueInETHAtom,\n  currentCrabPositionValueInETHAtomV2,\n} from 'src/state/crab/atoms'\nimport BigNumber from 'bignumber.js'\n\n/*\n  depositedEth = Sum of deposited ethAmount - Sum of withdrawn ethAmount\n  depositedUsd = Sum of deposited ethUsed - Sum of withdrawn ethUsd\n  minCurrentEth = currentEth \n  minCurrentUsd = currentEth * indexPrice\n  minPnlUsd = minCurrentUsd - depositedUsd\n  minPnL = minPnlUsd / depositedUsd * 100\n*/\nexport const useCrabPosition = (user: string) => {\n  const crabLoading = useAtomValue(crabLoadingAtom)\n  const isCrabPositionValueLoading = useAtomValue(crabPositionValueLoadingAtom)\n  const currentEthValue = useAtomValue(currentCrabPositionValueInETHAtom)\n\n  const { loading: txHistoryLoading, data: txHistoryData } = useUserCrabTxHistory(user)\n\n  const index = useAtomValue(indexAtom)\n  const ethIndexPrice = toTokenAmount(index, 18).sqrt()\n\n  const [minCurrentEth, setMinCurrentEth] = useState(BIG_ZERO)\n  const [minCurrentUsd, setMinCurrentUsd] = useState(BIG_ZERO)\n  const [minPnlUsd, setMinPnlUsd] = useState(BIG_ZERO)\n  const [minPnL, setMinPnL] = useState(BIG_ZERO)\n\n  const { depositedEth, usdAmount: depositedUsd } = useAppMemo(() => {\n    if (txHistoryLoading || !txHistoryData) return { depositedEth: BIG_ZERO, usdAmount: BIG_ZERO }\n\n    const { depositedEth, usdAmount } = txHistoryData?.reduce(\n      (acc, tx) => {\n        if (tx.type === CrabStrategyTxType.FLASH_DEPOSIT) {\n          acc.depositedEth = acc.depositedEth.plus(tx.ethAmount)\n          acc.lpAmount = acc.lpAmount.plus(tx.lpAmount)\n          acc.usdAmount = acc.usdAmount.plus(tx.ethUsdValue)\n        } else if (tx.type === CrabStrategyTxType.FLASH_WITHDRAW) {\n          acc.depositedEth = acc.depositedEth.minus(tx.ethAmount)\n          acc.lpAmount = acc.lpAmount.minus(tx.lpAmount)\n          acc.usdAmount = acc.usdAmount.minus(tx.ethUsdValue)\n        }\n        // Reset to zero if position closed\n        if (acc.lpAmount.isZero()) {\n          acc.depositedEth = BIG_ZERO\n          acc.usdAmount = BIG_ZERO\n        }\n\n        return acc\n      },\n      { depositedEth: BIG_ZERO, lpAmount: BIG_ZERO, usdAmount: BIG_ZERO },\n    )\n\n    return { depositedEth, usdAmount }\n  }, [txHistoryData, txHistoryLoading])\n\n  const calculateCurrentValue = useAppCallback(async () => {\n    const minCurrentUsd = currentEthValue.times(ethIndexPrice)\n    const minPnlUsd = minCurrentUsd.minus(depositedUsd)\n\n    setMinCurrentEth(currentEthValue)\n    setMinCurrentUsd(minCurrentUsd)\n\n    setMinPnlUsd(minPnlUsd)\n    setMinPnL(minPnlUsd.div(depositedUsd).times(100))\n  }, [currentEthValue, depositedUsd, ethIndexPrice])\n\n  useEffect(() => {\n    if (crabLoading || txHistoryLoading || isCrabPositionValueLoading) return\n    calculateCurrentValue()\n  }, [calculateCurrentValue, crabLoading, isCrabPositionValueLoading, txHistoryLoading])\n\n  return {\n    depositedEth,\n    depositedUsd,\n    minCurrentEth,\n    minCurrentUsd,\n    minPnL,\n    minPnlUsd,\n    loading: crabLoading || txHistoryLoading,\n  }\n}\n\n/*\n  depositedEth = Sum of deposited ethAmount - Sum of withdrawn ethAmount\n  depositedUsd = Sum of deposited ethUsed - Sum of withdrawn ethUsd\n  minCurrentEth = currentEth \n  minCurrentUsd = currentEth * indexPrice\n  minPnlUsd = minCurrentUsd - depositedUsd\n  minPnL = minPnlUsd / depositedUsd * 100\n*/\nexport const useCrabPositionV2 = (user: string) => {\n  const crabLoading = useAtomValue(crabLoadingAtomV2)\n  const [crabPositionRefetching, setCrabPositionRefetching] = useState(false)\n  const isCrabPositionValueLoading = useAtomValue(crabPositionValueLoadingAtomV2)\n  const currentEthValue = useAtomValue(currentCrabPositionValueInETHAtomV2)\n  const [txToSearch, setTxToSearch] = useState<string | undefined>(undefined)\n  const currentQueuedCrabEth = useAtomValue(crabQueuedInEthAtom)\n\n  const { loading: txHistoryLoading, data: txHistoryData, startPolling, stopPolling } = useUserCrabV2TxHistory(user)\n\n  const index = useAtomValue(indexAtom)\n  const ethIndexPrice = toTokenAmount(index, 18).sqrt()\n\n  const [minCurrentEth, setMinCurrentEth] = useState(BIG_ZERO)\n  const [minCurrentUsd, setMinCurrentUsd] = useState(BIG_ZERO)\n  const [minPnlUsd, setMinPnlUsd] = useState(BIG_ZERO)\n  const [minPnL, setMinPnL] = useState(BIG_ZERO)\n\n  const { remainingDepositEth: depositedEth, remainingDepositUsd: depositedUsd } = useAppMemo(() => {\n    console.log(txHistoryData, 'Crab')\n    if (txHistoryLoading || !txHistoryData || txHistoryData.length === 0) {\n      return { remainingDepositUsd: BIG_ZERO, remainingDepositEth: BIG_ZERO }\n    }\n\n    const { totalSharesDeposited, totalSharesWithdrawn, totalUSDDeposit, totalETHDeposit } = txHistoryData?.reduce(\n      (acc, tx) => {\n        if (\n          tx.type === CrabStrategyV2TxType.FLASH_DEPOSIT ||\n          tx.type === CrabStrategyV2TxType.DEPOSIT ||\n          tx.type === CrabStrategyV2TxType.DEPOSIT_V1 ||\n          tx.type === CrabStrategyTxType.DEPOSIT ||\n          tx.type === CrabStrategyV2TxType.OTC_DEPOSIT\n        ) {\n          acc.totalSharesDeposited = acc.totalSharesDeposited.plus(tx.lpAmount)\n          acc.totalUSDDeposit = acc.totalUSDDeposit.plus(tx.ethUsdValue)\n          acc.totalETHDeposit = acc.totalETHDeposit.plus(tx.ethAmount)\n        } else if (\n          tx.type === CrabStrategyV2TxType.FLASH_WITHDRAW ||\n          tx.type === CrabStrategyV2TxType.WITHDRAW ||\n          tx.type === CrabStrategyV2TxType.OTC_WITHDRAW\n        ) {\n          acc.totalSharesWithdrawn = acc.totalSharesWithdrawn.plus(tx.lpAmount)\n        }\n\n        return acc\n      },\n      {\n        totalSharesDeposited: BIG_ZERO,\n        totalSharesWithdrawn: BIG_ZERO,\n        totalUSDDeposit: BIG_ZERO,\n        totalETHDeposit: BIG_ZERO,\n      },\n    )\n\n    const remainingShares = new BigNumber(1).minus(totalSharesWithdrawn.div(totalSharesDeposited))\n    const remainingDepositUsd = remainingShares.multipliedBy(totalUSDDeposit)\n    const remainingDepositEth = remainingShares.multipliedBy(totalETHDeposit)\n\n    return { remainingDepositUsd, remainingDepositEth }\n  }, [txHistoryData, txHistoryLoading])\n\n  const calculateCurrentValue = useAppCallback(async () => {\n    const ethValue = currentEthValue.plus(currentQueuedCrabEth)\n    const minCurrentUsd = ethValue.times(ethIndexPrice)\n    const minPnlUsd = minCurrentUsd.minus(depositedUsd)\n\n    setMinCurrentEth(ethValue)\n    setMinCurrentUsd(minCurrentUsd)\n\n    setMinPnlUsd(minPnlUsd)\n    setMinPnL(minPnlUsd.div(depositedUsd).times(100))\n  }, [currentEthValue, currentQueuedCrabEth, depositedUsd, ethIndexPrice])\n\n  useEffect(() => {\n    if (crabLoading || txHistoryLoading || isCrabPositionValueLoading || crabPositionRefetching) {\n      return\n    }\n\n    calculateCurrentValue()\n  }, [calculateCurrentValue, crabLoading, isCrabPositionValueLoading, txHistoryLoading, crabPositionRefetching])\n\n  useEffect(() => {\n    if (!txToSearch) stopPolling()\n    const match = txHistoryData?.find((tx) => tx.id.toLowerCase() === txToSearch)\n    if (match) {\n      setCrabPositionRefetching(false)\n      setTxToSearch(undefined)\n    }\n  }, [setCrabPositionRefetching, stopPolling, txHistoryData, txToSearch])\n\n  const pollForNewTx = useAppCallback(\n    (tx: string) => {\n      setCrabPositionRefetching(true)\n      setTxToSearch(tx)\n      startPolling(500)\n    },\n    [setCrabPositionRefetching, startPolling],\n  )\n\n  return {\n    depositedEth,\n    depositedUsd,\n    minCurrentEth,\n    minCurrentUsd,\n    minPnL,\n    minPnlUsd,\n    loading: crabLoading || txHistoryLoading || crabPositionRefetching,\n    pollForNewTx,\n    firstDepositTimestamp: txHistoryData?.[0]?.timestamp,\n  }\n}\n\n/*\nAC:\nloading\n  should be true if either transaction history or crab is loading.\n  should be false if both of them are loaded\n\ndepositedEth and depositedUsd\n  should be zero if transaction history is loading.\n  should be caculated as correct values if transaction history is loaded\n\nminCurrentEth and minCurrentUsd\n  should be zero if either transaction history or crab is loading.\n  should be caculated as correct values if both of them are loaded\n\nminPnL and minPnlUsd\n  same as above\n\n\nDependencies:\n  crabLoadingAtom\n  currentEthValueAtom\n  indexAtom\n  useUserCrabTxHistory\n*/\n"
  },
  {
    "path": "packages/frontend/src/hooks/useCrabV2AuctionHistory.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport { useAtomValue } from 'jotai'\n\nimport { crabV2Auctions } from '../queries/squeeth/__generated__/crabV2Auctions'\nimport CRAB_V2_AUCTION_QUERY from '../queries/squeeth/crabV2AuctionQuery'\nimport { toTokenAmount } from '@utils/calculations'\nimport { WETH_DECIMALS, OSQUEETH_DECIMALS } from '../constants'\nimport { squeethClient } from '@utils/apollo-client'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\nimport { visibleStrategyHedgesAtom } from '@state/crab/atoms'\n\nexport const useCrabStrategyV2TxHistory = () => {\n  const networkId = useAtomValue(networkIdAtom)\n  const visibleHedges = useAtomValue(visibleStrategyHedgesAtom)\n  const { data, loading } = useQuery<crabV2Auctions>(CRAB_V2_AUCTION_QUERY, {\n    fetchPolicy: 'cache-and-network',\n    client: squeethClient[networkId],\n  })\n\n  const uiData = data?.hedgeOTCs!.map((tx) => {\n    const oSqueethAmount = toTokenAmount(tx.quantity, OSQUEETH_DECIMALS)\n    const clearingPrice = toTokenAmount(tx.clearingPrice, WETH_DECIMALS)\n    const ethAmount = oSqueethAmount.times(clearingPrice)\n\n    return {\n      ...tx,\n      ethAmount,\n      oSqueethAmount,\n    }\n  })\n\n  return {\n    loading,\n    data: uiData?.slice(0, visibleHedges),\n    showMore: (uiData ?? []).length > visibleHedges,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useENS.ts",
    "content": "import { useAtomValue } from 'jotai'\nimport { useEffect, useState } from 'react'\nimport { web3Atom } from 'src/state/wallet/atoms'\nimport { ethers } from 'ethers'\n\nexport function useENS(address: string | null | undefined) {\n  const [ensName, setENSName] = useState<string | null>()\n  const web3 = useAtomValue(web3Atom)\n\n  useEffect(() => {\n    async function resolveENS() {\n      if (address && web3.currentProvider) {\n        const provider = new ethers.providers.Web3Provider(web3.currentProvider as any)\n        const name = await provider.lookupAddress(address)\n        if (name) setENSName(name)\n      }\n    }\n    resolveENS()\n  }, [address, web3])\n\n  return { ensName }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useETHPrice.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { useQuery, useQueryClient } from 'react-query'\n\nimport { toTokenAmount } from '@utils/calculations'\nimport { ethPriceAtom, indexAtom } from 'src/state/controller/atoms'\nimport { useAtomValue } from 'jotai'\n\nconst ethPriceQueryKeys = {\n  currentEthPrice: () => ['currentEthPrice'],\n  onChainEthPrice: () => ['onChainEthPrice'],\n}\n\n/**\n * get token price by address.\n * @param token token address\n * @param refetchIntervalSec refetch interval in seconds\n * @returns {BigNumber} price denominated in USD\n */\nexport const useETHPrice = (refetchIntervalSec = 30) => {\n  const queryClient = useQueryClient()\n  const index = useAtomValue(indexAtom)\n\n  const ethPrice = useQuery(ethPriceQueryKeys.currentEthPrice(), () => getETHPriceCoingecko(), {\n    onError() {\n      queryClient.setQueryData(ethPriceQueryKeys.currentEthPrice(), toTokenAmount(index, 18).sqrt())\n    },\n    refetchInterval: refetchIntervalSec * 1000,\n    refetchOnWindowFocus: true,\n  })\n\n  return ethPrice.data ?? new BigNumber(0)\n}\n\n/**\n * Get's the onchain ETH price\n * @returns {BigNumber} price denominated in USD\n */\nexport const useOnChainETHPrice = () => {\n  const ethPrice = useAtomValue(ethPriceAtom)\n  return ethPrice\n}\n\nexport const getETHPriceCoingecko = async (): Promise<BigNumber> => {\n  const coin = 'ethereum'\n\n  const url = `https://api.coingecko.com/api/v3/simple/price?ids=${coin}&vs_currencies=usd`\n\n  const res = await fetch(url)\n  const priceStruct: { usd: number } = (await res.json())[coin.toLowerCase()]\n  if (priceStruct === undefined) throw new Error('Error getting ethPrice from Coingecko')\n  const price = priceStruct.usd\n  return new BigNumber(price)\n}\n\nexport const getHistoricEthPrice = async (dateString: string): Promise<BigNumber> => {\n  try {\n    const pair = 'ETH/USD'\n\n    const response = await fetch(\n      `/api/twelvedata?path=time_series&start_date=${dateString}&end_date=${dateString}&symbol=${pair}&interval=1min`,\n    ).then((res) => res.json())\n\n    if (response.status === 'error' || !response.values?.[0]?.close) {\n      return new BigNumber(0)\n    }\n\n    return new BigNumber(Number(response.values[0].close))\n  } catch (error) {\n    return new BigNumber(0)\n  }\n}\n\nexport const getHistoricEthPrices = async (timestamps: number[]) => {\n  if (timestamps.length === 0) {\n    return\n  }\n\n  try {\n    const timestampStr = timestamps.join(',')\n    const pair = 'ETH/USD'\n\n    const response = await (\n      await fetch(\n        `/api/historicalprice?timestamps=${timestampStr}&pair=${pair}&interval=1min&timezone=${\n          Intl.DateTimeFormat().resolvedOptions().timeZone\n        }`,\n      )\n    ).json()\n\n    if (response.status === 'error') {\n      // Return an object with all timestamps mapped to '0'\n      return timestamps.reduce((acc, timestamp) => {\n        acc[timestamp] = '0'\n        return acc\n      }, {} as Record<number, string>)\n    }\n\n    return response\n  } catch (error) {\n    // In case of any error, return an object with all timestamps mapped to '0'\n    return timestamps.reduce((acc, timestamp) => {\n      acc[timestamp] = '0'\n      return acc\n    }, {} as Record<number, string>)\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useExecuteOnce.ts",
    "content": "import { useCallback, useRef } from 'react'\n\nconst useExecuteOnce = (fn?: any) => {\n  const executedRef = useRef(false)\n\n  const executeFunction = useCallback(\n    (...params) => {\n      if (!executedRef.current) {\n        fn?.(...params)\n        executedRef.current = true\n      }\n    },\n    [fn],\n  )\n\n  const reset = () => (executedRef.current = false)\n\n  return [executeFunction, reset]\n}\n\nexport default useExecuteOnce\n"
  },
  {
    "path": "packages/frontend/src/hooks/useInterval.ts",
    "content": "import { useEffect, useRef } from 'react'\n\ntype Callback = () => void\n\nexport function useInterval(callback: Callback, delay: number) {\n  const savedCallback = useRef<Callback>()\n\n  // Remember the latest callback.\n  useEffect(() => {\n    savedCallback.current = callback\n  }, [callback])\n\n  // Set up the interval.\n  useEffect(() => {\n    function tick() {\n      savedCallback.current?.()\n    }\n    if (delay !== null) {\n      const id = setInterval(tick, delay)\n      return () => clearInterval(id)\n    }\n  }, [delay])\n}\n\nexport default useInterval\n"
  },
  {
    "path": "packages/frontend/src/hooks/useIntervalAsync.ts",
    "content": "import { useEffect, useRef } from 'react'\nimport { clearIntervalAsync, setIntervalAsync } from 'set-interval-async/dynamic'\n\ntype Callback = () => void\n\n/**\n * for calling async functions at intervals\n * @param callback the async callback function\n * @param interval, the interval in milliseconds, it must be at least 10ms\n * @returns {void}\n */\nexport function useIntervalAsync(callback: Callback, interval: number) {\n  const savedCallback = useRef<Callback>(callback)\n\n  if (interval < 10) {\n    throw new Error('Interval must be at least 10ms')\n  }\n\n  // if the provided function changes, change its reference\n  useEffect(() => {\n    if (typeof callback === 'function') {\n      savedCallback.current = callback\n    }\n  }, [callback])\n\n  useEffect(() => {\n    const timer = setIntervalAsync(savedCallback.current, interval)\n\n    return () => {\n      clearIntervalAsync(timer)\n    }\n  }, [interval])\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useNormHistory.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport { squeethClient } from '@utils/apollo-client'\n\nimport NORMHISTORY_QUERY from '../queries/squeeth/normHistoryQuery'\nimport { useEffect, useRef, useState } from 'react'\nimport { useAtomValue } from 'jotai'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\nimport {\n  normalizationFactorUpdates,\n  normalizationFactorUpdatesVariables,\n} from '@queries/squeeth/__generated__/normalizationFactorUpdates'\n\nexport const useNormHistory = () => {\n  const networkId = useAtomValue(networkIdAtom)\n  const lastId = useRef('')\n  const [normHistory, setNormHistory] = useState<any[]>([])\n  const [fetchingComplete, setFetchingComplete] = useState(false)\n  const { data, loading, refetch } = useQuery<normalizationFactorUpdates, normalizationFactorUpdatesVariables>(\n    NORMHISTORY_QUERY,\n    {\n      variables: {\n        lastID: '',\n      },\n      client: squeethClient[networkId],\n      fetchPolicy: 'cache-and-network',\n      notifyOnNetworkStatusChange: true,\n    },\n  )\n\n  useEffect(() => {\n    if (!loading) {\n      if (data && data['normalizationFactorUpdates'].length > 0) {\n        const normHistoryItems = normHistory\n        setNormHistory(\n          normHistoryItems\n            .concat(data['normalizationFactorUpdates'])\n            .filter((val, ind, self) => ind === self.findIndex((item) => item.id === val.id)),\n        )\n        lastId.current = data['normalizationFactorUpdates'][data['normalizationFactorUpdates'].length - 1].id\n\n        if (data['normalizationFactorUpdates'].length === 1000) {\n          refetch({ lastID: lastId.current })\n        } else {\n          setFetchingComplete(true)\n        }\n      } else {\n        setFetchingComplete(true)\n      }\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [loading])\n\n  return {\n    normHistory,\n    fetchingComplete,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useNormHistoryFromTime.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport { squeethClient } from '@utils/apollo-client'\nimport { NORMHISTORY_TIME_QUERY } from '../queries/squeeth/normHistoryQuery'\nimport { useEffect, useState } from 'react'\nimport { NormHistory } from '../types'\nimport { updateTimestampLiveVolDB } from '@utils/pricer'\nimport { useAtomValue } from 'jotai'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\n\nexport const useNormHistoryFromTime = (timestamps: number[]) => {\n  const networkId = useAtomValue(networkIdAtom)\n  const [timeIndex, setTimeIndex] = useState(0)\n  const [dataUpdated, setDataUpdated] = useState(true)\n  const { data, loading } = useQuery(NORMHISTORY_TIME_QUERY, {\n    variables: {\n      timestamp: timestamps[timeIndex],\n      timestampOnedayAfter: timestamps[timeIndex] + 24 * 60 * 60,\n    },\n    client: squeethClient[networkId],\n    fetchPolicy: 'cache-and-network',\n  })\n\n  useEffect(() => {\n    if (timestamps.length > 0) {\n      setDataUpdated(false)\n    }\n  }, [timestamps.length])\n\n  useEffect(() => {\n    if (!loading) {\n      if (timeIndex >= 0 && timeIndex < timestamps.length) {\n        ;(async () => {\n          const normFactors: NormHistory[] =\n            data && data['normalizationFactorUpdates'] ? data['normalizationFactorUpdates'] : []\n          if (normFactors.length > 0) {\n            const avgVol = normFactors.reduce((total, item) => {\n              const secondsElapsed = Number(item.timestamp) - Number(item.lastModificationTimestamp)\n              const deltaT = secondsElapsed / (420 * 60 * 60)\n              const markIndex = 1 / Math.exp(Math.log(Number(item.newNormFactor) / Number(item.oldNormFactor)) / deltaT)\n              const dayFunding = Math.log(markIndex) / 17.5\n              const annualVol = (dayFunding < 0 ? -1 : 1) * Math.sqrt(Math.abs(dayFunding) * 365)\n              return total + annualVol / normFactors.length\n            }, 0)\n            await updateTimestampLiveVolDB(timestamps[timeIndex], avgVol)\n          }\n          if (timeIndex === timestamps.length - 1) {\n            setDataUpdated(true)\n          } else {\n            setTimeIndex(timeIndex + 1)\n          }\n        })()\n      }\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [loading])\n\n  return dataUpdated\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useOSQTHPrice.ts",
    "content": "import { useState } from 'react'\nimport { useAtomValue } from 'jotai'\n\nimport { squeethInitialPriceAtom, squeethInitialPriceErrorAtom } from '@state/squeethPool/atoms'\nimport { useETHPrice } from '@hooks/useETHPrice'\nimport useAppEffect from '@hooks/useAppEffect'\n\nexport const useOSQTHPrice = () => {\n  const [loading, setLoading] = useState(false)\n\n  const ethPrice = useETHPrice()\n  const squeethPriceInETH = useAtomValue(squeethInitialPriceAtom)\n  const squeethPriceError = useAtomValue(squeethInitialPriceErrorAtom)\n\n  const squeethPrice = squeethPriceInETH.times(ethPrice)\n\n  useAppEffect(() => {\n    if (squeethPrice.isZero() && squeethPriceError === '') {\n      setLoading(true)\n    } else {\n      setLoading(false)\n    }\n  }, [squeethPrice, squeethPriceError])\n\n  return { loading, data: squeethPrice, error: squeethPriceError }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/usePopup.tsx",
    "content": "import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport Slide from '@material-ui/core/Slide'\nimport ReactDOM from 'react-dom'\nimport { makeStyles, createStyles } from '@material-ui/core/styles'\nimport { openCrispChat, sendCrispChatMessage } from '@utils/crisp-chat'\nimport useAmplitude from './useAmplitude'\nimport { SITE_EVENTS } from '@utils/amplitude'\n\nexport const useStyles = makeStyles((theme) =>\n  createStyles({\n    popup: {\n      position: 'fixed',\n      bottom: '90px',\n      right: '20px',\n      maxWidth: '20vw',\n      border: `1px solid #303436`,\n      padding: '10px',\n      borderRadius: '8px',\n      display: 'flex',\n      flexDirection: 'column',\n      gap: '10px',\n      backgroundColor: '#191B1C',\n      [theme.breakpoints.down('lg')]: {\n        maxWidth: '30vw',\n      },\n      [theme.breakpoints.down('md')]: {\n        maxWidth: '30vw',\n      },\n      [theme.breakpoints.down('sm')]: {\n        maxWidth: '40vw',\n      },\n      [theme.breakpoints.down('xs')]: {\n        maxWidth: '60vw',\n      },\n    },\n    popupText: {\n      margin: 0,\n    },\n    popupActions: {\n      display: 'flex',\n      gap: '10px',\n    },\n    popupAction: {\n      padding: '10px',\n      backgroundColor: 'transparent',\n      color: '#fff',\n      border: `1px solid #303436`,\n      borderRadius: '8px',\n      cursor: 'pointer',\n      transitionDuration: '200ms',\n      '&:hover': {\n        backgroundColor: theme.palette.background.default,\n        color: '#000',\n      },\n    },\n  }),\n)\n\ninterface PopupAction {\n  label?: string\n  closeAfterAction?: boolean\n  analyticsEvent?: string\n  isClosingAction?: boolean\n  onClick?: () => void\n}\n\nexport interface PopupConfig {\n  id: string\n  text?: string\n  actions?: PopupAction[]\n}\n\ninterface PopupProps extends PopupConfig {\n  showPopup?: boolean\n  hide?: () => void\n}\n\nconst Popup = ({ text, actions = [], showPopup, hide }: PopupProps) => {\n  const classes = useStyles()\n  const { track } = useAmplitude()\n\n  const onClickAction = useCallback(\n    (action: PopupAction) => {\n      action.onClick?.()\n      action.analyticsEvent ? track(action.analyticsEvent, { action: action.label }) : null\n      action.closeAfterAction ? hide?.() : null\n    },\n    [hide, track],\n  )\n  return (\n    <Slide direction=\"left\" in={showPopup} mountOnEnter unmountOnExit>\n      <div className={classes.popup}>\n        <p className={classes.popupText}>{text ?? ''}</p>\n        <div className={classes.popupActions}>\n          {actions.map((action) => (\n            <button\n              key={action.label}\n              onClick={() => onClickAction(action)}\n              type=\"button\"\n              className={classes.popupAction}\n            >\n              {action.label}\n            </button>\n          ))}\n        </div>\n      </div>\n    </Slide>\n  )\n}\nconst popupRoot = typeof document !== 'undefined' ? document.getElementById('popup') : undefined\n\nconst usePopup = (config: PopupConfig) => {\n  const [showPopup, setShowPopup] = useState(false)\n  const { track } = useAmplitude()\n  const timeout = useRef<any>()\n  const nodeRef = useRef<HTMLElement | undefined>(\n    typeof document !== 'undefined' ? document.createElement('div') : undefined,\n  )\n\n  const show = useCallback(() => {\n    setShowPopup(true)\n    track(SITE_EVENTS.SHOW_ERROR_FEEDBACK_POPUP, { title: config?.text })\n    clearTimeout(timeout.current)\n    timeout.current = setTimeout(() => {\n      setShowPopup(false)\n    }, 10000)\n  }, [track, config?.text])\n\n  const hide = () => {\n    setShowPopup(false)\n  }\n  const actions = useMemo(() => {\n    return (config.actions ?? []).map((action) => ({\n      ...action,\n      onClick: action.isClosingAction ? hide : action.onClick,\n    }))\n  }, [config.actions])\n\n  useEffect(() => {\n    nodeRef.current?.setAttribute('id', config.id)\n    if (popupRoot?.querySelector(`#${config.id}`) != null) popupRoot?.querySelector(`#${config.id}`)?.remove()\n    popupRoot?.appendChild(nodeRef?.current as HTMLElement)\n  }, [config.id])\n\n  const popupElement = useMemo(() => {\n    return <Popup id={config.id} hide={hide} showPopup={showPopup} text={config.text} actions={actions} />\n  }, [showPopup, config, actions])\n\n  useEffect(() => {\n    ReactDOM.render(popupElement, nodeRef.current as HTMLElement)\n  }, [popupElement, showPopup])\n\n  return { show, hide, showPopup }\n}\n\nexport default usePopup\n\nexport const GenericErrorPopupConfig: (userMessage: string, id: string) => PopupConfig = (\n  userMessage: string,\n  id: string,\n) => ({\n  id,\n  text: 'Oops, something is not right on our side, would you like to speak to our support team ?',\n  actions: [\n    {\n      label: 'Yes',\n      closeAfterAction: true,\n      analyticsEvent: SITE_EVENTS.CLICK_ERROR_FEEDBACK_ACTION,\n      onClick: () => {\n        sendCrispChatMessage(userMessage)\n        openCrispChat()\n      },\n    },\n    {\n      label: 'No Thanks',\n      analyticsEvent: SITE_EVENTS.CLICK_ERROR_FEEDBACK_ACTION,\n      isClosingAction: true,\n      closeAfterAction: true,\n    },\n  ],\n})\n"
  },
  {
    "path": "packages/frontend/src/hooks/useRenderCounter.js",
    "content": "import React from 'react'\nimport isEmpty from 'lodash/isEmpty'\nimport isString from 'lodash/isString'\n\nfunction getDisplayName(type) {\n  return (\n    type.displayName ||\n    type.name ||\n    (type.type && getDisplayName(type.type)) ||\n    (type.render && getDisplayName(type.render)) ||\n    (isString(type) ? type : null)\n  )\n}\n\nconst origCreateElement = React.createElement\n\nlet renderCount = {}\n\nif (process.env.NODE_ENV === 'development') {\n  const ignoreNames = ['HiddenJs', '_class', 'o']\n\n  React.createElement = function (orgComp, ...params) {\n    if (typeof orgComp === 'function') {\n      const displayName = getDisplayName(orgComp)\n      if (displayName && !ignoreNames.includes(displayName) && !displayName.startsWith('With')) {\n        if (renderCount[displayName]) {\n          renderCount[displayName]++\n        } else {\n          renderCount[displayName] = 1\n        }\n      }\n    }\n\n    const element = origCreateElement.apply(React, [orgComp, ...params])\n\n    return element\n  }\n}\n\nexport default function useRenderCounter(logRenderCountKey, resetRenderCountKey) {\n  React.useEffect(() => {\n    const keydownHandler = (event) => {\n      if (process.env.NODE_ENV !== 'development') {\n        return\n      }\n\n      if (event.key == logRenderCountKey && event.ctrlKey) {\n        console.clear()\n        if (isEmpty(renderCount)) {\n          console.log('There was no rerender after reset.')\n        } else {\n          console.table(renderCount)\n        }\n      }\n\n      if (event.key == resetRenderCountKey && event.ctrlKey) {\n        console.clear()\n        console.log('Render counts has been reset.')\n        renderCount = {}\n      }\n    }\n\n    document.addEventListener('keydown', keydownHandler)\n\n    return () => {\n      document.removeEventListener('keydown', keydownHandler)\n    }\n  }, [logRenderCountKey, resetRenderCountKey])\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useStateWithReset.ts",
    "content": "import React, { useState, useCallback } from 'react'\n\nconst useStateWithReset = <S>(\n  initialState: S | (() => S),\n): [S, React.Dispatch<React.SetStateAction<S>>, () => void] => {\n  const [state, setState] = useState(initialState)\n\n  const resetState = useCallback(() => setState(initialState), [initialState])\n  return [state, setState, resetState]\n}\n\nexport default useStateWithReset\n"
  },
  {
    "path": "packages/frontend/src/hooks/useTVL.ts",
    "content": "import { useQuery } from 'react-query'\n\nexport function useTVL() {\n  const { data } = useQuery('tvl', async () => {\n    const tvlResponse = await fetch('/api/tvl', {\n      method: 'GET',\n      headers: { 'Content-Type': 'application/json' },\n    })\n\n    if (!tvlResponse.ok) {\n      throw new Error('Network response was not ok')\n    }\n\n    const tvl = await tvlResponse.json()\n    return Math.round(tvl / 1e6)\n  })\n\n  return data\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useTrackSiteReload.ts",
    "content": "import { SITE_EVENTS } from '@utils/amplitude'\nimport { useEffect } from 'react'\nimport useAmplitude from './useAmplitude'\n\nconst useTrackSiteReload = () => {\n  const { track } = useAmplitude()\n  const win: any = typeof window !== 'undefined' ? window : undefined\n\n  useEffect(() => {\n    if (win?.performance) {\n      if (win?.performance.navigation.type == 1) {\n        track(SITE_EVENTS.RELOAD_SITE)\n      }\n    }\n  }, [win, track])\n}\n\nexport default useTrackSiteReload\n"
  },
  {
    "path": "packages/frontend/src/hooks/useTrackTransactionFlow.ts",
    "content": "import { useCallback } from 'react'\n\nimport { BULL_EVENTS, CRAB_EVENTS, WALLET_EVENTS } from '@utils/amplitude'\nimport useAmplitude from './useAmplitude'\nimport { REVERTED_TRANSACTION_CODE } from '@constants/index'\n\nconst useTrackTransactionFlow = () => {\n  const { track } = useAmplitude()\n\n  const logAnalytics = useCallback(\n    async (fn: () => Promise<any>, eventName: CRAB_EVENTS | BULL_EVENTS | WALLET_EVENTS) => {\n      track(`${eventName}_CLICK`)\n      try {\n        await fn()\n        track(`${eventName}_SUCCESS`)\n      } catch (e: any) {\n        if (e?.code === REVERTED_TRANSACTION_CODE) {\n          track(`${eventName}_REVERT`)\n        }\n        track(`${eventName}_FAILED`, { code: e?.code })\n        console.log(e)\n      }\n    },\n    [track],\n  )\n\n  return logAnalytics\n}\n\nexport default useTrackTransactionFlow\n"
  },
  {
    "path": "packages/frontend/src/hooks/useTransactionHistory.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport BigNumber from 'bignumber.js'\nimport { useAtomValue } from 'jotai'\n\nimport { BIG_ZERO, TransactionType } from '../constants'\nimport {\n  transactions,\n  transactionsVariables,\n  transactions_positionSnapshots,\n} from '../queries/uniswap/__generated__/transactions'\nimport TRANSACTIONS_QUERY from '../queries/uniswap/transactionsQuery'\nimport { useUserCrabTxHistory } from './useUserCrabTxHistory'\nimport { useUserCrabV2TxHistory } from './useUserCrabV2TxHistory'\nimport { BullStrategyTxType, CrabStrategyTxType } from '../types'\nimport { CrabStrategyV2TxType } from '../types'\nimport { addressAtom } from 'src/state/wallet/atoms'\nimport { addressesAtom, isWethToken0Atom, swapsAtom } from 'src/state/positions/atoms'\nimport { useEthPriceMap } from 'src/state/ethPriceCharts/atoms'\nimport { useUserBullTxHistory } from './useUserBullTxHistory'\n\nconst bigZero = new BigNumber(0)\n\nconst getTransactionType = (c: any) => {\n  if (c.type === CrabStrategyV2TxType.OTC_DEPOSIT) return TransactionType.OTC_DEPOSIT\n\n  if (c.type === CrabStrategyV2TxType.OTC_WITHDRAW) return TransactionType.OTC_WITHDRAW\n\n  return c.type === CrabStrategyV2TxType.FLASH_DEPOSIT || c.type === CrabStrategyV2TxType.DEPOSIT_V1\n    ? c.erc20Token\n      ? TransactionType.CRAB_V2_USDC_FLASH_DEPOSIT\n      : TransactionType.CRAB_V2_FLASH_DEPOSIT\n    : c.erc20Token\n    ? TransactionType.CRAB_V2_USDC_FLASH_WITHDRAW\n    : TransactionType.CRAB_V2_FLASH_WITHDRAW\n}\n\nexport const useTransactionHistory = () => {\n  const { squeethPool, shortHelper, swapRouter } = useAtomValue(addressesAtom)\n  const address = useAtomValue(addressAtom)\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n  const ethPriceMap = useEthPriceMap()\n  const swapsData = useAtomValue(swapsAtom)\n  const swaps = swapsData?.swaps\n\n  const { data, loading } = useQuery<transactions, transactionsVariables>(TRANSACTIONS_QUERY, {\n    variables: {\n      poolAddress: squeethPool,\n      owner: address || '',\n      origin: address || '',\n      recipients: [shortHelper, address || '', swapRouter],\n      orderDirection: 'desc',\n    },\n    fetchPolicy: 'cache-and-network',\n  })\n\n  const { data: crabData } = useUserCrabTxHistory(address || '')\n  const { data: crabV2Data } = useUserCrabV2TxHistory(address || '')\n  const { data: bullData } = useUserBullTxHistory(address || '', true)\n\n  const addRemoveLiquidityTrans =\n    ethPriceMap &&\n    (data?.positionSnapshots || []).map(\n      (transaction: transactions_positionSnapshots, index: number, array: transactions_positionSnapshots[]) => {\n        const transactionDetails = {\n          squeethAmount: new BigNumber(isWethToken0 ? transaction.depositedToken1 : transaction.depositedToken0),\n          ethAmount: new BigNumber(isWethToken0 ? transaction.depositedToken0 : transaction.depositedToken1),\n          usdValue: bigZero,\n          timestamp: transaction.transaction.timestamp,\n          transactionType: TransactionType.ADD_LIQUIDITY,\n          txId: transaction.transaction.id,\n          ethPriceAtDeposit: bigZero,\n        }\n\n        const squeethDepositedAmount = new BigNumber(\n          isWethToken0 ? transaction.depositedToken1 : transaction.depositedToken0,\n        )\n        const ethDepositedAmount = new BigNumber(\n          isWethToken0 ? transaction.depositedToken0 : transaction.depositedToken1,\n        )\n        const squeethWithdrawnAmount = new BigNumber(\n          isWethToken0 ? transaction.withdrawnToken1 : transaction.withdrawnToken0,\n        )\n        const ethWithdrawnAmount = new BigNumber(\n          isWethToken0 ? transaction.withdrawnToken0 : transaction.withdrawnToken1,\n        )\n\n        const prevSqueethDepositedAmount = new BigNumber(\n          // Index + 1 here is because the array is ordered from latest to oldest\n          isWethToken0 ? array[index + 1]?.depositedToken1 : array[index + 1]?.depositedToken0,\n        )\n        const prevEthDepositedAmount = new BigNumber(\n          isWethToken0 ? array[index + 1]?.depositedToken0 : array[index + 1]?.depositedToken1,\n        )\n        const prevSqueethWithdrawnAmount = new BigNumber(\n          isWethToken0 ? array[index + 1]?.withdrawnToken1 : array[index + 1]?.withdrawnToken0,\n        )\n        const prevEthWithdrawnAmount = new BigNumber(\n          isWethToken0 ? array[index + 1]?.withdrawnToken0 : array[index + 1]?.withdrawnToken1,\n        )\n\n        if (squeethDepositedAmount.isGreaterThan(prevSqueethDepositedAmount)) {\n          transactionDetails.squeethAmount = squeethDepositedAmount.minus(prevSqueethDepositedAmount)\n          transactionDetails.ethAmount = ethDepositedAmount.minus(prevEthDepositedAmount)\n          transactionDetails.transactionType = TransactionType.ADD_LIQUIDITY\n        } else if (squeethWithdrawnAmount.isGreaterThan(prevSqueethWithdrawnAmount)) {\n          transactionDetails.squeethAmount = squeethWithdrawnAmount.minus(prevSqueethWithdrawnAmount)\n          transactionDetails.ethAmount = ethWithdrawnAmount.minus(prevEthWithdrawnAmount)\n          transactionDetails.transactionType = TransactionType.REMOVE_LIQUIDITY\n        }\n\n        const time = new Date(Number(transaction.transaction.timestamp) * 1000).setUTCHours(0, 0, 0) / 1000\n        const usdValue = transactionDetails.ethAmount.multipliedBy(ethPriceMap[time]).abs()\n\n        return { ...transactionDetails, usdValue, ethPriceAtDeposit: new BigNumber(ethPriceMap[time]) }\n      },\n    )\n\n  const transactions =\n    ethPriceMap &&\n    (swaps || []).map((s) => {\n      const squeethAmount = new BigNumber(isWethToken0 ? s.amount1 : s.amount0)\n      const ethAmount = new BigNumber(isWethToken0 ? s.amount0 : s.amount1)\n      const time = new Date(Number(s.timestamp) * 1000).setUTCHours(0, 0, 0) / 1000\n      const usdValue = ethAmount.multipliedBy(ethPriceMap[time]).abs()\n\n      let transactionType = TransactionType.BUY\n      if (squeethAmount.isPositive() && s.recipient.toLowerCase() !== shortHelper.toLowerCase()) {\n        transactionType = TransactionType.SELL\n      } else if (s.recipient.toLowerCase() === shortHelper.toLowerCase()) {\n        if (squeethAmount.isNegative()) transactionType = TransactionType.BURN_SHORT\n        if (squeethAmount.isPositive()) transactionType = TransactionType.MINT_SHORT\n      }\n\n      return {\n        squeethAmount: squeethAmount.abs(),\n        ethAmount: ethAmount.abs(),\n        usdValue,\n        timestamp: s.timestamp,\n        transactionType,\n        txId: s.transaction.id,\n        ethPriceAtDeposit: new BigNumber(ethPriceMap[time]),\n      }\n    })\n\n  const crabTransactions = (crabData || [])?.map((c) => {\n    const transactionType =\n      c.type === CrabStrategyTxType.FLASH_DEPOSIT\n        ? TransactionType.CRAB_FLASH_DEPOSIT\n        : TransactionType.CRAB_FLASH_WITHDRAW\n    const { oSqueethAmount: squeethAmount, ethAmount, ethUsdValue: usdValue, timestamp } = c\n\n    return {\n      transactionType,\n      squeethAmount: squeethAmount.abs(),\n      ethAmount: ethAmount.abs(),\n      usdValue,\n      timestamp,\n      txId: c.id,\n    }\n  })\n\n  const crabV2Transactions = (crabV2Data || [])?.map((c) => {\n    const transactionType = getTransactionType(c)\n\n    const { oSqueethAmount: squeethAmount, ethAmount, ethUsdValue: usdValue, timestamp } = c\n\n    return {\n      transactionType,\n      squeethAmount: squeethAmount.abs(),\n      ethAmount: ethAmount.abs(),\n      usdValue,\n      timestamp,\n      txId: c.transaction,\n    }\n  })\n\n  const bullTransactions = (bullData || [])?.map((c) => {\n    const transactionType =\n      c.type === BullStrategyTxType.FLASH_DEPOSIT\n        ? TransactionType.BULL_FLASH_DEPOSIT\n        : TransactionType.BULL_FLASH_WITHDRAW\n    const { ethAmount, ethUsdValue: usdValue, timestamp } = c\n\n    return {\n      transactionType,\n      squeethAmount: BIG_ZERO,\n      ethAmount: ethAmount.abs(),\n      usdValue,\n      timestamp,\n      txId: c.id,\n    }\n  })\n\n  return {\n    transactions: [\n      ...(transactions || []),\n      ...(addRemoveLiquidityTrans || []),\n      ...crabTransactions,\n      ...crabV2Transactions,\n      ...bullTransactions,\n    ].sort((transactionA, transactionB) => transactionB.timestamp - transactionA.timestamp),\n    loading,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useUniswapQuoter.tsx",
    "content": "import BigNumber from 'bignumber.js'\nimport { useAtomValue } from 'jotai'\nimport { quoterContractAtom } from 'src/state/contracts/atoms'\n\nexport const useUniswapQuoter = () => {\n  const contract = useAtomValue(quoterContractAtom)\n\n  const getExactIn = async (\n    tokenIn: string,\n    tokenOut: string,\n    amountIn: BigNumber,\n    poolFee: number,\n    slippage: number,\n  ) => {\n    if (!contract) return null\n\n    const quoteExactInputSingleParams = {\n      tokenIn: tokenIn,\n      tokenOut: tokenOut,\n      amountIn: amountIn.toFixed(0),\n      fee: poolFee,\n      sqrtPriceLimitX96: 0,\n    }\n\n    const quote = await contract.methods.quoteExactInputSingle(quoteExactInputSingleParams).call()\n    const minAmountOut = new BigNumber(quote.amountOut)\n      .times(100 - slippage)\n      .div(100)\n      .toFixed(0)\n    return { ...quote, minAmountOut }\n  }\n\n  const getExactOut = async (tokenIn: string, tokenOut: string, amountOut: BigNumber, poolFee: number) => {\n    if (!contract) return null\n\n    const quoteExactOutputSingleParams = {\n      tokenIn: tokenIn,\n      tokenOut: tokenOut,\n      amount: amountOut.toFixed(0),\n      fee: poolFee,\n      sqrtPriceLimitX96: 0,\n    }\n\n    const quote = await contract.methods.quoteExactOutputSingle(quoteExactOutputSingleParams).call()\n    return quote\n  }\n\n  return { getExactIn, getExactOut }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useUniswapTicks.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport { Tick } from '@uniswap/v3-sdk'\nimport { useAtomValue } from 'jotai'\n\nimport { ticks, ticksVariables } from '../queries/uniswap/__generated__/ticks'\nimport TICKS_QUERY from '../queries/uniswap/ticksQuery'\nimport { addressesAtom } from 'src/state/positions/atoms'\n\nconst useUniswapTicks = () => {\n  const { squeethPool } = useAtomValue(addressesAtom)\n  const { data, loading } = useQuery<ticks, ticksVariables>(TICKS_QUERY, {\n    variables: { poolAddress: squeethPool },\n  })\n\n  const ticks = data?.ticks\n    .map((d) => new Tick({ index: d.tickIdx, liquidityGross: d.liquidityGross, liquidityNet: d.liquidityNet }))\n    .sort((t1, t2) => t1.index - t2.index)\n\n  return {\n    ticks,\n    loading,\n  }\n}\n\nexport default useUniswapTicks\n"
  },
  {
    "path": "packages/frontend/src/hooks/useUsdAmount.ts",
    "content": "import BigNumber from 'bignumber.js'\n\nimport { useCallback } from 'react'\nimport {\n  useEth90daysPriceMap,\n  useEthPricesSinceStrategiesLaunchMap,\n  useEthWithinOneDayPriceMap,\n} from 'src/state/ethPriceCharts/atoms'\n\nconst getClosestTime = (ethWithinOneDayPriceMap: { [key: number]: number }, timestamp: any): number => {\n  if (!ethWithinOneDayPriceMap || !timestamp) return 0\n  const closest = Object.keys(ethWithinOneDayPriceMap)?.length\n    ? Object.keys(ethWithinOneDayPriceMap).reduce(function (previousValue: string, currentValue: string): any {\n        const prev = Number(previousValue)\n        const cur = Number(currentValue)\n        const prevDiff = Math.abs(prev - timestamp)\n        const curDiff = Math.abs(cur - timestamp)\n\n        if (prevDiff == curDiff) {\n          return previousValue > currentValue ? prev : cur\n        } else {\n          return curDiff < prevDiff ? cur : prev\n        }\n      })\n    : '0'\n  return Number(closest)\n}\n\nexport const useUsdAmount = () => {\n  const ethPriceMap = useEthPricesSinceStrategiesLaunchMap()\n  const eth90daysPriceMap = useEth90daysPriceMap()\n  const ethWithinOneDayPriceMap = useEthWithinOneDayPriceMap()\n\n  const getUsdAmt = useCallback(\n    (wethAmt: BigNumber, timestamp: any) => {\n      if (!ethPriceMap || !eth90daysPriceMap) return new BigNumber(0)\n\n      const currentTime = new Date(Date.now())\n      const txTime = new Date(Number(timestamp) * 1000)\n      let usdAmount\n      let time\n      const diffDays = (currentTime.getTime() - txTime.getTime()) / (1000 * 3600 * 24)\n\n      if (diffDays > 90) {\n        time = new Date(Number(timestamp) * 1000).setUTCHours(0, 0, 0) / 1000\n        const closestTime = getClosestTime(ethPriceMap, time)\n        usdAmount = wethAmt.multipliedBy(ethPriceMap[closestTime])\n      } else if (diffDays <= 90 && diffDays >= 1) {\n        time = new Date(Number(timestamp) * 1000).setUTCMinutes(0, 0, 0)\n        const closestTime = getClosestTime(eth90daysPriceMap, time)\n        usdAmount = wethAmt.multipliedBy(eth90daysPriceMap[closestTime])\n      } else {\n        time = new Date(Number(timestamp) * 1000).setUTCSeconds(0, 0)\n        const closestTime = getClosestTime(ethWithinOneDayPriceMap, time)\n        usdAmount = wethAmt.multipliedBy(ethWithinOneDayPriceMap[closestTime])\n      }\n\n      return usdAmount\n    },\n    [eth90daysPriceMap, ethPriceMap, ethWithinOneDayPriceMap],\n  )\n\n  return { getUsdAmt }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useUserBullTxHistory.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport { userBullTxes, userBullTxesVariables } from '../queries/squeeth/__generated__/userBullTxes'\nimport USER_BULL_TX_QUERY from '../queries/squeeth/userBullQuery'\nimport { toTokenAmount } from '@utils/calculations'\nimport { WETH_DECIMALS, BIG_ONE } from '../constants'\nimport { squeethClient } from '@utils/apollo-client'\nimport { CrabStrategyV2TxType } from '../types/index'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\nimport { useAtomValue } from 'jotai'\nimport useAppMemo from './useAppMemo'\nimport { getHistoricEthPrices } from './useETHPrice'\nimport { useEffect, useState } from 'react'\nimport BigNumber from 'bignumber.js'\nimport { useUsdAmount } from './useUsdAmount'\n\nconst getTxTitle = (type: string) => {\n  if (type === CrabStrategyV2TxType.FLASH_DEPOSIT) return 'Flash Deposit'\n  if (type === CrabStrategyV2TxType.FLASH_WITHDRAW) return 'Flash Withdraw'\n}\n\nexport const useUserBullTxHistory = (user: string, isDescending?: boolean) => {\n  const networkId = useAtomValue(networkIdAtom)\n  // const [ethUsdPriceMap, setEthUsdPriceMap] = useState<Record<number, string> | undefined>()\n  // const [ethUsdPriceMapLoading, setEthUsdPriceMapLoading] = useState(false)\n  const { getUsdAmt } = useUsdAmount()\n  const { data, loading, startPolling, stopPolling } = useQuery<userBullTxes, userBullTxesVariables>(\n    USER_BULL_TX_QUERY,\n    {\n      fetchPolicy: 'cache-and-network',\n      client: squeethClient[networkId],\n      variables: {\n        ownerId: user ?? '',\n        orderDirection: isDescending ? 'desc' : 'asc',\n      },\n    },\n  )\n\n  const bullUserTxes = useAppMemo(() => data?.bullUserTxes ?? [], [data])\n\n  // get all timestamps found in the user's history once\n  // useEffect(() => {\n  //   const timestampsArr = bullUserTxes.map((tx) => tx.timestamp * 1000)\n\n  //   setEthUsdPriceMap(undefined)\n  //   setEthUsdPriceMapLoading(true)\n\n  //   getHistoricEthPrices(timestampsArr)\n  //     .then((result) => {\n  //       setEthUsdPriceMap(result ?? undefined)\n  //     })\n  //     .finally(() => {\n  //       setEthUsdPriceMapLoading(false)\n  //     })\n  // }, [bullUserTxes])\n\n  const uiData = useAppMemo(() => {\n    // if (!ethUsdPriceMap) {\n    //   return []\n    // }\n\n    return bullUserTxes.map((tx) => {\n      const ethAmount = toTokenAmount(tx.ethAmount, WETH_DECIMALS)\n      const ethPriceAtTxTimestamp = getUsdAmt(toTokenAmount(BIG_ONE, 18), tx.timestamp)\n      const ethUsdValue = ethAmount.multipliedBy(ethPriceAtTxTimestamp)\n\n      const bullAmount = toTokenAmount(tx.bullAmount, WETH_DECIMALS)\n\n      return {\n        ...tx,\n        ethAmount,\n        bullAmount,\n        ethUsdValue,\n        txTitle: getTxTitle(tx.type),\n      }\n    })\n  }, [bullUserTxes, getUsdAmt])\n\n  return {\n    loading: loading,\n    data: uiData,\n    startPolling,\n    stopPolling,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useUserCrabTxHistory.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport { userCrabTxes, userCrabTxesVariables } from '../queries/squeeth/__generated__/userCrabTxes'\nimport USER_CRAB_TX_QUERY from '../queries/squeeth/userCrabTxQuery'\nimport { toTokenAmount } from '@utils/calculations'\nimport { WETH_DECIMALS, OSQUEETH_DECIMALS } from '../constants'\nimport { squeethClient } from '@utils/apollo-client'\nimport { CrabStrategyTxType } from '../types/index'\nimport { useUsdAmount } from './useUsdAmount'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\nimport { useAtomValue } from 'jotai'\n\nconst getTxTitle = (type: string) => {\n  if (type === CrabStrategyTxType.DEPOSIT) return 'Deposit'\n  if (type === CrabStrategyTxType.WITHDRAW) return 'Withdraw'\n  if (type === CrabStrategyTxType.FLASH_DEPOSIT) return 'Flash Deposit'\n  if (type === CrabStrategyTxType.FLASH_WITHDRAW) return 'Flash Withdraw'\n  if (type === CrabStrategyTxType.HEDGE_ON_UNISWAP) return 'Hedge on Uniswap'\n  if (type === CrabStrategyTxType.HEDGE) return 'Hedge'\n}\n\nexport const useUserCrabTxHistory = (user: string, isDescending?: boolean) => {\n  const networkId = useAtomValue(networkIdAtom)\n  const { getUsdAmt } = useUsdAmount()\n  const { data, loading, startPolling, stopPolling } = useQuery<userCrabTxes, userCrabTxesVariables>(\n    USER_CRAB_TX_QUERY,\n    {\n      fetchPolicy: 'cache-and-network',\n      client: squeethClient[networkId],\n      variables: {\n        ownerId: user ?? '',\n        orderDirection: isDescending ? 'desc' : 'asc',\n      },\n    },\n  )\n\n  const uiData = data?.crabStrategyTxes.map((tx) => {\n    const ethAmount = toTokenAmount(tx.ethAmount, WETH_DECIMALS)\n    const ethUsdValue = getUsdAmt(ethAmount, tx.timestamp)\n    const lpAmount = toTokenAmount(tx.lpAmount, WETH_DECIMALS)\n    const oSqueethAmount = toTokenAmount(tx.wSqueethAmount, OSQUEETH_DECIMALS)\n\n    return {\n      ...tx,\n      ethAmount,\n      lpAmount,\n      oSqueethAmount,\n      ethUsdValue,\n      txTitle: getTxTitle(tx.type),\n    }\n  })\n\n  return {\n    loading,\n    data: uiData,\n    startPolling,\n    stopPolling,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useUserCrabV2TxHistory.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport { userCrabV2Txes, userCrabV2TxesVariables } from '../queries/squeeth/__generated__/userCrabV2Txes'\nimport USER_CRAB_V2_TX_QUERY from '../queries/squeeth/userCrabV2TxQuery'\nimport { toTokenAmount } from '@utils/calculations'\nimport {\n  WETH_DECIMALS,\n  OSQUEETH_DECIMALS,\n  V2_MIGRATION_ETH_AMOUNT,\n  V2_MIGRATION_SUPPLY,\n  V2_MIGRATION_OSQTH_AMOUNT,\n  V2_MIGRATION_OSQTH_PRICE,\n  V2_MIGRATION_ETH_PRICE,\n  USDC_DECIMALS,\n  BIG_ONE,\n} from '../constants'\nimport { squeethClient } from '@utils/apollo-client'\nimport { CrabStrategyV2TxType } from '../types/index'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\nimport { useAtomValue } from 'jotai'\nimport useAppMemo from './useAppMemo'\nimport BigNumber from 'bignumber.js'\nimport { addressesAtom } from 'src/state/positions/atoms'\nimport { getHistoricEthPrices } from './useETHPrice'\nimport { useEffect, useMemo, useState } from 'react'\nimport { useUsdAmount } from './useUsdAmount'\n\nconst getTxTitle = (type: string) => {\n  if (type === CrabStrategyV2TxType.DEPOSIT) return 'Deposit'\n  if (type === CrabStrategyV2TxType.WITHDRAW) return 'Withdraw'\n  if (type === CrabStrategyV2TxType.FLASH_DEPOSIT) return 'Flash Deposit'\n  if (type === CrabStrategyV2TxType.FLASH_WITHDRAW) return 'Flash Withdraw'\n  if (type === CrabStrategyV2TxType.DEPOSIT_V1) return 'Deposit v1 shares'\n}\n\nexport const useUserCrabV2TxHistory = (user: string, isDescending?: boolean) => {\n  const networkId = useAtomValue(networkIdAtom)\n  const { usdc } = useAtomValue(addressesAtom)\n  // const [ethUsdPriceMap, setEthUsdPriceMap] = useState<Record<number, string> | undefined>()\n  // const [ethUsdPriceMapLoading, setEthUsdPriceMapLoading] = useState(false)\n  const { getUsdAmt } = useUsdAmount()\n  const { data, loading, startPolling, stopPolling, error } = useQuery<userCrabV2Txes, userCrabV2TxesVariables>(\n    USER_CRAB_V2_TX_QUERY,\n    {\n      fetchPolicy: 'cache-and-network',\n      client: squeethClient[networkId],\n      variables: {\n        ownerId: user ?? '',\n        orderDirection: isDescending ? 'desc' : 'asc',\n      },\n    },\n  )\n\n  const crabUserTxes = useAppMemo(() => data?.crabUserTxes ?? [], [data])\n\n  // get all timestamps found in the user's history once\n  // useEffect(() => {\n  //   const timestampsArr = crabUserTxes.map((tx) => tx.timestamp * 1000)\n\n  //   setEthUsdPriceMap(undefined)\n  //   setEthUsdPriceMapLoading(true)\n\n  //   getHistoricEthPrices(timestampsArr)\n  //     .then((result) => {\n  //       setEthUsdPriceMap(result ?? undefined)\n  //     })\n  //     .finally(() => {\n  //       setEthUsdPriceMapLoading(false)\n  //     })\n  // }, [crabUserTxes])\n\n  // const isEthUsdPriceMapValid = useMemo(\n  //   () => ethUsdPriceMap && crabUserTxes.every((tx) => !!ethUsdPriceMap![Number(tx.timestamp) * 1000]),\n  //   [crabUserTxes, ethUsdPriceMap],\n  // )\n\n  const uiData = useAppMemo(() => {\n    // if (!isEthUsdPriceMapValid) {\n    //   return []\n    // }\n\n    return crabUserTxes.map((tx) => {\n      let ethAmount = toTokenAmount(tx.ethAmount, WETH_DECIMALS)\n\n      const ethPriceAtTxTimestamp = getUsdAmt(toTokenAmount(BIG_ONE, 18), tx.timestamp)\n      let ethUsdValue = ethAmount.multipliedBy(ethPriceAtTxTimestamp)\n\n      if (tx.type === CrabStrategyV2TxType.DEPOSIT_V1) {\n        const ethMigrated = new BigNumber(V2_MIGRATION_ETH_AMOUNT)\n        const oSqthMigrated = new BigNumber(V2_MIGRATION_OSQTH_AMOUNT)\n\n        ethAmount = ethMigrated\n          .minus(oSqthMigrated.times(V2_MIGRATION_OSQTH_PRICE))\n          .times(toTokenAmount(tx.lpAmount, WETH_DECIMALS))\n          .div(V2_MIGRATION_SUPPLY)\n\n        ethUsdValue = ethAmount.times(V2_MIGRATION_ETH_PRICE)\n      }\n\n      if (tx.type === CrabStrategyV2TxType.FLASH_WITHDRAW && usdc.toLowerCase() === tx.erc20Token?.toLowerCase()) {\n        ethUsdValue = toTokenAmount(tx.erc20Amount, USDC_DECIMALS)\n      } else if (\n        tx.type === CrabStrategyV2TxType.FLASH_DEPOSIT &&\n        usdc.toLowerCase() === tx.erc20Token?.toLowerCase()\n      ) {\n        ethUsdValue = toTokenAmount(tx.erc20Amount, USDC_DECIMALS).minus(\n          ethPriceAtTxTimestamp.isZero() ? 0 : toTokenAmount(tx.excessEth, 18).multipliedBy(ethPriceAtTxTimestamp),\n        )\n      }\n\n      if (tx.type === CrabStrategyV2TxType.OTC_DEPOSIT || tx.type === CrabStrategyV2TxType.OTC_WITHDRAW) {\n        ethUsdValue = toTokenAmount(tx.erc20Amount, USDC_DECIMALS).minus(\n          toTokenAmount(tx.ethAmount, 18).multipliedBy(ethPriceAtTxTimestamp),\n        )\n        ethAmount = ethPriceAtTxTimestamp.isZero()\n          ? new BigNumber(0)\n          : toTokenAmount(tx.erc20Amount, USDC_DECIMALS).div(ethPriceAtTxTimestamp)\n      }\n\n      const lpAmount = toTokenAmount(tx.lpAmount, WETH_DECIMALS)\n      const oSqueethAmount = toTokenAmount(tx.wSqueethAmount, OSQUEETH_DECIMALS)\n\n      return {\n        ...tx,\n        ethAmount,\n        lpAmount,\n        oSqueethAmount,\n        ethUsdValue,\n        txTitle: getTxTitle(tx.type),\n      }\n    })\n  }, [crabUserTxes, usdc, getUsdAmt])\n\n  return {\n    loading: loading,\n    data: uiData,\n    startPolling,\n    stopPolling,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useVault.ts",
    "content": "import { Vault } from '../types'\nimport { useCallback, useEffect, useState } from 'react'\nimport { useGetVault } from 'src/state/controller/hooks'\n\nconst useVault = (vid: number) => {\n  const getVault = useGetVault()\n  const [vault, setVault] = useState<Vault>()\n  const [loading, setLoading] = useState(true)\n\n  useEffect(() => {\n    getVault(vid).then((v) => {\n      setVault(v ?? undefined)\n      setLoading(false)\n    })\n  }, [getVault, vid])\n\n  const updateVault = useCallback(() => {\n    getVault(vid).then((v) => setVault(v ?? undefined))\n  }, [getVault, vid])\n\n  return { vault, loading, updateVault }\n}\n\nexport default useVault\n"
  },
  {
    "path": "packages/frontend/src/hooks/useVaultData.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { useAtom } from 'jotai'\nimport { useState } from 'react'\n\nimport { useGetCollatRatioAndLiqPrice } from 'src/state/controller/hooks'\nimport { collatPercentAtom, existingCollatPercentAtom, existingLiqPriceAtom } from 'src/state/positions/atoms'\nimport useAppEffect from './useAppEffect'\n\ninterface IVault {\n  id: string\n  NFTCollateralId: any\n  collateralAmount: BigNumber\n  shortAmount: BigNumber\n  operator: any\n}\n\nexport const useVaultData = (vault: IVault | undefined) => {\n  const [existingCollatPercent, setExistingCollatPercent] = useAtom(existingCollatPercentAtom)\n  const [existingCollat, setExistingCollat] = useState(new BigNumber(0))\n  const [existingLiqPrice, setExistingLiqPrice] = useAtom(existingLiqPriceAtom)\n  const [collatPercent, setCollatPercent] = useAtom(collatPercentAtom)\n\n  const getCollatRatioAndLiqPrice = useGetCollatRatioAndLiqPrice()\n\n  useAppEffect(() => {\n    if (!vault) {\n      setExistingCollat(new BigNumber(0))\n      setExistingCollatPercent(0)\n      setCollatPercent(0)\n      setExistingLiqPrice(new BigNumber(0))\n      return\n    }\n\n    setExistingCollat(vault.collateralAmount)\n\n    getCollatRatioAndLiqPrice(\n      vault.collateralAmount,\n      vault.shortAmount,\n      vault.NFTCollateralId ? Number(vault.NFTCollateralId) : undefined,\n    ).then(({ collateralPercent, liquidationPrice }) => {\n      setExistingCollatPercent(collateralPercent)\n      setCollatPercent(collateralPercent)\n      setExistingLiqPrice(new BigNumber(liquidationPrice))\n    })\n  }, [\n    getCollatRatioAndLiqPrice,\n    setCollatPercent,\n    setExistingCollat,\n    setExistingCollatPercent,\n    setExistingLiqPrice,\n    vault,\n  ])\n\n  return {\n    vault,\n    existingCollatPercent,\n    existingLiqPrice,\n    setCollatPercent,\n    collatPercent,\n    existingCollat,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useVaultHistory.ts",
    "content": "import { useState } from 'react'\nimport { useQuery, NetworkStatus } from '@apollo/client'\nimport { BIG_ZERO } from '@constants/index'\n\nimport VAULT_HISTORY_QUERY, { VAULT_HISTORY_SUBSCRIPTION } from '../queries/squeeth/vaultHistoryQuery'\nimport {\n  VaultHistory,\n  VaultHistoryVariables,\n  VaultHistory_vaultHistories,\n} from '../queries/squeeth/__generated__/VaultHistory'\nimport { squeethClient } from '@utils/apollo-client'\nimport { Action } from '@constants/index'\nimport { toTokenAmount } from '@utils/calculations'\nimport { addressAtom, networkIdAtom } from 'src/state/wallet/atoms'\nimport { useAtomValue } from 'jotai'\nimport { usePrevious } from 'react-use'\nimport { vaultHistoryUpdatingAtom } from 'src/state/positions/atoms'\nimport { useUpdateAtom } from 'jotai/utils'\nimport useAppEffect from './useAppEffect'\nimport useAppMemo from './useAppMemo'\n\nexport const useVaultHistoryQuery = (vaultId: number, poll = false) => {\n  const address = useAtomValue(addressAtom)\n  const networkId = useAtomValue(networkIdAtom)\n  const [vaultHistories, setVaultHistories] = useState<VaultHistory_vaultHistories[]>([])\n  const setVaultHistoryUpdating = useUpdateAtom(vaultHistoryUpdatingAtom)\n\n  const { data, loading, refetch, subscribeToMore, startPolling, stopPolling, networkStatus } = useQuery<\n    VaultHistory,\n    VaultHistoryVariables\n  >(VAULT_HISTORY_QUERY, {\n    client: squeethClient[networkId],\n    fetchPolicy: 'cache-and-network',\n    notifyOnNetworkStatusChange: true,\n    variables: {\n      vaultId: vaultId,\n    },\n  })\n  const vaultHistory = data?.vaultHistories\n  const prevVaultHistory = usePrevious(vaultHistory)\n\n  useAppEffect(() => {\n    if (vaultHistory && vaultHistory.length > 0) {\n      setVaultHistories(vaultHistory)\n    }\n  }, [vaultHistory])\n\n  useAppEffect(() => {\n    if (poll && prevVaultHistory?.length === vaultHistory?.length) {\n      startPolling(500)\n    } else {\n      setVaultHistoryUpdating(false)\n      stopPolling()\n    }\n  }, [poll, prevVaultHistory, startPolling, stopPolling, vaultHistory, setVaultHistoryUpdating])\n\n  useAppEffect(() => {\n    subscribeToMore({\n      document: VAULT_HISTORY_SUBSCRIPTION,\n      variables: {\n        vaultId: vaultId,\n      },\n      updateQuery(prev, { subscriptionData }) {\n        if (!subscriptionData.data || subscriptionData.data.vaultHistories.length === data?.vaultHistories.length)\n          return prev\n        const newVaultsHistories = subscriptionData.data.vaultHistories\n        return { vaultHistories: newVaultsHistories }\n      },\n    })\n  }, [address, vaultId, subscribeToMore, data?.vaultHistories.length])\n\n  return {\n    vaultHistory: vaultHistories,\n    loading: loading || poll || networkStatus === NetworkStatus.refetch,\n    refetch,\n  }\n}\n\nexport const useVaultHistory = (vaultId: number) => {\n  const { vaultHistory } = useVaultHistoryQuery(vaultId)\n\n  //accumulated four actions, mintedSqueeth doesn't take minted squeeth sold into account\n  //only consider first valid vault\n  //mintedSqueeth + openShortSqueeth = shortAmount in the vault\n  const { mintedSqueeth, burnedSqueeth, openShortSqueeth, closeShortSqueeth } = useAppMemo(\n    () =>\n      vaultHistory?.reduce(\n        (acc, s) => {\n          if (s.action === Action.MINT) {\n            acc.mintedSqueeth = acc.mintedSqueeth.plus(s.oSqthAmount)\n          } else if (s.action === Action.BURN) {\n            acc.mintedSqueeth = acc.mintedSqueeth.minus(s.oSqthAmount)\n            acc.burnedSqueeth = acc.burnedSqueeth.plus(s.oSqthAmount)\n          } else if (s.action === Action.OPEN_SHORT) {\n            acc.openShortSqueeth = acc.openShortSqueeth.plus(s.oSqthAmount)\n          } else if (s.action === Action.CLOSE_SHORT) {\n            acc.closeShortSqueeth = acc.closeShortSqueeth.plus(s.oSqthAmount)\n            // users fully close short position\n            if (\n              acc.closeShortSqueeth.isEqualTo(acc.openShortSqueeth.plus(acc.mintedSqueeth)) &&\n              !acc.closeShortSqueeth.isEqualTo(0)\n            ) {\n              acc.mintedSqueeth = BIG_ZERO\n              acc.burnedSqueeth = BIG_ZERO\n              acc.openShortSqueeth = BIG_ZERO\n              acc.closeShortSqueeth = BIG_ZERO\n            } else {\n              acc.openShortSqueeth = acc.openShortSqueeth.minus(s.oSqthAmount)\n            }\n          }\n          //if user burn all their osqueeth, reset all values\n          if (acc.mintedSqueeth.isLessThanOrEqualTo(0)) {\n            acc.mintedSqueeth = BIG_ZERO\n            acc.burnedSqueeth = BIG_ZERO\n          }\n          //if user close all their short position with OPEN_SHORT/CLOSE_SHORT, reset all values\n          if (acc.openShortSqueeth.isLessThanOrEqualTo(0)) {\n            acc.openShortSqueeth = BIG_ZERO\n            acc.closeShortSqueeth = BIG_ZERO\n          }\n\n          return acc\n        },\n        {\n          mintedSqueeth: BIG_ZERO,\n          burnedSqueeth: BIG_ZERO,\n          openShortSqueeth: BIG_ZERO,\n          closeShortSqueeth: BIG_ZERO,\n        },\n      ) || {\n        mintedSqueeth: BIG_ZERO,\n        burnedSqueeth: BIG_ZERO,\n        openShortSqueeth: BIG_ZERO,\n        closeShortSqueeth: BIG_ZERO,\n      },\n    [vaultHistory],\n  )\n  // console.log(vaultHistory, toTokenAmount(mintedSqueeth, 18).toString(), toTokenAmount(openShortSqueeth, 18).toString())\n  return {\n    mintedSqueeth: toTokenAmount(mintedSqueeth, 18),\n    burnedSqueeth: toTokenAmount(burnedSqueeth, 18),\n    openShortSqueeth: toTokenAmount(openShortSqueeth, 18),\n    closeShortSqueeth: toTokenAmount(closeShortSqueeth, 18),\n    vaultHistory,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/hooks/useYourVaults.ts",
    "content": "import { QueryHookOptions, useQuery } from '@apollo/client'\nimport { useAtomValue } from 'jotai'\nimport { addressAtom, networkIdAtom } from 'src/state/wallet/atoms'\nimport { YOUR_VAULTS_QUERY } from '../queries/squeeth/vaultsQuery'\nimport { YourVaults, YourVaultsVariables } from '../queries/squeeth/__generated__/YourVaults'\nimport { squeethClient } from '../utils/apollo-client'\n\nexport default function useYourVaults(options?: QueryHookOptions<YourVaults, YourVaultsVariables>) {\n  const address = useAtomValue(addressAtom)\n  const networkId = useAtomValue(networkIdAtom)\n\n  return useQuery<YourVaults, YourVaultsVariables>(YOUR_VAULTS_QUERY, {\n    client: squeethClient[networkId],\n    variables: { ownerId: address?.toLowerCase() ?? '' },\n    skip: !address,\n    ...options,\n  })\n}\n"
  },
  {
    "path": "packages/frontend/src/lib/pnl.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { closestIndexTo, differenceInMinutes, format, subMinutes } from 'date-fns'\nimport { QueryClient } from 'react-query'\n\nimport { BIG_ZERO, TWELVEDATA_NO_PRICEDATA_DURATION } from '../constants/'\nimport { swaps_swaps } from '../queries/uniswap/__generated__/swaps'\nimport { VaultHistory_vaultHistories } from '../queries/squeeth/__generated__/VaultHistory'\nimport { toTokenAmount } from '@utils/calculations'\nimport { getHistoricEthPrice, getHistoricEthPrices } from '@hooks/useETHPrice'\nimport { getETHWithinOneDayPrices } from '@utils/ethPriceCharts'\nimport { Action } from '../../types/global_apollo'\n\ntype ShortPnLParams = {\n  wethAmount: BigNumber\n  buyQuote: BigNumber\n  ethPrice: BigNumber\n}\n\nexport function calcUnrealizedPnl({ wethAmount, buyQuote, ethPrice }: ShortPnLParams) {\n  if (\n    wethAmount.isEqualTo(0) ||\n    !wethAmount.isFinite() ||\n    buyQuote.isEqualTo(0) ||\n    !buyQuote.isFinite() ||\n    ethPrice.isEqualTo(0) ||\n    !ethPrice.isFinite()\n  ) {\n    return new BigNumber(0)\n  }\n\n  return wethAmount.minus(buyQuote).multipliedBy(ethPrice)\n}\n\ntype ShortGainParams = {\n  shortUnrealizedPNL: BigNumber\n  usdAmount: BigNumber\n  wethAmount: BigNumber\n  uniswapEthPrice: BigNumber\n}\n\nexport function calcShortGain({ shortUnrealizedPNL, usdAmount, wethAmount, uniswapEthPrice }: ShortGainParams) {\n  if (\n    wethAmount.isEqualTo(0) ||\n    shortUnrealizedPNL.isEqualTo(0) ||\n    uniswapEthPrice.isEqualTo(0) ||\n    usdAmount.isEqualTo(0)\n  ) {\n    return new BigNumber(0)\n  }\n  return shortUnrealizedPNL.div(usdAmount.plus(wethAmount.times(uniswapEthPrice).absoluteValue())).times(100)\n}\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      staleTime: Infinity,\n    },\n  },\n})\n\nexport async function calcETHCollateralPnl(\n  data: VaultHistory_vaultHistories[] | undefined,\n  uniswapEthPrice: BigNumber,\n  currentVaultEthBalance: BigNumber,\n) {\n  const vaultHistories = await getVaultHistoriesWithEthPrice(data || [])\n  const { deposits, withdrawals, priceError } = vaultHistories.reduce(\n    (acc, vaultHistory) => {\n      const ethPriceAtTimeOfAction = vaultHistory.ethPrice\n\n      if (ethPriceAtTimeOfAction?.isZero()) {\n        acc.priceError = true\n      }\n      if (vaultHistory.action === Action.DEPOSIT_COLLAT) {\n        acc.deposits = acc.deposits.plus(\n          new BigNumber(toTokenAmount(vaultHistory.ethCollateralAmount, 18)).times(ethPriceAtTimeOfAction),\n        )\n      } else if (vaultHistory.action === Action.WITHDRAW_COLLAT) {\n        acc.withdrawals = acc.withdrawals.plus(\n          new BigNumber(toTokenAmount(vaultHistory.ethCollateralAmount, 18)).times(ethPriceAtTimeOfAction),\n        )\n      }\n      return acc\n    },\n    { deposits: BIG_ZERO, withdrawals: BIG_ZERO, priceError: false },\n  )\n\n  return !priceError ? currentVaultEthBalance.times(uniswapEthPrice).minus(deposits.minus(withdrawals)) : BIG_ZERO\n}\n\n/**\n * getRelevantSwaps - gets the swaps that constitute the users current position\n * @param squeethAmount\n * @param swaps\n * @param isWethToken0\n * @param isLong\n * @returns array of swaps that add up to the user's squeethAmount\n */\nconst getRelevantSwaps = (squeethAmount: BigNumber, swaps: swaps_swaps[], isWethToken0: boolean, isLong = false) => {\n  let totalSqueeth = BIG_ZERO\n  const relevantSwaps = []\n  for (let index = swaps.length - 1; index >= 0; index--) {\n    const squeethAmountFromSwapsData = new BigNumber(isWethToken0 ? swaps[index].amount1 : swaps[index].amount0)\n    // squeethAmountFromSwaps data from uniswap is -ve when it's a buy and +ve when it's a sell\n    const sqthAmount = isLong ? squeethAmountFromSwapsData.negated() : squeethAmountFromSwapsData\n    totalSqueeth = totalSqueeth.plus(sqthAmount)\n    relevantSwaps.push(swaps[index])\n\n    //checking if the squeethAmount of the swaps in the relevantSwaps array add up to the user's position\n    if (squeethAmount.isEqualTo(totalSqueeth)) {\n      break\n    }\n  }\n  return relevantSwaps\n}\n\nexport function pnl(currentValue: BigNumber, cost: BigNumber): BigNumber {\n  return currentValue.minus(cost)\n}\n\nexport function pnlInPerct(currentValue: BigNumber, cost: BigNumber): BigNumber {\n  if (cost.isEqualTo(0)) return BIG_ZERO\n  return currentValue.dividedBy(cost).minus(1).times(100)\n}\n\nexport function pnlv2(currentValue: BigNumber, remainingDeposit: BigNumber): BigNumber {\n  return currentValue.minus(remainingDeposit)\n}\n\nexport function pnlInPerctv2(currentValue: BigNumber, remainingDeposit: BigNumber): BigNumber {\n  if (remainingDeposit.isEqualTo(0)) return BIG_ZERO\n  return currentValue.dividedBy(remainingDeposit).minus(1).times(100)\n}\n\nconst getSwapsWithEthPrice = async (swaps: swaps_swaps[]) => {\n  const timestamps = swaps.map((s) => Number(s.timestamp) * 1000)\n\n  // Don't fetch if already fetched\n  const ethPriceMap = await queryClient.fetchQuery(timestamps, () => getHistoricEthPrices(timestamps), {\n    staleTime: Infinity,\n  })\n\n  const swapsWithEthPrice = swaps.map((s) => ({\n    ...s,\n    ethPrice: new BigNumber(ethPriceMap[Number(s.timestamp) * 1000]),\n  }))\n\n  return swapsWithEthPrice\n}\n\nconst getVaultHistoriesWithEthPrice = async (vaultHistories: VaultHistory_vaultHistories[]) => {\n  const timestamps = vaultHistories.map((v) => Number(v.timestamp) * 1000)\n\n  // Don't fetch if already fetched\n  const ethPriceMap = await queryClient.fetchQuery(timestamps, () => getHistoricEthPrices(timestamps), {\n    staleTime: Infinity,\n  })\n\n  const historyWithEthPrice = vaultHistories.map((v) => ({\n    ...v,\n    ethPrice: new BigNumber(ethPriceMap[Number(v.timestamp) * 1000]),\n  }))\n\n  return historyWithEthPrice\n}\n\nexport async function calcDollarShortUnrealizedpnl(\n  swaps: swaps_swaps[],\n  isWethToken0: boolean,\n  positionValue: BigNumber,\n  uniswapEthPrice: BigNumber,\n  squeethAmount: BigNumber,\n  ethCollateralPnl: BigNumber,\n) {\n  const relevantSwaps = getRelevantSwaps(squeethAmount, swaps, isWethToken0)\n  const relevantSwapsWithEthPrice = await getSwapsWithEthPrice(relevantSwaps)\n\n  const { totalWethInUSD, priceError } = relevantSwapsWithEthPrice.reduce(\n    (acc, swap, index) => {\n      const wethAmt = new BigNumber(isWethToken0 ? swap.amount0 : swap.amount1)\n\n      const ethPriceWhenOpened = swap.ethPrice\n\n      if (ethPriceWhenOpened?.isZero()) {\n        acc.priceError = true\n      }\n\n      acc.totalWethInUSD = acc.totalWethInUSD.plus(wethAmt.negated().times(ethPriceWhenOpened))\n\n      return acc\n    },\n    { totalWethInUSD: BIG_ZERO, priceError: false },\n  )\n\n  const usd = totalWethInUSD.minus(positionValue).plus(ethCollateralPnl)\n\n  return {\n    usd,\n    eth: usd.div(uniswapEthPrice),\n    loading: priceError,\n  }\n}\n\nexport async function calcDollarLongUnrealizedpnl(\n  swaps: swaps_swaps[],\n  isWethToken0: boolean,\n  positionValue: BigNumber,\n  uniswapEthPrice: BigNumber,\n  squeethAmount: BigNumber,\n) {\n  const relevantSwaps = getRelevantSwaps(squeethAmount, swaps, isWethToken0, true)\n  const relevantSwapsWithEthPrice = await getSwapsWithEthPrice(relevantSwaps)\n\n  const { totalUSDWethAmount, priceError } = relevantSwapsWithEthPrice.reduce(\n    (acc, swap) => {\n      const wethAmt = new BigNumber(isWethToken0 ? swap.amount0 : swap.amount1)\n\n      const ethPriceWhenOpened = swap.ethPrice\n\n      if (ethPriceWhenOpened?.isZero()) {\n        acc.priceError = true\n      }\n\n      acc.totalUSDWethAmount = acc.totalUSDWethAmount.plus(wethAmt.times(ethPriceWhenOpened ?? BIG_ZERO))\n\n      return acc\n    },\n    { totalUSDWethAmount: BIG_ZERO, priceError: false },\n  )\n\n  const usdValue = !priceError ? positionValue.minus(totalUSDWethAmount) : BIG_ZERO\n  return {\n    usd: usdValue,\n    eth: !usdValue.isZero() ? usdValue.div(uniswapEthPrice) : BIG_ZERO,\n    loading: priceError,\n  }\n}\n\nconst historicPriceQueryKeys = {\n  historicPrice: (timestamp: string) => [`userPrice_${timestamp}`],\n}\n\n/**\n * @deprecated\n */\nasync function getEthPriceAtTransactionTime(timestamp: string) {\n  try {\n    const timeInMilliseconds = new Date(Number(timestamp) * 1000).setUTCSeconds(0, 0)\n    const currentTimeInMilliseconds = Date.now()\n    // Gets difference in minutes between the current time\n    // and the timestamp for which ethPrice data is being requested\n    const diff = differenceInMinutes(currentTimeInMilliseconds, timeInMilliseconds, { roundingMethod: 'round' })\n\n    if (diff < TWELVEDATA_NO_PRICEDATA_DURATION) {\n      // call coingecko\n      const priceData = await queryClient.fetchQuery(\n        historicPriceQueryKeys.historicPrice(timestamp),\n        () => getETHWithinOneDayPrices(),\n        {\n          staleTime: Infinity,\n        },\n      )\n\n      if (priceData.length === 1) {\n        // call twelvedata\n        const dateTimeString = format(\n          new Date(subMinutes(new Date(), TWELVEDATA_NO_PRICEDATA_DURATION)).setUTCSeconds(0),\n          'yyyy-MM-dd HH:mm:ss',\n        )\n        return await queryClient.fetchQuery(\n          historicPriceQueryKeys.historicPrice(timestamp),\n          () => getHistoricEthPrice(dateTimeString),\n          {\n            staleTime: Infinity,\n          },\n        )\n      }\n\n      const dateList = priceData.map((item) => item.time)\n      const dateIndex = closestIndexTo(timeInMilliseconds, dateList)\n\n      if (dateIndex) {\n        return new BigNumber(priceData[dateIndex].value)\n      }\n\n      const dateTimeString = format(\n        new Date(subMinutes(new Date(), TWELVEDATA_NO_PRICEDATA_DURATION)).setUTCSeconds(0),\n        'yyyy-MM-dd HH:mm:ss',\n      )\n      return await queryClient.fetchQuery(\n        historicPriceQueryKeys.historicPrice(timestamp),\n        () => getHistoricEthPrice(dateTimeString),\n        {\n          staleTime: Infinity,\n        },\n      )\n    }\n\n    // call twelvedata\n    const dateTimeString = format(new Date(timeInMilliseconds), 'yyyy-MM-dd HH:mm:ss')\n\n    return await queryClient.fetchQuery(\n      historicPriceQueryKeys.historicPrice(timestamp),\n      () => getHistoricEthPrice(dateTimeString),\n      {\n        staleTime: Infinity,\n      },\n    )\n  } catch (error) {\n    return BIG_ZERO\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/markdown/pos-merge.md",
    "content": "### What Opyn Users Should Know Ahead of The Merge\n\n### Last Modified: September 13, 2022\n\n&nbsp;\n&nbsp;\n&nbsp;\n\nOpyn supports The Merge and does not have plans to support any forks in our web app. Opyn will only work on the canonical chain that is moving to PoS. If a canonical PoW ETH fork emerges, the Squeeth interface will not support forked PoW Squeeth, vault NFTs, or Crab Vault receipt tokens. To learn more about The Merge, see Ethereum’s [announcement](https://blog.ethereum.org/2022/08/24/mainnet-merge-announcement).\n\nAs an Opyn user, you do not need to do anything. Assuming the Merge is successful, the Squeeth Protocol will continue to work without issue through the transition from proof of work (PoW) to proof of stake (PoS). Opyn’s web app ([opyn.co](https://opyn.co/)) will also continue to function. Though if any third-party infrastructure providers (e.g. node providers) have downtime, some users may experience brief periods of unavailability.\n\nIt’s also worth noting the possibility of increased ETH price volatility leading up to and around the merge. Squeeth offers exposure to the squared price of Ethereum, so ETH volatility is particularly pertinent. Users who are short Squeeth or deposited in the Crab Strategy should monitor ETH price volatility and liquidation levels. Users who are long Squeeth should continue to monitor their positions and the funding cost of Squeeth. Please take note of The Merge timeline and manage your positions accordingly.\n\nGiven Squeeth uses the [Uniswap v3 GMA](https://uniswap.org/whitepaper-v3.pdf) (geometric moving average) TWAP as an oracle price, we want to highlight changes that accompany The Merge:\n\nUniswap v3 oracles were designed with PoW security tradeoffs in mind, where it’s predictably difficult for a single entity to mine multiple blocks in a row. To combat the possibility of a Uniswap v3 GMA TWAP oracle manipulation for Squeeth, Opyn uses the ETH-USDC pool and sets a TWAP period long enough to reduce the likelihood of manipulation attempts. Uniswap details the new risks for TWAP under PoS [here](https://uniswap.org/blog/what-to-know-pre-merge).\n\nUsers utilizing Opyn’s gamma protocol infra also do not need to do anything.\n\nThe Merge will occur around ETH mainnet block height of 15,540,293, which, at the time of writing, is [estimated to happen between Thu Sep 15 2:23 UTC & Thu Sep 15 3:33 UTC](https://bordel.wtf/). If The Merge delays and occurs within 1 hour of 8:00 UTC on Fri Sep 16, it’s possible that gamma contracts will be paused to ensure accurate oracle pricing for option expiration.\n\n*Note: Trading digital assets confers high risk due to large price fluctuations. Before trading, please have a full understanding of all the risks associated with investing in digital assets.*\n\n*It is your responsibility to understand the implications of the Merge. Opyn is not liable for any losses incurred.*\n\nWe are looking forward to The Merge! Please reach out in [Discord](http://discord.gg/opyn) if you have any questions.\n\n"
  },
  {
    "path": "packages/frontend/src/markdown/privacy-policy.md",
    "content": "### Opyn Privacy Policy\r\n\r\n### Last Modified: November 19, 2022\r\n\r\n&nbsp;\r\n&nbsp;\r\n&nbsp;\r\n\r\n#### 1. Introduction\r\n\r\nWelcome to the Opyn, Inc. (“Opyn”) Privacy Policy (the “Privacy Policy”). This Privacy Policy explains how we collect and use any information you submit when using the Interface, as defined within the Opyn User Terms of Service (“User Terms”). This Privacy Policy should be read in conjunction with the User Terms and is integrated into the User Terms. All capitalized proper nouns not defined in this Privacy Policy will have the same definitions and meanings as defined by the User Terms. Please review the Privacy Policy periodically as we may revise it from time to time. If you do not agree with or accept our Privacy Policy in its entirety, you must not access or use the Interface. If you use the Interface following a change to the terms of this Privacy Policy you agree to accept the revised policies. Please do not submit any information to us if you reside in a Restricted Territory or if you or your organization is a Restricted Person or US Person.\r\n\r\n#### 2. Information Collected\r\n\r\nAt Opyn, we may collect the following information from you when you access or use the Interface:\r\n\r\n- Digital Wallet address, transaction history, and other associated information.\r\n- Interactions with the Interface including but not limited to usage data and preferences.\r\n- Online identifiers like computer and browser information, operating system, data usage, data transferred, geo location, and IP address.\r\n- Information provided by third parties or publicly accessible databases which we may combine with other information collected.\r\n\r\n#### 3. Use of Your Information\r\n\r\nWhere applicable, we will use any information collected as directed by you and in accordance with the User Terms. Further, we may use your information in the following ways:\r\n\r\n- To provide any services offered by the Interface, to process transactions, and to maintain, develop, and operate the Interface.\r\n- To enforce the Privacy Policy or User Terms; to comply with applicable laws; to respond to third party, legal, and governmental inquiries; and to investigate any illegal or fraudulent activity.\r\n- To enhance or improve our users’ experiences.\r\n- To send and receive information to you via selected communication methods as set forth within the User Terms or where requested by you.\r\n- To notify you of additional Opyn services and updates.\r\n- To assist in maintaining the functionality, safety, and security of the Interface.\r\n- To share your information with third party contractors hired by us to perform functions and provide services to us such as infrastructure providers, Blockchain Technology providers, marketing providers, and other vendors we use to make available the Interface.\r\n- To release to governmental entities, authorities, or legal claimants as required.\r\n\r\n#### 4. Analytics\r\n\r\nThird party analytics tools collect or use information about your use of the Interface, which helps us improve the user experience. We want to process as little personal information as possible when you use the Interface. We use [Amplitude](https://amplitude.com/amplitude-security-and-privacy), a user analytics platform, in order to track how users interact with the interface in order to establish, implement, and evaluate how to improve the user experience. Amplitude uses cookies to help analyze how users use the site. For more information on the Amplitude cookie and how to disable it, go to section [6.2 “Cookies the Interface Uses.”](#6-cookies)\r\n\r\n#### 5. Sanctions and Risk Management\r\n\r\nWe use Chainalysis, a third party blockchain intelligence service provider to detect, prevent, and mitigate financial crime and other illicit or harmful activities on the Interface. Chainalysis combines on-chain data and real-world investigations to identify financial crime and other high-risk activities. Opyn applies an industry-wide standard of risk categories (e.g., sanctions, ransomware, child exploitation, stolen funds). Addresses that fall into a risk category are blocked from accessing the Squeeth App. User wallet addresses connecting to the Squeeth app will be cross-checked using a Chainalysis API with designated risk categories. Your address is shared with Chainalysis, but no metadata or IP addresses are shared. Users are not identified in this risk-assessment process.  We do not retain the information we collect any longer than necessary for these purposes.\r\n\r\n[Sentry](https://docs.sentry.io/platforms/javascript/guides/nextjs/enriching-events/context/) is used to record blocked address events that occur through the Chainalysis API.\r\n\r\n#### 6. Cookies\r\n\r\nWhen you first come to the Interface, you may receive a notification that cookies are present. By clicking or tapping “Accept,” you agree to the use of these cookies as described here. By tapping “Decline,” you refuse to accept cookies from the Interface. If you refuse cookies, you might not be able to use other cookie-dependent features of the Interface. To manage specific Cookie settings, review this Privacy Policy for further information.\r\n\r\n##### **6.1 What is a Cookie**\r\nA cookie is a small string of text that a website (or online service) stores on a user’s browser. It saves data on your browser about your visit to our site or other sites. It often includes a unique identifier (e.g., cookie #123).\r\n\r\n- “First-party cookies” are cookies set by us (or on our behalf) on our site. \r\n- “Third-party cookies” are cookies set by other companies whose functionality is embedded into a site (e.g., google.com).\r\n- “Session cookies” are temporary cookies stored on your device while you visit the Interface. They expire when you close your browser. \r\n- “Persistent cookies” are stored on your browser for a period of time after you leave the Interface. Persistent cookies expire on a set expiration date or when they are deleted manually.\r\n\r\n##### **6.2 Cookies the Interface Uses**\r\n\r\nAmplitude: We use a third-party, persistent session SDK javascript cookie from Amplitude, AMP_###,  to analyze how users use the interface. Third party analytics tools collect or use information about your use of the Interface, which helps us improve the user experience. The information generated by the cookie about your use of the website will be transmitted to and stored by Amplitude on servers in the European Economic Area. We do not track IP addresses through Amplitude. Amplitude will use this information on behalf of the Interface for the purpose of evaluating your use of the Interface, compiling reports on Interface activity and providing other services relating to Interface activity and internet usage. The IP-address that your browser conveys within the scope of Amplitude will not be associated with any other data held by Amplitude. \r\n\r\nThis performance cookie will be stored for up to 1 year. \r\n\r\nIn order to opt-out of the Amplitude cookie click [HERE](/opt-out).\r\n\r\n##### **6.3 Disabling Cookies Through Your Browser**\r\n\r\nMost browsers automatically accept cookies, but this is typically something you can adjust. Information for each browser can be found in the links below:\r\n\r\n- [Safari on desktop](https://support.apple.com/guide/safari/manage-cookies-and-website-data-sfri11471/mac) and [Safari Mobile (iPhone and iPads)](https://support.apple.com/en-us/HT201265): Note that, by default, Safari is engineered to protect you from being tracked from site to site unless you disable Intelligent Tracking Prevention (ITP).\r\n- [Firefox](https://support.mozilla.org/en-US/kb/clear-cookies-and-site-data-firefox?redirectlocale=en-US&redirectslug=delete-cookies-remove-info-websites-stored): By default, Firefox protects you from cross-site tracking so long as you have not disabled Enhanced Tracking Protection (ETP). There is therefore less need to manage cookies to protect your privacy.\r\n- [Chrome](https://support.google.com/chrome/answer/95647?hl=en)\r\n- [Microsoft Edge](https://support.microsoft.com/en-us/help/4468242/microsoft-edge-browsing-data-and-privacy-microsoft-privacy): Enabling tracking prevention with Edge will protect you from being tracked between sites, such that there will be less of a need to manage your cookies in order to protect your privacy.\r\n- [Samsung Internet Browser](https://aboutdevice.com/clear-cookies-history-cache-on-samsung-internet-browser-android/). Note that Samsung Internet Browser includes “Smart Watch” protection that works to help protect you from being tracked across sites.\r\n- Brave: Brave has several mechanisms to keep you from being tracked online, but you can [change your privacy settings](https://support.brave.com/hc/en-us/articles/360017989132-How-do-I-change-my-Privacy-Settings-) if you wish to have greater control over its decisions. \r\n\r\nFor more information about other browsers, please refer to this [“All About Cookies” guide](https://www.allaboutcookies.org/manage-cookies/).\r\n\r\nTo reset your device identifier, follow [Google instructions](https://support.google.com/googleplay/android-developer/answer/6048248?hl=en) and [Apple instructions](https://support.apple.com/en-us/HT205223).\r\n\r\n#### 7. Governmental Entities\r\n\r\nWe may combine any information collected with information made available in third party databases and public sources. We may use such information to address claims, to respond to governmental inquires or requests, or to investigate issues. Further, such information may be shared with governmental entities including criminal, civil, and, regulatory agencies. Please be aware that we may keep copies of your information subject to our internal retention policies for the purposes of abiding by Applicable Laws or to prevent fraud or injury to a third party.\r\n\r\n#### 8. Accessing and Editing Your Information\r\n\r\nTo access your Personal Data and information about how Opyn collects and uses your personal data, obtain a machine-readable, portable copy of your file, or to delete your personal data, please email us at legal@opyn.co.  Your ethereum wallet address is required as we cannot otherwise identify any associated data with your activity to execute your request.\r\n\r\nTo delete your order/transactional information. You may request to have this information deleted from Opyn’s personal records, which will restrict your access to the information. However, the information will be archived and kept on file for 10 years to comply with legal and contractual requirements. \r\n\r\nPlease note, however, that ethereum-based transactions by their very nature as a transaction on the Ethereum blockchain are publicly available transactions that cannot be deleted from public record as they are recorded on the ethereum blockchain. For more information on how transactions are recorded on Ethereum see the Ethereum Foundation’s website [HERE](https://ethereum.org/en/developers/docs/transactions/).\r\n\r\nIf you have any questions regarding any information collected please contact us at legal@opyn.co.\r\n#### 9. Opt Out of Commercial, Non-Commercial Communications and Do Not Track\r\n\r\nIf you decide to provide us with your contact information, you agree that we may send you communications via emails or other methods. However, you may choose to unsubscribe from certain communications by notifying Opyn that you no longer wish to receive these communications, we will endeavour to honor such requests promptly. If you wish to opt out of certain communications or information collection, please contact us at legal@opyn.co.\r\n\r\n#### 10. Third Party Websites and Links\r\n\r\nWhen accessing a third party site through our Interface, you acknowledge that you are aware that these third party websites are not screened for privacy or security issues by us, and you release us from any liability for the conduct of these third party websites. Please be aware that this Privacy Policy, and any other policies in place, in addition to any amendments, do not create rights enforceable by third parties. Opyn bears no responsibility for the information collected or used by any third party website. You must review their policies to understand how their information collection practices work.\r\n\r\n#### 11. Security Measures\r\n\r\nWe make reasonable attempts to protect your information by using physical and electronic safeguards such as encryption. However, as the Interface relies on Blockchain Technology and electronic infrastructure that we have no control over, we can make no guarantees as to the security or privacy of your information submitted. For this reason, we recommend that you use anti-virus software, firewalls, and other precautions to protect yourself from security and privacy threats.\r\n\r\n#### 12. Age Compliance\r\n\r\nWe do not collect or process any information for any persons under the age of majority in your jurisdiction (“Minors”). Please do not submit information to us if you are under the age of majority in your applicable jurisdiction. In the event that we have inadvertently collected any information from a Minor please contact us immediately.\r\n\r\n#### 13. International Transfer\r\n\r\nYour information may be transferred to – and maintained on – computers located outside of your state, province, country, or other governmental jurisdiction where the privacy laws may not be as protective as those in your jurisdiction. Your consent to this Privacy Policy followed by your submission of such information represents your agreement to that transfer. Information that is submitted to Opyn will be collected, processed, stored, disclosed, and disposed of in accordance with applicable United States’ law and this policy. In addition, such information may be stored on servers located outside your resident jurisdiction. United States’ law may not provide the degree of protection for information that is available in other countries.\r\n\r\n#### 14. Merger and Acquisition\r\n\r\nIn the event that Opyn is involved in a bankruptcy, merger, acquisition, reorganization or sale of assets, your information may be transferred as part of that transaction. Please be aware that once the information is transferred your privacy rights may change.\r\n\r\n#### 15. Amendments\r\n\r\nLike our User Terms, we may amend this Privacy Policy from time to time. When we amend this Privacy Policy, we will modify the date listed on this Privacy Policy or we may contact you. You must agree to the amendments as a condition of your continued use of our Interface. If you do not agree, you must immediately cease using our Interface.\r\n\r\n#### 16. Contact\r\n\r\nIf you have any questions regarding our Privacy Policy please contact us at legal@opyn.co.\r\n\r\n"
  },
  {
    "path": "packages/frontend/src/markdown/terms-of-service-faq.md",
    "content": "### Terms of Service FAQ\n\n#### Frequently Asked Questions about the Squeeth Terms of Service\n\n&nbsp;\n\n##### Periodically, we update our [Terms of Service](https://squeeth.opyn.co/terms-of-service) as we work to improve the Squeeth App user experience. We want our users to understand exactly what’s contained in updates and why we’ve made those updates.\n\n&nbsp;\n\n\n#### Q. What are the major changes in the August 25, 2022 Updated Terms of Service?\n\n#### A. Opyn is implementing a new risk-management system that assesses and blocks Ethereum addresses associated with certain legally prohibited conduct that attempt to interact with [opyn.co](https://opyn.co/).\n\n&nbsp;\n\n#### Q. What kind of risk are you hoping to assess and how?\n\n#### A. We use [Chainalysis](https://demo.chainalysis.com/request-a-demo/?utm_source=google&utm_medium=cpc&utm_campaign={campaign}&utm_term=chainalysis&utm_content=558401973804&gclid=CjwKCAjwrNmWBhA4EiwAHbjEQCpNwFS8fzEmA-hBxxpdLQaX1jgTU4ZsiPPLZ8MZSeTWA_wLHg_LthoCLIgQAvD_BwE), a blockchain intelligence service provider. Chainalysis combines on-chain data and real-world investigations to identify financial crime and other high-risk activities. Opyn applies an industry-wide standard of risk categories (e.g., sanctions, ransomware, child exploitation, stolen funds). Addresses that fall into a risk category are blocked from accessing the Squeeth App. \n\n&nbsp;\n\n#### Q. What data is collected in this process?\n\n#### A. User wallet addresses connecting to the Squeeth app will be cross-checked using a Chainalysis API with designated risk categories. Your address is shared with Chainalysis, but no metadata or IP addresses are shared. Users will not be identified in this risk-assessment process.\n\n&nbsp;\n\n#### Q. Will this risk-assessment impact access to the Squeeth Protocol through other interfaces?\n\n#### A. No. Only the Ethereum addresses interacting with the Squeeth app interface will be cross-checked against standards for risk assessment. This includes [opyn.co](https://opyn.co/). We will not be cross-checking the addresses of those interacting with the underlying Uniswap Protocol or other protocols via other interfaces. Given the Protocol’s decentralized and open-source nature, we do not control users’ access to it via any portal other than our own app.\n\n&nbsp;\n\n#### Q. What other APIs/data services does the Squeeth Interface use?\n\n#### A. The Squeeth app also uses the Alchemy API, The Graph API, Fathom Analytics, and Sentry. Alchemy fetches on-chain data and constructs contract calls with the Alchemy API. The Graph API is used to obtain market data such as liquidity distribution of a pool. Fathom Analytics is used to learn more about user behavior and improve the user experience through anonymized data. We do not use cookies for Fathom Analytics. Sentry is used to record blocked address events that occur through the Chainalysis API. \n\n#### For more information on our API and data collection policies see Opyn’s Privacy Policy. \n\n&nbsp;\n\n#### Q. My address was incorrectly blocked. How can I remedy this? \n\n#### A. If you believe your address has been incorrectly flagged, please contact legal@opyn.co.\n"
  },
  {
    "path": "packages/frontend/src/markdown/terms-of-service.md",
    "content": "### Opyn User Terms of Service\r\n\r\n### Last Updated: July 1, 2024\r\n\r\n&nbsp;\r\n&nbsp;\r\n&nbsp;\r\n\r\n#### 1. Introduction\r\n\r\nWelcome to [https://opyn.co](https://opyn.co), a website-hosted user interface, and any associated software or services (collectively the \"Interface\") provided by Opyn, Inc. (“Opyn”, \"we\", \"our\", or \"us\"). The Interface provides access to a decentralized protocol on the blockchain that allows users to transact certain digital assets through power perpetual contracts (the \"Protocol\"). The Opyn User Terms of Service is an agreement (“Agreement” or “Terms”) between Opyn, the owner and operator of the Interface, and you (“you”, “your” or “user(s)”), a user of the Interface. Where you enter into this Agreement on behalf of a legal entity or organization you represent and warrant that you have the authority to bind such legal entity or organization to this Agreement. \r\n\r\nPLEASE BE AWARE THAT THERE ARE ARBITRATION AND CLASS ACTION PROVISIONS THAT MAY AFFECT YOUR RIGHTS. \r\n\r\nYou must read this Agreement carefully. By accessing or using the Interface, you signify that you have read, understand, and agree to be bound by this Agreement in its entirety. If you do not agree to these Terms, you are not authorized to access or use the Interface.\r\n\r\nOUR INTERFACE IS NOT OFFERED TO PERSONS OR ENTITIES WHO RESIDE IN, ARE CITIZENS OF, ARE LOCATED IN, ARE INCORPORATED IN, OR HAVE A REGISTERED OFFICE IN THE UNITED STATES OF AMERICA (COLLECTIVELY, “US PERSONS”). MOREOVER, OUR INTERFACE IS NOT OFFERED TO PERSONS OR ENTITIES WHO RESIDE IN, ARE CITIZENS OF, ARE LOCATED IN, ARE INCORPORATED IN, OR HAVE A REGISTERED OFFICE IN ANY RESTRICTED TERRITORY, DEFINED BELOW (ANY SUCH PERSON OR ENTITY FROM A RESTRICTED TERRITORY, A “RESTRICTED PERSON”). WE DO NOT MAKE EXCEPTIONS; THEREFORE, IF YOU ARE A US PERSON OR RESTRICTED PERSON DO NOT ATTEMPT TO USE OUR PROTOCOL OR ACCESS OR ATTEMPT TO ACCESS THE INTERFACE. USE OF A VIRTUAL PRIVATE NETWORK (“VPN”) TO CIRCUMVENT THE RESTRICTIONS SET FORTH HEREIN IS PROHIBITED. WE RESERVE THE RIGHT TO RESTRICT ANY USER’S ACCESS TO THE INTERFACE SUBJECT TO ANY RESTRICTIONS WE MAY SET FORTH IN THIS AGREEMENT.\r\n\r\n#### 2. Use and Eligibility\r\n\r\nAs a condition to accessing or using the Interface, you represent, warrant, and covenant to Opyn the following:\r\n\r\n- if you are entering into these Terms to access the Protocol or, in the future, to access the Protocol, then you are not a US Person;\r\n- you are not a resident, national, or agent of Belarus, Burma (Myanmar), Cote D'Ivoire (Ivory Coast), Cuba, Democratic Republic of Congo, Iran, Iraq, Liberia, North Korea, Sudan, Syria, Ukraine, Zimbabwe, or any other country or region that is subject of comprehensive country-wide or region-wide economic sanction by the United States, the United Kingdom or the European Union (collectively, “Restricted Territories” or singularly a “Restricted Territory”);\r\n- you are not located in, reside in, incorporated in, or have a registered office in the Dominion of Canada, or any other country which prohibits the offering of leverage in connection with trading of crypto contracts or crypto assets, or generally prohibits digital asset transactions (collectively, “Restricted Territories” or singularly a “Restricted Territory”);  \r\n- you are not a member of any sanctions list or equivalent maintained by the United States government, the United Kingdom government, the European Union, or the United Nations (collectively, “Sanctions Lists Persons”);\r\n- you do not intend to transact with any Restricted Person or Sanctions List Person;\r\n- you only will transfer legally-obtained Digital Assets (defined below) that belong to you (or you are legally authorized to use), when using, transacting, or connecting to the Interface;\r\n- you shall maintain the security and confidentiality of your private keys associated with any Blockchain Technology (defined below) address, passwords, and API keys.\r\n- your access to the Interface is not (a) prohibited by and does not otherwise violate or assist you to violate any domestic or foreign law, rule, statute, regulation, by-law, order, protocol, code, decree, or another directive, requirement, or guideline, published or in force that applies to or is otherwise intended to govern or regulate any person, property, transaction, activity, event or other matter, including any rule, order, judgment, directive or other requirement or guideline issued by any domestic or foreign federal, provincial or state, municipal, local or other governmental, regulatory, judicial or administrative authority having jurisdiction over Opyn, you, the Interface or Protocol, or as otherwise duly enacted, enforceable by law, the common law or equity (collectively, “Applicable Laws”); and (b) contributing to or facilitating any illegal activity;\r\n- you will obey all Applicable Laws in connection with using the Interface, and you will not use the Interface or Protocol if any Applicable Laws prohibit you from doing so;\r\n- you understand the inherent risks associated with Blockchain Technology, the Protocol, and the Interface, which may result in the loss of some or all of your Digital Assets;\r\n- you have sufficient knowledge, market sophistication, professional advice, and experience to make your evaluation of the merits and risks of any transaction conducted in connection with the Interface, Protocol, or any Digital Asset;\r\n- you accept all consequences of using the Interface, including the risk that you may lose access to your Digital Assets indefinitely;\r\n- you are solely responsible for evaluating and understanding any risks related to any transactions involving the Interface, Protocol, and your Digital Assets including, but not limited to, long or short positions using the Protocol; and\r\n- you do not, and will not, use VPN software or any other privacy or anonymization tools or techniques to circumvent, or attempt to circumvent, any restrictions that apply to the Interface.\r\n\r\n#### 3. Age\r\n\r\nYou represent and warrant that you are at least the age of majority in your jurisdiction (e.g., eighteen years old) and have the full right, power, and authority to enter into and comply with the terms and conditions of this Agreement on behalf of yourself or any company or legal entity for which you may access or use the Interface.\r\n\r\n#### 4. Privacy\r\n\r\nWe care about your privacy. Please note that when you use the Interface, you are interacting with Blockchain Technology, which provides transparency into your transactions. Opyn does not control and is not responsible for any information you make public on Blockchain Technology by either using the Interface or accessing the Protocol. \r\n\r\nThe only information we collect from you is your blockchain wallet address, completed transaction hashes, and the digital asset names, symbols, or other blockchain identifiers of the digital assets that you use for transactions. We do not collect any personal information from you (e.g., your name or other identifiers that can be linked to you). We do, however, use third-party service providers, like Alchemy and Fathom Analytics. We do not control how these third parties handle your data and you should review their privacy policies to understand how they collect, use, and share your personal information. For more information, please see our [Privacy Policy](https://opyn.co/privacy-policy).\r\n\r\nWe use the Digital wallet address that you use to connect with the Interface to detect, prevent, and mitigate financial crime and other illicit or harmful activities on the Interface. For these purposes, we may share the Digital wallet address we collect with blockchain analytics providers. We share information with these service providers only so that they can help us promote the safety, security, and integrity of the Interface. We do not retain the information we collect any longer than necessary for these purposes.\r\n\r\nIf you have additional questions regarding our data privacy practices please visit our [Privacy Policy](https://opyn.co/privacy-policy). Our Privacy Policy is incorporated by reference into this Agreement.\r\n\r\n#### 5. Prohibited Activity\r\n\r\nYou may not use the Interface to engage in the following categories of activity set forth below or any activities that we determine in our sole discretion may harm us or a third party (“Prohibited Uses”). The Prohibited Uses include but are not limited to:\r\n\r\n- Any activity that violates any relevant and applicable anti-money laundering and anti-terrorist financing laws and sanctions programs, such as, without limitation, the Bank Secrecy Act and the U.S. Department of Treasury’s Office of Foreign Asset Controls (“Financing Laws”). By using the Interface, you agree that we must comply with Applicable Law including any Financing Laws, which may require us to, upon request by government agencies, take certain actions or provide information which we deem necessary, which may not be in your best interests.\r\n- Any transactions involving items that infringe or violate any copyright, trademark, right of publicity or privacy or any other proprietary right under Applicable Law, including but not limited to, sales, distribution, or access to counterfeit software, or other licensed materials without the appropriate authorization from the rights holder; use of Opyn’s Intellectual Property (defined below) without express consent from Opyn.\r\n- Any activity that seeks to interfere with or compromise the integrity, security, or proper functioning of the Interface or computer, server, network, personal device, or other information technology system, including, but not limited to, the deployment of viruses; denial-of-service attacks; use of any robot, spider, crawler, scraper or other automated means to extract or export data collected through the Interface; and conduct that imposes, or may impose, an unreasonable or disproportionately large load on our infrastructure.\r\n- Any activity that seeks to defraud us or any other person or entity, including, but not limited to, providing any false, inaccurate, or misleading information in order to unlawfully obtain the property of another, or any action that implies an untrue endorsement by or affiliation with Opyn.\r\n- Any activity that violates any Applicable Law including but not limited to laws or regulations concerning the integrity of trading markets such as manipulative tactics like spoofing or wash trading.\r\n- Any use of the Interface to stalk, harass, bully, or harm another individual, or use of the Interface in any way that is defamatory, obscene, invasive, threatening, or harassing.\r\n\r\n#### 6. Access\r\n\r\nAfter connecting your Digital Wallet (defined below) and complying with all obligations as set forth within this Agreement, we may grant you a fully revocable right to access and use the Interface in accordance with this Agreement and any additional instructions. Your access and use of the Interface is limited to yourself, and where you are an organization or entity any persons authorized by your organization or entity, you may not transfer or assign your access to any third parties. All rights not explicitly granted are reserved for Opyn. Your access to use our Interface may be suspended or terminated, If you breach any of these access provisions or at our discretion. Additionally, we may revoke your access to our Interface if we believe that your actions may harm us, our business interests, or any third party rights. Failure by us to revoke your access does not act as a waiver of your conduct. Nothing in this Agreement obligates us to provide you any access or use of the Interface.\r\n\r\n#### 7. Digital Wallet\r\n\r\nIn order to access the Protocol through the Interface you may be required to connect a digital wallet that is hosted by you or a third party (“Digital Wallet”) that contains digital assets (“Digital Assets”) legally owned by you. You are solely responsible for any transactions or transmissions that occur with your Digital Wallet.\r\n\r\nYou agree to notify Opyn immediately of any unauthorized use or other breach of security of your Digital Wallet. Opyn will not be liable for any losses you incur as a result of someone else using your Digital Wallet. However, you could be held liable for losses incurred by Opyn or another party due to someone else using your Digital Wallet.\r\n\r\nAny Digital Wallets connected to the Interface are non-custodial, meaning that Opyn does not control your Digital Wallet and has no access to your private encryption keys. Under no circumstances should you attempt to use your Digital Wallet to store or transact any non-supported Digital Assets. Opyn assumes no responsibility or liability in connection with any usage of your Digital Wallet with the Interface or Protocol, and you are solely responsible for your use of your Digital Wallet, including transfers of Digital Assets.\r\n\r\n#### 8. No Professional Advice or Fiduciary Duties\r\n\r\nAll information accessible through the Interface is for informational purposes only and should not be construed as investment, tax, or legal advice. You should not take, or refrain from taking, any action based on any information contained within the Interface or any other information that we make available at any time, including, without limitation, blog posts, articles, links to third-party content, discord content, news feeds, tutorials, tweets, and videos. Before you make any financial, legal, or other decisions involving the Interface, you should seek independent professional advice from an individual who is licensed and qualified in the area for which such advice would be appropriate.\r\n\r\nWe are not your broker, intermediary, agent or advisor and have no fiduciary relationship or obligation with you when you use the Interface or Protocol. We have no liability for any of your activities or decisions made while using the Interface. This Agreement is not intended to, and does not, create or impose any fiduciary duties on us. To the fullest extent permitted by law, you acknowledge and agree that we owe no fiduciary duties or liabilities to you or any other party, and that to the extent any such duties or liabilities may exist at law or in equity, those duties and liabilities are hereby irrevocably disclaimed, waived, and eliminated. You further agree that the only duties and obligations that we owe you are those set out expressly in this Agreement.\r\n\r\n#### 9. Interface\r\n\r\n- Use of the Interface, in particular for transactions involving Digital Assets, are highly volatile, experimental, and may carry financial risk. All transaction decisions are made solely by you. We accept no responsibility whatsoever for, and will in no circumstances be liable to you in connection with, your use of the Interface for performing Digital Asset transactions through the Protocol, including but not limited to you entering into any long short positions or trading Digital Assets.\r\n- The Interface attempts to provide up-to-date information for all Digital Assets listed; however, due to the nature of Digital Assets some information may be out of date or inaccurate. As you control your own Digital Wallet you are solely responsible for verifying any information regarding the Digital Assets, the Interface, and the Protocol. No representation is made as to the accuracy, completeness, or appropriateness for any particular purpose of any information distributed via the Interface or otherwise encountered when using the Interface. We are not liable to you for any inaccurately quoted information including but not limited to Digital Asset rates or pricing rates for any Digital Assets.\r\n- Our Interface cannot control the timing of any transactions, transaction times are based on your Digital Assets and the Blockchain Technology selected, and we are not liable or responsible for any delays or any issues due to untimeliness of any transactions initiated through the Interface. Use of the Interface is at your sole risk and liability.\r\n\r\n#### 10. Protocol\r\n\r\nThe developed Protocol is built through smart contracts and subject to the operating procedures of any underlying Blockchain Technology. Your use and access to the Protocol is at your sole risk and liability. You understand that the Protocol remains under development, which creates technological, trading, and other risks when using the Interface. These risks include, but are not limited to, delays or losses in trades, withdrawals, and Digital Assets. You agree that these risks may materially impact your transactions while using the Interface, which could result in the loss of the transaction or a complete loss of your Digital Assets. As the Protocol and Blockchain Technology supporting the Protocol are constantly under development we cannot guarantee or otherwise ensure full security, fidelity, operation, accuracy, or completeness of the Protocol. You acknowledge that the Protocol is subject to flaws and that you are solely responsible for evaluating any code provided in the Protocol, and you represent and warrant that you have the skill and ability to evaluate and understand the risks of the Protocol. You are solely responsible for your use and access to the Protocol which may be accessed via the Interface or through other means as permitted by any Blockchain Technology.\r\n\r\n#### 11. Blockchain Technology\r\n\r\nPlease be aware that the underlying technology that makes blockchain based networks, cryptographic systems, and smart contracts available (collectively “Blockchain Technology”) can be used, copied, modified, and distributed by third parties. Opyn does not control or operate the Blockchain Technology, and we assume no responsibility for the operation, functionality, or security of the Blockchain Technology. Blockchain Technology is subject to change that is out of our control, which could materially affect the Interface, the Protocol, and the value, functionality, availability, and use of any Digital Assets.\r\n\r\nIt is your responsibility to make yourself aware of upcoming operating changes, and you must carefully consider publicly available information in determining whether to continue to use the Interface, transact with any Protocols using your Digital Assets, or otherwise interact with the Blockchain Technology through the Interface. Blockchain Technology is currently under development, and this creates uncertainty relating to Digital Assets and transactions through the Interface. You acknowledge and accept the risks of using your Digital Assets with our Interface that relies on Blockchain Technology and agree that Opyn is not responsible for any changes to any Blockchain Technology that may cause you to experience a complete loss of value or access to your Digital Assets. Such changes may include, but are not limited, to forks, rollbacks, changes to operating rules, breaches of security, and outages.\r\n\r\n#### 12. Fees and Costs\r\n\r\nWhere you use the Interface, including the Protocol, unless expressly stated otherwise pursuant to a promotion operated by Us you may be required to pay a fee where necessary, including but not limited to any third party fees. You are solely responsible for paying all fees, and we are not liable to you for any delays in any transactions where you have failed to pay any fees. Although we attempt to provide accurate fee information, this information reflects our estimate of fees. Such fees may vary from the actual fees that you pay to use the Protocol through the Interface and/or the gas fees required for your Digital Assets.\r\n\r\n#### 13. Gas\r\n\r\nAny transaction involving the Digital Assets through the Interface is only completed upon confirmation through the Blockchain Technology, and we are not liable for any incomplete transactions or delays. You shall be required to maintain an adequate amount of Digital Assets to consume as gas (“Gas”) within your Digital Wallet to process any requested transactions. Where you fail to maintain adequate Gas amounts you understand that you will be unable to partake in any transactions using your Digital Wallet. We shall not be responsible for any delay in any transactions due to inadequate Gas within your Digital Wallet. Please be aware that any Gas used cannot be returned and all Gas consumption or charges are subject to the Blockchain Technology.\r\n\r\n#### 14. Reversals\r\n\r\nDue to the nature of Blockchain Technology you understand and agree that using the Interface including interacting with any Protocols may be irreversible and you solely undertake this risk when using the Interface. As we do not control your Digital Wallet we cannot reverse any transactions that occur using your Digital Wallet.\r\n\r\n#### 15. Interface Availability and Modification\r\n\r\nWe do not guarantee that the Interface will always be available, work, or be accessible at any particular time. Specifically, we do not guarantee any uptime or specific availability of the Interface. You agree and acknowledge that the Interface uses remote access and may not always be either 100% reliable or available.\r\n\r\nWe reserve the right to alter, modify, update, or remove the Interface or any portions thereof, at any time at our discretion. We reserve the right to discontinue previously offered features or functionality at our sole discretion and without prior notice. We are not liable to you or to any third party for any modification, suspension, or discontinuance of any feature or component of any portion of the Interface. We reserve the right to determine the timing and content of software updates, which may be automatically updated without notice to you. We may conduct such modifications to our Interface for security, intellectual property, legal reasons, or various other reasons at our discretion, and we are not required to explain such modifications or provide you access to previous versions of our Interface. Nothing in this section obligates us to take measures to update the Interfac\r\n\r\n#### 16. Content\r\n\r\nYou hereby grant to us a royalty-free, fully paid-up, sublicensable (through multiple tiers), transferable, perpetual, irrevocable, non-exclusive, worldwide license to use, copy, modify, create derivative works of, display, perform, publish and distribute, in any form, medium or manner, any content that is available to other users as a result of your use of the Site or the Services (collectively, “Your Content”), including for promoting Opyn or the Services. You represent and warrant that (a) you own Your Content or have the right to grant the rights and licenses in these Terms; and (b) Your Content and our use of Your Content, as licensed herein, does not and will not violate, misappropriate or infringe on any third party’s rights.\r\n\r\n#### 17. Links\r\n\r\nThe Services or third parties may provide links to other World Wide Web or accessible sites, applications, or resources. You acknowledge and agree that Opyn is not responsible for the availability of such external sites, applications or resources, and does not endorse and is not responsible or liable for any content, advertising, products, or other materials on or available from such sites or resources. You further acknowledge and agree that Company will not be responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in connection with use of or reliance on any such content, goods, or services available on or through any such site or resource.\r\n\r\n#### 18. Third Parties\r\n\r\nWe are not a party to any agreements that you may enter with any third party. OPYN EXPRESSLY DISCLAIMS ANY RESPONSIBILITY OR LIABILITY FOR ANY DAMAGE, LOSS, OR INJURY ARISING OUT OF YOUR INTERACTIONS WITH THIRD PARTIES, INCLUDING ANY THIRD PARTY CONTENT (DEFINED BELOW), AND ANY LOSS OR INJURY ARISING OUT OF ANY ACT OR OMISSION OF ANY THIRD PARTY OR ANY THIRD PARTY CONTENT. Opyn is not liable for the acts, errors, omissions, representations, warranties, breaches, negligence, misconduct of any third party or for any personal injuries, death, property damage, or other damages (including lost profits, or expenses resulting from any agreements or interactions with third parties.\r\n\r\n#### 19. Third Party Content\r\n\r\nThrough the Interface, third party information may be accessed, and you may be able to interact with third parties (“Third Party Content”). Opyn does not introduce, endorse, or recommend any third parties or any third party’s Third Party Content to you or vice versa. Any opinions, advice, or information expressed by any third party are those of the individual/organization, and they do not reflect the opinions of Opyn. Opyn does not direct, is not an employer of, has no control over, makes no representations, and does not guarantee the quality, safety or legality of any third party or any Third Party Content. Please be aware that any Third Party Content posted may not be truthful, accurate, or up-to-date.\r\n\r\n#### 20. Termination\r\n\r\nWe may terminate your access to the Interface, Protocol or this Agreement with you if we determine that: (1) you have violated any Applicable Laws while using our Interface; (2) if you have violated this Agreement or any other of our policies; or (3) if we believe that any of your actions may harm Opyn or a third party, at our sole decision or discretion. Please be aware that upon termination of your access to the Interface, portions of our Interface may be immediately disabled. Where termination has occurred, portions of this Agreement shall survive and remain in full force as stated in the “Survival” section of this Agreement.\r\n\r\n#### 21. Taxes\r\n\r\nDepending on the Applicable Laws of your jurisdiction you may be required to pay taxes related to your usage of the Interface. You agree that you are solely liable for any taxes related to your use of the Interface, any Digital Asset transactions, or activity involving your Digital Wallet. We shall not be liable for any taxes incurred by you under any Applicable Laws.\r\n\r\n#### 22. Fraudulent Transactions\r\n\r\nIf we believe that you have participated in a fraudulent transaction we will pursue our claims against you to the fullest extent allowed by law and we reserve the right to take any action necessary regarding any fraudulent transactions. In the event that we believe that a user has completed a fraudulent transaction, we will forward your information to the applicable law enforcement agency, which may result in civil or criminal penalties.\r\n\r\n#### 23. Intellectual Property\r\n\r\nThe name “Opyn,” “Opyn, Inc.”, the Opyn logo, any associated software, and the trademarks, marks, and logos contained therein, are owned by or licensed to Opyn or its licensors. The Protocol is comprised entirely of open source or source-available software running on the public Ethereum blockchain. This intellectual property is available under the terms of our copyright licenses and our trademark guidelines. You agree to not engage in the unauthorized use, access, copying, or distribution of the intellectual property, unless we have given you express written permission. All rights not expressly granted are hereby reserved for Opyn and its licensors.\r\n\r\n#### 24. Assumption of Risk\r\n\r\nTransacting Digital Assets or using Blockchain Technology involves significant risks and potential for financial losses which may result in the theft or loss of some or all of your Digital Assets. Such risks include without limitation the following:\r\n- the Digital Assets and the Blockchain Technology are constantly under development making your Digital Assets vulnerable to hacking, breaches in security, flaws, errors, bugs, failures, loss, theft, and fraud (whether due to Opyn or otherwise);\r\n- Digital Assets may fail to operate, lose all value, or be changed in a manner including without limitation a fork or rollback of the underlying Blockchain Technology;\r\n- the Digital Assets may decrease in value or lose all of its value due to various factors including discovery of wrongful conduct, market manipulation, changes to the underlying Digital Asset or Blockchain Technology. Such factors could cause transaction costs to increase which may impact your use of the Interface;\r\n- suspension or cessation of support for an Digital Assets by Blockchain Technology service providers may result in a total loss or inability to transfer or access any Digital Assets; and\r\n- Digital Assets may lose value or functionality due to governmental action, laws, or regulation as there is uncertainty to the legal status and categorization of Digital Assets. Such actions could result in the loss of access to the Interface.\r\n\r\nYou hereby assume and agree that Opyn will have no responsibility or liability for such risks. You hereby irrevocably waive, release, and discharge any and all claims, whether known or unknown to you, against Opyn, its affiliates and their respective shareholders, members, directors, officers, employees, contractors, agents, and representatives related to any of the risks set forth herein. You accept the risk of all use of the Digital Assets and are responsible for conducting your own independent analysis of the risks specific to the Digital Assets. You should not acquire any Digital Assets unless you have sufficient financial resources and can afford to lose all value of the Digital Assets.\r\n\r\n#### 25. Limitation of Liability\r\n\r\nIN NO EVENT SHALL OPYN, ITS OFFICERS, DIRECTORS, EMPLOYEES, CONTRACTORS, AFFILIATES, OR AGENTS, BE LIABLE TO YOU FOR ANY INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES, WHETHER BASED ON WARRANTY, CONTRACT, TORT (INCLUDING NEGLIGENCE), OR ANY OTHER LEGAL THEORY, AND WHETHER OR NOT OPYN IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. In jurisdictions that allow a limitation on liability, you agree that our liability is no more than the amount you paid in the past six months in any fees (excluding Gas) to access the Interface or one-hundred US dollars (USD$100.00), whichever is greater. The limitations of damages set forth above are fundamental elements of the basis of the bargain between Opyn and you. Some jurisdictions do not allow the exclusion or limitation of liability for consequential or incidental damages. So the above limitation or exclusion may not apply to you, and you may also have other legal rights that vary between jurisdictions. Specifically, in those jurisdictions not allowed, we do not disclaim liability for: (a) personal injury caused by Opyn’s negligence or that of any of its officers, employees, contractors, or agents; (b) fraudulent misrepresentation; or (c) any liability which it is not lawful to exclude either now or in the future. You agree that the exclusions and limitation of liability set out in this Agreement are reasonable. If you do not believe they are reasonable, please do not use our Interface.\r\n\r\n#### 26. Release\r\n\r\nYou expressly agree that you assume all risks in connection with your access and use of the Interface or your interaction with the Protocol, whether such risks are set forth in this Agreement or otherwise. YOU EXPRESSLY WAIVE AND RELEASE US FROM ANY AND ALL LIABILITY, CLAIMS, OR DAMAGES ARISING FROM OR IN ANY WAY RELATED TO YOUR USE OF THE INTERFACE OR PROTOCOL OR ANY RISKS ARISING FROM SUCH USE. YOU RELEASE OPYN AND ITS DIRECTORS, OFFICERS, EMPLOYEES AND ASSIGNS FROM ANY AND ALL CLAIMS, DEMANDS, OR DAMAGES (ACTUAL, DIRECT, OR CONSEQUENTIAL) OF EVERY KIND AND NATURE, KNOWN AND UNKNOWN, SUSPECTED AND UNSUSPECTED, DISCLOSED AND UNDISCLOSED, ARISING OUT OF OR IN ANY WAY CONNECTED WITH ANY DISPUTE WITH ANOTHER USER, THE INTERFACE, PROTOCOL, OR OTHER THIRD PARTY.\r\n\r\n#### 27. Indemnity\r\n\r\nYou agree to release, defend, indemnify, and hold Opyn and its affiliates and subsidiaries, and their officers, directors, employees, contractors, and agents, harmless from and against any claims, liabilities, damages, losses, and expenses, including, without limitation, reasonable legal and accounting fees, arising out of or in any way connected with (i) your breach of this Agreement; (ii) your improper use of the Opyn Interface or Protocol; (iii) your interaction with any other user or other third party including without limitation any injuries, losses or damages of any kind arising in connection with or as a result of such interaction; and (iv) your breach of any Applicable Laws, regulations or third-party rights. You agree that this indemnity extends to requiring you to pay for our reasonable attorneys’ fees, court costs, and disbursements. In the event of a claim such as one described in this paragraph, we may elect to settle with the party/parties making the claim and you shall be liable for the damages as though we had proceeded with a trial.\r\n\r\n#### 28. No Warranties\r\n\r\nThe Interface is provided \"AS IS\", \"AS AVAILABLE\" and \"WITH ALL FAULTS\" BASIS. TO THE FULLEST EXTENT PERMISSIBLE BY LAW, NEITHER OPYN, NOR ANY OF THEIR EMPLOYEES, CONTRACTORS, MANAGERS, OFFICERS, ASSIGNS OR AGENTS MAKE ANY REPRESENTATIONS OR WARRANTIES OR ENDORSEMENTS OF ANY KIND WHATSOEVER, EXPRESS OR IMPLIED. In addition, we disclaim all warranties, express or implied, including, but not limited to, the warranties of merchantability, fitness for a particular purpose, non-infringement, title, custom, trade, quiet enjoyment, lost profits, system integration and freedom from computer virus. The inclusion of any Digital Assets on this Interface does not constitute any endorsement or recommendation by Opyn. Opyn does not warrant that your use of the Interface or Protocol is lawful in any particular jurisdiction, and Opyn specifically disclaims any such warranties.\r\n\r\n#### 29. Choice of Law\r\n\r\nThis Agreement shall be governed by the laws in force in the state of California.\r\n\r\n#### 30. Arbitration\r\n\r\nPlease read the following section carefully because it requires you to arbitrate certain disputes and claims with Opyn and limits how you can seek relief from Opyn. Also, Opyn arbitration precludes you from suing in court or having a jury trial.\r\n\r\nYou and Opyn agree that any dispute arising out of or related to this Agreement (“Dispute”), including, but not limited to, the validity, construction, and performance of this Agreement, shall be governed by and under the laws of the state of California, without giving effect to conflict of laws principles thereof.\r\n\r\n##### 30.1 Informal Resolution\r\n\r\nFor any dispute or claim that you have against Opyn, before seeking mediation, arbitration, or any other form of legal relief, you agree to first contact Opyn and attempt to resolve the claim informally by sending a written notice of your claim (“Notice”) to Opyn by email at legal@opyn.co. The Notice must (a) include your name, residence address, email address, and telephone number; (b) describe the nature and basis of the claim; and (c) set forth the specific relief sought. Our Notice to you will be similar in form to that described above. Where we receive or send such a Notice, you and Opyn shall attempt in good faith to resolve such claims in an informal manner.The parties agree to maintain the confidential nature of all disputes and disagreements between them, including, but not limited to, informal negotiations, mediation or arbitration, except as may be necessary to prepare for or conduct these dispute resolution procedures or unless otherwise required by law or judicial decision.\r\n\r\n##### 30.2 Binding Arbitration\r\n\r\nIf you and Opyn cannot reach an agreement to resolve the claim within thirty (30) days after such Notice is received, then either party may submit the dispute to binding arbitration administered by JAMS (“Binding Arbitration” or “Arbitration”). If there is a dispute about whether this arbitration provision can be enforced or applies to the Dispute, you and Opyn agree that the arbitrator will decide that issue. However, any claim that all or part of the Class Action Waiver is unenforceable, unconscionable, void or voidable may be determined only by a court of competent jurisdiction and not by an arbitrator.\r\n\r\nYou and Opyn agree that arbitration under this Agreement will substantially and procedurally be governed by the Federal Arbitration Act, 9 U.S.C. §1, et seq. (the “FAA”), to the maximum extent permitted by applicable law. The arbitration will be administered by JAMS before one (1) arbitrator. Arbitration proceedings will be held in San Francisco, California in English, under the JAMS Streamlined Arbitration Rules and Procedures (“JAMS Rules”). The most recent version of the JAMS Rules may be found at [https://www.jamsadr.com/](https://www.jamsadr.com/) and are hereby incorporated by reference. You either acknowledge and agree that you have read and understand the JAMS Rules or waive your opportunity to read the JAMS Rules and waive any claim that the JAMS Rules are unfair or should not apply for any reason. The arbitrator's award shall be final and binding and may be entered as a judgment in any court of competent jurisdiction. The location of the arbitration shall be San Francisco, CA or a location agreed upon by the parties. Where a Dispute does not exceed $15,000 such Dispute shall be arbitrated solely via pleadings and documents. Both parties agree that they shall solely be responsible for paying for any fees related to any arbitration resolution.\r\n\r\nTo the fullest extent permitted by applicable law, no arbitration under this Agreement shall be joined to an arbitration involving any other party subject to this Agreement, whether through class action proceedings or otherwise. You agree that regardless of any statute or law to the contrary, any claim or cause of action arising out of, related to or connected with the use of the Interface, Protocol, or this Agreement must be filed within one (1) year after such claim or cause of action arose or be forever banned. In the event that the law does not permit the above-mentioned dispute to be resolved through arbitration, you agree that any actions shall be brought solely in a court of competent jurisdiction located within or otherwise nearest to San Francisco, CA.\r\n\r\n##### 30.3 Opt-Out\r\n\r\nYou have the right to opt out of binding arbitration within thirty (30) days of the date you first accepted this Agreement by notifying us with a communication labeled “Arbitration Opt Out” to legal@opyn.co or by mail at Opyn, Inc. 2021 Fillmore St. Suite 199, San Francisco, CA 94115. In order to be effective, the opt out notice must include your full name, any identifying information, and must clearly indicate your intent to opt out of binding arbitration. If you have decided to opt out of Binding Arbitration, all Disputes shall be heard in a court of competent jurisdiction located in San Francisco County, CA.\r\n\r\n##### 30.4 Exceptions to Arbitration\r\n\r\nUser agrees that all Disputes shall be arbitrated, except for as provided above and as follows: (i) any claim related to actual or threatened infringement, misappropriation or violation of a party’s copyrights, trademarks, trade secrets, patents, or other intellectual property rights; and (ii) any claim seeking emergency injunctive relief based on exigent circumstances such as, imminent danger or commission of a crime. Such claims shall be brought before a judicial proceeding in a court of competent jurisdiction located within San Francisco County, CA.\r\n\r\n##### 30.5 Class Action\r\n\r\nYOU UNDERSTAND AND AGREE THAT YOU AND OPYN MAY EACH BRING CLAIMS IN ARBITRATION AGAINST THE OTHER ONLY IN AN INDIVIDUAL CAPACITY AND NOT ON A CLASS, COLLECTIVE ACTION, OR REPRESENTATIVE BASIS (“CLASS ACTION WAIVER”). YOU UNDERSTAND AND AGREE THAT YOU AND OPYN BOTH ARE WAIVING THE RIGHT TO PURSUE OR HAVE A DISPUTE RESOLVED AS A PLAINTIFF OR CLASS MEMBER IN ANY PURPORTED CLASS, COLLECTIVE OR REPRESENTATIVE PROCEEDING. Notwithstanding any other provision of this Agreement, the Arbitration provisions or any associated rules or the disputes regarding the scope, applicability, enforceability, revocability, or validity of the Class Action Waiver may be resolved only by a civil court of competent jurisdiction and not by an arbitrator. In any case in which: (1) the dispute is filed as a class, collective, or representative action and (2) there is a final judicial determination that the Class Action Waiver is unenforceable as to any Disputes, the class, collective, and/or representative action on such Disputes must be litigated in a civil court of competent jurisdiction, but the Class Action Waiver shall be enforced in arbitration on an individual basis as to all other Claims to the fullest extent possible.\r\n\r\n#### 31. Force Majeure\r\n\r\nYou agree that we are not responsible to you for anything that we may otherwise be responsible for, if it is the result of events beyond our control, including, but not limited to, acts of God, war, insurrection, riots, terrorism, crime, labor shortages (including lawful and unlawful strikes), embargoes, postal disruption, internet outage, contagion, communication disruption, failure or shortage of infrastructure, shortage of materials, or any other event beyond our control.\r\n\r\n#### 32. Severability\r\n\r\nIn the event that a provision of this Agreement is found to be unlawful, conflicting with another provision of the Agreement, or otherwise unenforceable, the Agreement will remain in force as though it had been entered into without that unenforceable provision being included in it. If two or more provisions of this Agreement or any other agreement you may have with Opyn are deemed to conflict with each other’s operation, you agree that Opyn shall have the sole right to elect which provision remains in force.\r\n\r\n#### 33. Non-Waiver\r\n\r\nWe reserve all rights permitted to us under this Agreement as well as under the provisions of any applicable law. Our non-enforcement of any particular provision or provisions of this Agreement or any applicable law should not be construed as our waiver of the right to enforce that same provision under the same or different circumstances at any time in the future.\r\n\r\n#### 34. Survival\r\n\r\nAll provisions of this Agreement which by their nature should survive termination shall survive termination, including, without limitation, Opyn Intellectual Property provisions including use of the Interface or Protocol, User eligibility, User covenants, representations and warranties, limitation of liabilities, release, arbitration, indemnity, fees and costs, assumption of risk, warranty disclaimers, indemnity and miscellaneous provisions.\r\n\r\n#### 35. Assignment\r\n\r\nYou may not assign your rights and/or obligations under this Agreement to any other party without our prior written consent. We may assign our rights and/or obligations under this Agreement to any other party at our discretion.\r\n\r\n#### 36. Amendments\r\n\r\nWe may amend this Agreement from time to time. When we amend this Agreement, we will update this page and indicate the date that it was last modified. You may refuse to agree to the amendments, but if you do, you must immediately cease using our Interface.\r\n\r\n#### 37. Electronic Communications\r\n\r\nThe communications between you and Opyn use electronic means, whether you visit the Interface or send Opyn emails, write in the Opyn Discord, or whether Opyn posts notices on the Interface or communicates with you via email. For contractual purposes, you (1) consent to receive communications from Opyn in an electronic form; and (2) agree that all terms, conditions, agreements, notices, disclosures, and other communications that Opyn provides to you electronically satisfy any legal requirement that such communications would satisfy if it were to be in writing. The foregoing does not affect your statutory rights.\r\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/BullPosition.tsx",
    "content": "import { Tooltip, Typography, makeStyles, Link } from '@material-ui/core'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport useStyles from './useStyles'\nimport Image from 'next/image'\nimport { Tooltips } from '../../constants'\nimport { useAtomValue } from 'jotai'\nimport {\n  bullCurrentETHPositionAtom,\n  bullCurrentUSDCPositionAtom,\n  bullDepositedETHAtom,\n  bullDepositedUSDCAtom,\n  bullEthPnlAtom,\n  bullEthPnlPerctAtom,\n  bullPositionLoadedAtom,\n} from '@state/bull/atoms'\nimport bullStrategyImg from 'public/images/bull_strategy.png'\n\nconst BullPosition: React.FC = () => {\n  const classes = useStyles()\n  const bullCurrentETH = useAtomValue(bullCurrentETHPositionAtom)\n  const bullCurrentUSD = useAtomValue(bullCurrentUSDCPositionAtom)\n\n  const bullDepositedETH = useAtomValue(bullDepositedETHAtom)\n  const bullDepositedUSD = useAtomValue(bullDepositedUSDCAtom)\n\n  const bullEthPnl = useAtomValue(bullEthPnlAtom)\n  const bullEthPnlInPerct = useAtomValue(bullEthPnlPerctAtom)\n\n  const loading = !useAtomValue(bullPositionLoadedAtom)\n\n  if (bullCurrentETH.isZero()) return null\n\n  return (\n    <div className={classes.position} id=\"pos-page-bull\">\n      <div className={classes.positionTitle}>\n        <div style={{ display: 'flex', alignItems: 'center' }}>\n          <div className={classes.emoji}>\n            <Image src={bullStrategyImg} width=\"100%\" alt=\"zen bull\" />\n          </div>\n          <Typography style={{ marginLeft: '8px' }}>Zen Bull</Typography>\n        </div>\n        <Typography className={classes.link}>\n          <Link href={`/strategies/bull`} target=\"_blank\">\n            Redeem\n          </Link>\n        </Typography>\n      </div>\n      <div className={classes.shortPositionData}>\n        <div className={classes.innerPositionData}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Deposited Amount\n            </Typography>\n            <Tooltip title={Tooltips.CrabMigratedDeposit}>\n              <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n            <Typography variant=\"body1\">{bullDepositedETH.toFixed(6)}&nbsp;ETH</Typography>\n            <Typography variant=\"body2\" color=\"textSecondary\">\n              <span id=\"pos-page-crab-deposited-amount\">${bullDepositedUSD.toFixed(2)}</span>\n            </Typography>\n          </div>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Current Position\n            </Typography>\n            <Typography variant=\"body1\">{!loading ? `${bullCurrentETH.toFixed(6)}` : 'Loading'} ETH</Typography>\n            <Typography variant=\"body2\" color=\"textSecondary\">\n              {!loading ? `$${bullCurrentUSD.toFixed(2)}` : 'Loading'}\n            </Typography>\n          </div>\n        </div>\n        <div className={classes.innerPositionData} style={{ marginTop: '16px' }}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Unrealized P&L\n            </Typography>\n            <Tooltip title={Tooltips.CrabPnL}>\n              <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n            <Typography\n              variant=\"body1\"\n              className={bullEthPnl.isLessThan(0) ? classes.red : classes.green}\n              id=\"pos-page-crab-pnl-amount\"\n            >\n              {!loading ? `${bullEthPnl.toFixed(6)} ETH` : 'Loading'}\n            </Typography>\n            <Typography variant=\"caption\" className={bullEthPnlInPerct.isLessThan(0) ? classes.red : classes.green}>\n              {!loading ? `${bullEthPnlInPerct.toFixed(2)}` + '%' : 'Loading'}\n            </Typography>\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n\nexport default BullPosition\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/ConnectWallet.tsx",
    "content": "import { Typography } from '@material-ui/core'\nimport { useAtomValue } from 'jotai'\nimport { supportedNetworkAtom } from 'src/state/wallet/atoms'\nimport { useSelectWallet } from 'src/state/wallet/hooks'\nimport { LinkButton } from '../../components/Button'\nimport Nav from '../../components/Nav'\nimport useStyles from './useStyles'\n\nconst ConnectWallet: React.FC = () => {\n  const selectWallet = useSelectWallet()\n  const classes = useStyles()\n  const supportedNetwork = useAtomValue(supportedNetworkAtom)\n\n  return (\n    <div>\n      <Nav />\n      <div className={classes.container}>\n        {supportedNetwork ? (\n          <LinkButton style={{ margin: 'auto' }} onClick={selectWallet}>\n            Connect Wallet\n          </LinkButton>\n        ) : (\n          <Typography>Unsupported Network</Typography>\n        )}\n      </div>\n    </div>\n  )\n}\n\nexport default ConnectWallet\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/CrabPosition.tsx",
    "content": "import { Tooltip, Typography, Link } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport { useAtomValue } from 'jotai'\nimport { useEffect } from 'react'\nimport { useCurrentCrabPositionValue, useCurrentCrabPositionValueV2, useSetStrategyData } from 'src/state/crab/hooks'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport { crabStrategyCollatRatioAtom } from 'src/state/crab/atoms'\nimport useStyles from './useStyles'\nimport { Tooltips } from '../../constants'\n\ntype CrabPositionType = {\n  depositedEth: BigNumber\n  depositedUsd: BigNumber\n  loading: boolean\n  pnlWMidPriceInUSD: BigNumber\n  pnlWMidPriceInPerct: BigNumber\n  currentCrabPositionValue: BigNumber\n  currentCrabPositionValueInETH: BigNumber\n  version: String\n}\n\nconst CrabPosition: React.FC<CrabPositionType> = ({\n  depositedEth,\n  depositedUsd,\n  loading,\n  pnlWMidPriceInPerct,\n  pnlWMidPriceInUSD,\n  currentCrabPositionValue,\n  currentCrabPositionValueInETH,\n  version,\n}) => {\n  const classes = useStyles()\n  const collatRatio = useAtomValue(crabStrategyCollatRatioAtom)\n  const setStrategyData = useSetStrategyData()\n  useCurrentCrabPositionValue()\n  useCurrentCrabPositionValueV2()\n\n  useEffect(() => {\n    setStrategyData()\n  }, [collatRatio, setStrategyData])\n\n  return (\n    <div className={classes.position} id=\"pos-page-crab\">\n      <div className={classes.positionTitle}>\n        <div style={{ display: 'flex', alignItems: 'center' }}>\n          <Typography>🦀</Typography>\n          <Typography style={{ marginLeft: '8px' }}>{version}</Typography>\n        </div>\n        <Typography className={classes.link}>\n          <Link href={`/strategies/crab`} target=\"_blank\">\n            Redeem\n          </Link>\n        </Typography>\n      </div>\n      <div className={classes.shortPositionData}>\n        <div className={classes.innerPositionData}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Deposited Amount\n            </Typography>\n            <Tooltip title={Tooltips.CrabMigratedDeposit}>\n              <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n            <Typography variant=\"body1\">$ {depositedUsd.toFixed(2)}</Typography>\n            <Typography variant=\"body2\" color=\"textSecondary\">\n              <span id=\"pos-page-crab-deposited-amount\">{depositedEth.toFixed(6)}</span>\n              &nbsp; ETH\n            </Typography>\n          </div>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Current Position\n            </Typography>\n            <Typography variant=\"body1\">{!loading ? `$ ${currentCrabPositionValue.toFixed(2)}` : 'Loading'}</Typography>\n            <Typography variant=\"body2\" color=\"textSecondary\">\n              {!loading ? `${currentCrabPositionValueInETH.toFixed(6)}  ETH` : 'Loading'}\n            </Typography>\n          </div>\n        </div>\n        <div className={classes.innerPositionData} style={{ marginTop: '16px' }}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Unrealized P&L\n            </Typography>\n            <Tooltip title={Tooltips.CrabPnL}>\n              <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n            <Typography\n              variant=\"body1\"\n              className={pnlWMidPriceInUSD.isLessThan(0) ? classes.red : classes.green}\n              id=\"pos-page-crab-pnl-amount\"\n            >\n              {!loading ? '$' + `${pnlWMidPriceInUSD.toFixed(2)}` : 'Loading'}\n            </Typography>\n            <Typography variant=\"caption\" className={pnlWMidPriceInPerct.isLessThan(0) ? classes.red : classes.green}>\n              {!loading ? `${pnlWMidPriceInPerct.toFixed(2)}` + '%' : 'Loading'}\n            </Typography>\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n\nexport default CrabPosition\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/CrabPositionV2.tsx",
    "content": "import { Tooltip, Typography, Link } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport { useAtomValue } from 'jotai'\nimport { useEffect } from 'react'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\n\nimport { useCurrentCrabPositionValue, useCurrentCrabPositionValueV2, useSetStrategyData } from '@state/crab/hooks'\nimport { crabStrategyCollatRatioAtom, usdcQueuedAtom, crabQueuedAtom, crabUSDValueAtom } from '@state/crab/atoms'\nimport { Tooltips, USDC_DECIMALS } from '@constants/index'\nimport { toTokenAmount } from '@utils/calculations'\nimport { formatCurrency } from '@utils/formatter'\nimport useStyles from './useStyles'\n\ntype CrabPositionV2Type = {\n  depositedEth: BigNumber\n  depositedUsd: BigNumber\n  loading: boolean\n  pnlWMidPriceInUSD: BigNumber\n  pnlWMidPriceInPerct: BigNumber\n  currentCrabPositionValue: BigNumber\n  currentCrabPositionValueInETH: BigNumber\n  version: String\n}\n\nconst CrabPositionV2: React.FC<CrabPositionV2Type> = ({\n  depositedEth,\n  depositedUsd,\n  loading,\n  pnlWMidPriceInPerct,\n  pnlWMidPriceInUSD,\n  currentCrabPositionValue,\n  currentCrabPositionValueInETH,\n  version,\n}) => {\n  const classes = useStyles()\n  const collatRatio = useAtomValue(crabStrategyCollatRatioAtom)\n  const usdcQueued = useAtomValue(usdcQueuedAtom)\n  const crabQueued = useAtomValue(crabQueuedAtom)\n  const crabUsdValue = useAtomValue(crabUSDValueAtom)\n\n  const setStrategyData = useSetStrategyData()\n  useCurrentCrabPositionValue()\n  useCurrentCrabPositionValueV2()\n\n  useEffect(() => {\n    setStrategyData()\n  }, [collatRatio, setStrategyData])\n\n  const initiatedDepositAmount = toTokenAmount(usdcQueued, USDC_DECIMALS)\n  const initiatedWithdrawalAmount = toTokenAmount(crabQueued, 18).times(toTokenAmount(crabUsdValue, 18))\n\n  return (\n    <div className={classes.position} id=\"pos-page-crab\">\n      <div className={classes.positionTitle}>\n        <div style={{ display: 'flex', alignItems: 'center' }}>\n          <Typography>🦀</Typography>\n          <Typography style={{ marginLeft: '8px' }}>{version}</Typography>\n        </div>\n        <Typography className={classes.link}>\n          <Link href={`/strategies/crab`} target=\"_blank\">\n            Redeem\n          </Link>\n        </Typography>\n      </div>\n      <div className={classes.shortPositionData}>\n        <div className={classes.innerPositionData}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Deposited Amount\n            </Typography>\n            <Tooltip title={Tooltips.CrabMigratedDeposit}>\n              <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n            <Typography variant=\"body1\">$ {depositedUsd.toFixed(2)}</Typography>\n            <Typography variant=\"body2\" color=\"textSecondary\">\n              <span id=\"pos-page-crab-deposited-amount\">{depositedEth.toFixed(6)}</span>\n              &nbsp; ETH\n            </Typography>\n          </div>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Current Position\n            </Typography>\n            <Typography variant=\"body1\">{!loading ? `$ ${currentCrabPositionValue.toFixed(2)}` : 'Loading'}</Typography>\n            <Typography variant=\"body2\" color=\"textSecondary\">\n              {!loading ? `${currentCrabPositionValueInETH.toFixed(6)}  ETH` : 'Loading'}\n            </Typography>\n          </div>\n        </div>\n        <div className={classes.innerPositionData} style={{ marginTop: '16px' }}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Unrealized P&L\n            </Typography>\n            <Tooltip title={Tooltips.CrabPnL}>\n              <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n            <Typography\n              variant=\"body1\"\n              className={pnlWMidPriceInUSD.isLessThan(0) ? classes.red : classes.green}\n              id=\"pos-page-crab-pnl-amount\"\n            >\n              {!loading ? '$' + `${pnlWMidPriceInUSD.toFixed(2)}` : 'Loading'}\n            </Typography>\n            <Typography variant=\"caption\" className={pnlWMidPriceInPerct.isLessThan(0) ? classes.red : classes.green}>\n              {!loading ? `${pnlWMidPriceInPerct.toFixed(2)}` + '%' : 'Loading'}\n            </Typography>\n          </div>\n        </div>\n\n        <div className={classes.innerPositionData}>\n          {/* ignore dust amount */}\n          {usdcQueued.isGreaterThan('100') && (\n            <div style={{ width: '50%', marginTop: '16px' }}>\n              <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n                Initiated Deposit\n              </Typography>\n              <Tooltip title={Tooltips.InitiatedDeposit}>\n                <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n              </Tooltip>\n              <Typography variant=\"body1\">\n                {!loading ? formatCurrency(Number(initiatedDepositAmount)) : 'Loading'}\n              </Typography>\n            </div>\n          )}\n\n          {/* ignore dust amount */}\n          {crabQueued.isGreaterThan('10000000000') && (\n            <div style={{ width: '50%', marginTop: '16px' }}>\n              <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n                Initiated Withdrawal\n              </Typography>\n              <Tooltip title={Tooltips.InitiatedWithdrawal}>\n                <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n              </Tooltip>\n              <Typography variant=\"body1\">\n                {!loading ? formatCurrency(Number(initiatedWithdrawalAmount)) : 'Loading'}\n              </Typography>\n            </div>\n          )}\n        </div>\n      </div>\n    </div>\n  )\n}\n\nexport default CrabPositionV2\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/History.tsx",
    "content": "import { createStyles, IconButton, makeStyles, Typography } from '@material-ui/core'\nimport OpenInNewIcon from '@material-ui/icons/OpenInNew'\n\nimport { EtherscanPrefix } from '../../constants'\nimport { TransactionType } from '@constants/enums'\nimport { useTransactionHistory } from '@hooks/useTransactionHistory'\nimport { useUsdAmount } from '@hooks/useUsdAmount'\nimport { networkIdAtom } from 'src/state/wallet/atoms'\nimport { useAtomValue } from 'jotai'\nimport { useETHPrice } from '@hooks/useETHPrice'\nimport { normFactorAtom } from 'src/state/controller/atoms'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      marginTop: theme.spacing(2),\n      marginBottom: theme.spacing(5),\n    },\n    tableCell: {\n      width: '10px',\n    },\n    red: {\n      color: theme.palette.error.main,\n    },\n    green: {\n      color: theme.palette.success.main,\n    },\n    txTypeContainer: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    historyItem: {\n      padding: theme.spacing(2),\n      backgroundColor: `${theme.palette.background.paper}40`,\n      marginTop: theme.spacing(2),\n      borderRadius: theme.spacing(1),\n      display: 'flex',\n      justifyContent: 'space-between',\n    },\n    txItemCol: {\n      width: '30%',\n    },\n    txItemVal: {\n      width: '30%',\n    },\n  }),\n)\n\nconst History: React.FC = () => {\n  const { transactions } = useTransactionHistory()\n  const networkId = useAtomValue(networkIdAtom)\n  const ethPrice = useETHPrice()\n  const normalizationFactor = useAtomValue(normFactorAtom)\n\n  const classes = useStyles()\n  const { getUsdAmt } = useUsdAmount()\n\n  return (\n    <div className={classes.container}>\n      {transactions.map((tx, index) => (\n        <div className={classes.historyItem} key={tx.timestamp + index}>\n          <div className={classes.txItemCol}>\n            <Typography variant=\"body2\">{tx.transactionType}</Typography>\n            <Typography variant=\"caption\" color=\"textSecondary\">\n              {new Date(Number(tx.timestamp) * 1000).toDateString()}\n            </Typography>\n          </div>\n          {tx.transactionType === TransactionType.CRAB_FLASH_DEPOSIT ||\n          tx.transactionType === TransactionType.CRAB_FLASH_WITHDRAW ||\n          tx.transactionType === TransactionType.BULL_FLASH_DEPOSIT ||\n          tx.transactionType === TransactionType.BULL_FLASH_WITHDRAW ? (\n            <>\n              <div className={classes.txItemVal}>\n                <Typography\n                  variant=\"body2\"\n                  className={\n                    tx.transactionType === TransactionType.CRAB_FLASH_WITHDRAW ||\n                    tx.transactionType === TransactionType.BULL_FLASH_WITHDRAW\n                      ? classes.red\n                      : classes.green\n                  }\n                >\n                  {tx.ethAmount.toFixed(4)}&nbsp; WETH\n                </Typography>\n                {(() => {\n                  const usdAmount = getUsdAmt(tx.ethAmount, tx.timestamp)\n                  return usdAmount.gt(0) ? (\n                    <Typography variant=\"caption\" color=\"textSecondary\">\n                      ${usdAmount.toFixed(2)}\n                    </Typography>\n                  ) : null\n                })()}\n              </div>\n              <div className={classes.txItemVal} />\n            </>\n          ) : (\n            <>\n              <div className={classes.txItemVal}>\n                {tx.transactionType != TransactionType.OTC_DEPOSIT &&\n                tx.transactionType != TransactionType.OTC_WITHDRAW ? (\n                  <>\n                    <Typography\n                      variant=\"body2\"\n                      className={\n                        tx.transactionType === TransactionType.BUY ||\n                        tx.transactionType === TransactionType.BURN_SHORT ||\n                        tx.transactionType === TransactionType.REMOVE_LIQUIDITY\n                          ? classes.green\n                          : classes.red\n                      }\n                    >\n                      {tx.squeethAmount.toFixed(8)}&nbsp; oSQTH\n                    </Typography>\n                    <Typography variant=\"caption\" color=\"textSecondary\">\n                      $\n                      {tx.squeethAmount\n                        .times(ethPrice)\n                        .times(ethPrice)\n                        .div(10000)\n                        .times(normalizationFactor)\n                        .toFixed(2)}\n                    </Typography>\n                  </>\n                ) : null}\n              </div>\n              <div className={classes.txItemVal}>\n                <Typography\n                  variant=\"body2\"\n                  className={\n                    tx.transactionType === TransactionType.BUY ||\n                    tx.transactionType === TransactionType.BURN_SHORT ||\n                    tx.transactionType === TransactionType.ADD_LIQUIDITY\n                      ? classes.red\n                      : classes.green\n                  }\n                >\n                  {tx.transactionType === TransactionType.CRAB_V2_USDC_FLASH_DEPOSIT ||\n                  tx.transactionType === TransactionType.CRAB_V2_USDC_FLASH_WITHDRAW\n                    ? tx.usdValue.gt(0)\n                      ? `${tx.usdValue.toFixed(2)} USDC`\n                      : null\n                    : tx.ethAmount.gt(0)\n                    ? `${tx.ethAmount.toFixed(4)} WETH`\n                    : null}\n                </Typography>\n                <Typography variant=\"caption\" color=\"textSecondary\">\n                  {tx.transactionType === TransactionType.CRAB_V2_USDC_FLASH_DEPOSIT ||\n                  tx.transactionType === TransactionType.CRAB_V2_USDC_FLASH_WITHDRAW\n                    ? tx.ethAmount.gt(0)\n                      ? `${tx.ethAmount.toFixed(4)} WETH`\n                      : null\n                    : tx.usdValue.gt(0)\n                    ? `$${tx.usdValue.toFixed(2)}`\n                    : null}\n                </Typography>\n              </div>\n            </>\n          )}\n\n          <div>\n            <IconButton size=\"small\" href={`${EtherscanPrefix[networkId]}/${tx.txId}`} target=\"_blank\">\n              <OpenInNewIcon style={{ fontSize: '16px' }} color=\"secondary\" />\n            </IconButton>\n          </div>\n        </div>\n      ))}\n    </div>\n  )\n}\n\nexport default History\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/LPedSqueeth.tsx",
    "content": "import { useVaultData } from '@hooks/useVaultData'\nimport { Link, Tooltip, Typography } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport { useFirstValidVault, useLpDebt } from 'src/state/positions/hooks'\nimport useStyles from './useStyles'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport { Tooltips } from '../../constants'\n\ninterface Props {\n  vaultExists: boolean\n}\n\nexport default function LPedSqueeth({ vaultExists }: Props) {\n  const classes = useStyles()\n  const { validVault: vault, vaultId, isVaultLoading } = useFirstValidVault()\n  const lpedSqueeth = useLpDebt()\n  const { existingCollat, existingLiqPrice, existingCollatPercent } = useVaultData(vault)\n\n  return (\n    <div className={classes.position}>\n      <div className={classes.positionTitle}>\n        <Typography>LPed Squeeth</Typography>\n        <Typography className={classes.link} id=\"lp-vault-link\">\n          {vaultExists ? <Link href={`vault/${vaultId}`}>Manage</Link> : null}\n        </Typography>\n      </div>\n      <div className={classes.shortPositionData}>\n        <div className={classes.innerPositionData}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Amount\n            </Typography>\n            <Typography variant=\"body1\">\n              <span id=\"pos-page-lped-osqth-bal\">{lpedSqueeth.toFixed(8)}</span>\n              &nbsp; oSQTH\n            </Typography>\n          </div>\n        </div>\n        <div className={classes.innerPositionData} style={{ marginTop: '16px' }}>\n          {new BigNumber(existingLiqPrice).isFinite() ? (\n            <div style={{ width: '50%' }}>\n              <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n                Liquidation Price\n              </Typography>\n              <Tooltip title={Tooltips.LiquidationPrice}>\n                <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n              </Tooltip>\n              <Typography variant=\"body1\">\n                ${isVaultLoading && existingLiqPrice.isEqualTo(0) ? 'Loading' : existingLiqPrice.toFixed(2)}\n              </Typography>\n            </div>\n          ) : null}\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Collateral (Amt / Ratio)\n            </Typography>\n            <Typography variant=\"body1\">\n              {isVaultLoading && existingCollat.isEqualTo(0) ? 'Loading' : existingCollat.toFixed(4)} ETH\n              {new BigNumber(existingCollatPercent).isFinite() ? ' (' + existingCollatPercent + ' %)' : null}\n            </Typography>\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/LongSqueeth.tsx",
    "content": "import { Typography, Link } from '@material-ui/core'\nimport { useAtomValue } from 'jotai'\nimport { useComputeSwaps, useLongRealizedPnl, useLPPositionsQuery } from 'src/state/positions/hooks'\nimport { loadingAtom } from 'src/state/pnl/atoms'\nimport useStyles from './useStyles'\nimport { useLongGain, useCurrentLongPositionValue, useLongUnrealizedPNL } from 'src/state/pnl/hooks'\nimport { toTokenAmount } from '@utils/calculations'\nimport { indexAtom } from 'src/state/controller/atoms'\nimport { isToHidePnLAtom } from 'src/state/positions/atoms'\nimport { HidePnLText } from '@components/HidePnLText'\nimport { PnLType } from '../../types'\nimport { PnLTooltip } from '@components/PnLTooltip'\n\nexport default function LongSqueeth() {\n  const classes = useStyles()\n  const { loading: isPositionLoading } = useLPPositionsQuery()\n  const { squeethAmount, loading: swapsLoading } = useComputeSwaps()\n  const isPnLLoading = useAtomValue(loadingAtom)\n  const isToHidePnL = useAtomValue(isToHidePnLAtom)\n  // const longGain = useLongGain()\n  // const longUnrealizedPNL = useLongUnrealizedPNL()\n  const longRealizedPNL = useLongRealizedPnl()\n  const longPositionValue = useCurrentLongPositionValue()\n\n  return (\n    <div className={classes.position}>\n      <div className={classes.positionTitle}>\n        <Typography>Long Squeeth</Typography>\n        <Typography className={classes.link}>\n          <Link href={`/squeeth`} target=\"_blank\">\n            Redeem\n          </Link>\n        </Typography>\n      </div>\n      <div className={classes.shortPositionData}>\n        <div className={classes.innerPositionData}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              oSQTH Amount\n            </Typography>\n            <Typography variant=\"body1\">\n              {isPositionLoading && squeethAmount.isEqualTo(0) ? (\n                'Loading'\n              ) : (\n                <span id=\"pos-page-long-osqth-bal\">{squeethAmount.toFixed(8)}</span>\n              )}{' '}\n              &nbsp; oSQTH\n            </Typography>\n          </div>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Position Value\n            </Typography>\n            <Typography variant=\"body1\">\n              ${isPnLLoading && longPositionValue.isEqualTo(0) ? 'Loading' : longPositionValue.toFixed(2)}\n            </Typography>\n          </div>\n        </div>\n        {isToHidePnL ? (\n          <HidePnLText />\n        ) : (\n          <div className={classes.innerPositionData} style={{ marginTop: '16px' }}>\n            {/* <div style={{ width: '50%' }}>\n              <div className={classes.pnlTitle}>\n                <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n                  Unrealized P&L\n                </Typography>\n                <PnLTooltip pnlType={PnLType.Unrealized} />\n              </div>\n              {isPnLLoading || longUnrealizedPNL.loading ? (\n                <Typography variant=\"body1\">Loading</Typography>\n              ) : (\n                <>\n                  <Typography variant=\"body1\" className={longGain.isLessThan(0) ? classes.red : classes.green}>\n                    $ {longUnrealizedPNL.usd.toFixed(2)} ({longUnrealizedPNL.eth.toFixed(5)} ETH)\n                  </Typography>\n                  <Typography variant=\"caption\" className={longGain.isLessThan(0) ? classes.red : classes.green}>\n                    {(longGain || 0).toFixed(2)}%\n                  </Typography>\n                </>\n              )}\n            </div> */}\n            <div style={{ width: '50%' }}>\n              <div className={classes.pnlTitle}>\n                <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n                  Realized P&L\n                </Typography>\n                <PnLTooltip pnlType={PnLType.Realized} />\n              </div>\n              <Typography variant=\"body1\" className={longRealizedPNL.gte(0) ? classes.green : classes.red}>\n                $ {swapsLoading ? 'Loading' : longRealizedPNL.toFixed(2)}\n              </Typography>\n            </div>\n          </div>\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/MintedSqueeth.tsx",
    "content": "import { useVaultData } from '@hooks/useVaultData'\nimport { Tooltip, Typography } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport Link from 'next/link'\nimport { useFirstValidVault, useLPPositionsQuery, useMintedDebt } from 'src/state/positions/hooks'\nimport useStyles from './useStyles'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport { Tooltips } from '../../constants'\n\ninterface Props {\n  vaultExists: boolean\n}\n\nexport default function MintedSqueeth({ vaultExists }: Props) {\n  const classes = useStyles()\n  const { validVault, vaultId, isVaultLoading } = useFirstValidVault()\n  const { loading: isPositionLoading } = useLPPositionsQuery()\n  const { existingCollat, existingLiqPrice, existingCollatPercent } = useVaultData(validVault)\n  const mintedDebt = useMintedDebt()\n\n  return (\n    <div className={classes.position}>\n      <div className={classes.positionTitle}>\n        <Typography>Minted Squeeth</Typography>\n        <Typography className={classes.link}>\n          {vaultExists ? <Link href={`vault/${vaultId}`}>Manage</Link> : null}\n        </Typography>\n      </div>\n      <div className={classes.shortPositionData}>\n        <div className={classes.innerPositionData}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Amount\n            </Typography>\n            <Typography variant=\"body1\">\n              {isPositionLoading ? 'Loading' : <span id=\"pos-page-minted-osqth-bal\">{mintedDebt.toFixed(8)}</span>}{' '}\n              &nbsp; oSQTH\n            </Typography>\n          </div>\n        </div>\n        <div className={classes.innerPositionData} style={{ marginTop: '16px' }}>\n          {new BigNumber(existingLiqPrice).isFinite() ? (\n            <div style={{ width: '50%' }}>\n              <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n                Liquidation Price\n              </Typography>\n              <Tooltip title={Tooltips.LiquidationPrice}>\n                <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n              </Tooltip>\n              <Typography variant=\"body1\">\n                $ {isVaultLoading && existingLiqPrice.isEqualTo(0) ? 'Loading' : existingLiqPrice.toFixed(2)}\n              </Typography>\n            </div>\n          ) : null}\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Collateral (Amt / Ratio)\n            </Typography>\n            <Typography variant=\"body1\">\n              {isVaultLoading && existingCollat.isEqualTo(0) ? 'Loading' : existingCollat.toFixed(4)} ETH\n              {new BigNumber(existingCollatPercent).isFinite() ? ' (' + existingCollatPercent + ' %)' : null}\n            </Typography>\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/Positions.tsx",
    "content": "import { Box, Tooltip, Typography } from '@material-ui/core'\nimport FiberManualRecordIcon from '@material-ui/icons/FiberManualRecord'\n\nimport clsx from 'clsx'\nimport { useAtomValue } from 'jotai'\n\nimport { LPTable } from '@components/Lp/LPTable'\nimport Nav from '@components/Nav'\nimport History from '@pages/positions/History'\nimport { PositionType } from '../../types'\nimport { BIG_ZERO, Tooltips } from '../../constants'\nimport { useVaultLiquidations } from '@hooks/contracts/useLiquidations'\nimport { toTokenAmount } from '@utils/calculations'\nimport { useCrabPosition } from '@hooks/useCrabPosition'\nimport { addressAtom } from 'src/state/wallet/atoms'\nimport {\n  useComputeSwaps,\n  useFirstValidVault,\n  useLpDebt,\n  useMintedDebt,\n  useShortDebt,\n  usePositionsAndFeesComputation,\n} from 'src/state/positions/hooks'\nimport { activePositionsAtom, positionTypeAtom } from 'src/state/positions/atoms'\nimport { poolAtom } from 'src/state/squeethPool/atoms'\nimport { indexAtom } from 'src/state/controller/atoms'\nimport useAppMemo from '@hooks/useAppMemo'\nimport useStyles from './useStyles'\nimport CrabPosition from './CrabPosition'\nimport CrabPositionV2 from './CrabPositionV2'\nimport YourVaults from './YourVaults'\nimport LongSqueeth from './LongSqueeth'\nimport ShortSqueeth from './ShortSqueeth'\nimport LPedSqueeth from './LPedSqueeth'\nimport MintedSqueeth from './MintedSqueeth'\nimport ShortSqueethLiquidated from './ShortSqueethLiquidated'\nimport {\n  useCurrentCrabPositionValue,\n  useCurrentCrabPositionValueV2,\n  useSetStrategyData,\n  useSetStrategyDataV2,\n} from 'src/state/crab/hooks'\nimport { pnl, pnlInPerct, pnlv2, pnlInPerctv2 } from 'src/lib/pnl'\nimport { useCrabPositionV2 } from '@hooks/useCrabPosition/useCrabPosition'\nimport useAppEffect from '@hooks/useAppEffect'\nimport { crabQueuedInEthAtom, crabQueuedInUsdAtom } from '@state/crab/atoms'\nimport { useBullPosition } from '@hooks/useBullPosition'\nimport BullPosition from './BullPosition'\nimport { useInitBullStrategy } from '@state/bull/hooks'\n\nexport default function Positions() {\n  const classes = useStyles()\n  const pool = useAtomValue(poolAtom)\n  const address = useAtomValue(addressAtom)\n  const positionType = useAtomValue(positionTypeAtom)\n  const activePositions = useAtomValue(activePositionsAtom)\n\n  const { squeethAmount } = useComputeSwaps()\n  const { validVault: vault, vaultId } = useFirstValidVault()\n  const lpedSqueeth = useLpDebt()\n  const mintedDebt = useMintedDebt()\n  const shortDebt = useShortDebt()\n  const index = useAtomValue(indexAtom)\n  const setStrategyDataV2 = useSetStrategyDataV2()\n  const setStrategyData = useSetStrategyData()\n  const crabV2QueuedInUsd = useAtomValue(crabQueuedInUsdAtom)\n  useInitBullStrategy()\n  useBullPosition(address ?? '')\n\n  useAppEffect(() => {\n    setStrategyDataV2()\n    setStrategyData()\n  }, [setStrategyData, setStrategyDataV2])\n\n  usePositionsAndFeesComputation()\n  const { depositedEth, depositedUsd, loading: isCrabPositonLoading } = useCrabPosition(address || '')\n  const { currentCrabPositionValue, currentCrabPositionValueInETH, isCrabPositionValueLoading } =\n    useCurrentCrabPositionValue()\n\n  const {\n    depositedEth: depositedEthV2,\n    depositedUsd: depositedUsdV2,\n    loading: isCrabPositonLoadingV2,\n  } = useCrabPositionV2(address || '')\n  const {\n    currentCrabPositionValue: currentCrabPositionValueV2,\n    currentCrabPositionValueInETH: currentCrabPositionValueInETHV2,\n    isCrabPositionValueLoading: isCrabPositionValueLoadingV2,\n  } = useCurrentCrabPositionValueV2()\n\n  const isCrabloading = useAppMemo(() => {\n    return isCrabPositonLoading || isCrabPositionValueLoading\n  }, [isCrabPositonLoading, isCrabPositionValueLoading])\n\n  const isCrabV2loading = useAppMemo(() => {\n    return isCrabPositonLoadingV2 || isCrabPositionValueLoadingV2\n  }, [isCrabPositonLoadingV2, isCrabPositionValueLoadingV2])\n\n  const pnlWMidPriceInUSD = useAppMemo(() => {\n    return pnl(currentCrabPositionValue, depositedUsd)\n  }, [currentCrabPositionValue, depositedUsd])\n  const pnlWMidPriceInPerct = useAppMemo(() => {\n    return pnlInPerct(currentCrabPositionValue, depositedUsd)\n  }, [currentCrabPositionValue, depositedUsd])\n  const pnlWMidPriceInUSDV2 = useAppMemo(() => {\n    return pnlv2(currentCrabPositionValueV2.plus(crabV2QueuedInUsd), depositedUsdV2)\n  }, [currentCrabPositionValueV2, depositedUsdV2, crabV2QueuedInUsd])\n  const pnlWMidPriceInPerctV2 = useAppMemo(() => {\n    return pnlInPerctv2(currentCrabPositionValueV2.plus(crabV2QueuedInUsd), depositedUsdV2)\n  }, [currentCrabPositionValueV2, depositedUsdV2, crabV2QueuedInUsd])\n\n  const vaultExists = useAppMemo(() => {\n    return Boolean(vault && vault.collateralAmount?.isGreaterThan(0))\n  }, [vault])\n\n  const { liquidations } = useVaultLiquidations(Number(vaultId))\n\n  const fullyLiquidated = useAppMemo(() => {\n    return vault && vault.shortAmount?.isZero() && liquidations.length > 0\n  }, [vault, liquidations?.length])\n\n  return (\n    <div>\n      <Nav />\n      <div className={classes.container}>\n        <div className={classes.header}>\n          <Typography color=\"primary\" variant=\"h6\">\n            Your Positions\n          </Typography>\n          <div style={{ display: 'flex' }}>\n            <Typography component=\"span\" color=\"textSecondary\">\n              ETH Price:{' '}\n            </Typography>\n\n            <div className={classes.tooltipContainer}>\n              <Typography component=\"span\">$ {toTokenAmount(index, 18).sqrt().toFixed(2).toLocaleString()}</Typography>\n              <Tooltip title={Tooltips.SpotPrice}>\n                <FiberManualRecordIcon fontSize=\"small\" className={clsx(classes.dotIcon, classes.infoIcon)} />\n              </Tooltip>\n            </div>\n          </div>\n        </div>\n\n        {shortDebt.isZero() &&\n        depositedEth.isZero() &&\n        depositedEthV2.isZero() &&\n        squeethAmount.isZero() &&\n        mintedDebt.isZero() &&\n        lpedSqueeth.isZero() ? (\n          <div className={classes.empty}>\n            <Typography>No active positions</Typography>\n          </div>\n        ) : null}\n\n        {positionType === PositionType.LONG && <LongSqueeth />}\n\n        {positionType === PositionType.SHORT && <ShortSqueeth />}\n\n        {lpedSqueeth.isGreaterThan(0) && !fullyLiquidated && <LPedSqueeth vaultExists={vaultExists} />}\n\n        {mintedDebt.isGreaterThan(0) && !fullyLiquidated && <MintedSqueeth vaultExists={vaultExists} />}\n\n        {liquidations.length > 0 && <ShortSqueethLiquidated />}\n\n        {!!address && currentCrabPositionValueInETH.isGreaterThan(0) && (\n          <CrabPosition\n            depositedEth={depositedEth}\n            depositedUsd={depositedUsd}\n            loading={isCrabloading}\n            pnlWMidPriceInUSD={pnlWMidPriceInUSD}\n            pnlWMidPriceInPerct={pnlWMidPriceInPerct}\n            currentCrabPositionValue={currentCrabPositionValue}\n            currentCrabPositionValueInETH={currentCrabPositionValueInETH}\n            version=\"Crab Strategy V1\"\n          />\n        )}\n\n        {!!address && currentCrabPositionValueInETHV2.isGreaterThan(0) && (\n          <CrabPositionV2\n            depositedEth={depositedEthV2}\n            depositedUsd={depositedUsdV2}\n            loading={isCrabV2loading}\n            pnlWMidPriceInUSD={pnlWMidPriceInUSDV2}\n            pnlWMidPriceInPerct={pnlWMidPriceInPerctV2}\n            currentCrabPositionValue={currentCrabPositionValueV2}\n            currentCrabPositionValueInETH={currentCrabPositionValueInETHV2}\n            version=\"Crab Strategy V2\"\n          />\n        )}\n\n        {/* {!!address ? <BullPosition /> : null} */}\n\n        {activePositions?.length > 0 && (\n          <>\n            <div className={classes.header}>\n              <Typography color=\"primary\" variant=\"h6\">\n                Your LP Positions\n              </Typography>\n            </div>\n            <LPTable isLPage={false} pool={pool!} />\n          </>\n        )}\n\n        <Box mt={8} component=\"section\">\n          <Typography color=\"primary\" variant=\"h6\">\n            Your Vaults\n          </Typography>\n          <Box mt={2}>\n            <YourVaults />\n          </Box>\n        </Box>\n\n        <div className={classes.history}>\n          <Typography color=\"primary\" variant=\"h6\">\n            Transaction History\n          </Typography>\n          <History />\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/ShortSqueeth.tsx",
    "content": "import { Tooltip, Typography } from '@material-ui/core'\nimport {\n  useComputeSwaps,\n  useFirstValidVault,\n  useLPPositionsQuery,\n  useShortRealizedPnl,\n} from 'src/state/positions/hooks'\nimport useStyles from './useStyles'\nimport Link from 'next/link'\nimport { useAtomValue } from 'jotai'\nimport { loadingAtom } from 'src/state/crab/atoms'\nimport { useCurrentShortPositionValue, useShortGain, useShortUnrealizedPNL } from 'src/state/pnl/hooks'\nimport InfoIcon from '@material-ui/icons/InfoOutlined'\nimport { Tooltips } from '../../constants'\nimport { useVaultData } from '@hooks/useVaultData'\nimport { HidePnLText } from '@components/HidePnLText'\nimport { isToHidePnLAtom } from 'src/state/positions/atoms'\nimport { PnLType } from '../../types'\nimport { PnLTooltip } from '@components/PnLTooltip'\n\nexport default function ShortSqueeth() {\n  const classes = useStyles()\n  const { validVault, vaultId, isVaultLoading } = useFirstValidVault()\n  const { existingCollat, existingLiqPrice, existingCollatPercent } = useVaultData(validVault)\n  const { loading: isPositionLoading } = useLPPositionsQuery()\n  const { squeethAmount, loading: swapsLoading } = useComputeSwaps()\n  const isPnLLoading = useAtomValue(loadingAtom)\n  const shortPositionValue = useCurrentShortPositionValue()\n  const shortGain = useShortGain()\n  // const shortUnrealizedPNL = useShortUnrealizedPNL()\n  const shortRealizedPNL = useShortRealizedPnl()\n  const isToHidePnL = useAtomValue(isToHidePnLAtom)\n\n  return (\n    <div className={classes.position}>\n      <div className={classes.positionTitle}>\n        <Typography>Short Squeeth</Typography>\n        <Typography className={classes.link}>\n          <Link href={`vault/${vaultId}`}>Manage</Link>\n        </Typography>\n      </div>\n      <div className={classes.shortPositionData}>\n        <div className={classes.innerPositionData}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              oSQTH Amount\n            </Typography>\n            {isPositionLoading ? (\n              <Typography variant=\"body1\">Loading</Typography>\n            ) : (\n              <Typography variant=\"body1\" id=\"pos-page-short-osqth-bal\">\n                {squeethAmount.toFixed(8) + ' oSQTH'}\n              </Typography>\n            )}\n          </div>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Position Value\n            </Typography>\n            {isPositionLoading ? (\n              <Typography variant=\"body1\">Loading</Typography>\n            ) : (\n              <Typography variant=\"body1\">\n                {isPnLLoading && shortPositionValue.isEqualTo(0) ? 'Loading' : '$' + shortPositionValue.toFixed(2)}\n              </Typography>\n            )}\n          </div>\n        </div>\n        <div className={classes.innerPositionData} style={{ marginTop: '16px' }}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Liquidation Price\n            </Typography>\n            <Tooltip title={Tooltips.LiquidationPrice}>\n              <InfoIcon fontSize=\"small\" className={classes.infoIcon} />\n            </Tooltip>\n            <Typography variant=\"body1\">\n              {isVaultLoading && existingLiqPrice.isEqualTo(0) ? 'Loading' : '$' + existingLiqPrice.toFixed(2)}\n            </Typography>\n          </div>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Collateral (Amt / Ratio)\n            </Typography>\n            <Typography variant=\"body1\">\n              {isVaultLoading && existingCollat.isEqualTo(0) ? 'Loading' : existingCollat.toFixed(4)} ETH (\n              {existingCollatPercent}%)\n            </Typography>\n          </div>\n        </div>\n        {isToHidePnL ? (\n          <HidePnLText />\n        ) : (\n          <div className={classes.innerPositionData} style={{ marginTop: '16px' }}>\n            {/* <div style={{ width: '50%' }}>\n              <div className={classes.pnlTitle}>\n                <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n                  Unrealized P&L\n                </Typography>\n                <PnLTooltip pnlType={PnLType.Unrealized} />\n              </div>\n              {isPositionLoading || shortUnrealizedPNL.loading ? (\n                <Typography variant=\"body1\">Loading</Typography>\n              ) : (\n                <>\n                  <Typography variant=\"body1\" className={shortGain.isLessThan(0) ? classes.red : classes.green}>\n                    $ {shortUnrealizedPNL.usd.toFixed(2)} ({shortUnrealizedPNL.eth.toFixed(5)} ETH)\n                  </Typography>\n                  <Typography variant=\"caption\" className={shortGain.isLessThan(0) ? classes.red : classes.green}>\n                    {(shortGain || 0).toFixed(2)}%\n                  </Typography>\n                </>\n              )}\n            </div> */}\n            <div style={{ width: '50%' }}>\n              <div className={classes.pnlTitle}>\n                <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n                  Realized P&L\n                </Typography>\n                <PnLTooltip pnlType={PnLType.Realized} />\n              </div>\n              <Typography variant=\"body1\" className={shortRealizedPNL.gte(0) ? classes.green : classes.red}>\n                $ {swapsLoading ? 'Loading' : shortRealizedPNL.toFixed(2)}\n              </Typography>\n            </div>\n          </div>\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/ShortSqueethLiquidated.tsx",
    "content": "import { useVaultData } from '@hooks/useVaultData'\nimport { Link, Typography } from '@material-ui/core'\nimport BigNumber from 'bignumber.js'\nimport { useFirstValidVault, useLPPositionsQuery } from 'src/state/positions/hooks'\nimport useStyles from './useStyles'\n\nexport default function ShortSqueethLiquidated() {\n  const classes = useStyles()\n  const { validVault, vaultId } = useFirstValidVault()\n  const { loading: isPositionLoading } = useLPPositionsQuery()\n  const { existingCollat, existingCollatPercent } = useVaultData(validVault)\n\n  return (\n    <div className={classes.position}>\n      <div className={classes.positionTitle}>\n        <Typography className={classes.red}>Short Squeeth - Liquidated</Typography>\n        <Typography className={classes.link}>\n          <Link href={`vault/${vaultId}`}>Manage</Link>\n        </Typography>\n      </div>\n      <div className={classes.shortPositionData}>\n        <div className={classes.innerPositionData}>\n          <div style={{ width: '50%' }}>\n            <Typography variant=\"caption\" component=\"span\" color=\"textSecondary\">\n              Redeemable Collateral\n            </Typography>\n            <Typography variant=\"body1\">\n              {isPositionLoading && existingCollat.isEqualTo(0) ? 'Loading' : existingCollat.toFixed(4)} ETH\n              {new BigNumber(existingCollatPercent).isFinite() ? ' (' + existingCollatPercent + ' %)' : null}\n            </Typography>\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/YourVaults.test.tsx",
    "content": "import { render, screen } from '@testing-library/react'\nimport YourVaults from './YourVaults'\nimport * as useYourVaults from '../../hooks/useYourVaults'\n\ndescribe('YourVaults', () => {\n  const mockedVaults = [\n    {\n      id: '172',\n      shortAmount: '2800000000000000000',\n      collateralAmount: '69000000000000000000',\n    },\n  ]\n\n  const setup = async (response: any) => {\n    jest.spyOn(useYourVaults, 'default').mockReturnValue(response)\n\n    render(<YourVaults />)\n  }\n\n  it('renders loading text while API is loading', async () => {\n    await setup({ loading: true })\n\n    expect(screen.getByText(/Loading.../i)).toBeInTheDocument()\n  })\n\n  it('renders error message when there is a error', async () => {\n    await setup({\n      error: { message: 'Something went wrong!' },\n    })\n\n    expect(screen.getByText(/Something went wrong!/i)).toBeInTheDocument()\n  })\n\n  it('renders short amount and collateral amount eth correctly', async () => {\n    await setup({\n      data: { vaults: mockedVaults },\n    })\n\n    expect(screen.getByText(/69\\.0000/i)).toBeInTheDocument()\n    expect(screen.getByText(/2\\.8000/i)).toBeInTheDocument()\n  })\n\n  it('renders link to the vault detail page', async () => {\n    await setup({\n      data: { vaults: mockedVaults },\n    })\n\n    expect(screen.getByRole('link')).toHaveAttribute('href', '/vault/172')\n  })\n})\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/YourVaults.tsx",
    "content": "import LabelWithTooltip from '@components/LabelWithTooltip'\nimport SqueethCard from '@components/SqueethCard'\nimport useYourVaults from '../../hooks/useYourVaults'\nimport { Grid, Typography } from '@material-ui/core'\nimport { toTokenAmount } from '../../utils/calculations'\nimport BigNumber from 'bignumber.js'\nimport Link from 'next/link'\nimport { FC } from 'react'\n\nconst YourVaults: FC = () => {\n  const { data: { vaults } = {}, loading, error } = useYourVaults()\n\n  if (error) {\n    return <Typography color=\"error\">{error.message}</Typography>\n  }\n\n  if (loading) {\n    return <Typography>Loading...</Typography>\n  }\n\n  return (\n    <>\n      {vaults?.map((vault, index) => (\n        <Link key={vault.id} href={`/vault/${vault.id}`} passHref>\n          <a>\n            <SqueethCard mt={index ? 2 : 0}>\n              <Grid container>\n                <Grid item md={4}>\n                  <LabelWithTooltip labelVariant=\"caption\" label=\"Id\" />\n                  <Typography variant=\"body1\">{vault.id}</Typography>\n                </Grid>\n\n                <Grid item md={4}>\n                  <LabelWithTooltip labelVariant=\"caption\" label=\"Short Amount\" />\n                  <Typography variant=\"body1\">\n                    {toTokenAmount(new BigNumber(vault.shortAmount), 18).toFixed(4)}&nbsp; oSQTH\n                  </Typography>\n                </Grid>\n\n                <Grid item md={4}>\n                  <LabelWithTooltip labelVariant=\"caption\" label=\"Collateral Amount\" />\n                  <Typography variant=\"body1\">\n                    {toTokenAmount(new BigNumber(vault.collateralAmount), 18).toFixed(4)}&nbsp; ETH\n                  </Typography>\n                </Grid>\n              </Grid>\n            </SqueethCard>\n          </a>\n        </Link>\n      ))}\n    </>\n  )\n}\n\nexport default YourVaults\n"
  },
  {
    "path": "packages/frontend/src/pages/positions/useStyles.ts",
    "content": "import { createStyles, makeStyles } from '@material-ui/core'\n\nconst useStyles = makeStyles((theme) =>\n  createStyles({\n    container: {\n      margin: theme.spacing(6, 8),\n      width: '800px',\n      marginLeft: 'auto',\n      marginRight: 'auto',\n      paddingBottom: theme.spacing(8),\n      [theme.breakpoints.down('sm')]: {\n        width: '100%',\n        padding: theme.spacing(0, 2),\n      },\n    },\n    header: {\n      marginTop: theme.spacing(8),\n      display: 'flex',\n      justifyContent: 'space-between',\n    },\n    position: {\n      padding: theme.spacing(2),\n      backgroundColor: `${theme.palette.background.paper}40`,\n      marginTop: theme.spacing(2),\n      borderRadius: theme.spacing(1),\n      display: 'flex',\n      justifyContent: 'space-between',\n      [theme.breakpoints.down('sm')]: {\n        display: 'block',\n      },\n    },\n    positionData: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      width: '65%',\n      [theme.breakpoints.down('sm')]: {\n        marginTop: theme.spacing(1),\n        width: '100%',\n      },\n    },\n    shortPositionData: {\n      width: '65%',\n      [theme.breakpoints.down('sm')]: {\n        marginTop: theme.spacing(1),\n        width: '100%',\n      },\n    },\n    innerPositionData: {\n      display: 'flex',\n      width: '100%',\n      justifyContent: 'space-between',\n    },\n    positionTitle: {\n      width: '30%',\n      [theme.breakpoints.down('sm')]: {\n        width: '100%',\n      },\n    },\n    empty: {\n      marginTop: theme.spacing(2),\n    },\n    green: {\n      color: theme.palette.success.main,\n    },\n    red: {\n      color: theme.palette.error.main,\n    },\n    history: {\n      marginTop: theme.spacing(8),\n      marginBottom: theme.spacing(8),\n    },\n    link: {\n      color: theme.palette.primary.main,\n      textDecoration: 'underline',\n      fontWeight: 600,\n      fontSize: 14,\n      marginTop: theme.spacing(1),\n    },\n    infoIcon: {\n      fontSize: '10px',\n      marginLeft: theme.spacing(0.5),\n    },\n    tooltipContainer: {\n      marginLeft: '.5em',\n    },\n    dotIcon: {\n      marginRight: '1em',\n    },\n    pnlTitle: {\n      display: 'flex',\n      alignItems: 'center',\n    },\n    emoji: {\n      width: '18px',\n      maxHeight: '25px',\n    },\n  }),\n)\n\nexport default useStyles\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/Vault.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: Vault\n// ====================================================\n\nexport interface Vault_vault_owner {\n  __typename: \"Account\";\n  id: string;\n}\n\nexport interface Vault_vault {\n  __typename: \"Vault\";\n  id: string;\n  shortAmount: any;\n  collateralAmount: any;\n  NftCollateralId: any | null;\n  owner: Vault_vault_owner;\n  operator: any | null;\n}\n\nexport interface Vault {\n  vault: Vault_vault | null;\n}\n\nexport interface VaultVariables {\n  vaultID: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/VaultHistory.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\nimport { Action } from \"./../../../../types/global_apollo\";\n\n// ====================================================\n// GraphQL query operation: VaultHistory\n// ====================================================\n\nexport interface VaultHistory_vaultHistories {\n  __typename: \"VaultHistory\";\n  id: string;\n  timestamp: any;\n  totalEthCollateralAmount: any;\n  oSqthAmount: any;\n  ethCollateralAmount: any;\n  action: Action;\n  vaultId: any;\n}\n\nexport interface VaultHistory {\n  vaultHistories: VaultHistory_vaultHistories[];\n}\n\nexport interface VaultHistoryVariables {\n  vaultId: any;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/Vaults.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: Vaults\n// ====================================================\n\nexport interface Vaults_vaults_owner {\n  __typename: \"Account\";\n  id: string;\n}\n\nexport interface Vaults_vaults {\n  __typename: \"Vault\";\n  id: string;\n  shortAmount: any;\n  collateralAmount: any;\n  NftCollateralId: any | null;\n  owner: Vaults_vaults_owner;\n  operator: any | null;\n}\n\nexport interface Vaults {\n  vaults: Vaults_vaults[];\n}\n\nexport interface VaultsVariables {\n  ownerId: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/YourVaults.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: YourVaults\n// ====================================================\n\nexport interface YourVaults_vaults {\n  __typename: \"Vault\";\n  id: string;\n  shortAmount: any;\n  collateralAmount: any;\n}\n\nexport interface YourVaults {\n  vaults: YourVaults_vaults[];\n}\n\nexport interface YourVaultsVariables {\n  ownerId: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/bullHedges.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: bullHedges\n// ====================================================\n\nexport interface bullHedges_fullRebalances {\n  __typename: \"FullRebalance\";\n  id: string;\n  wPowerPerpAmount: any | null;\n  isDepositingInCrab: boolean | null;\n  timestamp: any;\n  wethTargetInEuler: any | null;\n}\n\nexport interface bullHedges_leverageRebalances {\n  __typename: \"LeverageRebalance\";\n  id: string;\n  isSellingUsdc: boolean | null;\n  usdcAmount: any;\n  timestamp: any;\n}\n\nexport interface bullHedges {\n  fullRebalances: bullHedges_fullRebalances[];\n  leverageRebalances: bullHedges_leverageRebalances[];\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/crabAuctions.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: crabAuctions\n// ====================================================\n\nexport interface crabAuctions_crabAuctions {\n  __typename: \"CrabAuction\";\n  id: string;\n  owner: any;\n  squeethAmount: any;\n  ethAmount: any;\n  isSellingSqueeth: boolean;\n  isHedgingOnUniswap: boolean;\n  timestamp: any;\n}\n\nexport interface crabAuctions {\n  crabAuctions: crabAuctions_crabAuctions[];\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/crabV2Auctions.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: crabV2Auctions\n// ====================================================\n\nexport interface crabV2Auctions_hedgeOTCs {\n  __typename: \"HedgeOTC\";\n  id: string;\n  bidID: any;\n  quantity: any;\n  isBuying: boolean;\n  clearingPrice: any;\n  timestamp: any;\n}\n\nexport interface crabV2Auctions {\n  hedgeOTCs: crabV2Auctions_hedgeOTCs[];\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/liquidations.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: liquidations\n// ====================================================\n\nexport interface liquidations_liquidations {\n  __typename: \"Liquidation\";\n  id: string;\n  debtAmount: any;\n  liquidator: any;\n  vaultId: any;\n  collateralPaid: any;\n}\n\nexport interface liquidations {\n  liquidations: liquidations_liquidations[];\n}\n\nexport interface liquidationsVariables {\n  vaultId: any;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/normalizationFactorUpdates.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: normalizationFactorUpdates\n// ====================================================\n\nexport interface normalizationFactorUpdates_normalizationFactorUpdates {\n  __typename: \"NormalizationFactorUpdate\";\n  id: string;\n  oldNormFactor: any;\n  newNormFactor: any;\n  lastModificationTimestamp: any;\n  timestamp: any;\n}\n\nexport interface normalizationFactorUpdates {\n  normalizationFactorUpdates: normalizationFactorUpdates_normalizationFactorUpdates[];\n}\n\nexport interface normalizationFactorUpdatesVariables {\n  lastID?: string | null;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/normalizationFactorUpdatesTime.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: normalizationFactorUpdatesTime\n// ====================================================\n\nexport interface normalizationFactorUpdatesTime_normalizationFactorUpdates {\n  __typename: \"NormalizationFactorUpdate\";\n  id: string;\n  oldNormFactor: any;\n  newNormFactor: any;\n  lastModificationTimestamp: any;\n  timestamp: any;\n}\n\nexport interface normalizationFactorUpdatesTime {\n  normalizationFactorUpdates: normalizationFactorUpdatesTime_normalizationFactorUpdates[];\n}\n\nexport interface normalizationFactorUpdatesTimeVariables {\n  timestamp?: number | null;\n  timestampOnedayAfter?: number | null;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/strategyQuery.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: strategyQuery\n// ====================================================\n\nexport interface strategyQuery_strategy {\n  __typename: \"Strategy\";\n  id: string;\n  vaultId: any;\n  lastHedgeTx: string;\n  lastHedgeTimestamp: any;\n}\n\nexport interface strategyQuery {\n  strategy: strategyQuery_strategy | null;\n}\n\nexport interface strategyQueryVariables {\n  strategyId: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/subscriptionVaultHistory.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\nimport { Action } from \"./../../../../types/global_apollo\";\n\n// ====================================================\n// GraphQL subscription operation: subscriptionVaultHistory\n// ====================================================\n\nexport interface subscriptionVaultHistory_vaultHistories {\n  __typename: \"VaultHistory\";\n  id: string;\n  timestamp: any;\n  totalEthCollateralAmount: any;\n  oSqthAmount: any;\n  ethCollateralAmount: any;\n  action: Action;\n  vaultId: any;\n}\n\nexport interface subscriptionVaultHistory {\n  vaultHistories: subscriptionVaultHistory_vaultHistories[];\n}\n\nexport interface subscriptionVaultHistoryVariables {\n  vaultId: any;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/subscriptionVaults.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL subscription operation: subscriptionVaults\n// ====================================================\n\nexport interface subscriptionVaults_vaults_owner {\n  __typename: \"Account\";\n  id: string;\n}\n\nexport interface subscriptionVaults_vaults {\n  __typename: \"Vault\";\n  id: string;\n  shortAmount: any;\n  collateralAmount: any;\n  NftCollateralId: any | null;\n  owner: subscriptionVaults_vaults_owner;\n  operator: any | null;\n}\n\nexport interface subscriptionVaults {\n  vaults: subscriptionVaults_vaults[];\n}\n\nexport interface subscriptionVaultsVariables {\n  ownerId: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/userBullTxes.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: userBullTxes\n// ====================================================\n\nexport interface userBullTxes_bullUserTxes {\n  __typename: \"BullUserTx\";\n  id: string;\n  owner: any;\n  bullAmount: any;\n  ethAmount: any;\n  type: string;\n  timestamp: any;\n}\n\nexport interface userBullTxes {\n  bullUserTxes: userBullTxes_bullUserTxes[];\n}\n\nexport interface userBullTxesVariables {\n  ownerId: string;\n  orderDirection: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/userCrabTxes.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: userCrabTxes\n// ====================================================\n\nexport interface userCrabTxes_crabStrategyTxes {\n  __typename: \"CrabStrategyTx\";\n  id: string;\n  type: string;\n  ethAmount: any;\n  wSqueethAmount: any | null;\n  lpAmount: any | null;\n  timestamp: any;\n}\n\nexport interface userCrabTxes {\n  crabStrategyTxes: userCrabTxes_crabStrategyTxes[];\n}\n\nexport interface userCrabTxesVariables {\n  ownerId: string;\n  orderDirection: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/__generated__/userCrabV2Txes.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: userCrabV2Txes\n// ====================================================\n\nexport interface userCrabV2Txes_crabUserTxes {\n  __typename: \"CrabUserTx\";\n  id: string;\n  type: string;\n  ethAmount: any;\n  wSqueethAmount: any | null;\n  lpAmount: any | null;\n  timestamp: any;\n  excessEth: any | null;\n  erc20Token: string | null;\n  erc20Amount: any | null;\n  transaction: string;\n}\n\nexport interface userCrabV2Txes {\n  crabUserTxes: userCrabV2Txes_crabUserTxes[];\n}\n\nexport interface userCrabV2TxesVariables {\n  ownerId: string;\n  orderDirection: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/bullHedgeQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const BULL_REBALANCE_QUERY = gql`\n  query bullHedges {\n    fullRebalances(orderBy: timestamp, orderDirection: desc) {\n      id\n      wPowerPerpAmount\n      isDepositingInCrab\n      timestamp\n      wethTargetInEuler\n    }\n    leverageRebalances(orderBy: timestamp, orderDirection: desc) {\n      id\n      isSellingUsdc\n      usdcAmount\n      timestamp\n    }\n  }\n`\nexport default BULL_REBALANCE_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/crabAuctionQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const CRAB_TX_QUERY = gql`\n  query crabAuctions {\n    crabAuctions(orderBy: timestamp, orderDirection: desc) {\n      id\n      owner\n      squeethAmount\n      ethAmount\n      isSellingSqueeth\n      isHedgingOnUniswap\n      timestamp\n    }\n  }\n`\nexport default CRAB_TX_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/crabV2AuctionQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const CRAB_V2_AUCTION_QUERY = gql`\n  query crabV2Auctions {\n    hedgeOTCs(orderBy: timestamp, orderDirection: desc) {\n      id\n      bidID\n      quantity\n      isBuying\n      clearingPrice\n      timestamp\n    }\n  }\n`\nexport default CRAB_V2_AUCTION_QUERY"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/liquidationsQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const LIQUIDATIONS_QUERY = gql`\n  query liquidations($vaultId: BigInt!) {\n    liquidations(where: { vaultId: $vaultId }) {\n      id\n      debtAmount\n      liquidator\n      vaultId\n      collateralPaid\n    }\n  }\n`\nexport default LIQUIDATIONS_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/normHistoryQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\n// Can't skip more than 5000 items. If we wan't to skip more than that we should use lastID.\n// Refer https://thegraph.com/docs/en/querying/graphql-api/#pagination\nconst NORMHISTORY_QUERY = gql`\n  query normalizationFactorUpdates($lastID: String) {\n    normalizationFactorUpdates(first: 1000, orderBy: timestamp, where: { id_gt: $lastID }) {\n      id\n      oldNormFactor\n      newNormFactor\n      lastModificationTimestamp\n      timestamp\n    }\n  }\n`\n\nexport const NORMHISTORY_TIME_QUERY = gql`\n  query normalizationFactorUpdatesTime($timestamp: Int, $timestampOnedayAfter: Int) {\n    normalizationFactorUpdates(where: { timestamp_gte: $timestamp, timestamp_lt: $timestampOnedayAfter }) {\n      id\n      oldNormFactor\n      newNormFactor\n      lastModificationTimestamp\n      timestamp\n    }\n  }\n`\n\nexport default NORMHISTORY_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/strategyQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const STRATEGY_QUERY = gql`\n  query strategyQuery($strategyId: ID!) {\n    strategy(id: $strategyId) {\n      id\n      vaultId\n      lastHedgeTx\n      lastHedgeTimestamp\n    }\n  }\n`\nexport default STRATEGY_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/userBullQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const USER_BULL_TX_QUERY = gql`\n  query userBullTxes($ownerId: ID!, $orderDirection: String!) {\n    bullUserTxes(\n      orderBy: timestamp\n      orderDirection: $orderDirection\n      where: { owner: $ownerId, type_in: [\"FLASH_DEPOSIT\", \"FLASH_WITHDRAW\"] }\n    ) {\n      id\n      owner\n      bullAmount\n      ethAmount\n      type\n      timestamp\n    }\n  }\n`\nexport default USER_BULL_TX_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/userCrabTxQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const USER_CRAB_TX_QUERY = gql`\n  query userCrabTxes($ownerId: ID!, $orderDirection: String!) {\n    crabStrategyTxes(\n      orderBy: timestamp\n      orderDirection: $orderDirection\n      where: { owner: $ownerId, type_in: [\"FLASH_DEPOSIT\", \"FLASH_WITHDRAW\"] }\n    ) {\n      id\n      type\n      ethAmount\n      wSqueethAmount\n      lpAmount\n      timestamp\n    }\n  }\n`\nexport default USER_CRAB_TX_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/userCrabV2TxQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const USER_CRAB_V2_TX_QUERY = gql`\n  query userCrabV2Txes($ownerId: ID!, $orderDirection: String!) {\n    crabUserTxes(\n      orderBy: timestamp\n      orderDirection: $orderDirection\n      where: {\n        owner: $ownerId\n        type_in: [\"FLASH_DEPOSIT\", \"FLASH_WITHDRAW\", \"DEPOSIT\", \"WITHDRAW\", \"DEPOSIT_V1\", \"OTC_DEPOSIT\", \"OTC_WITHDRAW\"]\n      }\n    ) {\n      id\n      type\n      ethAmount\n      wSqueethAmount\n      lpAmount\n      timestamp\n      excessEth\n      erc20Token\n      erc20Amount\n      transaction\n    }\n  }\n`\nexport default USER_CRAB_V2_TX_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/vaultHistoryQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nconst VAULT_HISTORY_QUERY = gql`\n  query VaultHistory($vaultId: BigInt!) {\n    vaultHistories(orderBy: timestamp, orderDirection: asc, where: { vaultId: $vaultId }) {\n      id\n      timestamp\n      totalEthCollateralAmount\n      oSqthAmount\n      ethCollateralAmount\n      action\n      vaultId\n    }\n  }\n`\n\nexport const VAULT_HISTORY_SUBSCRIPTION = gql`\n  subscription subscriptionVaultHistory($vaultId: BigInt!) {\n    vaultHistories(orderBy: timestamp, orderDirection: asc, where: { vaultId: $vaultId }) {\n      id\n      timestamp\n      totalEthCollateralAmount\n      oSqthAmount\n      ethCollateralAmount\n      action\n      vaultId\n    }\n  }\n`\n\nexport default VAULT_HISTORY_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/squeeth/vaultsQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const VAULTS_QUERY = gql`\n  query Vaults($ownerId: ID!) {\n    vaults(where: { owner: $ownerId }) {\n      id\n      shortAmount\n      collateralAmount\n      NftCollateralId\n      owner {\n        id\n      }\n      operator\n    }\n  }\n`\n\nexport const YOUR_VAULTS_QUERY = gql`\n  query YourVaults($ownerId: ID!) {\n    vaults(where: { owner: $ownerId, collateralAmount_gt: 0 }) {\n      id\n      shortAmount\n      collateralAmount\n    }\n  }\n`\n\nexport const VAULTS_SUBSCRIPTION = gql`\n  subscription subscriptionVaults($ownerId: ID!) {\n    vaults(where: { owner: $ownerId }) {\n      id\n      shortAmount\n      collateralAmount\n      NftCollateralId\n      owner {\n        id\n      }\n      operator\n    }\n  }\n`\n\nexport const VAULT_QUERY = gql`\n  query Vault($vaultID: ID!) {\n    vault(id: $vaultID) {\n      id\n      shortAmount\n      collateralAmount\n      NftCollateralId\n      owner {\n        id\n      }\n      operator\n    }\n  }\n`\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/__generated__/activePositions.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: activePositions\n// ====================================================\n\nexport interface activePositions_positions_token0 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface activePositions_positions_token1 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface activePositions_positions_pool {\n  __typename: \"Pool\";\n  id: string;\n}\n\nexport interface activePositions_positions_tickLower {\n  __typename: \"Tick\";\n  id: string;\n  price0: any;\n  price1: any;\n  tickIdx: any;\n}\n\nexport interface activePositions_positions_tickUpper {\n  __typename: \"Tick\";\n  id: string;\n  price0: any;\n  price1: any;\n  tickIdx: any;\n}\n\nexport interface activePositions_positions {\n  __typename: \"Position\";\n  id: string;\n  owner: any;\n  liquidity: any;\n  token0: activePositions_positions_token0;\n  token1: activePositions_positions_token1;\n  pool: activePositions_positions_pool;\n  tickLower: activePositions_positions_tickLower;\n  tickUpper: activePositions_positions_tickUpper;\n  collectedFeesToken0: any;\n  collectedFeesToken1: any;\n  depositedToken0: any;\n  depositedToken1: any;\n  withdrawnToken0: any;\n  withdrawnToken1: any;\n}\n\nexport interface activePositions {\n  positions: activePositions_positions[];\n}\n\nexport interface activePositionsVariables {\n  poolAddress: string;\n  owner: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/__generated__/positions.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: positions\n// ====================================================\n\nexport interface positions_positions_token0 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface positions_positions_token1 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface positions_positions_pool {\n  __typename: \"Pool\";\n  id: string;\n}\n\nexport interface positions_positions_tickLower {\n  __typename: \"Tick\";\n  id: string;\n  price0: any;\n  price1: any;\n  tickIdx: any;\n}\n\nexport interface positions_positions_tickUpper {\n  __typename: \"Tick\";\n  id: string;\n  price0: any;\n  price1: any;\n  tickIdx: any;\n}\n\nexport interface positions_positions {\n  __typename: \"Position\";\n  id: string;\n  owner: any;\n  liquidity: any;\n  token0: positions_positions_token0;\n  token1: positions_positions_token1;\n  pool: positions_positions_pool;\n  tickLower: positions_positions_tickLower;\n  tickUpper: positions_positions_tickUpper;\n  collectedFeesToken0: any;\n  collectedFeesToken1: any;\n  depositedToken0: any;\n  depositedToken1: any;\n  withdrawnToken0: any;\n  withdrawnToken1: any;\n}\n\nexport interface positions {\n  positions: positions_positions[];\n}\n\nexport interface positionsVariables {\n  poolAddress: string;\n  owner: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/__generated__/subscriptionSwaps.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL subscription operation: subscriptionSwaps\n// ====================================================\n\nexport interface subscriptionSwaps_swaps_pool_token0 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface subscriptionSwaps_swaps_pool_token1 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface subscriptionSwaps_swaps_pool {\n  __typename: \"Pool\";\n  token0: subscriptionSwaps_swaps_pool_token0;\n  token1: subscriptionSwaps_swaps_pool_token1;\n}\n\nexport interface subscriptionSwaps_swaps_transaction {\n  __typename: \"Transaction\";\n  id: string;\n  blockNumber: any;\n}\n\nexport interface subscriptionSwaps_swaps {\n  __typename: \"Swap\";\n  pool: subscriptionSwaps_swaps_pool;\n  id: string;\n  timestamp: any;\n  recipient: any;\n  amount0: any;\n  amount1: any;\n  amountUSD: any;\n  origin: any;\n  transaction: subscriptionSwaps_swaps_transaction;\n}\n\nexport interface subscriptionSwaps {\n  swaps: subscriptionSwaps_swaps[];\n}\n\nexport interface subscriptionSwapsVariables {\n  tokenAddress: any;\n  origin: any;\n  orderDirection: string;\n  recipient_not_in: any[];\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/__generated__/subscriptionSwapsRopsten.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL subscription operation: subscriptionSwapsRopsten\n// ====================================================\n\nexport interface subscriptionSwapsRopsten_swaps_pool_token0 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface subscriptionSwapsRopsten_swaps_pool_token1 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface subscriptionSwapsRopsten_swaps_pool {\n  __typename: \"Pool\";\n  token0: subscriptionSwapsRopsten_swaps_pool_token0;\n  token1: subscriptionSwapsRopsten_swaps_pool_token1;\n}\n\nexport interface subscriptionSwapsRopsten_swaps_transaction {\n  __typename: \"Transaction\";\n  id: string;\n  blockNumber: any;\n}\n\nexport interface subscriptionSwapsRopsten_swaps {\n  __typename: \"Swap\";\n  pool: subscriptionSwapsRopsten_swaps_pool;\n  id: string;\n  timestamp: any;\n  recipient: any;\n  amount0: any;\n  amount1: any;\n  amountUSD: any;\n  origin: any;\n  transaction: subscriptionSwapsRopsten_swaps_transaction;\n}\n\nexport interface subscriptionSwapsRopsten {\n  swaps: subscriptionSwapsRopsten_swaps[];\n}\n\nexport interface subscriptionSwapsRopstenVariables {\n  poolAddress: string;\n  recipients: string[];\n  origin: any;\n  orderDirection: string;\n  recipient_not_in: any[];\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/__generated__/subscriptionpositions.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL subscription operation: subscriptionpositions\n// ====================================================\n\nexport interface subscriptionpositions_positions_token0 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface subscriptionpositions_positions_token1 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface subscriptionpositions_positions_pool {\n  __typename: \"Pool\";\n  id: string;\n}\n\nexport interface subscriptionpositions_positions_tickLower {\n  __typename: \"Tick\";\n  id: string;\n  price0: any;\n  price1: any;\n  tickIdx: any;\n}\n\nexport interface subscriptionpositions_positions_tickUpper {\n  __typename: \"Tick\";\n  id: string;\n  price0: any;\n  price1: any;\n  tickIdx: any;\n}\n\nexport interface subscriptionpositions_positions {\n  __typename: \"Position\";\n  id: string;\n  owner: any;\n  liquidity: any;\n  token0: subscriptionpositions_positions_token0;\n  token1: subscriptionpositions_positions_token1;\n  pool: subscriptionpositions_positions_pool;\n  tickLower: subscriptionpositions_positions_tickLower;\n  tickUpper: subscriptionpositions_positions_tickUpper;\n  collectedFeesToken0: any;\n  collectedFeesToken1: any;\n  depositedToken0: any;\n  depositedToken1: any;\n  withdrawnToken0: any;\n  withdrawnToken1: any;\n}\n\nexport interface subscriptionpositions {\n  positions: subscriptionpositions_positions[];\n}\n\nexport interface subscriptionpositionsVariables {\n  poolAddress: string;\n  owner: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/__generated__/swaps.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: swaps\n// ====================================================\n\nexport interface swaps_swaps_pool_token0 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface swaps_swaps_pool_token1 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface swaps_swaps_pool {\n  __typename: \"Pool\";\n  token0: swaps_swaps_pool_token0;\n  token1: swaps_swaps_pool_token1;\n}\n\nexport interface swaps_swaps_transaction {\n  __typename: \"Transaction\";\n  id: string;\n  blockNumber: any;\n}\n\nexport interface swaps_swaps {\n  __typename: \"Swap\";\n  pool: swaps_swaps_pool;\n  id: string;\n  timestamp: any;\n  recipient: any;\n  amount0: any;\n  amount1: any;\n  amountUSD: any;\n  origin: any;\n  transaction: swaps_swaps_transaction;\n}\n\nexport interface swaps {\n  swaps: swaps_swaps[];\n}\n\nexport interface swapsVariables {\n  tokenAddress: any;\n  origin: any;\n  orderDirection: string;\n  recipient_not_in: any[];\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/__generated__/swapsRopsten.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: swapsRopsten\n// ====================================================\n\nexport interface swapsRopsten_swaps_pool_token0 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface swapsRopsten_swaps_pool_token1 {\n  __typename: \"Token\";\n  id: string;\n  symbol: string;\n}\n\nexport interface swapsRopsten_swaps_pool {\n  __typename: \"Pool\";\n  token0: swapsRopsten_swaps_pool_token0;\n  token1: swapsRopsten_swaps_pool_token1;\n}\n\nexport interface swapsRopsten_swaps_transaction {\n  __typename: \"Transaction\";\n  id: string;\n  blockNumber: any;\n}\n\nexport interface swapsRopsten_swaps {\n  __typename: \"Swap\";\n  pool: swapsRopsten_swaps_pool;\n  id: string;\n  timestamp: any;\n  recipient: any;\n  amount0: any;\n  amount1: any;\n  amountUSD: any;\n  origin: any;\n  transaction: swapsRopsten_swaps_transaction;\n}\n\nexport interface swapsRopsten {\n  swaps: swapsRopsten_swaps[];\n}\n\nexport interface swapsRopstenVariables {\n  poolAddress: string;\n  recipients: string[];\n  origin: any;\n  orderDirection: string;\n  recipient_not_in: any[];\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/__generated__/ticks.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: ticks\n// ====================================================\n\nexport interface ticks_ticks {\n  __typename: \"Tick\";\n  id: string;\n  tickIdx: any;\n  liquidityNet: any;\n  liquidityGross: any;\n}\n\nexport interface ticks {\n  ticks: ticks_ticks[];\n}\n\nexport interface ticksVariables {\n  poolAddress: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/__generated__/transactions.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n// ====================================================\n// GraphQL query operation: transactions\n// ====================================================\n\nexport interface transactions_positionSnapshots_transaction {\n  __typename: \"Transaction\";\n  id: string;\n  timestamp: any;\n}\n\nexport interface transactions_positionSnapshots {\n  __typename: \"PositionSnapshot\";\n  id: string;\n  owner: any;\n  liquidity: any;\n  depositedToken0: any;\n  depositedToken1: any;\n  withdrawnToken0: any;\n  withdrawnToken1: any;\n  transaction: transactions_positionSnapshots_transaction;\n}\n\nexport interface transactions {\n  positionSnapshots: transactions_positionSnapshots[];\n}\n\nexport interface transactionsVariables {\n  poolAddress: any;\n  owner: string;\n  origin: string;\n  recipients: string[];\n  orderDirection: string;\n}\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/positionsQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const POSITIONS_SUBSCRIPTION = gql`\n  subscription subscriptionpositions($poolAddress: String!, $owner: String!) {\n    positions(where: { pool: $poolAddress, owner: $owner }) {\n      id\n      owner\n      liquidity\n      token0 {\n        id\n        symbol\n      }\n      token1 {\n        id\n        symbol\n      }\n      pool {\n        id\n      }\n      tickLower {\n        id\n        price0\n        price1\n        tickIdx\n      }\n      tickUpper {\n        id\n        price0\n        price1\n        tickIdx\n      }\n      collectedFeesToken0\n      collectedFeesToken1\n      depositedToken0\n      depositedToken1\n      withdrawnToken0\n      withdrawnToken1\n    }\n  }\n`\n\nexport const POSITIONS_QUERY = gql`\n  query positions($poolAddress: String!, $owner: String!) {\n    positions(where: { pool: $poolAddress, owner: $owner }) {\n      id\n      owner\n      liquidity\n      token0 {\n        id\n        symbol\n      }\n      token1 {\n        id\n        symbol\n      }\n      pool {\n        id\n      }\n      tickLower {\n        id\n        price0\n        price1\n        tickIdx\n      }\n      tickUpper {\n        id\n        price0\n        price1\n        tickIdx\n      }\n      collectedFeesToken0\n      collectedFeesToken1\n      depositedToken0\n      depositedToken1\n      withdrawnToken0\n      withdrawnToken1\n    }\n  }\n`\n\nexport const ACTIVE_POSITIONS_QUERY = gql`\n  query activePositions($poolAddress: String!, $owner: String!) {\n    positions(where: { pool: $poolAddress, owner: $owner, liquidity_gt: 0 }) {\n      id\n      owner\n      liquidity\n      token0 {\n        id\n        symbol\n      }\n      token1 {\n        id\n        symbol\n      }\n      pool {\n        id\n      }\n      tickLower {\n        id\n        price0\n        price1\n        tickIdx\n      }\n      tickUpper {\n        id\n        price0\n        price1\n        tickIdx\n      }\n      collectedFeesToken0\n      collectedFeesToken1\n      depositedToken0\n      depositedToken1\n      withdrawnToken0\n      withdrawnToken1\n    }\n  }\n`\nexport default POSITIONS_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/swapsQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const SWAPS_SUBSCRIPTION = gql`\n  subscription subscriptionSwaps(\n    $tokenAddress: Bytes!\n    $origin: Bytes!\n    $orderDirection: String!\n    $recipient_not_in: [Bytes!]!\n  ) {\n    swaps(\n      orderBy: timestamp\n      orderDirection: $orderDirection\n      where: { token1: $tokenAddress, origin: $origin, recipient_not_in: $recipient_not_in }\n      first: 1000\n      skip: 0\n    ) {\n      pool {\n        token0 {\n          id\n          symbol\n        }\n        token1 {\n          id\n          symbol\n        }\n      }\n      id\n      timestamp\n      recipient\n      amount0\n      amount1\n      amountUSD\n      origin\n      transaction {\n        id\n        blockNumber\n      }\n    }\n  }\n`\n\nexport const SWAPS_QUERY = gql`\n  query swaps($tokenAddress: Bytes!, $origin: Bytes!, $orderDirection: String!, $recipient_not_in: [Bytes!]!) {\n    swaps(\n      orderBy: timestamp\n      orderDirection: $orderDirection\n      where: { token1: $tokenAddress, origin: $origin, recipient_not_in: $recipient_not_in, poolAddress: $poolAddress }\n      first: 1000\n      skip: 0\n    ) {\n      pool {\n        token0 {\n          id\n          symbol\n        }\n        token1 {\n          id\n          symbol\n        }\n      }\n      id\n      timestamp\n      recipient\n      amount0\n      amount1\n      amountUSD\n      origin\n      transaction {\n        id\n        blockNumber\n      }\n    }\n  }\n`\nexport default SWAPS_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/swapsRopstenQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const SWAPS_ROPSTEN_SUBSCRIPTION = gql`\n  subscription subscriptionSwapsRopsten(\n    $poolAddress: String!\n    $recipients: [String!]!\n    $origin: Bytes!\n    $orderDirection: String!\n    $recipient_not_in: [Bytes!]!\n  ) {\n    swaps(\n      orderBy: timestamp\n      orderDirection: $orderDirection\n      where: { pool: $poolAddress, origin: $origin, recipient_in: $recipients, recipient_not_in: $recipient_not_in }\n      first: 1000\n      skip: 0\n    ) {\n      pool {\n        token0 {\n          id\n          symbol\n        }\n        token1 {\n          id\n          symbol\n        }\n      }\n      id\n      timestamp\n      recipient\n      amount0\n      amount1\n      amountUSD\n      origin\n      transaction {\n        id\n        blockNumber\n      }\n    }\n  }\n`\n\nexport const SWAPS_ROPSTEN_QUERY = gql`\n  query swapsRopsten(\n    $poolAddress: String!\n    $recipients: [String!]!\n    $origin: Bytes!\n    $orderDirection: String!\n    $recipient_not_in: [Bytes!]!\n  ) {\n    swaps(\n      orderBy: timestamp\n      orderDirection: $orderDirection\n      where: { pool: $poolAddress, origin: $origin, recipient_in: $recipients, recipient_not_in: $recipient_not_in }\n      first: 1000\n      skip: 0\n    ) {\n      pool {\n        token0 {\n          id\n          symbol\n        }\n        token1 {\n          id\n          symbol\n        }\n      }\n      id\n      timestamp\n      recipient\n      amount0\n      amount1\n      amountUSD\n      origin\n      transaction {\n        id\n        blockNumber\n      }\n    }\n  }\n`\nexport default SWAPS_ROPSTEN_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/ticksQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nexport const TICKS_QUERY = gql`\n  query ticks($poolAddress: String!) {\n    ticks(where: { poolAddress: $poolAddress }, first: 1000) {\n      id\n      tickIdx\n      liquidityNet\n      liquidityGross\n    }\n  }\n`\nexport default TICKS_QUERY\n"
  },
  {
    "path": "packages/frontend/src/queries/uniswap/transactionsQuery.ts",
    "content": "import { gql } from '@apollo/client'\n\nconst TRANSACTIONS_QUERY = gql`\n  query transactions(\n    $poolAddress: Bytes!\n    $owner: String!\n    $origin: String!\n    $recipients: [String!]!\n    $orderDirection: String!\n  ) {\n    positionSnapshots(\n      orderBy: id\n      orderDirection: $orderDirection\n      where: { pool: $poolAddress, owner: $owner }\n      subgraphError: allow\n    ) {\n      id\n      owner\n      liquidity\n      depositedToken0\n      depositedToken1\n      withdrawnToken0\n      withdrawnToken1\n      transaction {\n        id\n        timestamp\n      }\n    }\n  }\n`\nexport default TRANSACTIONS_QUERY\n"
  },
  {
    "path": "packages/frontend/src/server/firebase-admin.ts",
    "content": "import { initializeApp, cert } from 'firebase-admin/app'\nimport { apps, auth, firestore } from 'firebase-admin'\n\ntry {\n  apps.length > 0\n    ? apps[0]\n    : initializeApp({\n        credential: cert({\n          projectId: 'mm-bot-prod',\n          clientEmail: process.env.FIREBASE_CLIENT_EMAIL,\n          privateKey: process.env.FIREBASE_PRIVATE_KEY,\n        }),\n      })\n} catch (e) {\n  console.log('error in init', e)\n}\n\nexport const dbAdmin = firestore()\n\nexport const updateBlockedAddress = async (address: string) => {\n  const docRef = dbAdmin.collection('blocked-addresses').doc(address)\n  const doc = await docRef.get()\n\n  let visitCount = 0\n\n  if (doc.exists) {\n    visitCount = doc.data()?.visitCount + 1\n    await docRef.set({ address, visitCount })\n  } else {\n    visitCount = 1\n    await docRef.set({ address, visitCount: 1 })\n  }\n\n  return visitCount\n}\n\nexport const getAddressStrikeCount = async (address: string) => {\n  const docRef = dbAdmin.collection('blocked-addresses').doc(address)\n  const doc = await docRef.get()\n  if (doc.exists) {\n    return doc.data()?.visitCount\n  } else {\n    return 0\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/server/ipqs.ts",
    "content": "type ApiResponse = {\n  success: boolean\n  message: string\n  fraud_score: number\n  country_code: string\n  region: string\n  city: string\n  ISP: string\n  ASN: number\n  operating_system: string\n  browser: string\n  organization: string\n  is_crawler: boolean\n  timezone: string\n  mobile: boolean\n  host: string\n  proxy: boolean\n  vpn: boolean\n  tor: boolean\n  active_vpn: boolean\n  active_tor: boolean\n  device_brand: string\n  device_model: string\n  recent_abuse: boolean\n  bot_status: boolean\n  connection_type: string\n  abuse_velocity: string\n  zip_code: string\n  latitude: number\n  longitude: number\n  request_id: string\n}\n\nasync function checkUserIP(ipAddress: string): Promise<ApiResponse | null> {\n  const key = process.env.IPQS_API_KEY\n  const strictness = 1 // This optional parameter controls the level of strictness for the lookup. Setting this option higher will increase the chance for false-positives as well as the time needed to perform the IP analysis. Increase this setting if you still continue to see fraudulent IPs with our base setting (level 1 is recommended) or decrease this setting for faster lookups with less false-positives. Current options for this parameter are 0 (fastest), 1 (recommended), 2 (more strict), or 3 (strictest).\n  const allow_public_access_points = 'true' // Bypasses certain checks for IP addresses from education and research institutions, schools, and some corporate connections to better accommodate audiences that frequently use public connections. This value can be set to true to make the service less strict while still catching the riskiest connections.\n  const url =\n    'https://www.ipqualityscore.com/api/json/ip/' +\n    key +\n    '/' +\n    ipAddress +\n    '?strictness=' +\n    strictness +\n    '&allow_public_access_points=' +\n    allow_public_access_points\n  const result = await getIPQUrl(url)\n  if (result !== null) {\n    return result\n  } else {\n    return null\n  }\n}\n\nasync function getIPQUrl(url: string): Promise<ApiResponse | null> {\n  try {\n    const response = await fetch(url)\n    const data = await response.json()\n    return data\n  } catch (error) {\n    return null\n  }\n}\n\nexport async function isVPN(ipAddress: string): Promise<boolean> {\n  const ipResult = await checkUserIP(ipAddress)\n  if (ipResult === null) {\n    return false\n  }\n\n  const isSuspectedToBeVPN = ipResult.vpn === true || ipResult.tor === true\n  if (isSuspectedToBeVPN) {\n    const org = ipResult.organization\n\n    // exclude datacenter IPs\n    // organization should include one of whitelisted datacenter organizations\n    const whitelistedDataOrgs = (process.env.WHITELISTED_DATACENTER_ORGANIZATIONS || '').split(',')\n    const isWhitelistedOrg = whitelistedDataOrgs.some((whitelistedOrg) =>\n      org.toLowerCase().includes(whitelistedOrg.toLowerCase()),\n    )\n    const isActiveVPN = ipResult.active_vpn === true\n\n    // label as isAllowedOrg only if isWhitelistedOrg and not a active VPN\n    const isAllowedOrg = isWhitelistedOrg && !isActiveVPN\n    return !isAllowedOrg\n  }\n\n  return false\n}\n"
  },
  {
    "path": "packages/frontend/src/state/bull/atoms.ts",
    "content": "import { BIG_ZERO, BULL_START_DATE, OSQUEETH_DECIMALS, USDC_DECIMALS } from '@constants/index'\nimport { indexAtom, currentImpliedFundingAtom } from '@state/controller/atoms'\nimport { crabUSDValueAtom } from '@state/crab/atoms'\nimport { toTokenAmount } from '@utils/calculations'\nimport { getBullChartData } from '@utils/pricer'\nimport BigNumber from 'bignumber.js'\nimport { atom, useAtomValue } from 'jotai'\nimport { useQuery } from 'react-query'\n\nexport const visibleStrategyRebalancesAtom = atom<number>(3)\nexport const bullCrabBalanceAtom = atom(new BigNumber(0))\nexport const bullSupplyAtom = atom(new BigNumber(0))\nexport const bullEulerWethCollatPerShareAtom = atom(new BigNumber(0))\nexport const bullEulerUsdcDebtPerShareAtom = atom(new BigNumber(0))\nexport const bullEthValuePerShareAtom = atom(new BigNumber(0))\nexport const bullCapAtom = atom(new BigNumber(0))\nexport const bullDepositedEthInEulerAtom = atom(new BigNumber(0))\nexport const bullDeltaAtom = atom(new BigNumber(0))\nexport const bullCRAtom = atom(new BigNumber(0))\n\n// Positions\nexport const bullCurrentETHPositionAtom = atom(new BigNumber(0))\nexport const bullCurrentUSDCPositionAtom = atom(new BigNumber(0))\n\nexport const bullDepositedETHAtom = atom(new BigNumber(0))\nexport const bullDepositedUSDCAtom = atom(new BigNumber(0))\n\nexport const bullEthPnlAtom = atom(new BigNumber(0))\nexport const bullEthPnlPerctAtom = atom(new BigNumber(0))\n\nexport const bullFirstDepositTimestampAtom = atom(0)\n\nexport const isBullReadyAtom = atom(false)\nexport const bullPositionLoadedAtom = atom(false)\nexport const isBullPositionRefetchingAtom = atom(false)\n\nexport const eulerUsdcBorrowRateAtom = atom(new BigNumber(0.05))\nexport const eulerETHLendRateAtom = atom(new BigNumber(0.1))\n\nexport const bullEulerUSDCDebtAtom = atom(BIG_ZERO)\n\nexport const bullCurrentFundingAtom = atom((get) => {\n  const ethPrice = toTokenAmount(get(indexAtom), OSQUEETH_DECIMALS).sqrt()\n  const usdRate = get(eulerUsdcBorrowRateAtom)\n  const ethRate = get(eulerETHLendRateAtom)\n  const usdDebt = get(bullEulerUSDCDebtAtom)\n  const ethCollat = get(bullDepositedEthInEulerAtom)\n  const ethCollatInUsd = ethCollat.times(ethPrice)\n  const dollarValueOfCrabInBull = get(bullCrabBalanceAtom).times(toTokenAmount(get(crabUSDValueAtom), 18))\n\n  const usdInterest = usdDebt.times(Math.exp(usdRate.div(365 / 2).toNumber())).minus(usdDebt)\n  const ethInterest = ethCollatInUsd.times(Math.exp(ethRate.div(365 / 2).toNumber())).minus(ethCollatInUsd)\n  const totalRate = ethInterest.minus(usdInterest)\n  const interestFunding = totalRate.div(dollarValueOfCrabInBull).div(2) // Divided by 2 because we are calculating for 2 days\n  const squeethFunding = get(currentImpliedFundingAtom)\n\n  return interestFunding.plus(squeethFunding).toNumber()\n})\n\nexport const bullThresholdAtom = atom((get) => {\n  const funding = get(bullCurrentFundingAtom)\n  if (funding < 0) return 0\n\n  const impliedVol = Math.sqrt(funding * 365)\n  return impliedVol / Math.sqrt(365 / 2)\n})\n\nexport const bullTimeAtLastHedgeAtom = atom(0)\n\nexport const bullStrategyFilterStartDateAtom = atom<Date>(new Date(BULL_START_DATE))\nexport const bullStrategyFilterEndDateAtom = atom<Date>(new Date())\n\n// Bull Recovery Withdrawal variables\nexport const bullCrabPositionValueInEth = atom(new BigNumber(0))\nexport const bullCrabValueInEth = atom(new BigNumber(0))\nexport const isBullRecoveryReadyAtom = atom(false)\n\nexport const useBullPnLChartData = () => {\n  const startDate = useAtomValue(bullStrategyFilterStartDateAtom)\n  const endDate = useAtomValue(bullStrategyFilterEndDateAtom)\n\n  return useQuery(\n    ['pnlChart', { startDate, endDate }],\n    async () =>\n      getBullChartData(\n        Number(startDate.valueOf().toString().slice(0, -3)),\n        Number(endDate.valueOf().toString().slice(0, -3)),\n      ),\n    {\n      staleTime: Infinity,\n      refetchOnWindowFocus: true,\n    },\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/state/bull/hooks.ts",
    "content": "import { useQuery } from '@apollo/client'\nimport {\n  BIG_ONE,\n  BIG_ZERO,\n  REVERTED_TRANSACTION_CODE,\n  UNI_POOL_FEES,\n  USDC_DECIMALS,\n  WETH_DECIMALS,\n  BULL_TOKEN_DECIMALS,\n} from '@constants/index'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport useAmplitude from '@hooks/useAmplitude'\nimport useAppCallback from '@hooks/useAppCallback'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { useOnChainETHPrice } from '@hooks/useETHPrice'\nimport usePopup, { GenericErrorPopupConfig } from '@hooks/usePopup'\nimport STRATEGY_QUERY from '@queries/squeeth/strategyQuery'\nimport { strategyQuery, strategyQueryVariables } from '@queries/squeeth/__generated__/strategyQuery'\nimport {\n  auctionBullContractAtom,\n  bullStrategyContractAtom,\n  eulerLensContractAtom,\n  flashBullContractAtom,\n  quoterContractAtom,\n  wethETokenContractAtom,\n  bullEmergencyWithdrawContractAtom,\n  bullShutdownEmergencyWithdrawContractAtom,\n} from '@state/contracts/atoms'\nimport { indexAtom } from '@state/controller/atoms'\nimport { crabStrategySlippageAtomV2, crabStrategyVaultAtomV2, crabTotalSupplyV2Atom } from '@state/crab/atoms'\nimport { addressesAtom } from '@state/positions/atoms'\nimport { squeethInitialPriceAtom } from '@state/squeethPool/atoms'\nimport { useGetWSqueethPositionValueInETH } from '@state/squeethPool/hooks'\nimport { addressAtom, networkIdAtom } from '@state/wallet/atoms'\nimport { useHandleTransaction } from '@state/wallet/hooks'\nimport { BULL_EVENTS } from '@utils/amplitude'\nimport { squeethClient } from '@utils/apollo-client'\nimport { fromTokenAmount, getUSDCPoolFee, toTokenAmount } from '@utils/calculations'\nimport { getExactIn, getExactOut } from '@utils/quoter'\nimport BigNumber from 'bignumber.js'\nimport { useAtomValue, useSetAtom } from 'jotai'\nimport { useUpdateAtom } from 'jotai/utils'\nimport { useEffect, useMemo, useState } from 'react'\nimport { useQueryClient } from 'react-query'\nimport { useMountedState } from 'react-use'\nimport {\n  bullCapAtom,\n  bullCRAtom,\n  bullDeltaAtom,\n  bullCrabBalanceAtom,\n  bullCurrentETHPositionAtom,\n  bullCurrentUSDCPositionAtom,\n  bullDepositedEthInEulerAtom,\n  bullEthValuePerShareAtom,\n  bullEulerUsdcDebtPerShareAtom,\n  bullEulerWethCollatPerShareAtom,\n  bullSupplyAtom,\n  isBullReadyAtom,\n  eulerUsdcBorrowRateAtom,\n  eulerETHLendRateAtom,\n  bullTimeAtLastHedgeAtom,\n  bullEulerUSDCDebtAtom,\n  bullCrabPositionValueInEth,\n  bullCrabValueInEth,\n  isBullRecoveryReadyAtom,\n} from './atoms'\nimport {\n  calcAssetNeededForFlashWithdraw,\n  getEulerInterestRate,\n  getWethToLendFromCrabEth,\n  calcAssetNeededForEmergencyWithdraw,\n} from './utils'\n\nexport const useInitBullStrategy = () => {\n  const setBullState = useSetBullState()\n  const setBullUserState = useSetBullUserState()\n  const setBullTimeAtLastHedge = useSetAtom(bullTimeAtLastHedgeAtom)\n  const { auctionBull } = useAtomValue(addressesAtom)\n  const networkId = useAtomValue(networkIdAtom)\n\n  const { data, loading } = useQuery<strategyQuery, strategyQueryVariables>(STRATEGY_QUERY, {\n    variables: { strategyId: auctionBull },\n    fetchPolicy: 'cache-and-network',\n    client: squeethClient[networkId],\n  })\n\n  useEffect(() => {\n    if (loading) return\n\n    setBullTimeAtLastHedge(data?.strategy?.lastHedgeTimestamp)\n  }, [data?.strategy?.lastHedgeTimestamp, loading, setBullTimeAtLastHedge])\n\n  useEffect(() => {\n    setBullState()\n  }, [setBullState])\n\n  useEffect(() => {\n    setBullUserState()\n  }, [setBullUserState])\n}\n\nexport const useSetBullState = () => {\n  const bullContract = useAtomValue(bullStrategyContractAtom)\n  const etokenContract = useAtomValue(wethETokenContractAtom)\n  const auctionBullContract = useAtomValue(auctionBullContractAtom)\n  const eulerLenseContract = useAtomValue(eulerLensContractAtom)\n  const setBullCrabBalance = useUpdateAtom(bullCrabBalanceAtom)\n  const setBullSupply = useUpdateAtom(bullSupplyAtom)\n  const setEulerWeth = useUpdateAtom(bullEulerWethCollatPerShareAtom)\n  const setEulerUsdc = useUpdateAtom(bullEulerUsdcDebtPerShareAtom)\n  const setBullCap = useUpdateAtom(bullCapAtom)\n  const setDepositedEth = useUpdateAtom(bullDepositedEthInEulerAtom)\n  const setBullCR = useUpdateAtom(bullCRAtom)\n  const setBullDelta = useUpdateAtom(bullDeltaAtom)\n  const setUsdcBorrowRate = useUpdateAtom(eulerUsdcBorrowRateAtom)\n  const setEthLendRate = useUpdateAtom(eulerETHLendRateAtom)\n  const setTotalUSDCInEuler = useUpdateAtom(bullEulerUSDCDebtAtom)\n  const { bullStrategy, weth, usdc } = useAtomValue(addressesAtom)\n\n  const isMounted = useMountedState()\n\n  const setBullState = useAppCallback(async () => {\n    if (!bullContract || !etokenContract || !auctionBullContract || !eulerLenseContract) return null\n    try {\n      const p1 = bullContract.methods.getCrabBalance().call()\n      const p2 = bullContract.methods.totalSupply().call()\n      const p3 = bullContract.methods.calcWethToWithdraw(BIG_ONE.toString()).call()\n      const p4 = bullContract.methods.calcUsdcToRepay(BIG_ONE.toString()).call()\n      const p5 = bullContract.methods.strategyCap().call()\n      const p6 = etokenContract.methods.balanceOfUnderlying(bullStrategy).call()\n      const p7 = auctionBullContract.methods.getCurrentDeltaAndCollatRatio().call()\n      const p8 = eulerLenseContract.methods.interestRates(weth).call()\n      const p9 = eulerLenseContract.methods.interestRates(usdc).call()\n      const p10 = eulerLenseContract.methods.getDTokenBalance(usdc, bullStrategy).call()\n\n      const [\n        crabBalance,\n        totalSupply,\n        eulerWeth,\n        eulerUsdc,\n        bullCap,\n        depositedEth,\n        deltaAndCr,\n        wethInterests,\n        usdcInterests,\n        totalUsdcInEuler,\n      ] = await Promise.all([p1, p2, p3, p4, p5, p6, p7, p8, p9, p10])\n\n      if (!isMounted()) return null\n\n      setBullCrabBalance(toTokenAmount(crabBalance, WETH_DECIMALS))\n      setBullSupply(toTokenAmount(totalSupply, WETH_DECIMALS))\n      setEulerWeth(toTokenAmount(eulerWeth, WETH_DECIMALS))\n      setEulerUsdc(toTokenAmount(eulerUsdc, USDC_DECIMALS))\n      setBullCap(toTokenAmount(bullCap, WETH_DECIMALS))\n      setDepositedEth(toTokenAmount(depositedEth, WETH_DECIMALS))\n      setBullDelta(toTokenAmount(deltaAndCr[0], WETH_DECIMALS))\n      setBullCR(toTokenAmount(deltaAndCr[1], WETH_DECIMALS))\n      setUsdcBorrowRate(getEulerInterestRate(new BigNumber(usdcInterests[1])))\n      setEthLendRate(getEulerInterestRate(new BigNumber(wethInterests[2])))\n      setTotalUSDCInEuler(toTokenAmount(totalUsdcInEuler, USDC_DECIMALS))\n    } catch (error) {\n      console.error(error)\n    }\n  }, [bullContract, etokenContract, auctionBullContract, eulerLenseContract, bullStrategy, weth, usdc, isMounted])\n\n  return setBullState\n}\n\nexport const useSetBullUserState = () => {\n  const { bullStrategy } = useAtomValue(addressesAtom)\n  const { value: bullShare } = useTokenBalance(bullStrategy)\n  const eulerWeth = useAtomValue(bullEulerWethCollatPerShareAtom)\n  const eulerUsdc = useAtomValue(bullEulerUsdcDebtPerShareAtom)\n  const index = useAtomValue(indexAtom)\n  const ethPrice = toTokenAmount(index, 18).sqrt()\n  const bullCrabBalance = useAtomValue(bullCrabBalanceAtom)\n  const bullSupply = useAtomValue(bullSupplyAtom)\n  const crabTotalSupply = useAtomValue(crabTotalSupplyV2Atom)\n  const crabV2Vault = useAtomValue(crabStrategyVaultAtomV2)\n  const getWSqueethPositionValueInETH = useGetWSqueethPositionValueInETH()\n  const setBullCurrentPosition = useUpdateAtom(bullCurrentETHPositionAtom)\n  const setBullCurrentUsdcPosition = useUpdateAtom(bullCurrentUSDCPositionAtom)\n  const setBullEthValuePerShare = useUpdateAtom(bullEthValuePerShareAtom)\n  const setBullReady = useUpdateAtom(isBullReadyAtom)\n\n  const isMounted = useMountedState()\n\n  const setBullUserState = useAppCallback(async () => {\n    if (!crabV2Vault || eulerWeth.isZero() || eulerUsdc.isZero() || !isMounted()) return null\n\n    const leverageComponent = bullShare.times(eulerWeth.minus(eulerUsdc.div(ethPrice))).div(bullSupply)\n    const userCrab = bullShare.times(bullCrabBalance).div(bullSupply)\n    const crabCollat = userCrab.times(crabV2Vault.collateralAmount).div(crabTotalSupply)\n    const crabDebt = userCrab.times(crabV2Vault.shortAmount).div(crabTotalSupply)\n    const crabDebtInEth = getWSqueethPositionValueInETH(crabDebt)\n\n    const crabComponent = crabCollat.minus(crabDebtInEth)\n    const userBullPosition = crabComponent.plus(leverageComponent)\n    if (!isMounted()) return null\n    setBullCurrentPosition(new BigNumber(userBullPosition.toFixed(18)))\n    setBullCurrentUsdcPosition(userBullPosition.times(ethPrice))\n    setBullEthValuePerShare(userBullPosition.div(bullShare))\n    setBullReady(true)\n  }, [bullCrabBalance, bullShare, bullSupply, crabTotalSupply, crabV2Vault, ethPrice, eulerUsdc, eulerWeth, isMounted])\n\n  return setBullUserState\n}\n\nexport const useBullShutdownEmergencyWithdrawState = () => {\n  const bullShutdownEmergencyWithdrawContract = useAtomValue(bullShutdownEmergencyWithdrawContractAtom)\n\n  const getWethAtRedemption = async () => {\n    try {\n      if (!bullShutdownEmergencyWithdrawContract) {\n        return BIG_ZERO\n      }\n\n      const wethAtRedemption = await bullShutdownEmergencyWithdrawContract.methods.wethAtRedemption().call()\n      return toTokenAmount(new BigNumber(wethAtRedemption.toString()), WETH_DECIMALS)\n    } catch (error) {\n      console.error('Error getting wethAtRedemption', error)\n      return BIG_ZERO\n    }\n  }\n\n  const getBullTotalSupplyAtRedemption = async () => {\n    try {\n      if (!bullShutdownEmergencyWithdrawContract) {\n        return BIG_ZERO\n      }\n\n      const bullSupplyAtRedemption = await bullShutdownEmergencyWithdrawContract.methods\n        .zenBullTotalSupplyAtRedemption()\n        .call()\n      return toTokenAmount(new BigNumber(bullSupplyAtRedemption.toString()), BULL_TOKEN_DECIMALS)\n    } catch (error) {\n      console.error('Error getting zenBullTotalSupplyAtRedemption', error)\n      return BIG_ZERO\n    }\n  }\n\n  const isContractReadyForRedemption = async () => {\n    if (!bullShutdownEmergencyWithdrawContract) {\n      return false\n    }\n\n    try {\n      const supply = await getBullTotalSupplyAtRedemption()\n      return supply.gt(0)\n    } catch (error) {\n      console.error('Error checking contract redemption state', error)\n      return false\n    }\n  }\n\n  return {\n    getWethAtRedemption,\n    getBullTotalSupplyAtRedemption,\n    isContractReadyForRedemption,\n  }\n}\n\nexport const useCalculateWethToReceive = (zenBullAmount: BigNumber) => {\n  const bullShutdownEmergencyWithdrawContract = useAtomValue(bullShutdownEmergencyWithdrawContractAtom)\n  const { getWethAtRedemption, getBullTotalSupplyAtRedemption } = useBullShutdownEmergencyWithdrawState()\n\n  const calculateWethToReceive = async () => {\n    if (!bullShutdownEmergencyWithdrawContract) {\n      return BIG_ZERO\n    }\n\n    const [wethAtRedemption, totalSupply] = await Promise.all([getWethAtRedemption(), getBullTotalSupplyAtRedemption()])\n    if (totalSupply.isZero()) {\n      return new BigNumber(0)\n    }\n    return zenBullAmount.times(wethAtRedemption).div(totalSupply)\n  }\n\n  return calculateWethToReceive\n}\n\nexport const useZenBullRedeem = () => {\n  const contract = useAtomValue(bullShutdownEmergencyWithdrawContractAtom)\n  const address = useAtomValue(addressAtom)\n  const handleTransaction = useHandleTransaction()\n  const { track } = useAmplitude()\n\n  const redeemZenBull = async (amountToRedeem: BigNumber, onTxConfirmed?: (wethToReceive: BigNumber) => void) => {\n    if (!contract) {\n      console.error('Emergency withdraw contract not initialized')\n      return null\n    }\n\n    try {\n      track(BULL_EVENTS.REDEEM_ZENBULL_CLICK)\n\n      const amountToRedeemRaw = fromTokenAmount(amountToRedeem, 18).toFixed(0)\n\n      // Get expected WETH to receive\n      const wethToReceive = await contract.methods.wethAtRedemption().call()\n      const totalSupply = await contract.methods.zenBullTotalSupplyAtRedemption().call()\n      const expectedWeth = amountToRedeem.times(wethToReceive).div(totalSupply)\n\n      // Execute transaction\n      await handleTransaction(\n        contract.methods.claimZenBullRedemption(amountToRedeemRaw).send({\n          from: address,\n        }),\n        () => onTxConfirmed?.(expectedWeth),\n      )\n\n      track(BULL_EVENTS.REDEEM_ZENBULL_SUCCESS, {\n        amountRedeemed: amountToRedeem.toNumber(),\n        wethReceived: expectedWeth.toNumber(),\n      })\n      return true\n    } catch (error: any) {\n      console.error('Error redeeming ZenBull', error)\n\n      track(BULL_EVENTS.REDEEM_ZENBULL_FAILED, {\n        amount: amountToRedeem.toNumber(),\n        error: error?.message,\n      })\n      return null\n    }\n  }\n\n  return redeemZenBull\n}\n\nexport const useInitBullRecoveryStrategy = () => {\n  const setBullRecoveryState = useSetBullRecoveryState()\n  const setBullRecoveryUserState = useSetBullRecoveryUserState()\n\n  useEffect(() => {\n    setBullRecoveryState()\n  }, [setBullRecoveryState])\n\n  useEffect(() => {\n    setBullRecoveryUserState()\n  }, [setBullRecoveryUserState])\n}\n\nexport const useSetBullRecoveryState = () => {\n  const bullContract = useAtomValue(bullStrategyContractAtom)\n  const bullEmergencyWithdrawContract = useAtomValue(bullEmergencyWithdrawContractAtom)\n\n  const setBullCrabBalance = useUpdateAtom(bullCrabBalanceAtom)\n  const setBullSupply = useUpdateAtom(bullSupplyAtom)\n\n  const isMounted = useMountedState()\n\n  const setBullRecoveryState = useAppCallback(async () => {\n    if (!bullContract || !bullEmergencyWithdrawContract) {\n      return null\n    }\n\n    try {\n      const p1 = bullContract.methods.getCrabBalance().call()\n      const p2 = bullContract.methods.totalSupply().call()\n      const p3 = bullEmergencyWithdrawContract.methods.redeemedZenBullAmountForCrabWithdrawal().call()\n\n      const [crabBalance, totalSupply, redeemed] = await Promise.all([p1, p2, p3])\n\n      if (!isMounted()) return null\n\n      setBullCrabBalance(toTokenAmount(crabBalance, WETH_DECIMALS))\n      setBullSupply(toTokenAmount(totalSupply, WETH_DECIMALS).minus(toTokenAmount(redeemed, WETH_DECIMALS)))\n    } catch (error) {\n      console.error(error)\n    }\n  }, [bullContract, bullEmergencyWithdrawContract, isMounted])\n\n  return setBullRecoveryState\n}\n\nexport const useSetBullRecoveryUserState = () => {\n  const { bullStrategy } = useAtomValue(addressesAtom)\n  const bullCrabBalance = useAtomValue(bullCrabBalanceAtom)\n  const bullSupply = useAtomValue(bullSupplyAtom)\n  const crabTotalSupply = useAtomValue(crabTotalSupplyV2Atom)\n  const crabV2Vault = useAtomValue(crabStrategyVaultAtomV2)\n  const index = useAtomValue(indexAtom)\n\n  const setBullCrabPositionValueInEth = useUpdateAtom(bullCrabPositionValueInEth)\n  const setBullCrabValueInEth = useUpdateAtom(bullCrabValueInEth)\n  const setBullRecoveryReady = useUpdateAtom(isBullRecoveryReadyAtom)\n\n  const getWSqueethPositionValueInETH = useGetWSqueethPositionValueInETH()\n  const isMounted = useMountedState()\n\n  const { value: userBullBalance } = useTokenBalance(bullStrategy)\n  const ethPrice = toTokenAmount(index, 18).sqrt()\n\n  const setBullRecoveryUserState = useAppCallback(async () => {\n    if (!crabV2Vault || !isMounted()) {\n      return null\n    }\n\n    const bullShare = bullSupply.isZero() ? BIG_ZERO : userBullBalance.div(bullSupply)\n    const userCrab = bullShare.times(bullCrabBalance)\n    const crabCollat = userCrab.times(crabV2Vault.collateralAmount).div(crabTotalSupply)\n    const crabDebt = userCrab.times(crabV2Vault.shortAmount).div(crabTotalSupply)\n    const crabDebtInEth = getWSqueethPositionValueInETH(crabDebt)\n\n    const crabComponent = crabCollat.minus(crabDebtInEth)\n    const userBullCrabPosition = crabComponent\n\n    setBullCrabPositionValueInEth(new BigNumber(userBullCrabPosition.toFixed(18)))\n    setBullCrabValueInEth(userBullCrabPosition.div(userBullBalance))\n    setBullRecoveryReady(true)\n  }, [bullCrabBalance, userBullBalance, bullSupply, crabTotalSupply, crabV2Vault, ethPrice, isMounted])\n\n  return setBullRecoveryUserState\n}\n\nexport const useGetFlashBulldepositParams = () => {\n  const bullStrategyContract = useAtomValue(bullStrategyContractAtom)\n  const crabV2Vault = useAtomValue(crabStrategyVaultAtomV2)\n  const crabTotalSupply = useAtomValue(crabTotalSupplyV2Atom)\n  const bullCrabBalance = useAtomValue(bullCrabBalanceAtom)\n  const bullSupply = useAtomValue(bullSupplyAtom)\n  const quoterContract = useAtomValue(quoterContractAtom)\n  const { weth, oSqueeth, usdc } = useAtomValue(addressesAtom)\n  const slippage = useAtomValue(crabStrategySlippageAtomV2)\n  const network = useAtomValue(networkIdAtom)\n  const queryClient = useQueryClient()\n  const ethPrice = useOnChainETHPrice()\n  const sqthPrice = useAtomValue(squeethInitialPriceAtom)\n\n  const emptyState = useMemo(\n    () => ({\n      ethToCrab: BIG_ZERO,\n      minEthFromSqth: BIG_ZERO,\n      minEthFromUsdc: BIG_ZERO,\n      ethOutForSqth: BIG_ZERO,\n      ethOutForUsdc: BIG_ZERO,\n      oSqthIn: BIG_ZERO,\n      usdcIn: BIG_ZERO,\n      wPowerPerpPoolFee: UNI_POOL_FEES,\n      usdcPoolFee: getUSDCPoolFee(network),\n      priceImpact: 0,\n      wethToLend: BIG_ZERO,\n      poolFee: 0,\n    }),\n    [network],\n  )\n\n  const getFlashBullDepositParams = useAppCallback(\n    async (totalEthDeposit: BigNumber) => {\n      if (!bullStrategyContract || !crabV2Vault || !quoterContract) return emptyState\n\n      let prevState = { ...emptyState }\n      let start = new BigNumber(0.25)\n      let end = new BigNumber(3)\n      const deviation = new BigNumber(0.0001) // .01 %\n\n      while (start.lte(end)) {\n        const middle = start.plus(end).div(2)\n\n        const ethToCrab = totalEthDeposit.times(middle)\n        const { oSqthToMint, wethToLend, usdcToBorrow } = await getWethToLendFromCrabEth(\n          bullStrategyContract,\n          ethToCrab,\n          crabV2Vault,\n          crabTotalSupply,\n          bullCrabBalance,\n          bullSupply,\n        )\n\n        if (ethToCrab.eq(prevState.ethToCrab)) break\n\n        const oSqthProceedsPromise = getExactIn(\n          quoterContract,\n          oSqueeth,\n          weth,\n          fromTokenAmount(oSqthToMint, 18),\n          UNI_POOL_FEES,\n          slippage,\n        )\n        const usdcProceedsPromise = getExactIn(\n          quoterContract,\n          usdc,\n          weth,\n          fromTokenAmount(usdcToBorrow, USDC_DECIMALS),\n          getUSDCPoolFee(network),\n          slippage,\n        )\n\n        const [\n          { minAmountOut: oSqthMinProceeds, amountOut: oSqthProceeds },\n          { minAmountOut: usdcMinProceeds, amountOut: usdcProceeds },\n        ] = await Promise.all([oSqthProceedsPromise, usdcProceedsPromise])\n\n        const minEthFromSqth = toTokenAmount(oSqthMinProceeds, 18)\n        const minEthFromUsdc = toTokenAmount(usdcMinProceeds, 18)\n        const cumulativeSpotPrice = oSqthToMint.times(sqthPrice).plus(usdcToBorrow.div(ethPrice))\n        const executionPrice = toTokenAmount(oSqthProceeds, 18).plus(toTokenAmount(usdcProceeds, 18))\n\n        const squeethSpot = oSqthToMint.times(sqthPrice) // eth from sqth trade\n        const usdcSpot = usdcToBorrow.div(ethPrice) // eth from usdc trade\n\n        // cumulative uniswap fees\n\n        const poolFee = squeethSpot\n          .times(UNI_POOL_FEES)\n          .plus(usdcSpot.times(getUSDCPoolFee(network)))\n          .div(cumulativeSpotPrice)\n\n        const priceImpact = (1 - executionPrice.div(cumulativeSpotPrice).toNumber()) * 100\n\n        prevState = {\n          ...emptyState,\n          ethToCrab,\n          minEthFromSqth,\n          minEthFromUsdc,\n          priceImpact,\n          wethToLend,\n          ethOutForSqth: toTokenAmount(oSqthProceeds, 18),\n          ethOutForUsdc: toTokenAmount(usdcProceeds, 18),\n          usdcIn: usdcToBorrow,\n          oSqthIn: oSqthToMint,\n          poolFee: poolFee.div(10000).toNumber(),\n        }\n\n        const totalToBull = ethToCrab.plus(wethToLend).minus(minEthFromSqth).minus(minEthFromUsdc)\n        // Total to bull should almost equal to totalEthDeposit\n        if (totalToBull.gt(totalEthDeposit)) {\n          end = middle\n        } else {\n          if (totalEthDeposit.div(totalToBull).minus(1).lte(deviation)) {\n            // Means we found a number lightly less than totalEthDeposit\n            break\n          }\n          start = middle\n        }\n      }\n\n      return prevState\n    },\n    [\n      bullCrabBalance,\n      bullStrategyContract,\n      bullSupply,\n      crabTotalSupply,\n      crabV2Vault,\n      emptyState,\n      ethPrice,\n      network,\n      oSqueeth,\n      quoterContract,\n      slippage,\n      sqthPrice,\n      usdc,\n      weth,\n    ],\n  )\n\n  const queryKey = useAppMemo(\n    () =>\n      `getFlashBullDepositParams-${network}-${crabTotalSupply.toString()}-${bullCrabBalance.toString()}-${bullSupply.toString()}-${crabV2Vault?.collateralAmount.toString()}-${slippage.toString()}-${ethPrice.toString()}-${sqthPrice.toString()}`,\n    [\n      network,\n      crabTotalSupply,\n      bullCrabBalance,\n      bullSupply,\n      crabV2Vault?.collateralAmount,\n      slippage,\n      ethPrice,\n      sqthPrice,\n    ],\n  )\n\n  const getCachedDepositParams = async (totalEthDeposit: BigNumber) => {\n    try {\n      const data = await queryClient.fetchQuery({\n        queryKey: `${queryKey}-${totalEthDeposit.toString()}`,\n        queryFn: () => getFlashBullDepositParams(totalEthDeposit),\n        staleTime: 60_000,\n      })\n      return data\n    } catch (error) {\n      console.log(error)\n      return emptyState\n    }\n  }\n\n  return getCachedDepositParams\n}\n\nexport const useBullFlashDeposit = () => {\n  const flashBullContract = useAtomValue(flashBullContractAtom)\n  const address = useAtomValue(addressAtom)\n  const handleTransaction = useHandleTransaction()\n  const { track } = useAmplitude()\n  const { flashBull } = useAtomValue(addressesAtom)\n  const { show: showErrorFeedbackPopup } = usePopup(\n    GenericErrorPopupConfig('Hi, I am having trouble depositing into bull.', 'deposit-bull'),\n  )\n\n  const flashDepositToBull = async (\n    ethToCrab: BigNumber,\n    minEthFromSqth: BigNumber,\n    minEthFromUsdc: BigNumber,\n    wPowerPerpPoolFee: number,\n    usdcPoolFee: number,\n    ethToSend: BigNumber,\n    dataToTrack?: any,\n    onTxConfirmed?: (id?: string) => void,\n  ) => {\n    if (!flashBullContract) return\n    track(BULL_EVENTS.DEPOSIT_BULL_CLICK, dataToTrack)\n    let gasEstimate\n    let gas\n    try {\n      try {\n        gasEstimate = await flashBullContract.methods\n          .flashDeposit({\n            ethToCrab: fromTokenAmount(ethToCrab, 18).toFixed(0),\n            minEthFromSqth: fromTokenAmount(minEthFromSqth, 18).toFixed(0),\n            minEthFromUsdc: fromTokenAmount(minEthFromUsdc, 18).toFixed(0),\n            wPowerPerpPoolFee,\n            usdcPoolFee,\n          })\n          .estimateGas({\n            to: flashBull,\n            value: fromTokenAmount(ethToSend, WETH_DECIMALS).toFixed(0),\n            from: address,\n          })\n\n        console.log('gasEstimate for flashdeposit', gasEstimate)\n        if (gasEstimate === 0) throw new Error('WRONG_GAS_ESTIMATE')\n      } catch (e) {\n        track(BULL_EVENTS.DEPOSIT_BULL_WRONG_GAS)\n        alert('Error occurred, please refresh and try again')\n        throw e\n      }\n\n      gas = Number((gasEstimate * 1.2).toFixed(0))\n\n      await handleTransaction(\n        flashBullContract.methods\n          .flashDeposit({\n            ethToCrab: fromTokenAmount(ethToCrab, 18).toFixed(0),\n            minEthFromSqth: fromTokenAmount(minEthFromSqth, 18).toFixed(0),\n            minEthFromUsdc: fromTokenAmount(minEthFromUsdc, 18).toFixed(0),\n            wPowerPerpPoolFee,\n            usdcPoolFee,\n          })\n          .send({\n            from: address,\n            value: fromTokenAmount(ethToSend, 18).toFixed(0),\n            gas: gasEstimate ? gas : undefined,\n          }),\n        onTxConfirmed,\n      )\n      track(BULL_EVENTS.DEPOSIT_BULL_SUCCESS, { ...(dataToTrack ? { ...dataToTrack, gas } : {}) })\n    } catch (e: any) {\n      const trackingData = { ...(dataToTrack ?? {}), gas }\n      e?.code === REVERTED_TRANSACTION_CODE ? track(BULL_EVENTS.DEPOSIT_BULL_REVERT, trackingData) : null\n      e?.code !== REVERTED_TRANSACTION_CODE ? showErrorFeedbackPopup() : null\n      track(BULL_EVENTS.DEPOSIT_BULL_FAILED, {\n        code: e?.code,\n        message: e?.message,\n        ...trackingData,\n      })\n      console.log(e)\n    }\n  }\n\n  return flashDepositToBull\n}\n\nexport const useGetFlashWithdrawParams = () => {\n  const bullStrategyContract = useAtomValue(bullStrategyContractAtom)\n  const crabV2Vault = useAtomValue(crabStrategyVaultAtomV2)\n  const crabTotalSupply = useAtomValue(crabTotalSupplyV2Atom)\n  const bullCrabBalance = useAtomValue(bullCrabBalanceAtom)\n  const bullSupply = useAtomValue(bullSupplyAtom)\n  const network = useAtomValue(networkIdAtom)\n  const quoterContract = useAtomValue(quoterContractAtom)\n  const slippage = useAtomValue(crabStrategySlippageAtomV2)\n  const { oSqueeth, weth, usdc } = useAtomValue(addressesAtom)\n  const queryClient = useQueryClient()\n  const ethPrice = useOnChainETHPrice()\n  const sqthPrice = useAtomValue(squeethInitialPriceAtom)\n\n  const emptyState = {\n    maxEthForWPowerPerp: BIG_ZERO,\n    maxEthForUsdc: BIG_ZERO,\n    wPowerPerpPoolFee: UNI_POOL_FEES,\n    usdcPoolFee: getUSDCPoolFee(network),\n    priceImpact: 0,\n    ethInForSqth: BIG_ZERO,\n    ethInForUsdc: BIG_ZERO,\n    oSqthOut: BIG_ZERO,\n    usdcOut: BIG_ZERO,\n    poolFee: 0,\n  }\n\n  const getFlashWithdrawParams = async (bullToFlashWithdraw: BigNumber) => {\n    if (!bullStrategyContract || !crabV2Vault || !quoterContract) return emptyState\n\n    const { wPowerPerpToRedeem, usdcToRepay } = await calcAssetNeededForFlashWithdraw(\n      bullStrategyContract,\n      bullToFlashWithdraw,\n      crabV2Vault,\n      bullSupply,\n      bullCrabBalance,\n      crabTotalSupply,\n    )\n\n    const oSqthProceedsPromise = getExactOut(\n      quoterContract,\n      weth,\n      oSqueeth,\n      fromTokenAmount(wPowerPerpToRedeem, 18),\n      UNI_POOL_FEES,\n      slippage,\n    )\n\n    const usdcProceedsPromise = getExactOut(\n      quoterContract,\n      weth,\n      usdc,\n      fromTokenAmount(usdcToRepay, USDC_DECIMALS),\n      getUSDCPoolFee(network),\n      slippage,\n    )\n\n    const [\n      { maxAmountIn: oSqthMinProceeds, amountIn: oSqthProceeds },\n      { maxAmountIn: usdcMinProceeds, amountIn: usdcProceeds },\n    ] = await Promise.all([oSqthProceedsPromise, usdcProceedsPromise])\n\n    const maxEthForWPowerPerp = toTokenAmount(oSqthMinProceeds, 18)\n    const maxEthForUsdc = toTokenAmount(usdcMinProceeds, 18)\n\n    const cumulativeSpotPrice = wPowerPerpToRedeem.times(sqthPrice).plus(usdcToRepay.div(ethPrice))\n    const executionPrice = toTokenAmount(oSqthProceeds, 18).plus(toTokenAmount(usdcProceeds, 18))\n\n    const squeethSpot = wPowerPerpToRedeem.times(sqthPrice)\n    const usdcSpot = usdcToRepay.div(ethPrice)\n\n    // cumulative uniswap fees\n\n    const poolFee = squeethSpot\n      .times(UNI_POOL_FEES)\n      .plus(usdcSpot.times(getUSDCPoolFee(network)))\n      .div(cumulativeSpotPrice)\n\n    const priceImpact = (executionPrice.div(cumulativeSpotPrice).toNumber() - 1) * 100\n\n    return {\n      ...emptyState,\n      maxEthForUsdc,\n      maxEthForWPowerPerp,\n      priceImpact,\n      ethInForSqth: toTokenAmount(oSqthProceeds, 18),\n      ethInForUsdc: toTokenAmount(usdcProceeds, 18),\n      usdcOut: usdcToRepay,\n      oSqthOut: wPowerPerpToRedeem,\n      poolFee: poolFee.div(10000).toNumber(),\n    }\n  }\n\n  const queryKey = useAppMemo(\n    () =>\n      `getFlashBullWithdrawParams-${network}-${crabTotalSupply.toString()}-${bullCrabBalance.toString()}-${bullSupply.toString()}-${crabV2Vault?.collateralAmount.toString()}-${ethPrice.toString()}-${sqthPrice.toString()}-${slippage.toString()}`,\n    [\n      network,\n      crabTotalSupply,\n      bullCrabBalance,\n      bullSupply,\n      crabV2Vault?.collateralAmount,\n      ethPrice,\n      sqthPrice,\n      slippage,\n    ],\n  )\n\n  const getCachedWithdrawParams = async (bullToWithdraw: BigNumber) => {\n    try {\n      const data = await queryClient.fetchQuery({\n        queryKey: `${queryKey}-${bullToWithdraw.toString()}`,\n        queryFn: () => getFlashWithdrawParams(bullToWithdraw),\n        staleTime: 60_000,\n      })\n      return data\n    } catch (error) {\n      console.log(error)\n      return emptyState\n    }\n  }\n\n  return getCachedWithdrawParams\n}\n\nexport const useBullFlashWithdraw = () => {\n  const flashBullContract = useAtomValue(flashBullContractAtom)\n  const address = useAtomValue(addressAtom)\n  const handleTransaction = useHandleTransaction()\n  const { track } = useAmplitude()\n  const { flashBull } = useAtomValue(addressesAtom)\n  const { show: showErrorFeedbackPopup } = usePopup(\n    GenericErrorPopupConfig('Hi, I am having trouble withdrawing from bull.', 'withdraw-bull'),\n  )\n\n  const flashWithdrawFromBull = async (\n    bullAmount: BigNumber,\n    maxEthForWPowerPerp: BigNumber,\n    maxEthForUsdc: BigNumber,\n    wPowerPerpPoolFee: number,\n    usdcPoolFee: number,\n    dataToTrack?: any,\n    onTxConfirmed?: () => void,\n  ) => {\n    if (!flashBullContract) return\n    track(BULL_EVENTS.WITHDRAW_BULL_CLICK, dataToTrack)\n    let gasEstimate\n    let gas\n    try {\n      try {\n        gasEstimate = await flashBullContract.methods\n          .flashWithdraw({\n            bullAmount: fromTokenAmount(bullAmount, 18).toFixed(0),\n            maxEthForWPowerPerp: fromTokenAmount(maxEthForWPowerPerp, 18).toFixed(0),\n            maxEthForUsdc: fromTokenAmount(maxEthForUsdc, 18).toFixed(0),\n            wPowerPerpPoolFee,\n            usdcPoolFee,\n          })\n          .estimateGas({\n            to: flashBull,\n            from: address,\n          })\n\n        console.log('gasEstimate for flashwithdraw', gasEstimate)\n        if (gasEstimate === 0) throw new Error('WRONG_GAS_ESTIMATE')\n      } catch (e) {\n        track(BULL_EVENTS.WITHDRAW_BULL_WRONG_GAS)\n        alert('Error occurred, please refresh and try again')\n        throw e\n      }\n      gas = Number((gasEstimate * 1.2).toFixed(0))\n      await handleTransaction(\n        flashBullContract.methods\n          .flashWithdraw({\n            bullAmount: fromTokenAmount(bullAmount, 18).toFixed(0),\n            maxEthForWPowerPerp: fromTokenAmount(maxEthForWPowerPerp, 18).toFixed(0),\n            maxEthForUsdc: fromTokenAmount(maxEthForUsdc, 18).toFixed(0),\n            wPowerPerpPoolFee,\n            usdcPoolFee,\n          })\n          .send({\n            from: address,\n            gas: gasEstimate ? Number((gasEstimate * 1.2).toFixed(0)) : undefined,\n          }),\n        onTxConfirmed,\n      )\n\n      track(BULL_EVENTS.WITHDRAW_BULL_SUCCESS, { ...(dataToTrack ? { ...dataToTrack, gas } : {}) })\n    } catch (e: any) {\n      const trackingData = { ...(dataToTrack ?? {}), gas }\n      e?.code === REVERTED_TRANSACTION_CODE ? track(BULL_EVENTS.WITHDRAW_BULL_REVERT, trackingData) : null\n      e?.code !== REVERTED_TRANSACTION_CODE ? showErrorFeedbackPopup() : null\n\n      track(BULL_EVENTS.WITHDRAW_BULL_FAILED, {\n        code: e?.code,\n        message: e?.message,\n        ...trackingData,\n      })\n      console.log(e)\n    }\n  }\n\n  return flashWithdrawFromBull\n}\n\nexport const useGetEmergencyWithdrawParams = () => {\n  const crabV2Vault = useAtomValue(crabStrategyVaultAtomV2)\n  const bullSupply = useAtomValue(bullSupplyAtom)\n  const bullCrabBalance = useAtomValue(bullCrabBalanceAtom)\n  const crabTotalSupply = useAtomValue(crabTotalSupplyV2Atom)\n  const quoterContract = useAtomValue(quoterContractAtom)\n  const { oSqueeth, weth } = useAtomValue(addressesAtom)\n  const slippage = useAtomValue(crabStrategySlippageAtomV2)\n  const sqthPriceInEth = useAtomValue(squeethInitialPriceAtom)\n  const network = useAtomValue(networkIdAtom)\n  const queryClient = useQueryClient()\n\n  const emptyState = {\n    maxEthForWPowerPerp: BIG_ZERO,\n    ethInForOsqth: BIG_ZERO,\n    osqthOut: BIG_ZERO,\n    wPowerPerpPoolFee: UNI_POOL_FEES,\n    priceImpact: 0,\n  }\n\n  const getEmergencyWithdrawParams = async (bullToWithdraw: BigNumber) => {\n    if (!crabV2Vault || !quoterContract) {\n      return emptyState\n    }\n\n    const { wPowerPerpToRedeem } = await calcAssetNeededForEmergencyWithdraw(\n      bullToWithdraw,\n      crabV2Vault,\n      bullSupply,\n      bullCrabBalance,\n      crabTotalSupply,\n    )\n\n    const { maxAmountIn: maxEthForOsqth, amountIn: ethForOsqth } = await getExactOut(\n      quoterContract,\n      weth,\n      oSqueeth,\n      fromTokenAmount(wPowerPerpToRedeem, 18),\n      UNI_POOL_FEES,\n      slippage,\n    )\n\n    const maxEthForWPowerPerp = toTokenAmount(maxEthForOsqth, 18)\n    const ethInForOsqth = toTokenAmount(ethForOsqth, 18)\n\n    const spotPrice = wPowerPerpToRedeem.times(sqthPriceInEth)\n    const executionPrice = ethInForOsqth\n\n    const priceImpact = (executionPrice.div(spotPrice).toNumber() - 1) * 100\n\n    return {\n      ...emptyState,\n      maxEthForWPowerPerp,\n      ethInForOsqth,\n      osqthOut: wPowerPerpToRedeem,\n      priceImpact,\n    }\n  }\n\n  const queryKey = useAppMemo(\n    () =>\n      `getEmergencyWithdrawParams-${network}-${crabTotalSupply.toString()}-${bullCrabBalance.toString()}-${bullSupply.toString()}-${crabV2Vault?.collateralAmount.toString()}-${sqthPriceInEth.toString()}-${slippage.toString()}`,\n    [network, crabTotalSupply, bullCrabBalance, bullSupply, crabV2Vault?.collateralAmount, sqthPriceInEth, slippage],\n  )\n\n  const getCachedWithdrawParams = async (bullToWithdraw: BigNumber) => {\n    try {\n      const data = await queryClient.fetchQuery({\n        queryKey: `${queryKey}-${bullToWithdraw.toString()}`,\n        queryFn: () => getEmergencyWithdrawParams(bullToWithdraw),\n        staleTime: 60_000,\n      })\n      return data\n    } catch (error) {\n      console.log(error)\n      return emptyState\n    }\n  }\n\n  return getCachedWithdrawParams\n}\n\nexport const useBullEmergencyWithdrawEthFromCrab = () => {\n  const bullEmergencyWithdrawContract = useAtomValue(bullEmergencyWithdrawContractAtom)\n  const address = useAtomValue(addressAtom)\n  const { bullEmergencyWithdraw } = useAtomValue(addressesAtom)\n  const { track } = useAmplitude()\n  const handleTransaction = useHandleTransaction()\n  const { show: showErrorFeedbackPopup } = usePopup(\n    GenericErrorPopupConfig('Hi, I am having trouble withdrawing from bull.', 'withdraw-bull-recovery'),\n  )\n\n  const bullEmergencyWithdrawFromCrab = async (\n    bullAmount: BigNumber,\n    maxEthForWPowerPerp: BigNumber,\n    dataToTrack?: any,\n    onTxConfirmed?: () => void,\n  ) => {\n    if (!bullEmergencyWithdrawContract) {\n      return\n    }\n\n    track(BULL_EVENTS.EMERGENCY_WITHDRAW_BULL_CLICK, dataToTrack)\n\n    let gasEstimate\n    let gas\n\n    try {\n      const _bullAmount = fromTokenAmount(bullAmount, 18).toFixed(0)\n      const _maxEthForWPowerPerp = fromTokenAmount(maxEthForWPowerPerp, 18).toFixed(0)\n\n      try {\n        gasEstimate = await bullEmergencyWithdrawContract.methods\n          .emergencyWithdrawEthFromCrab(_bullAmount, _maxEthForWPowerPerp)\n          .estimateGas({\n            to: bullEmergencyWithdraw,\n            from: address,\n          })\n\n        console.log('gasEstimate for bullEmergencyWithdraw', gasEstimate)\n        if (gasEstimate === 0) throw new Error('WRONG_GAS_ESTIMATE')\n      } catch (e) {\n        console.error('gas estimate error: ', e)\n        track(BULL_EVENTS.EMERGENCY_WITHDRAW_BULL_WRONG_GAS)\n        alert('Error occurred, please refresh and try again')\n        throw e\n      }\n      gas = Number((gasEstimate * 1.2).toFixed(0))\n      await handleTransaction(\n        bullEmergencyWithdrawContract.methods.emergencyWithdrawEthFromCrab(_bullAmount, _maxEthForWPowerPerp).send({\n          from: address,\n          gas: gasEstimate ? Number((gasEstimate * 1.2).toFixed(0)) : undefined,\n        }),\n        onTxConfirmed,\n      )\n\n      track(BULL_EVENTS.EMERGENCY_WITHDRAW_BULL_SUCCESS, { ...(dataToTrack ? { ...dataToTrack, gas } : {}) })\n    } catch (e: any) {\n      const trackingData = { ...(dataToTrack ?? {}), gas }\n      e?.code === REVERTED_TRANSACTION_CODE ? track(BULL_EVENTS.EMERGENCY_WITHDRAW_BULL_REVERT, trackingData) : null\n      e?.code !== REVERTED_TRANSACTION_CODE ? showErrorFeedbackPopup() : null\n\n      track(BULL_EVENTS.EMERGENCY_WITHDRAW_BULL_FAILED, {\n        code: e?.code,\n        message: e?.message,\n        ...trackingData,\n      })\n      console.log(e)\n    }\n  }\n\n  return bullEmergencyWithdrawFromCrab\n}\n"
  },
  {
    "path": "packages/frontend/src/state/bull/utils.ts",
    "content": "import { Vault } from '../../types'\nimport BigNumber from 'bignumber.js'\nimport { Contract } from 'web3-eth-contract'\nimport { fromTokenAmount, toTokenAmount } from '@utils/calculations'\nimport { BIG_ZERO, USDC_DECIMALS, WETH_DECIMALS } from '@constants/index'\n\nexport const getWethToLendFromCrabEth = async (\n  bullStrategy: Contract,\n  ethToCrab: BigNumber,\n  vault: Vault,\n  totalCrabSupply: BigNumber,\n  bullCrabBalance: BigNumber,\n  bullSupply: BigNumber,\n) => {\n  const oSqthToMint = calcWsqueethToMint(ethToCrab, vault.shortAmount, vault.collateralAmount)\n  const crabToGet = calcCrabToMint(ethToCrab, vault.collateralAmount, totalCrabSupply)\n  const bullShare = bullSupply.isZero() ? new BigNumber(1) : crabToGet.div(bullCrabBalance.plus(crabToGet))\n  const data = await bullStrategy.methods\n    .calcLeverageEthUsdc(\n      fromTokenAmount(crabToGet, 18).toFixed(0),\n      fromTokenAmount(bullShare, 18).toFixed(0),\n      fromTokenAmount(vault.collateralAmount.plus(ethToCrab), 18).toFixed(0),\n      fromTokenAmount(vault.shortAmount.plus(oSqthToMint), 18).toFixed(0),\n      fromTokenAmount(totalCrabSupply.plus(crabToGet), 18).toFixed(0),\n    )\n    .call()\n\n  const [wethToLend, usdcToBorrow] = [data[0], data[1]]\n  return {\n    oSqthToMint,\n    wethToLend: toTokenAmount(wethToLend, WETH_DECIMALS),\n    usdcToBorrow: toTokenAmount(usdcToBorrow, USDC_DECIMALS),\n  }\n}\n\nexport const calcAssetNeededForFlashWithdraw = async (\n  bullStrategy: Contract,\n  bullAmount: BigNumber,\n  vault: Vault,\n  bullSupply: BigNumber,\n  bullCrabBalance: BigNumber,\n  totalCrabSupply: BigNumber,\n) => {\n  const bullShare = bullAmount.div(bullSupply)\n  const crabToRedeem = bullShare.times(bullCrabBalance)\n  const wPowerPerpToRedeem = crabToRedeem.times(vault.shortAmount).div(totalCrabSupply)\n  const ethToWithdraw = crabToRedeem.times(vault.collateralAmount).div(totalCrabSupply)\n  const usdcToRepay = toTokenAmount(\n    await bullStrategy.methods.calcUsdcToRepay(fromTokenAmount(bullShare, 18).toFixed(0)).call(),\n    USDC_DECIMALS,\n  )\n\n  return { crabToRedeem, wPowerPerpToRedeem, ethToWithdraw, usdcToRepay }\n}\n\nexport const calcAssetNeededForEmergencyWithdraw = async (\n  bullAmount: BigNumber,\n  vault: Vault,\n  bullSupply: BigNumber,\n  bullCrabBalance: BigNumber,\n  totalCrabSupply: BigNumber,\n) => {\n  const bullShare = bullAmount.div(bullSupply)\n  const crabToRedeem = bullShare.times(bullCrabBalance)\n  const wPowerPerpToRedeem = crabToRedeem.times(vault.shortAmount).div(totalCrabSupply)\n\n  return { crabToRedeem, wPowerPerpToRedeem }\n}\n\n// ToDo: Include fee calculation\nconst calcWsqueethToMint = (depositEthAmount: BigNumber, strategyDebt: BigNumber, strategyCollat: BigNumber) => {\n  return depositEthAmount.times(strategyDebt).div(strategyCollat)\n}\n\nconst calcCrabToMint = (depositEthAmount: BigNumber, strategyCollat: BigNumber, totalSupply: BigNumber) => {\n  const depositorShare = depositEthAmount.div(strategyCollat.plus(depositEthAmount))\n\n  return totalSupply.times(depositorShare).div(new BigNumber(1).minus(depositorShare))\n}\n\n// https://docs.euler.finance/developers/numeric-limits#interestrate\nexport const getEulerInterestRate = (apy: BigNumber) => {\n  return apy.div(new BigNumber(10).pow(27))\n}\n"
  },
  {
    "path": "packages/frontend/src/state/contracts/atoms.ts",
    "content": "import { atom } from 'jotai'\nimport { Contract } from 'web3-eth-contract'\n\nimport { getContract } from '@utils/getContract'\nimport controllerAbi from '../../abis/controller.json'\nimport controllerHelperAbi from '../../abis/controllerHelper.json'\nimport crabStrategyAbi from '../../abis/crabStrategy.json'\nimport crabStrategyV2Abi from '../../abis/crabStrategyV2.json'\nimport positionManagerAbi from '../../abis/NFTpositionmanager.json'\nimport routerABI from '../../abis/swapRouter.json'\nimport uniABI from '../../abis/uniswapPool.json'\nimport shortAbi from '../../abis/shortHelper.json'\nimport crabMigrationAbi from '../../abis/crabMigration.json'\nimport quoterAbi from '../../abis/quoter.json'\nimport crabHelperAbi from '../../abis/crabHelper.json'\nimport crabNettingAbi from '../../abis/crabNetting.json'\nimport flashBullAbi from '../../abis/flashBullStrategy.json'\nimport bullStrategyAbi from '../../abis/bullStrategy.json'\nimport bullEmergencyWithdrawAbi from '../../abis/bullEmergencyWithdraw.json'\nimport bullShutdownEmergencyWithdrawAbi from '../../abis/bullShutdownEmergencyWithdraw.json'\nimport eTokenAbi from '../../abis/eulerEToken.json'\nimport auctionBullAbi from '../../abis/auctionBull.json'\nimport eulerSimpleLensAbi from '../../abis/eulerSimpleLens.json'\nimport { addressesAtom } from '../positions/atoms'\nimport { web3Atom } from '../wallet/atoms'\n\nexport const controllerContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { controller } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, controller, controllerAbi)\n})\n\nexport const crabStrategyContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { crabStrategy } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, crabStrategy, crabStrategyAbi)\n})\n\nexport const crabStrategyContractAtomV2 = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { crabStrategy2 } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, crabStrategy2, crabStrategyV2Abi)\n})\n\nexport const nftManagerContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { nftManager } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, nftManager, positionManagerAbi)\n})\n\nexport const quoterContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { quoter } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, quoter, quoterAbi)\n})\n\nexport const swapRouterContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { swapRouter } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, swapRouter, routerABI)\n})\n\nexport const swapRouter2ContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { swapRouter2 } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, swapRouter2, routerABI)\n})\n\nexport const squeethPoolContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { squeethPool } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, squeethPool, uniABI)\n})\n\nexport const shortHelperContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { shortHelper } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, shortHelper, shortAbi)\n})\n\nexport const crabMigrationContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { crabMigration } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, crabMigration, crabMigrationAbi)\n})\n\nexport const controllerHelperHelperContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { controllerHelper } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, controllerHelper, controllerHelperAbi)\n})\n\nexport const crabHelperContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { crabHelper } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, crabHelper, crabHelperAbi)\n})\n\nexport const crabNettingContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { crabNetting } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, crabNetting, crabNettingAbi)\n})\n\nexport const flashBullContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { flashBull } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, flashBull, flashBullAbi)\n})\n\nexport const bullStrategyContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { bullStrategy } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, bullStrategy, bullStrategyAbi)\n})\n\nexport const wethETokenContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { wethEToken } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, wethEToken, eTokenAbi)\n})\n\nexport const auctionBullContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { auctionBull } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, auctionBull, auctionBullAbi)\n})\n\nexport const eulerLensContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { eulerSimpleLens } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, eulerSimpleLens, eulerSimpleLensAbi)\n})\n\nexport const bullEmergencyWithdrawContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { bullEmergencyWithdraw } = get(addressesAtom)\n  if (!web3) return null\n  return getContract(web3, bullEmergencyWithdraw, bullEmergencyWithdrawAbi)\n})\n\nexport const bullShutdownEmergencyWithdrawContractAtom = atom<Contract | null>((get) => {\n  const web3 = get(web3Atom)\n  const { bullShutdownEmergencyWithdraw } = get(addressesAtom)\n  if (!web3) return null\n\n  return getContract(web3, bullShutdownEmergencyWithdraw, bullShutdownEmergencyWithdrawAbi)\n})\n"
  },
  {
    "path": "packages/frontend/src/state/controller/atoms.ts",
    "content": "import { atom } from 'jotai'\nimport BigNumber from 'bignumber.js'\n\nimport { BIG_ZERO } from '@constants/index'\n\nexport const impliedVolAtom = atom((get) => {\n  const mark = get(markAtom)\n  const index = get(indexAtom)\n  const currentImpliedFunding = get(currentImpliedFundingAtom)\n  if (mark.isZero()) return 0\n  if (mark.lt(index)) return 0\n  if (currentImpliedFunding < 0) return 0\n\n  return Math.sqrt(currentImpliedFunding * 365)\n})\n\nexport const normFactorAtom = atom(new BigNumber(Infinity))\nexport const indexForSettlementAtom = atom(BIG_ZERO)\nexport const dailyHistoricalFundingAtom = atom({ period: 0, funding: 0 })\nexport const currentImpliedFundingAtom = atom(0)\nexport const currentImpliedFundingShutdownAtom = atom(0)\nexport const dailyHistoricalFundingShutdownAtom = atom({ period: 0, funding: 0 })\nexport const impliedVolatilityShutdownAtom = atom(0)\nexport const markAtom = atom(BIG_ZERO)\nexport const indexAtom = atom(BIG_ZERO)\nexport const ethPriceAtom = atom(BIG_ZERO)\nexport const osqthRefVolAtom = atom(0)\n"
  },
  {
    "path": "packages/frontend/src/state/controller/hooks.ts",
    "content": "import { useAtom, useAtomValue } from 'jotai'\nimport BigNumber from 'bignumber.js'\n\nimport { addressAtom, networkIdAtom, web3Atom } from '../wallet/atoms'\nimport { OSQUEETH_DECIMALS, SWAP_EVENT_TOPIC, TWAP_PERIOD } from '../../constants'\nimport {\n  markAtom,\n  currentImpliedFundingAtom,\n  currentImpliedFundingShutdownAtom,\n  dailyHistoricalFundingAtom,\n  impliedVolatilityShutdownAtom,\n  impliedVolAtom,\n  indexAtom,\n  normFactorAtom,\n  osqthRefVolAtom,\n  ethPriceAtom,\n  dailyHistoricalFundingShutdownAtom,\n  indexForSettlementAtom,\n} from './atoms'\nimport { fromTokenAmount, toTokenAmount } from '@utils/calculations'\nimport { useHandleTransaction } from '../wallet/hooks'\nimport { INDEX_SCALE } from '../../constants'\nimport { addressesAtom, isWethToken0Atom } from '../positions/atoms'\nimport { useCallback, useEffect } from 'react'\nimport { useOracle } from '@hooks/contracts/useOracle'\nimport {\n  calculateLiquidationPriceForLP,\n  getCurrentImpliedFunding,\n  getCurrentImpliedFundingShutdown,\n  getDailyHistoricalFunding,\n  getDailyHistoricalFundingShutdown,\n  getImpliedVolatilityShutdown,\n  getIndex,\n  getMark,\n  getOsqthRefVol,\n} from './utils'\nimport { useGetETHandOSQTHAmount } from '../nftmanager/hooks'\nimport { controllerContractAtom } from '../contracts/atoms'\nimport { SQUEETH_UNI_POOL, ETH_USDC_POOL } from '@constants/address'\nimport useAppEffect from '@hooks/useAppEffect'\nimport useInterval from '@hooks/useInterval'\n\nexport const useOpenDepositAndMint = () => {\n  const address = useAtomValue(addressAtom)\n  const handleTransaction = useHandleTransaction()\n  const contract = useAtomValue(controllerContractAtom)\n  /**\n   * @param vaultId - 0 to create new\n   * @param amount - Amount of squeeth to mint, if 0 act as add collateral\n   * @param vaultType\n   * @returns\n   */\n  const openDepositAndMint = (\n    vaultId: number,\n    amount: BigNumber,\n    collatAmount: BigNumber,\n    onTxConfirmed?: () => void,\n  ) => {\n    if (!contract || !address) return\n\n    const _amount = fromTokenAmount(amount, OSQUEETH_DECIMALS).toFixed(0)\n    const ethAmt = fromTokenAmount(collatAmount, 18).toFixed(0)\n    return handleTransaction(\n      contract.methods.mintWPowerPerpAmount(vaultId, _amount.toString(), 0).send({\n        from: address,\n        value: ethAmt,\n      }),\n      onTxConfirmed,\n    )\n  }\n\n  return openDepositAndMint\n}\n\nexport const useDepositCollateral = () => {\n  const address = useAtomValue(addressAtom)\n  const handleTransaction = useHandleTransaction()\n  const contract = useAtomValue(controllerContractAtom)\n  /**\n   * Less gas than openDepositAndMint if only deposit is needed\n   * @param vaultId\n   * @param collatAmount\n   */\n  const depositCollateral = (vaultId: number, collatAmount: BigNumber, onTxConfirmed?: () => void) => {\n    if (!contract || !address) return\n\n    const ethAmt = fromTokenAmount(collatAmount, 18)\n    return handleTransaction(\n      contract.methods.deposit(vaultId).send({\n        from: address,\n        value: ethAmt.toFixed(0),\n      }),\n      onTxConfirmed,\n    )\n  }\n  return depositCollateral\n}\n\nexport const useWithdrawCollateral = () => {\n  const address = useAtomValue(addressAtom)\n  const handleTransaction = useHandleTransaction()\n  const contract = useAtomValue(controllerContractAtom)\n  /**\n   * Less gas than burnAndRedeem\n   * @param vaultId\n   * @param collatAmount\n   * @returns\n   */\n  const withdrawCollateral = (vaultId: number, collatAmount: BigNumber, onTxConfirmed?: () => void) => {\n    if (!contract || !address) return\n\n    const ethAmt = fromTokenAmount(collatAmount, 18)\n    return handleTransaction(\n      contract.methods.withdraw(vaultId, ethAmt.toFixed(0)).send({\n        from: address,\n      }),\n      onTxConfirmed,\n    )\n  }\n\n  return withdrawCollateral\n}\n\nexport const useBurnAndRedeem = () => {\n  const address = useAtomValue(addressAtom)\n  const handleTransaction = useHandleTransaction()\n  const contract = useAtomValue(controllerContractAtom)\n  /**\n   * @param vaultId\n   * @param amount - Amount of squeeth to burn, if 0 act as remove collateral\n   * @param collatAmount - Amount of collat to remove\n   * @returns\n   */\n  const burnAndRedeem = (vaultId: number, amount: BigNumber, collatAmount: BigNumber, onTxConfirmed?: () => void) => {\n    if (!contract || !address) return\n\n    const _amount = fromTokenAmount(amount, OSQUEETH_DECIMALS)\n    const ethAmt = fromTokenAmount(collatAmount, 18)\n    return handleTransaction(\n      contract.methods.burnWPowerPerpAmount(vaultId, _amount.toFixed(0), ethAmt.toFixed(0)).send({\n        from: address,\n      }),\n      onTxConfirmed,\n    )\n  }\n  return burnAndRedeem\n}\n\nexport const useUpdateOperator = () => {\n  const address = useAtomValue(addressAtom)\n  const handleTransaction = useHandleTransaction()\n  const contract = useAtomValue(controllerContractAtom)\n  /**\n   * Authorize an address to modify the vault\n   * @param vaultId\n   * @param operator\n   */\n  const updateOperator = async (vaultId: number, operator: string, onTxConfirmed?: () => void) => {\n    if (!contract || !address) return\n\n    await handleTransaction(\n      contract.methods.updateOperator(vaultId, operator).send({\n        from: address,\n      }),\n      onTxConfirmed,\n    )\n  }\n\n  return updateOperator\n}\n\nexport const useGetVault = () => {\n  const contract = useAtomValue(controllerContractAtom)\n\n  const getVault = useCallback(\n    async (vaultId: number) => {\n      if (!contract) return null\n      const vault = await contract.methods.vaults(vaultId).call()\n      const { NftCollateralId, collateralAmount, shortAmount, operator } = vault\n\n      return {\n        id: vaultId,\n        NFTCollateralId: NftCollateralId,\n        collateralAmount: toTokenAmount(new BigNumber(collateralAmount), 18),\n        shortAmount: toTokenAmount(new BigNumber(shortAmount), OSQUEETH_DECIMALS),\n        operator,\n      }\n    },\n    [contract],\n  )\n\n  return getVault\n}\n\nexport const useGetDebtAmount = () => {\n  const { ethUsdcPool, weth, usdc } = useAtomValue(addressesAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  const normFactor = useAtomValue(normFactorAtom)\n  const { getTwapSafe } = useOracle()\n  const getDebtAmount = useCallback(\n    async (shortAmount: BigNumber) => {\n      if (!contract) return new BigNumber(0)\n\n      const ethUsdcPrice = await getTwapSafe(ethUsdcPool, weth, usdc, TWAP_PERIOD)\n      const _shortAmt = fromTokenAmount(shortAmount, OSQUEETH_DECIMALS)\n      const ethDebt = new BigNumber(_shortAmt).div(INDEX_SCALE).multipliedBy(normFactor).multipliedBy(ethUsdcPrice)\n      return toTokenAmount(ethDebt, 18)\n    },\n    [contract, ethUsdcPool, getTwapSafe, normFactor?.toString(), usdc, weth],\n  )\n  return getDebtAmount\n}\n\n// get ETH debt amount based on the settlement index price\nexport const useGetOSqthSettlementAmount = () => {\n  const contract = useAtomValue(controllerContractAtom)\n  const normFactor = useAtomValue(normFactorAtom)\n  const indexForSettlement = useAtomValue(indexForSettlementAtom)\n\n  const getOSqthSettlementAmount = useCallback(\n    async (shortAmount: BigNumber) => {\n      if (!contract) {\n        return new BigNumber(0)\n      }\n      // sometimes getting normFactor as infinite number\n      if (!normFactor.isFinite()) {\n        return new BigNumber(0)\n      }\n\n      const shortAmountRaw = fromTokenAmount(shortAmount, OSQUEETH_DECIMALS)\n      const ethDebt = shortAmountRaw.multipliedBy(normFactor).multipliedBy(indexForSettlement)\n      return toTokenAmount(ethDebt, 18)\n    },\n    [contract, normFactor?.toString(), indexForSettlement?.toString()],\n  )\n  return getOSqthSettlementAmount\n}\n\nexport const useGetTwapEthPrice = () => {\n  const { ethUsdcPool, weth, usdc } = useAtomValue(addressesAtom)\n  const { getTwapSafe } = useOracle()\n  const getTwapEthPrice = useCallback(\n    async () => await getTwapSafe(ethUsdcPool, weth, usdc, TWAP_PERIOD),\n    [usdc, ethUsdcPool, getTwapSafe, weth],\n  )\n\n  return getTwapEthPrice\n}\n\nexport const useGetShortAmountFromDebt = () => {\n  const { ethUsdcPool, weth, usdc } = useAtomValue(addressesAtom)\n  const normFactor = useAtomValue(normFactorAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  const { getTwapSafe } = useOracle()\n  const getShortAmountFromDebt = async (debtAmount: BigNumber) => {\n    if (!contract) return new BigNumber(0)\n\n    const ethUsdcPrice = await getTwapSafe(ethUsdcPool, weth, usdc, TWAP_PERIOD)\n    const shortAmount = fromTokenAmount(debtAmount, 18).times(INDEX_SCALE).div(normFactor).div(ethUsdcPrice)\n    return toTokenAmount(shortAmount.toFixed(0), OSQUEETH_DECIMALS)\n  }\n\n  return getShortAmountFromDebt\n}\n\nexport const useGetUniNFTCollatDetail = () => {\n  const normFactor = useAtomValue(normFactorAtom)\n  const getETHandOSQTHAmount = useGetETHandOSQTHAmount()\n  const getTwapEthPrice = useGetTwapEthPrice()\n\n  const getUniNFTCollatDetail = async (uniId: number) => {\n    const ethPrice = await getTwapEthPrice()\n    const { wethAmount, oSqthAmount, position } = await getETHandOSQTHAmount(uniId)\n    const sqthValueInEth = oSqthAmount.multipliedBy(normFactor).multipliedBy(ethPrice).div(INDEX_SCALE)\n\n    return { collateral: sqthValueInEth.plus(wethAmount), position }\n  }\n\n  return getUniNFTCollatDetail\n}\n\nexport const useGetUniNFTDetails = () => {\n  const normFactor = useAtomValue(normFactorAtom)\n  const getETHandOSQTHAmount = useGetETHandOSQTHAmount()\n  const getTwapEthPrice = useGetTwapEthPrice()\n\n  const getUniNFTAmounts = async (uniId: number) => {\n    const ethPrice = await getTwapEthPrice()\n    const { wethAmount, oSqthAmount, position } = await getETHandOSQTHAmount(uniId)\n    const sqthValueInEth = oSqthAmount.multipliedBy(normFactor).multipliedBy(ethPrice).div(INDEX_SCALE)\n\n    return {\n      ethAmount: wethAmount,\n      squeethAmount: oSqthAmount,\n      squeethValueInEth: sqthValueInEth,\n      position,\n    }\n  }\n\n  return getUniNFTAmounts\n}\n\nexport const useGetCollatRatioAndLiqPrice = () => {\n  const impliedVol = useAtomValue(impliedVolAtom)\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n  const normFactor = useAtomValue(normFactorAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  const getTwapEthPrice = useGetTwapEthPrice()\n  const getDebtAmount = useGetDebtAmount()\n  const getETHandOSQTHAmount = useGetETHandOSQTHAmount()\n  const getUniNFTCollatDetail = useGetUniNFTCollatDetail()\n  const getCollatRatioAndLiqPrice = useCallback(\n    async (collateralAmount: BigNumber, shortAmount: BigNumber, uniId?: number) => {\n      const emptyState = {\n        collateralPercent: 0,\n        liquidationPrice: new BigNumber(0),\n      }\n      if (!contract || !normFactor) return emptyState\n\n      let effectiveCollat = collateralAmount\n      let liquidationPrice = new BigNumber(0)\n      // Uni LP token is deposited\n      if (uniId) {\n        const { collateral: uniCollat, position } = await getUniNFTCollatDetail(uniId)\n        effectiveCollat = effectiveCollat.plus(uniCollat)\n\n        if (position) {\n          liquidationPrice = calculateLiquidationPriceForLP(\n            collateralAmount,\n            shortAmount,\n            position,\n            isWethToken0,\n            normFactor,\n            impliedVol,\n          )\n        }\n      }\n      const debt = await getDebtAmount(shortAmount)\n\n      if (debt && !debt.isZero() && debt.isPositive()) {\n        const collateralPercent = Number(effectiveCollat.div(debt).times(100).toFixed(1))\n        const rSqueeth = normFactor.multipliedBy(new BigNumber(shortAmount)).dividedBy(10000)\n        if (!uniId) liquidationPrice = effectiveCollat.div(rSqueeth.multipliedBy(1.5))\n\n        return {\n          collateralPercent,\n          liquidationPrice,\n        }\n      }\n\n      return emptyState\n    },\n    [contract, getDebtAmount, getETHandOSQTHAmount, getTwapEthPrice, impliedVol, isWethToken0, normFactor.toString()],\n  )\n\n  return getCollatRatioAndLiqPrice\n}\n\nexport const useDepositUnuPositionToken = () => {\n  const address = useAtomValue(addressAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const depositUniPositionToken = async (vaultId: number, uniTokenId: number, onTxConfirmed?: () => void) => {\n    if (!contract || !address) return\n\n    await handleTransaction(\n      contract.methods.depositUniPositionToken(vaultId, uniTokenId).send({\n        from: address,\n      }),\n      onTxConfirmed,\n    )\n  }\n  return depositUniPositionToken\n}\n\nexport const useWithdrawUniPositionToken = () => {\n  const address = useAtomValue(addressAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const withdrawUniPositionToken = async (vaultId: number, onTxConfirmed?: () => void) => {\n    if (!contract || !address) return\n    await handleTransaction(\n      contract.methods.withdrawUniPositionToken(vaultId).send({\n        from: address,\n      }),\n      onTxConfirmed,\n    )\n  }\n  return withdrawUniPositionToken\n}\n\nexport const useRedeemVault = () => {\n  const address = useAtomValue(addressAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  const handleTransaction = useHandleTransaction()\n\n  const redeemVault = async (vaultId: number, onTxConfirmed?: () => void) => {\n    if (!contract || !address) return\n    await handleTransaction(\n      contract.methods.redeemShort(vaultId).send({\n        from: address,\n      }),\n      onTxConfirmed,\n    )\n  }\n  return redeemVault\n}\n\nconst useNormFactor = () => {\n  const networkId = useAtomValue(networkIdAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  const [normFactor, setNormFactor] = useAtom(normFactorAtom)\n  useEffect(() => {\n    if (!contract) return\n    contract.methods\n      .getExpectedNormalizationFactor()\n      .call()\n      .then((normFactor: any) => {\n        setNormFactor(toTokenAmount(new BigNumber(normFactor.toString()), 18))\n      })\n      .catch(() => {\n        contract.methods\n          .normalizationFactor()\n          .call()\n          .then((normFactor: any) => {\n            setNormFactor(toTokenAmount(new BigNumber(normFactor.toString()), 18))\n          })\n          .catch(() => {\n            console.log('normFactor error')\n          })\n      })\n  }, [contract, setNormFactor, networkId])\n\n  return normFactor\n}\n\nconst useIndex = () => {\n  const address = useAtomValue(addressAtom)\n  const web3 = useAtomValue(web3Atom)\n  const networkId = useAtomValue(networkIdAtom)\n  const [index, setIndex] = useAtom(indexAtom)\n  const contract = useAtomValue(controllerContractAtom)\n\n  useEffect(() => {\n    if (!contract) return\n    getIndex(1, contract).then(setIndex)\n  }, [address, networkId, contract, setIndex])\n\n  // setup index listender\n  useEffect(() => {\n    if (!web3) return\n    const sub = web3.eth.subscribe(\n      'logs',\n      {\n        address: [ETH_USDC_POOL[networkId]],\n        topics: [SWAP_EVENT_TOPIC],\n      },\n      () => {\n        getIndex(1, contract).then(setIndex)\n      },\n    )\n\n    return () => {\n      sub.unsubscribe()\n    }\n  }, [contract, web3, networkId])\n\n  return index\n}\n\nexport const useUpdateEthPrice = () => {\n  const { getTwapSafe } = useOracle()\n  const [ethPrice, setEthPrice] = useAtom(ethPriceAtom)\n  const { ethUsdcPool, weth, usdc } = useAtomValue(addressesAtom)\n\n  const getTwapEth = () => {\n    if (ethUsdcPool && weth && usdc) {\n      getTwapSafe(ethUsdcPool, weth, usdc, 1).then((quote) => {\n        setEthPrice(quote)\n      })\n    }\n  }\n\n  useInterval(getTwapEth, 15000)\n\n  useAppEffect(() => {\n    getTwapEth()\n  }, [getTwapSafe])\n\n  return ethPrice\n}\n\nconst useDailyHistoricalFunding = () => {\n  const address = useAtomValue(addressAtom)\n  const networkId = useAtomValue(networkIdAtom)\n  const [dailyHistoricalFunding, setDailyHistoricalFunding] = useAtom(dailyHistoricalFundingAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  useEffect(() => {\n    if (!contract) return\n    getDailyHistoricalFunding(contract).then(setDailyHistoricalFunding)\n  }, [address, networkId, contract, setDailyHistoricalFunding])\n\n  return dailyHistoricalFunding\n}\n\nconst useCurrentImpliedFunding = () => {\n  const address = useAtomValue(addressAtom)\n  const networkId = useAtomValue(networkIdAtom)\n  const [currentImpliedFunding, setCurrentImpliedFunding] = useAtom(currentImpliedFundingAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  useEffect(() => {\n    if (!contract) return\n    getCurrentImpliedFunding(contract).then(setCurrentImpliedFunding)\n  }, [address, networkId, setCurrentImpliedFunding, contract])\n\n  return currentImpliedFunding\n}\n\nconst useCurrentImpliedFundingShutdown = () => {\n  const address = useAtomValue(addressAtom)\n  const networkId = useAtomValue(networkIdAtom)\n  const [currentImpliedFundingShutdown, setCurrentImpliedFundingShutdown] = useAtom(currentImpliedFundingShutdownAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  useEffect(() => {\n    if (!contract) return\n    getCurrentImpliedFundingShutdown(contract).then(setCurrentImpliedFundingShutdown)\n  }, [address, networkId, setCurrentImpliedFundingShutdown, contract])\n\n  return currentImpliedFundingShutdown\n}\n\nconst useDailyHistoricalFundingShutdown = () => {\n  const address = useAtomValue(addressAtom)\n  const networkId = useAtomValue(networkIdAtom)\n  const [dailyHistoricalFundingShutdown, setDailyHistoricalFundingShutdown] = useAtom(\n    dailyHistoricalFundingShutdownAtom,\n  )\n  const contract = useAtomValue(controllerContractAtom)\n  useEffect(() => {\n    if (!contract) return\n    getDailyHistoricalFundingShutdown(contract).then(setDailyHistoricalFundingShutdown)\n  }, [address, networkId, setDailyHistoricalFundingShutdown, contract])\n\n  return dailyHistoricalFundingShutdown\n}\n\nconst useImpliedVolatilityShutdown = () => {\n  const address = useAtomValue(addressAtom)\n  const networkId = useAtomValue(networkIdAtom)\n  const [impliedVolatilityShutdown, setImpliedVolatilityShutdown] = useAtom(impliedVolatilityShutdownAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  useEffect(() => {\n    if (!contract) return\n    getImpliedVolatilityShutdown(contract).then(setImpliedVolatilityShutdown)\n  }, [address, networkId, setImpliedVolatilityShutdown, contract])\n\n  return impliedVolatilityShutdown\n}\n\nconst useMark = () => {\n  const address = useAtomValue(addressAtom)\n  const web3 = useAtomValue(web3Atom)\n  const networkId = useAtomValue(networkIdAtom)\n  const [mark, setMark] = useAtom(markAtom)\n  const contract = useAtomValue(controllerContractAtom)\n\n  useEffect(() => {\n    if (!contract) return\n    getMark(1, contract).then(setMark)\n  }, [address, networkId, contract, setMark])\n\n  // setup mark listener\n  useEffect(() => {\n    if (!web3) return\n    const sub = web3.eth.subscribe(\n      'logs',\n      {\n        address: [SQUEETH_UNI_POOL[networkId]],\n        topics: [SWAP_EVENT_TOPIC],\n      },\n      () => {\n        getMark(3, contract).then(setMark)\n      },\n    )\n    // cleanup function\n    return () => {\n      sub.unsubscribe()\n    }\n  }, [contract, networkId, web3])\n\n  return mark\n}\n\nconst useOsqthRefVol = async (): Promise<number> => {\n  const address = useAtomValue(addressAtom)\n  const networkId = useAtomValue(networkIdAtom)\n  const [OsqthRefVol, setOsqthRefVol] = useAtom(osqthRefVolAtom)\n  useEffect(() => {\n    getOsqthRefVol().then(setOsqthRefVol)\n  }, [address, networkId])\n  return OsqthRefVol\n}\n\nconst useIndexForSettlement = () => {\n  const networkId = useAtomValue(networkIdAtom)\n  const contract = useAtomValue(controllerContractAtom)\n  const [indexForSettlement, setIndexForSettlement] = useAtom(indexForSettlementAtom)\n  useEffect(() => {\n    if (!contract) return\n\n    contract.methods\n      .indexForSettlement()\n      .call()\n      .then((_indexPriceForSettlement: any) => {\n        setIndexForSettlement(toTokenAmount(new BigNumber(_indexPriceForSettlement.toString()), 18))\n      })\n      .catch(() => {\n        console.log('indexForSettlement error')\n      })\n  }, [contract, setIndexForSettlement, networkId])\n\n  return indexForSettlement\n}\n\nexport const useInitController = () => {\n  useIndex()\n  useUpdateEthPrice()\n  useMark()\n  useCurrentImpliedFunding()\n  useCurrentImpliedFundingShutdown()\n  useDailyHistoricalFundingShutdown()\n  useImpliedVolatilityShutdown()\n  useDailyHistoricalFunding()\n  useNormFactor()\n  // useOsqthRefVol()\n  useIndexForSettlement()\n}\n"
  },
  {
    "path": "packages/frontend/src/state/controller/utils.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { Contract } from 'web3-eth-contract'\nimport { Position } from '@uniswap/v3-sdk'\nimport fzero from 'fzero'\n\nimport { toTokenAmount } from '@utils/calculations'\nimport { Vault } from '../../types'\nimport { FUNDING_PERIOD, INDEX_SCALE, BIG_ONE, SHUTDOWN_DATE, BIG_ZERO, OSQUEETH_DECIMALS } from '../../constants'\nimport floatifyBigNums from '@utils/floatifyBigNums'\n\n/**\n * Liquidation price is calculated using this document: https://docs.google.com/document/d/1MzuPADIZqLm3aQu-Ri2Iyk9ZUvDA1D6oOikKwwjSC2M/edit\n *\n * If you have any doubts please ask Joe Clark aka alpinechicken 🦔\n */\nexport const calculateLiquidationPriceForLP = (\n  ethCollat: BigNumber,\n  shortAmount: BigNumber,\n  position: Position,\n  isWethToken0: boolean,\n  normFactor: BigNumber,\n  impliedVol: number,\n) => {\n  const liquidity = toTokenAmount(position.liquidity.toString(), 18)\n\n  const ETH_LOWER_BOUND = 500\n  const ETH_UPPER_BOUND = 30000\n\n  const pa = !isWethToken0\n    ? new BigNumber(position?.token0PriceLower.toSignificant(18) || 0)\n    : new BigNumber(1).div(position?.token0PriceUpper.toSignificant(18) || 0)\n  const pb = !isWethToken0\n    ? new BigNumber(position?.token0PriceUpper.toSignificant(18) || 0)\n    : new BigNumber(1).div(position?.token0PriceLower.toSignificant(18) || 0)\n\n  const maxEth = liquidity.times(pb.sqrt().minus(pa.sqrt()))\n  const maxSqth = liquidity.times(new BigNumber(1).div(pa.sqrt()).minus(new BigNumber(1).div(pb.sqrt())))\n\n  const divider = shortAmount.times(1.5).times(normFactor)\n\n  const ethValueFunction = (ethPrice: string) => {\n    const _ethPrice = new BigNumber(ethPrice)\n    const p = _ethPrice\n      .times(normFactor)\n      .times(Math.exp(impliedVol * impliedVol * 0.04794520548))\n      .div(INDEX_SCALE)\n\n    if (p.lt(pa)) {\n      return maxSqth.times(p)\n    }\n    if (p.gt(pb)) {\n      return maxEth\n    }\n\n    return liquidity.times(p.sqrt().times(2).minus(pa.sqrt()).minus(p.div(pb.sqrt())))\n  }\n\n  const fzeroFunction = (ethPrice: string) => {\n    const _result = new BigNumber(ethPrice)\n      .minus(ethValueFunction(ethPrice).plus(ethCollat).times(INDEX_SCALE).div(divider))\n      .toString()\n    return _result\n  }\n\n  const result = fzero(fzeroFunction, [ETH_LOWER_BOUND, ETH_UPPER_BOUND], { maxiter: 50 })\n\n  return new BigNumber(result.solution)\n}\n\ntype UnivariateFunction = (x: number) => number\n/**\n * We need to find a zero for implied volatilty function and fzero is unreliable\n * so using bisection algorithm https://en.wikipedia.org/wiki/Bisection_method\n * */\nexport const bisection = (fn: UnivariateFunction, a: number, b: number, tolerance: number, maxIterations: number) => {\n  let i = 0\n\n  while (i < maxIterations) {\n    const c = (a + b) / 2\n    const f_c = fn(c)\n\n    if (f_c === 0 || b - a < tolerance) {\n      return c\n    }\n\n    i++\n\n    if (fn(a) * f_c > 0) {\n      a = c\n    } else {\n      b = c\n    }\n  }\n\n  return 0 // Did not converge within maxIterations\n}\n\n/**\n * Squeeth price in shutdown\n * See development here https://colab.research.google.com/drive/1gNpmXwmYPsWHwaI_pjuq3L5biq7NJVCx#scrollTo=qtjMrP_F_91z\n * */\nexport const getSqueethPriceShutdown = (\n  ethPrice: BigNumber,\n  normFactor: BigNumber,\n  daysToShutdown: number,\n  ethVol: number,\n) => {\n  const expiringQuadraticToday = ethPrice.times(Math.exp((ethVol * ethVol * daysToShutdown) / 365))\n  const expiringQuadraticTomorrow = ethPrice.times(Math.exp((ethVol * ethVol * (daysToShutdown - 1)) / 365))\n  // alpha is a value that makes the shutdown squeeth have the same return as expiring squeeth over one day.\n  const alpha = expiringQuadraticToday\n    .minus(expiringQuadraticTomorrow)\n    .div(\n      expiringQuadraticToday\n        .minus(expiringQuadraticTomorrow)\n        .plus(expiringQuadraticToday.minus(ethPrice).div(FUNDING_PERIOD)),\n    )\n  return normFactor.times(ethPrice.plus(alpha.times(expiringQuadraticToday.minus(ethPrice))).div(INDEX_SCALE))\n}\n\n/**\n * Squeeth implied volatility in shutdown using bisection to find the zero\n * */\nexport const getSqueethImpliedVolatilityShutdown = (\n  ethPrice: BigNumber,\n  normFactor: BigNumber,\n  daysToShutdown: number,\n  price: number,\n) => {\n  const fn = (vol: number) => {\n    return Number(getSqueethPriceShutdown(ethPrice, normFactor, daysToShutdown, vol)) - price\n  }\n  // params to find implied vol between 1% and 200% within 100 iterations\n  const volLower = 0.01\n  const volUpper = 2\n  const tolerance = 1e-6\n  const maxIterations = 100\n  // find implied volatility to match the price\n  const root = bisection(fn, volLower, volUpper, tolerance, maxIterations)\n  return root\n}\n\n/**\n * Days until shutdown\n * */\nexport const getDaysToShutdown = () => {\n  const now = new Date()\n  const shutdownDate = new Date(SHUTDOWN_DATE)\n  const millisecondsPerDay = 1000 * 60 * 60 * 24\n  return (shutdownDate.getTime() - now.getTime()) / millisecondsPerDay\n}\n\nexport async function getVault(vaultId: number, contract: Contract | null): Promise<Vault | null> {\n  if (!contract) return null\n  const vault = await contract.methods.vaults(vaultId).call()\n  const { NftCollateralId, collateralAmount, shortAmount, operator } = vault\n\n  return {\n    id: vaultId,\n    NFTCollateralId: NftCollateralId,\n    collateralAmount: toTokenAmount(new BigNumber(collateralAmount), 18),\n    shortAmount: toTokenAmount(new BigNumber(shortAmount), OSQUEETH_DECIMALS),\n    operator,\n  }\n}\n\nexport async function getIndex(period: number, contract: Contract | null) {\n  if (!contract) return BIG_ZERO\n\n  const indexPrice = await contract.methods.getIndex(period.toString()).call()\n  return new BigNumber(indexPrice).times(INDEX_SCALE).times(INDEX_SCALE)\n}\n\nexport async function getMark(period: number, contract: Contract | null) {\n  if (!contract) return BIG_ZERO\n  const markPrice = await contract.methods.getDenormalizedMark(period.toString()).call()\n  return new BigNumber(markPrice).times(INDEX_SCALE).times(INDEX_SCALE)\n}\n\nexport async function getNormFactor(contract: Contract | null) {\n  if (!contract) return BIG_ZERO\n  const normFactor = await contract.methods.normalizationFactor().call()\n  return new BigNumber(normFactor).dividedBy(BIG_ONE)\n}\n\n// Tries to get funding for the longest period available based on Uniswap storage slots, optimistically 24hrs, worst case spot\n// TODO: get 24hr historical funding from the subgraph to have a value that isn't dynamic based on storage slots\nexport async function getDailyHistoricalFunding(contract: Contract | null) {\n  if (!contract) return { period: 0, funding: 0 }\n  let index = BIG_ZERO\n  let mark = BIG_ZERO\n  let period = 24\n  let isError = false\n  //start by trying 24hr twap, if fails try dividing by 2 until 45min minimum, fall back to spot otherwise\n  for (; period >= 0.75; period = period / 2) {\n    try {\n      //convert period from hours to seconds\n      index = await getIndex(period * 3600, contract)\n      mark = await getMark(period * 3600, contract)\n      isError = false\n    } catch (error) {\n      isError = true\n    }\n    if (isError === false) {\n      break\n    }\n  }\n  if (index.isEqualTo(0) || mark.isEqualTo(0)) {\n    index = await getIndex(1, contract)\n    mark = await getMark(1, contract)\n  }\n\n  if (index.isEqualTo(0)) {\n    return { period: 0, funding: 0 }\n  }\n\n  console.log('period ' + period, floatifyBigNums({ mark, index }))\n\n  const funding = Math.log(mark.dividedBy(index).toNumber()) / FUNDING_PERIOD\n\n  return { period: period, funding: funding }\n}\n\nexport async function getCurrentImpliedFunding(contract: Contract | null) {\n  if (!contract) return 0\n  const currIndex = await getIndex(1, contract)\n  const currMark = await getMark(1, contract)\n  if (currIndex.isEqualTo(0)) {\n    return 0\n  }\n\n  return Math.log(currMark.dividedBy(currIndex).toNumber()) / FUNDING_PERIOD\n}\n\n/**\n * Implied funding before shutdown is perp funding + expected Mark/Index decay\n * */\nexport async function getCurrentImpliedFundingShutdown(contract: Contract | null) {\n  if (!contract) return 0\n  const currIndex = await getIndex(1, contract)\n  const currMark = await getMark(1, contract)\n  if (currIndex.isEqualTo(0)) {\n    return 0\n  }\n  // First part of funding is normal funding calc\n  const currentFunding = Math.log(currMark.dividedBy(currIndex).toNumber()) / FUNDING_PERIOD\n\n  // // Second part of funding is Mark/Index decay\n  const ethPrice = currIndex.dividedBy(BIG_ONE).sqrt()\n  const normFactor = await getNormFactor(contract)\n  const osqthPrice = Number(currMark.dividedBy(ethPrice).times(normFactor).dividedBy(BIG_ONE.times(INDEX_SCALE)))\n  const ethVol = getSqueethImpliedVolatilityShutdown(ethPrice, normFactor, getDaysToShutdown(), osqthPrice)\n\n  const markIndexDecay =\n    1 -\n    Number(getSqueethPriceShutdown(ethPrice, normFactor, getDaysToShutdown() - 1, ethVol)) /\n      Number(getSqueethPriceShutdown(ethPrice, normFactor, getDaysToShutdown(), ethVol))\n\n  return currentFunding + markIndexDecay\n}\n\n/**\n * Implied funding before shutdown is perp funding + expected Mark/Index decay\n * */\nexport async function getImpliedVolatilityShutdown(contract: Contract | null) {\n  if (!contract) return 0\n  const currIndex = await getIndex(1, contract)\n  const currMark = await getMark(1, contract)\n  if (currIndex.isEqualTo(0)) {\n    return 0\n  }\n  // First part of funding is normal funding calc\n\n  // // Second part of funding is Mark/Index decay\n  const ethPrice = currIndex.dividedBy(BIG_ONE).sqrt()\n  const normFactor = await getNormFactor(contract)\n  const osqthPrice = Number(currMark.dividedBy(ethPrice).times(normFactor).dividedBy(BIG_ONE.times(INDEX_SCALE)))\n  const ethVol = getSqueethImpliedVolatilityShutdown(ethPrice, normFactor, getDaysToShutdown(), osqthPrice)\n\n  return ethVol\n}\n\n// Tries to get funding for the longest period available based on Uniswap storage slots, optimistically 24hrs, worst case spot\n// TODO: get 24hr historical funding from the subgraph to have a value that isn't dynamic based on storage slots\nexport async function getDailyHistoricalFundingShutdown(contract: Contract | null) {\n  if (!contract) return { period: 0, funding: 0 }\n  let historicalIndex = BIG_ZERO\n  let historicalMark = BIG_ZERO\n  let period = 24\n  let isError = false\n  //start by trying 24hr twap, if fails try dividing by 2 until 45min minimum, fall back to spot otherwise\n  for (; period >= 0.75; period = period / 2) {\n    try {\n      //convert period from hours to seconds\n      historicalIndex = await getIndex(period * 3600, contract)\n      historicalMark = await getMark(period * 3600, contract)\n      isError = false\n    } catch (error) {\n      isError = true\n    }\n    if (isError === false) {\n      break\n    }\n  }\n  if (historicalIndex.isEqualTo(0) || historicalMark.isEqualTo(0)) {\n    historicalIndex = await getIndex(1, contract)\n    historicalMark = await getMark(1, contract)\n  }\n\n  if (historicalIndex.isEqualTo(0)) {\n    return { period: 0, funding: 0 }\n  }\n\n  // First part of funding is normal funding calc\n  const historicalFunding = Math.log(historicalMark.dividedBy(historicalIndex).toNumber()) / FUNDING_PERIOD\n\n  // // Second part of funding is Mark/Index decay\n  const ethPrice = historicalIndex.dividedBy(BIG_ONE).sqrt()\n\n  const normFactor = await getNormFactor(contract)\n  const osqthPrice = Number(historicalMark.dividedBy(ethPrice).times(normFactor).dividedBy(BIG_ONE.times(INDEX_SCALE)))\n\n  const ethVol = getSqueethImpliedVolatilityShutdown(ethPrice, normFactor, getDaysToShutdown(), osqthPrice)\n\n  const markIndexDecay =\n    1 -\n    Number(getSqueethPriceShutdown(ethPrice, normFactor, getDaysToShutdown() - 1, ethVol)) /\n      Number(getSqueethPriceShutdown(ethPrice, normFactor, getDaysToShutdown(), ethVol))\n\n  return { period: period, funding: historicalFunding + markIndexDecay }\n}\n\nexport async function getOsqthRefVol() {\n  try {\n    const response = await fetch(`/api/currentsqueethvol`)\n\n    // Check if the fetch request itself was successful\n    if (!response.ok) {\n      throw new Error(`HTTP error! status: ${response.status}`)\n    }\n\n    const data = await response.json()\n\n    // Check for API-level error response\n    if (data.status === 'error') {\n      throw new Error(data.message || 'Error fetching squeeth vol')\n    }\n\n    return data * 100\n  } catch (error) {\n    console.error('Error fetching squeeth vol:', error)\n    return 0\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/state/crab/atoms.ts",
    "content": "import { atom, useAtomValue } from 'jotai'\n\nimport { BIG_ZERO, DEFAULT_SLIPPAGE } from '@constants/index'\nimport { Vault } from '../../types'\nimport { readyAtom } from '../squeethPool/atoms'\nimport { CRABV2_START_DATE } from '@constants/index'\nimport { getCrabPnlV2ChartData } from '@utils/pricer'\nimport { useQuery } from 'react-query'\nimport { toTokenAmount } from '@utils/calculations'\n\nexport const maxCapAtom = atom(BIG_ZERO)\nexport const crabStrategyVaultAtom = atom<Vault | null>(null)\nexport const crabStrategyCollatRatioAtom = atom(0)\nexport const crabStrategyLiquidationPriceAtom = atom(BIG_ZERO)\nexport const timeAtLastHedgeAtom = atom(0)\nexport const loadingAtom = atom(true)\nexport const visibleStrategyHedgesAtom = atom<number>(3)\n\nexport const maxCapAtomV2 = atom(BIG_ZERO)\nexport const crabStrategyVaultAtomV2 = atom<Vault | null>(null)\nexport const crabStrategyCollatRatioAtomV2 = atom(0)\nexport const crabStrategyLiquidationPriceAtomV2 = atom(BIG_ZERO)\nexport const timeAtLastHedgeAtomV2 = atom(0)\nexport const loadingAtomV2 = atom(true)\nexport const ethPriceAtLastHedgeAtomV2 = atom(BIG_ZERO)\n\n// export const currentEthValueAtom = atom(BIG_ZERO)\nexport const currentEthLoadingAtom = atom(true)\nexport const currentCrabPositionValueAtom = atom(BIG_ZERO)\nexport const currentCrabPositionValueInETHAtom = atom(BIG_ZERO)\nexport const profitableMovePercentAtom = atom(0)\nexport const crabStrategySlippageAtom = atom(DEFAULT_SLIPPAGE)\nexport const isTimeHedgeAvailableAtom = atom(false)\nexport const isPriceHedgeAvailableAtom = atom(false)\nexport const crabPositionValueLoadingAtom = atom(true)\nexport const userCrabShares = atom(BIG_ZERO)\n\nexport const currentEthLoadingAtomV2 = atom(true)\nexport const currentCrabPositionValueAtomV2 = atom(BIG_ZERO)\nexport const currentCrabPositionValueInETHAtomV2 = atom(BIG_ZERO)\nexport const currentCrabPositionETHActualAtomV2 = atom(BIG_ZERO)\nexport const profitableMovePercentAtomV2 = atom(0)\nexport const crabStrategySlippageAtomV2 = atom(DEFAULT_SLIPPAGE)\nexport const isTimeHedgeAvailableAtomV2 = atom(false)\nexport const isPriceHedgeAvailableAtomV2 = atom(false)\nexport const crabPositionValueLoadingAtomV2 = atom(true)\nexport const userCrabSharesV2 = atom(BIG_ZERO)\nexport const crabTotalSupplyV2Atom = atom(BIG_ZERO)\n\nexport const usdcQueuedAtom = atom(BIG_ZERO)\nexport const crabQueuedAtom = atom(BIG_ZERO)\nexport const crabQueuedInEthAtom = atom(BIG_ZERO)\nexport const crabQueuedInUsdAtom = atom(BIG_ZERO)\nexport const crabUSDValueAtom = atom(BIG_ZERO)\n\nexport const totalUsdcQueuedAtom = atom(BIG_ZERO)\nexport const totalCrabQueuedAtom = atom(BIG_ZERO)\nexport const totalCrabQueueInUsddAtom = atom((get) => {\n  const crabQueued = get(totalCrabQueuedAtom)\n  const crabUSDValue = get(crabUSDValueAtom)\n  return crabQueued.multipliedBy(toTokenAmount(crabUSDValue, 18))\n})\n\nexport const isNettingAuctionLiveAtom = atom(false)\nexport const minUSDCAmountAtom = atom(BIG_ZERO)\nexport const minCrabAmountAtom = atom(BIG_ZERO)\n\nexport const crabLoadingAtom = atom((get) => {\n  const loading = get(loadingAtom)\n  const ready = get(readyAtom)\n  const currentEthLoading = get(currentEthLoadingAtom)\n  return loading || !ready || currentEthLoading\n})\n\nexport const crabLoadingAtomV2 = atom((get) => {\n  const loading = get(loadingAtomV2)\n  const ready = get(readyAtom)\n  const currentEthLoading = get(currentEthLoadingAtomV2)\n  return loading || !ready || currentEthLoading\n})\n\nexport const crabv2StrategyFilterStartDateAtom = atom<Date>(new Date(CRABV2_START_DATE))\nexport const crabv2StrategyFilterEndDateAtom = atom<Date>(new Date())\n\nexport const useCrabPnLV2ChartData = () => {\n  const startDate = useAtomValue(crabv2StrategyFilterStartDateAtom)\n  const endDate = useAtomValue(crabv2StrategyFilterEndDateAtom)\n\n  return useQuery(\n    ['pnlChart', { startDate, endDate }],\n    async () =>\n      getCrabPnlV2ChartData(\n        Number(startDate.valueOf().toString().slice(0, -3)),\n        Number(endDate.valueOf().toString().slice(0, -3)),\n      ),\n    {\n      staleTime: Infinity,\n      refetchOnWindowFocus: true,\n    },\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/state/crab/hooks.ts",
    "content": "import { useAtom, useAtomValue, useSetAtom } from 'jotai'\nimport { useUpdateAtom } from 'jotai/utils'\nimport { useCallback, useEffect } from 'react'\nimport Web3 from 'web3'\nimport { Contract } from 'web3-eth-contract'\n\nimport {\n  maxCapAtom,\n  crabStrategyVaultAtom,\n  crabStrategyCollatRatioAtom,\n  crabStrategyLiquidationPriceAtom,\n  crabStrategyLiquidationPriceAtomV2,\n  timeAtLastHedgeAtom,\n  loadingAtom,\n  profitableMovePercentAtom,\n  profitableMovePercentAtomV2,\n  isTimeHedgeAvailableAtom,\n  isPriceHedgeAvailableAtom,\n  currentEthLoadingAtom,\n  currentCrabPositionValueAtom,\n  currentCrabPositionValueInETHAtom,\n  crabPositionValueLoadingAtom,\n  crabStrategyVaultAtomV2,\n  maxCapAtomV2,\n  crabStrategyCollatRatioAtomV2,\n  loadingAtomV2,\n  isPriceHedgeAvailableAtomV2,\n  isTimeHedgeAvailableAtomV2,\n  timeAtLastHedgeAtomV2,\n  crabPositionValueLoadingAtomV2,\n  currentCrabPositionValueAtomV2,\n  currentCrabPositionValueInETHAtomV2,\n  currentEthLoadingAtomV2,\n  currentCrabPositionETHActualAtomV2,\n  ethPriceAtLastHedgeAtomV2,\n  usdcQueuedAtom,\n  crabQueuedAtom,\n  crabUSDValueAtom,\n  isNettingAuctionLiveAtom,\n  crabQueuedInEthAtom,\n  crabQueuedInUsdAtom,\n  minUSDCAmountAtom,\n  minCrabAmountAtom,\n  crabTotalSupplyV2Atom,\n  totalUsdcQueuedAtom,\n  totalCrabQueuedAtom,\n} from './atoms'\nimport { addressesAtom } from '../positions/atoms'\nimport {\n  getMaxCap,\n  getStrategyVaultId,\n  getTimeAtLastHedge,\n  checkTimeHedge,\n  checkPriceHedge,\n  checkPriceHedgeV2,\n  getCollateralFromCrabAmount,\n  getWsqueethFromCrabAmount,\n  getCurrentProfitableMovePercent,\n  getCurrentProfitableMovePercentV2,\n  getTotalCrabSupply,\n} from './utils'\nimport { useGetCollatRatioAndLiqPrice, useGetVault } from '../controller/hooks'\nimport db from '@utils/firestore'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport BigNumber from 'bignumber.js'\nimport { useGetBuyQuote, useGetSellQuote, useGetWSqueethPositionValueInETH } from '../squeethPool/hooks'\nimport { fromTokenAmount, getUSDCPoolFee, toTokenAmount } from '@utils/calculations'\nimport { useHandleTransaction } from '../wallet/hooks'\nimport { addressAtom, networkIdAtom, web3Atom } from '../wallet/atoms'\nimport { currentImpliedFundingAtom, impliedVolAtom, indexAtom, normFactorAtom } from '../controller/atoms'\nimport {\n  crabHelperContractAtom,\n  crabMigrationContractAtom,\n  crabNettingContractAtom,\n  crabStrategyContractAtom,\n  crabStrategyContractAtomV2,\n} from '../contracts/atoms'\nimport useAppCallback from '@hooks/useAppCallback'\nimport {\n  BIG_ONE,\n  BIG_ZERO,\n  REVERTED_TRANSACTION_CODE,\n  UNI_POOL_FEES,\n  USDC_DECIMALS,\n  WETH_DECIMALS,\n} from '@constants/index'\nimport useAppEffect from '@hooks/useAppEffect'\nimport { useETHPrice, useOnChainETHPrice } from '@hooks/useETHPrice'\nimport { userMigratedSharesAtom, userMigratedSharesETHAtom } from '../crabMigration/atom'\nimport useAppMemo from '@hooks/useAppMemo'\nimport * as Fathom from 'fathom-client'\nimport { Networks } from '../../types/index'\nimport { useUniswapQuoter } from '@hooks/useUniswapQuoter'\nimport { getEthPriceAtHedge } from '@utils/pricer'\nimport { squeethInitialPriceAtom } from '../squeethPool/atoms'\nimport { CRAB_EVENTS } from '@utils/amplitude'\nimport useAmplitude from '@hooks/useAmplitude'\nimport usePopup, { GenericErrorPopupConfig } from '@hooks/usePopup'\n\nexport const useSetStrategyData = () => {\n  const setMaxCap = useUpdateAtom(maxCapAtom)\n  const setVault = useUpdateAtom(crabStrategyVaultAtom)\n  const setCollatRatio = useUpdateAtom(crabStrategyCollatRatioAtom)\n  const setLiquidationPrice = useUpdateAtom(crabStrategyLiquidationPriceAtom)\n  const setLoading = useUpdateAtom(loadingAtom)\n  const setIsPriceHedgeAvailable = useUpdateAtom(isPriceHedgeAvailableAtom)\n  const setIsTimeHedgeAvailable = useUpdateAtom(isTimeHedgeAvailableAtom)\n  const setTimeAtLastHedge = useUpdateAtom(timeAtLastHedgeAtom)\n  const contract = useAtomValue(crabStrategyContractAtom)\n  const getVault = useGetVault()\n  const getCollatRatioAndLiqPrice = useGetCollatRatioAndLiqPrice()\n\n  const setStrategyData = useCallback(async () => {\n    if (!contract) return\n\n    getMaxCap(contract).then(setMaxCap)\n    getStrategyVaultId(contract)\n      .then(getVault)\n      .then((v) => {\n        setVault(v)\n        if (v) {\n          getCollatRatioAndLiqPrice(v.collateralAmount, v.shortAmount)\n            .then((cl) => {\n              setCollatRatio(cl.collateralPercent)\n              setLiquidationPrice(cl.liquidationPrice)\n              setLoading(false)\n            })\n            .catch((e) => {\n              setLoading(false)\n            })\n        }\n      })\n    getTimeAtLastHedge(contract).then(setTimeAtLastHedge)\n    checkTimeHedge(contract).then((h) => setIsTimeHedgeAvailable(h[0]))\n    if (process.env.NEXT_PUBLIC_FIREBASE_API_KEY) {\n      // Check price hedge only if firebase is available\n      const doc = await db.doc('squeeth-monitoring/crab').get()\n      checkPriceHedge(doc?.data()?.lastAuctionTrigger || 0, contract).then(setIsPriceHedgeAvailable)\n    }\n  }, [contract, getCollatRatioAndLiqPrice, getVault])\n\n  return setStrategyData\n}\n\nexport const useSetStrategyDataV2 = () => {\n  const setMaxCap = useUpdateAtom(maxCapAtomV2)\n  const setVault = useUpdateAtom(crabStrategyVaultAtomV2)\n  const setCollatRatio = useUpdateAtom(crabStrategyCollatRatioAtomV2)\n  const setLiquidationPrice = useUpdateAtom(crabStrategyLiquidationPriceAtomV2)\n  const setLoading = useUpdateAtom(loadingAtomV2)\n  const setIsPriceHedgeAvailable = useUpdateAtom(isPriceHedgeAvailableAtomV2)\n  const setIsTimeHedgeAvailable = useUpdateAtom(isTimeHedgeAvailableAtomV2)\n  const setTimeAtLastHedge = useUpdateAtom(timeAtLastHedgeAtomV2)\n  const contract = useAtomValue(crabStrategyContractAtomV2)\n  const getVault = useGetVault()\n  const getCollatRatioAndLiqPrice = useGetCollatRatioAndLiqPrice()\n  const networkId = useAtomValue(networkIdAtom)\n  const setEthPriceAtLastHedge = useUpdateAtom(ethPriceAtLastHedgeAtomV2)\n  const normFactor = useAtomValue(normFactorAtom)\n  const setCrabTotalSupply = useUpdateAtom(crabTotalSupplyV2Atom)\n\n  const setStrategyData = useCallback(async () => {\n    if (!contract || !normFactor) return\n\n    getMaxCap(contract).then(setMaxCap)\n    getStrategyVaultId(contract)\n      .then(getVault)\n      .then((v) => {\n        setVault(v)\n        if (v) {\n          getCollatRatioAndLiqPrice(v.collateralAmount, v.shortAmount)\n            .then((cl) => {\n              setCollatRatio(cl.collateralPercent)\n              setLiquidationPrice(cl.liquidationPrice)\n              setLoading(false)\n            })\n            .catch((e) => {\n              setLoading(false)\n            })\n        }\n      })\n    getTimeAtLastHedge(contract).then(setTimeAtLastHedge)\n    getTotalCrabSupply(contract).then(setCrabTotalSupply)\n    if (networkId !== Networks.ROPSTEN) {\n      checkTimeHedge(contract).then((h) => {\n        setIsTimeHedgeAvailable(h)\n      })\n      if (process.env.NEXT_PUBLIC_FIREBASE_API_KEY) {\n        // Check price hedge only if firebase is available\n        checkPriceHedgeV2(contract).then(setIsPriceHedgeAvailable)\n      }\n      // get eth price at hedge\n      getEthPriceAtHedge().then(setEthPriceAtLastHedge)\n    }\n  }, [contract, getCollatRatioAndLiqPrice, getVault, networkId])\n\n  return setStrategyData\n}\n\nexport const useCalculateEthWillingToPay = () => {\n  const vault = useAtomValue(crabStrategyVaultAtom)\n\n  const contract = useAtomValue(crabStrategyContractAtom)\n  const getBuyQuote = useGetBuyQuote()\n  const calculateEthWillingToPay = useCallback(\n    async (amount: BigNumber, slippage: number) => {\n      const emptyState = {\n        amountIn: new BigNumber(0),\n        maximumAmountIn: new BigNumber(0),\n        priceImpact: '0',\n      }\n      if (!vault) return emptyState\n\n      const squeethDebt = await getWsqueethFromCrabAmount(amount, contract)\n      console.log('Debt', squeethDebt?.toString(), amount.toString())\n      if (!squeethDebt) return emptyState\n\n      const ethWillingToPayQuote = await getBuyQuote(squeethDebt, new BigNumber(slippage))\n      return ethWillingToPayQuote\n    },\n    [contract, getBuyQuote, vault?.id],\n  )\n\n  return calculateEthWillingToPay\n}\n\nexport const useCalculateEthWillingToPayV2 = () => {\n  const vault = useAtomValue(crabStrategyVaultAtomV2)\n\n  const contract = useAtomValue(crabStrategyContractAtomV2)\n  const getBuyQuote = useGetBuyQuote()\n  const getWSqueethPositionValueInETH = useGetWSqueethPositionValueInETH()\n\n  const calculateEthWillingToPay = useCallback(\n    async (amount: BigNumber, slippage: number) => {\n      const emptyState = {\n        amountIn: new BigNumber(0),\n        maximumAmountIn: new BigNumber(0),\n        priceImpact: '0',\n        squeethDebt: new BigNumber(0),\n        ethToGet: new BigNumber(0),\n        poolFee: '0',\n      }\n      if (!vault) return emptyState\n\n      const squeethDebt = await getWsqueethFromCrabAmount(amount, contract)\n      const collat = await getCollateralFromCrabAmount(amount, contract, vault)\n      console.log('Debt', squeethDebt?.toString(), amount.toString())\n      if (!squeethDebt) return emptyState\n\n      const ethWillingToPayQuote = await getBuyQuote(squeethDebt, new BigNumber(slippage))\n      return {\n        ...ethWillingToPayQuote,\n        squeethDebt,\n        ethToGet: collat?.minus(ethWillingToPayQuote.maximumAmountIn) || BIG_ZERO,\n      }\n    },\n    [contract, getBuyQuote, vault?.id],\n  )\n\n  return calculateEthWillingToPay\n}\n\nexport const getEthToReceiveFromCrabAmount = async (crabAmount: BigNumber, contract: Contract | null, web3: Web3) => {\n  if (!contract) return null\n\n  const totalSupply = toTokenAmount(await contract.methods.totalSupply().call(), 18)\n  const contractBalance = toTokenAmount(await web3.eth.getBalance(contract.options.address), 18)\n\n  return contractBalance.times(crabAmount).div(totalSupply)\n}\n\nexport const useCalculateEthToReceiveShutdown = (version: 'v1' | 'v2' = 'v2') => {\n  const contractV1 = useAtomValue(crabStrategyContractAtom)\n  const contractV2 = useAtomValue(crabStrategyContractAtomV2)\n  const web3 = useAtomValue(web3Atom)\n\n  const contract = version === 'v1' ? contractV1 : contractV2\n\n  const calculateEthToReceive = useCallback(\n    async (crabAmount: BigNumber) => {\n      if (!contract || !web3) {\n        return new BigNumber(0)\n      }\n\n      const ethToReceive = await getEthToReceiveFromCrabAmount(crabAmount, contract, web3)\n      return ethToReceive\n    },\n    [contract, web3],\n  )\n\n  return calculateEthToReceive\n}\n\nexport const useClaimV2Shares = () => {\n  const contract = useAtomValue(crabMigrationContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n\n  const claimV2Shares = useCallback(\n    async (onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      return await handleTransaction(\n        contract.methods.claimV2Shares().send({\n          from: address,\n        }),\n        onTxConfirmed,\n      )\n    },\n    [contract, address, handleTransaction],\n  )\n\n  return claimV2Shares\n}\n\nexport const useWithdrawShutdown = (version: 'v1' | 'v2' = 'v2') => {\n  const contractV1 = useAtomValue(crabStrategyContractAtom)\n  const contractV2 = useAtomValue(crabStrategyContractAtomV2)\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n\n  const contract = version === 'v1' ? contractV1 : contractV2\n\n  const withdrawShutdown = useCallback(\n    async (crabAmount: BigNumber, onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      return await handleTransaction(\n        contract.methods.withdrawShutdown(fromTokenAmount(crabAmount, 18).toFixed(0)).send({\n          from: address,\n        }),\n        onTxConfirmed,\n      )\n    },\n    [contract, address, handleTransaction],\n  )\n\n  return withdrawShutdown\n}\n\nexport const useCurrentCrabPositionValue = () => {\n  const { crabStrategy } = useAtomValue(addressesAtom)\n\n  const [isCrabPositionValueLoading, setIsCrabPositionValueLoading] = useAtom(crabPositionValueLoadingAtom)\n  const [currentCrabPositionValue, setCurrentCrabPositionValue] = useAtom(currentCrabPositionValueAtom)\n  const [currentCrabPositionValueInETH, setCurrentCrabPositionValueInETH] = useAtom(currentCrabPositionValueInETHAtom)\n  const { value: userCrabBalance } = useTokenBalance(crabStrategy, 15, 18)\n  const contract = useAtomValue(crabStrategyContractAtom)\n  const setCurrentEthLoading = useUpdateAtom(currentEthLoadingAtom)\n  const vault = useAtomValue(crabStrategyVaultAtom)\n  const ethPrice = useETHPrice()\n  const setStrategyData = useSetStrategyData()\n  const getWSqueethPositionValueInETH = useGetWSqueethPositionValueInETH()\n\n  useEffect(() => {\n    setStrategyData()\n  }, [])\n\n  const userShares = useAppMemo(() => {\n    return userCrabBalance\n  }, [userCrabBalance])\n\n  useAppEffect(() => {\n    ;(async () => {\n      setIsCrabPositionValueLoading(true)\n      const [collateral, squeethDebt] = await Promise.all([\n        getCollateralFromCrabAmount(userShares, contract, vault),\n        getWsqueethFromCrabAmount(userShares, contract),\n      ])\n\n      if (!squeethDebt || !collateral) {\n        setCurrentCrabPositionValue(BIG_ZERO)\n        setCurrentCrabPositionValueInETH(BIG_ZERO)\n        return\n      }\n\n      const ethDebt = getWSqueethPositionValueInETH(squeethDebt)\n\n      const crabPositionValueInETH = collateral.minus(ethDebt)\n      const crabPositionValueInUSD = crabPositionValueInETH.times(ethPrice)\n\n      setCurrentCrabPositionValue(crabPositionValueInUSD)\n      setCurrentCrabPositionValueInETH(crabPositionValueInETH)\n\n      setIsCrabPositionValueLoading(false)\n      setCurrentEthLoading(false)\n    })()\n  }, [\n    userShares,\n    contract,\n    setCurrentEthLoading,\n    setIsCrabPositionValueLoading,\n    getWSqueethPositionValueInETH,\n    ethPrice,\n    vault,\n  ])\n\n  return { currentCrabPositionValue, currentCrabPositionValueInETH, isCrabPositionValueLoading }\n}\n\nexport const useCurrentCrabPositionValueV2 = () => {\n  const { crabStrategy2 } = useAtomValue(addressesAtom)\n\n  const [isCrabPositionValueLoading, setIsCrabPositionValueLoading] = useAtom(crabPositionValueLoadingAtomV2)\n  const [currentCrabPositionValue, setCurrentCrabPositionValue] = useAtom(currentCrabPositionValueAtomV2)\n  const [currentCrabPositionValueInETH, setCurrentCrabPositionValueInETH] = useAtom(currentCrabPositionValueInETHAtomV2)\n  const {\n    value: userCrabBalance,\n    loading: balLoading,\n    refetch: refetchCrabTokenBalance,\n  } = useTokenBalance(crabStrategy2, 15, 18)\n  const userMigratedShares = useAtomValue(userMigratedSharesAtom)\n  const crabQueuedShares = useAtomValue(crabQueuedAtom)\n  const setUserMigratedSharesETH = useUpdateAtom(userMigratedSharesETHAtom)\n  const setCurrentCrabPositionETHActual = useUpdateAtom(currentCrabPositionETHActualAtomV2)\n  const setCrabQueuedInEth = useUpdateAtom(crabQueuedInEthAtom)\n  const setCrabQueuedInUsd = useUpdateAtom(crabQueuedInUsdAtom)\n  const contract = useAtomValue(crabStrategyContractAtomV2)\n  const setCurrentEthLoading = useUpdateAtom(currentEthLoadingAtomV2)\n  const vault = useAtomValue(crabStrategyVaultAtomV2)\n  const ethPrice = useOnChainETHPrice()\n  const setStrategyData = useSetStrategyData()\n  const getWSqueethPositionValueInETH = useGetWSqueethPositionValueInETH()\n  const normFactor = useAtomValue(normFactorAtom)\n  const squeethInitialPrice = useAtomValue(squeethInitialPriceAtom)\n  const setCrabUsdValue = useSetAtom(crabUSDValueAtom)\n  const fetchQueuedData = useQueuedCrabPositionAndStatus()\n\n  useEffect(() => {\n    setStrategyData()\n  }, [])\n\n  const userShares = useAppMemo(() => {\n    return userMigratedShares.plus(userCrabBalance)\n  }, [userMigratedShares, userCrabBalance])\n\n  useAppEffect(() => {\n    ;(async () => {\n      if (balLoading) {\n        setIsCrabPositionValueLoading(true)\n      }\n      fetchQueuedData()\n      const [collateral, squeethDebt, collateralOne, squeethDebtOne, collatMigrated, debtMigrated] = await Promise.all([\n        getCollateralFromCrabAmount(userShares, contract, vault),\n        getWsqueethFromCrabAmount(userShares, contract),\n        getCollateralFromCrabAmount(BIG_ONE, contract, vault),\n        getWsqueethFromCrabAmount(BIG_ONE, contract),\n        getCollateralFromCrabAmount(toTokenAmount(crabQueuedShares, 18), contract, vault),\n        getWsqueethFromCrabAmount(toTokenAmount(crabQueuedShares, 18), contract),\n      ])\n\n      if (\n        !squeethDebt ||\n        !collateral ||\n        !normFactor ||\n        ((collateral.isZero() || squeethDebt.isZero() || squeethInitialPrice.isZero()) && userShares.gt(0))\n      ) {\n        setCurrentCrabPositionValue(BIG_ZERO)\n        setCurrentCrabPositionValueInETH(BIG_ZERO)\n        setIsCrabPositionValueLoading(true)\n        return\n      }\n\n      const ethDebt = getWSqueethPositionValueInETH(squeethDebt)\n      if (collateralOne && squeethDebtOne) {\n        const ethDebtOne = getWSqueethPositionValueInETH(squeethDebtOne)\n        setCrabUsdValue(collateralOne.minus(ethDebtOne).times(ethPrice))\n      }\n\n      // Or else vault would have been liquidated\n      if (collateral.lt(ethDebt)) return\n\n      const crabPositionValueInETH = collateral.minus(ethDebt)\n      const crabPositionValueInUSD = crabPositionValueInETH.times(ethPrice)\n\n      if (debtMigrated && collatMigrated && !collatMigrated?.isZero() && !debtMigrated?.isZero()) {\n        const ethDebtOne = getWSqueethPositionValueInETH(debtMigrated)\n        setCrabQueuedInEth(collatMigrated.minus(ethDebtOne))\n        setCrabQueuedInUsd(collatMigrated.minus(ethDebtOne).times(ethPrice))\n      }\n\n      setCurrentCrabPositionValue(crabPositionValueInUSD)\n      setCurrentCrabPositionValueInETH(crabPositionValueInETH)\n      setUserMigratedSharesETH(\n        userShares.isZero() ? BIG_ZERO : crabPositionValueInETH.div(userShares).times(userMigratedShares),\n      )\n      setCurrentCrabPositionETHActual(\n        userShares.isZero() ? BIG_ZERO : crabPositionValueInETH.div(userShares).times(userCrabBalance),\n      )\n\n      setIsCrabPositionValueLoading(false)\n      setCurrentEthLoading(false)\n    })()\n  }, [\n    userShares,\n    contract,\n    setCurrentEthLoading,\n    setIsCrabPositionValueLoading,\n    getWSqueethPositionValueInETH,\n    setCurrentCrabPositionValue,\n    setCurrentCrabPositionValueInETH,\n    setUserMigratedSharesETH,\n    ethPrice,\n    vault,\n    balLoading,\n    squeethInitialPrice,\n    setCrabUsdValue,\n    crabQueuedShares,\n  ])\n\n  return {\n    currentCrabPositionValue,\n    currentCrabPositionValueInETH,\n    isCrabPositionValueLoading: balLoading || isCrabPositionValueLoading,\n    refetchCrabTokenBalance,\n  }\n}\n\nexport const useCalculateETHtoBorrowFromUniswap = () => {\n  const vault = useAtomValue(crabStrategyVaultAtom)\n  const getSellQuote = useGetSellQuote()\n\n  const calculateETHtoBorrowFromUniswap = useCallback(\n    async (ethDeposit: BigNumber, slippage: number) => {\n      const emptyState = {\n        amountOut: new BigNumber(0),\n        minimumAmountOut: new BigNumber(0),\n        priceImpact: '0',\n        ethBorrow: new BigNumber(0),\n      }\n      if (!vault || ethDeposit.eq(0)) return emptyState\n\n      let start = new BigNumber(0.25)\n      let end = new BigNumber(3)\n      const deviation = new BigNumber(0.0001) // .01 %\n\n      let prevState = emptyState\n      while (start.lte(end)) {\n        const middle = start.plus(end).div(2)\n        const ethBorrow = ethDeposit.times(middle)\n        const initialWSqueethDebt = ethBorrow.plus(ethDeposit).times(vault.shortAmount).div(vault.collateralAmount)\n        const quote = await getSellQuote(initialWSqueethDebt, new BigNumber(slippage))\n        const borrowRatio = quote.minimumAmountOut.div(ethBorrow).minus(1)\n        if (prevState.minimumAmountOut.eq(quote.minimumAmountOut)) {\n          break\n        }\n        prevState = { ...quote, ethBorrow }\n        if (borrowRatio.gt(0) && borrowRatio.lte(deviation)) {\n          break\n        } else {\n          // If ratio matches check in first half or search in second half\n          if (borrowRatio.gt(0)) {\n            start = middle\n          } else {\n            end = middle\n          }\n        }\n      }\n\n      console.log(\n        'Eth to borrow: ',\n        prevState.ethBorrow.toString(),\n        prevState.minimumAmountOut.toString(),\n        start.toString(),\n        end.toString(),\n      )\n      return prevState\n    },\n    [vault?.id, getSellQuote],\n  )\n\n  return calculateETHtoBorrowFromUniswap\n}\n\nexport const useCalculateETHtoBorrowFromUniswapV2 = () => {\n  const vault = useAtomValue(crabStrategyVaultAtomV2)\n  const getSellQuote = useGetSellQuote()\n\n  const calculateETHtoBorrowFromUniswap = useCallback(\n    async (ethDeposit: BigNumber, slippage: number) => {\n      const emptyState: any = {\n        amountOut: new BigNumber(0),\n        minimumAmountOut: new BigNumber(0),\n        priceImpact: '0',\n        poolFee: '0',\n        ethBorrow: new BigNumber(0),\n        initialWSqueethDebt: new BigNumber(0),\n      }\n      if (!vault || ethDeposit.eq(0)) return emptyState\n\n      let start = new BigNumber(0.25)\n      let end = new BigNumber(3)\n      const deviation = new BigNumber(0.0001) // .01 %\n\n      let prevState = emptyState\n      while (start.lte(end)) {\n        const middle = start.plus(end).div(2)\n        const ethBorrow = ethDeposit.times(middle)\n        const initialWSqueethDebt = ethBorrow.plus(ethDeposit).times(vault.shortAmount).div(vault.collateralAmount)\n        const quote = await getSellQuote(initialWSqueethDebt, new BigNumber(slippage))\n        const borrowRatio = quote.minimumAmountOut.div(ethBorrow).minus(1)\n        if (prevState.minimumAmountOut.eq(quote.minimumAmountOut)) {\n          break\n        }\n        prevState = { ...quote, ethBorrow, initialWSqueethDebt }\n        if (borrowRatio.gt(0) && borrowRatio.lte(deviation)) {\n          break\n        } else {\n          // If ratio matches check in first half or search in second half\n          if (borrowRatio.gt(0)) {\n            start = middle\n          } else {\n            end = middle\n          }\n        }\n      }\n\n      console.log(\n        'Eth to borrow: ',\n        prevState.ethBorrow.toString(),\n        prevState.minimumAmountOut.toString(),\n        start.toString(),\n        end.toString(),\n      )\n      return prevState\n    },\n    [vault?.id, getSellQuote],\n  )\n\n  return calculateETHtoBorrowFromUniswap\n}\n\nexport const useFlashDeposit = (calculateETHtoBorrowFromUniswap: any) => {\n  const maxCap = useAtomValue(maxCapAtom)\n  const address = useAtomValue(addressAtom)\n  const vault = useAtomValue(crabStrategyVaultAtom)\n  const contract = useAtomValue(crabStrategyContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const flashDeposit = useAppCallback(\n    async (amount: BigNumber, slippage: number, onTxConfirmed?: () => void) => {\n      if (!contract || !vault) return\n\n      let { ethBorrow: _ethBorrow } = await calculateETHtoBorrowFromUniswap(amount, slippage)\n      const _allowedEthToBorrow = maxCap.minus(amount.plus(vault.collateralAmount))\n      if (_ethBorrow.gt(_allowedEthToBorrow)) {\n        _ethBorrow = _allowedEthToBorrow\n      }\n      const ethBorrow = fromTokenAmount(_ethBorrow, 18)\n      const ethDeposit = fromTokenAmount(amount, 18)\n      return await handleTransaction(\n        contract.methods.flashDeposit(ethBorrow.plus(ethDeposit).toFixed(0)).send({\n          from: address,\n          value: fromTokenAmount(amount, 18).toFixed(0),\n        }),\n        onTxConfirmed,\n      )\n    },\n    [address, contract, handleTransaction, vault?.id, maxCap, calculateETHtoBorrowFromUniswap],\n  )\n\n  return flashDeposit\n}\n\nexport const useFlashDepositV2 = (calculateETHtoBorrowFromUniswap: any) => {\n  const maxCap = useAtomValue(maxCapAtomV2)\n  const address = useAtomValue(addressAtom)\n  const vault = useAtomValue(crabStrategyVaultAtomV2)\n  const contract = useAtomValue(crabStrategyContractAtomV2)\n  const handleTransaction = useHandleTransaction()\n  const { track } = useAmplitude()\n\n  const flashDeposit = useAppCallback(\n    async (amount: BigNumber, slippage: number, onTxConfirmed?: () => void) => {\n      if (!contract || !vault) return\n\n      let { ethBorrow: _ethBorrow } = await calculateETHtoBorrowFromUniswap(amount, slippage)\n      // Just to make sure the issue never happens\n      if (_ethBorrow.isZero()) {\n        Fathom.trackGoal('HOUQK7NR', 0)\n        alert('Some error occurred. Refresh the page!')\n        throw new Error('Some error occurred. Refresh the page!')\n      }\n      const _allowedEthToBorrow = maxCap.minus(amount.plus(vault.collateralAmount))\n      if (_ethBorrow.gt(_allowedEthToBorrow)) {\n        _ethBorrow = _allowedEthToBorrow\n      }\n\n      // TODO: fix it so it uses v2 ratio, not v1.\n      const ethBorrow = fromTokenAmount(_ethBorrow, 18)\n      const ethDeposit = fromTokenAmount(amount, 18)\n      const poolFeePercent = 3000\n      track(CRAB_EVENTS.DEPOSIT_CRAB_CLICK, { amount: amount.plus(_ethBorrow).toString() })\n      try {\n        const tx = await handleTransaction(\n          contract.methods.flashDeposit(ethBorrow.plus(ethDeposit).toFixed(0), poolFeePercent).send({\n            from: address,\n            value: fromTokenAmount(amount, 18).toFixed(0),\n          }),\n          onTxConfirmed,\n        )\n\n        track(CRAB_EVENTS.DEPOSIT_CRAB_SUCCESS, { amount: amount.plus(_ethBorrow).toNumber() })\n        return tx\n      } catch (e: any) {\n        e?.code === REVERTED_TRANSACTION_CODE ? track(CRAB_EVENTS.DEPOSIT_CRAB_REVERT) : null\n        track(CRAB_EVENTS.DEPOSIT_CRAB_FAILED, { code: e?.code })\n        throw e\n      }\n    },\n    [address, contract, handleTransaction, vault?.id, maxCap, calculateETHtoBorrowFromUniswap],\n  )\n\n  return flashDeposit\n}\n\nexport const useFlashDepositUSDC = (calculateETHtoBorrowFromUniswap: any) => {\n  const maxCap = useAtomValue(maxCapAtomV2)\n  const address = useAtomValue(addressAtom)\n  const { usdc, weth, crabStrategy2 } = useAtomValue(addressesAtom)\n  const network = useAtomValue(networkIdAtom)\n  const vault = useAtomValue(crabStrategyVaultAtomV2)\n  const contract = useAtomValue(crabHelperContractAtom)\n  const { getExactIn } = useUniswapQuoter()\n  const handleTransaction = useHandleTransaction()\n  const { track } = useAmplitude()\n  const { show: showErrorFeedbackPopup, showPopup } = usePopup(\n    GenericErrorPopupConfig('Hi, I am having trouble depositing into crab.', 'deposit-crab'),\n  )\n  const usdcFee = getUSDCPoolFee(network)\n\n  const flashDepositUSDC = useAppCallback(\n    async (amount: BigNumber, slippage: number, onTxConfirmed?: () => void) => {\n      if (!contract || !vault) return\n\n      const usdcAmount = fromTokenAmount(amount, USDC_DECIMALS)\n      const quote = await getExactIn(usdc, weth, usdcAmount, usdcFee, slippage)\n      const ethAmount = new BigNumber(quote.minAmountOut)\n      let { ethBorrow: _ethBorrow } = await calculateETHtoBorrowFromUniswap(toTokenAmount(ethAmount, 18), slippage)\n      // Just to make sure the issue never happens\n      if (_ethBorrow.isZero()) {\n        Fathom.trackGoal('HOUQK7NR', 0)\n        alert('Some error occurred. Refresh the page!')\n        throw new Error('Some error occurred. Refresh the page!')\n      }\n      const _allowedEthToBorrow = maxCap.minus(toTokenAmount(ethAmount, 18).plus(vault.collateralAmount))\n      if (_ethBorrow.gt(_allowedEthToBorrow)) {\n        _ethBorrow = _allowedEthToBorrow\n      }\n\n      // TODO: fix it so it uses v2 ratio, not v1.\n      const ethBorrow = fromTokenAmount(_ethBorrow, 18)\n      const ethDeposit = ethAmount\n      track(CRAB_EVENTS.DEPOSIT_CRAB_USDC_CLICK, { amount: amount.toString() })\n      let gasEstimate\n      try {\n        try {\n          gasEstimate = await contract.methods\n            .flashDepositERC20(\n              ethBorrow.plus(ethDeposit).toFixed(0),\n              usdcAmount.toFixed(0),\n              ethDeposit.toFixed(0),\n              usdcFee,\n              UNI_POOL_FEES,\n              usdc,\n            )\n            .estimateGas({\n              to: crabStrategy2,\n              from: address,\n            })\n          if (gasEstimate === 0) throw new Error('WRONG_GAS_ESTIMATE')\n        } catch (e) {\n          track(CRAB_EVENTS.DEPOSIT_CRAB_WRONG_GAS, { gas: gasEstimate })\n          alert('Error occurred, please refresh and try again')\n          throw e\n        }\n\n        const tx = await handleTransaction(\n          contract.methods\n            .flashDepositERC20(\n              ethBorrow.plus(ethDeposit).toFixed(0),\n              usdcAmount.toFixed(0),\n              ethDeposit.toFixed(0),\n              usdcFee,\n              UNI_POOL_FEES,\n              usdc,\n            )\n            .send({\n              from: address,\n            }),\n          onTxConfirmed,\n        )\n\n        track(CRAB_EVENTS.DEPOSIT_CRAB_USDC_SUCCESS, { amount: amount.toNumber() })\n        return tx\n      } catch (e: any) {\n        e?.code === REVERTED_TRANSACTION_CODE ? track(CRAB_EVENTS.DEPOSIT_CRAB_USDC_REVERT) : null\n        e?.code !== REVERTED_TRANSACTION_CODE ? showErrorFeedbackPopup() : null\n        track(CRAB_EVENTS.DEPOSIT_CRAB_USDC_FAILED, { code: e?.code })\n        console.log(e)\n      }\n    },\n    [address, contract, handleTransaction, vault?.id, maxCap, calculateETHtoBorrowFromUniswap],\n  )\n\n  return flashDepositUSDC\n}\n\nexport const useQueueDepositUSDC = () => {\n  const contract = useAtomValue(crabNettingContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const { track } = useAmplitude()\n  const { show: showErrorFeedbackPopup } = usePopup(\n    GenericErrorPopupConfig('Hi, I am having trouble depositing into crab.', 'deposit-stn-crab'),\n  )\n\n  const depositUSDC = useAppCallback(\n    async (amount: BigNumber, onTxConfirmed?: () => void) => {\n      if (!contract) return\n      track(CRAB_EVENTS.DEPOSIT_STN_CRAB_USDC_CLICK)\n      try {\n        console.log('Queue:', fromTokenAmount(amount, USDC_DECIMALS).toString())\n        await handleTransaction(\n          contract.methods.depositUSDC(fromTokenAmount(amount, USDC_DECIMALS).toString()).send({\n            from: address,\n          }),\n          onTxConfirmed,\n        )\n        track(CRAB_EVENTS.DEPOSIT_STN_CRAB_USDC_SUCCESS, { amount: amount.toNumber() })\n      } catch (e: any) {\n        e?.code === REVERTED_TRANSACTION_CODE ? track(CRAB_EVENTS.DEPOSIT_STN_CRAB_USDC_REVERT) : null\n        e?.code !== REVERTED_TRANSACTION_CODE ? showErrorFeedbackPopup() : null\n        track(CRAB_EVENTS.DEPOSIT_STN_CRAB_USDC_FAILED, { code: e?.code })\n        console.log(e)\n      }\n    },\n    [contract, address, handleTransaction],\n  )\n\n  return depositUSDC\n}\n\nexport const useQueueWithdrawCrab = () => {\n  const contract = useAtomValue(crabNettingContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const { track } = useAmplitude()\n  const { show: showErrorFeedbackPopup } = usePopup(\n    GenericErrorPopupConfig('Hi, I am having trouble withdrawing from crab.', 'withdraw-stn-crab'),\n  )\n\n  const queueWithdraw = useAppCallback(\n    async (amount: BigNumber, onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      track(CRAB_EVENTS.WITHDRAW_STN_CRAB_USDC_CLICK)\n      console.log('Queue: withdraw', fromTokenAmount(amount, WETH_DECIMALS).toString())\n      try {\n        await handleTransaction(\n          contract.methods.queueCrabForWithdrawal(fromTokenAmount(amount, WETH_DECIMALS).toFixed(0)).send({\n            from: address,\n          }),\n          onTxConfirmed,\n        )\n        track(CRAB_EVENTS.WITHDRAW_STN_CRAB_USDC_SUCCESS, { amount: amount.toNumber() })\n      } catch (e: any) {\n        e?.code === REVERTED_TRANSACTION_CODE ? track(CRAB_EVENTS.WITHDRAW_STN_CRAB_USDC_REVERT) : null\n        e?.code !== REVERTED_TRANSACTION_CODE ? showErrorFeedbackPopup() : null\n        track(CRAB_EVENTS.WITHDRAW_STN_CRAB_USDC_FAILED, { code: e?.code })\n        console.log(e)\n      }\n    },\n    [contract, address, handleTransaction],\n  )\n\n  return queueWithdraw\n}\n\nexport const useFlashWithdraw = () => {\n  const contract = useAtomValue(crabStrategyContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const calculateEthWillingToPay = useCalculateEthWillingToPay()\n\n  const flashWithdraw = useCallback(\n    async (amount: BigNumber, slippage: number, onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      const { maximumAmountIn: _ethWillingToPay } = await calculateEthWillingToPay(amount, slippage)\n      const ethWillingToPay = fromTokenAmount(_ethWillingToPay, 18)\n      const crabAmount = fromTokenAmount(amount, 18)\n      return await handleTransaction(\n        contract.methods.flashWithdraw(crabAmount.toFixed(0), ethWillingToPay.toFixed(0)).send({\n          from: address,\n        }),\n        onTxConfirmed,\n      )\n    },\n    [contract, address, handleTransaction, calculateEthWillingToPay],\n  )\n\n  return flashWithdraw\n}\n\nexport const useFlashWithdrawV2 = () => {\n  const contract = useAtomValue(crabStrategyContractAtomV2)\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const { crabStrategy2 } = useAtomValue(addressesAtom)\n  const calculateEthWillingToPay = useCalculateEthWillingToPayV2()\n  const { track } = useAmplitude()\n  const { show: showErrorFeedbackPopup } = usePopup(\n    GenericErrorPopupConfig('Hi, I am having trouble withdrawing from crab.', 'withdraw-crab'),\n  )\n\n  const flashWithdraw = useCallback(\n    async (amount: BigNumber, slippage: number, onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      const { maximumAmountIn: _ethWillingToPay } = await calculateEthWillingToPay(amount, slippage)\n      console.log(_ethWillingToPay.toString())\n      const ethWillingToPay = fromTokenAmount(_ethWillingToPay, 18)\n      const crabAmount = fromTokenAmount(amount, 18)\n      const poolFeePercent = 3000\n      track(CRAB_EVENTS.WITHDRAW_CRAB_CLICK)\n      let gasEstimate\n      try {\n        try {\n          gasEstimate = await contract.methods\n            .flashWithdraw(crabAmount.toFixed(0), ethWillingToPay.toFixed(0), poolFeePercent.toFixed(0))\n            .estimateGas({\n              to: crabStrategy2,\n              from: address,\n            })\n          if (gasEstimate === 0) throw new Error('WRONG_GAS_ESTIMATE')\n        } catch (e) {\n          track(CRAB_EVENTS.WITHDRAW_CRAB_WRONG_GAS, { gas: gasEstimate })\n          alert('Error occurred, please refresh and try again')\n          throw e\n        }\n\n        const tx = await handleTransaction(\n          contract.methods\n            .flashWithdraw(crabAmount.toFixed(0), ethWillingToPay.toFixed(0), poolFeePercent.toFixed(0))\n            .send({\n              from: address,\n            }),\n          onTxConfirmed,\n        )\n        track(CRAB_EVENTS.WITHDRAW_CRAB_SUCCESS, { amount: amount.toNumber() })\n        return tx\n      } catch (e: any) {\n        e?.code === REVERTED_TRANSACTION_CODE ? track(CRAB_EVENTS.WITHDRAW_CRAB_REVERT) : null\n        e?.code !== REVERTED_TRANSACTION_CODE ? showErrorFeedbackPopup() : null\n        track(CRAB_EVENTS.WITHDRAW_CRAB_FAILED, { code: e?.code })\n        throw e\n      }\n    },\n    [contract, address, handleTransaction, calculateEthWillingToPay],\n  )\n\n  return flashWithdraw\n}\n\nexport const useFlashWithdrawV2USDC = () => {\n  const contract = useAtomValue(crabHelperContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const calculateEthWillingToPay = useCalculateEthWillingToPayV2()\n  const { getExactIn } = useUniswapQuoter()\n  const { track } = useAmplitude()\n  const { usdc, weth, crabStrategy2 } = useAtomValue(addressesAtom)\n  const { show: showErrorFeedbackPopup } = usePopup(\n    GenericErrorPopupConfig('Hi, I am having trouble withdrawing from crab.', 'withdraw-crab-usdc'),\n  )\n  const network = useAtomValue(networkIdAtom)\n\n  const usdcFee = getUSDCPoolFee(network)\n\n  const flashWithdrawUSDC = useCallback(\n    async (amount: BigNumber, slippage: number, onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      const { maximumAmountIn: _ethWillingToPay, ethToGet } = await calculateEthWillingToPay(amount, slippage)\n      console.log(_ethWillingToPay.toString())\n      const ethWillingToPay = fromTokenAmount(_ethWillingToPay, 18)\n      const crabAmount = fromTokenAmount(amount, 18)\n      const { minAmountOut } = await getExactIn(weth, usdc, fromTokenAmount(ethToGet, 18), usdcFee, slippage)\n      console.log('Min amount out USDC', minAmountOut.toString())\n      const poolFeePercent = 3000\n\n      track(CRAB_EVENTS.WITHDRAW_CRAB_USDC_CLICK, { amount: amount.toNumber() })\n      let gasEstimate\n      try {\n        try {\n          gasEstimate = await contract.methods\n            .flashWithdrawERC20(\n              crabAmount.toFixed(0),\n              ethWillingToPay.toFixed(0),\n              usdc,\n              minAmountOut,\n              usdcFee,\n              poolFeePercent,\n            )\n            .estimateGas({\n              to: crabStrategy2,\n              from: address,\n            })\n          if (gasEstimate === 0) throw new Error('WRONG_GAS_ESTIMATE')\n        } catch (e) {\n          track(CRAB_EVENTS.WITHDRAW_CRAB_WRONG_GAS, { gas: gasEstimate })\n          alert('Error occurred, please refresh and try again')\n          throw e\n        }\n\n        await handleTransaction(\n          contract.methods\n            .flashWithdrawERC20(\n              crabAmount.toFixed(0),\n              ethWillingToPay.toFixed(0),\n              usdc,\n              minAmountOut,\n              usdcFee,\n              poolFeePercent,\n            )\n            .send({\n              from: address,\n            }),\n          onTxConfirmed,\n        )\n        track(CRAB_EVENTS.WITHDRAW_CRAB_USDC_SUCCESS, { amount: amount.toNumber() })\n      } catch (e: any) {\n        e?.code === REVERTED_TRANSACTION_CODE\n          ? track(CRAB_EVENTS.WITHDRAW_CRAB_USDC_REVERT, { amount: amount.toNumber() })\n          : null\n        e?.code !== REVERTED_TRANSACTION_CODE ? showErrorFeedbackPopup() : null\n        track(CRAB_EVENTS.WITHDRAW_CRAB_USDC_FAILED, { code: e?.code, message: e?.message, amount: amount.toNumber() })\n      }\n    },\n    [contract, address, handleTransaction, calculateEthWillingToPay],\n  )\n\n  return flashWithdrawUSDC\n}\n\nexport const useClaimWithdrawV2 = () => {\n  const contract = useAtomValue(crabMigrationContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const calculateEthWillingToPay = useCalculateEthWillingToPayV2()\n\n  const claimAndWithdraw = useCallback(\n    async (amount: BigNumber, slippage: number, onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      const { maximumAmountIn: _ethWillingToPay } = await calculateEthWillingToPay(amount, slippage)\n      const ethWillingToPay = fromTokenAmount(_ethWillingToPay, 18)\n      const crabAmount = fromTokenAmount(amount, 18)\n      const poolFeePercent = 3000\n      return await handleTransaction(\n        contract.methods\n          .claimAndWithdraw(crabAmount.toFixed(0), ethWillingToPay.toFixed(0), poolFeePercent.toFixed(0))\n          .send({\n            from: address,\n          }),\n        onTxConfirmed,\n      )\n    },\n    [contract, address, handleTransaction, calculateEthWillingToPay],\n  )\n\n  return claimAndWithdraw\n}\n\nexport const useFlashWithdrawEth = () => {\n  const { crabStrategy } = useAtomValue(addressesAtom)\n  const currentEthValue = useAtomValue(currentCrabPositionValueInETHAtom)\n  const { value: userCrabBalance } = useTokenBalance(crabStrategy, 5, 18)\n  const contract = useAtomValue(crabStrategyContractAtom)\n  const flashWithdraw = useFlashWithdraw()\n\n  const flashWithdrawEth = useCallback(\n    async (ethAmount: BigNumber, slippage: number, onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      const equivalentCrab = ethAmount.div(currentEthValue).times(userCrabBalance)\n      console.log(currentEthValue?.toString(), userCrabBalance?.toString(), ethAmount.toString())\n      return await flashWithdraw(equivalentCrab, slippage, onTxConfirmed)\n    },\n    [contract, currentEthValue?.toString(), flashWithdraw, userCrabBalance?.toString()],\n  )\n\n  return flashWithdrawEth\n}\n\nexport const useFlashWithdrawEthV2 = () => {\n  const { crabStrategy2 } = useAtomValue(addressesAtom)\n  const currentEthValue = useAtomValue(currentCrabPositionETHActualAtomV2)\n  const { value: userCrabBalance } = useTokenBalance(crabStrategy2, 5, 18)\n  const contract = useAtomValue(crabStrategyContractAtomV2)\n  const flashWithdraw = useFlashWithdrawV2()\n\n  const flashWithdrawEth = useCallback(\n    async (ethAmount: BigNumber, slippage: number, onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      const equivalentCrab = ethAmount.div(currentEthValue).times(userCrabBalance)\n      console.log(currentEthValue?.toString(), userCrabBalance?.toString(), ethAmount.toString())\n      return await flashWithdraw(equivalentCrab, slippage, onTxConfirmed)\n    },\n    [contract, currentEthValue?.toString(), flashWithdraw, userCrabBalance?.toString()],\n  )\n\n  return flashWithdrawEth\n}\n\nexport const useETHtoCrab = () => {\n  const { crabStrategy2 } = useAtomValue(addressesAtom)\n  const crabMigrationValueInEth = useAtomValue(userMigratedSharesETHAtom)\n  const currentCrabPositionValueInEth = useAtomValue(currentCrabPositionETHActualAtomV2)\n  const { value: userCrabBalance } = useTokenBalance(crabStrategy2, 5, 18)\n  const userMigratedShares = useAtomValue(userMigratedSharesAtom)\n\n  const userShares = useAppMemo(() => {\n    return userMigratedShares.plus(userCrabBalance)\n  }, [userMigratedShares, userCrabBalance])\n\n  const crabValueInEth = useAppMemo(() => {\n    return crabMigrationValueInEth.plus(currentCrabPositionValueInEth)\n  }, [])\n\n  const getUserCrabForEthAmount = useAppCallback(\n    (ethAmount: BigNumber) => {\n      if (crabValueInEth.isZero()) {\n        return BIG_ZERO\n      }\n      return ethAmount.div(crabValueInEth).times(userShares)\n    },\n    [crabValueInEth, userShares],\n  )\n\n  return getUserCrabForEthAmount\n}\n\nexport const useClaimAndWithdrawEthV2 = () => {\n  const currentEthValue = useAtomValue(userMigratedSharesETHAtom)\n  const userCrabBalance = useAtomValue(userMigratedSharesAtom)\n  const contract = useAtomValue(crabMigrationContractAtom)\n  const claimAndWithdraw = useClaimWithdrawV2()\n\n  const claimAndWithdrawEth = useCallback(\n    async (ethAmount: BigNumber, slippage: number, onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      const equivalentCrab = ethAmount.div(currentEthValue).times(userCrabBalance)\n      return await claimAndWithdraw(equivalentCrab, slippage, onTxConfirmed)\n    },\n    [contract, currentEthValue?.toString(), claimAndWithdraw, userCrabBalance?.toString()],\n  )\n\n  return claimAndWithdrawEth\n}\n\nexport const useSetStrategyCap = () => {\n  const contract = useAtomValue(crabStrategyContractAtom)\n  const address = useAtomValue(addressAtom)\n  const setStrategyCap = useCallback(\n    async (amount: BigNumber) => {\n      if (!contract) return\n\n      const crabAmount = fromTokenAmount(amount, 18)\n      return contract.methods.setStrategyCap(crabAmount.toFixed(0)).send({\n        from: address,\n      })\n    },\n    [contract, address],\n  )\n\n  return setStrategyCap\n}\n\nexport const useSetProfitableMovePercent = () => {\n  const [profitableMovePercent, setProfitableMovePercent] = useAtom(profitableMovePercentAtom)\n  const currentImpliedFunding = useAtomValue(currentImpliedFundingAtom)\n  const contract = useAtomValue(crabStrategyContractAtom)\n\n  useEffect(() => {\n    if (!contract) return\n    setProfitableMovePercent(getCurrentProfitableMovePercent(currentImpliedFunding))\n  }, [contract, currentImpliedFunding])\n\n  return profitableMovePercent\n}\n\nexport const useSetProfitableMovePercentV2 = () => {\n  const [profitableMovePercentV2, setProfitableMovePercentV2] = useAtom(profitableMovePercentAtomV2)\n  const currentImpliedFunding = useAtomValue(currentImpliedFundingAtom)\n  const currentImpliedVol = useAtomValue(impliedVolAtom)\n  const contract = useAtomValue(crabStrategyContractAtom)\n\n  useEffect(() => {\n    if (!contract) return\n    setProfitableMovePercentV2(getCurrentProfitableMovePercentV2(currentImpliedVol))\n  }, [contract, currentImpliedVol])\n\n  return profitableMovePercentV2\n}\n\nexport const useQueuedCrabPositionAndStatus = () => {\n  const contract = useAtomValue(crabNettingContractAtom)\n  const address = useAtomValue(addressAtom)\n  const setUsdcQueued = useSetAtom(usdcQueuedAtom)\n  const setCrabQueued = useSetAtom(crabQueuedAtom)\n  const setNettingAuctionLive = useSetAtom(isNettingAuctionLiveAtom)\n  const setMinUSDCAmount = useSetAtom(minUSDCAmountAtom)\n  const setMinCrabAmount = useSetAtom(minCrabAmountAtom)\n  const setTotalDeposits = useSetAtom(totalUsdcQueuedAtom)\n  const setTotalWithdrawals = useSetAtom(totalCrabQueuedAtom)\n\n  const fetchAndStoreQueuedPosition = async () => {\n    if (!contract) return\n\n    const minUSDCAmountPromise = contract.methods.minUSDCAmount().call()\n    const minCrabAmountPromise = contract.methods.minCrabAmount().call()\n    const totalDepositsPromise = contract.methods.depositsQueued().call()\n    const totalWithdrawalsPromise = contract.methods.withdrawsQueued().call()\n\n    const [minUSDCAmount, minCrabAmount, totalDeposits, totalWithdrawals] = await Promise.all([\n      minUSDCAmountPromise,\n      minCrabAmountPromise,\n      totalDepositsPromise,\n      totalWithdrawalsPromise,\n    ])\n\n    setTotalDeposits(toTokenAmount(totalDeposits, USDC_DECIMALS))\n    setTotalWithdrawals(toTokenAmount(totalWithdrawals, WETH_DECIMALS))\n    setMinUSDCAmount(new BigNumber(minUSDCAmount))\n    setMinCrabAmount(new BigNumber(minCrabAmount))\n\n    if (!contract || !address) return\n\n    const usdcPromise = contract.methods.usdBalance(address).call()\n    const crabPromise = contract.methods.crabBalance(address).call()\n    const auctionStatusPromise = contract.methods.isAuctionLive().call()\n\n    const [usdcQueued, crabQueued, auctionStatus] = await Promise.all([usdcPromise, crabPromise, auctionStatusPromise])\n    setUsdcQueued(new BigNumber(usdcQueued))\n    setCrabQueued(new BigNumber(crabQueued))\n    setNettingAuctionLive(auctionStatus)\n  }\n\n  return fetchAndStoreQueuedPosition\n}\n\nexport const useDeQueueDepositUSDC = () => {\n  const contract = useAtomValue(crabNettingContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const { track } = useAmplitude()\n\n  const deQueueUSDC = useAppCallback(\n    async (amount: BigNumber, onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      try {\n        track(CRAB_EVENTS.CANCEL_DEPOSIT_STN_CRAB_USDC_CLICK)\n        await handleTransaction(\n          contract.methods.withdrawUSDC(amount.toString(), false).send({\n            from: address,\n          }),\n          onTxConfirmed,\n        )\n        track(CRAB_EVENTS.CANCEL_DEPOSIT_STN_CRAB_USDC_SUCCESS, { amount: amount.toNumber() })\n      } catch (e: any) {\n        e?.code === REVERTED_TRANSACTION_CODE ? track(CRAB_EVENTS.CANCEL_DEPOSIT_STN_CRAB_USDC_REJECT) : null\n        track(CRAB_EVENTS.CANCEL_DEPOSIT_STN_CRAB_USDC_FAILED, { code: e?.code })\n        console.log(e)\n      }\n    },\n    [contract, address, handleTransaction],\n  )\n\n  return deQueueUSDC\n}\n\nexport const useDeQueueWithdrawCrab = () => {\n  const contract = useAtomValue(crabNettingContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const address = useAtomValue(addressAtom)\n  const { track } = useAmplitude()\n\n  const queueWithdraw = useAppCallback(\n    async (amount: BigNumber, onTxConfirmed?: () => void) => {\n      if (!contract) return\n\n      try {\n        track(CRAB_EVENTS.CANCEL_WITHDRAW_STN_CRAB_USDC_CLICK)\n        await handleTransaction(\n          contract.methods.dequeueCrab(amount.toFixed(0), false).send({\n            from: address,\n          }),\n          onTxConfirmed,\n        )\n        track(CRAB_EVENTS.CANCEL_WITHDRAW_STN_CRAB_USDC_SUCCESS, { amount: amount.toNumber() })\n      } catch (e: any) {\n        e?.code === REVERTED_TRANSACTION_CODE ? track(CRAB_EVENTS.CANCEL_WITHDRAW_STN_CRAB_USDC_REJECT) : null\n        track(CRAB_EVENTS.CANCEL_WITHDRAW_STN_CRAB_USDC_FAILED, { code: e?.code })\n        console.log(e)\n      }\n    },\n    [contract, address, handleTransaction],\n  )\n\n  return queueWithdraw\n}\n"
  },
  {
    "path": "packages/frontend/src/state/crab/utils.ts",
    "content": "import { Contract } from 'web3-eth-contract'\nimport BigNumber from 'bignumber.js'\nimport { fromTokenAmount, toTokenAmount } from '@utils/calculations'\nimport { Vault } from '../../types'\nimport { YEAR } from '../../constants'\n\nexport const checkTimeHedge = async (contract: Contract | null) => {\n  if (!contract) return null\n\n  const result = await contract.methods.checkTimeHedge().call()\n  return result\n}\n\nexport const checkPriceHedge = async (auctionTriggerTime: number, contract: Contract | null) => {\n  if (!contract) return null\n\n  const result = await contract.methods.checkPriceHedge(auctionTriggerTime).call()\n  return result\n}\n\nexport const checkPriceHedgeV2 = async (contract: Contract | null) => {\n  if (!contract) return null\n\n  const result = await contract.methods.checkPriceHedge().call()\n  return result\n}\n\nexport const getCollateralFromCrabAmount = async (\n  crabAmount: BigNumber,\n  contract: Contract | null,\n  vault: Vault | null,\n) => {\n  if (!contract || !vault) return null\n\n  const totalSupply = toTokenAmount(await contract.methods.totalSupply().call(), 18)\n  return vault.collateralAmount.times(crabAmount).div(totalSupply)\n}\n\nexport const getTotalCrabSupply = async (contract: Contract) => {\n  return toTokenAmount(await contract.methods.totalSupply().call(), 18)\n}\n\nexport const getCurrentProfitableMovePercentV2 = (currentImpliedVol: number) => {\n  // Approximating a hedge every 2 days, take the vol divided by the sqrt of # of periods\n  // In this case 365 / 2 = 182.5\n  return currentImpliedVol / Math.sqrt(YEAR / 2)\n}\n\nexport const getCurrentProfitableMovePercent = (currentImpliedFunding: number) => {\n  return Math.sqrt(currentImpliedFunding)\n}\n\nexport const getMaxCap = async (contract: Contract | null) => {\n  if (!contract) return new BigNumber(0)\n\n  const cap = await contract.methods.strategyCap().call()\n  return toTokenAmount(cap, 18)\n}\n\nexport const getStrategyVaultId = async (contract: Contract | null) => {\n  if (!contract) return 0\n\n  const _vaultId = await contract.methods.getStrategyVaultId().call()\n  return Number(_vaultId.toString())\n}\n\nexport const getTimeAtLastHedge = async (contract: Contract | null) => {\n  if (!contract) return null\n\n  const result = await contract.methods.timeAtLastHedge().call()\n  return result\n}\n\nexport const getWsqueethFromCrabAmount = async (crabAmount: BigNumber, contract: Contract | null) => {\n  if (!contract || crabAmount.isNaN()) return null\n\n  const result = await contract.methods.getWsqueethFromCrabAmount(fromTokenAmount(crabAmount, 18).toFixed(0)).call()\n  return toTokenAmount(result.toString(), 18)\n}\n\nexport const setStrategyCap = async (amount: BigNumber, contract: Contract | null, address: string | null) => {\n  if (!contract) return\n\n  const crabAmount = fromTokenAmount(amount, 18)\n  return contract.methods.setStrategyCap(crabAmount.toFixed(0)).send({\n    from: address,\n  })\n}\n"
  },
  {
    "path": "packages/frontend/src/state/crabMigration/atom.ts",
    "content": "import { BIG_ZERO } from '../../constants'\nimport { atom } from 'jotai'\n\nexport const totalMigratedSharesAtom = atom(BIG_ZERO)\nexport const userMigratedSharesAtom = atom(BIG_ZERO)\nexport const userMigratedSharesETHAtom = atom(BIG_ZERO)\nexport const isQueuedAtom = atom((get) => {\n  const userQueuedShares = get(userMigratedSharesAtom)\n  return userQueuedShares.gt(0)\n})\n"
  },
  {
    "path": "packages/frontend/src/state/crabMigration/hooks.ts",
    "content": "import { makeItCrabRain } from '@components/Strategies/Crab/util'\nimport useAppCallback from '@hooks/useAppCallback'\nimport { fromTokenAmount, toTokenAmount } from '@utils/calculations'\nimport BigNumber from 'bignumber.js'\nimport { useAtomValue, useSetAtom } from 'jotai'\nimport { useCallback, useEffect } from 'react'\nimport { crabMigrationContractAtom } from '../contracts/atoms'\nimport { addressAtom } from '../wallet/atoms'\nimport { useHandleTransaction } from '../wallet/hooks'\nimport { totalMigratedSharesAtom, userMigratedSharesAtom } from './atom'\n\nexport const useInitCrabMigration = () => {\n  const updateMigrationData = useUpdateSharesData()\n\n  useEffect(() => {\n    updateMigrationData()\n  }, [updateMigrationData])\n}\n\nexport const useUpdateSharesData = () => {\n  const address = useAtomValue(addressAtom)\n  const crabMigrationContract = useAtomValue(crabMigrationContractAtom)\n  //const setTotalMigratedShares = useSetAtom(totalMigratedSharesAtom)\n  const setUserMigratedShares = useSetAtom(userMigratedSharesAtom)\n\n  const updateMigrationData = useCallback(async () => {\n    // const p1 = crabMigrationContract?.methods.totalCrabV1SharesMigrated().call()\n    if (address != null) {\n      const p2 = crabMigrationContract?.methods.sharesDeposited(address).call()\n\n      try {\n        const [_userShare] = await Promise.all([p2])\n\n        //setTotalMigratedShares(toTokenAmount(_totalShare, 18))\n        setUserMigratedShares(toTokenAmount(_userShare, 18))\n      } catch (e) {\n        console.log(\"error in getting user's migrated shares\", e)\n      }\n    }\n  }, [address, crabMigrationContract?.methods, setUserMigratedShares])\n\n  return updateMigrationData\n}\n\n/**\n * Calls depositV1Shares function in migration contract. CrabV1 should be approved to migration contract by the user\n * @param amount Amount of v1 shares to deposit\n * @returns function to migrate\n */\nexport const useQueueMigrate = () => {\n  const address = useAtomValue(addressAtom)\n  const crabMigrationContract = useAtomValue(crabMigrationContractAtom)\n  const handleTransaction = useHandleTransaction()\n  // const setTotalMigratedShares = useSetAtom(totalMigratedSharesAtom)\n  const setUserMigratedShares = useSetAtom(userMigratedSharesAtom)\n\n  const queueMigrate = useAppCallback(\n    async (amount: BigNumber | string) => {\n      const res = await handleTransaction(\n        crabMigrationContract?.methods.depositV1Shares(fromTokenAmount(amount, 18).toFixed(0)).send({\n          from: address,\n        }),\n        () => makeItCrabRain(),\n      )\n\n      // const p1 = crabMigrationContract?.methods.totalCrabV1SharesMigrated().call()\n      const p2 = crabMigrationContract?.methods.sharesDeposited(address).call()\n      const [_userShare] = await Promise.all([p2])\n      // setTotalMigratedShares(toTokenAmount(_totalShare, 18))\n      setUserMigratedShares(toTokenAmount(_userShare, 18))\n      makeItCrabRain()\n\n      return res\n    },\n    [address, crabMigrationContract?.methods, handleTransaction, setUserMigratedShares],\n  )\n\n  return queueMigrate\n}\n"
  },
  {
    "path": "packages/frontend/src/state/ethPriceCharts/atoms.ts",
    "content": "import { atom, useAtomValue } from 'jotai'\nimport { useQuery } from 'react-query'\n\nimport {\n  getCUSDCPrices,\n  getETH90DaysPrices,\n  getCoingeckoETHPrices as getETHPrices,\n  getETHWithinOneDayPrices,\n} from '@utils/ethPriceCharts'\nimport {\n  getETHPNLCompounding,\n  getSqueethChartWithFunding,\n  getSqueethPNLCompounding,\n  useETHSqueethPNLCompounding,\n  getLongChartData,\n} from '@utils/pricer'\nimport useAppMemo from '@hooks/useAppMemo'\nimport useAppCallback from '@hooks/useAppCallback'\nimport { useMemo } from 'react'\n\nconst FIVE_MINUTES_IN_MILLISECONDS = 300_000\nconst STRATEGIES_LAUNCH_TIME_STAMP = 1642636810000\n\nconst ethPriceChartsQueryKeys = {\n  ethPriceRange: (days: number) => ['ethPriceRange', { days }],\n  allEthPricesRange: (days: number) => ['allEthPricesRange', { days }],\n  allEth90daysPrices: () => ['allEth90daysPrices'],\n  allEthWithinOneDayPrices: () => ['allEthWithinOneDayPrices'],\n  cusdcPricesRange: (days: number) => ['cusdcPricesRange', { days }],\n  squeethSeries: (ethPrices: any, volMultiplier: number, collatRatio: number) => [\n    'squeethSeries',\n    { ethPrices, volMultiplier, collatRatio },\n  ],\n  squeethPNLSeries: (ethPrices: any, volMultiplier: number, collatRatio: number, days: number) => [\n    'squeethPNLSeries',\n    { ethPrices, volMultiplier, collatRatio, days },\n  ],\n  ethPNLCompounding: (ethPrices: any) => ['ethPNLCompounding', { ethPricesData: ethPrices }],\n}\n\nexport const daysAtom = atom(7)\nexport const longPayoffFilterStartDateAtom = atom<Date>(new Date(Date.now() - 7 * 24 * 60 * 60 * 1000))\nexport const longPayoffFilterEndDateAtom = atom<Date>(new Date())\nexport const collatRatioAtom = atom(1.5)\nexport const volMultiplierAtom = atom(1.2)\n\nexport const useEthPrices = () => {\n  const days = useAtomValue(daysAtom)\n\n  return useQuery(ethPriceChartsQueryKeys.ethPriceRange(days), () => getETHPrices(days), {\n    enabled: Boolean(days),\n    staleTime: FIVE_MINUTES_IN_MILLISECONDS,\n  })\n}\n\nexport const useAllEthPrices = () => {\n  const days = useAtomValue(daysAtom)\n\n  return useQuery(ethPriceChartsQueryKeys.allEthPricesRange(days), () => getETHPrices(days), {\n    enabled: Boolean(days),\n    staleTime: FIVE_MINUTES_IN_MILLISECONDS,\n  })\n}\n\nexport const useEthPricesSinceStrategiesLaunch = () => {\n  const startTimestampInMilli = STRATEGIES_LAUNCH_TIME_STAMP\n  const currentTime = new Date(Date.now())\n  const days = Math.floor((currentTime.getTime() - startTimestampInMilli) / (1000 * 3600 * 24))\n  return useQuery(ethPriceChartsQueryKeys.allEthPricesRange(days), () => getETHPrices(days), {\n    staleTime: FIVE_MINUTES_IN_MILLISECONDS,\n  })\n}\n\nexport const useAllEth90daysPrices = () => {\n  return useQuery(ethPriceChartsQueryKeys.allEth90daysPrices(), () => getETH90DaysPrices(), {\n    staleTime: FIVE_MINUTES_IN_MILLISECONDS,\n  })\n}\n\nexport const useAllEthWithinOneDayPrices = () => {\n  return useQuery(ethPriceChartsQueryKeys.allEthWithinOneDayPrices(), () => getETHWithinOneDayPrices(), {\n    staleTime: FIVE_MINUTES_IN_MILLISECONDS,\n  })\n}\n\nexport const useCusdcPrices = () => {\n  const days = useAtomValue(daysAtom)\n\n  return useQuery(ethPriceChartsQueryKeys.cusdcPricesRange(days), () => getCUSDCPrices(days), {\n    staleTime: FIVE_MINUTES_IN_MILLISECONDS,\n  })\n}\n\nexport const useEthPNLCompounding = () => {\n  const ethPrices = useEthPrices()\n\n  return useQuery(\n    ethPriceChartsQueryKeys.ethPNLCompounding(ethPrices.data),\n    () => getETHPNLCompounding(ethPrices.data ?? []),\n    {\n      enabled: Boolean(ethPrices.isSuccess && ethPrices.data),\n    },\n  )\n}\n\nexport const useSqueethSeries = () => {\n  const ethPrices = useEthPrices()\n  const volMultiplier = useAtomValue(volMultiplierAtom)\n  const collatRatio = useAtomValue(collatRatioAtom)\n\n  return useQuery(\n    ethPriceChartsQueryKeys.squeethSeries(ethPrices.data?.length, volMultiplier, collatRatio),\n    () => getSqueethChartWithFunding(ethPrices.data ?? [], volMultiplier, collatRatio),\n    { enabled: Boolean(ethPrices.isSuccess && ethPrices.data) },\n  )\n}\n\nexport const useAccFunding = () => {\n  const squeethSeries = useSqueethSeries()\n  return squeethSeries.data?.accFunding\n}\n\nexport const useSqueethPNLSeries = () => {\n  const ethPrices = useEthPrices()\n  const days = useAtomValue(daysAtom)\n  const volMultiplier = useAtomValue(volMultiplierAtom)\n  const collatRatio = useAtomValue(collatRatioAtom)\n\n  return useQuery(\n    ethPriceChartsQueryKeys.squeethPNLSeries(ethPrices?.data?.length, volMultiplier, collatRatio, days),\n    () => getSqueethPNLCompounding(ethPrices.data ?? [], volMultiplier, collatRatio, days),\n    { enabled: Boolean(ethPrices.isSuccess && ethPrices.data && days) },\n  )\n}\n\nexport const useLongSeries = () => {\n  const volMultiplier = useAtomValue(volMultiplierAtom)\n  const ethPrices = useEthPrices()\n  const days = useAtomValue(daysAtom)\n  const ethSqueethPNLSeries = useETHSqueethPNLCompounding(ethPrices.data ?? [], volMultiplier, days)\n\n  return useAppMemo(\n    () => {\n      return (\n        ethSqueethPNLSeries.squeethPNL &&\n        ethSqueethPNLSeries.squeethPNL.map(({ time, longPNL }) => {\n          return { time, value: longPNL }\n        })\n      )\n    },\n    [ethSqueethPNLSeries.squeethPNL],\n    true,\n  )\n}\n\nexport const useShortSeries = () => {\n  const volMultiplier = useAtomValue(volMultiplierAtom)\n  const ethPrices = useEthPrices()\n  const days = useAtomValue(daysAtom)\n  const ethSqueethPNLSeries = useETHSqueethPNLCompounding(ethPrices.data ?? [], volMultiplier, days)\n\n  return useAppMemo(\n    () => {\n      return (\n        ethSqueethPNLSeries.squeethPNL &&\n        ethSqueethPNLSeries.squeethPNL.map(({ time, shortPNL }) => {\n          return { time, value: shortPNL }\n        })\n      )\n    },\n    [ethSqueethPNLSeries.squeethPNL],\n    true,\n  )\n}\n\nexport const usePrevShortSeries = () => {\n  const squeethSeries = useSqueethSeries()\n\n  return useAppMemo(() => {\n    return squeethSeries.data?.series.map(({ time, shortPNL }) => {\n      return { time, value: shortPNL }\n    })\n  }, [squeethSeries.data?.series])\n}\n\nexport const usePositionSizePercentageseries = () => {\n  const squeethSeries = useSqueethSeries()\n\n  return (\n    squeethSeries.data &&\n    squeethSeries.data.series.map(({ time, positionSize }) => {\n      return { time, value: positionSize * 100 }\n    })\n  )\n}\n\nexport const useFundingPercentageSeries = () => {\n  const squeethSeries = useSqueethSeries()\n\n  return squeethSeries.data\n    ? squeethSeries.data.series.map(({ time, fundingPerSqueeth, mark, timeElapsed: timeElapsedInDay }) => {\n        const fundingPercentageDay = fundingPerSqueeth / mark / timeElapsedInDay\n        return { time, value: Number((fundingPercentageDay * 100).toFixed(4)) }\n      })\n    : []\n}\n\nexport const useLongEthPNL = () => {\n  const volMultiplier = useAtomValue(volMultiplierAtom)\n  const ethPrices = useEthPrices()\n  const days = useAtomValue(daysAtom)\n  const ethSqueethPNLSeries = useETHSqueethPNLCompounding(ethPrices.data ?? [], volMultiplier, days)\n\n  return useAppMemo(\n    () => {\n      return (\n        ethSqueethPNLSeries.ethPNL &&\n        ethSqueethPNLSeries.ethPNL.map(({ time, longPNL }) => {\n          return { time, value: longPNL }\n        })\n      )\n    },\n    [ethSqueethPNLSeries?.ethPNL],\n    true,\n  )\n}\n\nexport const useShortEthPNL = () => {\n  const volMultiplier = useAtomValue(volMultiplierAtom)\n  const ethPrices = useEthPrices()\n  const days = useAtomValue(daysAtom)\n  const ethSqueethPNLSeries = useETHSqueethPNLCompounding(ethPrices.data ?? [], volMultiplier, days)\n\n  return useAppMemo(\n    () => {\n      return (\n        ethSqueethPNLSeries.ethPNL &&\n        ethSqueethPNLSeries.ethPNL.map(({ time, shortPNL }) => {\n          return { time, value: shortPNL }\n        })\n      )\n    },\n    [ethSqueethPNLSeries.ethPNL],\n    true,\n  )\n}\n\nexport const useStartingETHPrice = () => {\n  const ethPrices = useEthPrices()\n  return ethPrices.data && ethPrices.data.length > 0 ? ethPrices.data[0].value : 1\n}\n\nexport const useSqueethPrices = () => {\n  const ethPrices = useEthPrices()\n  const startingETHPrice = useStartingETHPrice()\n\n  return ethPrices.data\n    ? ethPrices.data.map(({ time, value }) => {\n        return { time, value: value ** 2 / startingETHPrice }\n      })\n    : []\n}\n\nexport const useEthPriceMap = () => {\n  const allEthPrices = useAllEthPrices()\n\n  return useMemo(\n    () =>\n      allEthPrices.data &&\n      allEthPrices.data.reduce((acc, p) => {\n        acc[p.time] = p.value\n        return acc\n      }, {} as Record<string, number>),\n    [allEthPrices.data],\n  )\n}\n\nexport const useEthPricesSinceStrategiesLaunchMap = () => {\n  const ethPrices = useEthPricesSinceStrategiesLaunch()\n\n  return useMemo(\n    () =>\n      ethPrices.data &&\n      ethPrices.data.reduce((acc, p) => {\n        acc[p.time] = p.value\n        return acc\n      }, {} as Record<string, number>),\n    [ethPrices.data],\n  )\n}\n\nexport const useEth90daysPriceMap = () => {\n  const allEth90daysPrices = useAllEth90daysPrices()\n\n  return useMemo(\n    () =>\n      allEth90daysPrices.data &&\n      allEth90daysPrices.data.reduce((acc, p) => {\n        acc[p.time] = p.value\n        return acc\n      }, {} as Record<string, number>),\n    [allEth90daysPrices.data],\n  )\n}\n\nexport const useEthWithinOneDayPriceMap = () => {\n  const allEthWithinOneDayPrices = useAllEthWithinOneDayPrices()\n\n  return useMemo(\n    () =>\n      allEthWithinOneDayPrices.data\n        ? allEthWithinOneDayPrices.data.reduce((acc: any, p) => {\n            acc[p.time] = p.value\n            return acc\n          }, {})\n        : {},\n    [allEthWithinOneDayPrices.data],\n  )\n}\n\nexport const useGetVaultPNLWithRebalance = () => {\n  const ethPrices = useEthPrices().data\n  const squeethSeries = useSqueethSeries().data\n  const prevShortSeries = usePrevShortSeries()\n  const startingETHPrice = useStartingETHPrice()\n\n  return useAppCallback(\n    (n: number, rebalanceInterval = 86400) => {\n      if (!squeethSeries || squeethSeries.series.length === 0) return []\n      if (!ethPrices || !prevShortSeries) return\n      if (ethPrices && squeethSeries.series.length !== ethPrices.length) return []\n\n      const delta = n - 2 // fix delta we want to hedge to. (n - 2)\n      const normalizedFactor = startingETHPrice\n\n      // how much eth holding throughout the time\n      let longAmount = n\n      const data: { time: number; value: number }[] = []\n      let nextRebalanceTime = ethPrices[0].time + rebalanceInterval\n\n      // set uniswap fee\n      const UNISWAP_FEE = 0.003\n\n      // accumulate total cost of buying (or selling) eth\n      let totalLongCost = startingETHPrice * longAmount\n\n      ethPrices.forEach(({ time, value: price }, i) => {\n        if (time > nextRebalanceTime) {\n          const m = squeethSeries.series[i].positionSize\n\n          // rebalance\n          const x = price / normalizedFactor\n\n          // solve n for formula:\n          // n - 2mx = m * delta\n          const newN = m * delta + 2 * x * m\n          const buyAmount = newN - longAmount\n          const buyCost = buyAmount * price + Math.abs(buyAmount * price * UNISWAP_FEE)\n          //console.log(`Date ${new Date(time * 1000).toDateString()}, price ${price.toFixed(3)} Rebalance: short squeeth ${m.toFixed(4)}, desired ETH long ${newN.toFixed(4)}, buy ${buyAmount.toFixed(4)} more eth`)\n\n          totalLongCost += buyCost\n          longAmount = newN\n\n          //console.log('total long cost', totalLongCost, 'longAmount', longAmount)\n\n          //normalizedFactor = price\n          nextRebalanceTime = nextRebalanceTime + rebalanceInterval\n        }\n\n        const longValue = price * longAmount - totalLongCost // should probably be be named something like ethDeltaPnL\n        const realizedPNL = prevShortSeries[i].value + longValue\n\n        // calculate how much eth to buy\n        data.push({\n          time: time,\n          value: realizedPNL,\n        })\n      })\n\n      return data\n    },\n    [ethPrices, prevShortSeries, squeethSeries, startingETHPrice],\n  )\n}\n\nexport const useGetStableYieldPNL = () => {\n  const cusdcPrices = useCusdcPrices().data\n  const startingETHPrice = useStartingETHPrice()\n\n  return useAppCallback(\n    (comparedLongAmount: number) => {\n      if (!cusdcPrices || cusdcPrices.length === 0) return []\n\n      // price of one unit of cUSDC\n      const startCUSDCPrice = cusdcPrices[0].value\n      const amountCUSDC = (startingETHPrice * comparedLongAmount) / startCUSDCPrice\n      return cusdcPrices.map(({ time, value }) => {\n        const pnlPerct =\n          Math.round(\n            ((amountCUSDC * value - startingETHPrice * comparedLongAmount) / (startingETHPrice * comparedLongAmount)) *\n              10000,\n          ) / 100\n        return {\n          time,\n          value: pnlPerct,\n        }\n      })\n    },\n    [cusdcPrices, startingETHPrice],\n    true,\n  )\n}\nexport const useSqueethIsLive = () => {\n  const volMultiplier = useAtomValue(volMultiplierAtom)\n  const ethPrices = useEthPrices()\n  const days = useAtomValue(daysAtom)\n  const ethSqueethPNLSeries = useETHSqueethPNLCompounding(ethPrices.data ?? [], volMultiplier, days)\n  return useAppMemo(\n    () => {\n      return (\n        ethSqueethPNLSeries.squeethPNL &&\n        ethSqueethPNLSeries.squeethPNL.map(({ isLive }) => {\n          return isLive\n        })\n      )\n    },\n    [ethSqueethPNLSeries.squeethPNL],\n    true,\n  )\n}\n\nexport const useLongChartData = () => {\n  const startDate = useAtomValue(longPayoffFilterStartDateAtom)\n  const endDate = useAtomValue(longPayoffFilterEndDateAtom)\n  const volMultiplier = useAtomValue(volMultiplierAtom)\n  const collatRatio = useAtomValue(collatRatioAtom)\n\n  const fromTs = startDate.getTime()\n  const toTs = endDate.getTime()\n\n  return useQuery(\n    ['longChart', { fromTs, toTs, collatRatio, volMultiplier }],\n    async () => getLongChartData(fromTs, toTs, collatRatio, volMultiplier),\n    {\n      enabled: Boolean(fromTs && toTs && volMultiplier && collatRatio),\n      staleTime: Infinity,\n      refetchOnWindowFocus: true,\n    },\n  )\n}\n"
  },
  {
    "path": "packages/frontend/src/state/lp/hooks.ts",
    "content": "import { nearestUsableTick, TickMath } from '@uniswap/v3-sdk'\nimport { fromTokenAmount, toTokenAmount } from '@utils/calculations'\nimport { useAtomValue } from 'jotai'\nimport { addressesAtom, isWethToken0Atom } from '../positions/atoms'\nimport BigNumber from 'bignumber.js'\nimport { INDEX_SCALE, OSQUEETH_DECIMALS, WETH_DECIMALS } from '@constants/index'\nimport {\n  controllerContractAtom,\n  controllerHelperHelperContractAtom,\n  nftManagerContractAtom,\n  quoterContractAtom,\n  squeethPoolContractAtom,\n} from '../contracts/atoms'\nimport useAppCallback from '@hooks/useAppCallback'\nimport { addressAtom } from '../wallet/atoms'\nimport { Contract } from 'web3-eth-contract'\nimport { useHandleTransaction } from '../wallet/hooks'\nimport { ethers } from 'ethers'\nimport { useCallback } from 'react'\nimport { useGetDebtAmount, useGetVault } from '../controller/hooks'\nimport { indexAtom, normFactorAtom } from '../controller/atoms'\n\n/*** CONSTANTS ***/\nconst COLLAT_RATIO_FLASHLOAN = 2\nconst POOL_FEE = 3000\nconst MAX_INT_128 = new BigNumber(2).pow(128).minus(1).toFixed(0)\nconst x96 = new BigNumber(2).pow(96)\nconst FLASHLOAN_BUFFER = 0.02\n\n/*** ACTIONS ***/\n\n// Opening a mint and LP position and depositing\nexport const useOpenPositionDeposit = () => {\n  const { squeethPool } = useAtomValue(addressesAtom)\n  const address = useAtomValue(addressAtom)\n  const contract = useAtomValue(controllerHelperHelperContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const getDebtAmount = useGetDebtAmount()\n  const squeethPoolContract = useAtomValue(squeethPoolContractAtom)\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n  const index = useAtomValue(indexAtom)\n  const normFactor = useAtomValue(normFactorAtom)\n  const getVault = useGetVault()\n  const getCollateralToLP = useGetCollateralToLP()\n  const openPositionDeposit = useAppCallback(\n    async (\n      squeethToMint: BigNumber,\n      lowerTickInput: number,\n      upperTickInput: number,\n      vaultId: number,\n      collatRatio: number,\n      slippage: number,\n      withdrawAmount: number,\n      onTxConfirmed?: () => void,\n    ) => {\n      const vaultBefore = await getVault(vaultId)\n      if (\n        !contract ||\n        !address ||\n        !squeethPoolContract ||\n        !vaultBefore ||\n        !vaultBefore.shortAmount ||\n        !vaultBefore.collateralAmount\n      )\n        return null\n\n      const mintWSqueethAmount = fromTokenAmount(squeethToMint, OSQUEETH_DECIMALS)\n      const { tick, tickSpacing } = await getPoolState(squeethPoolContract)\n      const lowerTick = nearestUsableTick(lowerTickInput, Number(tickSpacing))\n      const upperTick = nearestUsableTick(upperTickInput, Number(tickSpacing))\n\n      const collateralToLp = await getCollateralToLP(mintWSqueethAmount, lowerTick, upperTick, tick)\n      if (!collateralToLp) return\n\n      const amount0New = isWethToken0 ? collateralToLp : mintWSqueethAmount\n      const amount1New = isWethToken0 ? mintWSqueethAmount : collateralToLp\n      const amount0Min = amount0New.times(new BigNumber(1).minus(slippage)).toFixed(0)\n      const amount1Min = amount1New.times(new BigNumber(1).minus(slippage)).toFixed(0)\n\n      const collateralToWithdraw = fromTokenAmount(withdrawAmount, OSQUEETH_DECIMALS)\n      const ethIndexPrice = toTokenAmount(index, 18).sqrt()\n      const vaultShortAmt = fromTokenAmount(vaultBefore.shortAmount, OSQUEETH_DECIMALS)\n      const vaultCollateralAmt = fromTokenAmount(vaultBefore.collateralAmount, WETH_DECIMALS)\n\n      // Calculate collateralToMint\n      const oSQTHInETH = mintWSqueethAmount.times(ethIndexPrice.div(INDEX_SCALE)).times(normFactor)\n      const collateralToMint = new BigNumber(collatRatio)\n        .times(vaultShortAmt.plus(mintWSqueethAmount).times(normFactor).times(ethIndexPrice).div(INDEX_SCALE))\n        .minus(vaultCollateralAmt.minus(collateralToWithdraw).plus(collateralToLp).plus(oSQTHInETH))\n      const flashLoanAmount = new BigNumber(COLLAT_RATIO_FLASHLOAN + FLASHLOAN_BUFFER)\n        .times(vaultShortAmt.plus(mintWSqueethAmount))\n        .times(normFactor)\n        .times(ethIndexPrice)\n        .div(INDEX_SCALE)\n        .minus(vaultCollateralAmt)\n      const collateralToMintPos = BigNumber.max(collateralToMint, 0)\n      const flashLoanAmountPos = BigNumber.max(flashLoanAmount, 0)\n\n      const flashloanWMintDepositNftParams = {\n        wPowerPerpPool: squeethPool,\n        vaultId: vaultId,\n        wPowerPerpAmount: mintWSqueethAmount.toFixed(0),\n        collateralToDeposit: collateralToMintPos.plus(flashLoanAmountPos).toFixed(0),\n        collateralToFlashloan: flashLoanAmountPos.toFixed(0),\n        collateralToLp: collateralToLp.toFixed(0),\n        collateralToWithdraw: collateralToWithdraw.toFixed(0),\n        amount0Min,\n        amount1Min,\n        lowerTick: lowerTick,\n        upperTick: upperTick,\n      }\n\n      return handleTransaction(\n        contract.methods.flashloanWMintLpDepositNft(flashloanWMintDepositNftParams).send({\n          from: address,\n          value: collateralToLp.plus(collateralToMintPos).minus(collateralToWithdraw).toFixed(0),\n        }),\n        onTxConfirmed,\n      )\n    },\n    [\n      address,\n      squeethPool,\n      contract,\n      handleTransaction,\n      getDebtAmount,\n      squeethPoolContract,\n      isWethToken0,\n      index,\n      normFactor,\n      getVault,\n    ],\n  )\n\n  return openPositionDeposit\n}\n\n/*** GETTERS ***/\n\nexport const useGetPosition = () => {\n  const contract = useAtomValue(nftManagerContractAtom)\n\n  const getPosition = useCallback(\n    async (uniTokenId: number) => {\n      if (!contract) return null\n      const position = await contract.methods.positions(uniTokenId).call()\n      const {\n        nonce,\n        operator,\n        token0,\n        token1,\n        fee,\n        tickLower,\n        tickUpper,\n        liquidity,\n        feeGrowthInside0LastX128,\n        feeGrowthInside1LastX128,\n        tokensOwed0,\n        tokensOwed1,\n      } = position\n      return {\n        nonce,\n        operator,\n        token0,\n        token1,\n        fee,\n        tickLower,\n        tickUpper,\n        liquidity,\n        feeGrowthInside0LastX128,\n        feeGrowthInside1LastX128,\n        tokensOwed0,\n        tokensOwed1,\n      }\n    },\n    [contract],\n  )\n\n  return getPosition\n}\n\nexport const useGetLiquidity = () => {\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n\n  const getLiquidity = useCallback(\n    async (\n      squeethAmount: BigNumber,\n      sqrtLowerPrice: BigNumber,\n      sqrtUpperPrice: BigNumber,\n      sqrtSqueethPrice: BigNumber,\n    ) => {\n      if (isWethToken0) {\n        // Ly = y / (sqrtSqueethPrice - sqrtLowerPrice)\n        return squeethAmount.div(sqrtSqueethPrice.minus(sqrtLowerPrice))\n      } else {\n        // Lx = x * (sqrtSqueethPrice * sqrtUpperPrice) / (sqrtUpperPrice - sqrtSqueethPrice)\n        return squeethAmount.times(sqrtSqueethPrice.times(sqrtUpperPrice)).div(sqrtUpperPrice.minus(sqrtSqueethPrice))\n      }\n    },\n    [isWethToken0],\n  )\n\n  return getLiquidity\n}\n\nexport const useGetCollateralToLP = () => {\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n  const getLiquidity = useGetLiquidity()\n  const getTickPrices = useGetTickPrices()\n\n  const getCollateralToLP = useCallback(\n    async (squeethAmount: BigNumber, lowerTick: Number, upperTick: Number, tick: number) => {\n      const { sqrtLowerPrice, sqrtUpperPrice, sqrtSqueethPrice } = await getTickPrices(lowerTick, upperTick, tick)\n\n      if (\n        (sqrtUpperPrice.lt(sqrtSqueethPrice) && !isWethToken0) ||\n        (sqrtLowerPrice.gt(sqrtSqueethPrice) && isWethToken0)\n      ) {\n        // All weth position\n        console.log('LPing an all WETH position is not enabled, but you can rebalance to this position.')\n        return\n      } else if (\n        (sqrtLowerPrice.gt(sqrtSqueethPrice) && !isWethToken0) ||\n        (sqrtUpperPrice.lt(sqrtSqueethPrice) && isWethToken0)\n      ) {\n        // All squeeth position\n        return new BigNumber(0)\n      } else {\n        // isWethToken0  -> x = Ly * (sqrtUpperPrice - sqrtSqueethPrice)/(sqrtSqueethPrice * sqrtUpperPrice)\n        // !isWethToken0 -> y = Lx * (sqrtSqueethPrice - sqrtLowerPrice)\n\n        const liquidity = await getLiquidity(squeethAmount, sqrtLowerPrice, sqrtUpperPrice, sqrtSqueethPrice)\n        return isWethToken0\n          ? liquidity.times(sqrtUpperPrice.minus(sqrtSqueethPrice)).div(sqrtSqueethPrice.times(sqrtUpperPrice))\n          : liquidity.times(sqrtSqueethPrice.minus(sqrtLowerPrice))\n      }\n    },\n    [isWethToken0, getLiquidity],\n  )\n\n  return getCollateralToLP\n}\n\nexport const useGetTickPrices = () => {\n  const getTickPrices = useCallback(async (lowerTick: Number, upperTick: Number, currentTick: number) => {\n    const sqrtLowerPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(lowerTick)).toString()).div(x96)\n    const sqrtUpperPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(upperTick)).toString()).div(x96)\n    const sqrtSqueethPrice = new BigNumber(TickMath.getSqrtRatioAtTick(Number(currentTick)).toString()).div(x96)\n    return { sqrtLowerPrice, sqrtUpperPrice, sqrtSqueethPrice }\n  }, [])\n\n  return getTickPrices\n}\n\nexport const useGetDecreaseLiquidity = () => {\n  const contract = useAtomValue(nftManagerContractAtom)\n\n  const getDecreaseLiquiduity = useCallback(\n    async (tokenId: number, liquidity: number, amount0Min: number, amount1Min: number, deadline: number) => {\n      if (!contract) return null\n      const DecreaseLiquidityParams = {\n        tokenId,\n        liquidity,\n        amount0Min,\n        amount1Min,\n        deadline,\n      }\n\n      const decreaseLiquidity = await contract.methods.decreaseLiquidity(DecreaseLiquidityParams).call()\n\n      return decreaseLiquidity\n    },\n    [contract],\n  )\n\n  return getDecreaseLiquiduity\n}\n\nexport const useGetExactIn = () => {\n  const contract = useAtomValue(quoterContractAtom)\n  const { weth, oSqueeth } = useAtomValue(addressesAtom)\n\n  const getExactIn = useCallback(\n    async (amount: BigNumber, squeethIn: boolean) => {\n      if (!contract) return null\n\n      const QuoteExactInputSingleParams = {\n        tokenIn: squeethIn ? oSqueeth : weth,\n        tokenOut: squeethIn ? weth : oSqueeth,\n        amountIn: amount.toFixed(0),\n        fee: POOL_FEE,\n        sqrtPriceLimitX96: 0,\n      }\n\n      const quote = await contract.methods.quoteExactInputSingle(QuoteExactInputSingleParams).call()\n      return quote.amountOut\n    },\n    [contract, weth, oSqueeth],\n  )\n\n  return getExactIn\n}\n\nexport const useGetExactOut = () => {\n  const contract = useAtomValue(quoterContractAtom)\n  const { weth, oSqueeth } = useAtomValue(addressesAtom)\n\n  const getExactOut = useCallback(\n    async (amount: BigNumber, squeethOut: boolean) => {\n      if (!contract) return null\n\n      const QuoteExactOutputSingleParams = {\n        tokenIn: squeethOut ? weth : oSqueeth,\n        tokenOut: squeethOut ? oSqueeth : weth,\n        amount: amount.toFixed(0),\n        fee: POOL_FEE,\n        sqrtPriceLimitX96: 0,\n      }\n\n      const quote = await contract.methods.quoteExactOutputSingle(QuoteExactOutputSingleParams).call()\n      return quote.amountIn\n    },\n    [contract, weth, oSqueeth],\n  )\n\n  return getExactOut\n}\n\nasync function getPoolState(poolContract: Contract) {\n  const [slot, liquidity, tickSpacing] = await Promise.all([\n    poolContract?.methods.slot0().call(),\n    poolContract?.methods.liquidity().call(),\n    poolContract.methods.tickSpacing().call(),\n  ])\n\n  const PoolState = {\n    liquidity,\n    sqrtPriceX96: slot[0],\n    tick: slot[1],\n    observationIndex: slot[2],\n    observationCardinality: slot[3],\n    observationCardinalityNext: slot[4],\n    feeProtocol: slot[5],\n    unlocked: slot[6],\n    tickSpacing,\n  }\n\n  return PoolState\n}"
  },
  {
    "path": "packages/frontend/src/state/nftmanager/hooks.ts",
    "content": "import { Position } from '@uniswap/v3-sdk'\n\nimport { toTokenAmount } from '@utils/calculations'\nimport { useAtomValue } from 'jotai'\nimport { isWethToken0Atom } from '../positions/atoms'\nimport BigNumber from 'bignumber.js'\nimport { BIG_ZERO } from '@constants/index'\nimport { poolAtom } from '../squeethPool/atoms'\nimport { nftManagerContractAtom } from '../contracts/atoms'\nimport { useCallback } from 'react'\n\nexport const useGetPosition = () => {\n  const contract = useAtomValue(nftManagerContractAtom)\n  const pool = useAtomValue(poolAtom)\n  const getPosition = useCallback(\n    async (posId: number) => {\n      if (!contract || !pool) return\n\n      const { tickLower, tickUpper, liquidity, tokensOwed1, tokensOwed0 } = await contract.methods\n        .positions(posId)\n        .call()\n      const uniPosition = new Position({\n        pool,\n        tickLower: Number(tickLower),\n        tickUpper: Number(tickUpper),\n        liquidity: liquidity.toString(),\n      })\n\n      return { uniPosition, tokensOwed1: toTokenAmount(tokensOwed1, 18), tokensOwed0: toTokenAmount(tokensOwed0, 18) }\n    },\n    [contract, pool],\n  )\n\n  return getPosition\n}\n\nexport const useGetETHandOSQTHAmount = () => {\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n  const getPosition = useGetPosition()\n  const getETHandOSQTHAmount = useCallback(\n    async (posId: number) => {\n      const result = await getPosition(posId)\n      if (!result) return { wethAmount: BIG_ZERO, oSqthAmount: BIG_ZERO }\n\n      const { uniPosition, tokensOwed0, tokensOwed1 } = result\n      const amt0 = new BigNumber(uniPosition.amount0.toSignificant(18))\n      const amt1 = new BigNumber(uniPosition.amount1.toSignificant(18))\n\n      const wethAmount = isWethToken0 ? amt0.plus(tokensOwed0) : amt1.plus(tokensOwed1)\n      const oSqthAmount = !isWethToken0 ? amt0.plus(tokensOwed0) : amt1.plus(tokensOwed1)\n\n      return { wethAmount, oSqthAmount, position: result.uniPosition }\n    },\n    [getPosition, isWethToken0],\n  )\n\n  return getETHandOSQTHAmount\n}\n"
  },
  {
    "path": "packages/frontend/src/state/pnl/atoms.ts",
    "content": "import { atom } from 'jotai'\nimport { BIG_ZERO } from '@constants/index'\n\nexport const ethCollateralPnlAtom = atom(BIG_ZERO)\nexport const shortUnrealizedPNLAtom = atom({ usd: BIG_ZERO, eth: BIG_ZERO, loading: true })\nexport const longUnrealizedPNLAtom = atom({ usd: BIG_ZERO, eth: BIG_ZERO, loading: true })\nexport const buyQuoteAtom = atom(BIG_ZERO)\nexport const sellQuoteAtom = atom({\n  amountOut: BIG_ZERO,\n  minimumAmountOut: BIG_ZERO,\n  priceImpact: '0',\n  pools: Array<Array<any>>()\n})\n\nexport const longGainAtom = atom(BIG_ZERO)\nexport const shortGainAtom = atom(BIG_ZERO)\nexport const loadingAtom = atom(true)\n"
  },
  {
    "path": "packages/frontend/src/state/pnl/hooks.ts",
    "content": "import { useAtom, useAtomValue } from 'jotai'\nimport { useUpdateAtom } from 'jotai/utils'\n\nimport { useVaultHistoryQuery } from '@hooks/useVaultHistory'\nimport { toTokenAmount } from '@utils/calculations'\nimport { calcDollarLongUnrealizedpnl, calcDollarShortUnrealizedpnl, calcETHCollateralPnl } from 'src/lib/pnl'\nimport { useComputeSwaps, useFirstValidVault, useSwaps } from '../positions/hooks'\nimport {\n  buyQuoteAtom,\n  ethCollateralPnlAtom,\n  loadingAtom,\n  longGainAtom,\n  longUnrealizedPNLAtom,\n  sellQuoteAtom,\n  shortGainAtom,\n  shortUnrealizedPNLAtom,\n} from './atoms'\nimport {\n  isToHidePnLAtom,\n  isWethToken0Atom,\n  positionTypeAtom,\n  longPositionValueAtom,\n  shortPositionValueAtom,\n  swapsAtom,\n} from '../positions/atoms'\nimport { readyAtom } from '../squeethPool/atoms'\nimport { useGetBuyQuote, useGetSellQuote, useGetWSqueethPositionValue } from '../squeethPool/hooks'\nimport { BIG_ZERO } from '@constants/index'\nimport { PositionType } from '../../types'\nimport { useVaultData } from '@hooks/useVaultData'\nimport { indexAtom } from '../controller/atoms'\nimport useAppEffect from '@hooks/useAppEffect'\n\nexport function useEthCollateralPnl() {\n  const { vaultId, validVault, isVaultLoading } = useFirstValidVault()\n  const { vaultHistory, loading: vaultHistoryLoading } = useVaultHistoryQuery(vaultId)\n  const { existingCollat } = useVaultData(validVault)\n  const isToHidePnL = useAtomValue(isToHidePnLAtom)\n\n  const index = useAtomValue(indexAtom)\n\n  const [ethCollateralPnl, setEthCollateralPnl] = useAtom(ethCollateralPnlAtom)\n  const swapsData = useAtomValue(swapsAtom)\n\n  useAppEffect(() => {\n    ;(async () => {\n      if (\n        !isToHidePnL &&\n        vaultHistory?.length &&\n        !index.isZero() &&\n        !existingCollat.isZero() &&\n        swapsData?.swaps?.length &&\n        !vaultHistoryLoading &&\n        !isVaultLoading\n      ) {\n        const result = await calcETHCollateralPnl(vaultHistory, toTokenAmount(index, 18).sqrt(), existingCollat)\n        setEthCollateralPnl(result)\n      } else {\n        setEthCollateralPnl(BIG_ZERO)\n      }\n    })()\n  }, [\n    isToHidePnL,\n    existingCollat,\n    index,\n    setEthCollateralPnl,\n    swapsData?.swaps,\n    vaultHistory,\n    isVaultLoading,\n    vaultHistoryLoading,\n  ])\n\n  return ethCollateralPnl\n}\n\n/* depreciated */\nexport function useBuyAndSellQuote() {\n  const { loading: positionsLoading } = useSwaps()\n  const { squeethAmount } = useComputeSwaps()\n  const getSellQuote = useGetSellQuote()\n  const getBuyQuote = useGetBuyQuote()\n  const [buyQuote, setBuyQuote] = useAtom(buyQuoteAtom)\n  const [sellQuote, setSellQuote] = useAtom(sellQuoteAtom)\n  const setLoading = useUpdateAtom(loadingAtom)\n  const ready = useAtomValue(readyAtom)\n\n  useAppEffect(() => {\n    if (!ready || positionsLoading) return\n\n    const p1 = getSellQuote(squeethAmount).then(setSellQuote)\n    const p2 = getBuyQuote(squeethAmount).then((val) => setBuyQuote(val.amountIn))\n    Promise.all([p1, p2]).then(() => setLoading(false))\n  }, [getBuyQuote, getSellQuote, positionsLoading, ready, squeethAmount, setBuyQuote, setLoading, setSellQuote])\n\n  return { buyQuote, sellQuote }\n}\n\nexport function useCurrentLongPositionValue() {\n  const { squeethAmount } = useComputeSwaps()\n  const getWSqueethPositionValue = useGetWSqueethPositionValue()\n  const [positionValue, setPositionValue] = useAtom(longPositionValueAtom)\n  const positionType = useAtomValue(positionTypeAtom)\n\n  useAppEffect(() => {\n    if (squeethAmount.isZero() || positionType != PositionType.LONG) {\n      setPositionValue(BIG_ZERO)\n      return\n    }\n\n    const squeethPositionValueInUSD = getWSqueethPositionValue(squeethAmount)\n    setPositionValue(squeethPositionValueInUSD)\n  }, [squeethAmount, positionType, getWSqueethPositionValue, setPositionValue])\n\n  return positionValue\n}\n\nexport function useCurrentShortPositionValue() {\n  const { squeethAmount } = useComputeSwaps()\n  const getWSqueethPositionValue = useGetWSqueethPositionValue()\n\n  const [positionValue, setPositionValue] = useAtom(shortPositionValueAtom)\n  const positionType = useAtomValue(positionTypeAtom)\n\n  useAppEffect(() => {\n    if (squeethAmount.isZero() || positionType != PositionType.SHORT) {\n      setPositionValue(BIG_ZERO)\n      return\n    }\n\n    const squeethPositionValueInUSD = getWSqueethPositionValue(squeethAmount)\n    setPositionValue(squeethPositionValueInUSD)\n  }, [squeethAmount, setPositionValue, positionType, getWSqueethPositionValue])\n\n  return positionValue\n}\n\nexport function useLongGain() {\n  const [longGain, setLongGain] = useAtom(longGainAtom)\n  const { totalUSDFromBuy } = useComputeSwaps()\n  const longPositionValue = useAtomValue(longPositionValueAtom)\n  const positionType = useAtomValue(positionTypeAtom)\n  const setLoading = useUpdateAtom(loadingAtom)\n\n  useAppEffect(() => {\n    if (longPositionValue.isZero() && positionType != PositionType.LONG) {\n      setLongGain(BIG_ZERO)\n      setLoading(false)\n      return\n    }\n\n    // (a - b) / b === a / b - 1\n    const _gain = longPositionValue.dividedBy(totalUSDFromBuy).minus(1).times(100)\n    setLongGain(_gain)\n    setLoading(false)\n  }, [setLoading, positionType, longPositionValue, totalUSDFromBuy, setLongGain])\n\n  return longGain\n}\n\nexport function useShortGain() {\n  const [shortGain, setShortGain] = useAtom(shortGainAtom)\n  const shortPositionValue = useAtomValue(shortPositionValueAtom)\n  const positionType = useAtomValue(positionTypeAtom)\n  const setLoading = useUpdateAtom(loadingAtom)\n  const { totalUSDFromBuy } = useComputeSwaps()\n\n  useAppEffect(() => {\n    if (shortPositionValue.isZero() && positionType != PositionType.SHORT) {\n      setShortGain(BIG_ZERO)\n      setLoading(false)\n      return\n    }\n    // (a - b) / b === a / b - 1\n    const _gain = shortPositionValue.dividedBy(totalUSDFromBuy).minus(1).times(100)\n    setShortGain(_gain)\n    setLoading(false)\n  }, [setLoading, shortPositionValue, totalUSDFromBuy, positionType, setShortGain])\n  return shortGain\n}\n\nexport function useLongUnrealizedPNL() {\n  const { squeethAmount } = useComputeSwaps()\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n  const positionType = useAtomValue(positionTypeAtom)\n  const longPositionValue = useAtomValue(longPositionValueAtom)\n  const isToHidePnL = useAtomValue(isToHidePnLAtom)\n  const [longUnrealizedPNL, setLongUnrealizedPNL] = useAtom(longUnrealizedPNLAtom)\n  const index = useAtomValue(indexAtom)\n\n  const swapsData = useAtomValue(swapsAtom)\n  const swaps = swapsData?.swaps\n\n  useAppEffect(() => {\n    ;(async () => {\n      if (\n        !isToHidePnL &&\n        swaps?.length &&\n        !index.isZero() &&\n        !longPositionValue.isZero() &&\n        !squeethAmount.isZero() &&\n        positionType === PositionType.LONG\n      ) {\n        const pnl = await calcDollarLongUnrealizedpnl(\n          swaps,\n          isWethToken0,\n          longPositionValue,\n          toTokenAmount(index, 18).sqrt(),\n          squeethAmount,\n        )\n        setLongUnrealizedPNL((prevState) => ({ ...prevState, ...pnl }))\n      } else {\n        setLongUnrealizedPNL({ usd: BIG_ZERO, eth: BIG_ZERO, loading: true })\n      }\n    })()\n  }, [isToHidePnL, index, isWethToken0, swaps, squeethAmount, positionType, setLongUnrealizedPNL, longPositionValue])\n\n  return longUnrealizedPNL\n}\n\nexport function useShortUnrealizedPNL() {\n  const { squeethAmount } = useComputeSwaps()\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n  const positionType = useAtomValue(positionTypeAtom)\n  const ethCollateralPnl = useEthCollateralPnl()\n\n  const shortPositionValue = useAtomValue(shortPositionValueAtom)\n  const [shortUnrealizedPNL, setShortUnrealizedPNL] = useAtom(shortUnrealizedPNLAtom)\n  const index = useAtomValue(indexAtom)\n  const isToHidePnL = useAtomValue(isToHidePnLAtom)\n\n  const { loading: swapsLoading } = useSwaps()\n  const swapsData = useAtomValue(swapsAtom)\n  const swaps = swapsData?.swaps\n\n  useAppEffect(() => {\n    ;(async () => {\n      if (\n        !isToHidePnL &&\n        swaps?.length &&\n        !shortPositionValue.isZero() &&\n        !index.isZero() &&\n        !ethCollateralPnl.isZero() &&\n        !squeethAmount.isZero() &&\n        positionType === PositionType.SHORT &&\n        !swapsLoading\n      ) {\n        const pnl = await calcDollarShortUnrealizedpnl(\n          swaps,\n          isWethToken0,\n          shortPositionValue,\n          toTokenAmount(index, 18).sqrt(),\n          squeethAmount,\n          ethCollateralPnl,\n        )\n        setShortUnrealizedPNL({\n          ...pnl,\n        })\n      } else {\n        setShortUnrealizedPNL({ usd: BIG_ZERO, eth: BIG_ZERO, loading: true })\n      }\n    })()\n  }, [\n    shortPositionValue,\n    isToHidePnL,\n    ethCollateralPnl,\n    index,\n    isWethToken0,\n    swaps,\n    squeethAmount,\n    positionType,\n    setShortUnrealizedPNL,\n    swapsLoading,\n  ])\n\n  return shortUnrealizedPNL\n}\n"
  },
  {
    "path": "packages/frontend/src/state/positions/atoms.ts",
    "content": "import { atom } from 'jotai'\n\nimport { PositionType, Vault } from '../../types'\nimport {\n  CONTROLLER,\n  USDC,\n  ETH_USDC_POOL,\n  NFT_MANAGER,\n  ORACLE,\n  QUOTER,\n  SHORT_HELPER,\n  SQUEETH_UNI_POOL,\n  SWAP_ROUTER,\n  SWAP_ROUTER_02,\n  VAULT_MANAGER,\n  WETH,\n  OSQUEETH,\n  ZERO_ADDR,\n  CRAB_STRATEGY,\n  CRAB_MIGRATION,\n  CRAB_STRATEGY2,\n  CONTROLLER_HELPER,\n  CRAB_HELPER,\n  CRAB_NETTING,\n  FLASH_BULL_STRATEGY,\n  BULL_STRATEGY,\n  WETH_E_TOKEN,\n  AUCTION_BULL,\n  EULER_SIMPLE_LENS,\n  USDC_D_TOKEN,\n  BULL_EMERGENCY_WITHDRAW,\n  BULL_SHUTDOWN_EMERGENCY_WITHDRAW,\n} from '@constants/address'\nimport { networkIdAtom, web3Atom } from '../wallet/atoms'\nimport { BIG_ZERO } from '@constants/index'\nimport NFTpositionManagerABI from '../../abis/NFTpositionmanager.json'\nimport { swaps } from '@queries/uniswap/__generated__/swaps'\nimport { swapsRopsten } from '@queries/uniswap/__generated__/swapsRopsten'\n\nexport const positionTypeAtom = atom(PositionType.NONE)\nexport const isLongAtom = atom((get) => {\n  const positionType = get(positionTypeAtom)\n  return positionType === PositionType.LONG\n})\nexport const isShortAtom = atom((get) => {\n  const positionType = get(positionTypeAtom)\n  return positionType === PositionType.SHORT\n})\nexport const firstValidVaultAtom = atom(0)\nexport const addressesAtom = atom((get) => {\n  const networkId = get(networkIdAtom)\n  return {\n    zero: ZERO_ADDR.toLowerCase(),\n    controller: CONTROLLER[networkId].toLowerCase(),\n    vaultManager: VAULT_MANAGER[networkId].toLowerCase(),\n    oSqueeth: OSQUEETH[networkId].toLowerCase(),\n    weth: WETH[networkId].toLowerCase(),\n    swapRouter: SWAP_ROUTER[networkId].toLowerCase(),\n    swapRouter2: SWAP_ROUTER_02[networkId].toLowerCase(),\n    squeethPool: SQUEETH_UNI_POOL[networkId].toLowerCase(),\n    quoter: QUOTER[networkId].toLowerCase(),\n    shortHelper: SHORT_HELPER[networkId].toLowerCase(),\n    oracle: ORACLE[networkId].toLowerCase(),\n    ethUsdcPool: ETH_USDC_POOL[networkId].toLowerCase(),\n    usdc: USDC[networkId].toLowerCase(),\n    nftManager: NFT_MANAGER[networkId].toLowerCase(),\n    crabStrategy: CRAB_STRATEGY[networkId].toLowerCase(),\n    crabMigration: CRAB_MIGRATION[networkId].toLowerCase(),\n    crabStrategy2: CRAB_STRATEGY2[networkId].toLowerCase(),\n    controllerHelper: CONTROLLER_HELPER[networkId].toLowerCase(),\n    crabHelper: CRAB_HELPER[networkId].toLowerCase(),\n    crabNetting: CRAB_NETTING[networkId].toLowerCase(),\n    flashBull: FLASH_BULL_STRATEGY[networkId].toLowerCase(),\n    bullStrategy: BULL_STRATEGY[networkId].toLowerCase(),\n    bullEmergencyWithdraw: BULL_EMERGENCY_WITHDRAW[networkId].toLowerCase(),\n    wethEToken: WETH_E_TOKEN[networkId].toLowerCase(),\n    auctionBull: AUCTION_BULL[networkId].toLowerCase(),\n    eulerSimpleLens: EULER_SIMPLE_LENS[networkId].toLowerCase(),\n    usdcDToken: USDC_D_TOKEN[networkId].toLowerCase(),\n    bullShutdownEmergencyWithdraw: BULL_SHUTDOWN_EMERGENCY_WITHDRAW[networkId].toLowerCase(),\n  }\n})\n\nexport const isWethToken0Atom = atom((get) => {\n  const addresses = get(addressesAtom)\n  return parseInt(addresses.weth, 16) < parseInt(addresses.oSqueeth, 16)\n})\n\nexport const managerAtom = atom((get) => {\n  const { nftManager } = get(addressesAtom)\n  const web3 = get(web3Atom)\n  return new web3.eth.Contract(NFTpositionManagerABI as any, nftManager?.toLowerCase() || '')\n})\nexport const activePositionsAtom = atom<any[]>([])\nexport const closedPositionsAtom = atom<any[]>([])\nexport const squeethLiquidityAtom = atom(BIG_ZERO)\nexport const wethLiquidityAtom = atom(BIG_ZERO)\nexport const depositedSqueethAtom = atom(BIG_ZERO)\nexport const depositedWethAtom = atom(BIG_ZERO)\nexport const withdrawnSqueethAtom = atom(BIG_ZERO)\nexport const withdrawnWethAtom = atom(BIG_ZERO)\nexport const isLPAtom = atom((get) => {\n  const squeethLiquidity = get(squeethLiquidityAtom)\n  const wethLiquidity = get(wethLiquidityAtom)\n  return squeethLiquidity.gt(0) || wethLiquidity.gt(0)\n})\n\nexport const vaultAtom = atom<Vault | null>(null)\nexport const existingCollatPercentAtom = atom(0)\nexport const existingCollatAtom = atom(BIG_ZERO)\nexport const existingLiqPriceAtom = atom(BIG_ZERO)\nexport const collatPercentAtom = atom(0)\nexport const isVaultLoadingAtom = atom(true)\nexport const vaultHistoryUpdatingAtom = atom(false)\nexport const isToHidePnLAtom = atom(false)\nexport const swapsAtom = atom<swaps | swapsRopsten>({ swaps: [] })\nexport const longPositionValueAtom = atom(BIG_ZERO)\nexport const shortPositionValueAtom = atom(BIG_ZERO)\n"
  },
  {
    "path": "packages/frontend/src/state/positions/hooks.ts",
    "content": "import { useState } from 'react'\nimport { useAtom, useAtomValue, atom } from 'jotai'\nimport { useUpdateAtom } from 'jotai/utils'\nimport { useQuery } from '@apollo/client'\nimport { useContext } from 'react'\nimport BigNumber from 'bignumber.js'\nimport { Position } from '@uniswap/v3-sdk'\n\nimport { networkIdAtom, addressAtom } from '../wallet/atoms'\nimport { swaps, swapsVariables } from '@queries/uniswap/__generated__/swaps'\nimport SWAPS_QUERY, { SWAPS_SUBSCRIPTION } from '@queries/uniswap/swapsQuery'\nimport SWAPS_ROPSTEN_QUERY, { SWAPS_ROPSTEN_SUBSCRIPTION } from '@queries/uniswap/swapsRopstenQuery'\nimport { VAULT_QUERY } from '@queries/squeeth/vaultsQuery'\nimport { BIG_ZERO, OSQUEETH_DECIMALS } from '@constants/index'\nimport {\n  addressesAtom,\n  isWethToken0Atom,\n  positionTypeAtom,\n  managerAtom,\n  activePositionsAtom,\n  closedPositionsAtom,\n  squeethLiquidityAtom,\n  wethLiquidityAtom,\n  depositedSqueethAtom,\n  depositedWethAtom,\n  withdrawnSqueethAtom,\n  withdrawnWethAtom,\n  swapsAtom,\n} from './atoms'\nimport { positions, positionsVariables } from '@queries/uniswap/__generated__/positions'\nimport POSITIONS_QUERY, { POSITIONS_SUBSCRIPTION } from '@queries/uniswap/positionsQuery'\nimport { useVaultManager } from '@hooks/contracts/useVaultManager'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport { toTokenAmount } from '@utils/calculations'\nimport { squeethClient } from '@utils/apollo-client'\nimport { PositionType, Networks } from '../../types'\nimport { poolAtom, squeethInitialPriceAtom } from '../squeethPool/atoms'\nimport { useETHPrice } from '@hooks/useETHPrice'\nimport { useGetWSqueethPositionValue } from '../squeethPool/hooks'\nimport { useVaultHistory } from '@hooks/useVaultHistory'\nimport { swapsRopsten, swapsRopstenVariables } from '@queries/uniswap/__generated__/swapsRopsten'\nimport { Vault } from '@queries/squeeth/__generated__/Vault'\nimport { ComputeSwapsContext } from './providers'\nimport useAppEffect from '@hooks/useAppEffect'\nimport useAppMemo from '@hooks/useAppMemo'\n\nexport const useSwaps = () => {\n  const [networkId] = useAtom(networkIdAtom)\n  const [address] = useAtom(addressAtom)\n  const setSwaps = useUpdateAtom(swapsAtom)\n  const { squeethPool, oSqueeth, shortHelper, swapRouter, crabStrategy, crabStrategy2, flashBull, bullStrategy } =\n    useAtomValue(addressesAtom)\n  const { subscribeToMore, data, refetch, loading, error, startPolling, stopPolling } = useQuery<\n    swaps | swapsRopsten,\n    swapsVariables | swapsRopstenVariables\n  >(networkId === Networks.MAINNET ? SWAPS_QUERY : SWAPS_ROPSTEN_QUERY, {\n    variables: {\n      origin: address || '',\n      orderDirection: 'asc',\n      recipient_not_in: [crabStrategy, crabStrategy2, flashBull, bullStrategy],\n      ...(networkId === Networks.MAINNET\n        ? {\n            tokenAddress: oSqueeth,\n          }\n        : {\n            poolAddress: squeethPool,\n            recipients: [shortHelper, address || '', swapRouter],\n          }),\n    },\n    fetchPolicy: 'cache-and-network',\n  })\n\n  useAppEffect(() => {\n    subscribeToMore({\n      document: networkId === Networks.MAINNET ? SWAPS_SUBSCRIPTION : SWAPS_ROPSTEN_SUBSCRIPTION,\n      variables: {\n        origin: address || '',\n        orderDirection: 'asc',\n        recipient_not_in: [crabStrategy, crabStrategy2, flashBull, bullStrategy],\n        ...(networkId === Networks.MAINNET\n          ? {\n              tokenAddress: oSqueeth,\n            }\n          : {\n              poolAddress: squeethPool,\n              recipients: [shortHelper, address || '', swapRouter],\n            }),\n      },\n      updateQuery(prev, { subscriptionData }) {\n        if (!subscriptionData.data) return prev\n        const newSwaps = subscriptionData.data.swaps\n        return {\n          swaps: newSwaps,\n        }\n      },\n    })\n  }, [address, crabStrategy, networkId, oSqueeth, shortHelper, squeethPool, swapRouter, subscribeToMore])\n\n  useAppEffect(() => {\n    if (data?.swaps) {\n      setSwaps({ swaps: data?.swaps })\n    } else {\n      setSwaps({ swaps: [] })\n    }\n  }, [data?.swaps, setSwaps])\n\n  return { data, refetch, loading, error, startPolling, stopPolling }\n}\n\nexport const useComputeSwaps = () => {\n  const context = useContext(ComputeSwapsContext)\n\n  if (!context) {\n    throw new Error('useComputeSwaps must be used inside ComputeSwapsProvider')\n  }\n\n  return context\n}\n\nexport const useLongRealizedPnl = () => {\n  const { boughtSqueeth, soldSqueeth, totalUSDFromBuy, totalUSDFromSell } = useComputeSwaps()\n  return useAppMemo(() => {\n    if (!soldSqueeth.gt(0)) return BIG_ZERO\n    const costForOneSqth = !totalUSDFromBuy.isEqualTo(0) ? totalUSDFromBuy.div(boughtSqueeth) : BIG_ZERO\n    const realizedForOneSqth = !totalUSDFromSell.isEqualTo(0) ? totalUSDFromSell.div(soldSqueeth) : BIG_ZERO\n    const pnlForOneSqth = realizedForOneSqth.minus(costForOneSqth)\n\n    return pnlForOneSqth.multipliedBy(soldSqueeth)\n  }, [boughtSqueeth, soldSqueeth, totalUSDFromBuy, totalUSDFromSell])\n}\n\nexport const useShortRealizedPnl = () => {\n  const { boughtSqueeth, soldSqueeth, totalUSDFromBuy, totalUSDFromSell } = useComputeSwaps()\n  return useAppMemo(() => {\n    if (!boughtSqueeth.gt(0)) return BIG_ZERO\n\n    const costForOneSqth = !totalUSDFromSell.isEqualTo(0) ? totalUSDFromSell.div(soldSqueeth) : BIG_ZERO\n    const realizedForOneSqth = !totalUSDFromBuy.isEqualTo(0) ? totalUSDFromBuy.div(boughtSqueeth) : BIG_ZERO\n    const pnlForOneSqth = realizedForOneSqth.minus(costForOneSqth)\n\n    return pnlForOneSqth.multipliedBy(boughtSqueeth)\n  }, [boughtSqueeth, totalUSDFromBuy, soldSqueeth, totalUSDFromSell])\n}\n\nexport const useMintedSoldSort = () => {\n  const { vaultId } = useFirstValidVault()\n  const { openShortSqueeth } = useVaultHistory(Number(vaultId))\n  const positionType = useAtomValue(positionTypeAtom)\n  const { squeethAmount } = useComputeSwaps()\n\n  //when the squeethAmount < 0 and the abs amount is greater than openShortSqueeth, that means there is manually sold short position\n  return useAppMemo(() => {\n    return positionType === PositionType.SHORT && squeethAmount.abs().isGreaterThan(openShortSqueeth)\n      ? squeethAmount.abs().minus(openShortSqueeth)\n      : new BigNumber(0)\n  }, [positionType, squeethAmount, openShortSqueeth])\n}\n\nexport const useMintedDebt = () => {\n  const { vaultId } = useFirstValidVault()\n  const { mintedSqueeth } = useVaultHistory(Number(vaultId))\n  const lpDebt = useLpDebt()\n  const mintedSoldShort = useMintedSoldSort()\n\n  //mintedSqueeth balance from vault histroy - mintedSold short position = existing mintedDebt in vault, but\n  //LPed amount wont be taken into account from vault history, so will need to be deducted here and added the withdrawn amount back\n  //if there is LP Debt, shld be deducted from minted Debt\n  const mintedDebt = useAppMemo(() => {\n    return mintedSqueeth.minus(mintedSoldShort).minus(lpDebt)\n  }, [mintedSqueeth, mintedSoldShort, lpDebt])\n\n  return mintedDebt\n}\n\nexport const useShortDebt = () => {\n  const positionType = useAtomValue(positionTypeAtom)\n  const { squeethAmount } = useComputeSwaps()\n  const shortDebt = useAppMemo(() => {\n    return positionType === PositionType.SHORT ? squeethAmount : new BigNumber(0)\n  }, [positionType, squeethAmount])\n\n  return shortDebt.absoluteValue()\n}\n\nexport const useLongSqthBal = () => {\n  const { oSqueeth } = useAtomValue(addressesAtom)\n  const { value: oSqueethBal, loading, error, refetch } = useTokenBalance(oSqueeth, 15, OSQUEETH_DECIMALS)\n  const mintedDebt = useMintedDebt()\n  const longSqthBal = useAppMemo(() => {\n    return mintedDebt.gt(0) ? oSqueethBal.minus(mintedDebt) : oSqueethBal\n  }, [oSqueethBal, mintedDebt])\n  return { longSqthBal, loading, error, refetch }\n}\n\nexport const useLpDebt = () => {\n  const depositedSqueeth = useAtomValue(depositedSqueethAtom)\n  const withdrawnSqueeth = useAtomValue(withdrawnSqueethAtom)\n  const lpDebt = useAppMemo(() => {\n    return depositedSqueeth.minus(withdrawnSqueeth).isGreaterThan(0)\n      ? depositedSqueeth.minus(withdrawnSqueeth)\n      : new BigNumber(0)\n  }, [depositedSqueeth, withdrawnSqueeth])\n\n  return lpDebt\n}\n\nexport const useLPPositionsQuery = () => {\n  const { squeethPool } = useAtomValue(addressesAtom)\n  const address = useAtomValue(addressAtom)\n  const { data, refetch, loading, subscribeToMore } = useQuery<positions, positionsVariables>(POSITIONS_QUERY, {\n    variables: {\n      poolAddress: squeethPool?.toLowerCase(),\n      owner: address?.toLowerCase() || '',\n    },\n    fetchPolicy: 'cache-and-network',\n  })\n\n  useAppEffect(() => {\n    subscribeToMore({\n      document: POSITIONS_SUBSCRIPTION,\n      variables: {\n        poolAddress: squeethPool?.toLowerCase(),\n        owner: address?.toLowerCase() || '',\n      },\n      updateQuery(prev, { subscriptionData }) {\n        if (!subscriptionData.data) return prev\n        const newPosition = subscriptionData.data.positions\n        return {\n          positions: newPosition,\n        }\n      },\n    })\n  }, [address, squeethPool, subscribeToMore])\n\n  return { data, refetch, loading }\n}\n\nconst MAX_UNIT = '0xffffffffffffffffffffffffffffffff'\nconst positionFeesAtom = atom<any[]>([])\nexport const useLPPositionsAndFees = () => {\n  const manager = useAtomValue(managerAtom)\n  const address = useAtomValue(addressAtom)\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n  const pool = useAtomValue(poolAtom)\n  const squeethInitialPrice = useAtomValue(squeethInitialPriceAtom)\n  const getWSqueethPositionValue = useGetWSqueethPositionValue()\n  const { data } = useLPPositionsQuery()\n  const ethPrice = useETHPrice()\n  const [positionFees, setPositionFees] = useAtom(positionFeesAtom)\n\n  useAppEffect(() => {\n    ;(async function handlePositionFees() {\n      if (!pool || !squeethInitialPrice.toNumber() || !ethPrice.toNumber() || !data) return []\n\n      const positionFeesP = data.positions.map(async (p) => {\n        const position = { ...p }\n        const tokenIdHexString = new BigNumber(position.id).toString()\n        const uniPosition = new Position({\n          pool,\n          liquidity: position.liquidity.toString(),\n          tickLower: Number(position.tickLower.tickIdx),\n          tickUpper: Number(position.tickUpper.tickIdx),\n        })\n\n        const fees = await manager.methods\n          .collect({\n            tokenId: tokenIdHexString,\n            recipient: address,\n            amount0Max: MAX_UNIT,\n            amount1Max: MAX_UNIT,\n          })\n          .call()\n\n        const squeethAmt = isWethToken0\n          ? new BigNumber(uniPosition.amount1.toSignificant(18))\n          : new BigNumber(uniPosition.amount0.toSignificant(18))\n\n        const wethAmt = isWethToken0\n          ? new BigNumber(uniPosition.amount0.toSignificant(18))\n          : new BigNumber(uniPosition.amount1.toSignificant(18))\n\n        const squeethFees = isWethToken0 ? toTokenAmount(fees?.amount1, 18) : toTokenAmount(fees?.amount0, 18)\n        const wethFees = isWethToken0 ? toTokenAmount(fees?.amount0, 18) : toTokenAmount(fees?.amount1, 18)\n\n        const dollarValue = getWSqueethPositionValue(squeethAmt)\n          .plus(getWSqueethPositionValue(squeethFees))\n          .plus(wethAmt.times(ethPrice))\n          .plus(wethFees.times(ethPrice))\n\n        return {\n          ...position,\n          amount0: new BigNumber(uniPosition.amount0.toSignificant(18)),\n          amount1: new BigNumber(uniPosition.amount1.toSignificant(18)),\n          fees0: toTokenAmount(fees?.amount0, 18),\n          fees1: toTokenAmount(fees?.amount1, 18),\n          dollarValue,\n        }\n      })\n\n      setPositionFees(await Promise.all(positionFeesP))\n    })()\n  }, [\n    ethPrice,\n    squeethInitialPrice,\n    data?.positions,\n    address,\n    data,\n    getWSqueethPositionValue,\n    isWethToken0,\n    manager.methods,\n    pool,\n    setPositionFees,\n  ])\n\n  return positionFees\n}\n\nexport const usePositionsAndFeesComputation = () => {\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n  const [activePositions, setActivePositions] = useAtom(activePositionsAtom)\n  const setClosedPositions = useUpdateAtom(closedPositionsAtom)\n  const setDepositedSqueeth = useUpdateAtom(depositedSqueethAtom)\n  const setDepositedWeth = useUpdateAtom(depositedWethAtom)\n  const setWithdrawnSqueeth = useUpdateAtom(withdrawnSqueethAtom)\n  const setWithdrawnWeth = useUpdateAtom(withdrawnWethAtom)\n  const setWethLiquidity = useUpdateAtom(wethLiquidityAtom)\n  const setSqueethLiquidity = useUpdateAtom(squeethLiquidityAtom)\n\n  const positionAndFees = useLPPositionsAndFees()\n  const { loading: gphLoading } = useLPPositionsQuery()\n\n  useAppEffect(() => {\n    if (positionAndFees && !gphLoading) {\n      // Promise.all(positionAndFees).then((values: any[]) => {\n      setActivePositions(positionAndFees.filter((p) => p.amount0.gt(0) || p.amount1.gt(0)))\n      setClosedPositions(positionAndFees.filter((p) => p.amount0.isZero() && p.amount1.isZero()))\n      // Calculate cumulative LP position here\n      let depSqth = new BigNumber(0)\n      let depWeth = new BigNumber(0)\n      let withSqth = new BigNumber(0)\n      let withWeth = new BigNumber(0)\n      let sqthLiq = new BigNumber(0)\n      let wethLiq = new BigNumber(0)\n      for (const position of positionAndFees) {\n        sqthLiq = sqthLiq.plus(isWethToken0 ? position.amount1 : position.amount0)\n        wethLiq = wethLiq.plus(isWethToken0 ? position.amount0 : position.amount1)\n        depSqth = depSqth.plus(isWethToken0 ? position.depositedToken1 : position.depositedToken0)\n        depWeth = depWeth.plus(isWethToken0 ? position.depositedToken0 : position.depositedToken1)\n        withSqth = withSqth.plus(\n          isWethToken0\n            ? new BigNumber(position.withdrawnToken1).plus(position.collectedFeesToken1)\n            : new BigNumber(position.withdrawnToken0).plus(position.collectedFeesToken0),\n        )\n        withWeth = withWeth.plus(\n          !isWethToken0\n            ? new BigNumber(position.withdrawnToken1).plus(position.collectedFeesToken1)\n            : new BigNumber(position.withdrawnToken0).plus(position.collectedFeesToken0),\n        )\n      }\n\n      setDepositedSqueeth(depSqth)\n      setDepositedWeth(depWeth)\n      setWithdrawnSqueeth(withSqth)\n      setWithdrawnWeth(withWeth)\n      setSqueethLiquidity(sqthLiq)\n      setWethLiquidity(wethLiq)\n    }\n  }, [\n    gphLoading,\n    isWethToken0,\n    positionAndFees,\n    activePositions.length,\n    setActivePositions,\n    setClosedPositions,\n    setDepositedSqueeth,\n    setDepositedWeth,\n    setSqueethLiquidity,\n    setWethLiquidity,\n    setWithdrawnSqueeth,\n    setWithdrawnWeth,\n  ])\n}\n\nexport const useVaultQuery = (vaultId: number) => {\n  const networkId = useAtomValue(networkIdAtom)\n\n  const query = useQuery<Vault>(VAULT_QUERY, {\n    client: squeethClient[networkId],\n    fetchPolicy: 'cache-and-network',\n    variables: {\n      vaultID: vaultId,\n    },\n  })\n\n  const vaultData = useAppMemo(() => {\n    if (query.data) {\n      const vault = query.data.vault\n\n      return {\n        id: vault?.id,\n        NFTCollateralId: vault?.NftCollateralId,\n        collateralAmount: toTokenAmount(new BigNumber(vault?.collateralAmount), 18),\n        shortAmount: toTokenAmount(new BigNumber(vault?.shortAmount), OSQUEETH_DECIMALS),\n        operator: vault?.operator,\n        owner: vault?.owner?.id,\n      }\n    }\n  }, [query.data])\n\n  return { ...query, data: vaultData }\n}\n\nexport const useFirstValidVault = () => {\n  const { vaults: shortVaults, loading } = useVaultManager()\n\n  const vault = shortVaults?.find((vault) => vault.collateralAmount.isGreaterThan(0))\n\n  return {\n    isVaultLoading: loading,\n    vaultId: Number(vault?.id) || 0,\n    validVault: vault,\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/state/positions/providers.tsx",
    "content": "import BigNumber from 'bignumber.js'\nimport { createContext } from 'react'\nimport { useAtom, useAtomValue } from 'jotai'\nimport { useUpdateAtom } from 'jotai/utils'\nimport { BIG_ZERO, OSQUEETH_DECIMALS } from '@constants/index'\nimport { addressesAtom, isWethToken0Atom, positionTypeAtom, isToHidePnLAtom } from './atoms'\nimport { useUsdAmount } from '@hooks/useUsdAmount'\nimport { PositionType } from '../../types'\nimport { useFirstValidVault, useSwaps } from './hooks'\nimport useAppMemo from '@hooks/useAppMemo'\nimport { FC } from 'react'\nimport { useTokenBalance } from '@hooks/contracts/useTokenBalance'\nimport useAppEffect from '@hooks/useAppEffect'\ninterface ComputeSwapsContextValue {\n  squeethAmount: BigNumber\n  wethAmount: BigNumber\n  longUsdAmount: BigNumber\n  shortUsdAmount: BigNumber\n  boughtSqueeth: BigNumber\n  soldSqueeth: BigNumber\n  totalUSDFromBuy: BigNumber\n  totalUSDFromSell: BigNumber\n  loading: Boolean\n}\n\nexport const ComputeSwapsContext = createContext<ComputeSwapsContextValue | null>(null)\n\nexport const ComputeSwapsProvider: FC = ({ children }) => {\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n  const [positionType, setPositionType] = useAtom(positionTypeAtom)\n  const setIsToHidePnL = useUpdateAtom(isToHidePnLAtom)\n  const { getUsdAmt } = useUsdAmount()\n  const { data, loading } = useSwaps()\n  const { oSqueeth } = useAtomValue(addressesAtom)\n  const { value: oSqueethBal, refetch } = useTokenBalance(oSqueeth, 15, OSQUEETH_DECIMALS)\n  const { validVault: vault } = useFirstValidVault()\n\n  const computedSwaps = useAppMemo(\n    () =>\n      data?.swaps.reduce(\n        (acc, s) => {\n          //values are all from the pool pov\n          //if >0 for the pool, user gave some squeeth to the pool, meaning selling the squeeth\n          const squeethAmt = new BigNumber(isWethToken0 ? s.amount1 : s.amount0)\n          const wethAmt = new BigNumber(isWethToken0 ? s.amount0 : s.amount1)\n          const usdAmt = getUsdAmt(wethAmt, s.timestamp)\n          //buy one squeeth means -1 to the pool, +1 to the user\n          acc.squeethAmount = acc.squeethAmount.plus(squeethAmt.negated())\n          //<0 means, buying squeeth\n          //>0 means selling squeeth\n          if (squeethAmt.isPositive()) {\n            //sold Squeeth amount\n            acc.soldSqueeth = acc.soldSqueeth.plus(squeethAmt.abs())\n            //usd value from sell to close long position or open short\n            acc.totalUSDFromSell = acc.totalUSDFromSell.plus(usdAmt.abs())\n          } else if (squeethAmt.isNegative()) {\n            //bought Squeeth amount\n            acc.boughtSqueeth = acc.boughtSqueeth.plus(squeethAmt.abs())\n            //usd value from buy to close short position or open long\n            acc.totalUSDFromBuy = acc.totalUSDFromBuy.plus(usdAmt.abs())\n          }\n          if (acc.squeethAmount.isZero()) {\n            acc.longUsdAmount = BIG_ZERO\n            acc.shortUsdAmount = BIG_ZERO\n            acc.wethAmount = BIG_ZERO\n            acc.boughtSqueeth = BIG_ZERO\n            acc.soldSqueeth = BIG_ZERO\n            acc.totalUSDFromSell = BIG_ZERO\n            acc.totalUSDFromBuy = BIG_ZERO\n          } else {\n            // when the position is partially closed, will accumulate usdamount\n            acc.longUsdAmount = acc.longUsdAmount.plus(usdAmt)\n            acc.shortUsdAmount = acc.shortUsdAmount.plus(usdAmt.negated())\n            acc.wethAmount = acc.wethAmount.plus(wethAmt.negated())\n          }\n          return acc\n        },\n        {\n          squeethAmount: BIG_ZERO,\n          wethAmount: BIG_ZERO,\n          longUsdAmount: BIG_ZERO,\n          shortUsdAmount: BIG_ZERO,\n          boughtSqueeth: BIG_ZERO,\n          soldSqueeth: BIG_ZERO,\n          totalUSDFromBuy: BIG_ZERO,\n          totalUSDFromSell: BIG_ZERO,\n        },\n      ) || {\n        squeethAmount: BIG_ZERO,\n        wethAmount: BIG_ZERO,\n        longUsdAmount: BIG_ZERO,\n        shortUsdAmount: BIG_ZERO,\n        boughtSqueeth: BIG_ZERO,\n        soldSqueeth: BIG_ZERO,\n        totalUSDFromBuy: BIG_ZERO,\n        totalUSDFromSell: BIG_ZERO,\n      },\n    [isWethToken0, data?.swaps, getUsdAmt],\n  )\n\n  useAppEffect(() => {\n    if (oSqueethBal?.isGreaterThan(0) && oSqueethBal.isGreaterThan(vault?.shortAmount || 0)) {\n      setPositionType(PositionType.LONG)\n      // check if user osqth wallet balance is equal to the accumulated amount from tx history\n      // if it's not the same, it's likely that they do smt on crab acution or otc or lp etc so dont show the pnl for them\n      if (!computedSwaps.squeethAmount.isEqualTo(oSqueethBal)) {\n        setIsToHidePnL(true)\n      } else {\n        setIsToHidePnL(false)\n      }\n    } else if (oSqueethBal.isLessThan(vault?.shortAmount || 0)) {\n      setIsToHidePnL(true)\n      setPositionType(PositionType.SHORT)\n    } else {\n      setIsToHidePnL(false)\n      setPositionType(PositionType.NONE)\n    }\n  }, [computedSwaps.squeethAmount, oSqueethBal, setPositionType, setIsToHidePnL, vault?.shortAmount])\n\n  useAppEffect(() => {\n    refetch()\n  }, [computedSwaps.squeethAmount, refetch])\n\n  const value = useAppMemo(\n    () => ({\n      ...computedSwaps,\n      loading,\n      squeethAmount:\n        positionType === PositionType.LONG ? oSqueethBal : vault?.shortAmount.minus(oSqueethBal) || BIG_ZERO,\n    }),\n    [computedSwaps, loading, positionType, oSqueethBal, vault?.shortAmount],\n  )\n\n  return <ComputeSwapsContext.Provider value={value}>{children}</ComputeSwapsContext.Provider>\n}\n"
  },
  {
    "path": "packages/frontend/src/state/squeethPool/atoms.ts",
    "content": "import { Token } from '@uniswap/sdk-core'\nimport { Pool } from '@uniswap/v3-sdk'\nimport { atom } from 'jotai'\nimport BigNumber from 'bignumber.js'\n\nimport { isWethToken0Atom } from '../positions/atoms'\nimport { BIG_ZERO } from '@constants/index'\nimport { toTokenAmount } from '@utils/calculations'\nexport const poolAtom = atom<Pool | null>(null)\nexport const wethTokenAtom = atom<Token | null>(null)\nexport const squeethTokenAtom = atom<Token | null>(null)\nexport const wethPriceAtom = atom((get) => {\n  const pool = get(poolAtom)\n  const isWethToken0 = get(isWethToken0Atom)\n  return toTokenAmount(\n    new BigNumber(isWethToken0 ? pool?.token1Price.toSignificant(18) || 0 : pool?.token0Price.toSignificant(18) || 0),\n    18,\n  )\n})\nexport const squeethInitialPriceAtom = atom(BIG_ZERO)\nexport const squeethInitialPriceErrorAtom = atom('')\nexport const squeethPriceeAtom = atom(BIG_ZERO) // not being used\nexport const readyAtom = atom(false)\n"
  },
  {
    "path": "packages/frontend/src/state/squeethPool/hooks.ts",
    "content": "import { DEFAULT_SLIPPAGE, OSQUEETH_DECIMALS, UNI_POOL_FEES, WETH_DECIMALS, ZERO_ADDRESS } from '@constants/index'\nimport useAppCallback from '@hooks/useAppCallback'\nimport useAppEffect from '@hooks/useAppEffect'\nimport { useETHPrice } from '@hooks/useETHPrice'\nimport { useOracle } from '@hooks/contracts/useOracle'\nimport useUniswapTicks from '@hooks/useUniswapTicks'\nimport { CurrencyAmount, Percent, Token, TradeType } from '@uniswap/sdk-core'\nimport { AlphaRouter, ChainId, SwapRoute } from '@uniswap/smart-order-router'\nimport { Pool, Route, Trade } from '@uniswap/v3-sdk'\nimport { fromTokenAmount, parseSlippageInput } from '@utils/calculations'\nimport BigNumber from 'bignumber.js'\nimport { ethers } from 'ethers'\nimport { useAtomValue } from 'jotai'\nimport { useUpdateAtom } from 'jotai/utils'\nimport { Contract } from 'web3-eth-contract'\nimport routerABI from '../../abis/swapRouter.json'\nimport router2ABI from '../../abis/swapRouter2.json'\nimport { squeethPoolContractAtom, swapRouter2ContractAtom, swapRouterContractAtom } from '../contracts/atoms'\nimport { addressesAtom, isWethToken0Atom } from '../positions/atoms'\nimport { addressAtom, networkIdAtom, web3Atom } from '../wallet/atoms'\nimport { useHandleTransaction } from '../wallet/hooks'\nimport wethAbi from '../../abis/weth.json'\nimport { Pair } from '@uniswap/v2-sdk'\n\nimport {\n  poolAtom,\n  readyAtom,\n  squeethInitialPriceAtom,\n  squeethInitialPriceErrorAtom,\n  squeethTokenAtom,\n  wethTokenAtom,\n} from './atoms'\nimport { computeRealizedLPFeePercent } from './price'\nimport { slippageAmountAtom } from '../trade/atoms'\nimport { getErrorMessage } from '@utils/error'\nimport useInterval from '@hooks/useInterval'\nimport { getGasPriceProvider } from '@utils/gasProvider'\n\nconst getImmutables = async (squeethContract: Contract) => {\n  const [token0, token1, fee, tickSpacing, maxLiquidityPerTick] = await Promise.all([\n    squeethContract?.methods.token0().call(),\n    squeethContract?.methods.token1().call(),\n    squeethContract?.methods.fee().call(),\n    squeethContract?.methods.tickSpacing().call(),\n    squeethContract?.methods.maxLiquidityPerTick().call(),\n  ])\n\n  return { token0, token1, fee, tickSpacing, maxLiquidityPerTick }\n}\n\nexport const getPoolState = async (poolContract: Contract) => {\n  const [slot, liquidity, tickSpacing] = await Promise.all([\n    poolContract?.methods.slot0().call(),\n    poolContract?.methods.liquidity().call(),\n    poolContract.methods.tickSpacing().call(),\n  ])\n\n  const PoolState = {\n    liquidity,\n    sqrtPriceX96: slot[0],\n    tick: slot[1],\n    observationIndex: slot[2],\n    observationCardinality: slot[3],\n    observationCardinalityNext: slot[4],\n    feeProtocol: slot[5],\n    unlocked: slot[6],\n    tickSpacing,\n  }\n\n  return PoolState\n}\n\nexport const useUpdateSqueethPoolData = () => {\n  const isWethToken0 = useAtomValue(isWethToken0Atom)\n  const networkId = useAtomValue(networkIdAtom)\n  const setPool = useUpdateAtom(poolAtom)\n  const setWethToken = useUpdateAtom(wethTokenAtom)\n  const setSqueethToken = useUpdateAtom(squeethTokenAtom)\n  const contract = useAtomValue(squeethPoolContractAtom)\n  const { ticks } = useUniswapTicks()\n  useAppEffect(() => {\n    let isMounted = true\n\n    ;(async () => {\n      const { token0, token1, fee } = await getImmutables(contract!)\n\n      const state = await getPoolState(contract!)\n      const TokenA = new Token(\n        networkId,\n        token0,\n        isWethToken0 ? 18 : OSQUEETH_DECIMALS,\n        isWethToken0 ? 'WETH' : 'SQE',\n        isWethToken0 ? 'Wrapped Ether' : 'oSqueeth',\n      )\n      const TokenB = new Token(\n        networkId,\n        token1,\n        isWethToken0 ? OSQUEETH_DECIMALS : 18,\n        isWethToken0 ? 'SQE' : 'WETH',\n        isWethToken0 ? 'oSqueeth' : 'Wrapped Ether',\n      )\n\n      const pool = new Pool(\n        TokenA,\n        TokenB,\n        Number(fee),\n        state.sqrtPriceX96.toString(),\n        state.liquidity.toString(),\n        Number(state.tick),\n        ticks || [],\n      )\n\n      if (isMounted && ticks?.length) {\n        console.log('Pools is set with tick length', ticks?.length)\n        setPool(pool)\n      }\n\n      setWethToken(isWethToken0 ? TokenA : TokenB)\n      setSqueethToken(isWethToken0 ? TokenB : TokenA)\n    })()\n\n    return () => {\n      isMounted = false\n    }\n  }, [isWethToken0, networkId, ticks?.length, contract, setPool, setWethToken, setSqueethToken])\n}\n\nexport const useSetTokens = () => {\n  const networkId = useAtomValue(networkIdAtom)\n  const setWethToken = useUpdateAtom(wethTokenAtom)\n  const setSqueethToken = useUpdateAtom(squeethTokenAtom)\n  const { weth, oSqueeth } = useAtomValue(addressesAtom)\n  const setTokens = useAppEffect(() => {\n    ;(async () => {\n      const wethToken = new Token(networkId, weth, WETH_DECIMALS, 'WETH', 'Wrapped Ether')\n      const squeethToken = new Token(networkId, oSqueeth, OSQUEETH_DECIMALS, 'SQE', 'oSqueeth')\n\n      setWethToken(wethToken)\n      setSqueethToken(squeethToken)\n    })()\n  })\n  return setTokens\n}\n\nexport const useGetBuyQuoteForETH = () => {\n  const pool = useAtomValue(poolAtom)\n  const networkId = useAtomValue(networkIdAtom)\n  const web3 = useAtomValue(web3Atom)\n  const address = useAtomValue(addressAtom)\n  const wethToken = useAtomValue(wethTokenAtom)\n  const squeethToken = useAtomValue(squeethTokenAtom)\n\n  //If I input an exact amount of ETH I want to spend, tells me how much Squeeth I'd purchase\n  const getBuyQuoteForETH = useAppCallback(\n    async (ETHAmount: BigNumber, slippageAmount = new BigNumber(DEFAULT_SLIPPAGE)) => {\n      const emptyState = {\n        amountOut: new BigNumber(0),\n        minimumAmountOut: new BigNumber(0),\n        priceImpact: '0',\n        pools: [],\n      }\n\n      try {\n        const slippageTolerance = slippageAmount ? slippageAmount : DEFAULT_SLIPPAGE\n        const provider = new ethers.providers.Web3Provider(web3.currentProvider as any)\n        const chainId = networkId as any as ChainId\n\n        const gasPriceProvider = getGasPriceProvider(chainId)\n\n        const router = new AlphaRouter({\n          chainId: chainId,\n          provider: provider as any,\n          gasPriceProvider,\n        })\n\n        const rawAmount = CurrencyAmount.fromRawAmount(wethToken!, fromTokenAmount(ETHAmount, 18).toFixed(0))\n\n        const route = await router.route(rawAmount, squeethToken!, TradeType.EXACT_INPUT, {\n          recipient: address ?? ZERO_ADDRESS,\n          slippageTolerance: parseSlippageInput(slippageTolerance.toString()),\n          deadline: Math.floor(Date.now() / 1000 + 1800),\n        })\n\n        if (!route) return null\n\n        const realizedLpFeePercent = computeRealizedLPFeePercent(route!.trade)\n        const priceImpact = route!.trade.priceImpact.subtract(realizedLpFeePercent).multiply(-1)\n\n        return {\n          amountOut: new BigNumber(route!.quote.toSignificant(OSQUEETH_DECIMALS)),\n          minimumAmountOut: new BigNumber(\n            route!.trade\n              .minimumAmountOut(parseSlippageInput(slippageAmount.toString()))\n              .toSignificant(OSQUEETH_DECIMALS),\n          ),\n          priceImpact: priceImpact.toFixed(2),\n          pools: getPoolInfo(route, ETHAmount),\n        }\n      } catch (e) {\n        console.log(e)\n      }\n      return emptyState\n    },\n    [pool, wethToken?.address, squeethToken?.address, web3, networkId, address],\n  )\n\n  return getBuyQuoteForETH\n}\n\nexport const useUpdateSqueethPrices = () => {\n  const { getTwapSafe } = useOracle()\n\n  const setSqueethInitialPrice = useUpdateAtom(squeethInitialPriceAtom)\n  const setSqueethInitialPriceError = useUpdateAtom(squeethInitialPriceErrorAtom)\n  const setReady = useUpdateAtom(readyAtom)\n  const { oSqueeth, weth, squeethPool } = useAtomValue(addressesAtom)\n\n  const getTwapSqueeth = () => {\n    if (squeethPool && oSqueeth && weth)\n      getTwapSafe(squeethPool, oSqueeth, weth, 1)\n        .then((quote) => setSqueethInitialPrice(quote))\n        .catch((error) => {\n          console.error(error)\n          setSqueethInitialPriceError(getErrorMessage(error))\n        })\n        .finally(() => {\n          setReady(true)\n        })\n  }\n\n  useInterval(getTwapSqueeth, 15000)\n\n  useAppEffect(() => {\n    getTwapSqueeth()\n  }, [getTwapSafe, oSqueeth, weth, setReady, setSqueethInitialPrice, setSqueethInitialPriceError, squeethPool])\n}\n\nexport const useGetWSqueethPositionValue = () => {\n  const ethPrice = useETHPrice()\n  const squeethInitialPrice = useAtomValue(squeethInitialPriceAtom)\n  const getWSqueethPositionValue = useAppCallback(\n    (amount: BigNumber | number) => {\n      return new BigNumber(amount).times(squeethInitialPrice).times(ethPrice)\n    },\n    [ethPrice, squeethInitialPrice],\n  )\n\n  return getWSqueethPositionValue\n}\n\nexport const useGetWSqueethPositionValueInETH = () => {\n  const squeethInitialPrice = useAtomValue(squeethInitialPriceAtom)\n  const getWSqueethPositionValueInETH = useAppCallback(\n    (amount: BigNumber | number) => {\n      return new BigNumber(amount).times(squeethInitialPrice)\n    },\n    [squeethInitialPrice],\n  )\n  return getWSqueethPositionValueInETH\n}\n\nexport const useGetBuyQuote = () => {\n  const pool = useAtomValue(poolAtom)\n  const wethToken = useAtomValue(wethTokenAtom)\n  const squeethToken = useAtomValue(squeethTokenAtom)\n  //If I input an exact amount of squeeth I want to buy, tells me how much ETH I need to pay to purchase that squeeth\n  const getBuyQuote = useAppCallback(\n    async (squeethAmount: BigNumber, slippageAmount = new BigNumber(DEFAULT_SLIPPAGE)) => {\n      const emptyState = {\n        amountIn: new BigNumber(0),\n        maximumAmountIn: new BigNumber(0),\n        priceImpact: '0',\n        poolFee: '0',\n      }\n\n      if (!squeethAmount || !pool) return emptyState\n\n      try {\n        //WETH is input token, squeeth is output token. I'm using WETH to buy Squeeth\n        const route = new Route([pool], wethToken!, squeethToken!)\n        //getting the amount of ETH I need to put in to get an exact amount of squeeth I inputted out\n        const rawAmount = CurrencyAmount.fromRawAmount(\n          squeethToken!,\n          fromTokenAmount(squeethAmount, OSQUEETH_DECIMALS).toFixed(0),\n        )\n\n        if (rawAmount.equalTo(0)) {\n          return emptyState\n        }\n\n        const trade = await Trade.exactOut(route, rawAmount)\n        const feePercent = new BigNumber(pool.fee).div(10000)\n\n        //the amount of ETH I need to put in\n        return {\n          amountIn: new BigNumber(trade.inputAmount.toSignificant(18)),\n          maximumAmountIn: new BigNumber(\n            trade.maximumAmountIn(parseSlippageInput(slippageAmount.toString())).toSignificant(18),\n          ),\n          priceImpact: trade.priceImpact.toFixed(2),\n          poolFee: feePercent.toFixed(2),\n        }\n      } catch (e) {\n        console.log(e)\n      }\n\n      return emptyState\n    },\n    [pool, wethToken?.address, squeethToken?.address],\n  )\n\n  return getBuyQuote\n}\n\nexport const useGetBuyParam = () => {\n  const address = useAtomValue(addressAtom)\n  const squeethToken = useAtomValue(squeethTokenAtom)\n  const wethToken = useAtomValue(wethTokenAtom)\n  const getBuyQuote = useGetBuyQuote()\n  const getBuyParam = async (amount: BigNumber) => {\n    const amountMax = fromTokenAmount((await getBuyQuote(amount)).maximumAmountIn, 18)\n\n    return {\n      tokenIn: wethToken?.address, // address\n      tokenOut: squeethToken?.address, // address\n      fee: UNI_POOL_FEES, // uint24\n      recipient: address, // address\n      deadline: Math.floor(Date.now() / 1000 + 86400), // uint256\n      amountOut: fromTokenAmount(amount, OSQUEETH_DECIMALS).toString(), // uint256\n      amountInMaximum: amountMax.toString(),\n      sqrtPriceLimitX96: 0, // uint160\n    }\n  }\n\n  return getBuyParam\n}\n\nexport const useBuy = () => {\n  const address = useAtomValue(addressAtom)\n  const swapRouterContract = useAtomValue(swapRouterContractAtom)\n  const handleTransaction = useHandleTransaction()\n  const getBuyParam = useGetBuyParam()\n  const buy = async (amount: BigNumber) => {\n    const exactOutputParam = await getBuyParam(amount)\n\n    await handleTransaction(\n      swapRouterContract?.methods.exactOutputSingle(exactOutputParam).send({\n        from: address,\n      }),\n    )\n  }\n  return buy\n}\n\nexport const useGetBuyParamForETH = () => {\n  const address = useAtomValue(addressAtom)\n  const squeethToken = useAtomValue(squeethTokenAtom)\n  const wethToken = useAtomValue(wethTokenAtom)\n  const getBuyQuoteForETH = useGetBuyQuoteForETH()\n  const getBuyParamForETH = async (amount: BigNumber) => {\n    const quote = await getBuyQuoteForETH(amount)\n\n    return {\n      tokenIn: wethToken?.address,\n      tokenOut: squeethToken?.address,\n      fee: UNI_POOL_FEES,\n      recipient: address,\n      deadline: Math.floor(Date.now() / 1000 + 86400), // uint256\n      amountIn: fromTokenAmount(amount, 18),\n      amountOutMinimum: fromTokenAmount(quote!.minimumAmountOut, OSQUEETH_DECIMALS).toString(),\n      sqrtPriceLimitX96: 0,\n    }\n  }\n\n  return getBuyParamForETH\n}\n\nexport const useBuyForWETH = () => {\n  const address = useAtomValue(addressAtom)\n  const handleTransaction = useHandleTransaction()\n  const swapRouterContract = useAtomValue(swapRouterContractAtom)\n  const getBuyParamForETH = useGetBuyParamForETH()\n  const buyForWETH = async (amount: BigNumber) => {\n    const exactInputParam = await getBuyParamForETH(new BigNumber(amount))\n\n    const txHash = await handleTransaction(\n      swapRouterContract?.methods.exactInputSingle(exactInputParam).send({\n        from: address,\n        value: fromTokenAmount(amount, 18),\n      }),\n    )\n\n    return txHash\n  }\n\n  return buyForWETH\n}\n\nexport const useBuyAndRefundData = () => {\n  const address = useAtomValue(addressAtom)\n  const web3 = useAtomValue(web3Atom)\n  const getBuyParamForETH = useGetBuyParamForETH()\n  const buyAndRefundData = async (amount: BigNumber) => {\n    if (!web3) return\n    const exactInputParam = await getBuyParamForETH(amount)\n    exactInputParam.recipient = address\n    const tupleInput = Object.values(exactInputParam).map((v) => v?.toString() || '')\n\n    const swapIface = new ethers.utils.Interface(routerABI)\n    const encodedSwapCall = swapIface.encodeFunctionData('exactInputSingle', [tupleInput])\n    const encodedRefundCall = swapIface.encodeFunctionData('refundETH')\n\n    return [encodedSwapCall, encodedRefundCall]\n  }\n\n  return buyAndRefundData\n}\n\nexport const useBuyAndRefund = () => {\n  const address = useAtomValue(addressAtom)\n  const handleTransaction = useHandleTransaction()\n  const swapRouterContract = useAtomValue(swapRouterContractAtom)\n  const buyAndRefundData = useBuyAndRefundData()\n\n  const buyAndRefund = useAppCallback(\n    async (amount: BigNumber, onTxConfirmed?: () => void) => {\n      const callData = await buyAndRefundData(amount)\n\n      const result = await handleTransaction(\n        swapRouterContract?.methods.multicall(callData).send({\n          from: address,\n          value: fromTokenAmount(amount, 18),\n        }),\n        onTxConfirmed,\n      )\n\n      return result\n    },\n    [address, swapRouterContract, buyAndRefundData],\n  )\n\n  return buyAndRefund\n}\n\nexport const useAutoRoutedBuyAndRefund = () => {\n  const networkId = useAtomValue(networkIdAtom)\n  const address = useAtomValue(addressAtom)\n  const wethToken = useAtomValue(wethTokenAtom)\n  const { swapRouter2, weth } = useAtomValue(addressesAtom)\n  const web3 = useAtomValue(web3Atom)\n  const squeethToken = useAtomValue(squeethTokenAtom)\n  const swapRouter2Contract = useAtomValue(swapRouter2ContractAtom)\n  const slippageAmount = useAtomValue(slippageAmountAtom)\n  const handleTransaction = useHandleTransaction()\n\n  const autoRoutedBuyAndRefund = useAppCallback(\n    async (amount: BigNumber, onTxConfirmed?: () => void) => {\n      // Initializing the AlphaRouter\n      const provider = new ethers.providers.Web3Provider(web3.currentProvider as any)\n      const chainId = networkId as any as ChainId\n\n      const gasPriceProvider = getGasPriceProvider(chainId)\n      const router = new AlphaRouter({\n        chainId: chainId,\n        provider: provider as any,\n        gasPriceProvider,\n      })\n      const slippageTolerance = slippageAmount ? slippageAmount : DEFAULT_SLIPPAGE\n\n      // Call Route\n      const rawAmount = CurrencyAmount.fromRawAmount(wethToken!, fromTokenAmount(amount, WETH_DECIMALS).toFixed(0))\n      const route = await router.route(rawAmount, squeethToken!, TradeType.EXACT_INPUT, {\n        recipient: address!,\n        slippageTolerance: parseSlippageInput(slippageTolerance.toString()),\n        deadline: Math.floor(Date.now() / 1000 + 1800),\n      })\n\n      const wethContract = new web3.eth.Contract(wethAbi as any, weth)\n      await wethContract.methods.approve(swapRouter2, fromTokenAmount(amount, WETH_DECIMALS).toFixed(0))\n\n      const gasEstimate = await swapRouter2Contract?.methods\n        .multicall([route?.methodParameters?.calldata])\n        .estimateGas({\n          to: swapRouter2,\n          value: fromTokenAmount(amount, WETH_DECIMALS).toFixed(0),\n          from: address,\n        })\n\n      const result = await handleTransaction(\n        swapRouter2Contract?.methods.multicall([route?.methodParameters?.calldata]).send({\n          to: swapRouter2,\n          value: fromTokenAmount(amount, WETH_DECIMALS).toFixed(0),\n          from: address,\n          gas: gasEstimate,\n        }),\n        onTxConfirmed,\n      )\n      return result\n    },\n    [address, slippageAmount, web3, wethToken, squeethToken],\n  )\n\n  return autoRoutedBuyAndRefund\n}\n\nexport const useAutoRoutedGetSellQuote = () => {\n  const pool = useAtomValue(poolAtom)\n  const squeethToken = useAtomValue(squeethTokenAtom)\n  const wethToken = useAtomValue(wethTokenAtom)\n  const networkId = useAtomValue(networkIdAtom)\n  const web3 = useAtomValue(web3Atom)\n  const address = useAtomValue(addressAtom)\n\n  //I input an exact amount of squeeth I want to sell, tells me how much ETH I'd receive\n  const getSellQuote = useAppCallback(\n    async (squeethAmount: BigNumber, slippageAmount = new BigNumber(DEFAULT_SLIPPAGE)) => {\n      const emptyState = {\n        amountOut: new BigNumber(0),\n        minimumAmountOut: new BigNumber(0),\n        priceImpact: '0',\n        pools: [],\n      }\n      if (!squeethAmount || squeethAmount.eq(0)) return emptyState\n\n      const slippageTolerance = slippageAmount ? slippageAmount : DEFAULT_SLIPPAGE\n      const provider = new ethers.providers.Web3Provider(web3.currentProvider as any)\n      const chainId = networkId as any as ChainId\n\n      const gasPriceProvider = getGasPriceProvider(chainId)\n      const router = new AlphaRouter({\n        chainId: chainId,\n        provider: provider as any,\n        gasPriceProvider,\n      })\n\n      const rawAmount = CurrencyAmount.fromRawAmount(\n        squeethToken!,\n        fromTokenAmount(squeethAmount, OSQUEETH_DECIMALS).toFixed(0),\n      )\n      const route = await router.route(rawAmount, wethToken!, TradeType.EXACT_INPUT, {\n        recipient: address ?? ZERO_ADDRESS,\n        slippageTolerance: parseSlippageInput(slippageTolerance.toString()),\n        deadline: Math.floor(Date.now() / 1000 + 1800),\n      })\n\n      if (!route) return null\n\n      const realizedLpFeePercent = computeRealizedLPFeePercent(route!.trade)\n      const priceImpact = route!.trade.priceImpact.subtract(realizedLpFeePercent).multiply(-1)\n\n      try {\n        return {\n          amountOut: new BigNumber(route!.quote?.toSignificant(WETH_DECIMALS)),\n          minimumAmountOut: new BigNumber(\n            route!.trade.minimumAmountOut(parseSlippageInput(slippageAmount.toString())).toSignificant(WETH_DECIMALS),\n          ),\n          priceImpact: priceImpact.toFixed(2),\n          pools: getPoolInfo(route, squeethAmount),\n        }\n      } catch (e) {\n        console.log(e)\n      }\n\n      return emptyState\n    },\n    [pool, wethToken?.address, squeethToken?.address],\n  )\n  return getSellQuote\n}\n\nexport const useGetSellQuote = () => {\n  const pool = useAtomValue(poolAtom)\n  const squeethToken = useAtomValue(squeethTokenAtom)\n  const wethToken = useAtomValue(wethTokenAtom)\n  //I input an exact amount of squeeth I want to sell, tells me how much ETH I'd receive\n  const getSellQuote = useAppCallback(\n    async (squeethAmount: BigNumber, slippageAmount = new BigNumber(DEFAULT_SLIPPAGE)) => {\n      const emptyState = {\n        amountOut: new BigNumber(0),\n        minimumAmountOut: new BigNumber(0),\n        priceImpact: '0',\n        pools: [],\n      }\n      if (!squeethAmount || !pool) return emptyState\n\n      try {\n        //squeeth is input token, WETH is output token. I'm selling squeeth for WETH\n        const route = new Route([pool], squeethToken!, wethToken!)\n        //getting the amount of ETH I'd receive for inputting the amount of squeeth I want to sell\n        const rawAmount = CurrencyAmount.fromRawAmount(\n          squeethToken!,\n          fromTokenAmount(squeethAmount, OSQUEETH_DECIMALS).toFixed(0),\n        )\n\n        if (rawAmount.equalTo(0)) {\n          return emptyState\n        }\n\n        const trade = await Trade.exactIn(route, rawAmount)\n        const feePercent = new BigNumber(pool.fee).div(10000)\n\n        //the amount of ETH I'm receiving\n        return {\n          amountOut: new BigNumber(trade.outputAmount.toSignificant(18)),\n          minimumAmountOut: new BigNumber(\n            trade.minimumAmountOut(parseSlippageInput(slippageAmount.toString())).toSignificant(18),\n          ),\n          priceImpact: trade.priceImpact.toFixed(2),\n          poolFee: feePercent.toFixed(2),\n          pools: [],\n        }\n      } catch (e) {\n        console.log(e)\n      }\n\n      return emptyState\n    },\n    [pool, wethToken?.address, squeethToken?.address],\n  )\n  return getSellQuote\n}\n\nexport const useGetSellParam = () => {\n  const address = useAtomValue(addressAtom)\n  const squeethToken = useAtomValue(squeethTokenAtom)\n  const wethToken = useAtomValue(wethTokenAtom)\n  const getSellQuote = useGetSellQuote()\n  const getSellParam = useAppCallback(\n    async (amount: BigNumber) => {\n      const amountMin = fromTokenAmount((await getSellQuote(amount))!.minimumAmountOut, 18)\n\n      return {\n        tokenIn: squeethToken?.address,\n        tokenOut: wethToken?.address,\n        fee: UNI_POOL_FEES,\n        recipient: address,\n        deadline: Math.floor(Date.now() / 1000 + 86400), // uint256\n        amountIn: fromTokenAmount(amount, OSQUEETH_DECIMALS).toString(),\n        amountOutMinimum: amountMin.toString(),\n        sqrtPriceLimitX96: 0,\n      }\n    },\n    [getSellQuote, squeethToken?.address, wethToken?.address, address],\n  )\n  return getSellParam\n}\n\nconst useSellAndUnwrapData = () => {\n  const address = useAtomValue(addressAtom)\n  const web3 = useAtomValue(web3Atom)\n  const { swapRouter } = useAtomValue(addressesAtom)\n  const getSellParam = useGetSellParam()\n  const getSellQuote = useGetSellQuote()\n  const sellAndUnwrapData = async (amount: BigNumber) => {\n    if (!web3) return\n    const exactInputParam = await getSellParam(amount)\n    exactInputParam.recipient = swapRouter\n    const tupleInput = Object.values(exactInputParam).map((v) => v?.toString() || '')\n    const minimumAmountOut = fromTokenAmount((await getSellQuote(amount))!.minimumAmountOut, 18)\n    const swapIface = new ethers.utils.Interface(routerABI)\n    const encodedSwapCall = swapIface.encodeFunctionData('exactInputSingle', [tupleInput])\n    const encodedUnwrapCall = swapIface.encodeFunctionData('unwrapWETH9(uint256,address)', [\n      fromTokenAmount(minimumAmountOut, 18).toString(),\n      address,\n    ])\n    return [encodedSwapCall, encodedUnwrapCall]\n  }\n\n  return sellAndUnwrapData\n}\n\nexport const useSell = () => {\n  const address = useAtomValue(addressAtom)\n  const handleTransaction = useHandleTransaction()\n  const swapRouterContract = useAtomValue(swapRouterContractAtom)\n  const sellAndUnwrapData = useSellAndUnwrapData()\n\n  const sell = async (amount: BigNumber, onTxConfirmed?: () => void) => {\n    const callData = await sellAndUnwrapData(amount)\n\n    const result = await handleTransaction(\n      swapRouterContract?.methods.multicall(callData).send({\n        from: address,\n      }),\n      onTxConfirmed,\n    )\n\n    return result\n  }\n  return sell\n}\n\nexport const useAutoRoutedSell = () => {\n  const networkId = useAtomValue(networkIdAtom)\n  const address = useAtomValue(addressAtom)\n  const wethToken = useAtomValue(wethTokenAtom)\n  const { swapRouter2 } = useAtomValue(addressesAtom)\n  const web3 = useAtomValue(web3Atom)\n  const squeethToken = useAtomValue(squeethTokenAtom)\n  const handleTransaction = useHandleTransaction()\n  const swapRouter2Contract = useAtomValue(swapRouter2ContractAtom)\n  const slippageAmount = useAtomValue(slippageAmountAtom)\n\n  const autoRoutedSell = useAppCallback(\n    async (amount: BigNumber, onTxConfirmed?: () => void) => {\n      // Initializing the AlphaRouter\n      const provider = new ethers.providers.Web3Provider(web3.currentProvider as any)\n      const chainId = networkId as any as ChainId\n\n      const gasPriceProvider = getGasPriceProvider(chainId)\n      const router = new AlphaRouter({\n        chainId: chainId,\n        provider: provider as any,\n        gasPriceProvider,\n      })\n\n      // Call Route\n      const rawAmount = CurrencyAmount.fromRawAmount(\n        squeethToken!,\n        fromTokenAmount(amount, OSQUEETH_DECIMALS).toFixed(0),\n      )\n\n      const slippageTolerance = slippageAmount ? slippageAmount : DEFAULT_SLIPPAGE\n      const route = await router.route(rawAmount, wethToken!, TradeType.EXACT_INPUT, {\n        recipient: swapRouter2,\n        slippageTolerance: parseSlippageInput(slippageTolerance.toString()),\n        deadline: Math.floor(Date.now() / 1000 + 1800),\n      })\n\n      const minimumAmountOut = new BigNumber(\n        route?.trade.minimumAmountOut(parseSlippageInput(slippageTolerance.toString())).toFixed(18) || 0,\n      )\n      const swapIface = new ethers.utils.Interface(router2ABI)\n      const encodedUnwrapCall = swapIface.encodeFunctionData('unwrapWETH9(uint256,address)', [\n        fromTokenAmount(minimumAmountOut, 18).toString(),\n        address,\n      ])\n      const result = await handleTransaction(\n        swapRouter2Contract?.methods.multicall([route?.methodParameters?.calldata, encodedUnwrapCall]).send({\n          from: address,\n        }),\n        onTxConfirmed,\n      )\n      return result\n    },\n    [address, slippageAmount],\n  )\n\n  return autoRoutedSell\n}\n\nexport const useGetSellQuoteForETH = () => {\n  const pool = useAtomValue(poolAtom)\n  const squeethToken = useAtomValue(squeethTokenAtom)\n  const wethToken = useAtomValue(wethTokenAtom)\n  //I input an exact amount of ETH I want to receive, tells me how much squeeth I'd need to sell\n  const getSellQuoteForETH = useAppCallback(\n    async (ETHAmount: BigNumber, slippageAmount = new BigNumber(DEFAULT_SLIPPAGE)) => {\n      const emptyState = {\n        amountIn: new BigNumber(0),\n        maximumAmountIn: new BigNumber(0),\n        priceImpact: '0',\n      }\n      if (!ETHAmount || !pool) return emptyState\n\n      try {\n        //squeeth is input token, WETH is output token. I'm selling squeeth for WETH\n        const route = new Route([pool], squeethToken!, wethToken!)\n        //getting the amount of squeeth I'd need to sell to receive my desired amount of ETH\n        const rawAmount = CurrencyAmount.fromRawAmount(wethToken!, fromTokenAmount(ETHAmount, 18).toFixed(0))\n\n        if (rawAmount.equalTo(0)) {\n          return emptyState\n        }\n\n        const trade = await Trade.exactOut(route, rawAmount)\n\n        //the amount of squeeth I need to sell\n        return {\n          amountIn: new BigNumber(trade.inputAmount.toSignificant(18)),\n          maximumAmountIn: new BigNumber(\n            trade.maximumAmountIn(parseSlippageInput(slippageAmount.toString())).toSignificant(18),\n          ),\n          priceImpact: trade.priceImpact.toFixed(2),\n        }\n      } catch (e) {\n        console.log(e)\n      }\n\n      return emptyState\n    },\n    [pool, squeethToken, wethToken],\n  )\n\n  return getSellQuoteForETH\n}\n\nfunction getPoolInfo(route: SwapRoute, overallInputAmount: BigNumber) {\n  const V2_DEFAULT_FEE_TIER = 3000\n  const poolsUsed = []\n  const swaps = route.trade.swaps\n  for (let i = 0; i < swaps.length; i++) {\n    const poolsInRoute = swaps[i].route.pools\n    for (let j = 0; j < poolsInRoute.length; j++) {\n      const pool = poolsInRoute[j]\n      const portion = swaps[i].inputAmount.divide(route.trade.inputAmount)\n      const percent = new Percent(portion.numerator, portion.denominator)\n      poolsUsed.push(\n        pool instanceof Pair\n          ? ['V2', V2_DEFAULT_FEE_TIER, percent.toSignificant(2)]\n          : ['V3', pool.fee, percent.toSignificant(2)],\n      )\n    }\n  }\n  return poolsUsed\n}\n"
  },
  {
    "path": "packages/frontend/src/state/squeethPool/price.ts",
    "content": "import { Trade } from '@uniswap/router-sdk'\nimport { Currency, CurrencyAmount, Fraction, Percent, TradeType } from '@uniswap/sdk-core'\nimport { Pair } from '@uniswap/v2-sdk'\nimport { FeeAmount } from '@uniswap/v3-sdk'\nimport JSBI from 'jsbi'\n\nconst BIPS_BASE = JSBI.BigInt(10000)\nconst ALLOWED_PRICE_IMPACT_HIGH = new Percent(JSBI.BigInt(500), BIPS_BASE) // 5%\nconst ALLOWED_PRICE_IMPACT_LOW = new Percent(JSBI.BigInt(100), BIPS_BASE) // 1%\nconst ALLOWED_PRICE_IMPACT_MEDIUM = new Percent(JSBI.BigInt(500), BIPS_BASE) // 5%\nconst BLOCKED_PRICE_IMPACT_NON_EXPERT = new Percent(JSBI.BigInt(1500), BIPS_BASE) // 15%\nconst ONE_HUNDRED_PERCENT = new Percent('1')\nconst ZERO_PERCENT = new Percent('0')\n\nconst THIRTY_BIPS_FEE = new Percent(JSBI.BigInt(30), JSBI.BigInt(10000))\nconst INPUT_FRACTION_AFTER_FEE = ONE_HUNDRED_PERCENT.subtract(THIRTY_BIPS_FEE)\n\nexport function computeRealizedPriceImpact(trade: Trade<Currency, Currency, TradeType>): Percent {\n  const realizedLpFeePercent = computeRealizedLPFeePercent(trade)\n  return trade.priceImpact.subtract(realizedLpFeePercent)\n}\n\nexport function getPriceImpactWarning(priceImpact?: Percent): 'warning' | 'error' | undefined {\n  if (priceImpact?.greaterThan(ALLOWED_PRICE_IMPACT_HIGH)) return 'error'\n  if (priceImpact?.greaterThan(ALLOWED_PRICE_IMPACT_MEDIUM)) return 'warning'\n  return\n}\n\n// computes realized lp fee as a percent\nexport function computeRealizedLPFeePercent(trade: Trade<Currency, Currency, TradeType>): Percent {\n  let percent: Percent\n\n  // Since routes are either all v2 or all v3 right now, calculate separately\n  if (trade.swaps[0].route.pools instanceof Pair) {\n    // for each hop in our trade, take away the x*y=k price impact from 0.3% fees\n    // e.g. for 3 tokens/2 hops: 1 - ((1 - .03) * (1-.03))\n    percent = ONE_HUNDRED_PERCENT.subtract(\n      trade.swaps.reduce<Percent>(\n        (currentFee: Percent): Percent => currentFee.multiply(INPUT_FRACTION_AFTER_FEE),\n        ONE_HUNDRED_PERCENT\n      )\n    )\n  } else {\n    percent = ZERO_PERCENT\n    for (const swap of trade.swaps) {\n      const { numerator, denominator } = swap.inputAmount.divide(trade.inputAmount)\n      const overallPercent = new Percent(numerator, denominator)\n\n      const routeRealizedLPFeePercent = overallPercent.multiply(\n        ONE_HUNDRED_PERCENT.subtract(\n          swap.route.pools.reduce<Percent>((currentFee: Percent, pool): Percent => {\n            const fee =\n              pool instanceof Pair\n                ? // not currently possible given protocol check above, but not fatal\n                  FeeAmount.MEDIUM\n                : pool.fee\n            return currentFee.multiply(ONE_HUNDRED_PERCENT.subtract(new Fraction(fee, 1_000_000)))\n          }, ONE_HUNDRED_PERCENT)\n        )\n      )\n\n      percent = percent.add(routeRealizedLPFeePercent)\n    }\n  }\n\n  return new Percent(percent.numerator, percent.denominator)\n}\n\n// computes price breakdown for the trade\nexport function computeRealizedLPFeeAmount(\n  trade?: Trade<Currency, Currency, TradeType> | null\n): CurrencyAmount<Currency> | undefined {\n  if (trade) {\n    const realizedLPFee = computeRealizedLPFeePercent(trade)\n\n    // the amount of the input that accrues to LPs\n    return CurrencyAmount.fromRawAmount(trade.inputAmount.currency, trade.inputAmount.multiply(realizedLPFee).quotient)\n  }\n\n  return undefined\n}\n\nconst IMPACT_TIERS = [\n  BLOCKED_PRICE_IMPACT_NON_EXPERT,\n  ALLOWED_PRICE_IMPACT_HIGH,\n  ALLOWED_PRICE_IMPACT_MEDIUM,\n  ALLOWED_PRICE_IMPACT_LOW,\n]\n\ntype WarningSeverity = 0 | 1 | 2 | 3 | 4\nexport function warningSeverity(priceImpact: Percent | undefined): WarningSeverity {\n  if (!priceImpact) return 4\n  let impact: WarningSeverity = IMPACT_TIERS.length as WarningSeverity\n  for (const impactLevel of IMPACT_TIERS) {\n    if (impactLevel.lessThan(priceImpact)) return impact\n    impact--\n  }\n  return 0\n}"
  },
  {
    "path": "packages/frontend/src/state/trade/atoms.ts",
    "content": "import { atom } from 'jotai'\nimport { atomWithReset } from 'jotai/utils'\nimport BigNumber from 'bignumber.js'\n\nimport { BIG_ZERO, DEFAULT_SLIPPAGE, InputType } from '@constants/index'\nimport { PositionType, TradeType } from '../../types'\nimport { positionTypeAtom } from '../positions/atoms'\n\nconst quoteEmptyState = {\n  amountOut: BIG_ZERO,\n  minimumAmountOut: BIG_ZERO,\n  priceImpact: '0',\n  pools: Array<Array<any>>(),\n}\n\nconst sellCloseEmptyState = {\n  amountIn: BIG_ZERO,\n  maximumAmountIn: BIG_ZERO,\n  priceImpact: '0',\n}\n\nexport const slippageAmountAtom = atom(new BigNumber(DEFAULT_SLIPPAGE))\nexport const tradeTypeAtom = atom(TradeType.LONG)\nexport const tradeLoadingAtom = atom(false)\nexport const tradeSuccessAtom = atom(false)\nexport const tradeCompletedAtom = atomWithReset(false)\nexport const openPositionAtom = atom(0)\nexport const quoteAtom = atomWithReset(quoteEmptyState)\nexport const inputQuoteLoadingAtom = atom(false)\nexport const squeethExposureAtom = atom(0)\nexport const confirmedAmountAtom = atom('0')\nexport const isOpenPositionAtom = atom((get) => {\n  const openPosition = get(openPositionAtom)\n  return openPosition === 0\n})\nexport const inputTypeAtom = atomWithReset(InputType.ETH)\nexport const tradeAmountAtom = atomWithReset('0')\nexport const altTradeAmountAtom = atomWithReset('0')\nexport const inputQuoteAtom = atomWithReset('')\nexport const sellCloseQuoteAtom = atomWithReset(sellCloseEmptyState)\n\nexport const ethTradeAmountAtom = atomWithReset('0')\nexport const sqthTradeAmountAtom = atomWithReset('0')\nexport const transactionHashAtom = atomWithReset('')\n\nexport const actualTradeTypeAtom = atom((get) => {\n  const tradeType = get(tradeTypeAtom)\n  const positionType = get(positionTypeAtom)\n\n  if (tradeType === TradeType.LONG) {\n    if (positionType === PositionType.SHORT) return TradeType.SHORT\n    else return TradeType.LONG\n  } else {\n    if (positionType === PositionType.LONG) return TradeType.LONG\n    else return TradeType.SHORT\n  }\n})\n"
  },
  {
    "path": "packages/frontend/src/state/wallet/apis.ts",
    "content": "import axios from 'axios'\nimport * as Sentry from '@sentry/nextjs'\n\nexport const checkIsValidAddress = async (address: string) => {\n  if (process.env.NODE_ENV === 'development') {\n    return true\n  }\n\n  const { data } = await axios.get<{ valid: boolean }>(`/api/isValidAddress?address=${address}`)\n\n  if (!data.valid) {\n    Sentry.captureMessage(`Risk address ${address} is blocked.`)\n  }\n\n  return data.valid\n}\n\nexport const updateBlockedAddress = async (address: string) => {\n  // if (process.env.NODE_ENV === 'development') {\n  //   return true\n  // }\n\n  const response = await axios.post<{ message: string; visitCount: number }>('/api/updateBlockedAddress', { address })\n  return response.data.visitCount\n}\n\nexport const getAddressStrikeCount = async (address: string) => {\n  const { data } = await axios.get<{ count: number }>(`/api/strikes?address=${address}`)\n  return data.count\n}\n"
  },
  {
    "path": "packages/frontend/src/state/wallet/atoms.ts",
    "content": "import { atom } from 'jotai'\nimport Web3 from 'web3'\nimport { API as NotifyAPI, TransactionData } from 'bnc-notify'\nimport { API } from 'bnc-onboard/dist/src/interfaces'\n\nimport { Networks } from '../../types'\nimport { atomWithReset } from 'jotai/utils'\n\nconst useAlchemy = process.env.NEXT_PUBLIC_USE_ALCHEMY\nconst usePokt = process.env.NEXT_PUBLIC_USE_POKT\nconst defaultWeb3 =\n  useAlchemy === 'true'\n    ? new Web3(`https://eth-mainnet.alchemyapi.io/v2/${process.env.NEXT_PUBLIC_ALCHEMY_API_KEY}`)\n    : usePokt === 'true'\n    ? new Web3(`https://eth-mainnet.gateway.pokt.network/v1/lb/${process.env.NEXT_PUBLIC_POKT_ID}`)\n    : new Web3(`https://mainnet.infura.io/v3/${process.env.NEXT_PUBLIC_INFURA_API_KEY}`)\n\nexport const transactionDataAtom = atomWithReset<TransactionData | null>(null)\nexport const transactionLoadingAtom = atom((get) => {\n  const transactionData = get(transactionDataAtom)\n\n  if (\n    transactionData?.status === 'sent' ||\n    transactionData?.status === 'pending' ||\n    transactionData?.status === 'speedup' ||\n    transactionData?.status === 'cancel'\n  ) {\n    return true\n  }\n\n  if (transactionData?.status === 'confirmed' || transactionData?.status === 'failed') {\n    return false\n  }\n\n  return false\n})\nexport const cancelTransactionAtom = atomWithReset<boolean>(false)\nexport const addressAtom = atom<string | null>(null)\nexport const networkIdAtom = atom(Networks.MAINNET)\nexport const web3Atom = atom(defaultWeb3)\nexport const onboardAtom = atom<API | null>(null)\nexport const notifyAtom = atom<NotifyAPI | null>(null)\nexport const signerAtom = atom<any>(null)\nexport const supportedNetworkAtom = atom<boolean>(false)\n\nexport const connectedWalletAtom = atom((get) => {\n  const address = get(addressAtom)\n  const networkId = get(networkIdAtom)\n  return Boolean(address && networkId)\n})\n\nexport const isTransactionFirstStepAtom = atom(false)\nexport const onboardAddressAtom = atom<string | null>(null)\nexport const walletFailVisibleAtom = atom(false)\nexport const addressStrikeCountAtom = atom(0)\nexport const isStrikeCountModalOpenAtom = atom(false)\n"
  },
  {
    "path": "packages/frontend/src/state/wallet/hooks.ts",
    "content": "import { useAtom, useAtomValue } from 'jotai'\nimport { useResetAtom, useUpdateAtom } from 'jotai/utils'\nimport BigNumber from 'bignumber.js'\nimport Notify from 'bnc-notify'\nimport Onboard from 'bnc-onboard'\nimport Web3 from 'web3'\nimport { ethers } from 'ethers'\nimport { useQuery, useQueryClient } from 'react-query'\nimport { useRouter } from 'next/router'\n\nimport {\n  onboardAtom,\n  addressAtom,\n  notifyAtom,\n  networkIdAtom,\n  supportedNetworkAtom,\n  signerAtom,\n  web3Atom,\n  transactionDataAtom,\n  transactionLoadingAtom,\n  onboardAddressAtom,\n  walletFailVisibleAtom,\n  addressStrikeCountAtom,\n} from './atoms'\nimport { BIG_ZERO, EtherscanPrefix, TOS_UPDATE_DATE } from '../../constants/'\nimport { Networks } from '../../types'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useApolloClient } from '@apollo/client'\nimport useAppCallback from '@hooks/useAppCallback'\nimport useAppEffect from '@hooks/useAppEffect'\nimport { checkIsValidAddress } from './apis'\nimport { setUserId } from '@amplitude/analytics-browser'\nimport { WALLET_EVENTS } from '@utils/amplitude'\nimport useAmplitude from '@hooks/useAmplitude'\n\nexport const useSelectWallet = () => {\n  const [onboard] = useAtom(onboardAtom)\n  const onboardAddress = useAtomValue(onboardAddressAtom)\n\n  const setWalletFailVisible = useUpdateAtom(walletFailVisibleAtom)\n  const { pathname } = useRouter()\n  const connectWallet = useConnectWallet()\n\n  const onWalletSelect = async () => {\n    if (!onboard) return\n\n    onboard.walletSelect().then(async (success) => {\n      if (success) {\n        // in case connected specifically to zenbull\n        const isZenbullPage = pathname === '/strategies/bull'\n        if (isZenbullPage) {\n          window.localStorage.setItem('walletConnectedToZenbull', 'true')\n        }\n\n        window.localStorage.setItem(TOS_UPDATE_DATE, 'true')\n\n        // if onboard address is invalid\n        if (onboardAddress) {\n          checkIsValidAddress(onboardAddress).then((valid) => {\n            if (valid) {\n              connectWallet(onboardAddress)\n            } else {\n              setWalletFailVisible(true)\n            }\n          })\n        }\n\n        await onboard.walletCheck()\n      }\n    })\n  }\n\n  return onWalletSelect\n}\n\nexport const useConnectWallet = () => {\n  const setAddress = useUpdateAtom(addressAtom)\n  const { track } = useAmplitude()\n\n  const connectWallet = useAppCallback(\n    (address: string) => {\n      setAddress(address)\n      setUserId(address) // analytics\n      track(WALLET_EVENTS.WALLET_CONNECTED, { address: address })\n    },\n    [setAddress, track],\n  )\n\n  return connectWallet\n}\n\nexport const useDisconnectWallet = () => {\n  const [onboard] = useAtom(onboardAtom)\n  const setAddress = useUpdateAtom(addressAtom)\n  const setOnboardAddress = useUpdateAtom(onboardAddressAtom)\n  const setAddressStrikeCount = useUpdateAtom(addressStrikeCountAtom)\n\n  const queryClient = useQueryClient()\n  const apolloClient = useApolloClient()\n\n  const disconnectWallet = () => {\n    if (!onboard) return\n\n    onboard.walletReset()\n    window.localStorage.setItem('walletAddress', '')\n    setAddress(null)\n    setOnboardAddress(null)\n    setAddressStrikeCount(0)\n    queryClient.setQueryData('userWalletBalance', BIG_ZERO)\n    queryClient.removeQueries()\n    apolloClient.clearStore()\n  }\n\n  return disconnectWallet\n}\n\nexport const useHandleTransaction = () => {\n  const [notify] = useAtom(notifyAtom)\n  const [networkId] = useAtom(networkIdAtom)\n  const web3 = useAtomValue(web3Atom)\n  const { refetch } = useWalletBalance()\n  const setTransactionData = useUpdateAtom(transactionDataAtom)\n\n  const handleTransaction = useCallback(\n    (tx: any, onTxConfirmed?: (id?: string) => void) => {\n      if (!notify) return\n\n      tx.on('transactionHash', async (hash: string) => {\n        // Primary Method: Blocknative Notify\n        // This provides real-time transaction updates via websocket, showing transaction stages\n        // (pending, confirmed, failed, etc) with better UX and detailed status info\n        const { emitter } = notify.hash(hash)\n\n        // have to return the emitter object in last order, or the latter emitter object will replace the previous one\n        // if call getbalance in second order, since it has no return, it will show default notification w/o etherscan link\n        emitter.on('all', (transaction) => {\n          if (networkId === Networks.LOCAL) return\n\n          setTransactionData(transaction)\n\n          if (transaction.status === 'confirmed') {\n            if (onTxConfirmed) {\n              onTxConfirmed(hash)\n            }\n            refetch()\n          }\n\n          return {\n            link: `${EtherscanPrefix[networkId]}${transaction.hash}`,\n          }\n        })\n\n        // Fallback Method: Direct Provider Polling\n        // This is a backup in case the websocket connection fails\n        // It uses the provider's built-in waitForTransaction method which polls\n        // for transaction confirmation via standard RPC calls\n        if (!web3?.currentProvider) return\n\n        const provider = new ethers.providers.Web3Provider(web3.currentProvider as any)\n\n        try {\n          // Wait for 1 block confirmation\n          // This acts as a safety net - if Blocknative notify fails to detect confirmation,\n          // this will still catch it and update the UI accordingly\n          const receipt = await provider.waitForTransaction(hash, 1)\n\n          if (receipt.status === 1) {\n            setTransactionData({ status: 'confirmed', hash })\n            if (onTxConfirmed) {\n              onTxConfirmed(hash)\n            }\n            refetch()\n          } else {\n            setTransactionData({ status: 'failed', hash })\n          }\n        } catch (err) {\n          console.error('Transaction failed', err)\n          setTransactionData({ status: 'failed', hash })\n        }\n      })\n\n      return tx\n    },\n    [networkId, notify, refetch, setTransactionData, web3],\n  )\n\n  return handleTransaction\n}\n\nexport const useTransactionStatus = () => {\n  const [txCancelled, setTxCancelled] = useState(false)\n  const transactionData = useAtomValue(transactionDataAtom)\n  const resetTransactionData = useResetAtom(transactionDataAtom)\n  const transactionLoading = useAtomValue(transactionLoadingAtom)\n\n  const confirmed = transactionData?.status === 'confirmed' && !txCancelled\n  const cancelled = transactionData?.status === 'confirmed' && txCancelled\n\n  useEffect(() => {\n    if (transactionData?.status === 'cancel') {\n      setTxCancelled(true)\n    }\n  }, [transactionData?.status])\n\n  return useMemo(\n    () => ({\n      transactionData,\n      confirmed,\n      cancelled,\n      loading: transactionLoading,\n      resetTxCancelled: () => setTxCancelled(false),\n      resetTransactionData,\n    }),\n    [cancelled, confirmed, resetTransactionData, transactionData, transactionLoading],\n  )\n}\n\nconst balanceQueryKeys = {\n  userWalletBalance: (address: string) => ['userWalletBalance', { address }],\n}\nexport const useWalletBalance = () => {\n  const [address] = useAtom(addressAtom)\n  const [web3] = useAtom(web3Atom)\n\n  return useQuery(balanceQueryKeys.userWalletBalance(address ?? ''), () => getBalance(web3, address), {\n    enabled: Boolean(address),\n    refetchInterval: 30000,\n  })\n}\n\nexport const useOnboard = () => {\n  const setSupportedNetwork = useUpdateAtom(supportedNetworkAtom)\n  const [networkId, setNetworkId] = useAtom(networkIdAtom)\n  const [onboard, setOnboard] = useAtom(onboardAtom)\n  const address = useAtomValue(addressAtom)\n  const setOnboardAddress = useUpdateAtom(onboardAddressAtom)\n  const setWeb3 = useUpdateAtom(web3Atom)\n  const setSigner = useUpdateAtom(signerAtom)\n  const setNotify = useUpdateAtom(notifyAtom)\n  const queryClient = useQueryClient()\n  const apolloClient = useApolloClient()\n  const { refetch: refetchWalletBalance } = useWalletBalance()\n\n  const onNetworkChange = useAppCallback(\n    (updateNetwork: number) => {\n      if (updateNetwork in Networks) {\n        setNetworkId(updateNetwork)\n        setSupportedNetwork(true)\n        queryClient.refetchQueries()\n        apolloClient.resetStore()\n        refetchWalletBalance()\n\n        if (onboard !== null) {\n          const network = updateNetwork === 1337 ? 31337 : updateNetwork\n          // localStorage.setItem('networkId', network.toString())\n          onboard.config({\n            networkId: network,\n          })\n        }\n      } else {\n        setSupportedNetwork(false)\n        if (address === null || onboard === null) return\n        onboard.walletCheck()\n        console.log('Unsupported network')\n      }\n    },\n    [setNetworkId, setSupportedNetwork, queryClient, apolloClient, refetchWalletBalance, onboard, address],\n  )\n\n  const onWalletUpdate = useAppCallback(\n    (wallet: any) => {\n      if (wallet.provider) {\n        window.localStorage.setItem('selectedWallet', wallet.name)\n        const provider = new ethers.providers.Web3Provider(wallet.provider)\n        provider.pollingInterval = 30000\n        setWeb3(new Web3(wallet.provider))\n        setSigner(provider.getSigner())\n      }\n    },\n    [setSigner, setWeb3],\n  )\n\n  useAppEffect(() => {\n    const onboard = initOnboard(\n      {\n        address: setOnboardAddress,\n        network: onNetworkChange,\n        wallet: onWalletUpdate,\n      },\n      networkId,\n    )\n\n    setOnboard(onboard)\n    setNotify(initNotify(networkId))\n\n    // removed it for whitelist checking\n    const previouslySelectedWallet = window.localStorage.getItem('selectedWallet')\n\n    if (previouslySelectedWallet && onboard) {\n      onboard.walletSelect(previouslySelectedWallet).then((success) => {\n        console.log('Connected to wallet', success)\n      })\n    }\n  }, [networkId])\n}\nconst useAlchemy = process.env.NEXT_PUBLIC_USE_ALCHEMY\nconst usePokt = process.env.NEXT_PUBLIC_USE_POKT\nexport function initOnboard(subscriptions: any, networkId: Networks) {\n  const network = networkId === 1 ? 'mainnet' : 'ropsten'\n  const RPC_URL =\n    networkId === Networks.LOCAL\n      ? 'http://127.0.0.1:8545/'\n      : networkId === Networks.ARBITRUM_RINKEBY\n      ? 'https://rinkeby.arbitrum.io/rpc'\n      : useAlchemy === 'true'\n      ? `https://eth-${network}.alchemyapi.io/v2/${process.env.NEXT_PUBLIC_ALCHEMY_API_KEY}`\n      : usePokt === 'true'\n      ? `https://eth-${network}.gateway.pokt.network/v1/lb/${process.env.NEXT_PUBLIC_POKT_ID}`\n      : `https://${network}.infura.io/v3/${process.env.NEXT_PUBLIC_INFURA_API_KEY}`\n\n  return Onboard({\n    dappId: process.env.NEXT_PUBLIC_BLOCKNATIVE_DAPP_ID,\n    networkId: networkId,\n    darkMode: true,\n    blockPollingInterval: 30000,\n    subscriptions: subscriptions,\n    walletSelect: {\n      description: `<div>\n          <p> By connecting a wallet, you agree to the Opyn user <a href=\"/terms-of-service\" style=\"color: #2CE6F9;\" target=\"_blank\">Terms of Service</a> and acknowledge that you have read and understand the Opyn <a href=\"/privacy-policy\" style=\"color: #2CE6F9;\" target=\"_blank\">Privacy Policy</a>. Our Terms of Service and Opyn Privacy Policy were last updated on April 20, 2023.</p>\n          </div > `,\n\n      wallets: [\n        { walletName: 'metamask', preferred: true },\n        { walletName: 'coinbase', preferred: true },\n        {\n          walletName: 'walletLink',\n          rpcUrl: RPC_URL,\n          preferred: true,\n        },\n        {\n          walletName: 'walletConnect',\n          preferred: true,\n          rpc: {\n            [networkId]: RPC_URL,\n          },\n        },\n        {\n          walletName: 'lattice',\n          rpcUrl: RPC_URL,\n          preferred: true,\n          appName: 'Opyn V2',\n        },\n        {\n          walletName: 'ledger',\n          preferred: true,\n          rpcUrl: RPC_URL,\n        },\n        {\n          walletName: 'gnosis',\n          appName: 'WalletConnect',\n        },\n      ],\n    },\n    // walletCheck: [networkCheckResult],\n    walletCheck: [\n      { checkName: 'derivationPath' },\n      { checkName: 'connect' },\n      { checkName: 'accounts' },\n      { checkName: 'network' },\n    ],\n  })\n}\n\nexport function initNotify(networkId: Networks) {\n  return Notify({\n    dappId: process.env.NEXT_PUBLIC_BLOCKNATIVE_DAPP_ID, // [String] The API key created by step one above\n    networkId: networkId, // [Integer] The Ethereum network ID your Dapp uses.\n    darkMode: true, // (default: false)\n  })\n}\n\nasync function getBalance(web3: Web3, address: string | null) {\n  try {\n    if (!address) return\n    const balance = await web3.eth.getBalance(address)\n    return new BigNumber(balance)\n  } catch {\n    return new BigNumber(0)\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/styles/index.ts",
    "content": "import useTextStyles from './useTextStyles'\n\nexport { useTextStyles }\n"
  },
  {
    "path": "packages/frontend/src/styles/useTextStyles.ts",
    "content": "import { makeStyles } from '@material-ui/core/styles'\n\nconst useTextStyles = makeStyles({\n  // boldness\n  mediumBold: {\n    fontWeight: 500,\n  },\n\n  // color opacity\n  lightFontColor: {\n    color: 'rgba(255, 255, 255, 0.8)',\n  },\n  lighterFontColor: {\n    color: 'rgba(255, 255, 255, 0.6)',\n  },\n  lightestFontColor: {\n    color: 'rgba(255, 255, 255, 0.5)',\n  },\n\n  // font size\n  smallFont: {\n    fontSize: '15px',\n  },\n  smallerFont: {\n    fontSize: '14px',\n  },\n  smallestFont: {\n    fontSize: '12px',\n  },\n\n  // font family\n  monoFont: {\n    fontFamily: 'DM Mono',\n  },\n})\n\nexport default useTextStyles\n"
  },
  {
    "path": "packages/frontend/src/theme.ts",
    "content": "import { createTheme, ThemeOptions } from '@material-ui/core/styles'\n\nexport enum Mode {\n  LIGHT = 'LIGHT',\n  DARK = 'DARK',\n  NEW_DARK = 'NEW_DARK',\n}\n\nconst getTheme = (mode: Mode) => {\n  const palette = mode === Mode.LIGHT ? lightPalette : mode === Mode.NEW_DARK ? newDarkPalette : darkPalette\n\n  return createTheme({\n    ...palette,\n    breakpoints: {\n      values: {\n        xs: 0,\n        sm: 600,\n        md: 960,\n        lg: 1280,\n        xl: 1920,\n      },\n    },\n    props: {\n      MuiButtonBase: {\n        disableRipple: true,\n      },\n      MuiButtonGroup: {\n        disableRipple: true,\n      },\n    },\n    overrides: {\n      MuiTableCell: {\n        root: {\n          fontSize: '.7rem',\n          padding: '8px',\n          border: 'none',\n        },\n      },\n      MuiCard: {\n        root: {\n          boxShadow: 'none',\n          borderRadius: '10px',\n        },\n      },\n      MuiButton: {\n        root: {\n          borderRadius: '10px',\n          color: '#000',\n          textTransform: 'initial',\n        },\n        text: {\n          color: '#000',\n        },\n      },\n      MuiTooltip: {\n        tooltip: {\n          backgroundColor: '#383838',\n          opacity: '1',\n        },\n      },\n    },\n  })\n}\n\nconst getTypography = (mode: Mode) => {\n  if (mode === Mode.NEW_DARK) {\n    return {\n      fontWeightBold: 500,\n      fontFamily: [\n        'DM Sans',\n        'Open Sans',\n        'Mulish',\n        'Inter',\n        'DM Mono',\n        'Roboto Mono',\n        '-apple-system',\n        'BlinkMacSystemFont',\n        '\"Segoe UI\"',\n        'Roboto',\n        '\"Helvetica Neue\"',\n        'Arial',\n        '\"Segoe UI Emoji\"',\n      ].join(','),\n    }\n  } else {\n    return {\n      fontWeightBold: 500,\n      fontFamily: [\n        'Open Sans',\n        'Mulish',\n        'Inter',\n        'Roboto Mono',\n        '-apple-system',\n        'BlinkMacSystemFont',\n        '\"Segoe UI\"',\n        'Roboto',\n        '\"Helvetica Neue\"',\n        'Arial',\n        '\"Segoe UI Emoji\"',\n      ].join(','),\n    }\n  }\n}\n\nconst lightPalette: ThemeOptions = {\n  typography: getTypography(Mode.LIGHT),\n  palette: {\n    type: 'light',\n    primary: {\n      main: '#4DADF3',\n      contrastText: '#FFFFFF',\n    },\n    secondary: {\n      main: '#00fff9',\n    },\n    error: {\n      light: '#F2F2F2',\n      main: '#EC7987',\n      dark: '#BDBDBD',\n    },\n    warning: {\n      light: '#F5B07326',\n      main: '#F5B073',\n    },\n    success: {\n      main: '#49D273',\n      light: '#B2F0C5',\n    },\n    text: {\n      primary: '#545454',\n    },\n    background: {\n      default: '#F8F8F9',\n      stone: '#DCDAE9',\n      lightStone: '#DCDAE94D',\n      tooltip: '#77757E80',\n    },\n  },\n}\n\nconst darkPalette: ThemeOptions = {\n  typography: getTypography(Mode.DARK),\n  palette: {\n    type: 'dark',\n    primary: {\n      main: '#2CE6F9',\n      contrastText: '#FFFFFF',\n    },\n    secondary: {\n      main: '#00fff9',\n    },\n    error: {\n      main: '#f5475c',\n    },\n    warning: {\n      light: '#F5B07326',\n      main: '#F5B073',\n    },\n    success: {\n      main: '#49D273',\n      light: '#B2F0C5',\n    },\n    background: {\n      stone: 'rgba(255, 255, 255, 0.12)',\n      lightStone: 'rgba(255, 255, 255, 0.08)',\n      tooltip: 'rgba(255, 255, 255)',\n      default: '#181B1C',\n    },\n  },\n}\n\nconst newDarkPalette: ThemeOptions = {\n  typography: getTypography(Mode.NEW_DARK),\n  palette: {\n    type: 'dark',\n    primary: {\n      main: '#70E3F6',\n      light: '#18F5D7',\n      dark: '#0ebcd8', // todo: not sure what this should be since its not specified in figma\n      contrastText: '#FFFFFF',\n    },\n    secondary: {\n      main: '#00fff9',\n    },\n    error: {\n      main: '#FA7B67',\n      light: '#FA7B671a',\n    },\n    warning: {\n      main: '#F3FF6C',\n      light: '#F3FF6C1A',\n    },\n    success: {\n      main: '#67fabf',\n      light: '#67fabf1A',\n    },\n    background: {\n      stone: '#242728',\n      lightStone: '#303436',\n      tooltip: 'rgba(255, 255, 255)',\n      default: '#191B1C',\n    },\n  },\n}\n\nexport default getTheme\n"
  },
  {
    "path": "packages/frontend/src/types/index.ts",
    "content": "import BigNumber from 'bignumber.js'\n\nimport { positions_positions } from '../queries/uniswap/__generated__/positions'\n\ndeclare module '@material-ui/core/styles/createPalette' {\n  interface TypeBackground {\n    stone: string\n    lightStone: string\n    tooltip: string\n  }\n}\n\ndeclare module '@material-ui/core/styles' {\n  interface TypographyVariants {\n    number: React.CSSProperties\n  }\n}\n\n// Update the Typography's variant prop options\ndeclare module '@material-ui/core/Typography' {\n  interface TypographyPropsVariantOverrides {\n    number: true\n  }\n}\n\nexport enum Networks {\n  MAINNET = 1,\n  ROPSTEN = 3,\n  GOERLI = 5,\n  SEPOLIA = 11155111,\n  ARBITRUM_RINKEBY = 421611,\n  LOCAL = 31337,\n}\n\nexport type Vault = {\n  id: number\n  NFTCollateralId: string\n  collateralAmount: BigNumber\n  shortAmount: BigNumber\n  operator: string\n}\n\nexport type NormHistory = {\n  id: string\n  oldNormFactor: string\n  newNormFactor: string\n  lastModificationTimestamp: string\n  timestamp: string\n}\n\nexport enum PositionType {\n  NONE = 'None',\n  LONG = 'Long',\n  SHORT = 'Short',\n}\n\nexport enum TradeType {\n  LONG,\n  SHORT,\n}\n\nexport enum PnLType {\n  Unrealized = 'Unrealized',\n  Realized = 'Realized',\n}\nexport interface NFTManagers extends positions_positions {\n  fees0?: BigNumber\n  fees1?: BigNumber\n  amount0?: BigNumber\n  amount1?: BigNumber\n  dollarValue: BigNumber\n}\n\nexport enum CollateralStatus {\n  SAFE = 'SAFE',\n  RISKY = 'RISKY',\n  DANGER = 'DANGER',\n}\n\nexport enum CrabStrategyTxType {\n  DEPOSIT = 'DEPOSIT',\n  WITHDRAW = 'WITHDRAW',\n  FLASH_DEPOSIT = 'FLASH_DEPOSIT',\n  FLASH_WITHDRAW = 'FLASH_WITHDRAW',\n  HEDGE_ON_UNISWAP = 'HEDGE_ON_UNISWAP',\n  HEDGE = 'HEDGE',\n}\n\nexport enum CrabStrategyV2TxType {\n  DEPOSIT = 'DEPOSIT',\n  WITHDRAW = 'WITHDRAW',\n  WITHDRAW_SHUTDOWN = 'WITHDRAW_SHUTDOWN',\n  FLASH_DEPOSIT = 'FLASH_DEPOSIT',\n  FLASH_WITHDRAW = 'FLASH_WITHDRAW',\n  FLASH_DEPOSIT_CALLBACK = 'FLASH_DEPOSIT_CALLBACK',\n  FLASH_WITHDRAW_CALLBACK = 'FLASH_WITHDRAW_CALLBACK',\n  DEPOSIT_V1 = 'DEPOSIT_V1',\n  OTC_DEPOSIT = 'OTC_DEPOSIT',\n  OTC_WITHDRAW = 'OTC_WITHDRAW',\n}\n\nexport enum BullStrategyTxType {\n  FLASH_DEPOSIT = 'FLASH_DEPOSIT',\n  FLASH_WITHDRAW = 'FLASH_WITHDRAW',\n}\n\nexport enum BullRebalanceType {\n  LEVERAGE_REBALANCE = 'Leverage Rebalance',\n  FULL_REBALANCE = 'Full Rebalance',\n}\n\nexport default class ChartDataInfo {\n  time!: number\n  value!: number\n}\n\nexport enum AuctionType {\n  CRAB_HEDGE,\n  NETTING,\n  CALM_BULL,\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/__tests__/stringifyDeps.test.ts",
    "content": "import stringifyDeps from '@utils/stringifyDeps'\nimport BigNumber from 'bignumber.js'\n\ndescribe('stringifyDeps', () => {\n  it('stringify big number dependency', () => {\n    const result = stringifyDeps([5, 'test', new BigNumber(125), ['a', 'b'], {}])\n\n    expect(result).toEqual([5, 'test', '125', ['a', 'b'], {}])\n  })\n\n  it('stringify array if elements contain id property', () => {\n    const result = stringifyDeps([\n      5,\n      'test',\n      [\n        { id: 3, value: 1228 },\n        { id: 4, value: 1229 },\n      ],\n      ['a', 'b'],\n      {},\n    ])\n\n    expect(result).toEqual([5, 'test', '3,4', ['a', 'b'], {}])\n  })\n\n  it('returns original array if elements do not contain id property', () => {\n    const result = stringifyDeps([\n      5,\n      'test',\n      [\n        { description: 'test', value: 1228 },\n        { descrioption: 'example', value: 1229 },\n      ],\n      ['a', 'b'],\n      {},\n    ])\n\n    expect(result).toEqual([\n      5,\n      'test',\n      [\n        { description: 'test', value: 1228 },\n        { descrioption: 'example', value: 1229 },\n      ],\n      ['a', 'b'],\n      {},\n    ])\n  })\n})\n"
  },
  {
    "path": "packages/frontend/src/utils/amplitude.ts",
    "content": "import { init, track, Types } from '@amplitude/analytics-browser'\n\nconst analyticsEnabled = !!process.env.NEXT_PUBLIC_AMPLITUDE_KEY\n\n// Should be called once before calling track event\nexport const initializeAmplitude = () => {\n  if (!isOptedOut()) return\n\n  if (!process.env.NEXT_PUBLIC_AMPLITUDE_KEY) return\n\n  init(process.env.NEXT_PUBLIC_AMPLITUDE_KEY, undefined, {\n    serverZone: Types.ServerZone.EU,\n    trackingOptions: {\n      deviceManufacturer: false,\n      deviceModel: false,\n      ipAddress: false,\n      osName: true,\n      osVersion: true,\n      platform: true,\n    },\n    attribution: {\n      trackNewCampaigns: true,\n    },\n    serverUrl: '/api/amplitude',\n    disableCookies: true,\n  })\n}\n\nexport const trackEvent = (eventName: string, eventProps?: Record<string, unknown>) => {\n  if (!analyticsEnabled || !isOptedOut()) {\n    console.log(`Analytics: ${eventName}`, JSON.stringify(eventProps))\n    return\n  }\n\n  track(eventName, eventProps)\n}\n\nexport enum BULL_EVENTS {\n  DEPOSIT_BULL_AMOUNT_ENTERED = 'DEPOSIT_BULL_AMOUNT_ENTERED',\n  DEPOSIT_BULL_CLICK = 'DEPOSIT_BULL_CLICK',\n  DEPOSIT_BULL_SUCCESS = 'DEPOSIT_BULL_SUCCESS',\n  DEPOSIT_BULL_FAILED = 'DEPOSIT_BULL_FAILED',\n  DEPOSIT_BULL_REVERT = 'DEPOSIT_BULL_REVERT',\n  WITHDRAW_BULL_AMOUNT_ENTERED = 'WITHDRAW_BULL_AMOUNT_ENTERED',\n  WITHDRAW_BULL_CLICK = 'WITHDRAW_BULL_CLICK',\n  WITHDRAW_BULL_SUCCESS = 'WITHDRAW_BULL_SUCCESS',\n  WITHDRAW_BULL_FAILED = 'WITHDRAW_BULL_FAILED',\n  WITHDRAW_BULL_REVERT = 'WITHDRAW_BULL_REVERT',\n  APPROVE_WITHDRAW_BULL = 'APPROVE_WITHDRAW_BULL',\n  DEPOSIT_BULL_WRONG_GAS = 'DEPOSIT_BULL_WRONG_GAS',\n  WITHDRAW_BULL_WRONG_GAS = 'WITHDRAW_BULL_WRONG_GAS',\n  DEPOSIT_BULL_SET_AMOUNT_MAX = 'DEPOSIT_BULL_SET_AMOUNT_MAX',\n  WITHDRAW_BULL_SET_AMOUNT_MAX = 'WITHDRAW_BULL_SET_AMOUNT_MAX',\n  DEPOSIT_BULL_CHANGE_SLIPPAGE = 'DEPOSIT_BULL_CHANGE_SLIPPAGE',\n  WITHDRAW_BULL_CHANGE_SLIPPAGE = 'WITHDRAW_BULL_CHANGE_SLIPPAGE',\n  EMERGENCY_WITHDRAW_BULL_AMOUNT_ENTERED = 'EMERGENCY_WITHDRAW_BULL_AMOUNT_ENTERED',\n  EMERGENCY_WITHDRAW_BULL_CLICK = 'EMERGENCY_WITHDRAW_BULL_CLICK',\n  EMERGENCY_WITHDRAW_BULL_SUCCESS = 'EMERGENCY_WITHDRAW_BULL_SUCCESS',\n  EMERGENCY_WITHDRAW_BULL_FAILED = 'EMERGENCY_WITHDRAW_BULL_FAILED',\n  EMERGENCY_WITHDRAW_BULL_REVERT = 'EMERGENCY_WITHDRAW_BULL_REVERT',\n  APPROVE_EMERGENCY_WITHDRAW_BULL = 'APPROVE_EMERGENCY_WITHDRAW_BULL',\n  EMERGENCY_WITHDRAW_BULL_WRONG_GAS = 'EMERGENCY_WITHDRAW_BULL_WRONG_GAS',\n  EMERGENCY_WITHDRAW_BULL_SET_AMOUNT_MAX = 'EMERGENCY_WITHDRAW_BULL_SET_AMOUNT_MAX',\n  EMERGENCY_WITHDRAW_BULL_CHANGE_SLIPPAGE = 'EMERGENCY_WITHDRAW_BULL_CHANGE_SLIPPAGE',\n  REDEEM_ZENBULL_CLICK = 'REDEEM_ZENBULL_CLICK',\n  REDEEM_ZENBULL_SUCCESS = 'REDEEM_ZENBULL_SUCCESS',\n  REDEEM_ZENBULL_FAILED = 'REDEEM_ZENBULL_FAILED',\n  APPROVE_ZENBULL_REDEMPTION = 'APPROVE_ZENBULL_REDEMPTION',\n}\n\nexport enum WALLET_EVENTS {\n  WALLET_CONNECTED = 'WALLET_CONNECTED',\n}\n\nexport enum SITE_EVENTS {\n  RELOAD_SITE = 'RELOAD_SITE',\n  NAV_FAQ = 'NAV_FAQ',\n  NAV_AUCTION = 'NAV_AUCTION',\n  NAV_RESEARCH = 'NAV_RESEARCH',\n  CLICK_DISCORD = 'CLICK_DISCORD',\n  CLICK_DOCS = 'CLICK_DOCS',\n  CLICK_TERMS_OF_SERVICE = 'CLICK_TERMS_OF_SERVICE',\n  CLICK_PRIVACY_POLICY = 'CLICK_PRIVACY_POLICY',\n  TOGGLE_COOKIE_CONSENT = 'TOGGLE_COOKIE_CONSENT',\n  CLICK_LEARN_MORE_CRAB = 'CLICK_LEARN_MORE_CRAB',\n  CLICK_LEARN_MORE_BULL = 'CLICK_LEARN_MORE_BULL',\n  SEE_ADVANCED_METRICS_CRAB = 'SEE_ADVANCED_METRICS_CRAB',\n  SEE_ADVANCED_METRICS_BULL = 'SEE_ADVANCED_METRICS_BULL',\n  SUBGRAPH_QUERY_LOADED = 'SUBGRAPH_QUERY_LOADED',\n  SHOW_ERROR_FEEDBACK_POPUP = 'SHOW_ERROR_FEEDBACK_POPUP',\n  CLICK_ERROR_FEEDBACK_ACTION = 'CLICK_ERROR_FEEDBACK_ACTION',\n  CLICK_SHARE_PNL = 'CLICK_SHARE_PNL',\n}\n\nexport enum LANDING_EVENTS {\n  LANDING_VISIT = 'LANDING_VISIT',\n  LANDING_VISIT_MOBILE = 'LANDING_VISIT_MOBILE',\n  LANDING_VISIT_DESKTOP = 'LANDING_VISIT_DESKTOP',\n  NAV_DEVELOPERS = 'NAV_DEVELOPERS',\n  NAV_BLOG = 'NAV_BLOG',\n  NAV_SECURITY = 'NAV_SECURITY',\n  NAV_SOCIAL_TWITTER = 'NAV_SOCIAL_TWITTER',\n  NAV_SOCIAL_GITHUB = 'NAV_SOCIAL_GITHUB',\n  NAV_SOCIAL_DISCORD = 'NAV_SOCIAL_DISCORD',\n  NAV_SOCIAL_MEDIUM = 'NAV_SOCIAL_MEDIUM',\n  NAV_START_EARNING = 'NAV_START_EARNING',\n  NAV_HERO_TOP_START_EARNING = 'NAV_HERO_START_EARNING',\n  NAV_HERO_SQUEETH = 'NAV_HERO_SQUEETH',\n  NAV_HERO_DOWN_START_EARNING = 'NAV_HERO_DOWN_START_EARNING',\n  NAV_HERO_AUCTION = 'NAV_HERO_AUCTION',\n}\n\nexport enum LONG_SQUEETH_EVENTS {\n  APPROVE_LONG_OSQTH_CLICK = 'APPROVE_LONG_OSQTH_CLICK',\n  APPROVE_LONG_OSQTH_SUCCESS = 'APPROVE_LONG_OSQTH_SUCCESS',\n  APPROVE_LONG_OSQTH_FAILED = 'APPROVE_LONG_OSQTH_FAILED',\n  REDEEM_LONG_OSQTH_CLICK = 'REDEEM_LONG_OSQTH_CLICK',\n  REDEEM_LONG_OSQTH_SUCCESS = 'REDEEM_LONG_OSQTH_SUCCESS',\n  REDEEM_LONG_OSQTH_FAILED = 'REDEEM_LONG_OSQTH_FAILED',\n}\n\nexport enum SHORT_SQUEETH_EVENTS {\n  REDEEM_SHORT_OSQTH_CLICK = 'REDEEM_SHORT_OSQTH_CLICK',\n  REDEEM_SHORT_OSQTH_SUCCESS = 'REDEEM_SHORT_OSQTH_SUCCESS',\n  REDEEM_SHORT_OSQTH_FAILED = 'REDEEM_SHORT_OSQTH_FAILED',\n}\n\nexport enum CRAB_EVENTS {\n  DEPOSIT_CRAB_AMOUNT_ENTERED = 'DEPOSIT_CRAB_AMOUNT_ENTERED',\n  DEPOSIT_CRAB_CLICK = 'DEPOSIT_CRAB_CLICK',\n  DEPOSIT_CRAB_SUCCESS = 'DEPOSIT_CRAB_SUCCESS',\n  DEPOSIT_CRAB_REVERT = 'DEPOSIT_CRAB_REVERT',\n  DEPOSIT_CRAB_FAILED = 'DEPOSIT_CRAB_FAILED',\n  DEPOSIT_CRAB_USDC_CLICK = 'DEPOSIT_CRAB_USDC_CLICK',\n  DEPOSIT_CRAB_USDC_SUCCESS = 'DEPOSIT_CRAB_USDC_SUCCESS',\n  DEPOSIT_CRAB_USDC_REVERT = 'DEPOSIT_CRAB_USDC_REVERT',\n  DEPOSIT_CRAB_USDC_FAILED = 'DEPOSIT_CRAB_USDC_FAILED',\n  WITHDRAW_CRAB_USDC_CLICK = 'WITHDRAW_CRAB_USDC_CLICK',\n  WITHDRAW_CRAB_USDC_SUCCESS = 'WITHDRAW_CRAB_USDC_SUCCESS',\n  WITHDRAW_CRAB_USDC_REVERT = 'WITHDRAW_CRAB_USDC_REVERT',\n  WITHDRAW_CRAB_USDC_FAILED = 'WITHDRAW_CRAB_USDC_FAILED',\n  WITHDRAW_CRAB_AMOUNT_ENTERED = 'WITHDRAW_CRAB_AMOUNT_ENTERED',\n  WITHDRAW_CRAB_CLICK = 'WITHDRAW_CRAB_CLICK',\n  WITHDRAW_CRAB_SUCCESS = 'WITHDRAW_CRAB_SUCCESS',\n  WITHDRAW_CRAB_REVERT = 'WITHDRAW_CRAB_REVERT',\n  WITHDRAW_CRAB_FAILED = 'WITHDRAW_CRAB_FAILED',\n  DEPOSIT_STN_CRAB_USDC_CLICK = 'DEPOSIT_STN_CRAB_USDC_CLICK',\n  DEPOSIT_STN_CRAB_USDC_SUCCESS = 'DEPOSIT_STN_CRAB_USDC_SUCCESS',\n  DEPOSIT_STN_CRAB_USDC_REVERT = 'DEPOSIT_STN_CRAB_USDC_REVERT',\n  DEPOSIT_STN_CRAB_USDC_FAILED = 'DEPOSIT_STN_CRAB_USDC_FAILED',\n  CANCEL_DEPOSIT_STN_CRAB_USDC_CLICK = 'CANCEL_DEPOSIT_STN_CRAB_USDC_CLICK',\n  CANCEL_DEPOSIT_STN_CRAB_USDC_SUCCESS = 'CANCEL_DEPOSIT_STN_CRAB_USDC_SUCCESS',\n  CANCEL_DEPOSIT_STN_CRAB_USDC_REJECT = 'CANCEL_DEPOSIT_STN_CRAB_USDC_REJECT',\n  CANCEL_DEPOSIT_STN_CRAB_USDC_FAILED = 'CANCEL_DEPOSIT_STN_CRAB_USDC_FAILED',\n  WITHDRAW_STN_CRAB_USDC_CLICK = 'WITHDRAW_STN_CRAB_USDC_CLICK',\n  WITHDRAW_STN_CRAB_USDC_SUCCESS = 'WITHDRAW_STN_CRAB_USDC_SUCCESS',\n  WITHDRAW_STN_CRAB_USDC_REVERT = 'WITHDRAW_STN_CRAB_USDC_REVERT',\n  WITHDRAW_STN_CRAB_USDC_FAILED = 'WITHDRAW_STN_CRAB_USDC_FAILED',\n  CANCEL_WITHDRAW_STN_CRAB_USDC_CLICK = 'CANCEL_WITHDRAW_STN_CRAB_USDC_CLICK',\n  CANCEL_WITHDRAW_STN_CRAB_USDC_SUCCESS = 'CANCEL_WITHDRAW_STN_CRAB_USDC_SUCCESS',\n  CANCEL_WITHDRAW_STN_CRAB_USDC_REJECT = 'CANCEL_WITHDRAW_STN_CRAB_USDC_REJECT',\n  CANCEL_WITHDRAW_STN_CRAB_USDC_FAILED = 'CANCEL_WITHDRAW_STN_CRAB_USDC_FAILED',\n  USER_FORCE_INSTANT_DEP_CRAB = 'USER_FORCE_INSTANT_DEP_CRAB',\n  USER_FORCE_INSTANT_WIT_CRAB = 'USER_FORCE_INSTANT_WIT_CRAB',\n  APPROVE_DEPOSIT_CRAB_USDC = 'APPROVE_DEPOSIT_CRAB_USDC',\n  APPROVE_DEPOSIT_STN_CRAB_USDC = 'APPROVE_DEPOSIT_STN_CRAB_USDC',\n  APPROVE_WITHDRAW_CRAB_USDC = 'APPROVE_WITHDRAW_CRAB_USDC',\n  APPROVE_WITHDRAW_STN_CRAB_USDC = 'APPROVE_WITHDRAW_STN_CRAB_USDC',\n  DEPOSIT_CRAB_WRONG_GAS = 'DEPOSIT_CRAB_WRONG_GAS',\n  WITHDRAW_CRAB_WRONG_GAS = 'WITHDRAW_CRAB_WRONG_GAS',\n  DEPOSIT_CRAB_SET_AMOUNT_MAX = 'DEPOSIT_CRAB_SET_AMOUNT_MAX',\n  DEPOSIT_CRAB_CHANGE_SLIPPAGE = 'DEPOSIT_CRAB_CHANGE_SLIPPAGE',\n  WITHDRAW_CRAB_SET_AMOUNT_MAX = 'WITHDRAW_CRAB_SET_AMOUNT_MAX',\n  WITHDRAW_CRAB_CHANGE_SLIPPAGE = 'WITHDRAW_CRAB_CHANGE_SLIPPAGE',\n  CLAIM_CRABV2_SUCCESS = 'CLAIM_CRABV2_SUCCESS',\n  CLAIM_CRABV2_FAILED = 'CLAIM_CRABV2_FAILED',\n  APPROVE_CRABV2_SUCCESS = 'APPROVE_CRABV2_SUCCESS',\n  APPROVE_CRABV2_FAILED = 'APPROVE_CRABV2_FAILED',\n  REDEEM_CRABV2_SUCCESS = 'REDEEM_CRABV2_SUCCESS',\n  REDEEM_CRABV2_FAILED = 'REDEEM_CRABV2_FAILED',\n  REDEEM_CRABV2 = 'REDEEM_CRABV2',\n  APPROVE_CRABV1_SUCCESS = 'APPROVE_CRABV1_SUCCESS',\n  APPROVE_CRABV1_FAILED = 'APPROVE_CRABV1_FAILED',\n  REDEEM_CRABV1 = 'REDEEM_CRABV1',\n  REDEEM_CRABV1_SUCCESS = 'REDEEM_CRABV1_SUCCESS',\n  REDEEM_CRABV1_FAILED = 'REDEEM_CRABV1_FAILED',\n}\n\nexport const isOptedOut = async () => {\n  if (!process.env.NEXT_PUBLIC_AMPLITUDE_KEY || typeof window === 'undefined') return false\n  return true\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/apollo-client.ts",
    "content": "import { ApolloClient, InMemoryCache, split, HttpLink, ApolloLink, from } from '@apollo/client'\nimport { getMainDefinition } from '@apollo/client/utilities'\nimport { WebSocketLink } from '@apollo/client/link/ws'\nimport { SITE_EVENTS, trackEvent } from './amplitude'\nimport * as Fathom from 'fathom-client'\n\nconst THE_GRAPH_API_KEYS = {\n  SQUEETH: process.env.NEXT_PUBLIC_THE_GRAPH_SQUEETH_SUBGRAPH_API_KEY,\n  UNISWAP: process.env.NEXT_PUBLIC_THE_GRAPH_UNISWAP_SUBGRAPH_API_KEY,\n}\n\nconst SUBGRAPH_IDS = {\n  UNISWAP_V3: '5zvR82QoaXYFyDEKLZ9t6v9adgnptxYpKpSbxtgVENFV',\n  SQUEETH: '9VC95zuTxcMhXxU25qQkEK2akFzE3eEPiBZGXjGbGcbA',\n}\n\nconst httpLinkMN = new HttpLink({\n  uri: `https://gateway-arbitrum.network.thegraph.com/api/${THE_GRAPH_API_KEYS.UNISWAP}/subgraphs/id/${SUBGRAPH_IDS.UNISWAP_V3}`,\n})\n\nconst httpLinkRP = new HttpLink({\n  uri: 'https://api.thegraph.com/subgraphs/name/kmkoushik/uniswap-v3-ropsten',\n})\n\nconst httpLinkGL = new HttpLink({\n  uri: 'https://api.thegraph.com/subgraphs/name/kmkoushik/uniswap-v3-goerli',\n})\n\nconst httpLinkRPSqueeth = new HttpLink({\n  uri: 'https://api.thegraph.com/subgraphs/name/opynfinance/squeeth-ropsten',\n})\n\nconst httpLinkMNSqueeth = new HttpLink({\n  uri: `https://gateway-arbitrum.network.thegraph.com/api/${THE_GRAPH_API_KEYS.SQUEETH}/subgraphs/id/${SUBGRAPH_IDS.SQUEETH}`,\n  fetch: async (...pl) => {\n    const [_, options] = pl\n    if (options?.body) {\n      const body = JSON.parse(options.body.toString())\n      const startTime = new Date().getTime()\n      const res = await fetch(...pl)\n      const elapsed = new Date().getTime() - startTime\n      trackEvent(SITE_EVENTS.SUBGRAPH_QUERY_LOADED, { query: body.operationName, time: elapsed })\n      Fathom.trackGoal('HPHEK6AI', elapsed) //Track in fathom\n      return res\n    }\n\n    return fetch(...pl)\n  },\n})\n\nconst httpLinkGLSqueeth = new HttpLink({\n  uri: 'https://api.thegraph.com/subgraphs/name/haythem96/squeeth-temp-subgraph',\n})\n\nconst wsLinkRP =\n  typeof window !== 'undefined'\n    ? new WebSocketLink({\n        uri: 'wss://api.thegraph.com/subgraphs/name/kmkoushik/uniswap-v3-ropsten',\n        options: {\n          reconnect: false,\n        },\n      })\n    : null\n\nconst wsLinkMN =\n  typeof window !== 'undefined'\n    ? new WebSocketLink({\n        uri: 'wss://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3',\n        options: {\n          reconnect: false,\n        },\n      })\n    : null\n\nconst wsLinkGL =\n  typeof window !== 'undefined'\n    ? new WebSocketLink({\n        uri: 'wss://api.thegraph.com/subgraphs/name/kmkoushik/uniswap-v3-goerli',\n        options: {\n          reconnect: false,\n        },\n      })\n    : null\n\nconst wsLinkRPSqueeth =\n  typeof window !== 'undefined'\n    ? new WebSocketLink({\n        uri: 'wss://api.thegraph.com/subgraphs/name/opynfinance/squeeth-ropsten',\n        options: {\n          reconnect: false,\n        },\n      })\n    : null\n\nconst wsLinkMNSqueeth =\n  typeof window !== 'undefined'\n    ? new WebSocketLink({\n        uri: 'wss://api.thegraph.com/subgraphs/name/opynfinance/squeeth',\n        options: {\n          reconnect: false,\n        },\n      })\n    : null\n\nconst wsLinkGLSqueeth =\n  typeof window !== 'undefined'\n    ? new WebSocketLink({\n        uri: 'wss://api.thegraph.com/subgraphs/name/haythem96/squeeth-temp-subgraph',\n        options: {\n          reconnect: false,\n        },\n      })\n    : null\n\nconst splitLink = (wsLink: any, httpLink: any) => {\n  return split(\n    ({ query }) => {\n      const definition = getMainDefinition(query)\n      return definition.kind === 'OperationDefinition' && definition.operation === 'subscription'\n    },\n    wsLink,\n    httpLink,\n  )\n}\n\nconst mainnet = new ApolloClient({\n  link: typeof window !== 'undefined' ? splitLink(wsLinkMN, httpLinkMN) : undefined,\n  cache: new InMemoryCache(),\n})\n\nconst ropsten = new ApolloClient({\n  link: typeof window !== 'undefined' ? splitLink(wsLinkRP, httpLinkRP) : undefined,\n  cache: new InMemoryCache(),\n})\n\nconst goerli = new ApolloClient({\n  link: typeof window !== 'undefined' ? splitLink(wsLinkGL, httpLinkGL) : undefined,\n  cache: new InMemoryCache(),\n})\n\nconst sepolia = new ApolloClient({\n  link: typeof window !== 'undefined' ? splitLink(wsLinkGL, httpLinkGL) : undefined,\n  cache: new InMemoryCache(),\n})\n\nexport const uniswapClient = {\n  1: mainnet,\n  3: ropsten,\n  5: goerli,\n  11155111: sepolia,\n  31337: mainnet, // Can be replaced with local graph node if needed\n  421611: mainnet, // Should be replaced with arbitrum subgraph\n}\n\nconst squeethMainnet = new ApolloClient({\n  link: typeof window !== 'undefined' ? ApolloLink.from([splitLink(wsLinkMNSqueeth, httpLinkMNSqueeth)]) : undefined,\n  cache: new InMemoryCache(),\n})\n\nconst squeethRopsten = new ApolloClient({\n  link: typeof window !== 'undefined' ? splitLink(wsLinkRPSqueeth, httpLinkRPSqueeth) : undefined,\n  cache: new InMemoryCache(),\n})\n\nconst squeethGoerli = new ApolloClient({\n  link: typeof window !== 'undefined' ? splitLink(wsLinkGLSqueeth, httpLinkGLSqueeth) : undefined,\n  cache: new InMemoryCache(),\n})\n\nconst squeethSepolia = new ApolloClient({\n  link: typeof window !== 'undefined' ? splitLink(wsLinkGLSqueeth, httpLinkGLSqueeth) : undefined,\n  cache: new InMemoryCache(),\n})\n\nexport const squeethClient = {\n  1: squeethMainnet,\n  3: squeethRopsten,\n  5: squeethGoerli,\n  11155111: squeethSepolia,\n  31337: squeethMainnet, // Can be replaced with local graph node if needed\n  421611: squeethMainnet, // Should be replaced with arbitrum subgraph\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/atomTester.tsx",
    "content": "import { FC, useEffect } from 'react'\nimport { Getter, Setter, Atom, WritableAtom } from 'jotai'\nimport { useAtomCallback } from 'jotai/utils'\n\nlet _get!: Getter\nlet _set!: Setter\n\nexport const Wrapper: FC = ({ children }) => {\n  const initReader = useAtomCallback((get, set) => {\n    _get = get\n    _set = set\n  })\n\n  useEffect(() => {\n    initReader()\n  }, [initReader])\n\n  return <>{children}</>\n}\n\nexport const readAtom = <A extends Atom<any>>(a: A): A extends Atom<infer Data> ? Data : never => _get(a)\n\nexport const writeAtom = <A extends WritableAtom<any, any>>(\n  a: A,\n  update: A extends WritableAtom<any, infer Update> ? Update : never,\n) => a.write(_get, _set, update)\n"
  },
  {
    "path": "packages/frontend/src/utils/calculations.ts",
    "content": "import { Percent } from '@uniswap/sdk-core'\nimport { Pool } from '@uniswap/v3-sdk'\nimport BigNumber from 'bignumber.js'\n\nimport { BIG_ZERO, DEFAULT_SLIPPAGE, ETH_USDC_POOL_FEES, FUNDING_PERIOD, UNI_POOL_FEES } from '../constants'\nimport { CollateralStatus, Networks } from '../types'\n\n/**\n * Converts a raw amount from the blockchain into a more readable format.\n *\n * @param {BigNumber | number | string} amount - The raw amount from the blockchain.\n * @param {number} decimals - The number of decimals the token uses.\n * @returns {BigNumber} The amount in the more readable format.\n */\nexport function toTokenAmount(amount: BigNumber | number | string, decimals: number): BigNumber {\n  return new BigNumber(amount).div(new BigNumber(10).exponentiatedBy(decimals))\n}\n\n/**\n * Converts a readable amount into the raw format that the blockchain understands.\n *\n * @param {BigNumber | number | string} amount - The readable amount.\n * @param {number} decimals - The number of decimals the token uses.\n * @returns {BigNumber} The amount in the raw format that the blockchain understands.\n */\nexport function fromTokenAmount(amount: BigNumber | number | string, decimals: number): BigNumber {\n  return new BigNumber(amount).times(new BigNumber(10).exponentiatedBy(decimals))\n}\n\nexport function inRange(lower: number, upper: number, pool: Pool | undefined): boolean {\n  if (!pool) {\n    return false\n  }\n  return upper > pool?.tickCurrent && pool?.tickCurrent > lower\n}\n\nexport function parseSlippageInput(value: string) {\n  const parsed = Math.floor(Number.parseFloat(value) * 100)\n\n  if (value.length === 0 || !Number.isInteger(parsed) || parsed < 0 || parsed > 5000) {\n    const defaultSlippage = DEFAULT_SLIPPAGE * 100 //Percent(50, 10_000) = 0.5%\n    return new Percent(defaultSlippage, 10_000)\n  } else {\n    return new Percent(parsed, 10_000)\n  }\n}\n\nexport function getCollatPercentStatus(collatPercent: number) {\n  if (collatPercent < 200) return CollateralStatus.DANGER\n  if (collatPercent < 225) return CollateralStatus.RISKY\n  return CollateralStatus.SAFE\n}\n\n/**\n * For the given params it returns breakeven ETH price.\n *\n * Calculation is done with the help of https://docs.google.com/spreadsheets/d/1k1Y_WZ4Of9Prsn5hpHX2BXfdPuUg24X_KBrgYvV8Yw4/edit#gid=0\n */\nexport function getBreakEvenForLongSqueeth(\n  markPrice: BigNumber,\n  indexPrice: BigNumber,\n  normFactor: BigNumber,\n  days: number,\n) {\n  const markToIndexRatio = markPrice.div(indexPrice)\n  const indexToMarkRatio = indexPrice.div(markPrice)\n\n  const newNormFactor = normFactor.toNumber() * Math.pow(indexToMarkRatio.toNumber(), days / FUNDING_PERIOD)\n  console.log(newNormFactor, markToIndexRatio.toString(), toTokenAmount(markPrice, 18).toString())\n  const breakEven = Math.sqrt(toTokenAmount(indexPrice, 18).multipliedBy(normFactor).div(newNormFactor).toNumber())\n  return breakEven\n}\n\nexport function getUSDCPoolFee(network: Networks) {\n  return network === Networks.GOERLI ? UNI_POOL_FEES : ETH_USDC_POOL_FEES\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/cookies.ts",
    "content": "import Cookies from \"js-cookie\"\nimport { initializeAmplitude } from \"./amplitude\"\nimport * as Fathom from 'fathom-client'\n\nconst ACCEPT_COOKIE_FATHOM_EVENT_CODE = 'A4YYBAUT'\nconst REJECT_COOKIE_FATHOM_EVENT_CODE = '6WRWR0XB'\n\nexport enum CookieNames {\n    Consent = 'SqCookieControl',\n}\n\nexport const canStoreCookies = () => {\n    return getCookie(CookieNames.Consent) == 'true' ? true : false \n}\n\nexport const getCookie = (cookieName: string,) => {\n    return Cookies.get(cookieName)\n}\n\nexport const removeCookies = (cookieName?: string,) => {\n    if(cookieName){\n        return Cookies.remove(cookieName)\n    } else {\n        // remove all \n        var cookie = document.cookie.split(';');\n        for (var i = 0; i < cookie.length; i++) {\n            var chip = cookie[i],\n                entry = chip.split(\"=\"),\n                name = entry[0];\n            document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';\n        }\n    }\n}\n\nexport const setCookie = (cookieName: string, identifier: string) => {\n\n    const consent = (identifier == 'true') ? true : false\n    // save to cookie storage\n    Cookies.set(cookieName,identifier, {\n        expires: 365,\n        sameSite:'Strict',\n        path: '/'\n    });\n\n    if(consent){\n        initializeAmplitude()\n    }else {\n        removeCookies()\n    }\n    trackCookieChoice(consent)\n};\n\nexport const trackCookieChoice = (cookieChoice: boolean) => {\n\n    if(cookieChoice){\n        Fathom.trackGoal(ACCEPT_COOKIE_FATHOM_EVENT_CODE, 0)\n    }else {\n        Fathom.trackGoal(REJECT_COOKIE_FATHOM_EVENT_CODE, 0)\n    }\n    \n}\n\n\n"
  },
  {
    "path": "packages/frontend/src/utils/crisp-chat.ts",
    "content": "import { Crisp } from 'crisp-sdk-web'\n\nexport function sendCrispChatMessage(text: string) {\n  Crisp.message.send('text', text)\n}\n\nexport function openCrispChat() {\n  Crisp.chat.open()\n}\n\nexport function hideCrispChat() {\n  Crisp.chat.hide()\n}\n\nexport function showCrispChat() {\n  Crisp.chat.show()\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/csvToJson.ts",
    "content": "export function csvJSON(csv: any) {\n  const lines = csv.split('\\n')\n  const result = []\n  for (let i = 0; i < lines.length; i++) {\n    const currentline = lines[i].split(',').toString().replace(/\\W/g, '').replace(/\\s/g, '').toLowerCase()\n    result.push(currentline)\n  }\n  return JSON.stringify(result)\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/error.ts",
    "content": "type ErrorWithMessage = {\n  message: string\n}\n\nfunction isErrorWithMessage(error: unknown): error is ErrorWithMessage {\n  return (\n    typeof error === 'object' &&\n    error !== null &&\n    'message' in error &&\n    typeof (error as Record<string, unknown>).message === 'string'\n  )\n}\n\nfunction toErrorWithMessage(maybeError: unknown): ErrorWithMessage {\n  if (isErrorWithMessage(maybeError)) return maybeError\n\n  try {\n    return new Error(JSON.stringify(maybeError))\n  } catch {\n    // fallback in case there's an error stringifying the maybeError\n    // like with circular references for example.\n    return new Error(String(maybeError))\n  }\n}\n\nexport function getErrorMessage(error: unknown) {\n  return toErrorWithMessage(error).message\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/ethPriceCharts.ts",
    "content": "const emptyPriceList = [\n  {\n    time: new Date().setUTCMinutes(0, 0, 0),\n    value: 0,\n  },\n]\n\nexport async function getCoingeckoETHPrices(day = 1): Promise<{ time: number; value: number }[]> {\n  try {\n    const url = `https://api.coingecko.com/api/v3/coins/ethereum/market_chart?vs_currency=usd&days=${day}`\n    const response = await fetch(url)\n    const prices = (await response.json()).prices\n    return prices.map(([timestamp, price]: number[]) => {\n      return {\n        time: timestamp / 1000,\n        value: price,\n      }\n    })\n  } catch (error) {\n    return emptyPriceList\n  }\n}\n\nexport async function getCoingeckoETHPricesBetweenTimestamps(\n  fromTs: number,\n  toTs: number,\n): Promise<{ time: number; value: number }[]> {\n  const unixFrom = fromTs / 1000\n  const unixTo = toTs / 1000\n  try {\n    const url = `https://api.coingecko.com/api/v3/coins/ethereum/market_chart/range?vs_currency=usd&from=${unixFrom}&to=${unixTo}`\n    const response = await fetch(url)\n    const prices = (await response.json()).prices\n    return prices.map(([timestamp, price]: number[]) => {\n      return {\n        time: timestamp / 1000,\n        value: price,\n      }\n    })\n  } catch (error) {\n    return emptyPriceList\n  }\n}\n\nexport async function getCUSDCPrices(day = 1): Promise<{ time: number; value: number }[]> {\n  try {\n    const secondsInDay = 24 * 60 * 60\n    const endTime = Math.round(Date.now() / 1000)\n    const startTime = Math.round(endTime - day * secondsInDay)\n    const url = `https://api.compound.finance/api/v2/market_history/graph?asset=0x39aa39c021dfbae8fac545936693ac917d5e7563&min_block_timestamp=${startTime}&max_block_timestamp=${endTime}&num_buckets=${day}`\n    const response = await fetch(url)\n    const prices = (await response.json()).exchange_rates\n\n    const output: any = []\n    for (const i in prices) output[i] = { time: prices[i].block_timestamp, value: prices[i].rate }\n    return output\n  } catch (error) {\n    return emptyPriceList\n  }\n}\n\nexport async function getETH90DaysPrices(): Promise<{ time: number; value: number }[]> {\n  try {\n    const url = `https://api.coingecko.com/api/v3/coins/ethereum/market_chart?vs_currency=usd&days=90`\n    const response = await fetch(url)\n    const prices = (await response.json()).prices\n    return prices.map(([timestamp, price]: number[]) => {\n      return {\n        time: new Date(timestamp).setUTCMinutes(0, 0, 0),\n        value: price,\n      }\n    })\n  } catch (error) {\n    return emptyPriceList\n  }\n}\n\nexport async function getETHWithinOneDayPrices(): Promise<{ time: number; value: number }[]> {\n  try {\n    const url = `https://api.coingecko.com/api/v3/coins/ethereum/market_chart?vs_currency=usd&days=0.999`\n    const response = await fetch(url)\n    const prices = (await response.json()).prices\n    return prices.map(([timestamp, price]: number[]) => {\n      return {\n        time: new Date(timestamp).setUTCSeconds(0, 0),\n        value: price,\n      }\n    })\n  } catch (error) {\n    return emptyPriceList\n  }\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/firestore.ts",
    "content": "import firebase from 'firebase'\n\nconst firebaseConfig = {\n  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,\n  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,\n  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,\n  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,\n  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,\n  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,\n}\n\nconst firebaseApp = !firebase.apps.length ? firebase.initializeApp(firebaseConfig) : firebase.app()\n\nconst db = firebaseApp.firestore()\n\nexport default db\n\nexport const isBlocked = async (address: string) => {\n  const docRef = db.doc(`blocked-addresses/${address}`)\n  const doc = (await docRef.get()).data()\n\n  return doc?.visitCount > 3\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/floatifyBigNums.ts",
    "content": "import BigNumber from 'bignumber.js'\n\n/** Function for helping logging value that includes Big number  */\nexport default function floatifyBigNums(value: any): any {\n  if (value instanceof BigNumber) {\n    return value.toNumber()\n  }\n\n  if (value === null) {\n    return value\n  }\n\n  if (Array.isArray(value)) {\n    return value.map((v) => floatifyBigNums(v))\n  }\n\n  if (typeof value === 'object') {\n    return Object.entries(value).reduce((acc, [k, v]) => {\n      acc[k as any] = floatifyBigNums(v)\n      return acc\n    }, {} as any)\n  }\n\n  return value\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/formatter.ts",
    "content": "import { toTokenAmount } from '@utils/calculations'\nimport BigNumber from 'bignumber.js'\n\nexport const formatCurrency: (number: number, decimals?: number) => string = (number, decimals = 2) => {\n  return number.toLocaleString('en-us', {\n    style: 'currency',\n    currency: 'USD',\n    minimumFractionDigits: decimals,\n    maximumFractionDigits: decimals,\n  })\n}\n\nexport const formatBalance: (number: number) => string = (number) => {\n  return number.toLocaleString(undefined, {\n    minimumFractionDigits: 4,\n    maximumFractionDigits: 4,\n  })\n}\n\nexport const formatNumber: (number: number, decimals?: number) => string = (number, decimals = 2) => {\n  return number.toLocaleString(undefined, { minimumFractionDigits: decimals, maximumFractionDigits: decimals })\n}\n\nexport const formatTokenAmount: (amount: BigNumber | number | string, tokenDecimals: number) => string = (\n  amount,\n  tokenDecimals,\n) => {\n  const tokenAmount = toTokenAmount(amount, tokenDecimals)\n\n  let maximumFractionDigits = 2\n  if (tokenAmount.lte(0.005)) {\n    maximumFractionDigits = 4\n  } else if (tokenAmount.lte(0.05)) {\n    maximumFractionDigits = 3\n  }\n\n  return tokenAmount.toNumber().toLocaleString(undefined, {\n    minimumFractionDigits: 2,\n    maximumFractionDigits,\n  })\n}\n\nexport const truncateText = (text: string, maxLength: number) => {\n  if (text.length <= maxLength) return text\n  return text.slice(0, maxLength) + '...'\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/gasProvider.ts",
    "content": "import {\n  ChainId,\n  EIP1559GasPriceProvider,\n  CachingGasStationProvider,\n  OnChainGasPriceProvider,\n  LegacyGasPriceProvider,\n  GasPrice,\n  NodeJSCache,\n} from '@uniswap/smart-order-router'\nimport { JsonRpcProvider } from '@ethersproject/providers'\nimport NodeCache from 'node-cache'\n\nconst gasPriceProviderMap = new Map()\n\nexport const getGasPriceProvider = (chainId: ChainId) => {\n  if (gasPriceProviderMap.has(chainId)) {\n    return gasPriceProviderMap.get(chainId)\n  }\n\n  const gasPriceCache = new NodeJSCache<GasPrice>(new NodeCache({ stdTTL: 15, useClones: true }))\n  const connectionUrl = `https://eth-mainnet.alchemyapi.io/v2/${process.env.NEXT_PUBLIC_ALCHEMY_API_KEY}`\n  const jsonRpcProvider = new JsonRpcProvider(connectionUrl, chainId)\n\n  const gasPriceProvider = new CachingGasStationProvider(\n    chainId,\n    new OnChainGasPriceProvider(\n      chainId,\n      new EIP1559GasPriceProvider(jsonRpcProvider as any),\n      new LegacyGasPriceProvider(jsonRpcProvider as any),\n    ),\n    gasPriceCache,\n  )\n\n  gasPriceProviderMap.set(chainId, gasPriceProvider)\n\n  return gasPriceProvider\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/getContract.ts",
    "content": "import Web3 from 'web3'\n\nexport const getContract = (web3: Web3, contractAddress: string, abi: any) => {\n  return new web3.eth.Contract(abi as any, contractAddress)\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/index.tsx",
    "content": "export * from './pricer'\n\nexport function getCost(amount: number, price: number) {\n  return amount * price\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/markdown.ts",
    "content": "import fs from 'fs'\nimport path from 'path'\nimport matter from 'gray-matter'\n\nconst markdownDir = path.join(process.cwd(), 'src/markdown')\n\nexport function getMarkdown(file: string) {\n  const filePath = path.join(markdownDir, `${file}.md`)\n  const fileContents = fs.readFileSync(filePath, 'utf8')\n  const markdownData = matter(fileContents)\n\n  return markdownData.content\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/pricer.ts",
    "content": "// import { useNormHistoryFromTime } from '@hooks/useNormHistoryFromTime'\nimport useAppEffect from '@hooks/useAppEffect'\nimport { AuctionType } from '../types'\nimport { useState } from 'react'\nimport db from './firestore'\n\nconst apiKey = process.env.NEXT_PUBLIC_TARDIS_API_KEY as string\n\nconst updateDB = process.env.NEXT_PUBLIC_UPDATE_DB === 'true'\n\nconst omdbBaseUrl = process.env.NEXT_PUBLIC_OMDB_BASE_URL as string\n\nexport function getFairSqueethMarkBefore(price: number, timeElapsedInDay: number, vol: number, power = 2) {\n  const vDaily = vol / Math.sqrt(365)\n  const priceSquare = price ** 2\n  return Math.E ** (((power ** 2 - power) / 2) * (timeElapsedInDay * vDaily ** 2)) * priceSquare\n}\n\nexport function getFairSqueethMarkAfter(price: number, timeElapsedInDay: number, vol: number, power = 2) {\n  return 2 * (getFairSqueethMarkBefore(price, timeElapsedInDay, vol, power) - price ** 2 / 2)\n}\n\n// mock ask\nexport function getFairSqueethAsk(price: number, timeElapsedInDay: number, vol: number, power = 2) {\n  return getFairSqueethMarkAfter(price, timeElapsedInDay, power, vol)\n}\n\n// mock bid\nexport function getFairSqueethBid(price: number, timeElapsedInDay: number, vol: number, power = 2) {\n  return getFairSqueethMarkAfter(price, timeElapsedInDay, vol, power)\n}\n\nexport async function getETHPNLCompounding(ethPrices: { time: number; value: number }[]): Promise<\n  {\n    time: number\n    longPNL: number\n    shortPNL: number\n  }[]\n> {\n  if (ethPrices.length === 0) return []\n  let cumulativeEthLongShortReturn = 0\n  const charts: {\n    time: number\n    longPNL: number\n    shortPNL: number\n  }[] = []\n  for (let i = 0; i < ethPrices.length; i++) {\n    const { value: price, time } = ethPrices[i > 0 ? i : 0]\n    const preEthPrice = ethPrices[i > 0 ? i - 1 : 0].value\n    cumulativeEthLongShortReturn += Math.log(price / preEthPrice)\n\n    const longPNL = Math.round((Math.exp(cumulativeEthLongShortReturn) - 1) * 10000) / 100\n    const shortPNL = Math.round((Math.exp(-cumulativeEthLongShortReturn) - 1) * 10000) / 100\n\n    charts.push({ shortPNL, longPNL, time })\n  }\n\n  return charts\n}\n\nexport async function getSqueethPNLCompounding(\n  ethPrices: { time: number; value: number }[],\n  volMultiplier = 1.2,\n  _collatRatio = 1.5,\n  days = 365,\n): Promise<\n  {\n    time: number\n    longPNL: number\n    shortPNL: number\n  }[]\n> {\n  if (ethPrices.length === 0) return []\n  const volsMap = await getVolMap()\n  let cumulativeSqueethLongReturn = 0\n  let cumulativeSqueethCrabReturn = 1\n  const charts: {\n    time: number\n    longPNL: number\n    shortPNL: number\n  }[] = []\n  // const liquidatedRate = 1.5\n  // const newCR = collatRatio\n  // days > 90 is daily data, 90 >= days is hourly data, 1 > days is 5-minutely data\n  const fundingPeriodMultiplier = days > 90 ? 365 : days > 1 ? 365 * 24 : 356 * 24 * 12\n\n  for (let i = 0; i < ethPrices.length; i++) {\n    const { value: price, time } = ethPrices[i > 0 ? i : 0]\n    const annaulVol = await getVolForTimestampOrDefault(volsMap, time, price)\n    let vol = annaulVol * volMultiplier\n    const preEthPrice = ethPrices[i > 0 ? i - 1 : 0].value\n    let fundingCost = i === 0 ? 0 : (vol / Math.sqrt(fundingPeriodMultiplier)) ** 2\n    //short: -2r - r^2 + f + CR*r, CR=2 equals crab strategy pnl, 2r cancels out\n    //long: 2r +r^2 -f\n    cumulativeSqueethLongReturn += 2 * Math.log(price / preEthPrice) + Math.log(price / preEthPrice) ** 2 - fundingCost\n    // crab return\n    const crabVolMultiplier = 0.9\n    vol = annaulVol * crabVolMultiplier\n    fundingCost = i === 0 ? 0 : (vol / Math.sqrt(fundingPeriodMultiplier)) ** 2\n    const simR = price / preEthPrice - 1\n    cumulativeSqueethCrabReturn *= 1 + -(simR ** 2) + fundingCost\n    const longPNL = Math.round((Math.exp(cumulativeSqueethLongReturn) - 1) * 10000) / 100\n    const shortPNL = Math.round(Math.log(cumulativeSqueethCrabReturn) * 10000) / 100\n\n    charts.push({ shortPNL, longPNL, time })\n  }\n\n  return charts\n}\n\nexport function useETHSqueethPNLCompounding(\n  ethPrices: { time: number; value: number }[],\n  volMultiplier = 1.2,\n  days = 365,\n) {\n  const timestamps = ethPrices.map(({ time }) => time)\n  const [squeethChartData, setSqueethChartData] = useState<\n    { shortPNL: number; longPNL: number; time: number; isLive: boolean }[] | undefined\n  >(undefined)\n  const [ethChartData, setETHChartData] = useState<{ shortPNL: number; longPNL: number; time: number }[] | undefined>(\n    undefined,\n  )\n  // const [timesToFetchNorm, setTimesToFetchNorm] = useState<number[]>([])\n  // const normUpdated = useNormHistoryFromTime(timesToFetchNorm)\n\n  useAppEffect(\n    () => {\n      ;(async () => {\n        let cumulativeSqueethLongReturn = 0\n        let cumulativeSqueethCrabReturn = 1\n        const volsMap = await getVolMap()\n        const liveVolsMap = await getLiveVolMap()\n\n        // const normTimestamps = timestamps.filter((timestamp, index) => {\n        //   const utcDate = new Date(timestamp * 1000).toISOString().split('T')[0]\n        //   return (\n        //     (timestamp >= 1641772800 && !Object.keys(liveVolsMap ?? {}).includes(utcDate)) ||\n        //     index === timestamps.length - 1\n        //   ) // 1641772800 is UTC timestamp for Jan 10(the first date of live VOL) and exclude timestamp of current day as there will be data added\n        // })\n        // setTimesToFetchNorm(normTimestamps)\n\n        if (timestamps.length > 0) {\n          const annualVolData = await Promise.all(\n            timestamps.map(async (timestamp, index) => {\n              const { value: price, time } = ethPrices[index > 0 ? index : 0]\n              const utcDate = new Date(timestamp * 1000).toISOString().split('T')[0]\n              let annualVol = liveVolsMap[utcDate]\n              let isLive = true\n              if (!annualVol) {\n                annualVol = await getVolForTimestampOrDefault(volsMap, time, price)\n                isLive = false\n              }\n\n              return { annualVol, isLive }\n            }),\n          )\n\n          let cumulativeEthLongShortReturn = 0\n\n          const ethCharts = ethPrices.map((ethItem, index) => {\n            const { value: price, time } = ethItem\n            const preEthPrice = ethPrices[index > 0 ? index - 1 : 0].value\n            cumulativeEthLongShortReturn += Math.log(price / preEthPrice)\n\n            const longPNL = Math.round((Math.exp(cumulativeEthLongShortReturn) - 1) * 10000) / 100\n            const shortPNL = Math.round((Math.exp(-cumulativeEthLongShortReturn) - 1) * 10000) / 100\n            return { shortPNL, longPNL, time }\n          })\n          setETHChartData(ethCharts)\n\n          const charts = annualVolData.map((item, index) => {\n            const { annualVol, isLive } = item\n            const { value: price, time } = ethPrices[index > 0 ? index : 0]\n\n            const fundingPeriodMultiplier = days > 90 ? 365 : days > 1 ? 365 * 24 : 356 * 24 * 12\n\n            let vol = annualVol * volMultiplier\n            const preEthPrice = ethPrices[index > 0 ? index - 1 : 0].value\n            let fundingCost = index === 0 ? 0 : (vol / Math.sqrt(fundingPeriodMultiplier)) ** 2\n            cumulativeSqueethLongReturn +=\n              2 * Math.log(price / preEthPrice) + Math.log(price / preEthPrice) ** 2 - fundingCost\n            // crab return\n            const crabVolMultiplier = 0.9\n            vol = annualVol * crabVolMultiplier\n            fundingCost = index === 0 ? 0 : (vol / Math.sqrt(fundingPeriodMultiplier)) ** 2\n            const simR = price / preEthPrice - 1\n            cumulativeSqueethCrabReturn *= 1 + -(simR ** 2) + fundingCost\n            const longPNL = Math.round((Math.exp(cumulativeSqueethLongReturn) - 1) * 10000) / 100\n            const shortPNL = Math.round(Math.log(cumulativeSqueethCrabReturn) * 10000) / 100\n\n            return { shortPNL, longPNL, time, isLive }\n          })\n          setSqueethChartData(charts)\n        }\n      })()\n    },\n    [timestamps, days, ethPrices, volMultiplier],\n    true,\n  )\n  return { ethPNL: ethChartData, squeethPNL: squeethChartData }\n}\n\n/**\n * Convert eth price historical chart to long & short PNL (including funding)\n * @param ethPrices\n */\nexport async function getSqueethChartWithFunding(\n  ethPrices: { time: number; value: number }[],\n  volMultiplier: number,\n  collatRatio = 1.5,\n): Promise<{\n  series: {\n    time: number\n    longPNL: number\n    shortPNL: number\n    positionSize: number\n    fundingPerSqueeth: number\n    timeElapsed: number\n    mark: number\n  }[]\n  accFunding: number\n}> {\n  if (ethPrices.length === 0) return { series: [], accFunding: 0 }\n\n  // let price = squeethPrices[0].value\n  let positionSize = 1\n  let lastTime = ethPrices[0].time\n  let accFunding = 0\n\n  const startPrice = ethPrices[0].value\n  const scale = startPrice\n\n  const charts: {\n    time: number\n    longPNL: number\n    shortPNL: number\n    positionSize: number\n    mark: number\n    fundingPerSqueeth: number\n    timeElapsed: number\n  }[] = []\n\n  const volsMap = await getVolMap()\n\n  for (const { value: price, time } of ethPrices) {\n    const vol = (await getVolForTimestampOrDefault(volsMap, time, price)) * volMultiplier\n\n    const cost = getFairSqueethAsk(startPrice, 0, vol) / scale\n    const premium = getFairSqueethBid(startPrice, 0, vol) / scale\n\n    const timeElapsed = (time - lastTime) / 86400 // time since last action, in day\n    lastTime = time\n\n    const markBefore = getFairSqueethMarkBefore(price, timeElapsed, vol)\n\n    const fundingPerSqueeth = getFunding(price, markBefore)\n\n    const markAfter = getFairSqueethMarkAfter(price, timeElapsed, vol)\n\n    // reduce position size over time, as a funding charge\n    const fundingRatio = 1 - fundingPerSqueeth / markAfter\n    positionSize = positionSize * fundingRatio\n\n    const longPNL = (markAfter * positionSize) / scale - cost\n    const shortPNL = premium - (markAfter * positionSize) / scale + collatRatio * (price - startPrice)\n\n    charts.push({ shortPNL, longPNL, mark: markAfter, positionSize, time, fundingPerSqueeth, timeElapsed })\n\n    accFunding = accFunding + fundingPerSqueeth\n  }\n\n  return { series: charts, accFunding }\n}\n\nfunction getFunding(price: number, mark: number, power = 2) {\n  const index = price ** power\n  return mark - index\n}\n\n/**\n * Get vol from firebase, tardis or default with 1 * multiplier\n * @param timestamp\n * @param ethPrice\n */\nexport async function getVolForTimestamp(\n  timestamp: number,\n  ethPrice: number, // incase we need to query tardis and find ATM iv.\n): Promise<number> {\n  const map = await getVolMap()\n  return await getVolForTimestampOrDefault(map, timestamp, ethPrice)\n}\n\nexport async function getVolForTimestampOrDefault(\n  volsMap: { [key: string]: number | undefined },\n  timestamp: number,\n  ethPrice: number, // incase we need to query tardis and find ATM iv.\n): Promise<number> {\n  const utcDate = new Date(timestamp * 1000).toISOString().split('T')[0]\n  const vol = volsMap[utcDate]\n  if (vol) return vol\n\n  // if vol is not in the map\n\n  // if we're not updating the db, just use 1 * multiplier\n  if (!updateDB) return 1\n\n  // we're updating the db: get value from\n  const iv = await getVolForTimestampFromTardis(timestamp, ethPrice)\n  await updateTimestampVolDB(timestamp, iv)\n  return iv\n}\n\n/**\n * Get vol map object from firestore\n */\nexport async function getVolMap(): Promise<{ [key: string]: number }> {\n  const document = db.doc('squeeth-vol/historical-vol')\n  const doc = await document.get()\n  const data = doc.get('daily-vol')\n  return data\n}\n\nexport async function getLiveVolMap(): Promise<{ [key: string]: number }> {\n  const document = db.doc('squeeth-vol/slive-vol')\n  const doc = await document.get()\n  let data = doc.get('live-vol')\n  if (!data) {\n    await document.set({\n      'live-vol': {},\n    })\n    data = {}\n  }\n  return data\n}\n\nexport async function updateTimestampVolDB(timestamp: number, vol: number): Promise<void> {\n  const utcDate = new Date(timestamp * 1000).toISOString().split('T')[0]\n\n  const document = db.doc('squeeth-vol/historical-vol')\n  const doc = await document.get()\n  const data = doc.get('daily-vol')\n\n  if (Object.keys(data).includes(utcDate)) {\n    console.log(`don't need to update ${utcDate} vol`)\n    return\n  }\n  console.log(`Updating vol for ${utcDate} ${vol}`)\n  const copy = { ...data }\n  copy[utcDate] = Number(vol)\n  await document.set({\n    'daily-vol': copy,\n  })\n}\n\nexport async function updateTimestampLiveVolDB(timestamp: number, vol: number): Promise<void> {\n  const utcDate = new Date(timestamp * 1000).toISOString().split('T')[0]\n\n  const document = db.doc('squeeth-vol/slive-vol')\n  const doc = await document.get()\n  const data = doc.get('live-vol')\n\n  console.log(`Updating live vol for ${utcDate} ${vol}`)\n  const copy = { ...data }\n  copy[utcDate] = Number(vol)\n  await document.set({\n    'live-vol': copy,\n  })\n}\n\nexport async function getVolForTimestampFromTardis(timestamp: number, ethPrice: number) {\n  const utcDate = new Date(timestamp * 1000).toISOString().split('T')[0]\n\n  const domain = 'http://localhost:8010/proxy'\n  const base_url = `${domain}/v1/data-feeds/deribit`\n  const url = `${base_url}?from=${utcDate}&filters=[{\"channel\":\"markprice.options\"}]&offset=0`\n\n  try {\n    const response = await fetch(url, {\n      headers: {\n        Authorization: `Bearer ${apiKey}`,\n      },\n    })\n    if (response.body === null) return 1\n    const text = await response.text()\n    // only get second line (which is ETH at the 0:00 time)\n    const firstLine = text.split('\\n')[1]\n\n    const [, obj] = firstLine.split(' ')\n\n    const data = JSON.parse(obj).params.data\n\n    // find the most ATM option and use its IV.\n    let smallestDiff = Infinity\n    let tempIv = 0\n    for (const option of data) {\n      const { instrument_name, iv } = option as { instrument_name: string; iv: number }\n      const diff = Math.abs(instrumentNameToStrike(instrument_name) - ethPrice)\n      if (diff < smallestDiff) {\n        smallestDiff = diff\n        tempIv = iv\n      }\n    }\n\n    return tempIv\n  } catch (error) {\n    console.log(error)\n    return 1\n  }\n}\n\nfunction instrumentNameToStrike(optionName: string) {\n  return parseInt(optionName.split('-')[2])\n}\n\n/**\n * Todo: fill in logic\n * @param shortAmount\n * @param vol\n * @param ethPrice\n */\nexport function calculateMinCollatReq(shortAmount: number, _vol: number, _ethPrice: number) {\n  return shortAmount\n}\n\n/**\n * Todo: fill in logic\n * @param shortAmount\n * @param collateralAmount\n * @param vol\n * @param ethPrice\n */\nexport function calculateLiquidationPrice(\n  shortAmount: number,\n  collateralAmount: number,\n  vol: number,\n  ethPrice: number,\n) {\n  // mock\n  return (ethPrice * (shortAmount / collateralAmount + 2)) / (shortAmount / collateralAmount + 1)\n}\n\nfunction getEthPrices(startPrice: number, step: number, length: number) {\n  let inc = startPrice\n\n  return Array(length)\n    .fill(0)\n    .map((_, i) => {\n      if (i === 0) return inc\n      inc += step\n      return inc\n    })\n}\n\nexport function getSqueethLongPayOffGraph(ethPrice: number) {\n  const unitPerTrade = 2 / (2 * ethPrice) // Took from the sheet\n  const indexAtTrade = ethPrice ** 2 // Squeeeeeeth\n\n  const getEthPrices = () => {\n    let inc = 0\n    return Array(400)\n      .fill(0)\n      .map((_, i) => {\n        if (i === 0) return inc\n        inc += 20\n        return inc\n      })\n  }\n\n  const getWeightedPrice = (index: number) => {\n    let inc = 0\n    const days = Array(20)\n      .fill(0)\n      .map((_, i) => {\n        if (i === 0) return inc\n        inc += 1\n        return inc\n      })\n    const texps = days.map((d) => d / 365)\n    const weights = days.map((d) => 0.5 ** (1 + d))\n    const prices = texps.map((tx) => {\n      return index * Math.exp(1.44 * tx) // Sigma is 1.2\n    })\n    const weightedPrice = prices.reduce((acc, p, i) => acc + p * weights[i], 0)\n    return weightedPrice\n  }\n\n  const ethPrices = getEthPrices()\n  const markAtTrade = getWeightedPrice(indexAtTrade)\n  const powerPrices = ethPrices.map((p) => (p ** 2 * markAtTrade) / indexAtTrade)\n  const powerTokenPayout = powerPrices.map((p, i) => {\n    return (((unitPerTrade * (powerPrices[i] - markAtTrade)) / ethPrice) * 100).toFixed(0)\n  })\n  const ethPercents = ethPrices.map((p) => (100 * (p / ethPrice - 1)).toFixed(2))\n\n  const twoXLeverage = ethPrices.map((p) => {\n    const res = (((p - ethPrice) * 2) / ethPrice) * 100\n    if (res < -100) return null\n    return Number(res.toFixed(2))\n  })\n\n  const twoXLeverageImaginary = ethPrices.map((p) => {\n    const res = (((p - ethPrice) * 2) / ethPrice) * 100\n    if (res <= -100) return Number(res.toFixed(2))\n    return null\n  })\n\n  return {\n    ethPercents,\n    powerTokenPayout,\n    twoXLeverage,\n    twoXLeverageImaginary,\n  }\n}\n\nexport function getBuyAndLPPayOffGraph(ethPrice: number) {\n  const priceStep = 200\n  const squeethDeposit = 1\n  const squeethMultiplier = 1.1\n  const squeethPrice = squeethMultiplier * ethPrice\n  const ethDeposit = squeethDeposit * squeethPrice\n  const k = squeethDeposit * ethDeposit\n  const dollarToBuy = ethDeposit * ethPrice + squeethDeposit * squeethPrice * ethPrice\n  const eth1p5Lev = (dollarToBuy * 1.5) / ethPrice\n\n  const getEthPrices = () => {\n    let inc = 1000\n    return Array(25)\n      .fill(0)\n      .map((_, i) => {\n        if (i === 0) return inc\n        inc += priceStep\n        return inc\n      })\n  }\n\n  const ethPrices = getEthPrices()\n  const ethPercents = ethPrices.map((p) => (100 * (p / ethPrice - 1)).toFixed(2))\n\n  const lpPayout = ethPrices.map((_ethPrice) => {\n    const _squeethPrice = _ethPrice * squeethMultiplier\n    const _squeethBalance = Math.sqrt(k / _ethPrice)\n    const _ethBalance = k / _squeethBalance\n    const _dollarLp = _squeethBalance * _ethPrice * _squeethPrice + _ethBalance * _ethPrice\n    const _uniswapReturn = _dollarLp - dollarToBuy\n    return ((_uniswapReturn * 100) / dollarToBuy).toFixed(2)\n  })\n\n  const leveragePayout = ethPrices.map((_ethPrice) => {\n    const _levReturn = (_ethPrice - ethPrice) * eth1p5Lev\n    return ((_levReturn * 100) / dollarToBuy).toFixed(2)\n  })\n\n  return { lpPayout, leveragePayout, ethPercents }\n}\n\nexport function getMintAndLpPayoffGraph(ethPrice: number) {\n  const squeethDeposit = 1 // Number taken from sheet :|\n  const squeethMultiplier = 1.031\n  const scalingFactor = 10000\n  const squeethPrice = (ethPrice * squeethMultiplier) / scalingFactor\n  const ethDeposit = squeethDeposit * squeethPrice\n  const k = squeethDeposit * ethDeposit\n  const dollarToMint = (squeethDeposit * ethPrice * 2 * ethPrice) / scalingFactor + ethDeposit * ethPrice\n  const eth1Lev = (dollarToMint * 1) / ethPrice\n  const nf = 1\n  const ethCollatInVault = (squeethDeposit * ethPrice * 2) / scalingFactor\n\n  const ethPrices = getEthPrices(500, 250, 25)\n  const ethPercents = ethPrices.map((p) => (100 * (p / ethPrice - 1)).toFixed(2))\n\n  const leveragePayout = ethPrices.map((_ethPrice) => {\n    const _levReturn = (_ethPrice - ethPrice) * eth1Lev\n    return ((_levReturn * 100) / dollarToMint).toFixed(2)\n  })\n\n  const lpPayout = ethPrices.map((_ethPrice) => {\n    const _squeethPrice = (_ethPrice * squeethMultiplier * nf) / scalingFactor\n    const _squeethBalance = Math.sqrt(k / _squeethPrice)\n    const _ethBalance = k / _squeethBalance\n    const _valueMintAndLp =\n      (_squeethBalance - squeethDeposit) * _squeethPrice * _ethPrice +\n      _ethBalance * _ethPrice +\n      ethCollatInVault * _ethPrice\n    const _uniswapReturn = _valueMintAndLp - dollarToMint\n    return ((_uniswapReturn * 100) / dollarToMint).toFixed(2)\n  })\n\n  return { leveragePayout, ethPercents, lpPayout }\n}\n\nexport const getLongChartData = async (fromTs: number, toTs: number, collatRatio: number, volMultiplier: number) => {\n  const url = `/api/charts/longchart?fromTs=${fromTs}&toTs=${toTs}&collatRatio=${collatRatio}&volMultiplier=${volMultiplier}`\n  const response = await fetch(url)\n  const data = await response.json()\n  return data\n}\n\nexport const getCrabPnlV2ChartData = async (startDateTimestamp: number, endDateTimestamp: number) => {\n  const domain = omdbBaseUrl\n  const base_url = `${domain}/metrics/crabv2?start_timestamp=${startDateTimestamp}&end_timestamp=${endDateTimestamp}`\n  const url = `${base_url}`\n\n  const response = await fetch(url)\n  const data = await response.json()\n  return data\n}\n\nexport const getEthPriceAtHedge = async (type = AuctionType.CRAB_HEDGE) => {\n  const url = `/api/auction/lastHedgeAuction?type=${type}`\n  const response = await fetch(url)\n  const data = await response.json()\n\n  return data?.auction?.ethPrice\n}\n\nexport const getBullChartData = async (startDateTimestamp: number, endDateTimestamp: number) => {\n  const domain = omdbBaseUrl\n  const base_url = `${domain}/metrics/zenbull/pnl/${startDateTimestamp}/${endDateTimestamp}`\n  const url = `${base_url}`\n\n  const response = await fetch(url)\n  const data = await response.json()\n  return data\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/quoter.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { Contract } from 'web3-eth-contract'\n\nexport const getExactIn = async (\n  contract: Contract,\n  tokenIn: string,\n  tokenOut: string,\n  amountIn: BigNumber,\n  poolFee: number,\n  slippage: number,\n) => {\n  const quoteExactInputSingleParams = {\n    tokenIn: tokenIn,\n    tokenOut: tokenOut,\n    amountIn: amountIn.toFixed(0),\n    fee: poolFee,\n    sqrtPriceLimitX96: 0,\n  }\n\n  const quote = await contract.methods.quoteExactInputSingle(quoteExactInputSingleParams).call()\n  const minAmountOut = new BigNumber(quote.amountOut)\n    .times(100 - slippage)\n    .div(100)\n    .toFixed(0)\n  return { ...quote, minAmountOut }\n}\n\nexport const getExactOut = async (\n  contract: Contract,\n  tokenIn: string,\n  tokenOut: string,\n  amountOut: BigNumber,\n  poolFee: number,\n  slippage: number,\n) => {\n  const quoteExactOutputSingleParams = {\n    tokenIn: tokenIn,\n    tokenOut: tokenOut,\n    amount: amountOut.toFixed(0),\n    fee: poolFee,\n    sqrtPriceLimitX96: 0,\n  }\n\n  const quote = await contract.methods.quoteExactOutputSingle(quoteExactOutputSingleParams).call()\n  const maxAmountIn = new BigNumber(quote.amountIn)\n    .times(100 + slippage)\n    .div(100)\n    .toFixed(0)\n  return { ...quote, maxAmountIn }\n}\n"
  },
  {
    "path": "packages/frontend/src/utils/stringifyDeps.ts",
    "content": "import BigNumber from 'bignumber.js'\nimport { DependencyList } from 'react'\n\nexport default function stringifyDeps(deps?: DependencyList, lengthAsArrDep?: boolean) {\n  return deps?.map((dep) => {\n    if (dep instanceof BigNumber) {\n      return dep.toString()\n    }\n\n    if (Array.isArray(dep)) {\n      if (lengthAsArrDep) {\n        return dep.length\n      }\n\n      if (dep.every((item) => item?.hasOwnProperty('id'))) {\n        return dep.map((item) => item.id).join(',')\n      }\n    }\n\n    return dep\n  })\n}\n"
  },
  {
    "path": "packages/frontend/styles/Home.module.css",
    "content": ".container {\n  min-height: 100vh;\n  padding: 0 0.5rem;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  height: 100vh;\n}\n\n.main {\n  padding: 5rem 0;\n  flex: 1;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n}\n\n.footer {\n  width: 100%;\n  height: 100px;\n  border-top: 1px solid #eaeaea;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n}\n\n.footer a {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  flex-grow: 1;\n}\n\n.title a {\n  color: #0070f3;\n  text-decoration: none;\n}\n\n.title a:hover,\n.title a:focus,\n.title a:active {\n  text-decoration: underline;\n}\n\n.title {\n  margin: 0;\n  line-height: 1.15;\n  font-size: 4rem;\n}\n\n.title,\n.description {\n  text-align: center;\n}\n\n.description {\n  line-height: 1.5;\n  font-size: 1.5rem;\n}\n\n.code {\n  background: #fafafa;\n  border-radius: 5px;\n  padding: 0.75rem;\n  font-size: 1.1rem;\n  font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New,\n    monospace;\n}\n\n.grid {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  flex-wrap: wrap;\n  max-width: 800px;\n  margin-top: 3rem;\n}\n\n.card {\n  margin: 1rem;\n  padding: 1.5rem;\n  text-align: left;\n  color: inherit;\n  text-decoration: none;\n  border: 1px solid #eaeaea;\n  border-radius: 10px;\n  transition: color 0.15s ease, border-color 0.15s ease;\n  width: 45%;\n}\n\n.card:hover,\n.card:focus,\n.card:active {\n  color: #0070f3;\n  border-color: #0070f3;\n}\n\n.card h2 {\n  margin: 0 0 1rem 0;\n  font-size: 1.5rem;\n}\n\n.card p {\n  margin: 0;\n  font-size: 1.25rem;\n  line-height: 1.5;\n}\n\n.logo {\n  height: 1em;\n  margin-left: 0.5rem;\n}\n\n@media (max-width: 600px) {\n  .grid {\n    width: 100%;\n    flex-direction: column;\n  }\n}\n"
  },
  {
    "path": "packages/frontend/styles/globals.css",
    "content": "body {\n  padding: 0;\n  margin: 0;\n  font-family: 'Inter', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans,\n    Droid Sans, Helvetica Neue, sans-serif;\n\n  background: #181b1c;\n  /* fallback for old browsers */\n  /* background: -webkit-linear-gradient(to bottom, #3296fa11, #181B1C); \n    background: linear-gradient(to bottom, #3296fa11, #181B1C);  */\n  height: 100vh;\n  background-repeat: no-repeat;\n  background-attachment: fixed;\n  /* overflow: unset !important; */\n}\n\nhtml {\n  padding: 0;\n  margin: 0;\n  background: 'none';\n}\n\nsup {\n  vertical-align: top;\n  font-size: 0.6em;\n}\n\ninput[type='number']::-webkit-inner-spin-button,\ninput[type='number']::-webkit-outer-spin-button {\n  -webkit-appearance: none;\n  margin: 0;\n}\n\ninput[type='number'] {\n  -moz-appearance: textfield;\n}\n\na {\n  color: inherit;\n  text-decoration: none;\n}\n\n* {\n  box-sizing: border-box;\n}\n\n.bn-onboard-custom.bn-onboard-modal {\n  z-index: 99;\n}\n\n.crab-notice {\n  background: linear-gradient(270deg, rgba(32, 202, 26, 0.1), rgba(19, 131, 17, 0.4));\n  background-size: 200% 200%;\n\n  -webkit-animation: AnimationName 8s ease infinite;\n  -moz-animation: AnimationName 8s ease infinite;\n  animation: AnimationName 8s ease infinite;\n}\n\n@-webkit-keyframes AnimationName {\n  0% {\n    background-position: 0% 46%;\n  }\n\n  50% {\n    background-position: 100% 55%;\n  }\n\n  100% {\n    background-position: 0% 46%;\n  }\n}\n\n@-moz-keyframes AnimationName {\n  0% {\n    background-position: 0% 46%;\n  }\n\n  50% {\n    background-position: 100% 55%;\n  }\n\n  100% {\n    background-position: 0% 46%;\n  }\n}\n\n@keyframes AnimationName {\n  0% {\n    background-position: 0% 46%;\n  }\n\n  50% {\n    background-position: 100% 55%;\n  }\n\n  100% {\n    background-position: 0% 46%;\n  }\n}\n\n#rain-front {\n  position: absolute;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 2;\n}\n\n#rain-back {\n  z-index: 1;\n  bottom: 60px;\n  opacity: 0.5;\n}\n\n.drop {\n  position: absolute;\n  bottom: 100%;\n  width: 15px;\n  height: 120px;\n  pointer-events: none;\n  animation: drop 0s linear infinite;\n}\n\n@keyframes drop {\n  0% {\n    transform: translateY(0vh);\n  }\n\n  75% {\n    transform: translateY(90vh);\n  }\n\n  100% {\n    transform: translateY(100vh);\n  }\n}\n\n.stem {\n  width: 1px;\n  height: 60%;\n  margin-left: 7px;\n  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.25));\n  animation: stem 0s linear infinite;\n}\n\n@keyframes stem {\n  0% {\n    opacity: 1;\n  }\n\n  65% {\n    opacity: 1;\n  }\n\n  75% {\n    opacity: 0;\n  }\n\n  100% {\n    opacity: 0;\n  }\n}"
  },
  {
    "path": "packages/frontend/synpress.json",
    "content": "{\n  \"baseUrl\": \"http://localhost:3000\",\n  \"userAgent\": \"synpress\",\n  \"retries\": {\n    \"runMode\": 0,\n    \"openMode\": 0\n  },\n  \"integrationFolder\": \"tests/e2e/specs\",\n  \"screenshotsFolder\": \"tests/e2e/screenshots\",\n  \"videosFolder\": \"tests/e2e/videos\",\n  \"chromeWebSecurity\": true,\n  \"viewportWidth\": 1366,\n  \"viewportHeight\": 768,\n  \"component\": {\n    \"componentFolder\": \".\",\n    \"testFiles\": \"**/*spec.{js,jsx,ts,tsx}\"\n  },\n  \"env\": {\n    \"coverage\": false\n  },\n  \"defaultCommandTimeout\": 30000,\n  \"pageLoadTimeout\": 30000,\n  \"requestTimeout\": 30000\n}"
  },
  {
    "path": "packages/frontend/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"preserve\",\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@apollo/*\": [\"src/apollo/*\"],\n      \"@abis/*\": [\"src/abis/*\"],\n      \"@components/*\": [\"src/components/*\"],\n      \"@constants/*\": [\"src/constants/*\"],\n      \"@context/*\": [\"src/context/*\"],\n      \"@hooks/*\": [\"src/hooks/*\"],\n      \"@pages/*\": [\"src/pages/*\"],\n      \"@styles/*\": [\"src/styles/*\"],\n      \"@types/*\": [\"src/types/*\"],\n      \"@utils/*\": [\"src/utils/*\"],\n      \"@queries/*\": [\"src/queries/*\"],\n      \"@state/*\": [\"src/state/*\"]\n    }\n  },\n\n  \"include\": [\"next-env.d.ts\", \"**/*.ts\", \"**/*.tsx\"],\n  \"exclude\": [\"node_modules\", \"./src/types/global_apollo.ts\"]\n}\n"
  },
  {
    "path": "packages/frontend/types/global_apollo.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n// @generated\n// This file was automatically generated and should not be edited.\n\n//==============================================================\n// START Enums and Input Objects\n//==============================================================\n\nexport enum Action {\n  BURN = \"BURN\",\n  CLOSE_SHORT = \"CLOSE_SHORT\",\n  DEPOSIT_COLLAT = \"DEPOSIT_COLLAT\",\n  LIQUIDATE = \"LIQUIDATE\",\n  MINT = \"MINT\",\n  OPEN_SHORT = \"OPEN_SHORT\",\n  WITHDRAW_COLLAT = \"WITHDRAW_COLLAT\",\n}\n\n//==============================================================\n// END Enums and Input Objects\n//==============================================================\n"
  },
  {
    "path": "packages/hardhat/.eslintrc.js",
    "content": "module.exports = {\n  env: {\n    mocha: true,\n  },\n  extends: [\"airbnb\", \"plugin:prettier/recommended\"],\n  plugins: [\"babel\"],\n  parser: \"@typescript-eslint/parser\",\n  rules: {\n    \"prettier/prettier\": [\"error\"],\n    \"import/extensions\": [\n      \"error\",\n      \"ignorePackages\",\n      {\n        js: \"never\",\n        ts: \"never\",\n      },\n    ],\n    \"import/prefer-default-export\": \"off\",\n    \"prefer-destructuring\": \"off\",\n    \"prefer-template\": \"off\",\n    \"no-console\": \"off\",\n    \"func-names\": \"off\",\n    \"no-unused-expressions\": \"off\",\n    \"no-use-before-define\": \"off\",\n    \"no-await-in-loop\": \"off\",\n    \"no-underscore-dangle\": \"off\",\n    \"no-unused-vars\": \"off\"\n  },\n  ignorePatterns: [\"package.json\", \"contracts/*\", \"tasks/default.ts\"],\n  settings: {\n    \"import/resolver\": {\n      node: {\n        extensions: [\".js\", \".jsx\", \".ts\", \".tsx\"],\n      },\n    },\n  },\n};\n"
  },
  {
    "path": "packages/hardhat/.gitbook.yaml",
    "content": "root: ./\nstructure:\n  readme: README.md\n  summary: SUMMARY.md\n"
  },
  {
    "path": "packages/hardhat/.prettierignore",
    "content": "test\ndeploy\ntasks\n.eslintrc.js\nhardhat.config.ts\n"
  },
  {
    "path": "packages/hardhat/.prettierrc",
    "content": "{\n  \"plugins\": [\"prettier-plugin-solidity\"],\n  \"tabWidth\": 4,\n  \"printWidth\": 120\n}"
  },
  {
    "path": "packages/hardhat/.solcover.js",
    "content": "module.exports = {\n  skipFiles: ['mocks/', 'packages/','interfaces/', 'external/','test/','import/']\n};"
  },
  {
    "path": "packages/hardhat/CHANGE_DATE",
    "content": "2023-01-10"
  },
  {
    "path": "packages/hardhat/LICENSE_BUSL",
    "content": "Business Source License 1.1\n\nLicense text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.\n\n\n\"Business Source License\" is a trademark of MariaDB Corporation Ab.\n\n-----------------------------------------------------------------------------\n\nParameters\nLicensor:            Opyn \nLicensed Work:       Opyn Squeeth Core v1.0\n                     The Licensed Work is (c) 2022 Opyn\n\nAdditional Use Grant: Any uses listed and defined at\nhttps://github.com/opynfinance/squeeth-monorepo/packages/hardhat/USE_GRANT\n\nChange Date:          The earlier of 2023-01-10 or a date specified at\nhttps://github.com/opynfinance/squeeth-monorepo/packages/hardhat/CHANGE_DATE\n\nChange License:       GNU General Public License v2.0 or later\n\n-----------------------------------------------------------------------------\n\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provided that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON\nAN \"AS IS\" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License’s text to license\nyour works, and to refer to it using the trademark \"Business Source License\",\nas long as you comply with the Covenants of Licensor below.\n\n-----------------------------------------------------------------------------\n\nCovenants of Licensor\n\nIn consideration of the right to use this License’s text and the \"Business\nSource License\" name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provided by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n  or a license that is compatible with GPL Version 2.0 or a later version,\n  where \"compatible\" means that software provided under the Change License can\n  be included in a program with software provided under GPL Version 2.0 or a\n  later version. Licensor may specify additional Change Licenses without\n  limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n  impose any additional restriction on the right granted in this License, as\n  the Additional Use Grant; or (b) insert the text \"None\".\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\n\n-----------------------------------------------------------------------------\n\nNotice\n\nThe Business Source License (this document, or the \"License\") is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\n\n"
  },
  {
    "path": "packages/hardhat/README.md",
    "content": "# Squeeth Contracts\n\n[![Coverage Status](https://coveralls.io/repos/github/opynfinance/squeeth-monorepo/badge.svg?t=XrsOxo)](https://coveralls.io/github/opynfinance/squeeth-monorepo) [![CircleCI](https://circleci.com/gh/opynfinance/squeeth-monorepo/tree/master.svg?style=svg&circle-token=5d9ceb617a91160d922e21209489eb3060f326a3)](https://circleci.com/gh/opynfinance/squeeth-monorepo/tree/master)\n\nHere you can find all the contracts that is related to squeeth. To read auto-generated contract doc, you can go to `/docs/contracts-documentation`. \nFor a more comprehensive documentation about how the system works together, we suggest visiting our [GitBook page](https://opyn.gitbook.io/squeeth/)  \n\n# Running this Project\n\nThis project is developed with the **hardhat** framework, which means you can run the following commands directly through `npx hardhat` if you want to be flexible.\n\n## Setting environments\n\n### Mnemonic seed phrase\n\nSome commands (like `deploy`) need a mnemonic seed phrase specified as the tx sender. This will require you to have a `mnemonic.txt` file at the root of this folder, containing the mnemonic seed phrase you want to use to sign the transactions.\n\n### Environment variables\n\nTo deploy contract on testnet or mainnet, you will need to provide a infura key to connect to a infura provider. You can do this easily by changing the `.env.example` file and specify your keys there.\n\nThe `ETHERSCAN_KEY` is useful to verify contracts through command, and the `GAS_REPORT` boolean is something you can turn on to run tests with gas consumption report\n\n## Useful scripts\n\n### Compile\n\n```shell\nyarn compile\n```\n\n### Test\n\nrun test with default hardhat network\n\n```shell\nyarn test\n\n# run a specific test or on a different network\nnpx hardhat test test/unit-tests/controller.ts --network localhost\n\n# Run E2E test\nALCHEMY_KEY=XXXX yarn test:e2e\n```\n\n### Run Coverage test\n\nA coverage report will be available at `/coverage/index.html` after running the following command:\n\n```shell\nyarn coverage\n```\n\n### Deploy\n\nto start deployment on the hardhat localhost network.\n```shell\n# start the local chain\nyarn chain\n\n# deploy on local chain\nyarn deploy\n```\n\nto deploying on testnet, with INFURA_KEY specified as environment variable\n\n```shell\nnpx hardhat deploy --network ropsten\n```\n\n### Lint\n\n```shell\nyarn lint\n```\n\n## Licensing\n\nThe primary license for Squeeth V1 Core is the Business Source License 1.1 (`BUSL-1.1`), see [`LICENSE_BUSL`](./LICENSE_BUSL).\n\n### Exceptions\n- Some files in `contracts/core/` are licensed under `GPL-2.0-or-later` (as indicated in their SPDX headers), see [`contracts/core/LICENSE_GPL_3`](./contracts/core/LICENSE_GPL_3)\n- Some files in `contracts/external/` are licensed under `GPL-3.0-or-later` (as indicated in their SPDX headers), see [`contracts/external/LICENSE_GPL_3`](./contracts/external/LICENSE_GNU)\n- All files in `contracts/interfaces/` are licensed under `MIT` (as indicated in their SPDX headers), see [`contracts/interfaces/LICENSE_MIT`](./contracts/interfaces/LICENSE_MIT)\n- Some files in `contracts/libs/` are licensed under `GPL-2.0-or-later` (as indicated in their SPDX headers), see [`contracts/libs/LICENSE_GPL_3`](./contracts/libraries/LICENSE_GPL_3)\n- Some files in `contracts/libs/` are licensed under `MIT` (as indicated in their SPDX headers), see [`contracts/libs/LICENSE_MIT`](./contracts/libs/LICENSE_MIT)\n- Some files in `contracts/libs/` are licensed under `BSD-4-Clause` (as indicated in their SPDX headers), see [`contracts/libs/LICENSE_BSD`](./contracts/libs/LICENSE_BSD)\n- Some files in `contracts/mocks/` are licensed under `MIT` (as indicated in their SPDX headers), see [`contracts/mocks/LICENSE_MIT`](./contracts/mocks/LICENSE_MIT)\n- Some files in `contracts/mocks/` are licensed under `GPL-2.0-or-later` (as indicated in their SPDX headers), see [`contracts/mocks/LICENSE_GPL_3`](./contracts/mocks/LICENSE_GPL_3)\n- All files in `contracts/periphery/` are licensed under `GPL-2.0-or-later` (as indicated in their SPDX headers), see [`contracts/periphery/LICENSE_GPL_3`](./contracts/periphery/LICENSE_GPL_3)\n- All files in `contracts/import/` are licensed under `GPL-2.0-or-later` (as indicated in their SPDX headers), see [`contracts/periphery/LICENSE_GPL_3`](./contracts/periphery/LICENSE_GPL_3)\n- Some files in `contracts/strategy/` are licensed under `GPL-3.0-only` (as indicated in their SPDX headers), see [`contracts/strategy/LICENSE_GPL_3`](./contracts/strategy/LICENSE_GPL_3)\n- Some files in `contracts/strategy/` are licensed under `AGPL-3.0-only` (as indicated in their SPDX headers), see [`contracts/strategy/LICENSE_AGPL_3`](./contracts/strategy/LICENSE_MIT)\n- Some files in `contracts/test/` are licensed under `GPL-2.0-or-later` (as indicated in their SPDX headers), see [`contracts/strategy/LICENSE_GPL_3`](./contracts/strategy/LICENSE_GPL_3)\n- Some files in `contracts/test/` are licensed under `BSD-4-Clause` (as indicated in their SPDX headers), see [`contracts/test/LICENSE_BSD_4_Clause`](./contracts/test/LICENSE_BSD_4_Clause)\n- Most files in `deploy, deployments, docs, scripts, tasks, test` remain unlicensed (unless indicated in their SPDX headers)."
  },
  {
    "path": "packages/hardhat/SUMMARY.md",
    "content": "# Summary\n* contracts\n  * core\n    * [Controller](docs/contracts-documentation/core/Controller.md)\n    * [Oracle](docs/contracts-documentation/core/Oracle.md)\n    * [ShortPowerPerp](docs/contracts-documentation/core/ShortPowerPerp.md)\n    * [WPowerPerp](docs/contracts-documentation/core/WPowerPerp.md)\n  * libs\n    * [OracleLibrary](docs/contracts-documentation/libs/OracleLibrary.md)\n    * [Power2Base](docs/contracts-documentation/libs/Power2Base.md)\n    * [VaultLib](docs/contracts-documentation/libs/VaultLib.md)\n  * periphery\n    * [ShortHelper](docs/contracts-documentation/periphery/ShortHelper.md)\n  * strategy\n    * [CrabStrategy](docs/contracts-documentation/strategy/CrabStrategy.md)\n    * base\n      * [StrategyBase](docs/contracts-documentation/strategy/base/StrategyBase.md)\n      * [StrategyFlashSwap](docs/contracts-documentation/strategy/base/StrategyFlashSwap.md)\n      * [StrategyMath](docs/contracts-documentation/strategy/base/StrategyMath.md)\n"
  },
  {
    "path": "packages/hardhat/USE_GRANT",
    "content": "\" \""
  },
  {
    "path": "packages/hardhat/arguments/Controller-goerli.js",
    "content": "module.exports = [\"0xf7F94b4607Bcd1235212803bE8fD1B54D1D01b77\",\"0xe85595e810B77cf606D0aFd7eB575BB025323beE\",\"0x9421c968D28DD789363FbD8c9aA5cF2090F0a656\",\"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\"0x306bf03b689f7d7e5e9D3aAC87a068F16AFF9482\",\"0x5d3EfE9157003f05be0d4031F00D43F952d6F6b7\",\"0xC3c29372B5138d48993F0699A129b9EADf5191Bf\",\"0x24a66308bab3BEbC2821480adA395BF1C4ff8Bf2\",\"3000\"]"
  },
  {
    "path": "packages/hardhat/arguments/ControllerHelper-goerli.js",
    "content": "module.exports = [\"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\"0x24a66308bab3BEbC2821480adA395BF1C4ff8Bf2\",\"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\"0x4b62EB6797526491eEf6eF36D3B9960E5d66C394\",\"0x931172BB95549d0f29e10ae2D079ABA3C63318B3\",\"0x356079240635B276A63065478471d89340443C49\"]"
  },
  {
    "path": "packages/hardhat/arguments/CrabHelper-goerli.js",
    "content": "module.exports = [\"0x3fF39f6BF8156bdA997D93E3EFF6904c2bc4481f\",\"0x833A158dA5ceBc44901211427E9Df936023EC0d3\"]"
  },
  {
    "path": "packages/hardhat/arguments/CrabHelper-mainnet.js",
    "content": "module.exports = [\"0x3B960E47784150F5a63777201ee2B15253D713e8\", \"0xE592427A0AEce92De3Edee1F18E0157C05861564\"];\n"
  },
  {
    "path": "packages/hardhat/arguments/CrabMigration-goerli.js",
    "content": "module.exports = [\"0xF8bE62935C282E0Ec32c1B2A0920C048b9C0e2DA\",\"0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6\",\"0x4b62EB6797526491eEf6eF36D3B9960E5d66C394\",\"0x3CbBCf7411F5090E7A33A42d4aeC66d108d96430\",\"0x931172BB95549d0f29e10ae2D079ABA3C63318B3\"]"
  },
  {
    "path": "packages/hardhat/arguments/CrabMigration-mainnet.js",
    "content": "module.exports = [\"0xf205ad80BB86ac92247638914265887A8BAa437D\",\"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\",\"0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80\",\"0x62e28f054efc24b26A794F5C1249B6349454352C\",\"0x27182842E098f60e3D576794A5bFFb0777E025d3\"]"
  },
  {
    "path": "packages/hardhat/arguments/CrabMigration-ropsten.js",
    "content": "module.exports = [\"0xbffBD99cFD9d77c49595dFe8eB531715906ca4Cf\",\"0xc778417e063141139fce010982780140aa0cd5ab\",\"0xF7B8611008Ed073Ef348FE130671688BBb20409d\",\"0x682b4c36a6D4749Ced8C3abF47AefDFC57A17754\",\"0xfC3DD73e918b931be7DEfd0cc616508391bcc001\"]"
  },
  {
    "path": "packages/hardhat/arguments/CrabStrategy-goerli.js",
    "content": "module.exports = [\"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\"0xf7F94b4607Bcd1235212803bE8fD1B54D1D01b77\",\"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\"0xC3c29372B5138d48993F0699A129b9EADf5191Bf\",\"86400\",\"10000000000000000\",\"3600\",\"950000000000000000\",\"1050000000000000000\"]"
  },
  {
    "path": "packages/hardhat/arguments/CrabStrategyV2-goerli.js",
    "content": "module.exports = [\"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\"0xf7F94b4607Bcd1235212803bE8fD1B54D1D01b77\",\"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\"0xC3c29372B5138d48993F0699A129b9EADf5191Bf\",\"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\"3600\",\"200000000000000000\"]"
  },
  {
    "path": "packages/hardhat/arguments/CrabStrategyV2-mainnet.js",
    "content": "module.exports = [\"0x64187ae08781B09368e6253F9E94951243A493D5\",\"0x65D66c76447ccB45dAf1e8044e918fA786A483A1\",\"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\",\"0x1F98431c8aD98523631AE4a59f267346ea31F984\",\"0x82c427AdFDf2d245Ec51D8046b41c4ee87F0d29C\",\"0x67c083aE303741372F0f321Bf9cAD567CFEFE2DC\",\"0xa1CAB67a4383312718a5799Eaa127906e9d4B19E\",\"3600\",\"200000000000000000\"]"
  },
  {
    "path": "packages/hardhat/arguments/CrabStrategyV2-ropsten.js",
    "content": "module.exports = [\"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\"0xBD9F4bE886653177D22fA9c79FD0DFc41407fC89\",\"0xc778417e063141139fce010982780140aa0cd5ab\",\"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\"0x921c384F79de1BAe96d6f33E3E5b8d0B2B34cb68\",\"0xF15964458bcA1941dE53fBc004BA7842f4783EC6\",\"0xD0fb9d47B5F65d76C6bDf1b9E43a4A2345080B2f\",\"3600\",\"200000000000000000\"]"
  },
  {
    "path": "packages/hardhat/arguments/OpynUsdc-goerli.js",
    "content": "module.exports = [\"OpynUSDC\",\"OpynUSDC\",\"6\"]"
  },
  {
    "path": "packages/hardhat/arguments/OpynWeth-goerli.js",
    "content": "module.exports = [\"OpynWETH\",\"OpynWETH\",\"18\"]"
  },
  {
    "path": "packages/hardhat/arguments/Quoter-goerli.js",
    "content": "module.exports = [\"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\"]"
  },
  {
    "path": "packages/hardhat/arguments/ShortHelper-goerli.js",
    "content": "module.exports = [\"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\"0x833A158dA5ceBc44901211427E9Df936023EC0d3\",\"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\"]"
  },
  {
    "path": "packages/hardhat/arguments/ShortPowerPerp-goerli.js",
    "content": "module.exports = [\"short Squeeth\",\"sSQTH\"]"
  },
  {
    "path": "packages/hardhat/arguments/Timelock-goerli.js",
    "content": "module.exports = [\"0x609FFF64429e2A275a879e5C50e415cec842c629\",\"432000\"]"
  },
  {
    "path": "packages/hardhat/arguments/Timelock-mainnet.js",
    "content": "module.exports = [\"0x609FFF64429e2A275a879e5C50e415cec842c629\",\"432000\"]"
  },
  {
    "path": "packages/hardhat/arguments/Timelock-ropsten.js",
    "content": "module.exports = [\"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\"172800\"]"
  },
  {
    "path": "packages/hardhat/arguments/WPowerPerp-goerli.js",
    "content": "module.exports = [\"Opyn Squeeth\",\"oSQTH\"]"
  },
  {
    "path": "packages/hardhat/arguments.js",
    "content": "module.exports = [\n    \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n    \"0x8c7C1F786dA4DEe7d4bB49697A9B0C0c8Fb328e0\",\n    \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n    \"0xF7B8611008Ed073Ef348FE130671688BBb20409d\",\n    \"0xfC3DD73e918b931be7DEfd0cc616508391bcc001\",\n    \"0x682b4c36a6D4749Ced8C3abF47AefDFC57A17754\"\n];\n"
  },
  {
    "path": "packages/hardhat/ci/e2e.sh",
    "content": "#!/bin/bash\n\n# TO RUN: execute in packages/hardhat dir: INFURA_KEY=key ./ci/e2e.sh\n\necho \"Starting E2E mainnet fork tests\"\necho \"Using the current Infura key: \" $INFURA_KEY\n\n$(npm bin)/hardhat node --fork https://mainnet.infura.io/v3/$INFURA_KEY --fork-block-number 14345140 --no-deploy --network hardhat > /dev/null 2>&1 & sleep 10 && MAINNET_FORK=true $(npm bin)/hardhat test ./test/e2e/**.ts "
  },
  {
    "path": "packages/hardhat/contracts/core/Controller.sol",
    "content": "//SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport {INonfungiblePositionManager} from \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\";\nimport {IWETH9} from \"../interfaces/IWETH9.sol\";\nimport {IWPowerPerp} from \"../interfaces/IWPowerPerp.sol\";\nimport {IShortPowerPerp} from \"../interfaces/IShortPowerPerp.sol\";\nimport {IOracle} from \"../interfaces/IOracle.sol\";\nimport {IERC721Receiver} from \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\";\n\n//contract\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\n//lib\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\nimport {ABDKMath64x64} from \"../libs/ABDKMath64x64.sol\";\nimport {VaultLib} from \"../libs/VaultLib.sol\";\nimport {Uint256Casting} from \"../libs/Uint256Casting.sol\";\nimport {Power2Base} from \"../libs/Power2Base.sol\";\n\n/**\n *\n * Error\n * C0: Paused\n * C1: Not paused\n * C2: Shutdown\n * C3: Not shutdown\n * C4: Invalid oracle address\n * C5: Invalid shortPowerPerp address\n * C6: Invalid wPowerPerp address\n * C7: Invalid weth address\n * C8: Invalid quote currency address\n * C9: Invalid eth:quoteCurrency pool address\n * C10: Invalid wPowerPerp:eth pool address\n * C11: Invalid Uniswap position manager\n * C12: Can not liquidate safe vault\n * C13: Invalid address\n * C14: Set fee recipient first\n * C15: Fee too high\n * C16: Paused too many times\n * C17: Pause time limit exceeded\n * C18: Not enough paused time has passed\n * C19: Cannot receive eth\n * C20: Not allowed\n * C21: Need full liquidation\n * C22: Dust vault left\n * C23: Invalid nft\n * C24: Invalid state\n * C25: 0 liquidity Uniswap position token\n * C26: Wrong fee tier for NFT deposit\n */\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\n    using SafeMath for uint256;\n    using Uint256Casting for uint256;\n    using ABDKMath64x64 for int128;\n    using VaultLib for VaultLib.Vault;\n    using Address for address payable;\n\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\n    /// @dev system can only be paused for 182 days from deployment\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\n\n    uint256 public constant FUNDING_PERIOD = 420 hours;\n    uint24 public immutable feeTier;\n    uint32 public constant TWAP_PERIOD = 420 seconds;\n\n    //80% of index\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\n    //140% of index\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\n    // 10%\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\n    // 2%\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\n\n    /// @dev basic unit used for calculation\n    uint256 private constant ONE = 1e18;\n\n    address public immutable weth;\n    address public immutable quoteCurrency;\n    address public immutable ethQuoteCurrencyPool;\n    /// @dev address of the powerPerp/weth pool\n    address public immutable wPowerPerpPool;\n    address internal immutable uniswapPositionManager;\n    address public immutable shortPowerPerp;\n    address public immutable wPowerPerp;\n    address public immutable oracle;\n    address public feeRecipient;\n\n    uint256 internal immutable deployTimestamp;\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\n    uint256 public feeRate;\n    /// @dev the settlement price for each wPowerPerp for settlement\n    uint256 public indexForSettlement;\n\n    uint256 public pausesLeft = 4;\n    uint256 public lastPauseTime;\n\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\n    uint128 public normalizationFactor;\n    uint128 public lastFundingUpdateTimestamp;\n\n    bool internal immutable isWethToken0;\n    bool public isShutDown;\n    bool public isSystemPaused;\n\n    /// @dev vault data storage\n    mapping(uint256 => VaultLib.Vault) public vaults;\n\n    /// Events\n    event OpenVault(address sender, uint256 vaultId);\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\n    event ReduceDebt(\n        address sender,\n        uint256 vaultId,\n        uint256 ethRedeemed,\n        uint256 wPowerPerpRedeemed,\n        uint256 wPowerPerpBurned,\n        uint256 wPowerPerpExcess,\n        uint256 bounty\n    );\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\n    event NormalizationFactorUpdated(\n        uint256 oldNormFactor,\n        uint256 newNormFactor,\n        uint256 lastModificationTimestamp,\n        uint256 timestamp\n    );\n    event Paused(uint256 pausesLeft);\n    event UnPaused(address unpauser);\n    event Shutdown(uint256 indexForSettlement);\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\n\n    modifier notPaused() {\n        require(!isSystemPaused, \"C0\");\n        _;\n    }\n\n    modifier isPaused() {\n        require(isSystemPaused, \"C1\");\n        _;\n    }\n\n    modifier notShutdown() {\n        require(!isShutDown, \"C2\");\n        _;\n    }\n\n    modifier isShutdown() {\n        require(isShutDown, \"C3\");\n        _;\n    }\n\n    /**\n     * @notice constructor\n     * @param _oracle oracle address\n     * @param _shortPowerPerp ERC721 token address representing the short position\n     * @param _wPowerPerp ERC20 token address representing the long position\n     * @param _weth weth address\n     * @param _quoteCurrency quoteCurrency address\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\n     * @param _uniPositionManager uniswap v3 position manager address\n     */\n    constructor(\n        address _oracle,\n        address _shortPowerPerp,\n        address _wPowerPerp,\n        address _weth,\n        address _quoteCurrency,\n        address _ethQuoteCurrencyPool,\n        address _wPowerPerpPool,\n        address _uniPositionManager,\n        uint24 _feeTier\n    ) {\n        require(_oracle != address(0), \"C4\");\n        require(_shortPowerPerp != address(0), \"C5\");\n        require(_wPowerPerp != address(0), \"C6\");\n        require(_weth != address(0), \"C7\");\n        require(_quoteCurrency != address(0), \"C8\");\n        require(_ethQuoteCurrencyPool != address(0), \"C9\");\n        require(_wPowerPerpPool != address(0), \"C10\");\n        require(_uniPositionManager != address(0), \"C11\");\n\n        oracle = _oracle;\n        shortPowerPerp = _shortPowerPerp;\n        wPowerPerp = _wPowerPerp;\n        weth = _weth;\n        quoteCurrency = _quoteCurrency;\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\n        wPowerPerpPool = _wPowerPerpPool;\n        uniswapPositionManager = _uniPositionManager;\n        feeTier = _feeTier;\n        isWethToken0 = _weth < _wPowerPerp;\n\n        normalizationFactor = 1e18;\n        deployTimestamp = block.timestamp;\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\n    }\n\n    /**\n     * ======================\n     * | External Functions |\n     * ======================\n     */\n\n    /**\n     * @notice returns the expected normalization factor, if the funding is paid right now\n     * @dev can be used for on-chain and off-chain calculations\n     */\n    function getExpectedNormalizationFactor() external view returns (uint256) {\n        return _getNewNormalizationFactor();\n    }\n\n    /**\n     * @notice get the index price of the powerPerp, scaled down\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\n     * @dev this is the index price used when calculating funding and for collateralization\n     * @param _period period which you want to calculate twap with\n     * @return index price denominated in $USD, scaled by 1e18\n     */\n    function getIndex(uint32 _period) external view returns (uint256) {\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\n    }\n\n    /**\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\n     * @param _period period which you want to calculate twap with\n     * @return index price denominated in $USD, scaled by 1e18\n     */\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\n    }\n\n    /**\n     * @notice get the expected mark price of powerPerp after funding has been applied\n     * @param _period period of time for the twap in seconds\n     * @return mark price denominated in $USD, scaled by 1e18\n     */\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\n        return\n            Power2Base._getDenormalizedMark(\n                _period,\n                oracle,\n                wPowerPerpPool,\n                ethQuoteCurrencyPool,\n                weth,\n                quoteCurrency,\n                wPowerPerp,\n                _getNewNormalizationFactor()\n            );\n    }\n\n    /**\n     * @notice get the mark price of powerPerp before funding has been applied\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\n     * @param _period period which you want to calculate twap with\n     * @return mark price denominated in $USD, scaled by 1e18\n     */\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\n        return\n            Power2Base._getDenormalizedMark(\n                _period,\n                oracle,\n                wPowerPerpPool,\n                ethQuoteCurrencyPool,\n                weth,\n                quoteCurrency,\n                wPowerPerp,\n                normalizationFactor\n            );\n    }\n\n    /**\n     * @dev return if the vault is properly collateralized\n     * @param _vaultId id of the vault\n     * @return true if the vault is properly collateralized\n     */\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\n        VaultLib.Vault memory vault = vaults[_vaultId];\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\n        return _isVaultSafe(vault, expectedNormalizationFactor);\n    }\n\n    /**\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\n     * @param _vaultId vault to mint wPowerPerp in\n     * @param _powerPerpAmount amount of powerPerp to mint\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\n     * @return vaultId\n     * @return amount of wPowerPerp minted\n     */\n    function mintPowerPerpAmount(\n        uint256 _vaultId,\n        uint256 _powerPerpAmount,\n        uint256 _uniTokenId\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\n    }\n\n    /**\n     * @notice deposit collateral and mint wPowerPerp\n     * @param _vaultId vault to mint wPowerPerp in\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\n     * @return vaultId\n     */\n    function mintWPowerPerpAmount(\n        uint256 _vaultId,\n        uint256 _wPowerPerpAmount,\n        uint256 _uniTokenId\n    ) external payable notPaused nonReentrant returns (uint256) {\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\n        return vaultId;\n    }\n\n    /**\n     * @dev deposit collateral into a vault\n     * @param _vaultId id of the vault\n     */\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\n        _checkCanModifyVault(_vaultId, msg.sender);\n\n        _applyFunding();\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\n\n        _writeVault(_vaultId, cachedVault);\n    }\n\n    /**\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\n     * @param _vaultId id of the vault\n     * @param _uniTokenId uniswap position token id\n     */\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\n        _checkCanModifyVault(_vaultId, msg.sender);\n\n        _applyFunding();\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\n        _writeVault(_vaultId, cachedVault);\n    }\n\n    /**\n     * @notice withdraw collateral from a vault\n     * @param _vaultId id of the vault\n     * @param _amount amount of eth to withdraw\n     */\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\n        _checkCanModifyVault(_vaultId, msg.sender);\n\n        uint256 cachedNormFactor = _applyFunding();\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\n        _checkVault(cachedVault, cachedNormFactor);\n        _writeVault(_vaultId, cachedVault);\n        payable(msg.sender).sendValue(_amount);\n    }\n\n    /**\n     * @notice withdraw uniswap v3 position token from a vault\n     * @param _vaultId id of the vault\n     */\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\n        _checkCanModifyVault(_vaultId, msg.sender);\n\n        uint256 cachedNormFactor = _applyFunding();\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\n        _checkVault(cachedVault, cachedNormFactor);\n        _writeVault(_vaultId, cachedVault);\n    }\n\n    /**\n     * @notice burn wPowerPerp and remove collateral from a vault\n     * @param _vaultId id of the vault\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\n     * @param _withdrawAmount amount of eth to withdraw\n     */\n    function burnWPowerPerpAmount(\n        uint256 _vaultId,\n        uint256 _wPowerPerpAmount,\n        uint256 _withdrawAmount\n    ) external notPaused nonReentrant {\n        _checkCanModifyVault(_vaultId, msg.sender);\n\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\n    }\n\n    /**\n     * @notice burn powerPerp and remove collateral from a vault\n     * @param _vaultId id of the vault\n     * @param _powerPerpAmount amount of powerPerp to burn\n     * @param _withdrawAmount amount of eth to withdraw\n     * @return amount of wPowerPerp burned\n     */\n    function burnPowerPerpAmount(\n        uint256 _vaultId,\n        uint256 _powerPerpAmount,\n        uint256 _withdrawAmount\n    ) external notPaused nonReentrant returns (uint256) {\n        _checkCanModifyVault(_vaultId, msg.sender);\n\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\n    }\n\n    /**\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\n     * @param _vaultId vault containing uniswap v3 position to liquidate\n     */\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\n        _writeVault(_vaultId, cachedVault);\n    }\n\n    /**\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\n     * @param _vaultId target vault\n     */\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\n        _checkCanModifyVault(_vaultId, msg.sender);\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\n\n        _writeVault(_vaultId, cachedVault);\n    }\n\n    /**\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\n     * @dev normally can only liquidate 50% of a vault's debt\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\n     * @param _vaultId vault to liquidate\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\n     * @return amount of wPowerPerp repaid\n     */\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\n        uint256 cachedNormFactor = _applyFunding();\n\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \"C12\");\n\n        // try to save target vault before liquidation by reducing debt\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\n\n        // if vault is safe after saving, pay bounty and return early\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\n            _writeVault(_vaultId, cachedVault);\n            payable(msg.sender).sendValue(bounty);\n            return 0;\n        }\n\n        // add back the bounty amount, liquidators onlly get reward from liquidation\n        cachedVault.addEthCollateral(bounty);\n\n        // if the vault is still not safe after saving, liquidate it\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\n            cachedVault,\n            _maxDebtAmount,\n            cachedNormFactor,\n            msg.sender\n        );\n\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\n\n        _writeVault(_vaultId, cachedVault);\n\n        // pay the liquidator\n        payable(msg.sender).sendValue(collateralPaid);\n\n        return debtAmount;\n    }\n\n    /**\n     * @notice authorize an address to modify the vault\n     * @dev can be revoke by setting address to 0\n     * @param _vaultId id of the vault\n     * @param _operator new operator address\n     */\n    function updateOperator(uint256 _vaultId, address _operator) external {\n        require(\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\n            \"C20\"\n        );\n        vaults[_vaultId].operator = _operator;\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\n    }\n\n    /**\n     * @notice set the recipient who will receive the fee\n     * @dev this should be a contract handling insurance\n     * @param _newFeeRecipient new fee recipient\n     */\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\n        require(_newFeeRecipient != address(0), \"C13\");\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\n        feeRecipient = _newFeeRecipient;\n    }\n\n    /**\n     * @notice set the fee rate when user mints\n     * @dev this function cannot be called if the feeRecipient is still un-set\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\n     */\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\n        require(feeRecipient != address(0), \"C14\");\n        require(_newFeeRate <= 100, \"C15\");\n        emit FeeRateUpdated(feeRate, _newFeeRate);\n        feeRate = _newFeeRate;\n    }\n\n    /**\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\n     * @notice short positions can be redeemed for vault collateral minus value of debt\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\n     */\n    function shutDown() external onlyOwner notShutdown {\n        isSystemPaused = true;\n        isShutDown = true;\n        indexForSettlement = Power2Base._getScaledTwap(\n            oracle,\n            ethQuoteCurrencyPool,\n            weth,\n            quoteCurrency,\n            TWAP_PERIOD,\n            false\n        );\n        emit Shutdown(indexForSettlement);\n    }\n\n    /**\n     * @notice pause the system for up to 24 hours after which any one can unpause\n     * @dev can only be called for 365 days since the contract was launched or 4 times\n     */\n    function pause() external onlyOwner notShutdown notPaused {\n        require(pausesLeft > 0, \"C16\");\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \"C17\");\n        isSystemPaused = true;\n        pausesLeft -= 1;\n        lastPauseTime = block.timestamp;\n\n        emit Paused(pausesLeft);\n    }\n\n    /**\n     * @notice unpause the contract\n     * @dev anyone can unpause the contract after 24 hours\n     */\n    function unPauseAnyone() external isPaused notShutdown {\n        require(block.timestamp > (lastPauseTime + 1 days), \"C18\");\n        isSystemPaused = false;\n        emit UnPaused(msg.sender);\n    }\n\n    /**\n     * @notice unpause the contract\n     * @dev owner can unpause at any time\n     */\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\n        isSystemPaused = false;\n        emit UnPaused(msg.sender);\n    }\n\n    /**\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\n     * @param _wPerpAmount amount of wPowerPerp to burn\n     */\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\n\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\n        payable(msg.sender).sendValue(longValue);\n\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\n    }\n\n    /**\n     * @notice redeem short position when the system is shutdown\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\n     * @param _vaultId vault id\n     */\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\n        _checkCanModifyVault(_vaultId, msg.sender);\n\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n        uint256 cachedNormFactor = normalizationFactor;\n\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\n\n        uint256 debt = Power2Base._getLongSettlementValue(\n            cachedVault.shortAmount,\n            indexForSettlement,\n            cachedNormFactor\n        );\n        // if the debt is more than collateral, this line will revert\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\n\n        // reset the vault but don't burn the nft, just because people may want to keep it\n        cachedVault.shortAmount = 0;\n        cachedVault.collateralAmount = 0;\n        _writeVault(_vaultId, cachedVault);\n\n        payable(msg.sender).sendValue(excess);\n\n        emit RedeemShort(msg.sender, _vaultId, excess);\n    }\n\n    /**\n     * @notice update the normalization factor as a way to pay funding\n     */\n    function applyFunding() external notPaused {\n        _applyFunding();\n    }\n\n    /**\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\n     */\n    function donate() external payable isShutdown {}\n\n    /**\n     * @notice fallback function to accept eth\n     */\n    receive() external payable {\n        require(msg.sender == weth, \"C19\");\n    }\n\n    /**\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\n     * @return returns received selector\n     */\n    function onERC721Received(\n        address,\n        address,\n        uint256,\n        bytes memory\n    ) public virtual override returns (bytes4) {\n        return this.onERC721Received.selector;\n    }\n\n    /*\n     * ======================\n     * | Internal Functions |\n     * ======================\n     */\n\n    /**\n     * @notice check if an address can modify a vault\n     * @param _vaultId the id of the vault to check if can be modified by _account\n     * @param _account the address to check if can modify the vault\n     */\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\n        require(\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\n            \"C20\"\n        );\n    }\n\n    /**\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\n     * @param _account account to receive wPowerPerp\n     * @param _vaultId id of the vault\n     * @param _mintAmount amount to mint\n     * @param _depositAmount amount of eth as collateral\n     * @param _uniTokenId id of uniswap v3 position token\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\n     * @return the minted wPowerPerp amount\n     */\n    function _openDepositMint(\n        address _account,\n        uint256 _vaultId,\n        uint256 _mintAmount,\n        uint256 _depositAmount,\n        uint256 _uniTokenId,\n        bool _isWAmount\n    ) internal returns (uint256, uint256) {\n        uint256 cachedNormFactor = _applyFunding();\n        uint256 depositAmountWithFee = _depositAmount;\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\n        uint256 feeAmount;\n        VaultLib.Vault memory cachedVault;\n\n        // load vault or create new a new one\n        if (_vaultId == 0) {\n            (_vaultId, cachedVault) = _openVault(_account);\n        } else {\n            // make sure we're not accessing an unexistent vault.\n            _checkCanModifyVault(_vaultId, msg.sender);\n            cachedVault = vaults[_vaultId];\n        }\n\n        if (wPowerPerpAmount > 0) {\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\n        }\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\n\n        _checkVault(cachedVault, cachedNormFactor);\n        _writeVault(_vaultId, cachedVault);\n\n        // pay insurance fee\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\n\n        return (_vaultId, wPowerPerpAmount);\n    }\n\n    /**\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\n     * @param _account who should receive collateral\n     * @param _vaultId id of the vault\n     * @param _burnAmount amount of wPowerPerp to burn\n     * @param _withdrawAmount amount of eth collateral to withdraw\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\n     * @return total burned wPowerPower amount\n     */\n    function _burnAndWithdraw(\n        address _account,\n        uint256 _vaultId,\n        uint256 _burnAmount,\n        uint256 _withdrawAmount,\n        bool _isWAmount\n    ) internal returns (uint256) {\n        uint256 cachedNormFactor = _applyFunding();\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\n\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\n        _checkVault(cachedVault, cachedNormFactor);\n        _writeVault(_vaultId, cachedVault);\n\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\n\n        return wBurnAmount;\n    }\n\n    /**\n     * @notice open a new vault\n     * @dev create a new vault and bind it with a new short vault id\n     * @param _recipient owner of new vault\n     * @return id of the new vault\n     * @return new in-memory vault\n     */\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\n\n        VaultLib.Vault memory vault = VaultLib.Vault({\n            NftCollateralId: 0,\n            collateralAmount: 0,\n            shortAmount: 0,\n            operator: address(0)\n        });\n        emit OpenVault(msg.sender, vaultId);\n        return (vaultId, vault);\n    }\n\n    /**\n     * @notice deposit uniswap v3 position token into a vault\n     * @dev this function will update the vault memory in-place\n     * @param _vault the Vault memory to update\n     * @param _account account to transfer the uniswap v3 position from\n     * @param _vaultId id of the vault\n     * @param _uniTokenId uniswap position token id\n     */\n    function _depositUniPositionToken(\n        VaultLib.Vault memory _vault,\n        address _account,\n        uint256 _vaultId,\n        uint256 _uniTokenId\n    ) internal {\n        //get tokens for uniswap NFT\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\n            uniswapPositionManager\n        ).positions(_uniTokenId);\n\n        // require that liquidity is above 0\n        require(liquidity > 0, \"C25\");\n        // accept NFTs from only the wPowerPerp pool\n        require(fee == feeTier, \"C26\");\n        // check token0 and token1\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \"C23\");\n\n        _vault.addUniNftCollateral(_uniTokenId);\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\n    }\n\n    /**\n     * @notice add eth collateral into a vault\n     * @dev this function will update the vault memory in-place\n     * @param _vault the Vault memory to update.\n     * @param _vaultId id of the vault\n     * @param _amount amount of eth adding to the vault\n     */\n    function _addEthCollateral(\n        VaultLib.Vault memory _vault,\n        uint256 _vaultId,\n        uint256 _amount\n    ) internal {\n        _vault.addEthCollateral(_amount);\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\n    }\n\n    /**\n     * @notice remove uniswap v3 position token from the vault\n     * @dev this function will update the vault memory in-place\n     * @param _vault the Vault memory to update\n     * @param _account where to send the uni position token to\n     * @param _vaultId id of the vault\n     */\n    function _withdrawUniPositionToken(\n        VaultLib.Vault memory _vault,\n        address _account,\n        uint256 _vaultId\n    ) internal {\n        uint256 tokenId = _vault.NftCollateralId;\n        _vault.removeUniNftCollateral();\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\n    }\n\n    /**\n     * @notice remove eth collateral from the vault\n     * @dev this function will update the vault memory in-place\n     * @param _vault the Vault memory to update\n     * @param _vaultId id of the vault\n     * @param _amount amount of eth to withdraw\n     */\n    function _withdrawCollateral(\n        VaultLib.Vault memory _vault,\n        uint256 _vaultId,\n        uint256 _amount\n    ) internal {\n        _vault.removeEthCollateral(_amount);\n\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\n    }\n\n    /**\n     * @notice mint wPowerPerp (ERC20) to an account\n     * @dev this function will update the vault memory in-place\n     * @param _vault the Vault memory to update\n     * @param _account account to receive wPowerPerp\n     * @param _vaultId id of the vault\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\n     */\n    function _mintWPowerPerp(\n        VaultLib.Vault memory _vault,\n        address _account,\n        uint256 _vaultId,\n        uint256 _wPowerPerpAmount\n    ) internal {\n        _vault.addShort(_wPowerPerpAmount);\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\n\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\n    }\n\n    /**\n     * @notice burn wPowerPerp (ERC20) from an account\n     * @dev this function will update the vault memory in-place\n     * @param _vault the Vault memory to update\n     * @param _account account burning the wPowerPerp\n     * @param _vaultId id of the vault\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\n     */\n    function _burnWPowerPerp(\n        VaultLib.Vault memory _vault,\n        address _account,\n        uint256 _vaultId,\n        uint256 _wPowerPerpAmount\n    ) internal {\n        _vault.removeShort(_wPowerPerpAmount);\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\n\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\n    }\n\n    /**\n     * @notice liquidate a vault, pay the liquidator\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\n     * @dev this function will update the vault memory in-place\n     * @param _vault the Vault memory to update\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\n     * @param _normalizationFactor current normalization factor\n     * @param _liquidator liquidator address to receive eth\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\n     * @return collateralToPay amount of collateral paid to liquidator\n     */\n    function _liquidate(\n        VaultLib.Vault memory _vault,\n        uint256 _maxWPowerPerpAmount,\n        uint256 _normalizationFactor,\n        address _liquidator\n    ) internal returns (uint256, uint256) {\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\n            _maxWPowerPerpAmount,\n            uint256(_vault.shortAmount),\n            uint256(_vault.collateralAmount)\n        );\n\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\n        require(_maxWPowerPerpAmount >= liquidateAmount, \"C21\");\n\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\n        _vault.removeShort(liquidateAmount);\n        _vault.removeEthCollateral(collateralToPay);\n\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\n        require(!isDust, \"C22\");\n\n        return (liquidateAmount, collateralToPay);\n    }\n\n    /**\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\n     * @dev will be executed before liquidation if there's an NFT in the vault\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\n     * @dev will update the vault memory in-place\n     * @param _vault the Vault memory to update\n     * @param _owner account to send any excess\n     * @param _vaultId id of the vault to reduce debt on\n     * @param _payBounty true if paying caller 2% bounty\n     * @return bounty amount of bounty paid for liquidator\n     */\n    function _reduceDebt(\n        VaultLib.Vault memory _vault,\n        address _owner,\n        uint256 _vaultId,\n        bool _payBounty\n    ) internal returns (uint256) {\n        uint256 nftId = _vault.NftCollateralId;\n        if (nftId == 0) return 0;\n\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\n\n        // change weth back to eth\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\n\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\n            _vault,\n            withdrawnEthAmount,\n            withdrawnWPowerPerpAmount,\n            _payBounty\n        );\n\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\n\n        emit ReduceDebt(\n            msg.sender,\n            _vaultId,\n            withdrawnEthAmount,\n            withdrawnWPowerPerpAmount,\n            burnAmount,\n            excess,\n            bounty\n        );\n\n        return bounty;\n    }\n\n    /**\n     * @notice pay fee recipient\n     * @dev pay in eth from either the vault or the deposit amount\n     * @param _vault the Vault memory to update\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\n     * @param _depositAmount the amount of eth depositing or withdrawing\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\n     */\n    function _getFee(\n        VaultLib.Vault memory _vault,\n        uint256 _wPowerPerpAmount,\n        uint256 _depositAmount\n    ) internal view returns (uint256, uint256) {\n        uint256 cachedFeeRate = feeRate;\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\n        uint256 depositAmountAfterFee;\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\n            _wPowerPerpAmount,\n            oracle,\n            wPowerPerpPool,\n            wPowerPerp,\n            weth\n        );\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\n\n        // if fee can be paid from deposited collateral, pay from _depositAmount\n        if (_depositAmount > feeAmount) {\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\n            // if not, adjust the vault to pay from the vault collateral\n        } else {\n            _vault.removeEthCollateral(feeAmount);\n            depositAmountAfterFee = _depositAmount;\n        }\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\n        return (feeAmount, depositAmountAfterFee);\n    }\n\n    /**\n     * @notice write vault to storage\n     * @dev writes to vaults mapping\n     */\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\n        vaults[_vaultId] = _vault;\n    }\n\n    /**\n     * @dev redeem a uni position token and get back wPowerPerp and eth\n     * @param _uniTokenId uniswap v3 position token id\n     * @return wethAmount amount of weth withdrawn from uniswap\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\n     */\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\n\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\n\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\n            .DecreaseLiquidityParams({\n                tokenId: _uniTokenId,\n                liquidity: liquidity,\n                amount0Min: 0,\n                amount1Min: 0,\n                deadline: block.timestamp\n            });\n\n        positionManager.decreaseLiquidity(decreaseParams);\n\n        // withdraw max amount of weth and wPowerPerp from uniswap\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\n            tokenId: _uniTokenId,\n            recipient: address(this),\n            amount0Max: uint128(-1),\n            amount1Max: uint128(-1)\n        });\n\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\n\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\n    }\n\n    /**\n     * @notice update the normalization factor as a way to pay in-kind funding\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\n     * @return new normalization factor\n     **/\n    function _applyFunding() internal returns (uint256) {\n        // only update the norm factor once per block\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\n\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\n\n        emit NormalizationFactorUpdated(\n            normalizationFactor,\n            newNormalizationFactor,\n            lastFundingUpdateTimestamp,\n            block.timestamp\n        );\n\n        // the following will be batch into 1 SSTORE because of type uint128\n        normalizationFactor = newNormalizationFactor.toUint128();\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\n\n        return newNormalizationFactor;\n    }\n\n    /**\n     * @dev calculate new normalization factor base on the current timestamp\n     * @return new normalization factor if funding happens in the current block\n     */\n    function _getNewNormalizationFactor() internal view returns (uint256) {\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\n\n        if (period == 0) {\n            return normalizationFactor;\n        }\n\n        // make sure we use the same period for mark and index\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\n\n        // avoid reading normalizationFactor from storage multiple times\n        uint256 cacheNormFactor = normalizationFactor;\n\n        uint256 mark = Power2Base._getDenormalizedMark(\n            periodForOracle,\n            oracle,\n            wPowerPerpPool,\n            ethQuoteCurrencyPool,\n            weth,\n            quoteCurrency,\n            wPowerPerp,\n            cacheNormFactor\n        );\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\n\n        //the fraction of the funding period. used to compound the funding rate\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\n\n        // floor mark to be at least LOWER_MARK_RATIO of index\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\n        if (mark < lowerBound) {\n            mark = lowerBound;\n        } else {\n            // cap mark to be at most UPPER_MARK_RATIO of index\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\n            if (mark > upperBound) mark = upperBound;\n        }\n\n        // normFactor(new) = multiplier * normFactor(old)\n        // multiplier = (index/mark)^rFunding\n        // x^r = n^(log_n(x) * r)\n        // multiplier = 2^( log2(index/mark) * rFunding )\n\n        int128 base = ABDKMath64x64.divu(index, mark);\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\n        int128 multiplier = logTerm.exp_2();\n        return multiplier.mulu(cacheNormFactor);\n    }\n\n    /**\n     * @notice check if vault has enough collateral and is not a dust vault\n     * @dev revert if vault has insufficient collateral or is a dust vault\n     * @param _vault the Vault memory to update\n     * @param _normalizationFactor normalization factor\n     */\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\n        require(isSafe, \"C24\");\n        require(!isDust, \"C22\");\n    }\n\n    /**\n     * @notice check that the vault has enough collateral\n     * @param _vault in-memory vault\n     * @param _normalizationFactor normalization factor\n     * @return true if the vault is properly collateralized\n     */\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\n        return isSafe;\n    }\n\n    /**\n     * @notice return if the vault is properly collateralized and if it is a dust vault\n     * @param _vault the Vault memory to update\n     * @param _normalizationFactor normalization factor\n     * @return true if the vault is safe\n     * @return true if the vault is a dust vault\n     */\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\n        internal\n        view\n        returns (bool, bool)\n    {\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\n            oracle,\n            ethQuoteCurrencyPool,\n            weth,\n            quoteCurrency,\n            TWAP_PERIOD,\n            true // do not call more than maximum period so it does not revert\n        );\n        return\n            VaultLib.getVaultStatus(\n                _vault,\n                uniswapPositionManager,\n                _normalizationFactor,\n                scaledEthPrice,\n                MIN_COLLATERAL,\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\n                isWethToken0\n            );\n    }\n\n    /**\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\n     * @dev this function will update the vault memory in-place\n     * @return burnAmount amount of wPowerPerp that should be burned\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\n     * @return bounty amount of bounty should be paid out to caller\n     */\n    function _getReduceDebtResultInVault(\n        VaultLib.Vault memory _vault,\n        uint256 nftEthAmount,\n        uint256 nftWPowerperpAmount,\n        bool _payBounty\n    )\n        internal\n        view\n        returns (\n            uint256,\n            uint256,\n            uint256\n        )\n    {\n        uint256 bounty;\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\n\n        uint256 burnAmount = nftWPowerperpAmount;\n        uint256 wPowerPerpExcess;\n\n        if (nftWPowerperpAmount > _vault.shortAmount) {\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\n            burnAmount = _vault.shortAmount;\n        }\n\n        _vault.removeShort(burnAmount);\n        _vault.removeUniNftCollateral();\n        _vault.addEthCollateral(nftEthAmount);\n        _vault.removeEthCollateral(bounty);\n\n        return (burnAmount, wPowerPerpExcess, bounty);\n    }\n\n    /**\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\n     * @dev bounty is 2% of the total value of the position token\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\n     */\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\n        return\n            Power2Base\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\n                .add(_ethWithdrawn)\n                .mul(REDUCE_DEBT_BOUNTY)\n                .div(ONE);\n    }\n\n    /**\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \"dust vault\"\n     * @dev a liquidator cannot take out more collateral than the vault holds\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\n     * @param _vaultShortAmount the amount of short in the vault\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\n     * @return collateralToPay final amount of collateral paying out to the liquidator\n     */\n    function _getLiquidationResult(\n        uint256 _maxWPowerPerpAmount,\n        uint256 _vaultShortAmount,\n        uint256 _vaultCollateralAmount\n    ) internal view returns (uint256, uint256) {\n        // try limiting liquidation amount to half of the vault debt\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\n            _maxWPowerPerpAmount,\n            _vaultShortAmount.div(2)\n        );\n\n        if (_vaultCollateralAmount > collateralToPay) {\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\n                // the vault is left with dust after liquidation, allow liquidating full vault\n                // calculate the new liquidation amount and collateral again based on the new limit\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\n                    _maxWPowerPerpAmount,\n                    _vaultShortAmount\n                );\n            }\n        }\n\n        // check if final collateral to pay is greater than vault amount.\n        // if so the system only pays out the amount the vault has, which may not be profitable\n        if (collateralToPay > _vaultCollateralAmount) {\n            // force liquidator to pay full debt amount\n            finalLiquidateAmount = _vaultShortAmount;\n            collateralToPay = _vaultCollateralAmount;\n        }\n\n        return (finalLiquidateAmount, collateralToPay);\n    }\n\n    /**\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\n     * @return collateralToPay total collateral the liquidator will get\n     */\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\n        internal\n        view\n        returns (uint256, uint256)\n    {\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\n            ? _maxLiquidatableWAmount\n            : _maxInputWAmount;\n\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\n            finalWAmountToLiquidate,\n            oracle,\n            wPowerPerpPool,\n            wPowerPerp,\n            weth\n        );\n\n        // add 10% bonus for liquidators\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\n\n        return (finalWAmountToLiquidate, collateralToPay);\n    }\n\n    /**\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\n     * @param _period max period that we intend to use\n     * @return fair period not greator than _period to be used for both pools.\n     */\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\n\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/core/LICENSE_GPL_3",
    "content": "\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>."
  },
  {
    "path": "packages/hardhat/contracts/core/Oracle.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\n// uniswap Library only works under 0.7.6\npragma solidity =0.7.6;\n\n//interface\nimport {IUniswapV3Pool} from \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport {IERC20Detailed} from \"../interfaces/IERC20Detailed.sol\";\n\n//library\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {Uint256Casting} from \"../libs/Uint256Casting.sol\";\nimport {OracleLibrary} from \"../libs/OracleLibrary.sol\";\n\n/**\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\n */\ncontract Oracle {\n    using SafeMath for uint256;\n    using Uint256Casting for uint256;\n\n    uint128 private constant ONE = 1e18;\n\n    /**\n     * @notice get twap converted with base & quote token decimals\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \"OLD\"\n     * @param _pool uniswap pool address\n     * @param _base base currency. to get eth/usd price, eth is base token\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\n     * @param _period number of seconds in the past to start calculating time-weighted average\n     * @return price of 1 base currency in quote currency. scaled by 1e18\n     */\n    function getTwap(\n        address _pool,\n        address _base,\n        address _quote,\n        uint32 _period,\n        bool _checkPeriod\n    ) external view returns (uint256) {\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\n\n        // make sure the requested period < maxPeriod the pool recorded.\n        uint32 maxPeriod = _getMaxPeriod(_pool);\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\n    }\n\n    /**\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \"OLD\"\n     * @param _pool uniswap pool address\n     * @param _base base currency. to get eth/usd price, eth is base token\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\n     * @return price of 1 base currency in quote currency. scaled by 1e18\n     */\n    function getHistoricalTwap(\n        address _pool,\n        address _base,\n        address _quote,\n        uint32 _secondsAgoToStartOfTwap,\n        uint32 _secondsAgoToEndOfTwap\n    ) external view returns (uint256) {\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\n    }\n\n    /**\n     * @notice get the max period that can be used to request twap\n     * @param _pool uniswap pool address\n     * @return max period can be used to request twap\n     */\n    function getMaxPeriod(address _pool) external view returns (uint32) {\n        return _getMaxPeriod(_pool);\n    }\n\n    /**\n     * @notice get time weighed average tick, not converted to price\n     * @dev this function will not revert\n     * @param _pool address of the pool\n     * @param _period period in second that we want to calculate average on\n     * @return timeWeightedAverageTick the time weighted average tick\n     */\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\n        external\n        view\n        returns (int24 timeWeightedAverageTick)\n    {\n        uint32 maxPeriod = _getMaxPeriod(_pool);\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\n    }\n\n    /**\n     * @notice get twap converted with base & quote token decimals\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \"OLD\"\n     * @param _pool uniswap pool address\n     * @param _base base currency. to get eth/usd price, eth is base token\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\n     * @param _period number of seconds in the past to start calculating time-weighted average\n     * @return twap price which is scaled\n     */\n    function _fetchTwap(\n        address _pool,\n        address _base,\n        address _quote,\n        uint32 _period\n    ) internal view returns (uint256) {\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\n\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\n\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\n\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\n    }\n\n    /**\n     * @notice get raw twap from the uniswap pool\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \"OLD\".\n     * @param _pool uniswap pool address\n     * @param _base base currency. to get eth/usd price, eth is base token\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\n     * @param _period number of seconds in the past to start calculating time-weighted average\n     * @return amount of quote currency received for _amountIn of base currency\n     */\n    function _fetchRawTwap(\n        address _pool,\n        address _base,\n        address _quote,\n        uint32 _period\n    ) internal view returns (uint256) {\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\n    }\n\n    /**\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \"OLD\"\n     * @param _pool uniswap pool address\n     * @param _base base currency. to get eth/usd price, eth is base token\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\n     * @return price of 1 base currency in quote currency. scaled by 1e18\n     */\n    function _fetchHistoricTwap(\n        address _pool,\n        address _base,\n        address _quote,\n        uint32 _secondsAgoToStartOfTwap,\n        uint32 _secondsAgoToEndOfTwap\n    ) internal view returns (uint256) {\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\n\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\n    }\n\n    /**\n     * @notice get the max period that can be used to request twap\n     * @param _pool uniswap pool address\n     * @return max period can be used to request twap\n     */\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\n        // observationIndex: the index of the last oracle observation that was written\n        // cardinality: the current maximum number of observations stored in the pool\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\n\n        // first observation index\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\n\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\n\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\n\n        // (index + 1) % cardinality is not the oldest index,\n        // probably because cardinality is increased after last observation.\n        // in this case, observation at index 0 should be the oldest.\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\n\n        return uint32(block.timestamp) - oldestObservationTimestamp;\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/core/ShortPowerPerp.sol",
    "content": "//SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.7.6;\n\n//contract\nimport {ERC721} from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport {Initializable} from \"@openzeppelin/contracts/proxy/Initializable.sol\";\nimport {IController} from \"../interfaces/IController.sol\";\n\n/**\n * @notice ERC721 NFT representing ownership of a vault (short position)\n */\ncontract ShortPowerPerp is ERC721, Initializable {\n    /// @dev tokenId for the next vault opened\n    uint256 public nextId = 1;\n\n    address public controller;\n    address private immutable deployer;\n\n    modifier onlyController() {\n        require(msg.sender == controller, \"Not controller\");\n        _;\n    }\n\n    /**\n     * @notice short power perpetual constructor\n     * @param _name token name for ERC721\n     * @param _symbol token symbol for ERC721\n     */\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\n        deployer = msg.sender;\n    }\n\n    /**\n     * @notice initialize short contract\n     * @param _controller controller address\n     */\n    function init(address _controller) public initializer {\n        require(msg.sender == deployer, \"Invalid caller of init\");\n        require(_controller != address(0), \"Invalid controller address\");\n        controller = _controller;\n    }\n\n    /**\n     * @notice mint new NFT\n     * @dev autoincrement tokenId starts at 1\n     * @param _recipient recipient address for NFT\n     */\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\n        // mint NFT\n        _safeMint(_recipient, (tokenId = nextId++));\n    }\n\n    function _beforeTokenTransfer(\n        address, /* from */\n        address, /* to */\n        uint256 tokenId\n    ) internal override {\n        IController(controller).updateOperator(tokenId, address(0));\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/core/WPowerPerp.sol",
    "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.7.6;\n\n//interface\nimport {IWPowerPerp} from \"../interfaces/IWPowerPerp.sol\";\n\n//contract\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {Initializable} from \"@openzeppelin/contracts/proxy/Initializable.sol\";\n\n/**\n * @notice ERC20 Token representing wrapped long power perpetual position\n * @dev value of power perpetual is expected to go down over time through the impact of funding\n */\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\n    address public controller;\n    address private immutable deployer;\n\n    /**\n     * @notice long power perpetual constructor\n     * @param _name token name for ERC20\n     * @param _symbol token symbol for ERC20\n     */\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\n        deployer = msg.sender;\n    }\n\n    modifier onlyController() {\n        require(msg.sender == controller, \"Not controller\");\n        _;\n    }\n\n    /**\n     * @notice init wPowerPerp contract\n     * @param _controller controller address\n     */\n    function init(address _controller) external initializer {\n        require(msg.sender == deployer, \"Invalid caller of init\");\n        require(_controller != address(0), \"Invalid controller address\");\n        controller = _controller;\n    }\n\n    /**\n     * @notice mint wPowerPerp\n     * @param _account account to mint to\n     * @param _amount amount to mint\n     */\n    function mint(address _account, uint256 _amount) external override onlyController {\n        _mint(_account, _amount);\n    }\n\n    /**\n     * @notice burn wPowerPerp\n     * @param _account account to burn from\n     * @param _amount amount to burn\n     */\n    function burn(address _account, uint256 _amount) external override onlyController {\n        _burn(_account, _amount);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/external/LICENSE_GPL_3",
    "content": "// Copyright (C) 2015, 2016, 2017 Dapphub\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "packages/hardhat/contracts/external/WETH9.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity =0.7.6;\n\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\n\ncontract WETH9 {\n    string public name = \"Wrapped Ether\";\n    string public symbol = \"WETH\";\n    uint8 public decimals = 18;\n\n    event Approval(address indexed src, address indexed guy, uint256 wad);\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\n    event Deposit(address indexed dst, uint256 wad);\n    event Withdrawal(address indexed src, uint256 wad);\n\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    function deposit() public payable {\n        balanceOf[msg.sender] += msg.value;\n        emit Deposit(msg.sender, msg.value);\n    }\n\n    function withdraw(uint256 wad) public {\n        require(balanceOf[msg.sender] >= wad);\n        balanceOf[msg.sender] -= wad;\n        payable(msg.sender).transfer(wad);\n        emit Withdrawal(msg.sender, wad);\n    }\n\n    function totalSupply() public view returns (uint256) {\n        return address(this).balance;\n    }\n\n    function approve(address guy, uint256 wad) public returns (bool) {\n        allowance[msg.sender][guy] = wad;\n        emit Approval(msg.sender, guy, wad);\n        return true;\n    }\n\n    function transfer(address dst, uint256 wad) public returns (bool) {\n        return transferFrom(msg.sender, dst, wad);\n    }\n\n    function transferFrom(\n        address src,\n        address dst,\n        uint256 wad\n    ) public returns (bool) {\n        require(balanceOf[src] >= wad);\n\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\n            require(allowance[src][msg.sender] >= wad);\n            allowance[src][msg.sender] -= wad;\n        }\n\n        balanceOf[src] -= wad;\n        balanceOf[dst] += wad;\n\n        emit Transfer(src, dst, wad);\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/import/LICENSE_GPL_3",
    "content": "                  \n                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>."
  },
  {
    "path": "packages/hardhat/contracts/import/Uni.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\n\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\";\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\";\nimport \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\";\nimport \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\n\ncontract Uni {\n    // hack: force hardhat to import all the interfaces at compile time\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/interfaces/IController.sol",
    "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.7.6;\n\npragma abicoder v2;\n\nimport {VaultLib} from \"../libs/VaultLib.sol\";\n\ninterface IController {\n    function ethQuoteCurrencyPool() external view returns (address);\n\n    function feeRate() external view returns (uint256);\n\n    function getFee(\n        uint256 _vaultId,\n        uint256 _wPowerPerpAmount,\n        uint256 _collateralAmount\n    ) external view returns (uint256);\n\n    function quoteCurrency() external view returns (address);\n\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\n\n    function shortPowerPerp() external view returns (address);\n\n    function wPowerPerp() external view returns (address);\n\n    function wPowerPerpPool() external view returns (address);\n\n    function oracle() external view returns (address);\n\n    function weth() external view returns (address);\n\n    function getExpectedNormalizationFactor() external view returns (uint256);\n\n    function mintPowerPerpAmount(\n        uint256 _vaultId,\n        uint256 _powerPerpAmount,\n        uint256 _uniTokenId\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\n\n    function mintWPowerPerpAmount(\n        uint256 _vaultId,\n        uint256 _wPowerPerpAmount,\n        uint256 _uniTokenId\n    ) external payable returns (uint256 vaultId);\n\n    /**\n     * Deposit collateral into a vault\n     */\n    function deposit(uint256 _vaultId) external payable;\n\n    /**\n     * Withdraw collateral from a vault.\n     */\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\n\n    function burnWPowerPerpAmount(\n        uint256 _vaultId,\n        uint256 _wPowerPerpAmount,\n        uint256 _withdrawAmount\n    ) external;\n\n    function burnPowerPerpAmount(\n        uint256 _vaultId,\n        uint256 _powerPerpAmount,\n        uint256 _withdrawAmount\n    ) external returns (uint256 wPowerPerpAmount);\n\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\n\n    function updateOperator(uint256 _vaultId, address _operator) external;\n\n    /**\n     * External function to update the normalized factor as a way to pay funding.\n     */\n    function applyFunding() external;\n\n    function redeemShort(uint256 _vaultId) external;\n\n    function reduceDebtShutdown(uint256 _vaultId) external;\n\n    function isShutDown() external returns (bool);\n\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\n\n    function withdrawUniPositionToken(uint256 _vaultId) external;\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/interfaces/ICrabStrategyV2.sol",
    "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.7.6;\n\npragma abicoder v2;\n\ninterface ICrabStrategyV2 {\n    function wPowerPerp() external view returns (address);\n\n    function weth() external view returns (address);\n\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\n\n    function flashWithdraw(\n        uint256 _crabAmount,\n        uint256 _maxEthToPay,\n        uint24 _poolFee\n    ) external;\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/interfaces/IERC20Detailed.sol",
    "content": "// SPDX-License-Identifier: MIT\n\n// uniswap Library only works under 0.7.6\npragma solidity =0.7.6;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IERC20Detailed is IERC20 {\n    function decimals() external view returns (uint8);\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/interfaces/IEuler.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity =0.7.6;\npragma abicoder v2;\n\ninterface IEulerExec {\n    function deferLiquidityCheck(address account, bytes memory data) external;\n}\n\ninterface IDToken {\n    function underlyingAsset() external view returns (address);\n\n    function borrow(uint256 subAccountId, uint256 amount) external;\n\n    function repay(uint256 subAccountId, uint256 amount) external;\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/interfaces/IOracle.sol",
    "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.7.6;\n\ninterface IOracle {\n    function getHistoricalTwap(\n        address _pool,\n        address _base,\n        address _quote,\n        uint32 _period,\n        uint32 _periodToHistoricPrice\n    ) external view returns (uint256);\n\n    function getTwap(\n        address _pool,\n        address _base,\n        address _quote,\n        uint32 _period,\n        bool _checkPeriod\n    ) external view returns (uint256);\n\n    function getMaxPeriod(address _pool) external view returns (uint32);\n\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\n        external\n        view\n        returns (int24 timeWeightedAverageTick);\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/interfaces/IShortPowerPerp.sol",
    "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.7.6;\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\n\ninterface IShortPowerPerp is IERC721 {\n    function nextId() external view returns (uint256);\n\n    function mintNFT(address recipient) external returns (uint256 _newId);\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/interfaces/IWETH9.sol",
    "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.7.6;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IWETH9 is IERC20 {\n    function deposit() external payable;\n\n    function withdraw(uint256 wad) external;\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/interfaces/IWPowerPerp.sol",
    "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.7.6;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IWPowerPerp is IERC20 {\n    function mint(address _account, uint256 _amount) external;\n\n    function burn(address _account, uint256 _amount) external;\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/interfaces/LICENSE_MIT",
    "content": "MIT License\n\nCopyright (c) 2022 Opyn\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n"
  },
  {
    "path": "packages/hardhat/contracts/libs/ABDKMath64x64.sol",
    "content": "// SPDX-License-Identifier: BSD-4-Clause\n/*\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\n * Copyright (c) 2019, ABDK Consulting\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\npragma solidity ^0.7.0;\n\n/**\n * Smart contract library of mathematical functions operating with signed\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\n * basically a simple fraction whose numerator is signed 128-bit integer and\n * denominator is 2^64.  As long as denominator is always the same, there is no\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\n * represented by int128 type holding only the numerator.\n *\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\n * Changes (cont) - revert strings added\n * solidity version set to ^0.7.0\n */\nlibrary ABDKMath64x64 {\n    /*\n     * Minimum value signed 64.64-bit fixed point number may have.\n     * Minimum value signed 64.64-bit fixed point number may have.\n     * Minimum value signed 64.64-bit fixed point number may have.\n     * -2^127\n     */\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\n\n    /*\n     * Maximum value signed 64.64-bit fixed point number may have.\n     * Maximum value signed 64.64-bit fixed point number may have.\n     * Maximum value signed 64.64-bit fixed point number may have.\n     * 2^127-1\n     */\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n    /**\n     * Calculate x * y rounding down.  Revert on overflow.\n     *\n     * @param x signed 64.64-bit fixed point number\n     * @param y signed 64.64-bit fixed point number\n     * @return signed 64.64-bit fixed point number\n     */\n    function mul(int128 x, int128 y) internal pure returns (int128) {\n        int256 result = (int256(x) * y) >> 64;\n        require(result >= MIN_64x64 && result <= MAX_64x64, \"MUL-OVUF\");\n        return int128(result);\n    }\n\n    /**\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\n     *\n     * @param x signed 64.64 fixed point number\n     * @param y unsigned 256-bit integer number\n     * @return unsigned 256-bit integer number\n     */\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\n        if (y == 0) return 0;\n\n        require(x >= 0, \"MULU-X0\");\n\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\n        uint256 hi = uint256(x) * (y >> 128);\n\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \"MULU-OF1\");\n        hi <<= 64;\n\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \"MULU-OF2\");\n        return hi + lo;\n    }\n\n    /**\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\n     * integer numbers.  Revert on overflow or when y is zero.\n     *\n     * @param x unsigned 256-bit integer number\n     * @param y unsigned 256-bit integer number\n     * @return signed 64.64-bit fixed point number\n     */\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\n        require(y != 0, \"DIVU-INF\");\n        uint128 result = divuu(x, y);\n        require(result <= uint128(MAX_64x64), \"DIVU-OF\");\n        return int128(result);\n    }\n\n    /**\n     * Calculate binary logarithm of x.  Revert if x <= 0.\n     *\n     * @param x signed 64.64-bit fixed point number\n     * @return signed 64.64-bit fixed point number\n     */\n    function log_2(int128 x) public pure returns (int128) {\n        require(x > 0, \"LOG_2-X0\");\n\n        int256 msb = 0;\n        int256 xc = x;\n        if (xc >= 0x10000000000000000) {\n            xc >>= 64;\n            msb += 64;\n        }\n        if (xc >= 0x100000000) {\n            xc >>= 32;\n            msb += 32;\n        }\n        if (xc >= 0x10000) {\n            xc >>= 16;\n            msb += 16;\n        }\n        if (xc >= 0x100) {\n            xc >>= 8;\n            msb += 8;\n        }\n        if (xc >= 0x10) {\n            xc >>= 4;\n            msb += 4;\n        }\n        if (xc >= 0x4) {\n            xc >>= 2;\n            msb += 2;\n        }\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\n\n        int256 result = (msb - 64) << 64;\n        uint256 ux = uint256(x) << uint256(127 - msb);\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\n            ux *= ux;\n            uint256 b = ux >> 255;\n            ux >>= 127 + b;\n            result += bit * int256(b);\n        }\n\n        return int128(result);\n    }\n\n    /**\n     * Calculate binary exponent of x.  Revert on overflow.\n     *\n     * @param x signed 64.64-bit fixed point number\n     * @return signed 64.64-bit fixed point number\n     */\n    function exp_2(int128 x) public pure returns (int128) {\n        require(x < 0x400000000000000000, \"EXP_2-OF\"); // Overflow\n\n        if (x < -0x400000000000000000) return 0; // Underflow\n\n        uint256 result = 0x80000000000000000000000000000000;\n\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\n\n        result >>= uint256(63 - (x >> 64));\n        require(result <= uint256(MAX_64x64));\n\n        return int128(result);\n    }\n\n    /**\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\n     * integer numbers.  Revert on overflow or when y is zero.\n     *\n     * @param x unsigned 256-bit integer number\n     * @param y unsigned 256-bit integer number\n     * @return unsigned 64.64-bit fixed point number\n     */\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\n        require(y != 0);\n\n        uint256 result;\n\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\n        else {\n            uint256 msb = 192;\n            uint256 xc = x >> 192;\n            if (xc >= 0x100000000) {\n                xc >>= 32;\n                msb += 32;\n            }\n            if (xc >= 0x10000) {\n                xc >>= 16;\n                msb += 16;\n            }\n            if (xc >= 0x100) {\n                xc >>= 8;\n                msb += 8;\n            }\n            if (xc >= 0x10) {\n                xc >>= 4;\n                msb += 4;\n            }\n            if (xc >= 0x4) {\n                xc >>= 2;\n                msb += 2;\n            }\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\n\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \"DIVUU-OF1\");\n\n            uint256 hi = result * (y >> 128);\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\n\n            uint256 xh = x >> 192;\n            uint256 xl = x << 64;\n\n            if (xl < lo) xh -= 1;\n            xl -= lo; // We rely on overflow behavior here\n            lo = hi << 128;\n            if (xl < lo) xh -= 1;\n            xl -= lo; // We rely on overflow behavior here\n\n            assert(xh == hi >> 128);\n\n            result += xl / y;\n        }\n\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \"DIVUU-OF2\");\n        return uint128(result);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/libs/LICENSE_BSD_4_Clause",
    "content": "ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\nAuthor: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\nCopyright (c) 2019, ABDK Consulting\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\nAll advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\nNeither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  },
  {
    "path": "packages/hardhat/contracts/libs/LICENSE_GPL_3",
    "content": "\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>."
  },
  {
    "path": "packages/hardhat/contracts/libs/LICENSE_MIT",
    "content": "MIT License\n\nCopyright (c) 2022 Opyn\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n"
  },
  {
    "path": "packages/hardhat/contracts/libs/OracleLibrary.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity >=0.5.0 <0.8.0;\n\n//interface\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\n\n//lib\nimport \"@uniswap/v3-core/contracts/libraries/FullMath.sol\";\nimport \"@uniswap/v3-core/contracts/libraries/TickMath.sol\";\n\n/// @title oracle library\n/// @notice provides functions to integrate with uniswap v3 oracle\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\nlibrary OracleLibrary {\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\n    /// @dev written by opyn team\n    /// @param pool Address of uniswap v3 pool that we want to observe\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\n    function consultAtHistoricTime(\n        address pool,\n        uint32 _secondsAgoToStartOfTwap,\n        uint32 _secondsAgoToEndOfTwap\n    ) internal view returns (int24) {\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \"BP\");\n        int24 timeWeightedAverageTick;\n        uint32[] memory secondAgos = new uint32[](2);\n\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\n\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\n        secondAgos[0] = _secondsAgoToStartOfTwap;\n        secondAgos[1] = _secondsAgoToEndOfTwap;\n\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\n\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\n\n        // Always round to negative infinity\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\n\n        return timeWeightedAverageTick;\n    }\n\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\n    /// @param tick tick value used to calculate the quote\n    /// @param baseAmount amount of token to be converted\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\n    function getQuoteAtTick(\n        int24 tick,\n        uint128 baseAmount,\n        address baseToken,\n        address quoteToken\n    ) internal pure returns (uint256 quoteAmount) {\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\n\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\n        if (sqrtRatioX96 <= type(uint128).max) {\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\n            quoteAmount = baseToken < quoteToken\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\n        } else {\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\n            quoteAmount = baseToken < quoteToken\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/libs/Power2Base.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\n\n//interface\nimport {IOracle} from \"../interfaces/IOracle.sol\";\n\n//lib\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nlibrary Power2Base {\n    using SafeMath for uint256;\n\n    uint32 private constant TWAP_PERIOD = 420 seconds;\n    uint256 private constant INDEX_SCALE = 1e4;\n    uint256 private constant ONE = 1e18;\n    uint256 private constant ONE_ONE = 1e36;\n\n    /**\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\n     * @param _oracle oracle address\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\n     * @param _weth weth address\n     * @param _quoteCurrency quoteCurrency address\n     * @return for squeeth, return ethPrice^2\n     */\n    function _getIndex(\n        uint32 _period,\n        address _oracle,\n        address _ethQuoteCurrencyPool,\n        address _weth,\n        address _quoteCurrency\n    ) internal view returns (uint256) {\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\n            _oracle,\n            _ethQuoteCurrencyPool,\n            _weth,\n            _quoteCurrency,\n            _period,\n            false\n        );\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\n    }\n\n    /**\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\n     * @param _oracle oracle address\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\n     * @param _weth weth address\n     * @param _quoteCurrency quoteCurrency address\n     * @return for squeeth, return ethPrice^2\n     */\n    function _getUnscaledIndex(\n        uint32 _period,\n        address _oracle,\n        address _ethQuoteCurrencyPool,\n        address _weth,\n        address _quoteCurrency\n    ) internal view returns (uint256) {\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\n    }\n\n    /**\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\n     * @param _oracle oracle address\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\n     * @param _weth weth address\n     * @param _quoteCurrency quoteCurrency address\n     * @param _wSqueeth wSqueeth address\n     * @param _normalizationFactor current normalization factor\n     * @return for squeeth, return ethPrice * squeethPriceInEth\n     */\n    function _getDenormalizedMark(\n        uint32 _period,\n        address _oracle,\n        address _wSqueethEthPool,\n        address _ethQuoteCurrencyPool,\n        address _weth,\n        address _quoteCurrency,\n        address _wSqueeth,\n        uint256 _normalizationFactor\n    ) internal view returns (uint256) {\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\n            _oracle,\n            _ethQuoteCurrencyPool,\n            _weth,\n            _quoteCurrency,\n            _period,\n            false\n        );\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\n\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\n    }\n\n    /**\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\n     * @param _debtAmount wSqueeth amount paid by liquidator\n     * @param _oracle oracle address\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\n     * @param _wSqueeth wSqueeth address\n     * @param _weth weth address\n     * @return returns value of debt in ETH\n     */\n    function _getDebtValueInEth(\n        uint256 _debtAmount,\n        address _oracle,\n        address _wSqueethEthPool,\n        address _wSqueeth,\n        address _weth\n    ) internal view returns (uint256) {\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\n    }\n\n    /**\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\n     * @param _oracle oracle address\n     * @param _pool uniswap v3 pool address\n     * @param _base base currency. to get eth/usd price, eth is base token\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\n     * @param _period number of seconds in the past to start calculating time-weighted average.\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\n     * @return twap price scaled down by INDEX_SCALE\n     */\n    function _getScaledTwap(\n        address _oracle,\n        address _pool,\n        address _base,\n        address _quote,\n        uint32 _period,\n        bool _checkPeriod\n    ) internal view returns (uint256) {\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\n        return twap.div(INDEX_SCALE);\n    }\n\n    /**\n     * @notice request twap from our oracle\n     * @dev this will revert if period is > max period for the pool\n     * @param _oracle oracle address\n     * @param _pool uniswap v3 pool address\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\n     * @param _period number of seconds in the past to start calculating time-weighted average\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\n     * @return human readable price. scaled by 1e18\n     */\n    function _getTwap(\n        address _oracle,\n        address _pool,\n        address _base,\n        address _quote,\n        uint32 _period,\n        bool _checkPeriod\n    ) internal view returns (uint256) {\n        // period reaching this point should be check, otherwise might revert\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\n    }\n\n    /**\n     * @notice get the index value of wsqueeth in wei, used when system settles\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\n     * @param _indexPriceForSettlement index price for settlement\n     * @param _normalizationFactor current normalization factor\n     * @return amount in wei that should be paid to the token holder\n     */\n    function _getLongSettlementValue(\n        uint256 _wsqueethAmount,\n        uint256 _indexPriceForSettlement,\n        uint256 _normalizationFactor\n    ) internal pure returns (uint256) {\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/libs/SqrtPriceMathPartial.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport \"@uniswap/v3-core/contracts/libraries/FullMath.sol\";\nimport \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\";\nimport \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\";\n\n/// @title Functions based on Q64.96 sqrt price and liquidity\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\nlibrary SqrtPriceMathPartial {\n    /// @notice Gets the amount0 delta between two prices\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\n    /// @param sqrtRatioAX96 A sqrt price\n    /// @param sqrtRatioBX96 Another sqrt price\n    /// @param liquidity The amount of usable liquidity\n    /// @param roundUp Whether to round the amount up or down\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\n    function getAmount0Delta(\n        uint160 sqrtRatioAX96,\n        uint160 sqrtRatioBX96,\n        uint128 liquidity,\n        bool roundUp\n    ) external pure returns (uint256 amount0) {\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\n\n        require(sqrtRatioAX96 > 0);\n\n        return\n            roundUp\n                ? UnsafeMath.divRoundingUp(\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\n                    sqrtRatioAX96\n                )\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\n    }\n\n    /// @notice Gets the amount1 delta between two prices\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\n    /// @param sqrtRatioAX96 A sqrt price\n    /// @param sqrtRatioBX96 Another sqrt price\n    /// @param liquidity The amount of usable liquidity\n    /// @param roundUp Whether to round the amount up, or down\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\n    function getAmount1Delta(\n        uint160 sqrtRatioAX96,\n        uint160 sqrtRatioBX96,\n        uint128 liquidity,\n        bool roundUp\n    ) external pure returns (uint256 amount1) {\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n\n        return\n            roundUp\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/libs/TickMathExternal.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Math library for computing sqrt prices from ticks and vice versa\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\n/// prices between 2**-128 and 2**128\nlibrary TickMathExternal {\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\n    int24 internal constant MIN_TICK = -887272;\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\n    int24 internal constant MAX_TICK = -MIN_TICK;\n\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\n    /// @dev Throws if |tick| > max tick\n    /// @param tick The input tick for the above formula\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\n    /// at the given tick\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\n        require(absTick <= uint256(MAX_TICK), \"T\");\n\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\n\n        if (tick > 0) ratio = type(uint256).max / ratio;\n\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\n    }\n\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\n    /// ever return.\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\n        // second inequality must be < because the price can never reach the price at the max tick\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \"R\");\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\n\n        uint256 r = ratio;\n        uint256 msb = 0;\n\n        assembly {\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(5, gt(r, 0xFFFFFFFF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(4, gt(r, 0xFFFF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(3, gt(r, 0xFF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(2, gt(r, 0xF))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := shl(1, gt(r, 0x3))\n            msb := or(msb, f)\n            r := shr(f, r)\n        }\n        assembly {\n            let f := gt(r, 0x1)\n            msb := or(msb, f)\n        }\n\n        if (msb >= 128) r = ratio >> (msb - 127);\n        else r = ratio << (127 - msb);\n\n        int256 log_2 = (int256(msb) - 128) << 64;\n\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(63, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(62, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(61, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(60, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(59, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(58, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(57, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(56, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(55, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(54, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(53, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(52, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(51, f))\n            r := shr(f, r)\n        }\n        assembly {\n            r := shr(127, mul(r, r))\n            let f := shr(128, r)\n            log_2 := or(log_2, shl(50, f))\n        }\n\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\n\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\n\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/libs/Uint256Casting.sol",
    "content": "//SPDX-License-Identifier: MIT\n\npragma solidity =0.7.6;\n\nlibrary Uint256Casting {\n    /**\n     * @notice cast a uint256 to a uint128, revert on overflow\n     * @param y the uint256 to be downcasted\n     * @return z the downcasted integer, now type uint128\n     */\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\n        require((z = uint128(y)) == y, \"OF128\");\n    }\n\n    /**\n     * @notice cast a uint256 to a uint96, revert on overflow\n     * @param y the uint256 to be downcasted\n     * @return z the downcasted integer, now type uint96\n     */\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\n        require((z = uint96(y)) == y, \"OF96\");\n    }\n\n    /**\n     * @notice cast a uint256 to a uint32, revert on overflow\n     * @param y the uint256 to be downcasted\n     * @return z the downcasted integer, now type uint32\n     */\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\n        require((z = uint32(y)) == y, \"OF32\");\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/libs/VaultLib.sol",
    "content": "//SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity =0.7.6;\n\n//interface\nimport {INonfungiblePositionManager} from \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\";\n\n//lib\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {TickMathExternal} from \"./TickMathExternal.sol\";\nimport {SqrtPriceMathPartial} from \"./SqrtPriceMathPartial.sol\";\nimport {Uint256Casting} from \"./Uint256Casting.sol\";\n\n/**\n * Error code:\n * V1: Vault already had nft\n * V2: Vault has no NFT\n */\nlibrary VaultLib {\n    using SafeMath for uint256;\n    using Uint256Casting for uint256;\n\n    uint256 constant ONE_ONE = 1e36;\n\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\n    uint256 public constant CR_NUMERATOR = 3;\n    uint256 public constant CR_DENOMINATOR = 2;\n\n    struct Vault {\n        // the address that can update the vault\n        address operator;\n        // uniswap position token id deposited into the vault as collateral\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\n        uint32 NftCollateralId;\n        // amount of eth (wei) used in the vault as collateral\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\n        uint96 collateralAmount;\n        // amount of wPowerPerp minted from the vault\n        uint128 shortAmount;\n    }\n\n    /**\n     * @notice add eth collateral to a vault\n     * @param _vault in-memory vault\n     * @param _amount amount of eth to add\n     */\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\n    }\n\n    /**\n     * @notice add uniswap position token collateral to a vault\n     * @param _vault in-memory vault\n     * @param _tokenId uniswap position token id\n     */\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\n        require(_vault.NftCollateralId == 0, \"V1\");\n        require(_tokenId != 0, \"C23\");\n        _vault.NftCollateralId = _tokenId.toUint32();\n    }\n\n    /**\n     * @notice remove eth collateral from a vault\n     * @param _vault in-memory vault\n     * @param _amount amount of eth to remove\n     */\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\n    }\n\n    /**\n     * @notice remove uniswap position token collateral from a vault\n     * @param _vault in-memory vault\n     */\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\n        require(_vault.NftCollateralId != 0, \"V2\");\n        _vault.NftCollateralId = 0;\n    }\n\n    /**\n     * @notice add debt to vault\n     * @param _vault in-memory vault\n     * @param _amount amount of debt to add\n     */\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\n    }\n\n    /**\n     * @notice remove debt from vault\n     * @param _vault in-memory vault\n     * @param _amount amount of debt to remove\n     */\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\n    }\n\n    /**\n     * @notice check if a vault is properly collateralized\n     * @param _vault the vault we want to check\n     * @param _positionManager address of the uniswap position manager\n     * @param _normalizationFactor current _normalizationFactor\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\n     * @param _minCollateral minimum collateral that needs to be in a vault\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\n     * @return true if the vault is sufficiently collateralized\n     * @return true if the vault is considered as a dust vault\n     */\n    function getVaultStatus(\n        Vault memory _vault,\n        address _positionManager,\n        uint256 _normalizationFactor,\n        uint256 _ethQuoteCurrencyPrice,\n        uint256 _minCollateral,\n        int24 _wsqueethPoolTick,\n        bool _isWethToken0\n    ) internal view returns (bool, bool) {\n        if (_vault.shortAmount == 0) return (true, false);\n\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\n            ONE_ONE\n        );\n        uint256 totalCollateral = _getEffectiveCollateral(\n            _vault,\n            _positionManager,\n            _normalizationFactor,\n            _ethQuoteCurrencyPrice,\n            _wsqueethPoolTick,\n            _isWethToken0\n        );\n\n        bool isDust = totalCollateral < _minCollateral;\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\n        return (isAboveWater, isDust);\n    }\n\n    /**\n     * @notice get the total effective collateral of a vault, which is:\n     *         collateral amount + uniswap position token equivelent amount in eth\n     * @param _vault the vault we want to check\n     * @param _positionManager address of the uniswap position manager\n     * @param _normalizationFactor current _normalizationFactor\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\n     * @return the total worth of collateral in the vault\n     */\n    function _getEffectiveCollateral(\n        Vault memory _vault,\n        address _positionManager,\n        uint256 _normalizationFactor,\n        uint256 _ethQuoteCurrencyPrice,\n        int24 _wsqueethPoolTick,\n        bool _isWethToken0\n    ) internal view returns (uint256) {\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\n\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\n            _positionManager,\n            _vault.NftCollateralId,\n            _wsqueethPoolTick,\n            _isWethToken0\n        );\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\n            ONE_ONE\n        );\n        // add eth value from uniswap position token as collateral\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\n    }\n\n    /**\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\n     * @param _positionManager address of the uniswap position manager\n     * @param _tokenId uniswap position token id\n     * @param _wPowerPerpPoolTick current price tick\n     * @param _isWethToken0 whether weth is token0 in the pool\n     * @return ethAmount the eth amount this LP token contains\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\n     */\n    function _getUniPositionBalances(\n        address _positionManager,\n        uint256 _tokenId,\n        int24 _wPowerPerpPoolTick,\n        bool _isWethToken0\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\n        (\n            int24 tickLower,\n            int24 tickUpper,\n            uint128 liquidity,\n            uint128 tokensOwed0,\n            uint128 tokensOwed1\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\n            tickLower,\n            tickUpper,\n            _wPowerPerpPoolTick,\n            liquidity\n        );\n\n        return\n            _isWethToken0\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\n    }\n\n    /**\n     * @notice get uniswap position token info\n     * @param _positionManager address of the uniswap position position manager\n     * @param _tokenId uniswap position token id\n     * @return tickLower lower tick of the position\n     * @return tickUpper upper tick of the position\n     * @return liquidity raw liquidity amount of the position\n     * @return tokensOwed0 amount of token 0 can be collected as fee\n     * @return tokensOwed1 amount of token 1 can be collected as fee\n     */\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\n        internal\n        view\n        returns (\n            int24,\n            int24,\n            uint128,\n            uint128,\n            uint128\n        )\n    {\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\n        (\n            ,\n            ,\n            ,\n            ,\n            ,\n            int24 tickLower,\n            int24 tickUpper,\n            uint128 liquidity,\n            ,\n            ,\n            uint128 tokensOwed0,\n            uint128 tokensOwed1\n        ) = positionManager.positions(_tokenId);\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\n    }\n\n    /**\n     * @notice get balances of token0 / token1 in a uniswap position\n     * @dev knowing liquidity, tick range, and current tick gives balances\n     * @param _tickLower address of the uniswap position manager\n     * @param _tickUpper uniswap position token id\n     * @param _tick current price tick used for calculation\n     * @return amount0 the amount of token0 in the uniswap position token\n     * @return amount1 the amount of token1 in the uniswap position token\n     */\n    function _getToken0Token1Balances(\n        int24 _tickLower,\n        int24 _tickUpper,\n        int24 _tick,\n        uint128 _liquidity\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\n        // get the current price and tick from wPowerPerp pool\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\n\n        if (_tick < _tickLower) {\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\n                _liquidity,\n                true\n            );\n        } else if (_tick < _tickUpper) {\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\n                sqrtPriceX96,\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\n                _liquidity,\n                true\n            );\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\n                sqrtPriceX96,\n                _liquidity,\n                true\n            );\n        } else {\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\n                _liquidity,\n                true\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/LICENSE_GPL_3",
    "content": "                  \n                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>."
  },
  {
    "path": "packages/hardhat/contracts/mocks/LICENSE_MIT",
    "content": "MIT License\n\nCopyright (c) 2020 Opyn\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/MockController.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\n\nimport {IShortPowerPerp} from \"../interfaces/IShortPowerPerp.sol\";\nimport {IWPowerPerp} from \"../interfaces/IWPowerPerp.sol\";\n\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\nimport {VaultLib} from \"../libs/VaultLib.sol\";\n\ncontract MockController {\n    using SafeMath for uint256;\n    using VaultLib for VaultLib.Vault;\n    using Address for address payable;\n\n    uint256 internal constant secInDay = 86400;\n\n    address public quoteCurrency;\n    address public ethQuoteCurrencyPool;\n    uint256 public normalizationFactor;\n    uint256 public feeRate = 0;\n\n    /// @dev The token ID vault data\n    mapping(uint256 => VaultLib.Vault) public vaults;\n\n    IWPowerPerp public wPowerPerp;\n    IShortPowerPerp public shortPowerPerp;\n\n    function init(\n        address _shortPowerPerp,\n        address _wPowerPerp,\n        address _ethQuoteCurrencyPool,\n        address _quoteCurrency\n    ) public {\n        require(_shortPowerPerp != address(0), \"C5\");\n        require(_wPowerPerp != address(0), \"Invalid wPowerPerp address\");\n\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\n        quoteCurrency = _quoteCurrency;\n\n        normalizationFactor = 1e18;\n    }\n\n    function mintWPowerPerpAmount(\n        uint256 _vaultId,\n        uint256 _mintAmount,\n        uint256 /*_nftTokenId*/\n    ) external payable returns (uint256, uint256) {\n        uint256 wPowerPerpMinted;\n\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\n        if (_mintAmount > 0) {\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\n        }\n\n        return (_vaultId, wPowerPerpMinted);\n    }\n\n    function burnWPowerPerpAmount(\n        uint256 _vaultId,\n        uint256 _amount,\n        uint256 _withdrawAmount\n    ) external {\n        require(_canModifyVault(_vaultId, msg.sender), \"C3\");\n\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\n    }\n\n    function _openVault(address _recipient) internal returns (uint256) {\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\n        vaults[vaultId] = VaultLib.Vault({\n            NftCollateralId: 0,\n            collateralAmount: 0,\n            shortAmount: 0,\n            operator: address(0)\n        });\n\n        return vaultId;\n    }\n\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n        cachedVault.addEthCollateral(uint128(_amount));\n        vaults[_vaultId] = cachedVault;\n    }\n\n    function _withdrawCollateral(\n        address, /*_account*/\n        uint256 _vaultId,\n        uint256 _amount\n    ) internal {\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n        cachedVault.removeEthCollateral(_amount);\n        vaults[_vaultId] = cachedVault;\n    }\n\n    function _addShort(\n        address _account,\n        uint256 _vaultId,\n        uint256 _wPowerPerpAmount\n    ) internal returns (uint256 amountToMint) {\n        require(_canModifyVault(_vaultId, _account), \"C3\");\n\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\n\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n        cachedVault.addShort(amountToMint);\n        vaults[_vaultId] = cachedVault;\n\n        wPowerPerp.mint(_account, amountToMint);\n    }\n\n    function _removeShort(\n        address _account,\n        uint256 _vaultId,\n        uint256 _amount\n    ) internal {\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\n        cachedVault.removeShort(_amount);\n        vaults[_vaultId] = cachedVault;\n\n        wPowerPerp.burn(_account, _amount);\n    }\n\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\n    }\n\n    function getExpectedNormalizationFactor() external view returns (uint256) {\n        return normalizationFactor;\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/MockCrab.sol",
    "content": "pragma solidity =0.7.6;\n\n// interface\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockCrab is ERC20 {\n    address operator;\n    uint256 vaultId;\n    uint256 collateral;\n    uint256 short;\n    address public wPowerPerp;\n\n    constructor(\n        string memory _name,\n        string memory _symbol,\n        uint8 _decimals\n    ) ERC20(_name, _symbol) {\n        _setupDecimals(_decimals);\n    }\n\n    function mint(address _account, uint256 _amount) external {\n        _mint(_account, _amount);\n    }\n\n    function burn(address _account, uint256 _amount) external {\n        _burn(_account, _amount);\n    }\n\n    function setVaultDetails(\n        uint256 _vaultId,\n        uint256 _collateral,\n        uint256 _short\n    ) external {\n        vaultId = _vaultId;\n        collateral = _collateral;\n        short = _short;\n    }\n\n    function getVaultDetails()\n        external\n        view\n        returns (\n            address,\n            uint256,\n            uint256,\n            uint256\n        )\n    {\n        return (operator, vaultId, collateral, short);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/MockErc20.sol",
    "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.7.6;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract MockErc20 is ERC20, Ownable {\n    /// @dev mapping to track whitelisted minters\n    mapping(address => bool) internal whitelistedMinters;\n\n    /// @notice emits an event when a minter is whitelisted\n    event MinterWhitelisted(address indexed account);\n\n    /// @notice emits an event when a minter is blacklisted\n    event MinterBlacklisted(address indexed account);\n\n    /**\n     * @notice check if the sender is whitelistd\n     */\n    modifier onlyWhitelisted() {\n        require(whitelistedMinters[msg.sender] || msg.sender == owner(), \"Address not a whitelisted minter\");\n        _;\n    }\n\n    constructor(\n        string memory _name,\n        string memory _symbol,\n        uint8 _decimals\n    ) ERC20(_name, _symbol) {\n        _setupDecimals(_decimals);\n    }\n\n    function mint(address _account, uint256 _amount) external onlyWhitelisted {\n        _mint(_account, _amount);\n    }\n\n    function burn(address _account, uint256 _amount) external onlyWhitelisted {\n        _burn(_account, _amount);\n    }\n\n    /**\n     * @notice check if a minter is whitelisted\n     * @param _account address of minter\n     * @return boolean, True if address is a whitelisted minter\n     */\n    function isWhitelistedMinter(address _account) external view returns (bool) {\n        return whitelistedMinters[_account];\n    }\n\n    /**\n     * @notice allows the minter to whitelist other minters\n     * @param _account address of minter to be whitelisted\n     */\n    function whitelistMinter(address _account) external onlyWhitelisted {\n        whitelistedMinters[_account] = true;\n\n        emit MinterWhitelisted(_account);\n    }\n\n    /**\n     * @notice allow the minter to blacklist other minters\n     * @param _account address of minter to be blacklisted\n     */\n    function blacklistMinter(address _account) external onlyWhitelisted {\n        whitelistedMinters[_account] = false;\n\n        emit MinterBlacklisted(_account);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/MockEuler.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity =0.7.6;\npragma abicoder v2;\n\ncontract MockEuler {\n    uint256 a;\n\n    function deferLiquidityCheck(address account, bytes memory data) external {\n        a;\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/MockEulerDToken.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockEulerDToken {\n    ERC20 weth;\n\n    constructor(address _weth) {\n        weth = ERC20(_weth);\n    }\n\n    function borrow(uint256, uint256 amount) external {\n        weth.transfer(msg.sender, amount);\n    }\n\n    function repay(uint256, uint256 amount) external {\n        weth.transferFrom(msg.sender, address(this), amount);\n    }\n\n    function underlyingAsset() external view returns (address) {\n        return address(weth);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/MockOracle.sol",
    "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.7.6;\n\ncontract MockOracle {\n    mapping(address => uint256) public poolPeriodPrice;\n    mapping(address => int24) public poolTick;\n\n    function setPrice(address _pool, uint256 _price) external {\n        poolPeriodPrice[_pool] = _price;\n    }\n\n    function setAverageTick(address _pool, int24 _poolTick) external {\n        poolTick[_pool] = _poolTick;\n    }\n\n    function getTimeWeightedAverageTickSafe(\n        address _pool,\n        uint32 /*_period*/\n    ) external view returns (int24) {\n        return poolTick[_pool];\n    }\n\n    function getTwap(\n        address _pool,\n        address,\n        address,\n        uint32,\n        bool\n    ) external view returns (uint256) {\n        return poolPeriodPrice[_pool];\n    }\n\n    function getMaxPeriod(address) external pure returns (uint32) {\n        return uint32(-1);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/MockShortPowerPerp.sol",
    "content": "//SPDX-License-Identifier: MIT\n\npragma solidity =0.7.6;\n\nimport {ERC721Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\";\n\ncontract MockShortPowerPerp is ERC721Upgradeable {\n    uint256 public nextId = 1;\n\n    function mintNFT(address _recipient) external returns (uint256 tokenId) {\n        _safeMint(_recipient, (tokenId = nextId++));\n    }\n\n    function burnNFT(uint256 _tokenId) external {\n        _burn(_tokenId);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/MockTimelock.sol",
    "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity =0.8.10;\n\nimport {Timelock} from \"../strategy/timelock/Timelock.sol\";\n\ncontract MockTimelock is Timelock {\n    constructor(address _admin, uint256 _delay) Timelock(_admin, _delay) {}\n\n    function executeVaultTransfer(address crab, address newStrategy) public returns (bool) {\n        (bool success, bytes memory result) = crab.call(abi.encodeWithSignature(\"transferVault(address)\", newStrategy));\n\n        return success;\n    }\n\n    function mockSetDelay(uint256 _delay) external {\n        delay = _delay;\n    }\n\n    function mockSetPendingAdmin(address _pendingAdmin) external {\n        pendingAdmin = _pendingAdmin;\n    }\n\n    function mockSetAdmin(address _admin) external {\n        admin = _admin;\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/MockUniPositionManager.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity =0.7.6;\npragma abicoder v2;\n\nimport {ERC721} from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {INonfungiblePositionManager} from \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\";\n\ncontract MockUniPositionManager is ERC721 {\n    int24 public tickLower;\n    int24 public tickUpper;\n    uint128 public liquidity;\n    address public token0;\n    address public token1;\n\n    uint256 token0ToCollect;\n    uint256 token1ToCollect;\n\n    constructor() ERC721(\"Uniswap Position\", \"UNIP\") {}\n\n    function mint(address account, uint256 tokenId) external {\n        _mint(account, tokenId);\n    }\n\n    function setMockedProperties(\n        address _token0,\n        address _token1,\n        int24 _tickLower,\n        int24 _tickUpper,\n        uint128 _liquidity\n    ) external {\n        token0 = _token0;\n        token1 = _token1;\n        tickLower = _tickLower;\n        tickUpper = _tickUpper;\n        liquidity = _liquidity;\n    }\n\n    function positions(uint256)\n        public\n        view\n        returns (\n            uint96, //nonce,\n            address, //operator,\n            address, //token0,\n            address, //token1,\n            uint24, // fee,\n            int24, // tickLower,\n            int24, // tickUpper,\n            uint128, // liquidity,\n            uint256, //feeGrowthInside0LastX128,\n            uint256, //feeGrowthInside1LastX128,\n            uint128, //tokensOwed0,\n            uint128 //tokensOwed1\n        )\n    {\n        // return 0 for everything\n        return (\n            0, //nonce,\n            address(0), //operator,\n            token0, //token0,\n            token1, //token1,\n            3000, // fee,\n            tickLower, // tickLower,\n            tickUpper, // tickUpper,\n            liquidity, // liquidity,\n            0, //feeGrowthInside0LastX128,\n            0, //feeGrowthInside1LastX128,\n            0, //tokensOwed0,\n            0 //tokensOwed1\n        );\n    }\n\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\n        token0ToCollect = amount0;\n        token1ToCollect = amount1;\n    }\n\n    // SPDX-License-Identifier: GPL-2.0-or-later\n    function decreaseLiquidity(\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\n    ) external view returns (uint256, uint256) {\n        return (token0ToCollect, token1ToCollect);\n    }\n\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\n        uint256 cachedAmount0 = token0ToCollect;\n        uint256 cachedAmount1 = token1ToCollect;\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\n        IERC20(token0).transfer(params.recipient, token0Amount);\n        IERC20(token1).transfer(params.recipient, token1Amount);\n        token0ToCollect = 0;\n        token1ToCollect = 0;\n        return (token0Amount, token1Amount);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/MockUniswapV3Pool.sol",
    "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.7.6;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\ninterface IUniswapV3FlashCallback {\n    function uniswapV3FlashCallback(\n        uint256 fee0,\n        uint256 fee1,\n        bytes calldata data\n    ) external;\n}\n\ncontract MockUniswapV3Pool {\n    using SafeMath for uint256;\n\n    address public token0;\n    address public token1;\n    uint256 public fee;\n\n    struct PoolKey {\n        address token0;\n        address token1;\n        uint24 fee;\n    }\n\n    struct Slot0 {\n        // the current price\n        uint160 sqrtPriceX96;\n        // the current tick\n        int24 tick;\n        // the most-recently updated index of the observations array\n        uint16 observationIndex;\n        // the current maximum number of observations that are being stored\n        uint16 observationCardinality;\n        // the next maximum number of observations to store, triggered in observations.write\n        uint16 observationCardinalityNext;\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\n        // represented as an integer denominator (1/x)%\n        uint8 feeProtocol;\n        // whether the pool is locked\n        bool unlocked;\n    }\n\n    Slot0 public slot0;\n\n    function setPoolTokens(address _token0, address _token1) external {\n        token0 = _token0;\n        token1 = _token1;\n    }\n\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\n        slot0.tick = _tick;\n    }\n\n    function flash(\n        address recipient,\n        uint256 amount0,\n        uint256 amount1,\n        bytes calldata data\n    ) external {\n        // uint128 _liquidity = liquidity;\n        // require(_liquidity > 0, 'L');\n\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\n        uint256 fee0 = 0;\n        uint256 fee1 = 0;\n\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\n\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\n\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\n\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\n\n        require(balance0Before.add(fee0) <= balance0After, \"F0\");\n        require(balance1Before.add(fee1) <= balance1After, \"F1\");\n    }\n\n    function computeAddress(\n        address, /*factory*/\n        PoolKey memory /*key*/\n    ) internal view returns (address pool) {\n        return address(this);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/MockWSqueeth.sol",
    "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.7.6;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockWPowerPerp is ERC20 {\n    address public controller;\n\n    constructor() ERC20(\"Wrapped Power Perp\", \"WPowerPerp\") {}\n\n    function mint(address _account, uint256 _amount) external {\n        _mint(_account, _amount);\n    }\n\n    function burn(address _account, uint256 _amount) external {\n        _burn(_account, _amount);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/mocks/OpynWETH9.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity =0.7.6;\n\ncontract OpynWETH9 {\n    address owner;\n\n    string public name = \"Wrapped Opyn Ether\";\n    string public symbol = \"OpynWETH\";\n    uint8 public decimals = 18;\n\n    event Approval(address indexed src, address indexed guy, uint256 wad);\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\n    event Deposit(address indexed dst, uint256 wad);\n    event Withdrawal(address indexed src, uint256 wad);\n    event MinterWhitelisted(address indexed account);\n    event MinterBlacklisted(address indexed account);\n\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n    mapping(address => bool) internal whitelistedMinters;\n\n    /**\n     * @notice check if the sender is whitelistd\n     */\n    modifier onlyWhitelisted() {\n        require(whitelistedMinters[msg.sender] || msg.sender == owner, \"Address not a whitelisted minter\");\n\n        _;\n    }\n\n    constructor() {\n        owner = msg.sender;\n    }\n\n    receive() external payable {\n        deposit();\n    }\n\n    function mint(address _to, uint256 _amount) public onlyWhitelisted {\n        balanceOf[_to] += _amount;\n        emit Deposit(_to, _amount);\n    }\n\n    function burn(address _from, uint256 _amount) public onlyWhitelisted {\n        balanceOf[_from] -= _amount;\n        emit Withdrawal(_from, _amount);\n    }\n\n    function deposit() public payable {\n        balanceOf[msg.sender] += msg.value;\n        emit Deposit(msg.sender, msg.value);\n    }\n\n    function withdraw(uint256 wad) public {\n        require(balanceOf[msg.sender] >= wad);\n        balanceOf[msg.sender] -= wad;\n        msg.sender.transfer(wad);\n        emit Withdrawal(msg.sender, wad);\n    }\n\n    function totalSupply() public view returns (uint256) {\n        return address(this).balance;\n    }\n\n    function approve(address guy, uint256 wad) public returns (bool) {\n        allowance[msg.sender][guy] = wad;\n        emit Approval(msg.sender, guy, wad);\n        return true;\n    }\n\n    function transfer(address dst, uint256 wad) public returns (bool) {\n        return transferFrom(msg.sender, dst, wad);\n    }\n\n    function transferFrom(\n        address src,\n        address dst,\n        uint256 wad\n    ) public returns (bool) {\n        require(balanceOf[src] >= wad);\n\n        if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) {\n            require(allowance[src][msg.sender] >= wad);\n            allowance[src][msg.sender] -= wad;\n        }\n\n        balanceOf[src] -= wad;\n        balanceOf[dst] += wad;\n\n        emit Transfer(src, dst, wad);\n\n        return true;\n    }\n\n    /**\n     * @notice check if a minter is whitelisted\n     * @param _account address of minter\n     * @return boolean, True if address is a whitelisted minter\n     */\n    function isWhitelistedMinter(address _account) external view returns (bool) {\n        return whitelistedMinters[_account];\n    }\n\n    /**\n     * @notice allows the minter to whitelist other minters\n     * @param _account address of minter to be whitelisted\n     */\n    function whitelistMinter(address _account) external onlyWhitelisted {\n        whitelistedMinters[_account] = true;\n\n        emit MinterWhitelisted(_account);\n    }\n\n    /**\n     * @notice allow the minter to blacklist other minters\n     * @param _account address of minter to be blacklisted\n     */\n    function blacklistMinter(address _account) external onlyWhitelisted {\n        whitelistedMinters[_account] = false;\n\n        emit MinterBlacklisted(_account);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/periphery/ControllerHelper.sol",
    "content": "//SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport {IWETH9} from \"../interfaces/IWETH9.sol\";\nimport {IWPowerPerp} from \"../interfaces/IWPowerPerp.sol\";\nimport {IShortPowerPerp} from \"../interfaces/IShortPowerPerp.sol\";\nimport {IController} from \"../interfaces/IController.sol\";\nimport {IUniswapV3Pool} from \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport {IERC721Receiver} from \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {INonfungiblePositionManager} from \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// contract\nimport {UniswapControllerHelper} from \"./UniswapControllerHelper.sol\";\nimport {EulerControllerHelper} from \"./EulerControllerHelper.sol\";\n\n// lib\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\nimport {ControllerHelperDataType} from \"./lib/ControllerHelperDataType.sol\";\nimport {ControllerHelperUtil} from \"./lib/ControllerHelperUtil.sol\";\nimport {VaultLib} from \"../libs/VaultLib.sol\";\n\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\n    using SafeMath for uint256;\n    using Address for address payable;\n\n    bool private immutable isWethToken0;\n    address private immutable controller;\n    address private immutable shortPowerPerp;\n    address private immutable wPowerPerp;\n    address private immutable weth;\n    address private immutable nonfungiblePositionManager;\n\n    constructor(\n        address _controller,\n        address _nonfungiblePositionManager,\n        address _uniswapFactory,\n        address _exec,\n        address _euler,\n        address _dToken\n    )\n        UniswapControllerHelper(_uniswapFactory)\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\n    {\n        controller = _controller;\n        shortPowerPerp = IController(_controller).shortPowerPerp();\n        wPowerPerp = IController(_controller).wPowerPerp();\n        weth = IController(_controller).weth();\n        nonfungiblePositionManager = _nonfungiblePositionManager;\n\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\n\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\n\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\n    }\n\n    /**\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\n     * @return returns received selector\n     */\n    function onERC721Received(\n        address,\n        address,\n        uint256,\n        bytes memory\n    ) public virtual override returns (bytes4) {\n        return this.onERC721Received.selector;\n    }\n\n    /**\n     * @notice receive function to allow ETH transfer to this contract\n     */\n    receive() external payable {}\n\n    /**\n     * @notice flash close position and buy long squeeth\n     * @dev this function\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\n     */\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\n        external\n        payable\n    {\n        _checkAccess(_params.vaultId);\n\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\n\n        wrapInternal(msg.value);\n\n        _exactOutFlashSwap(\n            weth,\n            wPowerPerp,\n            _params.poolFee,\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\n            _params.maxToPay,\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\n            abi.encode(_params)\n        );\n\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\n    }\n\n    /**\n     * @notice sell long wPowerPerp and flashswap mint short position\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\n     */\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\n        external\n        payable\n    {\n        if (_params.vaultId != 0) {\n            _checkAccess(_params.vaultId);\n        }\n\n        wrapInternal(msg.value);\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\n        // flashswap and mint short position\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\n        _exactInFlashSwap(\n            wPowerPerp,\n            weth,\n            _params.poolFee,\n            totalAmountIn,\n            _params.minToReceive,\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\n            abi.encode(_params)\n        );\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\n    }\n\n    /**\n     * @notice close short position with user Uniswap v3 LP NFT\n     * @dev user should approve this contract for Uni NFT transfer\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\n     */\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\n        external\n        payable\n    {\n        _checkAccess(_params.vaultId);\n\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\n            msg.sender,\n            address(this),\n            _params.tokenId\n        );\n\n        wrapInternal(msg.value);\n\n        // close LP position\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\n            nonfungiblePositionManager,\n            ControllerHelperDataType.CloseUniLpParams({\n                tokenId: _params.tokenId,\n                liquidity: _params.liquidity,\n                liquidityPercentage: _params.liquidityPercentage,\n                amount0Min: _params.amount0Min,\n                amount1Min: _params.amount1Min\n            }),\n            isWethToken0\n        );\n\n        // if LP position is not fully closed, redeposit in vault or send back to user\n        ControllerHelperUtil.checkClosedLp(\n            msg.sender,\n            controller,\n            nonfungiblePositionManager,\n            0,\n            _params.tokenId,\n            _params.liquidityPercentage\n        );\n        // burn vault debt using amounts withdrawn from LP position\n        _closeShortWithAmountsFromLp(\n            _params.vaultId,\n            wPowerPerpAmountInLp,\n            _params.wPowerPerpAmountToBurn,\n            _params.collateralToWithdraw,\n            _params.limitPriceEthPerPowerPerp,\n            _params.poolFee,\n            _params.burnExactRemoved\n        );\n\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\n    }\n\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\n        external\n        payable\n    {\n        _checkAccess(_params.vaultId);\n\n        wrapInternal(msg.value);\n        _flashLoan(\n            weth,\n            _params.collateralToFlashloan,\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\n            abi.encode(_params)\n        );\n\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\n    }\n\n    /**\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\n     */\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\n        if (_params.vaultId != 0) {\n            _checkAccess(_params.vaultId);\n        }\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\n\n        wrapInternal(msg.value);\n\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\n            controller,\n            nonfungiblePositionManager,\n            wPowerPerp,\n            weth,\n            _params,\n            isWethToken0\n        );\n\n        // if openeded new vault, transfer vault NFT to user\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\n\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\n    }\n\n    /**\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\n     */\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\n        external\n        payable\n    {\n        if (_params.vaultId != 0) {\n            _checkAccess(_params.vaultId);\n        }\n\n        wrapInternal(msg.value);\n        _flashLoan(\n            weth,\n            _params.collateralToFlashloan,\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\n            abi.encode(_params)\n        );\n\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\n    }\n\n    /**\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\n     */\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\n            msg.sender,\n            address(this),\n            _params.tokenId\n        );\n\n        // close LP NFT and get Weth and WPowerPerp amounts\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\n            nonfungiblePositionManager,\n            ControllerHelperDataType.CloseUniLpParams({\n                tokenId: _params.tokenId,\n                liquidity: _params.liquidity,\n                liquidityPercentage: _params.liquidityPercentage,\n                amount0Min: uint128(_params.amount0Min),\n                amount1Min: uint128(_params.amount1Min)\n            }),\n            isWethToken0\n        );\n\n        ControllerHelperUtil.checkClosedLp(\n            msg.sender,\n            controller,\n            nonfungiblePositionManager,\n            0,\n            _params.tokenId,\n            _params.liquidityPercentage\n        );\n\n        if (wPowerPerpAmountInLp > 0) {\n            _exactInFlashSwap(\n                wPowerPerp,\n                weth,\n                _params.poolFee,\n                wPowerPerpAmountInLp,\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\n                \"\"\n            );\n        }\n\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\n    }\n\n    /**\n     * @notice Rebalance LP nft through trading\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\n     */\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\n        external\n        payable\n    {\n        wrapInternal(msg.value);\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\n            msg.sender,\n            address(this),\n            _params.tokenId\n        );\n        // close LP NFT and get Weth and WPowerPerp amounts\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\n            nonfungiblePositionManager,\n            ControllerHelperDataType.CloseUniLpParams({\n                tokenId: _params.tokenId,\n                liquidity: _params.liquidity,\n                liquidityPercentage: 1e18,\n                amount0Min: uint128(_params.amount0Min),\n                amount1Min: uint128(_params.amount1Min)\n            }),\n            isWethToken0\n        );\n\n        ControllerHelperUtil.checkClosedLp(\n            msg.sender,\n            controller,\n            nonfungiblePositionManager,\n            0,\n            _params.tokenId,\n            1e18\n        );\n\n        uint256 wethAmountDesired;\n        uint256 wPowerPerpAmountDesired;\n\n        if (isWethToken0) {\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\n                _params.wPowerPerpPool,\n                _params.wethAmountDesired,\n                _params.wPowerPerpAmountDesired,\n                _params.lowerTick,\n                _params.upperTick,\n                isWethToken0\n            );\n        } else {\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\n                _params.wPowerPerpPool,\n                _params.wethAmountDesired,\n                _params.wPowerPerpAmountDesired,\n                _params.lowerTick,\n                _params.upperTick,\n                isWethToken0\n            );\n        }\n\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\n            _exactOutFlashSwap(\n                weth,\n                wPowerPerp,\n                _params.poolFee,\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\n                \"\"\n            );\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\n            _exactInFlashSwap(\n                wPowerPerp,\n                weth,\n                _params.poolFee,\n                wPowerPerpExcess,\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\n                \"\"\n            );\n        }\n\n        // mint new position\n        ControllerHelperUtil.lpWPowerPerpPool(\n            nonfungiblePositionManager,\n            _params.wPowerPerpPool,\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\n                recipient: msg.sender,\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\n                amount0Min: _params.amount0DesiredMin,\n                amount1Min: _params.amount1DesiredMin,\n                lowerTick: _params.lowerTick,\n                upperTick: _params.upperTick\n            })\n        );\n\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\n    }\n\n    /**\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\n     * @param _vaultId vault ID\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\n     */\n    function rebalanceLpInVault(\n        uint256 _vaultId,\n        uint256 _collateralToFlashloan,\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\n    ) external payable {\n        // check ownership\n        _checkAccess(_vaultId);\n\n        wrapInternal(msg.value);\n        _flashLoan(\n            weth,\n            _collateralToFlashloan,\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\n            abi.encode(_vaultId, _params)\n        );\n\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\n\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\n    }\n\n    /**\n     * @notice checks if the msg.sender is the owener of the vault\n     * @param _vaultId vault ID\n     */\n    function _checkAccess(uint256 _vaultId) internal view {\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\n    }\n\n    /**\n     * @notice gets the shortAmount that has been minted from a vault\n     * @param _vaultId vault ID\n     * @return short amount from vault\n     */\n\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\n\n        return vault.shortAmount;\n    }\n\n    function _flashCallback(\n        address _initiator,\n        address, /*_asset*/\n        uint256 _amount,\n        uint8 _callSource,\n        bytes memory _calldata\n    ) internal override {\n        if (\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\n        ) {\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\n                _calldata,\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\n            );\n\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\n                controller,\n                nonfungiblePositionManager,\n                wPowerPerp,\n                weth,\n                ControllerHelperDataType.MintAndLpParams({\n                    recipient: address(this),\n                    wPowerPerpPool: data.wPowerPerpPool,\n                    vaultId: data.vaultId,\n                    wPowerPerpAmount: data.wPowerPerpAmount,\n                    collateralToDeposit: data.collateralToDeposit,\n                    collateralToLp: data.collateralToLp,\n                    amount0Min: data.amount0Min,\n                    amount1Min: data.amount1Min,\n                    lowerTick: data.lowerTick,\n                    upperTick: data.upperTick\n                }),\n                isWethToken0\n            );\n\n            // deposit Uni NFT token in vault\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\n\n            ControllerHelperUtil.burnWithdrawFromVault(\n                controller,\n                weth,\n                vaultId,\n                0,\n                _amount.add(data.collateralToWithdraw)\n            );\n\n            // if openeded new vault, transfer vault NFT to user\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\n        } else if (\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\n        ) {\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\n                _calldata,\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\n            );\n\n            IWETH9(weth).withdraw(_amount);\n            IController(controller).deposit{value: _amount}(data.vaultId);\n\n            IController(controller).withdrawUniPositionToken(data.vaultId);\n\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\n                nonfungiblePositionManager,\n                ControllerHelperDataType.CloseUniLpParams({\n                    tokenId: data.tokenId,\n                    liquidity: data.liquidity,\n                    liquidityPercentage: data.liquidityPercentage,\n                    amount0Min: data.amount0Min,\n                    amount1Min: data.amount1Min\n                }),\n                isWethToken0\n            );\n\n            ControllerHelperUtil.checkClosedLp(\n                _initiator,\n                controller,\n                nonfungiblePositionManager,\n                data.vaultId,\n                data.tokenId,\n                data.liquidityPercentage\n            );\n\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\n            _closeShortWithAmountsFromLp(\n                data.vaultId,\n                wPowerPerpAmountInLp,\n                data.wPowerPerpAmountToBurn,\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\n                data.limitPriceEthPerPowerPerp,\n                data.poolFee,\n                data.burnExactRemoved\n            );\n        } else if (\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\n        ) {\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\n                _calldata,\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\n            );\n\n            // deposit collateral into vault and withdraw LP NFT\n            IWETH9(weth).withdraw(_amount);\n            IController(controller).deposit{value: _amount}(vaultId);\n            IController(controller).withdrawUniPositionToken(vaultId);\n            for (uint256 i; i < data.length; i++) {\n                if (\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\n                ) {\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\n                        data[i].data,\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\n                    );\n\n                    ControllerHelperUtil.increaseLpLiquidity(\n                        controller,\n                        nonfungiblePositionManager,\n                        wPowerPerp,\n                        increaseLiquidityParam.wPowerPerpPool,\n                        vaultId,\n                        increaseLiquidityParam,\n                        isWethToken0\n                    );\n\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\n                } else if (\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\n                ) {\n                    // decrease liquidity in LP\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\n                        data[i].data,\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\n                    );\n\n                    ControllerHelperUtil.closeUniLp(\n                        nonfungiblePositionManager,\n                        ControllerHelperDataType.CloseUniLpParams({\n                            tokenId: decreaseLiquidityParam.tokenId,\n                            liquidity: decreaseLiquidityParam.liquidity,\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\n                            amount0Min: decreaseLiquidityParam.amount0Min,\n                            amount1Min: decreaseLiquidityParam.amount1Min\n                        }),\n                        isWethToken0\n                    );\n\n                    // if LP position is not fully closed, redeposit into vault or send back to user\n                    ControllerHelperUtil.checkClosedLp(\n                        _initiator,\n                        controller,\n                        nonfungiblePositionManager,\n                        vaultId,\n                        decreaseLiquidityParam.tokenId,\n                        decreaseLiquidityParam.liquidityPercentage\n                    );\n                } else if (\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\n                ) {\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\n                        data[i].data,\n                        (ControllerHelperDataType.DepositIntoVaultParams)\n                    );\n\n                    // make sure not to fail\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\n\n                    ControllerHelperUtil.mintDepositInVault(\n                        controller,\n                        weth,\n                        vaultId,\n                        depositIntoVaultParams.wPowerPerpToMint,\n                        depositIntoVaultParams.collateralToDeposit\n                    );\n                } else if (\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\n                ) {\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\n                        data[i].data,\n                        (ControllerHelperDataType.withdrawFromVaultParams)\n                    );\n\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\n\n                    if (withdrawFromVaultParams.burnExactRemoved) {\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\n                        ControllerHelperUtil.burnWithdrawFromVault(\n                            controller,\n                            weth,\n                            vaultId,\n                            currentBalance,\n                            withdrawFromVaultParams.collateralToWithdraw\n                        );\n                    } else {\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\n                        ControllerHelperUtil.burnWithdrawFromVault(\n                            controller,\n                            weth,\n                            vaultId,\n                            withdrawFromVaultParams.wPowerPerpToBurn,\n                            withdrawFromVaultParams.collateralToWithdraw\n                        );\n                    }\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\n                    // this will execute in the use case of fully closing old LP position, and creating new one\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\n                        data[i].data,\n                        (ControllerHelperDataType.MintAndLpParams)\n                    );\n\n                    uint256 tokenId;\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\n                        controller,\n                        nonfungiblePositionManager,\n                        wPowerPerp,\n                        weth,\n                        mintAndLpParams,\n                        isWethToken0\n                    );\n                    // deposit Uni NFT token in vault\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\n                } else if (\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\n                ) {\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\n                        data[i].data,\n                        (ControllerHelperDataType.GeneralSwapParams)\n                    );\n\n                    require(\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\n                    );\n\n                    _exactInFlashSwap(\n                        swapParams.tokenIn,\n                        swapParams.tokenOut,\n                        swapParams.poolFee,\n                        swapParams.amountIn,\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\n                        \"\"\n                    );\n                } else if (\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\n                ) {\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\n                        data[i].data,\n                        (ControllerHelperDataType.CollectFeesParams)\n                    );\n\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\n                        .CollectParams({\n                            tokenId: collectFeesParams.tokenId,\n                            recipient: address(this),\n                            amount0Max: collectFeesParams.amount0Max,\n                            amount1Max: collectFeesParams.amount0Max\n                        });\n\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\n                } else if (\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\n                ) {\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\n                        data[i].data,\n                        (ControllerHelperDataType.DepositExistingNftParams)\n                    );\n\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\n                }\n            }\n\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\n        }\n    }\n\n    /**\n     * @notice uniswap flash swap callback function\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\n     * @param _caller address of original function caller\n     * @param _amountToPay amount to pay back for flashswap\n     * @param _callData arbitrary data attached to callback\n     * @param _callSource identifier for which function triggered callback\n     */\n    function _swapCallback(\n        address _caller,\n        address _tokenIn,\n        address _pool,\n        uint256 _amountToPay,\n        bytes memory _callData,\n        uint8 _callSource\n    ) internal override {\n        if (\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\n        ) {\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\n                _callData,\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\n            );\n\n            ControllerHelperUtil.burnWithdrawFromVault(\n                controller,\n                weth,\n                data.vaultId,\n                data.wPowerPerpAmountToBurn,\n                data.collateralToWithdraw\n            );\n\n            IWETH9(weth).transfer(_pool, _amountToPay);\n        } else if (\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\n        ) {\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\n                _callData,\n                (ControllerHelperDataType.FlashSellLongWMintParams)\n            );\n\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\n                    controller,\n                    weth,\n                    data.vaultId,\n                    data.wPowerPerpAmountToMint,\n                    data.collateralToDeposit\n                );\n\n                // this is a newly open vault, transfer to the user\n                if (data.vaultId == 0)\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\n            }\n\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\n        } else if (\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\n        ) {\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\n        } else if (\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\n        ) {\n            IWETH9(weth).transfer(_pool, _amountToPay);\n        } else if (\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\n        ) {\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\n                _callData,\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\n            );\n\n            ControllerHelperUtil.burnWithdrawFromVault(\n                controller,\n                weth,\n                data.vaultId,\n                data.wPowerPerpAmountToBurn,\n                data.collateralToWithdraw\n            );\n\n            IWETH9(weth).transfer(_pool, _amountToPay);\n        } else if (\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\n        ) {\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\n        }\n    }\n\n    /**\n     * @notice wrap ETH to WETH\n     * @param _amount amount to wrap\n     */\n    function wrapInternal(uint256 _amount) internal {\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\n    }\n\n    function _closeShortWithAmountsFromLp(\n        uint256 _vaultId,\n        uint256 _wPowerPerpAmount,\n        uint256 _wPowerPerpAmountToBurn,\n        uint256 _collateralToWithdraw,\n        uint256 _limitPriceEthPerPowerPerp,\n        uint24 _poolFee,\n        bool burnExactRemoved\n    ) private {\n        if (burnExactRemoved) {\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\n\n            ControllerHelperUtil.burnWithdrawFromVault(\n                controller,\n                weth,\n                _vaultId,\n                _wPowerPerpAmount,\n                _collateralToWithdraw\n            );\n        } else {\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\n                // swap needed wPowerPerp amount to close short position\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\n\n                _exactOutFlashSwap(\n                    weth,\n                    wPowerPerp,\n                    _poolFee,\n                    wPowerPerpDeficit,\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\n                );\n            } else {\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\n                ControllerHelperUtil.burnWithdrawFromVault(\n                    controller,\n                    weth,\n                    _vaultId,\n                    _wPowerPerpAmountToBurn,\n                    _collateralToWithdraw\n                );\n\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\n                if (wPowerPerpExcess > 0) {\n                    _exactInFlashSwap(\n                        wPowerPerp,\n                        weth,\n                        _poolFee,\n                        wPowerPerpExcess,\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\n                        \"\"\n                    );\n                }\n            }\n        }\n\n        // wrap ETH to WETH\n        wrapInternal(address(this).balance);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/periphery/EulerControllerHelper.sol",
    "content": "// SPDX-License-Identifier: agpl-3.0\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport {IERC20Detailed} from \"../interfaces/IERC20Detailed.sol\";\n\n// lib\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\ninterface IDeferredLiquidityCheck {\n    function onDeferredLiquidityCheck(bytes memory data) external;\n}\n\ninterface IExec {\n    function deferLiquidityCheck(address account, bytes memory data) external;\n}\n\ninterface IEulerDToken {\n    function borrow(uint256 subAccountId, uint256 amount) external;\n\n    function repay(uint256 subAccountId, uint256 amount) external;\n}\n\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\n    using SafeMath for uint256;\n\n    address public immutable exec;\n    address public immutable euler;\n    address public immutable token;\n    address public immutable dToken;\n\n    struct FlashloanCallbackData {\n        address caller;\n        address assetToBorrow;\n        uint256 amountToBorrow;\n        uint8 callSource;\n        bytes callData;\n    }\n\n    constructor(\n        address _exec,\n        address _euler,\n        address _token,\n        address _dToken\n    ) {\n        exec = _exec;\n        euler = _euler;\n        token = _token;\n        dToken = _dToken;\n    }\n\n    function _flashCallback(\n        address _initiator,\n        address _asset,\n        uint256 _amount,\n        uint8 _callSource,\n        bytes memory _calldata\n    ) internal virtual {}\n\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\n        // sanity checks\n        require(msg.sender == euler);\n\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\n\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\n\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\n\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\n    }\n\n    /**\n     */\n    function _flashLoan(\n        address _asset,\n        uint256 _amount,\n        uint8 _callSource,\n        bytes memory _data\n    ) internal {\n        // Disable the liquidity check for \"this\" and call-back into onDeferredLiquidityCheck:\n        IExec(exec).deferLiquidityCheck(\n            address(this),\n            abi.encode(\n                FlashloanCallbackData({\n                    caller: msg.sender,\n                    assetToBorrow: _asset,\n                    amountToBorrow: _amount,\n                    callSource: _callSource,\n                    callData: _data\n                })\n            )\n        );\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/periphery/LICENSE_GPL_3",
    "content": "\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>."
  },
  {
    "path": "packages/hardhat/contracts/periphery/ShortHelper.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\npragma abicoder v2;\n// Interfaces\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport {IERC721Receiver} from \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {ISwapRouter} from \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\n\nimport {IWPowerPerp} from \"../interfaces/IWPowerPerp.sol\";\nimport {IWETH9} from \"../interfaces/IWETH9.sol\";\nimport {IShortPowerPerp} from \"../interfaces/IShortPowerPerp.sol\";\nimport {IController} from \"../interfaces/IController.sol\";\n\n// Libraries\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\n */\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\n    using SafeMath for uint256;\n    using Address for address payable;\n\n    IController public immutable controller;\n    ISwapRouter public immutable router;\n    IWETH9 public immutable weth;\n    IShortPowerPerp public immutable shortPowerPerp;\n    address public immutable wPowerPerp;\n\n    /**\n     * @notice constructor for short helper\n     * @param _controllerAddr controller address for wPowerPerp\n     * @param _swapRouter uniswap v3 swap router address\n     * @param _wethAddr weth address\n     */\n    constructor(\n        address _controllerAddr,\n        address _swapRouter,\n        address _wethAddr\n    ) {\n        require(_controllerAddr != address(0), \"Invalid controller address\");\n        require(_swapRouter != address(0), \"Invalid swap router address\");\n        require(_wethAddr != address(0), \"Invalid weth address\");\n        IController _controller = IController(_controllerAddr);\n        router = ISwapRouter(_swapRouter);\n        wPowerPerp = _controller.wPowerPerp();\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\n        IWETH9 _weth = IWETH9(_wethAddr);\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\n        _weth.approve(_swapRouter, type(uint256).max);\n\n        // assign immutable variables\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\n        weth = _weth;\n        controller = _controller;\n    }\n\n    /**\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\n     * @param _vaultId short wPowerPerp vault id\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\n     * @param _uniNftId uniswap v3 position token id\n     */\n    function openShort(\n        uint256 _vaultId,\n        uint256 _powerPerpAmount,\n        uint256 _uniNftId,\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\n    ) external payable nonReentrant {\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \"Not allowed\");\n        require(\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\n            \"Wrong swap tokens\"\n        );\n\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\n            _vaultId,\n            _powerPerpAmount,\n            _uniNftId\n        );\n        _exactInputParams.amountIn = wPowerPerpAmount;\n\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\n\n        // if the recipient is this address: unwrap eth and send back to msg.sender\n        if (_exactInputParams.recipient == address(this)) {\n            weth.withdraw(amountOut);\n            payable(msg.sender).sendValue(amountOut);\n        }\n\n        // this is a newly open vault, transfer to the user.\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\n    }\n\n    /**\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\n     * @param _vaultId short wPowerPerp vault id\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\n     * @param _withdrawAmount amount to withdraw\n     */\n    function closeShort(\n        uint256 _vaultId,\n        uint256 _wPowerPerpAmount,\n        uint256 _withdrawAmount,\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\n    ) external payable nonReentrant {\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \"Not allowed\");\n        require(\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\n            \"Wrong swap tokens\"\n        );\n\n        // wrap eth to weth\n        weth.deposit{value: msg.value}();\n\n        // pay weth and get wPowerPerp in return.\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\n\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\n\n        // send back unused eth and withdrawn collateral\n        weth.withdraw(msg.value.sub(amountIn));\n        // no eth should be left in the contract, so we send it all back\n        payable(msg.sender).sendValue(address(this).balance);\n    }\n\n    /**\n     * @dev only receive eth from weth contract and controller.\n     */\n    receive() external payable {\n        require(msg.sender == address(weth) || msg.sender == address(controller), \"can't receive eth\");\n    }\n\n    /**\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\n     * @return returns received selector\n     */\n    function onERC721Received(\n        address,\n        address,\n        uint256,\n        bytes memory\n    ) public virtual override returns (bytes4) {\n        return this.onERC721Received.selector;\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/periphery/UniswapControllerHelper.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\";\nimport \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\";\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\n\n// lib\nimport \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\";\nimport \"@uniswap/v3-periphery/contracts/libraries/Path.sol\";\nimport \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\";\nimport \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\";\nimport \"@uniswap/v3-core/contracts/libraries/TickMath.sol\";\nimport \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\";\n\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\n    using Path for bytes;\n    using SafeCast for uint256;\n    using LowGasSafeMath for uint256;\n    using LowGasSafeMath for int256;\n\n    /// @dev Uniswap factory address\n    address public immutable factory;\n\n    struct SwapCallbackData {\n        bytes path;\n        address caller;\n        uint8 callSource;\n        bytes callData;\n    }\n\n    /**\n     * @dev constructor\n     * @param _factory uniswap factory address\n     */\n    constructor(address _factory) {\n        require(_factory != address(0));\n        factory = _factory;\n    }\n\n    /**\n     * @notice uniswap swap callback function for flashswap\n     * @param amount0Delta amount of token0\n     * @param amount1Delta amount of token1\n     * @param _data callback data encoded as SwapCallbackData struct\n     */\n    function uniswapV3SwapCallback(\n        int256 amount0Delta,\n        int256 amount1Delta,\n        bytes calldata _data\n    ) external override {\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\n\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\n\n        //ensure that callback comes from uniswap pool\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\n\n        //determine the amount that needs to be repaid as part of the flashswap\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\n\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\n    }\n\n    /**\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\n     * @param _tokenIn token address to sell\n     * @param _tokenOut token address to receive\n     * @param _fee pool fee\n     * @param _amountIn amount to sell\n     * @param _amountOutMinimum minimum amount to receive\n     * @param _callSource function call source\n     * @param _data arbitrary data assigned with the call\n     */\n    function _exactInFlashSwap(\n        address _tokenIn,\n        address _tokenOut,\n        uint24 _fee,\n        uint256 _amountIn,\n        uint256 _amountOutMinimum,\n        uint8 _callSource,\n        bytes memory _data\n    ) internal returns (uint256) {\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\n        uint256 amountOut = _exactInputInternal(\n            _amountIn,\n            address(this),\n            uint160(0),\n            SwapCallbackData({\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\n                caller: msg.sender,\n                callSource: _callSource,\n                callData: _data\n            })\n        );\n\n        //slippage limit check\n        require(amountOut >= _amountOutMinimum);\n\n        return amountOut;\n    }\n\n    /**\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\n     * @param _tokenIn token address to sell\n     * @param _tokenOut token address to receive\n     * @param _fee pool fee\n     * @param _amountOut exact amount to receive\n     * @param _amountInMaximum maximum amount to sell\n     * @param _callSource function call source\n     * @param _data arbitrary data assigned with the call\n     */\n    function _exactOutFlashSwap(\n        address _tokenIn,\n        address _tokenOut,\n        uint24 _fee,\n        uint256 _amountOut,\n        uint256 _amountInMaximum,\n        uint8 _callSource,\n        bytes memory _data\n    ) internal {\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\n        uint256 amountIn = _exactOutputInternal(\n            _amountOut,\n            address(this),\n            uint160(0),\n            SwapCallbackData({\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\n                caller: msg.sender,\n                callSource: _callSource,\n                callData: _data\n            })\n        );\n\n        //slippage limit check\n        require(amountIn <= _amountInMaximum);\n    }\n\n    /**\n     * @notice function to be called by uniswap callback.\n     * @dev this function should be overridden by the child contract\n     * param _caller initial strategy function caller\n     * param _tokenIn token address sold\n     * param _tokenOut token address bought\n     * param _fee pool fee\n     * param _amountToPay amount to pay for the pool second token\n     * param _callData arbitrary data assigned with the flashswap call\n     * param _callSource function call source\n     */\n    function _swapCallback(\n        address _caller,\n        address _tokenIn,\n        address _pool,\n        uint256 _amountToPay,\n        bytes memory _callData,\n        uint8 _callSource\n    ) internal virtual {}\n\n    /**\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\n     * @param _amountIn amount of token to pay\n     * @param _recipient recipient for receive\n     * @param _sqrtPriceLimitX96 price limit\n     * @return amount of token bought (amountOut)\n     */\n    function _exactInputInternal(\n        uint256 _amountIn,\n        address _recipient,\n        uint160 _sqrtPriceLimitX96,\n        SwapCallbackData memory data\n    ) private returns (uint256) {\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\n        //uniswap token0 has a lower address than token1\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\n        //zeroForOne determines which token is being sold and which is being bought\n        bool zeroForOne = tokenIn < tokenOut;\n\n        //swap on uniswap, including data to trigger call back for flashswap\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\n            _recipient,\n            zeroForOne,\n            _amountIn.toInt256(),\n            _sqrtPriceLimitX96 == 0\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\n                : _sqrtPriceLimitX96,\n            abi.encode(data)\n        );\n\n        //determine the amountOut based on which token has a lower address\n        return uint256(-(zeroForOne ? amount1 : amount0));\n    }\n\n    /**\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\n     * @param _amountOut amount of token to receive\n     * @param _recipient recipient for receive\n     * @param _sqrtPriceLimitX96 price limit\n     * @return amount of token sold (amountIn)\n     */\n    function _exactOutputInternal(\n        uint256 _amountOut,\n        address _recipient,\n        uint160 _sqrtPriceLimitX96,\n        SwapCallbackData memory data\n    ) private returns (uint256) {\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\n\n        //uniswap token0 has a lower address than token1\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\n        //zeroForOne determines which token is being sold and which is being bought\n        bool zeroForOne = tokenIn < tokenOut;\n\n        //swap on uniswap, including data to trigger call back for flashswap\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\n            _recipient,\n            zeroForOne,\n            -_amountOut.toInt256(),\n            _sqrtPriceLimitX96 == 0\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\n                : _sqrtPriceLimitX96,\n            abi.encode(data)\n        );\n\n        //determine the amountIn and amountOut based on which token has a lower address\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\n            : (uint256(amount1Delta), uint256(-amount0Delta));\n        // it's technically possible to not receive the full output amount,\n        // so if no price limit has been specified, require this possibility away\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\n\n        return amountIn;\n    }\n\n    /**\n     * @notice returns the uniswap pool for the given token pair and fee\n     * @dev the pool contract may or may not exist\n     * @param tokenA address of first token\n     * @param tokenB address of second token\n     * @param fee fee tier for pool\n     */\n    function _getPool(\n        address tokenA,\n        address tokenB,\n        uint24 fee\n    ) internal view returns (address) {\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/periphery/lib/ControllerHelperDataType.sol",
    "content": "pragma solidity =0.7.6;\npragma abicoder v2;\n\n//SPDX-License-Identifier: BUSL-1.1\n\n// interface\nimport {INonfungiblePositionManager} from \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\";\nimport {IUniswapV3Pool} from \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport {IController} from \"../../interfaces/IController.sol\";\n\n// lib\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nlibrary ControllerHelperDataType {\n    using SafeMath for uint256;\n\n    /// @dev enum to differentiate between uniswap swap callback function source\n    enum CALLBACK_SOURCE {\n        FLASH_W_MINT,\n        FLASH_W_BURN,\n        FLASH_SELL_LONG_W_MINT,\n        SWAP_EXACTIN_WPOWERPERP_ETH,\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\n        GENERAL_SWAP\n    }\n\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\n    enum RebalanceVaultNftType {\n        IncreaseLpLiquidity,\n        DecreaseLpLiquidity,\n        DepositIntoVault,\n        WithdrawFromVault,\n        MintNewLp,\n        generalSwap,\n        CollectFees, \n        DepositExistingNft\n    }\n    \n    /// @dev params for flashswapWBurnBuyLong()\n    struct FlashswapWBurnBuyLongParams {\n        uint256 vaultId;    // vault ID\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\n        uint24 poolFee;     // uniswap pool fee\n    }\n\n    /// @dev params for flashswapSellLongWMint()\n    struct FlashSellLongWMintParams {\n        uint256 vaultId;    // vault ID\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\n        uint24 poolFee;     // uniswap pool fee\n    }\n\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\n    struct SwapExactoutEthWPowerPerpData {\n        uint256 vaultId; // vault ID\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\n    }\n\n    /// @dev params for CloseShortWithUserNft()\n    struct CloseShortWithUserNftParams {\n        uint256 vaultId; // vault ID\n        uint256 tokenId; // Uni NFT token ID\n        uint256 liquidity;  // liquidity amount in LP \n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\n        uint24 poolFee;      // uniswap pool fee\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\n    }\n\n    /// @dev params for wMintLp()\n    struct MintAndLpParams {\n        address recipient;  // recipient address\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\n        uint256 vaultId;    // vault ID\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\n        uint256 collateralToDeposit;    // collateral to deposit into vault\n        uint256 collateralToLp; // collateral amount to LP\n        uint256 amount0Min; // minimum amount to LP of asset0\n        uint256 amount1Min; // minimum amount to LP of asset1\n        int24 lowerTick;    // LP lower tick\n        int24 upperTick;    // LP upper tick\n    }\n\n    /// @dev params for flashloanWMintDepositNft()\n    struct FlashloanWMintLpDepositNftParams {\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\n        uint256 vaultId; // vault ID (could be zero)\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\n        uint256 amount0Min; // minimum amount of token0 to LP\n        uint256 amount1Min; // minimum amount of token1 to LP\n        int24 lowerTick; // range lower tick to LP in\n        int24 upperTick; // range upper tick to LP in\n    }\n\n    /// @dev params for flashloanCloseVaultLpNft()\n    struct FlashloanCloseVaultLpNftParam {\n        uint256 vaultId; // vault ID\n        uint256 tokenId; // Uni NFT token ID\n        uint256 liquidity; // amount of liquidity in LP position\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\n        uint24 poolFee;     // uniswap pool fee\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\n    }\n\n    /// @dev params for _closeUniLp() \n    struct CloseUniLpParams {\n        uint256 tokenId;    // Uni v3 NFT id\n        uint256 liquidity;  // LP liquidity amount\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\n    }\n\n    /// @dev params for sellAll()\n    struct ReduceLiquidityAndSellParams {\n        uint256 tokenId;    // Uni token ID\n        uint256 liquidity;  // LP liquidity amount\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\n    }\n\n    /// @dev params for rebalanceLpWithoutVault()\n    struct RebalanceLpWithoutVaultParams {\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\n        uint256 tokenId;    // Uni token ID\n        uint256 liquidity;  // LP liquidity amount\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\n        uint256 wethAmountDesired;  // WETH amount to LP\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\n        uint256 amount0Min; // amount min to get when closing LP for asset0\n        uint256 amount1Min; // amount min to get when closing LP for asset1\n        int24 lowerTick;    // LP lower tick\n        int24 upperTick;    // LP upper tick\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\n    }\n\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\n    struct LpWPowerPerpPoolParams {\n        address recipient;  // recipient address\n        uint256 amount0Desired; // amount desired to LP for asset0\n        uint256 amount1Desired; // amount desired to LP for asset1\n        uint256 amount0Min; // amount min to LP for asset0\n        uint256 amount1Min; // amount min to LP for asset1\n        int24 lowerTick;    // LP lower tick\n        int24 upperTick;    // LP upper tick\n    }\n\n    /// @dev params for rebalanceLpInVault()\n    struct RebalanceLpInVaultParams {\n        RebalanceVaultNftType rebalanceLpInVaultType;\n        bytes data;\n    }\n\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\n    struct IncreaseLpLiquidityParams {\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\n        uint256 tokenId;    // Uni v3 NFT token id\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\n        uint256 collateralToDeposit;    // collateral to deposit into vault\n        uint256 wethAmountToLp; // WETH amount to LP\n        uint256 amount0Min; // amount min to get for LPing of asset0\n        uint256 amount1Min; // amount min to get for LPing of asset1\n    }\n\n    /// @dev struct for decrease liquidity in LP position\n    struct DecreaseLpLiquidityParams {  \n        uint256 tokenId;    // Uni v3 NFT token id\n        uint256 liquidity;  // LP liquidity amount\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\n        uint128 amount0Min; // amount min to get for LPing of asset0\n        uint128 amount1Min; // amount min to get for LPing of asset1\n    }\n\n    /// @dev struct for minting into vault\n    struct DepositIntoVaultParams {\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\n        uint256 collateralToDeposit;    // collateral amount to deposit\n    }\n\n    /// @dev struct for withdrawing from vault\n    struct withdrawFromVaultParams {  \n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\n        uint256 collateralToWithdraw;   // collateral to withdraw\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\n    }\n\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\n    struct GeneralSwapParams {\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\n        uint256 amountIn; // amount to swap in\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\n    }\n\n    /// @dev struct for collecting fees owed from a uniswap NFT\n    struct CollectFeesParams {\n        uint256 tokenId;\n        uint128 amount0Max;\n        uint128 amount1Max;\n    }\n\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\n    struct DepositExistingNftParams {\n        uint256 tokenId;    // Uni v3 NFT id\n    }\n}"
  },
  {
    "path": "packages/hardhat/contracts/periphery/lib/ControllerHelperUtil.sol",
    "content": "//SPDX-License-Identifier: BUSL-1.1\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport {INonfungiblePositionManager} from \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\";\nimport {IUniswapV3Pool} from \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport {IController} from \"../../interfaces/IController.sol\";\nimport {IWPowerPerp} from \"../../interfaces/IWPowerPerp.sol\";\nimport {IWETH9} from \"../../interfaces/IWETH9.sol\";\nimport {IOracle} from \"../../interfaces/IOracle.sol\";\n\n// lib\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\nimport {ControllerHelperDataType} from \"./ControllerHelperDataType.sol\";\nimport {LiquidityAmounts} from \"./LiquidityAmounts.sol\";\nimport {TickMathExternal} from \"../../libs/TickMathExternal.sol\";\n\nlibrary ControllerHelperUtil {\n    using SafeMath for uint256;\n    using Address for address payable;\n\n    /**\n     * @notice fully or partially close Uni v3 LP\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\n     * @return withdrawn wPowerPerp and WETH amounts\n     */\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\n            .DecreaseLiquidityParams({\n                tokenId: _params.tokenId,\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\n                amount0Min: _params.amount0Min,\n                amount1Min: _params.amount1Min,\n                deadline: block.timestamp\n            });\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\n\n        uint256 wethAmount;\n        uint256 _wPowerPerpAmount;\n        (_isWethToken0)\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\n                INonfungiblePositionManager.CollectParams({\n                    tokenId: _params.tokenId,\n                    recipient: address(this),\n                    amount0Max: type(uint128).max,\n                    amount1Max: type(uint128).max\n                })\n            )\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\n            INonfungiblePositionManager.CollectParams({\n                tokenId: _params.tokenId,\n                recipient: address(this),\n                amount0Max: type(uint128).max,\n                amount1Max: type(uint128).max\n            })\n        );\n\n        return (_wPowerPerpAmount, wethAmount);\n    }\n\n    /**\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\n     * @param _collateralToLp amount of ETH collateral to LP\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\n     * @param _lowerTick LP position lower tick\n     * @param _upperTick LP position upper tick\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\n     * @return exact amount0 and amount1 to be LPed\n     */\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\n        uint256 amount0Desired; \n        uint256 amount1Desired;\n\n        {\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\n        }\n        \n        return (amount0Desired, amount1Desired);\n    }\n\n    /**\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\n     * @param _controller wPowerPerp controller address\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\n     * @return _vaultId and tokenId\n     */\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\n\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\n                \n        uint256 _vaultId = _mintAndLpParams.vaultId;\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\n                _mintAndLpParams.vaultId,\n                amountToMint,\n                0\n            );\n        }\n        // LP amount0Desired and amount1Desired in Uni v3\n        uint256 uniTokenId = lpWPowerPerpPool(\n            _nonfungiblePositionManager,\n            _mintAndLpParams.wPowerPerpPool,\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\n                recipient: _mintAndLpParams.recipient,\n                amount0Desired: amount0Desired,\n                amount1Desired: amount1Desired,\n                amount0Min: _mintAndLpParams.amount0Min,\n                amount1Min: _mintAndLpParams.amount1Min,\n                lowerTick: _mintAndLpParams.lowerTick,\n                upperTick: _mintAndLpParams.upperTick\n            })\n        );\n        return (_vaultId, uniTokenId);\n    }\n\n    /**\n     * @notice increase liquidityin Uni v3 position\n     * @param _controller controller address\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\n     * @param _vaultId vault Id\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\n     */\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\n            (\n                ,\n                ,\n                ,\n                ,\n                ,\n                int24 tickLower,\n                int24 tickUpper,\n                ,\n                ,\n                ,\n                ,\n                \n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\n\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\n\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\n                    _vaultId,\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\n                    0\n                );\n            }\n        }\n\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\n            tokenId: _increaseLiquidityParam.tokenId,\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\n            amount0Min: _increaseLiquidityParam.amount0Min,\n            amount1Min: _increaseLiquidityParam.amount1Min,\n            deadline: block.timestamp\n        });\n\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\n    }\n\n    /**\n     * @notice mint wPowerPerp in vault\n     * @param _controller controller address\n     * @param _weth WETH address\n     * @param _vaultId vault Id\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\n     * @param _collateralToDeposit amount of collateral to deposit\n     */\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\n\n        uint256 vaultId = _vaultId;\n        if (_wPowerPerpToMint > 0) {\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\n                _vaultId,\n                _wPowerPerpToMint,\n                0\n            );\n        } else {\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\n        }\n        return vaultId;\n    }\n\n    /**\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\n     * @param _controller controller address\n     * @param _weth weth address\n     * @param _vaultId vault Id\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\n     * @param _collateralToWithdraw amount of collateral to withdraw\n     */\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\n        IController(_controller).burnWPowerPerpAmount(\n            _vaultId,\n            _wPowerPerpToBurn,\n            _collateralToWithdraw\n        );\n\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\n    }\n\n    /**\n     * @notice LP into Uniswap V3 pool\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\n     */\n    function lpWPowerPerpPool(\n        address _nonfungiblePositionManager,\n        address _wPowerPerpPool,\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\n    ) public returns (uint256) {\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\n            tickLower: int24(_params.lowerTick),\n            tickUpper: int24(_params.upperTick),\n            amount0Desired: _params.amount0Desired,\n            amount1Desired: _params.amount1Desired,\n            amount0Min: _params.amount0Min,\n            amount1Min: _params.amount1Min,\n            recipient: _params.recipient,\n            deadline: block.timestamp\n        });\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\n            mintParams\n        );\n        return tokenId;\n    }\n\n    /**\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\n     * @param _user user address\n     * @param _controller controller address\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\n     * @param _vaultId vault ID\n     * @param _tokenId Uni LP NFT id\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\n     */\n    function checkClosedLp(\n        address _user,\n        address _controller,\n        address _nonfungiblePositionManager,\n        uint256 _vaultId,\n        uint256 _tokenId,\n        uint256 _liquidityPercentage\n    ) public {\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\n                address(this),\n                _user,\n                _tokenId\n            );\n        } else {\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\n        }\n    }\n\n    /**\n     * @notice send ETH and wPowerPerp\n     * @param _weth WETH address\n     * @param _wPowerPerp wPowerPerp address\n     */\n    function sendBack(address _weth, address _wPowerPerp) public {\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\n        payable(msg.sender).sendValue(address(this).balance);\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\n        if (wPowerPerpBalance > 0) {\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\n        }\n    }\n}"
  },
  {
    "path": "packages/hardhat/contracts/periphery/lib/LiquidityAmounts.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\nimport {SqrtPriceMathPartial} from \"../../libs/SqrtPriceMathPartial.sol\";\nimport \"@uniswap/v3-core/contracts/libraries/TickMath.sol\";\n\n\n/// @title Liquidity amount functions\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\nlibrary LiquidityAmounts {\n    /// @notice Downcasts uint256 to uint128\n    /// @param x The uint258 to be downcasted\n    /// @return y The passed value, downcasted to uint128\n    function toUint128(uint256 x) private pure returns (uint128 y) {\n        require((y = uint128(x)) == x);\n    }\n\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n    /// @param amount0 The amount0 being sent in\n    /// @return liquidity The amount of returned liquidity\n    function getLiquidityForAmount0(\n        uint160 sqrtRatioAX96,\n        uint160 sqrtRatioBX96,\n        uint256 amount0\n    ) internal pure returns (uint128 liquidity) {\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\n    }\n\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n    /// @param amount1 The amount1 being sent in\n    /// @return liquidity The amount of returned liquidity\n    function getLiquidityForAmount1(\n        uint160 sqrtRatioAX96,\n        uint160 sqrtRatioBX96,\n        uint256 amount1\n    ) internal pure returns (uint128 liquidity) {\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\n    }\n\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\n    /// pool prices and the prices at the tick boundaries\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n    /// @param amount0 The amount of token0 being sent in\n    /// @param amount1 The amount of token1 being sent in\n    /// @return liquidity The maximum amount of liquidity received\n    function getLiquidityForAmounts(\n        uint160 sqrtRatioX96,\n        uint160 sqrtRatioAX96,\n        uint160 sqrtRatioBX96,\n        uint256 amount0,\n        uint256 amount1\n    ) internal pure returns (uint128 liquidity) {\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\n\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\n        } else {\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\n        }\n    }\n\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n    /// @param liquidity The liquidity being valued\n    /// @return amount0 The amount of token0\n    function getAmount0ForLiquidity(\n        uint160 sqrtRatioAX96,\n        uint160 sqrtRatioBX96,\n        uint128 liquidity\n    ) internal pure returns (uint256 amount0) {\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n\n        return\n            FullMath.mulDiv(\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\n                sqrtRatioBX96 - sqrtRatioAX96,\n                sqrtRatioBX96\n            ) / sqrtRatioAX96;\n    }\n\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n    /// @param liquidity The liquidity being valued\n    /// @return amount1 The amount of token1\n    function getAmount1ForLiquidity(\n        uint160 sqrtRatioAX96,\n        uint160 sqrtRatioBX96,\n        uint128 liquidity\n    ) internal pure returns (uint256 amount1) {\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\n    }\n\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\n    /// pool prices and the prices at the tick boundaries\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n    /// @param liquidity The liquidity being valued\n    /// @return amount0 The amount of token0\n    /// @return amount1 The amount of token1\n    function getAmountsForLiquidity(\n        uint160 sqrtRatioX96,\n        uint160 sqrtRatioAX96,\n        uint160 sqrtRatioBX96,\n        uint128 liquidity\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\n        } else {\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\n        }\n    }\n\n    function getAmountsFromLiquidity(        \n        uint160 sqrtRatioX96,\n        int24 currentTick,\n        int24 tickLower,\n        int24 tickUpper,\n        uint128 liquidity\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\n        if (currentTick < tickLower) {\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\n                TickMath.getSqrtRatioAtTick(tickLower),\n                TickMath.getSqrtRatioAtTick(tickUpper),\n                liquidity,\n                false\n            );\n        } else if (currentTick < tickUpper) {\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\n                sqrtRatioX96,\n                TickMath.getSqrtRatioAtTick(tickUpper),\n                liquidity,\n                false\n            );\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\n                TickMath.getSqrtRatioAtTick(tickLower),\n                sqrtRatioX96,\n                liquidity,\n                false\n            );\n        } else {\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\n                TickMath.getSqrtRatioAtTick(tickLower),\n                TickMath.getSqrtRatioAtTick(tickUpper),\n                liquidity,\n                false\n            );\n            }\n    \n    }\n\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/strategy/AGPL_3",
    "content": "Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n\nEveryone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.\n\nPreamble\n\nThe GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software.\n\nThe licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users.\n\nWhen we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.\n\nDevelopers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software.\n\nA secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public.\n\nThe GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version.\n\nAn older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license.\n\nThe precise terms and conditions for copying, distribution and modification follow.\n\nTERMS AND CONDITIONS\n\n0. Definitions.\n\"This License\" refers to version 3 of the GNU Affero General Public License.\n\n\"Copyright\" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.\n\n\"The Program\" refers to any copyrightable work licensed under this License. Each licensee is addressed as \"you\". \"Licensees\" and \"recipients\" may be individuals or organizations.\n\nTo \"modify\" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a \"modified version\" of the earlier work or a work \"based on\" the earlier work.\n\nA \"covered work\" means either the unmodified Program or a work based on the Program.\n\nTo \"propagate\" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.\n\nTo \"convey\" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.\n\nAn interactive user interface displays \"Appropriate Legal Notices\" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.\n\n1. Source Code.\nThe \"source code\" for a work means the preferred form of the work for making modifications to it. \"Object code\" means any non-source form of a work.\nA \"Standard Interface\" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.\n\nThe \"System Libraries\" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A \"Major Component\", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.\n\nThe \"Corresponding Source\" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\nThe Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.\n\nThe Corresponding Source for a work in source code form is that same work.\n\n2. Basic Permissions.\nAll rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.\nYou may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.\n\nConveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.\n\n3. Protecting Users' Legal Rights From Anti-Circumvention Law.\nNo covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.\nWhen you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.\n\n4. Conveying Verbatim Copies.\nYou may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.\nYou may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.\n\n5. Conveying Modified Source Versions.\nYou may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:\na) The work must carry prominent notices stating that you modified it, and giving a relevant date.\nb) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to \"keep intact all notices\".\nc) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.\nd) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.\nA compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an \"aggregate\" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.\n\n6. Conveying Non-Source Forms.\nYou may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:\na) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.\nb) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.\nc) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.\nd) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.\ne) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.\nA separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.\n\nA \"User Product\" is either (1) a \"consumer product\", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, \"normally used\" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.\n\n\"Installation Information\" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.\n\nIf you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).\n\nThe requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.\n\nCorresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.\n\n7. Additional Terms.\n\"Additional permissions\" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.\nWhen you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.\n\nNotwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:\n\na) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or\nb) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or\nc) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or\nd) Limiting the use for publicity purposes of names of licensors or authors of the material; or\ne) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or\nf) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.\nAll other non-permissive additional terms are considered \"further restrictions\" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.\n\nIf you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.\n\nAdditional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.\n\n8. Termination.\nYou may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).\n\nHowever, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.\n\nMoreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.\n\nTermination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.\n\n9. Acceptance Not Required for Having Copies.\nYou are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.\n\n10. Automatic Licensing of Downstream Recipients.\nEach time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.\n\nAn \"entity transaction\" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.\n\nYou may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.\n\n11. Patents.\nA \"contributor\" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's \"contributor version\".\n\nA contributor's \"essential patent claims\" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, \"control\" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.\n\nEach contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.\n\nIn the following three paragraphs, a \"patent license\" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To \"grant\" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.\n\nIf you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent\nlicense to downstream recipients. \"Knowingly relying\" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.\n\nIf, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.\n\nA patent license is \"discriminatory\" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.\n\nNothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.\n\n12. No Surrender of Others' Freedom.\nIf conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may\nnot convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.\n\n13. Remote Network Interaction; Use with the GNU General Public License.\nNotwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph.\n\nNotwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License.\n\n14. Revised Versions of this License.\nThe Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License \"or any later version\" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation.\n\nIf the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.\n\nLater license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.\n\n15. Disclaimer of Warranty.\nTHERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n16. Limitation of Liability.\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\n17. Interpretation of Sections 15 and 16.\nIf the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.\n\n"
  },
  {
    "path": "packages/hardhat/contracts/strategy/CrabHelper.sol",
    "content": "//SPDX-License-Identifier: BUSL-1.1\n\npragma solidity =0.7.6;\n\nimport {ICrabStrategyV2} from \"../interfaces/ICrabStrategyV2.sol\";\nimport {IWETH9} from \"../interfaces/IWETH9.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport {StrategySwap} from \"./helper/StrategySwap.sol\";\n\n/**\n * @dev CrabHelper contract\n * @notice Contract for Crab helper functions\n * @author Opyn team\n */\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\n    using Address for address payable;\n\n    address public immutable crab;\n    address public immutable weth;\n\n    event FlashDepositERC20(\n        address indexed depositor,\n        address depositedERC20,\n        uint256 depositedAmount,\n        uint256 depositedEthAmount,\n        uint256 crabAmount,\n        uint256 returnedEth\n    );\n\n    event FlashWithdrawERC20(\n        address indexed withdrawer,\n        address withdrawnERC20,\n        uint256 withdrawnAmount,\n        uint256 withdrawnEthAmount,\n        uint256 crabAmount\n    );\n\n    /**\n     * @notice constructor\n     * @param _crab address of crabV2 contract\n     * @param _swapRouter address of Uniswap swap router\n     */\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\n        require(_crab != address(0), \"Invalid crab address\");\n\n        crab = _crab;\n        weth = ICrabStrategyV2(_crab).weth();\n    }\n\n    /**\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\n     * @param _ethToDeposit amount of ETH to deposit\n     * @param _amountIn amount of ERC20 token to swap for weth\n     * @param _minEthToGet min amount of ETH to receive in the swap\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\n     * @param _tokenIn ERC20 token to pay\n     */\n    function flashDepositERC20(\n        uint256 _ethToDeposit,\n        uint256 _amountIn,\n        uint256 _minEthToGet,\n        uint24 _erc20Fee,\n        uint24 _wPowerPerpFee,\n        address _tokenIn\n    ) external nonReentrant {\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\n\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\n\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\n\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\n\n        IERC20(crab).transfer(msg.sender, crabAmount);\n\n        if (address(this).balance > 0) {\n            payable(msg.sender).sendValue(address(this).balance);\n        }\n    }\n\n    /**\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\n     * @param _crabAmount amount of crab shares to withdraw\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\n     * @param _tokenOut ERC20 token to receive\n     * @param _minAmountOut min amount of ERC20 to receive\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\n     */\n    function flashWithdrawERC20(\n        uint256 _crabAmount,\n        uint256 _maxEthToPay,\n        address _tokenOut,\n        uint256 _minAmountOut,\n        uint24 _erc20Fee,\n        uint24 _wPowerPerpFee\n    ) external nonReentrant {\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\n\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\n\n        uint256 ethBalance = address(this).balance;\n        IWETH9(weth).deposit{value: ethBalance}();\n        uint256 tokenReceived = _swapExactInputSingle(\n            weth,\n            _tokenOut,\n            address(this),\n            msg.sender,\n            ethBalance,\n            _minAmountOut,\n            _erc20Fee\n        );\n\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\n    }\n\n    /**\n     * @notice receive function to allow ETH transfer to this contract\n     */\n    receive() external payable {\n        require(msg.sender == weth || msg.sender == crab, \"Cannot receive eth\");\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/strategy/CrabMigration.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport {IEulerExec, IDToken} from \"../interfaces/IEuler.sol\";\nimport {WETH9} from \"../external/WETH9.sol\";\n\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n// contract\nimport {CrabStrategyV2} from \"./CrabStrategyV2.sol\";\nimport {CrabStrategy} from \"./CrabStrategy.sol\";\nimport {StrategyMath} from \"./base/StrategyMath.sol\";\n\n/**\n * Migration Error Codes:\n * M1: Migration already happened\n * M2: Migration has not yet happened\n * M3: msg.sender is not Euler Mainnet Contract\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\n * M5: Can't withdraw more than you own\n * M6: Not enough ETH to repay the loan\n * M7: Invalid crabV2 address\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\n * M10: Wrong migration function, use flashMigrateFromV1toV2\n * M11: crabV2 address not yet set\n */\n\n/**\n * @dev CrabMigration contract\n * @notice Contract for Migrating from Crab V1 to Crab V2\n * @author Opyn team\n */\ncontract CrabMigration is Ownable {\n    using SafeERC20 for IERC20;\n    using StrategyMath for uint256;\n    using Address for address payable;\n\n    mapping(address => uint256) public sharesDeposited;\n    bool public isMigrated;\n\n    address payable public crabV1;\n    address payable public crabV2;\n    address public immutable euler;\n    address public immutable weth;\n\n    address immutable EULER_MAINNET;\n    address immutable dToken;\n    address immutable wPowerPerp;\n\n    struct FlashloanCallbackData {\n        address caller;\n        uint256 amountToBorrow;\n        uint8 callSource;\n        bytes callData;\n    }\n\n    struct BatchMigrate {\n        uint256 strategyCap;\n    }\n\n    struct FlashMigrateV1toV2 {\n        uint256 v1oSqthToPay;\n        uint256 ethToFlashDeposit;\n        uint256 crabV1ToWithdraw;\n        uint24 poolFee;\n    }\n\n    struct FlashMigrateAndBuyV1toV2 {\n        uint256 v1oSqthToPay;\n        uint256 ethToFlashDeposit;\n        uint256 withdrawMaxEthToPay;\n        uint256 crabV1ToWithdraw;\n        uint24 poolFeeFlashDeposit;\n    }\n\n    enum FLASH_SOURCE {\n        BATCH_MIGRATE,\n        FLASH_MIGRATE_V1_TO_V2,\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\n    }\n\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\n\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\n\n    modifier beforeMigration() {\n        require(!isMigrated, \"M1\");\n        _;\n    }\n\n    modifier afterMigration() {\n        require(isMigrated, \"M2\");\n        _;\n    }\n\n    modifier afterInitialized() {\n        require(crabV2 != address(0), \"M11\");\n        _;\n    }\n\n    /**\n     * @notice migration constructor\n     * @param _crabV1 address of crab V1\n     * @param _weth address of weth\n     * @param _eulerExec address of euler exec contract\n     * @param _dToken address of euler liability token\n     * @param _eulerMainnet address of euler deployment on mainnet\n     */\n    constructor(\n        address payable _crabV1,\n        address _weth,\n        address _eulerExec,\n        address _dToken,\n        address _eulerMainnet\n    ) {\n        require(_eulerExec != address(0), \"invalid _eulerExec address\");\n        require(_dToken != address(0), \"invalid _dToken address\");\n        require(_eulerMainnet != address(0), \"invalid _eulerMainnet address\");\n        require(_weth != address(0), \"invalid _weth address\");\n        require(_crabV1 != address(0), \"invalid _crabv1 address\");\n        require(IDToken(_dToken).underlyingAsset() == _weth, \"dToken underlying asset should be weth\");\n\n        crabV1 = _crabV1;\n        euler = _eulerExec;\n        EULER_MAINNET = _eulerMainnet;\n        weth = _weth;\n        dToken = _dToken;\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\n    }\n\n    /**\n     * @notice set the crabV2 address\n     * @param _crabV2 address of crab V2\n     */\n    function setCrabV2(address payable _crabV2) external onlyOwner {\n        require(_crabV2 != address(0), \"M7\");\n        crabV2 = _crabV2;\n    }\n\n    /**\n     * @notice deposit crab V1 shares in the pool for migration\n     * @param _amount amount of crabV1 shares to deposit\n     */\n    function depositV1Shares(uint256 _amount) external beforeMigration {\n        sharesDeposited[msg.sender] += _amount;\n\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\n\n        emit DepositV1Shares(msg.sender, _amount);\n    }\n\n    /**\n     * @notice withdraw crab V1 shares in the pool before migration\n     * @param _amount amount of V1 shares to withdraw\n     */\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\n\n        emit WithdrawV1Shares(msg.sender, _amount);\n    }\n\n    /**\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\n     * the V2 contract at the same collateral ratio as the V1 contract\n     * @param _strategyCap strategy cap in ETH\n     */\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\n        // 1. update isMigrated\n        isMigrated = true;\n\n        // 2. flash floan eth from euler eq to amt\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\n        IEulerExec(euler).deferLiquidityCheck(\n            address(this),\n            abi.encode(\n                FlashloanCallbackData({\n                    caller: msg.sender,\n                    amountToBorrow: amountEthToBorrow,\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\n                })\n            )\n        );\n    }\n\n    /**\n     * @notice Euler callback function\n     * @param encodedData callback data\n     */\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\n        require(msg.sender == EULER_MAINNET, \"M3\");\n\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\n\n        // 1. borrow weth\n        IDToken(dToken).borrow(0, data.amountToBorrow);\n        WETH9(weth).withdraw(data.amountToBorrow);\n\n        // 2. callback\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\n\n        // 3. repay the weth\n        WETH9(weth).deposit{value: data.amountToBorrow}();\n        IDToken(dToken).repay(0, data.amountToBorrow);\n    }\n\n    /**\n     * @notice callback function for flash actions\n     * @param _initiator address of original function caller\n     * @param _amount  amount to pay back for flashswap\n     * @param _callSource identifier for which function triggered callback\n     * @param _calldata arbitrary data attached to callback\n\n     */\n    function _flashCallback(\n        address _initiator,\n        uint256 _amount,\n        uint8 _callSource,\n        bytes memory _calldata\n    ) internal {\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\n\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\n\n            // 2. mint osqth in crab V2\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\n                wSqueethToMint,\n                crabV1Balance,\n                timeAtLastHedge,\n                priceAtLastHedge,\n                data.strategyCap\n            );\n\n            // 3. call withdraw from crab V1\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\n\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\n\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\n\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\n\n            // flash deposit remaining ETH, otherwise refund\n            // if CR1 = CR2 ethToFlashDeposit should be 0\n            if (data.ethToFlashDeposit > 0) {\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\n                    data.ethToFlashDeposit,\n                    data.poolFee\n                );\n            }\n\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\n            // send back V2 tokens to the user\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\n\n            uint256 excessEth = address(this).balance;\n\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\n\n            // send back excess ETH\n            if (excessEth > _amount) {\n                payable(_initiator).sendValue(excessEth.sub(_amount));\n            }\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\n\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\n\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\n\n            // find crab amount for contract's sqth balance\n            // remaining crab can be withdrawn using flash withdraw\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\n\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\n\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\n            require(address(this).balance >= _amount, \"M6\");\n\n            if (data.ethToFlashDeposit > 0) {\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\n                    data.ethToFlashDeposit,\n                    data.poolFeeFlashDeposit\n                );\n            }\n\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\n\n            // send V2 tokens to the user\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\n\n            uint256 excessEth = address(this).balance;\n\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\n\n            // send back the excess ETH\n            if (excessEth > _amount) {\n                payable(_initiator).sendValue(excessEth.sub(_amount));\n            }\n        }\n    }\n\n    /**\n     * @notice claim crab V2 shares\n     */\n    function claimV2Shares() external afterMigration {\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\n        sharesDeposited[msg.sender] = 0;\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\n    }\n\n    /**\n     * @notice claim crab V2 shares and flash withdraw from crab V2\n     * @param _amountToWithdraw V2 shares to claim\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\n     * @param _poolFee Uniswap pool fee for flash withdraw\n     */\n    function claimAndWithdraw(\n        uint256 _amountToWithdraw,\n        uint256 _maxEthToPay,\n        uint24 _poolFee\n    ) external afterMigration {\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\n        require(_amountToWithdraw <= amountV1Deposited, \"M5\");\n\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\n\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\n\n        // send eth to user\n        payable(msg.sender).sendValue(address(this).balance);\n    }\n\n    /**\n     * @notice view details of flash migration for specified amount of V1 shares\n     * @param _v1Shares amount of crab V1 shares\n     */\n    function flashMigrationDetails(uint256 _v1Shares)\n        external\n        view\n        returns (\n            bool,\n            uint256,\n            uint256,\n            uint256\n        )\n    {\n        return _flashMigrationDetails(_v1Shares);\n    }\n\n    /**\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\n     * @param _v1Shares V1 shares to migrate\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\n     * @param _poolFee uniswap pool fee for flash deposit\n     */\n    function flashMigrateFromV1toV2(\n        uint256 _v1Shares,\n        uint256 _ethToFlashDeposit,\n        uint24 _poolFee\n    ) external afterMigration {\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\n\n        require(isFlashOnlyMigrate, \"M9\");\n\n        IEulerExec(euler).deferLiquidityCheck(\n            address(this),\n            abi.encode(\n                FlashloanCallbackData({\n                    caller: msg.sender,\n                    amountToBorrow: ethNeededForV2,\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\n                    callData: abi.encode(\n                        FlashMigrateV1toV2({\n                            v1oSqthToPay: v1oSqthToPay,\n                            ethToFlashDeposit: _ethToFlashDeposit,\n                            crabV1ToWithdraw: _v1Shares,\n                            poolFee: _poolFee\n                        })\n                    )\n                })\n            )\n        );\n    }\n\n    /**\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\n     * @param _v1Shares V1 shares to migrate\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\n     */\n    function flashMigrateAndWithdrawFromV1toV2(\n        uint256 _v1Shares,\n        uint256 _ethToFlashDeposit,\n        uint256 _ethToBorrow,\n        uint256 _withdrawMaxEthToPay,\n        uint24 _poolFee\n    ) external afterMigration {\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\n\n        require(!isFlashOnlyMigrate, \"M10\");\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \"M8\");\n\n        IEulerExec(euler).deferLiquidityCheck(\n            address(this),\n            abi.encode(\n                FlashloanCallbackData({\n                    caller: msg.sender,\n                    amountToBorrow: _ethToBorrow,\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\n                    callData: abi.encode(\n                        FlashMigrateAndBuyV1toV2({\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\n                            ethToFlashDeposit: _ethToFlashDeposit,\n                            v1oSqthToPay: v1oSqthToPay,\n                            crabV1ToWithdraw: _v1Shares,\n                            poolFeeFlashDeposit: _poolFee\n                        })\n                    )\n                })\n            )\n        );\n    }\n\n    /**\n     * @notice get migration details for given amount of V1 shares\n     * @param _v1Shares amount of crab V1 shares\n     */\n    function _flashMigrationDetails(uint256 _v1Shares)\n        internal\n        view\n        returns (\n            bool,\n            uint256,\n            uint256,\n            uint256\n        )\n    {\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\n\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\n\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\n    }\n\n    /**\n     * @notice receive function to allow ETH transfer to this contract\n     */\n    receive() external payable {\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \"M4\");\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/strategy/CrabStrategy.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport {IController} from \"../interfaces/IController.sol\";\nimport {IWPowerPerp} from \"../interfaces/IWPowerPerp.sol\";\nimport {IOracle} from \"../interfaces/IOracle.sol\";\nimport {IWETH9} from \"../interfaces/IWETH9.sol\";\nimport {IUniswapV3Pool} from \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport {IController} from \"../interfaces/IController.sol\";\n\n// contract\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport {StrategyBase} from \"./base/StrategyBase.sol\";\nimport {StrategyFlashSwap} from \"./base/StrategyFlashSwap.sol\";\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n// lib\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n// StrategyMath licensed under AGPL-3.0-only\nimport {StrategyMath} from \"./base/StrategyMath.sol\";\nimport {Power2Base} from \"../libs/Power2Base.sol\";\n\n/**\n * @dev CrabStrategy contract\n * @notice Contract for Crab strategy\n * @author Opyn team\n */\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\n    using StrategyMath for uint256;\n    using Address for address payable;\n\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\n    uint256 public strategyCap;\n\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\n    /// @dev twap period to use for hedge calculations\n    uint32 public hedgingTwapPeriod = 420 seconds;\n\n    /// @dev enum to differentiate between uniswap swap callback function source\n    enum FLASH_SOURCE {\n        FLASH_DEPOSIT,\n        FLASH_WITHDRAW,\n        FLASH_HEDGE_SELL,\n        FLASH_HEDGE_BUY\n    }\n\n    /// @dev ETH:WSqueeth uniswap pool\n    address public immutable ethWSqueethPool;\n    /// @dev strategy uniswap oracle\n    address public immutable oracle;\n    address public immutable ethQuoteCurrencyPool;\n    address public immutable quoteCurrency;\n\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\n    uint256 public deltaHedgeThreshold = 1e15;\n    /// @dev time difference to trigger a hedge (seconds)\n    uint256 public hedgeTimeThreshold;\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\n    uint256 public hedgePriceThreshold;\n    /// @dev hedge auction duration (seconds)\n    uint256 public auctionTime;\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\n    uint256 public minPriceMultiplier;\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\n    uint256 public maxPriceMultiplier;\n\n    /// @dev timestamp when last hedge executed\n    uint256 public timeAtLastHedge;\n    /// @dev WSqueeth/Eth price when last hedge executed\n    uint256 public priceAtLastHedge;\n\n    /// @dev set to true when redeemShortShutdown has been called\n    bool private hasRedeemedInShutdown;\n\n    struct FlashDepositData {\n        uint256 totalDeposit;\n    }\n\n    struct FlashWithdrawData {\n        uint256 crabAmount;\n    }\n\n    struct FlashHedgeData {\n        uint256 wSqueethAmount;\n        uint256 ethProceeds;\n        uint256 minWSqueeth;\n        uint256 minEth;\n    }\n\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\n    event TimeHedgeOnUniswap(\n        address indexed hedger,\n        uint256 hedgeTimestamp,\n        uint256 auctionTriggerTimestamp,\n        uint256 minWSqueeth,\n        uint256 minEth\n    );\n    event PriceHedgeOnUniswap(\n        address indexed hedger,\n        uint256 hedgeTimestamp,\n        uint256 auctionTriggerTimestamp,\n        uint256 minWSqueeth,\n        uint256 minEth\n    );\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\n    event Hedge(\n        address indexed hedger,\n        bool auctionType,\n        uint256 hedgerPrice,\n        uint256 auctionPrice,\n        uint256 wSqueethHedgeTargetAmount,\n        uint256 ethHedgetargetAmount\n    );\n    event HedgeOnUniswap(\n        address indexed hedger,\n        bool auctionType,\n        uint256 auctionPrice,\n        uint256 wSqueethHedgeTargetAmount,\n        uint256 ethHedgetargetAmount\n    );\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\n    event SetStrategyCap(uint256 newCapAmount);\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\n    event SetAuctionTime(uint256 newAuctionTime);\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\n\n    /**\n     * @notice strategy constructor\n     * @dev this will open a vault in the power token contract and store the vault ID\n     * @param _wSqueethController power token controller address\n     * @param _oracle oracle address\n     * @param _weth weth address\n     * @param _uniswapFactory uniswap factory address\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\n     * @param _auctionTime auction duration (seconds)\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\n     */\n    constructor(\n        address _wSqueethController,\n        address _oracle,\n        address _weth,\n        address _uniswapFactory,\n        address _ethWSqueethPool,\n        uint256 _hedgeTimeThreshold,\n        uint256 _hedgePriceThreshold,\n        uint256 _auctionTime,\n        uint256 _minPriceMultiplier,\n        uint256 _maxPriceMultiplier\n    ) StrategyBase(_wSqueethController, _weth, \"Crab Strategy\", \"Crab\") StrategyFlashSwap(_uniswapFactory) {\n        require(_oracle != address(0), \"invalid oracle address\");\n        require(_ethWSqueethPool != address(0), \"invalid ETH:WSqueeth address\");\n        require(_hedgeTimeThreshold > 0, \"invalid hedge time threshold\");\n        require(_hedgePriceThreshold > 0, \"invalid hedge price threshold\");\n        require(_auctionTime > 0, \"invalid auction time\");\n        require(_minPriceMultiplier < 1e18, \"min price multiplier too high\");\n        require(_minPriceMultiplier > 0, \"invalid min price multiplier\");\n        require(_maxPriceMultiplier > 1e18, \"max price multiplier too low\");\n\n        oracle = _oracle;\n        ethWSqueethPool = _ethWSqueethPool;\n        hedgeTimeThreshold = _hedgeTimeThreshold;\n        hedgePriceThreshold = _hedgePriceThreshold;\n        auctionTime = _auctionTime;\n        minPriceMultiplier = _minPriceMultiplier;\n        maxPriceMultiplier = _maxPriceMultiplier;\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\n    }\n\n    /**\n     * @notice receive function to allow ETH transfer to this contract\n     */\n    receive() external payable {\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \"Cannot receive eth\");\n    }\n\n    /**\n     * @notice owner can set the strategy cap in ETH collateral terms\n     * @dev deposits are rejected if it would put the strategy above the cap amount\n     * @dev strategy collateral can be above the cap amount due to hedging activities\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\n     */\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\n        strategyCap = _capAmount;\n\n        emit SetStrategyCap(_capAmount);\n    }\n\n    /**\n     * @notice called to redeem the net value of a vault post shutdown\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\n     */\n    function redeemShortShutdown() external {\n        hasRedeemedInShutdown = true;\n        powerTokenController.redeemShort(vaultId);\n    }\n\n    /**\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\n     */\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\n\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\n            _ethToDeposit,\n            cachedStrategyDebt,\n            cachedStrategyCollateral\n        );\n\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\n            // store hedge data as strategy is delta neutral at this point\n            // only execute this upon first deposit\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\n                ethWSqueethPool,\n                wPowerPerp,\n                weth,\n                hedgingTwapPeriod,\n                true\n            );\n            timeAtLastHedge = block.timestamp;\n            priceAtLastHedge = wSqueethEthPrice;\n        }\n\n        _exactInFlashSwap(\n            wPowerPerp,\n            weth,\n            IUniswapV3Pool(ethWSqueethPool).fee(),\n            wSqueethToMint,\n            _ethToDeposit.sub(msg.value),\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\n            abi.encodePacked(_ethToDeposit)\n        );\n\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\n    }\n\n    /**\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\n     * @param _crabAmount strategy token amount to burn\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\n     */\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\n\n        _exactOutFlashSwap(\n            weth,\n            wPowerPerp,\n            IUniswapV3Pool(ethWSqueethPool).fee(),\n            exactWSqueethNeeded,\n            _maxEthToPay,\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\n            abi.encodePacked(_crabAmount)\n        );\n\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\n    }\n\n    /**\n     * @notice deposit ETH into strategy\n     * @dev provide ETH, return wSqueeth and strategy token\n     */\n    function deposit() external payable nonReentrant {\n        uint256 amount = msg.value;\n\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\n\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\n    }\n\n    /**\n     * @notice withdraw WETH from strategy\n     * @dev provide strategy tokens and wSqueeth, returns eth\n     * @param _crabAmount amount of strategy token to burn\n     */\n    function withdraw(uint256 _crabAmount) external nonReentrant {\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\n\n        // send back ETH collateral\n        payable(msg.sender).sendValue(ethToWithdraw);\n\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\n    }\n\n    /**\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\n     * @param _crabAmount amount of strategy token to burn\n     */\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\n        require(powerTokenController.isShutDown(), \"Squeeth contracts not shut down\");\n        require(hasRedeemedInShutdown, \"Crab must redeemShortShutdown\");\n\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\n        _burn(msg.sender, _crabAmount);\n\n        payable(msg.sender).sendValue(ethToWithdraw);\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\n    }\n\n    /**\n     * @notice hedge startegy based on time threshold with uniswap arbing\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\n     * @dev between uniswap execution price and the price of the hedging auction\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\n     */\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\n\n        require(isTimeHedgeAllowed, \"Time hedging is not allowed\");\n\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\n\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\n    }\n\n    /**\n     * @notice hedge startegy based on price threshold with uniswap arbing\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\n     * @dev between uniswap execution price and the price of the hedging auction\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\n     */\n    function priceHedgeOnUniswap(\n        uint256 _auctionTriggerTime,\n        uint256 _minWSqueeth,\n        uint256 _minEth\n    ) external payable {\n        require(_isPriceHedge(_auctionTriggerTime), \"Price hedging not allowed\");\n\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\n\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\n    }\n\n    /**\n     * @notice strategy hedging based on time threshold\n     * @dev need to attach msg.value if buying WSqueeth\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\n     */\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\n\n        require(isTimeHedgeAllowed, \"Time hedging is not allowed\");\n\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\n\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\n    }\n\n    /**\n     * @notice strategy hedging based on price threshold\n     * @dev need to attach msg.value if buying WSqueeth\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\n     */\n    function priceHedge(\n        uint256 _auctionTriggerTime,\n        bool _isStrategySellingWSqueeth,\n        uint256 _limitPrice\n    ) external payable nonReentrant {\n        require(_isPriceHedge(_auctionTriggerTime), \"Price hedging not allowed\");\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\n\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\n    }\n\n    /**\n     * @notice check if hedging based on price threshold is allowed\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\n     * @return true if hedging is allowed\n     */\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\n        return _isPriceHedge(_auctionTriggerTime);\n    }\n\n    /**\n     * @notice check if hedging based on time threshold is allowed\n     * @return isTimeHedgeAllowed true if hedging is allowed\n     * @return auctionTriggertime auction trigger timestamp\n     */\n    function checkTimeHedge() external view returns (bool, uint256) {\n        return _isTimeHedge();\n    }\n\n    /**\n     * @notice get wSqueeth debt amount associated with strategy token amount\n     * @param _crabAmount strategy token amount\n     * @return wSqueeth amount\n     */\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\n        return _getDebtFromStrategyAmount(_crabAmount);\n    }\n\n    /**\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\n     */\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\n        deltaHedgeThreshold = _deltaHedgeThreshold;\n\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\n    }\n\n    /**\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\n     * @param _hedgingTwapPeriod the twap period, in seconds\n     */\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\n        require(_hedgingTwapPeriod >= 180, \"twap period is too short\");\n\n        hedgingTwapPeriod = _hedgingTwapPeriod;\n\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\n    }\n\n    /**\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\n     */\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\n        require(_hedgeTimeThreshold > 0, \"invalid hedge time threshold\");\n\n        hedgeTimeThreshold = _hedgeTimeThreshold;\n\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\n    }\n\n    /**\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\n     */\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\n        require(_hedgePriceThreshold > 0, \"invalid hedge price threshold\");\n\n        hedgePriceThreshold = _hedgePriceThreshold;\n\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\n    }\n\n    /**\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\n     * @param _auctionTime the length of the hedge auction in seconds\n     */\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\n        require(_auctionTime > 0, \"invalid auction time\");\n\n        auctionTime = _auctionTime;\n\n        emit SetAuctionTime(_auctionTime);\n    }\n\n    /**\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\n     */\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\n        require(_minPriceMultiplier < 1e18, \"min price multiplier too high\");\n\n        minPriceMultiplier = _minPriceMultiplier;\n\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\n    }\n\n    /**\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\n     */\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\n        require(_maxPriceMultiplier > 1e18, \"max price multiplier too low\");\n\n        maxPriceMultiplier = _maxPriceMultiplier;\n\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\n    }\n\n    /**\n     * @notice get current auction details\n     * @param _auctionTriggerTime timestamp where auction started\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\n     */\n    function getAuctionDetails(uint256 _auctionTriggerTime)\n        external\n        view\n        returns (\n            bool,\n            uint256,\n            uint256,\n            uint256,\n            bool\n        )\n    {\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\n            ethWSqueethPool,\n            wPowerPerp,\n            weth,\n            hedgingTwapPeriod,\n            true\n        );\n        uint256 feeAdjustment = _calcFeeAdjustment();\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\n            strategyDebt,\n            ethDelta,\n            auctionWSqueethEthPrice,\n            feeAdjustment\n        );\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\n\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\n    }\n\n    /**\n     * @notice check if a user deposit puts the strategy above the cap\n     * @dev reverts if a deposit amount puts strategy over the cap\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\n     * @param _depositAmount the user deposit amount in ETH\n     * @param _strategyCollateral the updated strategy collateral\n     */\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \"Deposit exceeds strategy cap\");\n    }\n\n    /**\n     * @notice uniswap flash swap callback function\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\n     * @param _caller address of original function caller\n     * @param _amountToPay amount to pay back for flashswap\n     * @param _callData arbitrary data attached to callback\n     * @param _callSource identifier for which function triggered callback\n     */\n    function _strategyFlash(\n        address _caller,\n        address, /*_tokenIn*/\n        address, /*_tokenOut*/\n        uint24, /*_fee*/\n        uint256 _amountToPay,\n        bytes memory _callData,\n        uint8 _callSource\n    ) internal override {\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\n\n            // convert WETH to ETH as Uniswap uses WETH\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\n\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\n            //will revert if data.totalDeposit is > eth balance in contract\n            _deposit(_caller, data.totalDeposit, true);\n\n            //repay the flash swap\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\n\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\n\n            //return excess eth to the user that was not needed for slippage\n            if (address(this).balance > 0) {\n                payable(_caller).sendValue(address(this).balance);\n            }\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\n\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\n            uint256 ethToWithdraw = _withdraw(\n                _caller,\n                data.crabAmount,\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\n                true\n            );\n\n            //use some amount of withdrawn ETH to repay flash swap\n            IWETH9(weth).deposit{value: _amountToPay}();\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\n\n            //excess ETH not used to repay flash swap is transferred to the user\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\n\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\n\n            if (proceeds > 0) {\n                payable(_caller).sendValue(proceeds);\n            }\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\n            //strategy is selling wSqueeth for ETH\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\n\n            // convert WETH to ETH as Uniswap uses WETH\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\n\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\n\n            //minimum profit check for hedger\n            require(wSqueethProfit >= data.minWSqueeth, \"profit is less than min wSqueeth\");\n\n            //repay flash swap and transfer profit to hedger\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\n            //strategy is buying wSqueeth for ETH\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\n\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\n\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\n\n            //minimum profit check for hedger\n            require(ethProfit >= data.minEth, \"profit is less than min ETH\");\n\n            //repay flash swap and transfer profit to hedger\n            IWETH9(weth).deposit{value: _amountToPay}();\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\n            payable(_caller).sendValue(ethProfit);\n        }\n    }\n\n    /**\n     * @notice deposit into strategy\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\n     * @param _depositor depositor address\n     * @param _amount amount of ETH collateral to deposit\n     * @param _isFlashDeposit true if called by flashDeposit\n     * @return wSqueethToMint minted amount of WSqueeth\n     * @return depositorCrabAmount minted CRAB strategy token amount\n     */\n    function _deposit(\n        address _depositor,\n        uint256 _amount,\n        bool _isFlashDeposit\n    ) internal returns (uint256, uint256) {\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\n        _checkStrategyCap(_amount, strategyCollateral);\n\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\n\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\n\n        if (strategyDebt == 0 && strategyCollateral == 0) {\n            // store hedge data as strategy is delta neutral at this point\n            // only execute this upon first deposit\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\n                ethWSqueethPool,\n                wPowerPerp,\n                weth,\n                hedgingTwapPeriod,\n                true\n            );\n            timeAtLastHedge = block.timestamp;\n            priceAtLastHedge = wSqueethEthPrice;\n        }\n\n        // mint wSqueeth and send it to msg.sender\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\n        // mint LP to depositor\n        _mintStrategyToken(_depositor, depositorCrabAmount);\n\n        return (wSqueethToMint, depositorCrabAmount);\n    }\n\n    /**\n     * @notice withdraw WETH from strategy\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\n     * @param _crabAmount amount of strategy token to burn\n     * @param _wSqueethAmount amount of wSqueeth to burn\n     * @param _isFlashWithdraw flag if called by flashWithdraw\n     * @return ETH amount to withdraw\n     */\n    function _withdraw(\n        address _from,\n        uint256 _crabAmount,\n        uint256 _wSqueethAmount,\n        bool _isFlashWithdraw\n    ) internal returns (uint256) {\n        (, uint256 strategyCollateral) = _syncStrategyState();\n\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\n\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\n        _burn(_from, _crabAmount);\n\n        return ethToWithdraw;\n    }\n\n    /**\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\n     * @param _auctionTriggerTime timestamp where auction started\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\n     */\n    function _hedge(\n        uint256 _auctionTriggerTime,\n        bool _isStrategySellingWSqueeth,\n        uint256 _limitPrice\n    ) internal {\n        (\n            bool isSellingAuction,\n            uint256 wSqueethToAuction,\n            uint256 ethProceeds,\n            uint256 auctionWSqueethEthPrice\n        ) = _startAuction(_auctionTriggerTime);\n\n        require(_isStrategySellingWSqueeth == isSellingAuction, \"wrong auction type\");\n\n        if (isSellingAuction) {\n            // Receiving ETH and paying wSqueeth\n            require(auctionWSqueethEthPrice <= _limitPrice, \"Auction price > max price\");\n            require(msg.value >= ethProceeds, \"Low ETH amount received\");\n\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\n        } else {\n            require(msg.value == 0, \"ETH attached for buy auction\");\n            // Receiving wSqueeth and paying ETH\n            require(auctionWSqueethEthPrice >= _limitPrice, \"Auction price < min price\");\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\n        }\n\n        emit Hedge(\n            msg.sender,\n            _isStrategySellingWSqueeth,\n            _limitPrice,\n            auctionWSqueethEthPrice,\n            wSqueethToAuction,\n            ethProceeds\n        );\n    }\n\n    /**\n     * @notice execute arb between auction price and uniswap price\n     * @param _auctionTriggerTime auction starting time\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\n     */\n    function _hedgeOnUniswap(\n        uint256 _auctionTriggerTime,\n        uint256 _minWSqueeth,\n        uint256 _minEth\n    ) internal {\n        (\n            bool isSellingAuction,\n            uint256 wSqueethToAuction,\n            uint256 ethProceeds,\n            uint256 auctionWSqueethEthPrice\n        ) = _startAuction(_auctionTriggerTime);\n\n        if (isSellingAuction) {\n            _exactOutFlashSwap(\n                wPowerPerp,\n                weth,\n                IUniswapV3Pool(ethWSqueethPool).fee(),\n                ethProceeds,\n                wSqueethToAuction,\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\n            );\n        } else {\n            _exactOutFlashSwap(\n                weth,\n                wPowerPerp,\n                IUniswapV3Pool(ethWSqueethPool).fee(),\n                wSqueethToAuction,\n                ethProceeds,\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\n            );\n        }\n\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\n    }\n\n    /**\n     * @notice execute sell auction based on the parameters calculated\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\n     * @param _buyer buyer address\n     * @param _buyerAmount buyer ETH amount sent\n     * @param _wSqueethToSell wSqueeth amount to sell\n     * @param _ethToBuy ETH amount to buy\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\n     */\n    function _executeSellAuction(\n        address _buyer,\n        uint256 _buyerAmount,\n        uint256 _wSqueethToSell,\n        uint256 _ethToBuy,\n        bool _isHedgingOnUniswap\n    ) internal {\n        if (_isHedgingOnUniswap) {\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\n        } else {\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\n\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\n\n            if (remainingEth > 0) {\n                payable(_buyer).sendValue(remainingEth);\n            }\n        }\n\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\n    }\n\n    /**\n     * @notice execute buy auction based on the parameters calculated\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\n     * @param _seller seller address\n     * @param _wSqueethToBuy wSqueeth amount to buy\n     * @param _ethToSell ETH amount to sell\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\n     */\n    function _executeBuyAuction(\n        address _seller,\n        uint256 _wSqueethToBuy,\n        uint256 _ethToSell,\n        bool _isHedgingOnUniswap\n    ) internal {\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\n\n        if (!_isHedgingOnUniswap) {\n            payable(_seller).sendValue(_ethToSell);\n        }\n\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\n    }\n\n    /**\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\n     * @param _auctionTriggerTime auction starting time\n     * @return auction type\n     * @return WSqueeth amount to sell or buy\n     * @return ETH to sell/buy\n     * @return auction WSqueeth/ETH price\n     */\n    function _startAuction(uint256 _auctionTriggerTime)\n        internal\n        returns (\n            bool,\n            uint256,\n            uint256,\n            uint256\n        )\n    {\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\n            ethWSqueethPool,\n            wPowerPerp,\n            weth,\n            hedgingTwapPeriod,\n            true\n        );\n        uint256 feeAdjustment = _calcFeeAdjustment();\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\n            strategyDebt,\n            ethDelta,\n            auctionWSqueethEthPrice,\n            feeAdjustment\n        );\n\n        require(isSellingAuction == isStillSellingAuction, \"auction direction changed\");\n\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\n\n        timeAtLastHedge = block.timestamp;\n        priceAtLastHedge = currentWSqueethPrice;\n\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\n    }\n\n    /**\n     * @notice sync strategy debt and collateral amount from vault\n     * @return synced debt amount\n     * @return synced collateral amount\n     */\n    function _syncStrategyState() internal view returns (uint256, uint256) {\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\n\n        return (syncedStrategyDebt, syncedStrategyCollateral);\n    }\n\n    /**\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\n     * @return the fee adjustment factor\n     */\n    function _calcFeeAdjustment() internal view returns (uint256) {\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\n            oracle,\n            ethWSqueethPool,\n            wPowerPerp,\n            weth,\n            POWER_PERP_PERIOD,\n            false\n        );\n        uint256 feeRate = IController(powerTokenController).feeRate();\n        return wSqueethEthPrice.mul(feeRate).div(10000);\n    }\n\n    /**\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\n     * @param _depositedAmount amount of deposited WETH\n     * @param _strategyDebtAmount amount of strategy debt\n     * @param _strategyCollateralAmount collateral amount in strategy\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\n     */\n    function _calcWsqueethToMintAndFee(\n        uint256 _depositedAmount,\n        uint256 _strategyDebtAmount,\n        uint256 _strategyCollateralAmount\n    ) internal view returns (uint256, uint256) {\n        uint256 wSqueethToMint;\n        uint256 feeAdjustment = _calcFeeAdjustment();\n\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\n            require(totalSupply() == 0, \"Crab contracts shut down\");\n\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\n                ethWSqueethPool,\n                wPowerPerp,\n                weth,\n                hedgingTwapPeriod,\n                true\n            );\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\n        } else {\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\n            );\n        }\n\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\n\n        return (wSqueethToMint, fee);\n    }\n\n    /**\n     * @notice check if hedging based on time threshold is allowed\n     * @return true if time hedging is allowed\n     * @return auction trigger timestamp\n     */\n    function _isTimeHedge() internal view returns (bool, uint256) {\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\n\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\n    }\n\n    /**\n     * @notice check if hedging based on price threshold is allowed\n     * @param _auctionTriggerTime timestamp where auction started\n     * @return true if hedging is allowed\n     */\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\n            ethWSqueethPool,\n            wPowerPerp,\n            weth,\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\n            secondsToPriceHedgeTrigger\n        );\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\n\n        return priceThreshold >= hedgePriceThreshold;\n    }\n\n    /**\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\n     * @param _auctionTriggerTime timestamp where auction started\n     * @param _wSqueethEthPrice WSqueeth/ETH price\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\n     * @return auction price\n     */\n    function _getAuctionPrice(\n        uint256 _auctionTriggerTime,\n        uint256 _wSqueethEthPrice,\n        bool _isSellingAuction\n    ) internal view returns (uint256) {\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\n            ? 1e18\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\n\n        uint256 priceMultiplier;\n        if (_isSellingAuction) {\n            priceMultiplier = maxPriceMultiplier.sub(\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\n            );\n        } else {\n            priceMultiplier = minPriceMultiplier.add(\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\n            );\n        }\n\n        return _wSqueethEthPrice.wmul(priceMultiplier);\n    }\n\n    /**\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\n     * @param _debt strategy debt\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\n     * @param _wSqueethEthPrice WSqueeth/ETH price\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\n     */\n    function _checkAuctionType(\n        uint256 _debt,\n        uint256 _ethDelta,\n        uint256 _wSqueethEthPrice,\n        uint256 _feeAdjustment\n    ) internal view returns (bool, uint256) {\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\n\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\n            wSqueethDelta,\n            _ethDelta,\n            _wSqueethEthPrice,\n            _feeAdjustment\n        );\n\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \"strategy is delta neutral\");\n\n        return (isSellingAuction, targetHedge);\n    }\n\n    /**\n     * @dev calculate amount of strategy token to mint for depositor\n     * @param _amount amount of ETH deposited\n     * @param _strategyCollateralAmount amount of strategy collateral\n     * @param _crabTotalSupply total supply of strategy token\n     * @return amount of strategy token to mint\n     */\n    function _calcSharesToMint(\n        uint256 _amount,\n        uint256 _strategyCollateralAmount,\n        uint256 _crabTotalSupply\n    ) internal pure returns (uint256) {\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\n\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\n\n        return _amount;\n    }\n\n    /**\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\n     * @param _crabAmount strategy token amount\n     * @param _totalSupply strategy total supply\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\n     */\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\n        return _crabAmount.wdiv(_totalSupply);\n    }\n\n    /**\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\n     * @param _crabRatio crab ratio\n     * @param _strategyCollateralAmount amount of collateral in strategy\n     * @return amount of ETH allowed to withdraw\n     */\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\n        return _strategyCollateralAmount.wmul(_crabRatio);\n    }\n\n    /**\n     * @notice determine target hedge and auction type (selling/buying auction)\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\n     * @param _wSqueethDelta WSqueeth delta\n     * @param _ethDelta ETH delta\n     * @param _wSqueethEthPrice WSqueeth/ETH price\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\n     * @return target hedge in wSqueeth\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\n     */\n    function _getTargetHedgeAndAuctionType(\n        uint256 _wSqueethDelta,\n        uint256 _ethDelta,\n        uint256 _wSqueethEthPrice,\n        uint256 _feeAdjustment\n    ) internal pure returns (uint256, bool) {\n        return\n            (_wSqueethDelta > _ethDelta)\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/strategy/CrabStrategyV2.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport {IController} from \"../interfaces/IController.sol\";\nimport {IWPowerPerp} from \"../interfaces/IWPowerPerp.sol\";\nimport {IOracle} from \"../interfaces/IOracle.sol\";\nimport {IWETH9} from \"../interfaces/IWETH9.sol\";\nimport {IUniswapV3Pool} from \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport {IController} from \"../interfaces/IController.sol\";\nimport {IShortPowerPerp} from \"../interfaces/IShortPowerPerp.sol\";\n\n// contract\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport {StrategyBase} from \"./base/StrategyBase.sol\";\nimport {StrategyFlashSwap} from \"./base/StrategyFlashSwap.sol\";\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {EIP712} from \"@openzeppelin/contracts/drafts/EIP712.sol\";\n\n// lib\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n// StrategyMath licensed under AGPL-3.0-only\nimport {StrategyMath} from \"./base/StrategyMath.sol\";\nimport {Power2Base} from \"../libs/Power2Base.sol\";\nimport {ECDSA} from \"@openzeppelin/contracts/cryptography/ECDSA.sol\";\n\n/**\n * Crab V2 Error Codes:\n * C1: Caller is not timelock\n * C2: Contract not yet initialized\n * C3: Invalid oracle address\n * C4: Invalid timelock address\n * C5: Invalid ETH:WSqueeth address\n * C6: Invalid crabMigration address\n * C7: Invalid hedge time threshold\n * C8: Invalid hedge price threshold\n * C9: Cannot receive ETH\n * C10: Caller not Crab Migration contract\n * C11: Crab V2 already initialized\n * C12: Squeeth contracts not shut down\n * C13: Crab must redeemShortShutdown\n * C14: Twap period is too short\n * C15: Price tolerance is too high\n * C16: Deposit exceeds strategy cap\n * C17: Clearing Price should be below bid price\n * C18: Clearing Price should be above offer price\n * C19: Invalid offer signature\n * C20: Order has expired\n * C21: Manager Price should be greater than 0\n * C22: Not a valid Time or Price hedge\n * C23: Orders must take the opposite side of the hedge\n * C24: All orders must be either buying or selling\n * C25: Orders are not arranged properly\n * C26: Crab contracts shut down\n *  C27: Nonce already used.\n */\n\n/**\n * @dev CrabStrategyV2 contract\n * @notice Contract for Crab strategy\n * @author Opyn team\n */\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\n    using StrategyMath for uint256;\n    using Address for address payable;\n\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\n    uint256 public strategyCap;\n\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\n\n    /// @dev basic unit used for calculation\n    uint256 private constant ONE = 1e18;\n    uint256 private constant ONE_ONE = 1e36;\n\n    // @dev OTC price must be within this distance of the uniswap twap price\n    uint256 public otcPriceTolerance = 5e16; // 5%\n\n    // @dev OTC price tolerance cannot exceed 20%\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\n\n    /// @dev twap period to use for hedge calculations\n    uint32 public hedgingTwapPeriod = 420 seconds;\n    /// @dev true if CrabV2 was initialized\n    bool public isInitialized;\n\n    /// @dev typehash for signed orders\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\n        keccak256(\n            \"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\"\n        );\n\n    /// @dev enum to differentiate between uniswap swap callback function source\n    enum FLASH_SOURCE {\n        FLASH_DEPOSIT,\n        FLASH_WITHDRAW\n    }\n\n    /// @dev ETH:wSqueeth uniswap pool\n    address public immutable ethWSqueethPool;\n    /// @dev strategy uniswap oracle\n    address public immutable oracle;\n    address public immutable timelock;\n    address public immutable crabMigration;\n\n    /// @dev time difference to trigger a hedge (seconds)\n    uint256 public hedgeTimeThreshold;\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\n    uint256 public hedgePriceThreshold;\n\n    /// @dev timestamp when last hedge executed\n    uint256 public timeAtLastHedge;\n    /// @dev wSqueeth/Eth price when last hedge executed\n    uint256 public priceAtLastHedge;\n\n    /// @dev set to true when redeemShortShutdown has been called\n    bool private hasRedeemedInShutdown;\n\n    /// @dev store the used flag for a nonce for each address\n    mapping(address => mapping(uint256 => bool)) public nonces;\n\n    struct FlashDepositData {\n        uint256 totalDeposit;\n    }\n\n    struct FlashWithdrawData {\n        uint256 crabAmount;\n    }\n\n    struct Order {\n        uint256 bidId;\n        address trader;\n        uint256 quantity;\n        uint256 price;\n        bool isBuying;\n        uint256 expiry;\n        uint256 nonce;\n        uint8 v;\n        bytes32 r;\n        bytes32 s;\n    }\n\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\n    event HedgeOTCSingle(\n        address trader,\n        uint256 bidId,\n        uint256 quantity,\n        uint256 price,\n        bool isBuying,\n        uint256 clearingPrice\n    );\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\n    event SetStrategyCap(uint256 newCapAmount);\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\n\n    modifier onlyTimelock() {\n        require(msg.sender == timelock, \"C1\");\n        _;\n    }\n\n    modifier afterInitialization() {\n        require(isInitialized, \"C2\");\n        _;\n    }\n\n    /**\n     * @notice strategy constructor\n     * @dev this will open a vault in the power token contract and store the vault ID\n     * @param _wSqueethController power token controller address\n     * @param _oracle oracle address\n     * @param _weth weth address\n     * @param _uniswapFactory uniswap factory address\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\n     * @param _timelock timelock contract address\n     * @param _crabMigration crab migration contract address\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\n     */\n    constructor(\n        address _wSqueethController,\n        address _oracle,\n        address _weth,\n        address _uniswapFactory,\n        address _ethWSqueethPool,\n        address _timelock,\n        address _crabMigration,\n        uint256 _hedgeTimeThreshold,\n        uint256 _hedgePriceThreshold\n    )\n        StrategyBase(_wSqueethController, _weth, \"Crab Strategy v2\", \"Crabv2\")\n        StrategyFlashSwap(_uniswapFactory)\n        EIP712(\"CrabOTC\", \"2\")\n    {\n        require(_oracle != address(0), \"C3\");\n        require(_timelock != address(0), \"C4\");\n        require(_ethWSqueethPool != address(0), \"C5\");\n        require(_crabMigration != address(0), \"C6\");\n        require(_hedgeTimeThreshold > 0, \"C7\");\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \"C8\");\n\n        oracle = _oracle;\n        ethWSqueethPool = _ethWSqueethPool;\n        hedgeTimeThreshold = _hedgeTimeThreshold;\n        hedgePriceThreshold = _hedgePriceThreshold;\n        timelock = _timelock;\n        crabMigration = _crabMigration;\n    }\n\n    /**\n     * @notice receive function to allow ETH transfer to this contract\n     */\n    receive() external payable {\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \"C9\");\n    }\n\n    /**\n     * @notice initializes the collateral ratio after the first migration\n     * @param _wSqueethToMint amount of wPowerPerp to mint\n     * @param _crabSharesToMint crab shares to mint\n     * @param _timeAtLastHedge time at last hedge for crab V1\n     * @param _priceAtLastHedge price at last hedge for crab V1\n     * @param _strategyCap strategy cap for crab V2\n     */\n    function initialize(\n        uint256 _wSqueethToMint,\n        uint256 _crabSharesToMint,\n        uint256 _timeAtLastHedge,\n        uint256 _priceAtLastHedge,\n        uint256 _strategyCap\n    ) external payable {\n        require(msg.sender == crabMigration, \"C10\");\n        require(!isInitialized, \"C11\");\n\n        _setStrategyCap(_strategyCap);\n\n        uint256 amount = msg.value;\n\n        _checkStrategyCap(amount, 0);\n\n        // store hedge data from crab V1\n        timeAtLastHedge = _timeAtLastHedge;\n        priceAtLastHedge = _priceAtLastHedge;\n\n        // mint wSqueeth and send it to msg.sender\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\n        // mint LP to depositor\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\n\n        isInitialized = true;\n    }\n\n    /**\n     * @notice transfer vault NFT to new contract\n     * @dev strategy cap is set to 0 to avoid future deposits\n     * @param _newStrategy new strategy contract address\n     */\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\n        _setStrategyCap(0);\n\n        emit VaultTransferred(_newStrategy, vaultId);\n    }\n\n    /**\n     * @notice owner can set the strategy cap in ETH collateral terms\n     * @dev deposits are rejected if it would put the strategy above the cap amount\n     * @dev strategy collateral can be above the cap amount due to hedging activities\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\n     */\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\n        _setStrategyCap(_capAmount);\n    }\n\n    /**\n     * @notice set strategy cap amount\n     * @dev deposits are rejected if it would put the strategy above the cap amount\n     * @dev strategy collateral can be above the cap amount due to hedging activities\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\n     */\n    function _setStrategyCap(uint256 _capAmount) internal {\n        strategyCap = _capAmount;\n        emit SetStrategyCap(_capAmount);\n    }\n\n    /**\n     * @notice called to redeem the net value of a vault post shutdown\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\n     */\n    function redeemShortShutdown() external afterInitialization {\n        hasRedeemedInShutdown = true;\n        powerTokenController.redeemShort(vaultId);\n    }\n\n    /**\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\n     * @param _poolFee Uniswap pool fee\n     */\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\n\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\n            _ethToDeposit,\n            cachedStrategyDebt,\n            cachedStrategyCollateral\n        );\n\n        _exactInFlashSwap(\n            wPowerPerp,\n            weth,\n            _poolFee,\n            wSqueethToMint,\n            _ethToDeposit.sub(msg.value),\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\n            abi.encodePacked(_ethToDeposit)\n        );\n\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\n    }\n\n    /**\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\n     * @param _crabAmount strategy token amount to burn\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\n     * @param _poolFee Uniswap pool fee\n\n     */\n    function flashWithdraw(\n        uint256 _crabAmount,\n        uint256 _maxEthToPay,\n        uint24 _poolFee\n    ) external nonReentrant {\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\n\n        _exactOutFlashSwap(\n            weth,\n            wPowerPerp,\n            _poolFee,\n            exactWSqueethNeeded,\n            _maxEthToPay,\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\n            abi.encodePacked(_crabAmount)\n        );\n\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\n    }\n\n    /**\n     * @notice deposit ETH into strategy\n     * @dev provide ETH, return wSqueeth and strategy token\n     */\n    function deposit() external payable nonReentrant {\n        uint256 amount = msg.value;\n\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\n\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\n    }\n\n    /**\n     * @notice withdraw WETH from strategy\n     * @dev provide strategy tokens and wSqueeth, returns ETH\n     * @param _crabAmount amount of strategy token to burn\n     */\n    function withdraw(uint256 _crabAmount) external nonReentrant {\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\n\n        // send back ETH collateral\n        payable(msg.sender).sendValue(ethToWithdraw);\n\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\n    }\n\n    /**\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\n     * @param _crabAmount amount of strategy token to burn\n     */\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\n        require(powerTokenController.isShutDown(), \"C12\");\n        require(hasRedeemedInShutdown, \"C13\");\n\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\n        _burn(msg.sender, _crabAmount);\n\n        payable(msg.sender).sendValue(ethToWithdraw);\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\n    }\n\n    /**\n     * @notice set nonce to true\n     * @param _nonce the number to be set true\n     */\n    function setNonceTrue(uint256 _nonce) external {\n        nonces[msg.sender][_nonce] = true;\n    }\n\n    /**\n     * @notice get wSqueeth debt amount associated with strategy token amount\n     * @param _crabAmount strategy token amount\n     * @return wSqueeth amount\n     */\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\n        return _getDebtFromStrategyAmount(_crabAmount);\n    }\n\n    /**\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\n     * @param _hedgingTwapPeriod the twap period, in seconds\n     */\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\n        require(_hedgingTwapPeriod >= 180, \"C14\");\n\n        hedgingTwapPeriod = _hedgingTwapPeriod;\n\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\n    }\n\n    /**\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\n     */\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\n        require(_hedgeTimeThreshold > 0, \"C7\");\n\n        hedgeTimeThreshold = _hedgeTimeThreshold;\n\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\n    }\n\n    /**\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\n     */\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \"C8\");\n\n        hedgePriceThreshold = _hedgePriceThreshold;\n\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\n    }\n\n    /**\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\n     */\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\n        // Tolerance cannot be more than 20%\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \"C15\");\n\n        otcPriceTolerance = _otcPriceTolerance;\n\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\n    }\n\n    /**\n     * @notice check if a user deposit puts the strategy above the cap\n     * @dev reverts if a deposit amount puts strategy over the cap\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\n     * @param _depositAmount the user deposit amount in ETH\n     * @param _strategyCollateral the updated strategy collateral\n     */\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \"C16\");\n    }\n\n    /**\n     * @notice uniswap flash swap callback function\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\n     * @param _caller address of original function caller\n     * @param _amountToPay amount to pay back for flashswap\n     * @param _callData arbitrary data attached to callback\n     * @param _callSource identifier for which function triggered callback\n     */\n    function _strategyFlash(\n        address _caller,\n        address _tokenIn,\n        address _tokenOut,\n        uint24 _fee,\n        uint256 _amountToPay,\n        bytes memory _callData,\n        uint8 _callSource\n    ) internal override {\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\n\n            // convert WETH to ETH as Uniswap uses WETH\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\n\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\n            // will revert if data.totalDeposit is > eth balance in contract\n            _deposit(_caller, data.totalDeposit, true);\n\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\n\n            // repay the flash swap\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\n\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\n\n            // return excess eth to the user that was not needed for slippage\n            if (address(this).balance > 0) {\n                payable(_caller).sendValue(address(this).balance);\n            }\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\n\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\n            uint256 ethToWithdraw = _withdraw(\n                _caller,\n                data.crabAmount,\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\n                true\n            );\n\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\n\n            // use some amount of withdrawn ETH to repay flash swap\n            IWETH9(weth).deposit{value: _amountToPay}();\n            IWETH9(weth).transfer(address(pool), _amountToPay);\n\n            // excess ETH not used to repay flash swap is transferred to the user\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\n\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\n\n            if (proceeds > 0) {\n                payable(_caller).sendValue(proceeds);\n            }\n        }\n    }\n\n    /**\n     * @notice deposit into strategy\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\n     * @param _depositor depositor address\n     * @param _amount amount of ETH collateral to deposit\n     * @param _isFlashDeposit true if called by flashDeposit\n     * @return wSqueethToMint minted amount of WSqueeth\n     * @return depositorCrabAmount minted CRAB strategy token amount\n     */\n    function _deposit(\n        address _depositor,\n        uint256 _amount,\n        bool _isFlashDeposit\n    ) internal returns (uint256, uint256) {\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\n        _checkStrategyCap(_amount, strategyCollateral);\n\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\n\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\n\n        // mint wSqueeth and send it to msg.sender\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\n        // mint LP to depositor\n        _mintStrategyToken(_depositor, depositorCrabAmount);\n\n        return (wSqueethToMint, depositorCrabAmount);\n    }\n\n    /**\n     * @notice withdraw WETH from strategy\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\n     * @param _crabAmount amount of strategy token to burn\n     * @param _wSqueethAmount amount of wSqueeth to burn\n     * @param _isFlashWithdraw flag if called by flashWithdraw\n     * @return ETH amount to withdraw\n     */\n    function _withdraw(\n        address _from,\n        uint256 _crabAmount,\n        uint256 _wSqueethAmount,\n        bool _isFlashWithdraw\n    ) internal returns (uint256) {\n        (, uint256 strategyCollateral) = _syncStrategyState();\n\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\n\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\n        _burn(_from, _crabAmount);\n\n        return ethToWithdraw;\n    }\n\n    /**\n     * @dev set nonce flag of the trader to true\n     * @param _trader address of the signer\n     * @param _nonce number that is to be traded only once\n     */\n    function _useNonce(address _trader, uint256 _nonce) internal {\n        require(!nonces[_trader][_nonce], \"C27\");\n        nonces[_trader][_nonce] = true;\n    }\n\n    /**\n     * @dev view function to get the domain seperator used in signing\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\n        return _domainSeparatorV4();\n    }\n\n    /**\n     * @dev check the signer and swap tokens in the order\n     * @param _remainingAmount quantity the manager wants to trade\n     * @param _clearingPrice the price at which all orders are traded\n     * @param _order a signed order to swap tokens\n     */\n    function _execOrder(\n        uint256 _remainingAmount,\n        uint256 _clearingPrice,\n        Order memory _order\n    ) internal {\n        // check that order beats clearing price\n        if (_order.isBuying) {\n            require(_clearingPrice <= _order.price, \"C17\");\n        } else {\n            require(_clearingPrice >= _order.price, \"C18\");\n        }\n\n        _useNonce(_order.trader, _order.nonce);\n        bytes32 structHash = keccak256(\n            abi.encode(\n                _CRAB_BALANCE_TYPEHASH,\n                _order.bidId,\n                _order.trader,\n                _order.quantity,\n                _order.price,\n                _order.isBuying,\n                _order.expiry,\n                _order.nonce\n            )\n        );\n\n        bytes32 hash = _hashTypedDataV4(structHash);\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\n        require(offerSigner == _order.trader, \"C19\");\n        require(_order.expiry >= block.timestamp, \"C20\");\n\n        // adjust quantity for partial fills\n        if (_remainingAmount < _order.quantity) {\n            _order.quantity = _remainingAmount;\n        }\n        // weth clearing price for the order\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\n\n        if (_order.isBuying) {\n            // trader sends weth and receives oSQTH\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\n            IWETH9(weth).withdraw(wethAmount);\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\n        } else {\n            // trader sends oSQTH and receives weth\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\n            // wrap it\n            IWETH9(weth).deposit{value: wethAmount}();\n            IWETH9(weth).transfer(_order.trader, wethAmount);\n        }\n\n        emit HedgeOTCSingle(\n            _order.trader, // market maker\n            _order.bidId,\n            _order.quantity, // order oSQTH quantity\n            _order.price, // order price\n            _order.isBuying, // order direction\n            _clearingPrice // executed price for order\n        );\n    }\n\n    /**\n     * @dev hedge function to reduce delta using an array of signed orders\n     * @param _totalQuantity quantity the manager wants to trade\n     * @param _clearingPrice clearing price in weth\n     * @param _isHedgeBuying direction of hedge trade\n     * @param _orders an array of signed order to swap tokens\n     */\n    function hedgeOTC(\n        uint256 _totalQuantity,\n        uint256 _clearingPrice,\n        bool _isHedgeBuying,\n        Order[] memory _orders\n    ) external onlyOwner afterInitialization {\n        require(_clearingPrice > 0, \"C21\");\n        require(_isTimeHedge() || _isPriceHedge(), \"C22\");\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\n\n        timeAtLastHedge = block.timestamp;\n        priceAtLastHedge = _clearingPrice;\n\n        uint256 remainingAmount = _totalQuantity;\n        uint256 prevPrice = _orders[0].price;\n        uint256 currentPrice = _orders[0].price;\n        bool isOrderBuying = _orders[0].isBuying;\n        require(_isHedgeBuying != isOrderBuying, \"C23\");\n\n        // iterate through order array and execute if valid\n        for (uint256 i; i < _orders.length; ++i) {\n            currentPrice = _orders[i].price;\n            require(_orders[i].isBuying == isOrderBuying, \"C24\");\n            if (_isHedgeBuying) {\n                require(currentPrice >= prevPrice, \"C25\");\n            } else {\n                require(currentPrice <= prevPrice, \"C25\");\n            }\n            prevPrice = currentPrice;\n\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\n\n            if (remainingAmount > _orders[i].quantity) {\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\n            } else {\n                break;\n            }\n        }\n\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\n    }\n\n    /**\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\n     * @param _price clearing price provided by manager\n     * @param _isHedgeBuying is crab buying or selling oSQTH\n     */\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\n        // Get twap\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\n\n        if (_isHedgeBuying) {\n            require(\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\n                \"Price too high relative to Uniswap twap.\"\n            );\n        } else {\n            require(\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\n                \"Price too low relative to Uniswap twap.\"\n            );\n        }\n    }\n\n    /**\n     * @notice sync strategy debt and collateral amount from vault\n     * @return synced debt amount\n     * @return synced collateral amount\n     */\n    function _syncStrategyState() internal view returns (uint256, uint256) {\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\n\n        return (syncedStrategyDebt, syncedStrategyCollateral);\n    }\n\n    /**\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\n     * @return the fee adjustment factor\n     */\n    function _calcFeeAdjustment() internal view returns (uint256) {\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\n            oracle,\n            ethWSqueethPool,\n            wPowerPerp,\n            weth,\n            POWER_PERP_PERIOD,\n            false\n        );\n        uint256 feeRate = IController(powerTokenController).feeRate();\n        return wSqueethEthPrice.mul(feeRate).div(10000);\n    }\n\n    /**\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\n     * @param _depositedAmount amount of deposited WETH\n     * @param _strategyDebtAmount amount of strategy debt\n     * @param _strategyCollateralAmount collateral amount in strategy\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\n     */\n    function _calcWsqueethToMintAndFee(\n        uint256 _depositedAmount,\n        uint256 _strategyDebtAmount,\n        uint256 _strategyCollateralAmount\n    ) internal view returns (uint256, uint256) {\n        uint256 wSqueethToMint;\n        uint256 feeAdjustment = _calcFeeAdjustment();\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\n        require(!isShutdown, \"C26\");\n\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\n        );\n\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\n\n        return (wSqueethToMint, fee);\n    }\n\n    /**\n     * @notice check if hedging based on time threshold is allowed\n     * @return true if time hedging is allowed\n     */\n    function _isTimeHedge() internal view returns (bool) {\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\n    }\n\n    /**\n     * @notice check if hedging based on price threshold is allowed\n     * @return true if hedging is allowed\n     */\n    function _isPriceHedge() internal view returns (bool) {\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\n\n        return priceThreshold >= hedgePriceThreshold;\n    }\n\n    /**\n     * @notice check if hedging based on price threshold is allowed\n     * @return true if hedging is allowed\n     */\n    function checkPriceHedge() external view returns (bool) {\n        return _isPriceHedge();\n    }\n\n    /**\n     * @notice check if hedging based on time threshold is allowed\n     * @return true if hedging is allowed\n     */\n    function checkTimeHedge() external view returns (bool) {\n        return _isTimeHedge();\n    }\n\n    /**\n     * @dev calculate amount of strategy token to mint for depositor\n     * @param _amount amount of ETH deposited\n     * @param _strategyCollateralAmount amount of strategy collateral\n     * @param _crabTotalSupply total supply of strategy token\n     * @return amount of strategy token to mint\n     */\n    function _calcSharesToMint(\n        uint256 _amount,\n        uint256 _strategyCollateralAmount,\n        uint256 _crabTotalSupply\n    ) internal pure returns (uint256) {\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\n\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\n\n        return _amount;\n    }\n\n    /**\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\n     * @param _crabAmount strategy token amount\n     * @param _totalSupply strategy total supply\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\n     */\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\n        return _crabAmount.wdiv(_totalSupply);\n    }\n\n    /**\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\n     * @param _crabRatio crab ratio\n     * @param _strategyCollateralAmount amount of collateral in strategy\n     * @return amount of ETH allowed to withdraw\n     */\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\n        return _strategyCollateralAmount.wmul(_crabRatio);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/strategy/LICENSE_GPL_3",
    "content": "\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>."
  },
  {
    "path": "packages/hardhat/contracts/strategy/base/StrategyBase.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// interface\nimport {IController} from \"../../interfaces/IController.sol\";\nimport {IWPowerPerp} from \"../../interfaces/IWPowerPerp.sol\";\n\n// contract\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n// lib\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n// StrategyMath licensed under AGPL-3.0-only\nimport {StrategyMath} from \"./StrategyMath.sol\";\nimport {VaultLib} from \"../../libs/VaultLib.sol\";\n\n/**\n * @dev StrategyBase contract\n * @notice base contract for PowerToken strategy\n * @author opyn team\n */\ncontract StrategyBase is ERC20 {\n    using StrategyMath for uint256;\n    using Address for address payable;\n\n    /// @dev power token controller\n    IController public powerTokenController;\n\n    /// @dev WETH token\n    address public immutable weth;\n    address public immutable wPowerPerp;\n\n    /// @dev power token strategy vault ID\n    uint256 public immutable vaultId;\n\n    /**\n     * @notice constructor for StrategyBase\n     * @dev this will open a vault in the power token contract and store the vault ID\n     * @param _powerTokenController power token controller address\n     * @param _weth weth token address\n     * @param _name token name for strategy ERC20 token\n     * @param _symbol token symbol for strategy ERC20 token\n     */\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\n        require(_powerTokenController != address(0), \"invalid controller address\");\n        require(_weth != address(0), \"invalid weth address\");\n\n        weth = _weth;\n        powerTokenController = IController(_powerTokenController);\n        wPowerPerp = address(powerTokenController.wPowerPerp());\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\n    }\n    /**\n     * @notice get power token strategy vault ID \n     * @return vault ID\n     */\n    function getStrategyVaultId() external view returns (uint256) {\n        return vaultId;\n    }\n\n    /**\n     * @notice get the vault composition of the strategy \n     * @return operator\n     * @return nft collateral id\n     * @return collateral amount\n     * @return short amount\n    */\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\n        return _getVaultDetails();\n    }\n\n    /**\n     * @notice mint WPowerPerp and deposit collateral\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\n     * @param _to receiver address\n     * @param _wAmount amount of WPowerPerp to mint\n     * @param _collateral amount of collateral to deposit\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\n     */\n    function _mintWPowerPerp(\n        address _to,\n        uint256 _wAmount,\n        uint256 _collateral,\n        bool _keepWsqueeth\n    ) internal {\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\n\n        if (!_keepWsqueeth) {\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\n        }\n    }\n\n    /**\n     * @notice burn WPowerPerp and withdraw collateral\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\n     * @param _from WPowerPerp holder address\n     * @param _amount amount of wPowerPerp to burn\n     * @param _collateralToWithdraw amount of collateral to withdraw\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\n     */\n    function _burnWPowerPerp(\n        address _from,\n        uint256 _amount,\n        uint256 _collateralToWithdraw,\n        bool _isOwnedWSqueeth\n    ) internal {\n        if (!_isOwnedWSqueeth) {\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\n        }\n\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\n    }\n\n    /**\n     * @notice mint strategy token\n     * @param _to recepient address\n     * @param _amount token amount\n     */\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\n        _mint(_to, _amount);\n    }\n\n    /**\n     * @notice get strategy debt amount for a specific strategy token amount\n     * @param _strategyAmount strategy amount\n     * @return debt amount\n     */\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\n    }\n\n    /**\n     * @notice get the vault composition of the strategy \n     * @return operator\n     * @return nft collateral id\n     * @return collateral amount\n     * @return short amount\n     */\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\n\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\n    }\n}\n\n"
  },
  {
    "path": "packages/hardhat/contracts/strategy/base/StrategyFlashSwap.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\";\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\n\n// lib\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\n\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\n    using Path for bytes;\n    using SafeCast for uint256;\n    using LowGasSafeMath for uint256;\n    using LowGasSafeMath for int256;\n\n    /// @dev Uniswap factory address\n    address public immutable factory;\n\n    struct SwapCallbackData {\n        bytes path;\n        address caller;\n        uint8 callSource;\n        bytes callData;\n    }\n\n    /**\n     * @dev constructor\n     * @param _factory uniswap factory address\n     */\n    constructor(\n        address _factory\n    ) {\n        require(_factory != address(0), \"invalid factory address\");\n        factory = _factory;\n    }\n\n    /**\n     * @notice uniswap swap callback function for flashes\n     * @param amount0Delta amount of token0\n     * @param amount1Delta amount of token1\n     * @param _data callback data encoded as SwapCallbackData struct\n     */\n    function uniswapV3SwapCallback(\n        int256 amount0Delta,\n        int256 amount1Delta,\n        bytes calldata _data\n    ) external override {\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\n\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\n\n        //ensure that callback comes from uniswap pool\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\n\n        //determine the amount that needs to be repaid as part of the flashswap\n        uint256 amountToPay =\n            amount0Delta > 0\n                ?  uint256(amount0Delta)\n                :  uint256(amount1Delta);\n        \n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\n    }\n\n    /**\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\n     * @param _tokenIn token address to sell\n     * @param _tokenOut token address to receive\n     * @param _fee pool fee\n     * @param _amountIn amount to sell\n     * @param _amountOutMinimum minimum amount to receive\n     * @param _callSource function call source\n     * @param _data arbitrary data assigned with the call \n     */\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\n        uint256 amountOut = _exactInputInternal(\n            _amountIn,\n            address(this),\n            uint160(0),\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\n        );\n       \n        //slippage limit check\n        require(amountOut >= _amountOutMinimum, \"amount out less than min\");\n    }\n\n    /**\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\n     * @param _tokenIn token address to sell\n     * @param _tokenOut token address to receive\n     * @param _fee pool fee\n     * @param _amountOut exact amount to receive\n     * @param _amountInMaximum maximum amount to sell\n     * @param _callSource function call source\n     * @param _data arbitrary data assigned with the call \n     */\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\n        uint256 amountIn = _exactOutputInternal(\n            _amountOut,\n            address(this),\n            uint160(0),\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\n        );\n        \n        //slippage limit check\n        require(amountIn <= _amountInMaximum, \"amount in greater than max\");\n    }\n\n    /**\n     * @notice function to be called by uniswap callback. \n     * @dev this function should be overridden by the child contract\n     * param _caller initial strategy function caller\n     * param _tokenIn token address sold\n     * param _tokenOut token address bought\n     * param _fee pool fee\n     * param _amountToPay amount to pay for the pool second token\n     * param _callData arbitrary data assigned with the flashswap call \n     * param _callSource function call source\n     */\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\n    \n    /** \n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\n    * @param _amountIn amount of token to pay\n    * @param _recipient recipient for receive\n    * @param _sqrtPriceLimitX96 price limit\n    * @return amount of token bought (amountOut)\n    */\n    function _exactInputInternal(\n        uint256 _amountIn,\n        address _recipient,\n        uint160 _sqrtPriceLimitX96,\n        SwapCallbackData memory data\n    ) private returns (uint256) {\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\n       \n        //uniswap token0 has a lower address than token1\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\n        //zeroForOne determines which token is being sold and which is being bought\n        bool zeroForOne = tokenIn < tokenOut;\n\n        //swap on uniswap, including data to trigger call back for flashswap\n        (int256 amount0, int256 amount1) =\n            _getPool(tokenIn, tokenOut, fee).swap(\n                _recipient,\n                zeroForOne,\n                _amountIn.toInt256(),\n                _sqrtPriceLimitX96 == 0\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\n                    : _sqrtPriceLimitX96,\n                abi.encode(data)\n            );\n        \n        //determine the amountOut based on which token has a lower address\n        return uint256(-(zeroForOne ? amount1 : amount0));\n    }\n\n    /** \n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\n    * @param _amountOut amount of token to receive\n    * @param _recipient recipient for receive\n    * @param _sqrtPriceLimitX96 price limit\n    * @return amount of token sold (amountIn)\n    */\n    function _exactOutputInternal(\n        uint256 _amountOut,\n        address _recipient,\n        uint160 _sqrtPriceLimitX96,\n        SwapCallbackData memory data\n    ) private returns (uint256) {\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\n\n        //uniswap token0 has a lower address than token1\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\n        //zeroForOne determines which token is being sold and which is being bought\n        bool zeroForOne = tokenIn < tokenOut;\n        \n        //swap on uniswap, including data to trigger call back for flashswap\n        (int256 amount0Delta, int256 amount1Delta) =\n            _getPool(tokenIn, tokenOut, fee).swap(\n                _recipient,\n                zeroForOne,\n                -_amountOut.toInt256(),\n                _sqrtPriceLimitX96 == 0\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\n                    : _sqrtPriceLimitX96,\n                abi.encode(data)\n            );\n\n        //determine the amountIn and amountOut based on which token has a lower address\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\n            : (uint256(amount1Delta), uint256(-amount0Delta));\n        // it's technically possible to not receive the full output amount,\n        // so if no price limit has been specified, require this possibility away\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\n\n        return amountIn;\n    }\n\n    /** \n    * @notice returns the uniswap pool for the given token pair and fee\n    * @dev the pool contract may or may not exist\n    * @param tokenA address of first token \n    * @param tokenB address of second token \n    * @param fee fee tier for pool\n    */\n    function _getPool(\n        address tokenA,\n        address tokenB,\n        uint24 fee\n    ) internal view returns (IUniswapV3Pool) {\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/strategy/base/StrategyMath.sol",
    "content": "//SPDX-License-Identifier: AGPL-3.0-only\n\n/// math.sol -- mixin for inline numerical wizardry\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >0.4.13;\n\n\n/**\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\n * @dev change contract to library, added div() function\n */\nlibrary StrategyMath {\n    function add(uint x, uint y) internal pure returns (uint z) {\n        require((z = x + y) >= x, \"ds-math-add-overflow\");\n    }\n    function sub(uint x, uint y) internal pure returns (uint z) {\n        require((z = x - y) <= x, \"ds-math-sub-underflow\");\n    }\n    function mul(uint x, uint y) internal pure returns (uint z) {\n        require(y == 0 || (z = x * y) / y == x, \"ds-math-mul-overflow\");\n    }\n\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b > 0, \"SafeMath: division by zero\");\n        return a / b;\n    }\n\n    function min(uint x, uint y) internal pure returns (uint z) {\n        return x <= y ? x : y;\n    }\n    function max(uint x, uint y) internal pure returns (uint z) {\n        return x >= y ? x : y;\n    }\n    function imin(int x, int y) internal pure returns (int z) {\n        return x <= y ? x : y;\n    }\n    function imax(int x, int y) internal pure returns (int z) {\n        return x >= y ? x : y;\n    }\n\n    uint constant WAD = 10 ** 18;\n    uint constant RAY = 10 ** 27;\n\n    //rounds to zero if x*y < WAD / 2\n    function wmul(uint x, uint y) internal pure returns (uint z) {\n        z = add(mul(x, y), WAD / 2) / WAD;\n    }\n    //rounds to zero if x*y < WAD / 2\n    function rmul(uint x, uint y) internal pure returns (uint z) {\n        z = add(mul(x, y), RAY / 2) / RAY;\n    }\n    //rounds to zero if x*y < WAD / 2\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\n        z = add(mul(x, WAD), y / 2) / y;\n    }\n    //rounds to zero if x*y < RAY / 2\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\n        z = add(mul(x, RAY), y / 2) / y;\n    }\n\n    // Ceil A to a multiple m\n    function ceil(uint a, uint m) internal pure returns(uint z) {\n        z = mul(div(sub(add(a, m), 1), m), m);\n    }\n\n    // Floor A to a multiple m\n    function floor(uint a, uint m) internal pure returns(uint z) {\n        z = mul(div(a, m), m);\n    }\n\n    // This famous algorithm is called \"exponentiation by squaring\"\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\n    //\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\n    //\n    // These facts are why it works:\n    //\n    //  If n is even, then x^n = (x^2)^(n/2).\n    //  If n is odd,  then x^n = x * x^(n-1),\n    //   and applying the equation for even x gives\n    //    x^n = x * (x^2)^((n-1) / 2).\n    //\n    //  Also, EVM division is flooring and\n    //    floor[(n-1) / 2] = floor[n / 2].\n    //\n    function rpow(uint x, uint n) internal pure returns (uint z) {\n        z = n % 2 != 0 ? x : RAY;\n\n        for (n /= 2; n != 0; n /= 2) {\n            x = rmul(x, x);\n\n            if (n % 2 != 0) {\n                z = rmul(z, x);\n            }\n        }\n    }\n}"
  },
  {
    "path": "packages/hardhat/contracts/strategy/helper/StrategySwap.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity =0.7.6;\npragma abicoder v2;\n\nimport \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ncontract StrategySwap {\n    ISwapRouter public immutable swapRouter;\n\n    constructor(address _swapRouter) {\n        require(_swapRouter != address(0), \"invalid swap router address\");\n        swapRouter = ISwapRouter(_swapRouter);\n    }\n\n    /**\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\n     * @param _tokenIn token address to sell\n     * @param _tokenOut token address to receive\n     * @param _from from which user we are selling\n     * @param _to Recipient to get the tokens\n     * @param _amountIn Exact amount to sell\n     * @param _minAmountOut Minimum amount to be paid\n     * @param _fee pool fee\n     * @return amountOut The amount of WETH9 received.\n     */\n    function _swapExactInputSingle(\n        address _tokenIn,\n        address _tokenOut,\n        address _from,\n        address _to,\n        uint256 _amountIn,\n        uint256 _minAmountOut,\n        uint24 _fee\n    ) internal returns (uint256 amountOut) {\n        // _from must approve this contract\n\n        // Transfer the specified amount of tokenIn to this contract.\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\n\n        // Approve the router to spend tokenIn.\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\n\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\n            tokenIn: _tokenIn,\n            tokenOut: _tokenOut,\n            fee: _fee,\n            recipient: _to,\n            deadline: block.timestamp,\n            amountIn: _amountIn,\n            amountOutMinimum: _minAmountOut,\n            sqrtPriceLimitX96: 0\n        });\n\n        // The call to `exactInputSingle` executes the swap.\n        amountOut = swapRouter.exactInputSingle(params);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/strategy/timelock/SafeMath.sol",
    "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity =0.8.10;\n\n// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol\n// Subject to the MIT license.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 c;\n        unchecked { c = a + b; }\n        require(c >= a, \"SafeMath: addition overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        uint256 c;\n        unchecked { c = a + b; }\n        require(c >= a, errorMessage);\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     * - Subtraction cannot underflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return sub(a, b, \"SafeMath: subtraction underflow\");\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     * - Subtraction cannot underflow.\n     */\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b <= a, errorMessage);\n        uint256 c = a - b;\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n        // benefit is lost if 'b' is also tested.\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n        if (a == 0) {\n            return 0;\n        }\n\n        uint256 c;\n        unchecked { c = a * b; }\n        require(c / a == b, \"SafeMath: multiplication overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n        // benefit is lost if 'b' is also tested.\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n        if (a == 0) {\n            return 0;\n        }\n\n        uint256 c;\n        unchecked { c = a * b; }\n        require(c / a == b, errorMessage);\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers.\n     * Reverts on division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return div(a, b, \"SafeMath: division by zero\");\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers.\n     * Reverts with custom message on division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        // Solidity only automatically asserts when dividing by 0\n        require(b > 0, errorMessage);\n        uint256 c = a / b;\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * Reverts when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        return mod(a, b, \"SafeMath: modulo by zero\");\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * Reverts with custom message when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b != 0, errorMessage);\n        return a % b;\n    }\n}"
  },
  {
    "path": "packages/hardhat/contracts/strategy/timelock/Timelock.sol",
    "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity =0.8.10;\n\nimport \"./SafeMath.sol\";\n\ncontract Timelock {\n    using SafeMath for uint;\n\n    event NewAdmin(address indexed newAdmin);\n    event NewPendingAdmin(address indexed newPendingAdmin);\n    event NewDelay(uint indexed newDelay);\n    event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature,  bytes data, uint eta);\n    event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature,  bytes data, uint eta);\n    event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);\n\n    uint public constant GRACE_PERIOD = 14 days;\n    uint public constant MINIMUM_DELAY = 2 days;\n    uint public constant MAXIMUM_DELAY = 30 days;\n\n    address public admin;\n    address public pendingAdmin;\n    uint public delay;\n\n    mapping (bytes32 => bool) public queuedTransactions;\n\n\n    constructor(address admin_, uint delay_) public {\n        require(delay_ >= MINIMUM_DELAY, \"Timelock::constructor: Delay must exceed minimum delay.\");\n        require(delay_ <= MAXIMUM_DELAY, \"Timelock::setDelay: Delay must not exceed maximum delay.\");\n\n        admin = admin_;\n        delay = delay_;\n    }\n\n    fallback() external payable { }\n\n    function setDelay(uint delay_) public {\n        require(msg.sender == address(this), \"Timelock::setDelay: Call must come from Timelock.\");\n        require(delay_ >= MINIMUM_DELAY, \"Timelock::setDelay: Delay must exceed minimum delay.\");\n        require(delay_ <= MAXIMUM_DELAY, \"Timelock::setDelay: Delay must not exceed maximum delay.\");\n        delay = delay_;\n\n        emit NewDelay(delay);\n    }\n\n    function acceptAdmin() public {\n        require(msg.sender == pendingAdmin, \"Timelock::acceptAdmin: Call must come from pendingAdmin.\");\n        admin = msg.sender;\n        pendingAdmin = address(0);\n\n        emit NewAdmin(admin);\n    }\n\n    function setPendingAdmin(address pendingAdmin_) public {\n        require(msg.sender == address(this), \"Timelock::setPendingAdmin: Call must come from Timelock.\");\n        pendingAdmin = pendingAdmin_;\n\n        emit NewPendingAdmin(pendingAdmin);\n    }\n\n    function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) {\n        require(msg.sender == admin, \"Timelock::queueTransaction: Call must come from admin.\");\n        require(eta >= getBlockTimestamp().add(delay), \"Timelock::queueTransaction: Estimated execution block must satisfy delay.\");\n\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        queuedTransactions[txHash] = true;\n\n        emit QueueTransaction(txHash, target, value, signature, data, eta);\n        return txHash;\n    }\n\n    function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public {\n        require(msg.sender == admin, \"Timelock::cancelTransaction: Call must come from admin.\");\n\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        queuedTransactions[txHash] = false;\n\n        emit CancelTransaction(txHash, target, value, signature, data, eta);\n    }\n\n    function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) {\n        require(msg.sender == admin, \"Timelock::executeTransaction: Call must come from admin.\");\n\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        require(queuedTransactions[txHash], \"Timelock::executeTransaction: Transaction hasn't been queued.\");\n        require(getBlockTimestamp() >= eta, \"Timelock::executeTransaction: Transaction hasn't surpassed time lock.\");\n        require(getBlockTimestamp() <= eta.add(GRACE_PERIOD), \"Timelock::executeTransaction: Transaction is stale.\");\n\n        queuedTransactions[txHash] = false;\n\n        bytes memory callData;\n\n        if (bytes(signature).length == 0) {\n            callData = data;\n        } else {\n            callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);\n        }\n\n        // solium-disable-next-line security/no-call-value\n        (bool success, bytes memory returnData) = target.call{value: value}(callData);\n        require(success, \"Timelock::executeTransaction: Transaction execution reverted.\");\n\n        emit ExecuteTransaction(txHash, target, value, signature, data, eta);\n\n        return returnData;\n    }\n\n    function getBlockTimestamp() internal view returns (uint) {\n        // solium-disable-next-line security/no-block-members\n        return block.timestamp;\n    }\n}"
  },
  {
    "path": "packages/hardhat/contracts/test/ABDKTester.sol",
    "content": "// SPDX-License-Identifier: BSD-4-Clause\n/*\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\n * Copyright (c) 2019, ABDK Consulting\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n \npragma solidity =0.7.6;\n\nimport {ABDKMath64x64} from \"../libs/ABDKMath64x64.sol\";\n\ncontract ABDKTester{    \n    using ABDKMath64x64 for int128;\n    using ABDKMath64x64 for uint256;\n\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\n        return x.mul(y);\n    }\n    \n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\n        return -x.mul(y);\n    }\n\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\n        return x.mulu(y);\n    }\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\n        return x.divu(y);\n    }\n    function testLog_2(int128 x) external pure returns (int128 z) {\n        return x.log_2();\n    }\n    function testExp_2(int128 x) external pure returns (int128 z) {\n        return x.exp_2();\n    }\n}"
  },
  {
    "path": "packages/hardhat/contracts/test/CastingTester.sol",
    "content": "//SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\n\nimport {Uint256Casting} from \"../libs/Uint256Casting.sol\";\n\ncontract CastingTester{    \n    using Uint256Casting for uint256;\n\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\n        return y.toUint128();\n    }\n\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\n        return y.toUint96();\n    }\n\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\n        return y.toUint32();\n    }\n}"
  },
  {
    "path": "packages/hardhat/contracts/test/ControllerAccessTester.sol",
    "content": "//SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\n\nimport {IShortPowerPerp} from \"../interfaces/IShortPowerPerp.sol\";\n\n/**\n * use this contract to check that controller has correct access control to mint NFTs\n * a testing contract is necessary as the before transfer hook calls updateOperator\n */\ncontract ControllerAccessTester{\n    \n    IShortPowerPerp shortPowerPerp;\n\n    constructor(address _shortPowerPerp) {\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\n    }\n    \n    function mintTest(address _address) external returns (uint256) {\n        return shortPowerPerp.mintNFT(_address);\n    }\n\n    function updateOperator(uint256 _tokenId, address _operator) external {\n\n    }\n}"
  },
  {
    "path": "packages/hardhat/contracts/test/ControllerTester.sol",
    "content": "//SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\n\nimport {IController} from \"../interfaces/IController.sol\";\n\n/**\n* use this contract to confirm that funding is not charged twice if called in same block\n */\ncontract ControllerTester{\n\n  IController controller;\n\n  constructor(address _controller) {\n    controller = IController(_controller);\n  }\n\n  function testDoubleFunding() external {\n    controller.applyFunding();\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\n    controller.applyFunding();\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\n    require(normalizationFactor1==normalizationFactor2, \"funding charged twice\");\n  }\n}"
  },
  {
    "path": "packages/hardhat/contracts/test/LICENSE_BSD_4_Clause",
    "content": "ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\nAuthor: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\nCopyright (c) 2019, ABDK Consulting\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\nAll advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\nNeither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  },
  {
    "path": "packages/hardhat/contracts/test/LICENSE_BUSL",
    "content": "Business Source License 1.1\n\nLicense text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.\n\n\n\"Business Source License\" is a trademark of MariaDB Corporation Ab.\n\n-----------------------------------------------------------------------------\n\nParameters\nLicensor:            Opyn \nLicensed Work:       Opyn Squeeth Core v1.0\n                     The Licensed Work is (c) 2022 Opyn\n\nAdditional Use Grant: Any uses listed and defined at\nhttps://github.com/opynfinance/squeeth-monorepo/packages/hardhat/USE_GRANT\n\nChange Date:          The earlier of 2023-01-10 or a date specified at\nhttps://github.com/opynfinance/squeeth-monorepo/packages/hardhat/CHANGE_DATE\n\nChange License:       GNU General Public License v2.0 or later\n\n-----------------------------------------------------------------------------\n\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provided that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON\nAN \"AS IS\" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License’s text to license\nyour works, and to refer to it using the trademark \"Business Source License\",\nas long as you comply with the Covenants of Licensor below.\n\n-----------------------------------------------------------------------------\n\nCovenants of Licensor\n\nIn consideration of the right to use this License’s text and the \"Business\nSource License\" name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provided by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n  or a license that is compatible with GPL Version 2.0 or a later version,\n  where \"compatible\" means that software provided under the Change License can\n  be included in a program with software provided under GPL Version 2.0 or a\n  later version. Licensor may specify additional Change Licenses without\n  limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n  impose any additional restriction on the right granted in this License, as\n  the Additional Use Grant; or (b) insert the text \"None\".\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\n\n-----------------------------------------------------------------------------\n\nNotice\n\nThe Business Source License (this document, or the \"License\") is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\n\n"
  },
  {
    "path": "packages/hardhat/contracts/test/LICENSE_GPL_3",
    "content": "\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>."
  },
  {
    "path": "packages/hardhat/contracts/test/LiquidationHelper.sol",
    "content": "//SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\npragma abicoder v2;\n\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\n\nimport {SafeMath} from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport {IUniswapV3Pool} from \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport {IController} from \"../interfaces/IController.sol\";\n\nimport {IWETH9} from \"../interfaces/IWETH9.sol\";\nimport {IWPowerPerp} from \"../interfaces/IWPowerPerp.sol\";\nimport {IShortPowerPerp} from \"../interfaces/IShortPowerPerp.sol\";\nimport {IOracle} from \"../interfaces/IOracle.sol\";\n\nimport {VaultLib} from \"../libs/VaultLib.sol\";\nimport {Uint256Casting} from \"../libs/Uint256Casting.sol\";\nimport {Power2Base} from \"../libs/Power2Base.sol\";\n\ncontract LiquidationHelper  {\n\n    using SafeMath for uint256;\n    using Uint256Casting for uint256;\n    using VaultLib for VaultLib.Vault;\n\n    // constatns\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\n    uint32 public constant TWAP_PERIOD = 420 seconds;\n\n    address immutable public controller;\n    address immutable public oracle;\n    address immutable public wPowerPerp;\n    address immutable public weth;\n    address immutable public quoteCurrency;\n    address immutable public ethQuoteCurrencyPool;\n    address immutable public wPowerPerpPool;\n    address immutable public uniswapPositionManager;\n\n    bool immutable isWethToken0;\n    \n    constructor(\n        address _controller,\n        address _oracle,\n        address _wPowerPerp,\n        address _weth,\n        address _quoteCurrency,\n        address _ethQuoteCurrencyPool,\n        address _wPowerPerpPool,\n        address _uniPositionManager\n    ) {\n        controller = _controller;\n        oracle = _oracle;\n        wPowerPerp = _wPowerPerp;\n        weth = _weth;\n        quoteCurrency = _quoteCurrency;\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\n        wPowerPerpPool = _wPowerPerpPool;\n        uniswapPositionManager = _uniPositionManager;\n        isWethToken0 = _weth < _wPowerPerp;\n    }\n    \n    /**\n     * @notice check the result of a call to liquidate\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\n     * @param _vaultId vault to liquidate\n     * @return isUnsafe\n     * @return isLiquidatable after reducing debt\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\n     */\n    function checkLiquidation(uint256 _vaultId)\n        external\n        view\n        returns (\n            bool,\n            bool,\n            uint256,\n            uint256\n        )\n    {\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\n    }\n\n    /**\n     * @notice check that the vault has enough collateral\n     * @param _vault in-memory vault\n     * @param _normalizationFactor normalization factor\n     * @return true if the vault is properly collateralized\n     */\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\n        return isSafe;\n    }\n\n    /**\n     * @notice return if the vault is properly collateralized and if it is a dust vault\n     * @param _vault the Vault memory to update\n     * @param _normalizationFactor normalization factor\n     * @return true if the vault is safe\n     * @return true if the vault is a dust vault\n     */\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\n        internal\n        view\n        returns (bool, bool)\n    {\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\n            oracle,\n            ethQuoteCurrencyPool,\n            weth,\n            quoteCurrency,\n            TWAP_PERIOD,\n            true // do not call more than maximum period so it does not revert\n        );\n        return\n            VaultLib.getVaultStatus(\n                _vault,\n                uniswapPositionManager,\n                _normalizationFactor,\n                scaledEthPrice,\n                MIN_COLLATERAL,\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\n                isWethToken0\n            );\n    }\n\n    /**\n     * @notice check the result of a call to liquidate\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\n     * @param _vaultId vault to liquidate\n     * @return isUnsafe\n     * @return isLiquidatable after reducing debt\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\n     */\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\n        internal\n        view\n        returns (\n            bool,\n            bool,\n            uint256,\n            uint256\n        )\n    {\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\n\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\n            return (false, false, 0, 0);\n        }\n\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\n        if (cachedVault.NftCollateralId != 0) {\n            // using current tick to check how much nft is worth\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\n\n            // simulate vault state after removing nft\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\n                uniswapPositionManager,\n                cachedVault.NftCollateralId,\n                spotTick,\n                isWethToken0\n            );\n\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\n                cachedVault,\n                nftEthAmount,\n                nftWPowerperpAmount,\n                true\n            );\n\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\n                return (true, false, 0, bounty);\n            }\n            //re-add bounty if not safe after reducing debt\n            cachedVault.addEthCollateral(bounty);\n        }\n\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\n            cachedVault.shortAmount,\n            cachedVault.shortAmount,\n            cachedVault.collateralAmount\n        );\n\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\n    }\n\n    /**\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\n     * @dev this function will update the vault memory in-place\n     * @return burnAmount amount of wSqueeth that should be burned\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\n     * @return bounty amount of bounty should be paid out to caller\n     */\n    function _getReduceDebtResultInVault(\n        VaultLib.Vault memory _vault,\n        uint256 nftEthAmount,\n        uint256 nftWPowerperpAmount,\n        bool _payBounty\n    )\n        internal\n        view\n        returns (\n            uint256,\n            uint256,\n            uint256\n        )\n    {\n        uint256 bounty;\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\n\n        uint256 burnAmount = nftWPowerperpAmount;\n        uint256 wPowerPerpExcess;\n\n        if (nftWPowerperpAmount > _vault.shortAmount) {\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\n            burnAmount = _vault.shortAmount;\n        }\n\n        _vault.removeShort(burnAmount);\n        _vault.removeUniNftCollateral();\n        _vault.addEthCollateral(nftEthAmount);\n        _vault.removeEthCollateral(bounty);\n\n        return (burnAmount, wPowerPerpExcess, bounty);\n    }\n\n    /**\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\n     * @dev bounty is 2% of the total value of the position token\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\n     */\n    function _getReduceDebtBounty(\n        uint256 _ethWithdrawn,\n        uint256 _wPowerPerpReduced\n    ) internal view returns (uint256) {\n        return\n            Power2Base\n                ._getDebtValueInEth(\n                    _wPowerPerpReduced,\n                    oracle,\n                    wPowerPerpPool,\n                    wPowerPerp,\n                    weth\n                )\n                .add(_ethWithdrawn)\n                .mul(2)\n                .div(100);\n    }\n\n    /**\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \"dust vault\"\n     * @dev a liquidator cannot take out more collateral than the vault holds\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\n     * @param _vaultShortAmount the amount of short in the vault\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\n     * @return collateralToPay final amount of collateral paying out to the liquidator\n     */\n    function _getLiquidationResult(\n        uint256 _maxWPowerPerpAmount,\n        uint256 _vaultShortAmount,\n        uint256 _vaultCollateralAmount\n    ) internal view returns (uint256, uint256) {\n        // try limiting liquidation amount to half of the vault debt\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\n            _maxWPowerPerpAmount,\n            _vaultShortAmount.div(2)\n        );\n\n        if (_vaultCollateralAmount > collateralToPay) {\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\n                // the vault is left with dust after liquidation, allow liquidating full vault\n                // calculate the new liquidation amount and collateral again based on the new limit\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\n                    _maxWPowerPerpAmount,\n                    _vaultShortAmount\n                );\n            }\n        }\n\n        // check if final collateral to pay is greater than vault amount.\n        // if so the system only pays out the amount the vault has, which may not be profitable\n        if (collateralToPay > _vaultCollateralAmount) {\n            // force liquidator to pay full debt amount\n            finalLiquidateAmount = _vaultShortAmount;\n            collateralToPay = _vaultCollateralAmount;\n        }\n\n        return (finalLiquidateAmount, collateralToPay);\n    }\n\n    /**\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\n     * @return collateralToPay total collateral the liquidator will get\n     */\n    function _getSingleLiquidationAmount(\n        uint256 _maxInputWAmount,\n        uint256 _maxLiquidatableWAmount\n    ) internal view returns (uint256, uint256) {\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\n            ? _maxLiquidatableWAmount\n            : _maxInputWAmount;\n\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\n            finalWAmountToLiquidate,\n            oracle,\n            wPowerPerpPool,\n            wPowerPerp,\n            weth\n        );\n\n        // add 10% bonus for liquidators\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\n\n        return (finalWAmountToLiquidate, collateralToPay);\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/contracts/test/OracleTester.sol",
    "content": "//SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\n\nimport {IOracle} from \"../interfaces/IOracle.sol\";\nimport {Oracle} from \"../core/Oracle.sol\";\nimport {Uint256Casting} from \"../libs/Uint256Casting.sol\";\n\n/**\n * use this contract to test how to get twap from exactly 1 timestamp\n * Since we can't access block.timestamp offchain before sending the tx\n */\ncontract OracleTester is Oracle{\n\n  using Uint256Casting for uint256;\n\n  IOracle oracle;\n\n  constructor(address _oracle) {\n    oracle = IOracle(_oracle);\n  }\n\n  function testGetTwapSince(\n    uint256 _sinceTimestamp, \n    address _pool, \n    address _base, \n    address _quote\n  ) view external returns (uint256) {\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\n    return oracle.getTwap(_pool, _base, _quote, period, false);\n  }\n\n  function testGetTwapSafeSince(\n    uint256 _sinceTimestamp, \n    address _pool, \n    address _base, \n    address _quote\n  ) view external returns (uint256) {\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\n    return oracle.getTwap(_pool, _base, _quote, period, true);\n  }\n\n  function testGetWeightedTickSafe(\n    uint256 _sinceTimestamp,\n    address _pool\n  ) view external returns (int24) {\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\n  }\n\n  function testGetHistoricalTwapToNow(\n    uint256 _startTimestamp,\n    address _pool,\n    address _base,\n    address _quote\n  ) view external returns (uint256) {\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \n    uint32 secondsAgoToEndOfTwap=0;\n    \n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\n  }\n\n  function testGetHistoricalTwap(\n    uint256 _startTimestamp,\n    uint256 _endTimestamp,\n    address _pool,\n    address _base,\n    address _quote\n  ) view external returns (uint256) {\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \n        \n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\n  }\n\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\n      return y.toUint128();\n  }\n}"
  },
  {
    "path": "packages/hardhat/contracts/test/VaultTester.sol",
    "content": "//SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity =0.7.6;\n\nimport {VaultLib} from \"../libs/VaultLib.sol\";\nimport \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\";\n\ncontract VaultLibTester {\n\n  function getUniPositionBalances(\n      address _positionManager,\n      uint256 _tokenId,\n      int24 _wPowerPerpPoolTick,\n      bool _isWethToken0\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\n    }\n\n  /**\n   * expose this function so it's easier to test vault lib.\n   */\n  function getLiquidity(\n    uint160 sqrtRatioX96,\n    int24 tickA,\n    int24 tickB,\n    uint256 amount0Desired,\n    uint256 amount1Desired\n  ) external pure returns (uint128 liquidity) {\n\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\n\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\n        sqrtRatioX96,\n        sqrtRatioAX96,\n        sqrtRatioBX96,\n        amount0Desired,\n        amount1Desired\n    );\n  }\n\n  function getLiquidityForAmount0(\n    uint160 sqrtRatioAX96,\n    uint160 sqrtRatioBX96,\n    uint256 amount0\n  ) external pure returns (uint128 liquidity) {\n\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\n\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\n  }\n\n  function getLiquidityForAmount1(\n    uint160 sqrtRatioAX96,\n    uint160 sqrtRatioBX96,\n    uint256 amount1\n  ) external pure returns (uint128 liquidity) {\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\n\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\n  }\n\n  function getAmountsForLiquidity(\n    uint160 sqrtRatioX96,\n    uint160 sqrtRatioAX96,\n    uint160 sqrtRatioBX96,\n    uint128 liquidity\n  ) external pure returns (uint256 amount0, uint256 amount1) {\n    return LiquidityAmounts.getAmountsForLiquidity(\n      sqrtRatioX96,\n      sqrtRatioAX96,\n      sqrtRatioBX96,\n      liquidity\n    );\n  }\n}"
  },
  {
    "path": "packages/hardhat/crab-migration.js",
    "content": ""
  },
  {
    "path": "packages/hardhat/crabmigration-arguments.js",
    "content": "module.exports = [\n  \"0xbffBD99cFD9d77c49595dFe8eB531715906ca4Cf\",\n  \"0xc778417e063141139fce010982780140aa0cd5ab\",\n  \"0xF7B8611008Ed073Ef348FE130671688BBb20409d\",\n  \"0x682b4c36a6D4749Ced8C3abF47AefDFC57A17754\",\n  \"0xfC3DD73e918b931be7DEfd0cc616508391bcc001\",\n];\n"
  },
  {
    "path": "packages/hardhat/crabv2-arguments.js",
    "content": "module.exports = [\n  \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n  \"0xBD9F4bE886653177D22fA9c79FD0DFc41407fC89\",\n  \"0xc778417e063141139fce010982780140aa0cd5ab\",\n  \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n  \"0x921c384F79de1BAe96d6f33E3E5b8d0B2B34cb68\",\n  \"0xF15964458bcA1941dE53fBc004BA7842f4783EC6\",\n  \"0x1d1e0838d97996eD3f46b24f52533E3d09F02BcB\",\n  1,\n  \"1000000000000000000\",\n];\n"
  },
  {
    "path": "packages/hardhat/deploy/00_deploy_basic_coins.ts",
    "content": "import { HardhatRuntimeEnvironment } from 'hardhat/types';\nimport { DeployFunction } from 'hardhat-deploy/types';\n\nimport { networkNameToWeth, networkNameToUSDC, createArgumentFile } from '../tasks/utils'\n\nconst func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {\n  const { deployments, getNamedAccounts, ethers, network } = hre;\n  const { deployer } = await getNamedAccounts();\n  \n  console.log(`Start deploying with ${deployer}`)\n\n  const { deploy } = deployments;\n\n  // if goerli, deploy custom WETH and USDC\n  if (network.name === 'goerli') {\n    // Deploy USD\n    const opynUsdcArgs = [\"OpynUSDC\", \"OpynUSDC\", 6]\n    const usdc = await deploy(\"MockErc20\", { from: deployer, args: opynUsdcArgs, skipIfAlreadyDeployed: true});\n    createArgumentFile('OpynUsdc', network.name, opynUsdcArgs)\n    console.log(`OpynUSDC Deployed at ${usdc.address} 🍇`)\n\n    // const opynWethArgs = [\"OpynWETH\", \"OpynWETH\", 18]\n    // const weth = await deploy(\"MockErc20\", { from: deployer, args: opynWethArgs, skipIfAlreadyDeployed: true }); \n    // createArgumentFile('OpynWeth', network.name, opynWethArgs)\n    // console.log(`OpynWeth Deployed at ${weth.address} 🍇`)\n    \n    // Deploy WETH9 \n    const weth = await deploy(\"OpynWETH9\", { from: deployer,  skipIfAlreadyDeployed: true  }); \n    console.log(`OpynWeth Deployed at ${weth.address} 🍇`)\n  }\n  else {\n    // Deploy WETH9 and UniswapV3Factory for SwapRouter.\n    // Deploy WETH9 \n    const wethAddr = networkNameToWeth(network.name as string)\n    if (wethAddr === undefined) {\n      await deploy(\"WETH9\", { from: deployer });\n      const weth = await ethers.getContract(\"WETH9\", deployer);\n      console.log(`WETH9 Deployed at ${weth.address} 🍇`)\n    } else {\n      console.log(`Using WETH9 at ${wethAddr}`)\n    }\n\n    // Deploy USD\n    const usdcAddress = networkNameToUSDC(network.name as string)\n    if (usdcAddress === undefined) {\n      await deploy(\"MockErc20\", { from: deployer, args: [\"USDC\", \"USDC\", 6], skipIfAlreadyDeployed: true });\n      const usdc = await ethers.getContract(\"MockErc20\", deployer);\n      console.log(`USDC Deployed at ${usdc.address} 🍇`)\n    } else {\n      console.log(`Using USDC at ${usdcAddress}`)\n    }\n  }\n}\n\nexport default func;"
  },
  {
    "path": "packages/hardhat/deploy/01_deploy_uniswapv3.ts",
    "content": "import { HardhatRuntimeEnvironment } from 'hardhat/types';\nimport { DeployFunction } from 'hardhat-deploy/types';\n\nimport {\n  abi as SWAP_ROUTER_ABI,\n  bytecode as SWAP_ROUTER_BYTECODE,\n} from '@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json'\n\nimport {\n  abi as POSITION_MANAGER_ABI,\n  bytecode as POSITION_MANAGER_BYTECODE,\n} from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'\n\nimport {\n  abi as FACTORY_ABI,\n  bytecode as FACTORY_BYTECODE,\n} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json'\n\nimport {\n  abi as QUOTER_ABI,\n  bytecode as QUOTER_BYTECODE,\n} from '@uniswap/v3-periphery/artifacts/contracts/lens/QuoterV2.sol/QuoterV2.json'\n\nimport { getWETH, hasUniswapDeployments } from '../tasks/utils'\n\nconst func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {\n  const { deployments, getNamedAccounts, ethers, network } = hre;\n  const { deployer } = await getNamedAccounts();\n\n  console.log(`Start deploying with ${deployer}`)\n\n  const { deploy } = deployments;\n\n  if (hasUniswapDeployments(network.name)) {\n    console.log(`Already have Uniswap Deployment on network ${network.name}. Skipping this step. 🍹\\n`)\n    return\n  } \n  \n  console.log(`\\nDeploying whole Uniswap 🦄 on network ${network.name} again...`)\n\n  // get WETH9 \n  const weth9 = await getWETH(ethers, deployer, network.name)\n\n  // Deploy Uniswap Factory\n  await deploy(\"UniswapV3Factory\", {\n    from: deployer,\n    log: true,\n    contract: {\n      abi: FACTORY_ABI,\n      bytecode: FACTORY_BYTECODE\n    }\n  });\n  console.log(`UniswapV3Factory Deployed 🍹`)\n  const uniswapFactory = await ethers.getContract(\"UniswapV3Factory\", deployer);\n\n  await deploy(\"SwapRouter\", {\n    from: deployer,\n    log: true,\n    contract: {\n      abi: SWAP_ROUTER_ABI,\n      bytecode: SWAP_ROUTER_BYTECODE\n    },\n    args: [uniswapFactory.address, weth9.address]\n  });\n  console.log(`SwapRouter Deployed 🍍`)\n\n  // tokenDescriptor is only used to query tokenURI() on NFT. Don't need that in our deployment\n  const tokenDescriptorAddress = ethers.constants.AddressZero\n\n  await deploy(\"NonfungiblePositionManager\", {\n    from: deployer,\n    log: true,\n    contract: {\n      abi: POSITION_MANAGER_ABI,\n      bytecode: POSITION_MANAGER_BYTECODE,\n    },\n    args: [uniswapFactory.address, weth9.address, tokenDescriptorAddress]\n  });\n\n  console.log(`NonfungiblePositionManager Deployed 🥑\\n`)\n\n  const weth = await getWETH(ethers, deployer, network.name)\n\n  await deploy(\"Quoter\", {\n    from: deployer,\n    log: true,\n    contract: {\n      abi: QUOTER_ABI,\n      bytecode: QUOTER_BYTECODE,\n    },\n    args: [uniswapFactory.address, weth.address]\n  });\n\n  console.log(`Quoter Deployed  🥦\\n`) \n  \n}\n\nexport default func;"
  },
  {
    "path": "packages/hardhat/deploy/02_deploy_core.ts",
    "content": "import { HardhatRuntimeEnvironment } from 'hardhat/types';\nimport { DeployFunction } from 'hardhat-deploy/types';\nimport { createArgumentFile } from '../tasks/utils'\n\nconst func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {\n  const { deployments, getNamedAccounts, network } = hre;\n  const { deploy } = deployments;\n\n  const { deployer } = await getNamedAccounts();\n  await deploy(\"Oracle\", { from: deployer, log: true, skipIfAlreadyDeployed: true });\n\n  const shortPowerPerpArgs = ['short Squeeth', 'sSQTH']\n  await deploy(\"ShortPowerPerp\", { from: deployer, log: true, args: shortPowerPerpArgs, skipIfAlreadyDeployed: true });\n  createArgumentFile('ShortPowerPerp', network.name, shortPowerPerpArgs)\n\n  const wPowerPerpArgs = ['Opyn Squeeth', 'oSQTH']\n  await deploy(\"WPowerPerp\", { from: deployer, log: true, args: wPowerPerpArgs, skipIfAlreadyDeployed: true });\n  createArgumentFile('WPowerPerp', network.name, wPowerPerpArgs)\n}\n\nexport default func;"
  },
  {
    "path": "packages/hardhat/deploy/03_deploy_pools.ts",
    "content": "import { HardhatRuntimeEnvironment } from 'hardhat/types';\nimport { DeployFunction } from 'hardhat-deploy/types';\nimport { createUniPool } from '../test/setup'\n\nimport { getUSDC, getWETH, getUniswapDeployments } from '../tasks/utils'\nimport { oracleScaleFactor } from '../test/utils';\n\nconst func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {\n  const { getNamedAccounts, ethers, network } = hre;\n  const { deployer } = await getNamedAccounts();\n  const { positionManager, uniswapFactory } = await getUniswapDeployments(ethers, deployer, network.name)\n  if (network.name === \"goerli\" || network.name === \"mainnet\") {\n    return\n  }\n    \n  // Get Tokens\n  const weth9 = await getWETH(ethers, deployer, network.name)\n  const usdc = await getUSDC(ethers, deployer, network.name);  \n\n  // Create ETH/SQUEETH Pool with positionManager\n  const squeeth = await ethers.getContract(\"WPowerPerp\", deployer);\n\n  // update this number to initial price we want to start the pool with.\n\n  const squeethPriceInEth = 1300 / oracleScaleFactor.toNumber();\n  const squeethWethPool = await createUniPool(squeethPriceInEth, weth9, squeeth, positionManager, uniswapFactory)\n  const tx1 = await squeethWethPool.increaseObservationCardinalityNext(128)\n  await ethers.provider.waitForTransaction(tx1.hash, 1)\n\n  console.log(`SQU/ETH Pool created 🐑. Address: ${squeethWethPool.address}`)\n\n  if (network.name === \"mainnet\") {\n    return\n  }\n  const ethPriceInDai = 1300\n  const ethUSDPool = await createUniPool(ethPriceInDai, usdc, weth9, positionManager, uniswapFactory)\n  const tx2 = await ethUSDPool.increaseObservationCardinalityNext(128)\n  await ethers.provider.waitForTransaction(tx2.hash, 1)\n\n  console.log(`ETH/USD Pool created 🐑. Address: ${ethUSDPool.address}`)\n}\n\nexport default func;"
  },
  {
    "path": "packages/hardhat/deploy/04_deploy_controller.ts",
    "content": "import { HardhatRuntimeEnvironment } from 'hardhat/types';\nimport { DeployFunction } from 'hardhat-deploy/types';\n\nimport { getPoolAddress } from '../test/setup'\nimport { getUniswapDeployments, getUSDC, getWETH, createArgumentFile } from '../tasks/utils'\n\nconst func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {\n  const { getNamedAccounts, ethers, network, deployments } = hre;\n  const { deployer } = await getNamedAccounts();\n  const { deploy } = deployments;\n    \n  const feeTier = 3000\n\n  // Load contracts\n  const oracle = await ethers.getContract(\"Oracle\", deployer);\n  const shortSqueeth = await ethers.getContract(\"ShortPowerPerp\", deployer);\n  const wsqueeth = await ethers.getContract(\"WPowerPerp\", deployer);\n  const weth9 = await getWETH(ethers, deployer, network.name)\n  const usdc = await getUSDC(ethers, deployer, network.name)\n  const { uniswapFactory, positionManager } = await getUniswapDeployments(ethers, deployer, network.name)\n  const ethUSDCPool = await getPoolAddress(weth9, usdc, uniswapFactory)\n  const squeethEthPool = await getPoolAddress(weth9, wsqueeth, uniswapFactory)\n\n  if (network.name === 'goerli' || network.name === 'mainnet') return\n\n  // deploy abdk library\n  await deploy(\"ABDKMath64x64\", { from: deployer, log: true })\n  const abdk = await ethers.getContract(\"ABDKMath64x64\", deployer)\n\n  await deploy(\"TickMathExternal\", { from: deployer, log: true })\n  const tickMathExternal = await ethers.getContract(\"TickMathExternal\", deployer)\n\n  await deploy(\"SqrtPriceMathPartial\", { from: deployer, log: true })\n  const sqrtPriceMathPartial = await ethers.getContract(\"SqrtPriceMathPartial\", deployer)\n\n  // deploy controller\n  const controllerArgs = [oracle.address, shortSqueeth.address, wsqueeth.address, weth9.address, usdc.address, ethUSDCPool, squeethEthPool, positionManager.address, feeTier]\n  await deploy(\"Controller\", { from: deployer, log: true, libraries: { ABDKMath64x64: abdk.address, SqrtPriceMathPartial: sqrtPriceMathPartial.address, TickMathExternal: tickMathExternal.address }, args: controllerArgs });\n  createArgumentFile('Controller', network.name, controllerArgs)\n  const controller = await ethers.getContract(\"Controller\", deployer);\n\n  try {\n    const tx = await wsqueeth.init(controller.address, { from: deployer });\n    await ethers.provider.waitForTransaction(tx.hash, 1)\n    console.log(`Squeeth init done 🍋`);\n  } catch (error) {\n    console.log(`Squeeth already init or wrong deployer address.`)\n  }\n\n  try {\n    const tx = await shortSqueeth.init(controller.address, { from: deployer });\n    await ethers.provider.waitForTransaction(tx.hash, 1)\n    console.log(`ShortPowerPerp init done 🥭`);\n  } catch (error) {\n    console.log(`ShortPowerPerp already init or wrong deployer address.`)\n  }\n\n  const alsig = \"0x0144571202B48d8B3EEE3A95E4140B7144F8b72F\"\n\n  if (network.name === \"mainnet\") {\n    try {\n      const tx = await controller.transferOwnership(alsig, { from: deployer });\n      await ethers.provider.waitForTransaction(tx.hash, 1)\n      console.log(`Ownership transferred! 🥭`);\n    } catch (error) {\n      console.log(`Ownership transfer failed`)\n    }\n  }\n\n}\n\nexport default func;"
  },
  {
    "path": "packages/hardhat/deploy/05_deploy_periphery.ts",
    "content": "import { HardhatRuntimeEnvironment } from 'hardhat/types';\nimport { DeployFunction } from 'hardhat-deploy/types';\nimport { getUniswapDeployments, getWETH, createArgumentFile } from '../tasks/utils'\n\nconst func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {\n  const { deployments, getNamedAccounts, ethers, network } = hre;\n  const { deploy } = deployments;\n  const { deployer } = await getNamedAccounts();\n    \n  const controller = await ethers.getContract(\"Controller\", deployer);\n  const weth = await getWETH(ethers, deployer, network.name)\n  const { swapRouter } = await getUniswapDeployments(ethers, deployer, network.name)\n\n  const shortHelperArgs = [controller.address, swapRouter.address, weth.address]\n  await deploy(\"ShortHelper\", {\n    from: deployer,\n    log: true,\n    args: shortHelperArgs,\n    skipIfAlreadyDeployed: true,\n  });\n  createArgumentFile('ShortHelper', network.name, shortHelperArgs)\n  console.log(`Successfully deploy ShortHelper 🥦`)\n}\n\nexport default func;"
  },
  {
    "path": "packages/hardhat/deploy/06_deploy_crab_strategy.ts",
    "content": "import { HardhatRuntimeEnvironment } from 'hardhat/types';\nimport { DeployFunction } from 'hardhat-deploy/types';\nimport { getUniswapDeployments, getWETH, createArgumentFile } from '../tasks/utils'\nimport { getPoolAddress } from '../test/setup';\n\nconst func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {\n  const { deployments, getNamedAccounts, ethers, network } = hre;\n  const { deploy } = deployments;\n    \n  const { deployer } = await getNamedAccounts();\n  if (network.name === 'mainnet') return\n\n  const controller = await ethers.getContract(\"Controller\", deployer);\n  const oracle = await ethers.getContract(\"Oracle\", deployer);\n  const weth = await getWETH(ethers, deployer, network.name)\n  const wsqueeth = await ethers.getContract(\"WPowerPerp\", deployer);\n  const { uniswapFactory } = await getUniswapDeployments(ethers, deployer, network.name)\n  const squeethPoolAddr = await getPoolAddress(wsqueeth, weth, uniswapFactory)\n\n  // strategy parameters\n  const hedgeTimeThreshold = 86400\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n  // so this won't affect our deployment in test files\n  const crabStrategyArgs = [\n    controller.address,\n    oracle.address,\n    weth.address,\n    uniswapFactory.address,\n    squeethPoolAddr,\n    hedgeTimeThreshold,\n    hedgePriceThreshold,\n    auctionTime,\n    minPriceMultiplier,\n    maxPriceMultiplier\n  ]\n  await deploy(\"CrabStrategyDeployment\", {\n    contract: \"CrabStrategy\",\n    from: deployer,\n    log: true,\n    args: crabStrategyArgs,\n    gasLimit: 10000000,\n    skipIfAlreadyDeployed: true,\n  });\n  createArgumentFile('CrabStrategy', network.name, crabStrategyArgs)\n\n  console.log(`Successfully deploy CrabStrategy`)\n}\n\nexport default func;"
  },
  {
    "path": "packages/hardhat/deploy/07_deploy_controller_helper.ts",
    "content": "import { HardhatRuntimeEnvironment } from 'hardhat/types';\nimport { DeployFunction } from 'hardhat-deploy/types';\nimport { getUniswapDeployments, getController, getExec, getEuler, getDwethToken, createArgumentFile } from '../tasks/utils'\n\nconst func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {\n  const { deployments, getNamedAccounts, ethers, network } = hre;\n  const { deploy } = deployments;\n    \n  const { deployer } = await getNamedAccounts();\n\n  if (network.name === 'localhost' || network.name === 'goerli' || network.name === 'mainnet') return;\n\n  await deploy(\"TickMathExternal\", { from: deployer, log: true })\n  const tickMathExternal = await ethers.getContract(\"TickMathExternal\", deployer)\n\n  await deploy(\"SqrtPriceMathPartial\", { from: deployer, log: true })\n  const sqrtPriceMathPartial = await ethers.getContract(\"SqrtPriceMathPartial\", deployer)\n\n  // deploy ControllerHelperUtil lib\n  await deploy(\"ControllerHelperUtil\", { from: deployer, log: true, libraries: { TickMathExternal: tickMathExternal.address, SqrtPriceMathPartial: sqrtPriceMathPartial.address } })\n  const controllerHelperUtil = await ethers.getContract(\"ControllerHelperUtil\", deployer)\n\n  const controller = await getController(ethers, deployer, network.name);\n  console.log(\"controller\", controller.address)\n  const { positionManager, uniswapFactory } = await getUniswapDeployments(ethers, deployer, network.name)\n  console.log(\"positionManager\", positionManager.address)\n  console.log(\"uniswapFactory\", uniswapFactory.address)\n\n  const exec = await getExec(deployer, network.name)\n  const euler = await getEuler(deployer, network.name)\n  const dWethToken = await getDwethToken(deployer, network.name)\n  console.log(\"exec\", exec)\n  console.log(\"euler\", euler)\n  console.log(\"dWethToken\", dWethToken)\n\n  // deploy controller helper\n  const controllerHelperArgs = [controller.address, positionManager.address, uniswapFactory.address, exec, euler, dWethToken]\n  await deploy(\"ControllerHelper\", { from: deployer, log: true, libraries: { ControllerHelperUtil: controllerHelperUtil.address }, args: controllerHelperArgs });\n  const controllerHelper = await ethers.getContract(\"ControllerHelper\", deployer);\n\n  console.log(`Successfully deploy ControllerHelper ${controllerHelper.address}`)\n}\n\nexport default func;"
  },
  {
    "path": "packages/hardhat/deploy/08_deploy_crab_v2.ts",
    "content": "import { HardhatRuntimeEnvironment } from 'hardhat/types';\nimport { DeployFunction } from 'hardhat-deploy/types';\nimport { createArgumentFile, getCrab, getDwethToken, getEuler, getExec, getUniswapDeployments, getWETH } from '../tasks/utils'\nimport { getPoolAddress } from '../test/setup';\nimport { one } from '../test/utils';\n\nconst func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {\n  const { deployments, getNamedAccounts, ethers, network } = hre;\n  const { deploy } = deployments;\n    \n  const { deployer } = await getNamedAccounts();\n\n  const controller = await ethers.getContract(\"Controller\", deployer);\n  const oracle = await ethers.getContract(\"Oracle\", deployer);\n  const weth = await getWETH(ethers, deployer, network.name)\n  const wsqueeth = await ethers.getContract(\"WPowerPerp\", deployer);\n  const crabV1 = getCrab(network.name);\n\n  const { uniswapFactory, } = await getUniswapDeployments(ethers, deployer, network.name)\n\n  const squeethPoolAddr = await getPoolAddress(wsqueeth, weth, uniswapFactory)\n\n  const exec = await getExec(deployer, network.name)\n  const euler = await getEuler(deployer, network.name)\n  const dWethToken = await getDwethToken(deployer, network.name)\n\n  if (network.name === 'mainnet') {\n    const migrationArgs = [\n      crabV1,\n      weth.address,\n      exec,\n      dWethToken,\n      euler,\n    ]\n    // Deploy CrabMigration contract\n    await deploy(\"CrabMigration\", {\n      from: deployer,\n      log: true,\n      args: migrationArgs,\n      skipIfAlreadyDeployed: true,\n    });\n    console.log(`Successfully deploy CrabMigration`)\n  \n  \n    const timelockArgs = [\n      '0x609FFF64429e2A275a879e5C50e415cec842c629', // deployer,\n      432000,\n    ]\n    // Deploy Timelock contract\n    await deploy(\"Timelock\", {\n      from: deployer,\n      log: true,\n      args: timelockArgs,\n      skipIfAlreadyDeployed: true,\n    });\n    console.log(`Successfully deploy Timelock`)\n    createArgumentFile('CrabMigration', network.name, migrationArgs)\n    createArgumentFile('Timelock', network.name, timelockArgs)\n  \n  \n    const timelock = await ethers.getContract(\"Timelock\", deployer);\n    const migration = await ethers.getContract(\"CrabMigration\", deployer);\n    const v2args = [\n      controller.address,\n      oracle.address,\n      weth.address,\n      uniswapFactory.address,\n      squeethPoolAddr,\n      timelock.address,\n      migration.address,\n      3600,\n      '200000000000000000'\n    ]\n    // Deploy Crabv2 contract\n    await deploy(\"CrabStrategyV2\", {\n      from: deployer,\n      log: true,\n      args: v2args,\n      skipIfAlreadyDeployed: true,\n    });\n    createArgumentFile('CrabStrategyV2', network.name, v2args)\n    console.log(`Successfully deploy CrabStrategyV2`)\n  } else {\n    const v2args = [\n      controller.address,\n      oracle.address,\n      weth.address,\n      uniswapFactory.address,\n      squeethPoolAddr,\n      deployer,\n      deployer,\n      3600,\n      '200000000000000000'\n    ]\n    // Deploy Crabv2 contract\n    await deploy(\"CrabStrategyV2\", {\n      from: deployer,\n      log: true,\n      args: v2args,\n      skipIfAlreadyDeployed: true,\n      gasLimit: 10000000\n    });\n    createArgumentFile('CrabStrategyV2', network.name, v2args)\n    console.log(`Successfully deploy CrabStrategyV2`)\n  }\n}\n\nexport default func;"
  },
  {
    "path": "packages/hardhat/deploy/09_deploy_crab_helper.ts",
    "content": "\nimport { HardhatRuntimeEnvironment } from 'hardhat/types';\nimport { DeployFunction } from 'hardhat-deploy/types';\nimport { createArgumentFile, getUniswapDeployments} from '../tasks/utils'\n\nconst func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {\n  const { deployments, getNamedAccounts, ethers, network } = hre;\n  const { deploy } = deployments;\n\n  const { deployer } = await getNamedAccounts();\n\n  const { swapRouter } = await getUniswapDeployments(ethers, deployer, network.name)\n  const crabV2 = await ethers.getContract(\"CrabStrategyV2\", deployer);\n\n\n  const args = [crabV2.address, swapRouter.address]\n\n  console.log(crabV2.address, swapRouter.address)\n\n\n  // Deploy Crabv2 contract\n  await deploy(\"CrabHelper\", {\n    from: deployer,\n    log: true,\n    args,\n    skipIfAlreadyDeployed: true\n  });\n\n  createArgumentFile('CrabHelper', network.name, args)\n\n\n  console.log(`Successfully deploy CrabOTC`)\n}\n\nexport default func;"
  },
  {
    "path": "packages/hardhat/deployments/goerli/.chainId",
    "content": "5"
  },
  {
    "path": "packages/hardhat/deployments/goerli/ABDKMath64x64.json",
    "content": "{\n  \"address\": \"0x4CA8F19f951052162Bda12D1db72dEDa489dBD83\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"x\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"y\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"divu\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"x\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"name\": \"exp_2\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"x\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"name\": \"log_2\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x91efeeb7d065ed81f1f20fc46278de43d5a9a4c19bd22471b6ba61ecc7334fae\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x4CA8F19f951052162Bda12D1db72dEDa489dBD83\",\n    \"transactionIndex\": 6,\n    \"gasUsed\": \"941465\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x5f8ed3e5a63da131d6cda1ab2f24820e2bce2f2d9eab79129b50b4912ba9d1f0\",\n    \"transactionHash\": \"0x91efeeb7d065ed81f1f20fc46278de43d5a9a4c19bd22471b6ba61ecc7334fae\",\n    \"logs\": [],\n    \"blockNumber\": 8007857,\n    \"cumulativeGasUsed\": \"1749974\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"x\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"y\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"divu\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"int128\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"x\\\",\\\"type\\\":\\\"int128\\\"}],\\\"name\\\":\\\"exp_2\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"int128\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"x\\\",\\\"type\\\":\\\"int128\\\"}],\\\"name\\\":\\\"log_2\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"int128\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"divu(uint256,uint256)\\\":{\\\"params\\\":{\\\"x\\\":\\\"unsigned 256-bit integer number\\\",\\\"y\\\":\\\"unsigned 256-bit integer number\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"signed 64.64-bit fixed point number\\\"}},\\\"exp_2(int128)\\\":{\\\"params\\\":{\\\"x\\\":\\\"signed 64.64-bit fixed point number\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"signed 64.64-bit fixed point number\\\"}},\\\"log_2(int128)\\\":{\\\"params\\\":{\\\"x\\\":\\\"signed 64.64-bit fixed point number\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"signed 64.64-bit fixed point number\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"divu(uint256,uint256)\\\":{\\\"notice\\\":\\\"Calculate x / y rounding towards zero, where x and y are unsigned 256-bit integer numbers.  Revert on overflow or when y is zero.\\\"},\\\"exp_2(int128)\\\":{\\\"notice\\\":\\\"Calculate binary exponent of x.  Revert on overflow.\\\"},\\\"log_2(int128)\\\":{\\\"notice\\\":\\\"Calculate binary logarithm of x.  Revert if x <= 0.\\\"}},\\\"notice\\\":\\\"Smart contract library of mathematical functions operating with signed 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is basically a simple fraction whose numerator is signed 128-bit integer and denominator is 2^64.  As long as denominator is always the same, there is no need to store it, thus in Solidity signed 64.64-bit fixed point numbers are represented by int128 type holding only the numerator. Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4 Changes - some function visibility switched to public, solidity version set to 0.7.x Changes (cont) - revert strings added solidity version set to ^0.7.0\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/libs/ABDKMath64x64.sol\\\":\\\"ABDKMath64x64\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"contracts/libs/ABDKMath64x64.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: BSD-4-Clause\\\\n/*\\\\n * ABDK Math 64.64 Smart Contract Library.  Copyright \\\\u00a9 2019 by ABDK Consulting.\\\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\\\n * Copyright (c) 2019, ABDK Consulting\\\\n *\\\\n * All rights reserved.\\\\n *\\\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\\\n *\\\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\\\n */\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * Smart contract library of mathematical functions operating with signed\\\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\\\n * represented by int128 type holding only the numerator.\\\\n *\\\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\\\n * Changes (cont) - revert strings added\\\\n * solidity version set to ^0.7.0\\\\n */\\\\nlibrary ABDKMath64x64 {\\\\n    /*\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * -2^127\\\\n     */\\\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\\\n\\\\n    /*\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * 2^127-1\\\\n     */\\\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @param y signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\\\n        int256 result = (int256(x) * y) >> 64;\\\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\\\\\"MUL-OVUF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64 fixed point number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 256-bit integer number\\\\n     */\\\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\\\n        if (y == 0) return 0;\\\\n\\\\n        require(x >= 0, \\\\\\\"MULU-X0\\\\\\\");\\\\n\\\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\\\n        uint256 hi = uint256(x) * (y >> 128);\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"MULU-OF1\\\\\\\");\\\\n        hi <<= 64;\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\\\\\"MULU-OF2\\\\\\\");\\\\n        return hi + lo;\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\\\n        require(y != 0, \\\\\\\"DIVU-INF\\\\\\\");\\\\n        uint128 result = divuu(x, y);\\\\n        require(result <= uint128(MAX_64x64), \\\\\\\"DIVU-OF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function log_2(int128 x) public pure returns (int128) {\\\\n        require(x > 0, \\\\\\\"LOG_2-X0\\\\\\\");\\\\n\\\\n        int256 msb = 0;\\\\n        int256 xc = x;\\\\n        if (xc >= 0x10000000000000000) {\\\\n            xc >>= 64;\\\\n            msb += 64;\\\\n        }\\\\n        if (xc >= 0x100000000) {\\\\n            xc >>= 32;\\\\n            msb += 32;\\\\n        }\\\\n        if (xc >= 0x10000) {\\\\n            xc >>= 16;\\\\n            msb += 16;\\\\n        }\\\\n        if (xc >= 0x100) {\\\\n            xc >>= 8;\\\\n            msb += 8;\\\\n        }\\\\n        if (xc >= 0x10) {\\\\n            xc >>= 4;\\\\n            msb += 4;\\\\n        }\\\\n        if (xc >= 0x4) {\\\\n            xc >>= 2;\\\\n            msb += 2;\\\\n        }\\\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n        int256 result = (msb - 64) << 64;\\\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\\\n            ux *= ux;\\\\n            uint256 b = ux >> 255;\\\\n            ux >>= 127 + b;\\\\n            result += bit * int256(b);\\\\n        }\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary exponent of x.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function exp_2(int128 x) public pure returns (int128) {\\\\n        require(x < 0x400000000000000000, \\\\\\\"EXP_2-OF\\\\\\\"); // Overflow\\\\n\\\\n        if (x < -0x400000000000000000) return 0; // Underflow\\\\n\\\\n        uint256 result = 0x80000000000000000000000000000000;\\\\n\\\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\\\n\\\\n        result >>= uint256(63 - (x >> 64));\\\\n        require(result <= uint256(MAX_64x64));\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 64.64-bit fixed point number\\\\n     */\\\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\\\n        require(y != 0);\\\\n\\\\n        uint256 result;\\\\n\\\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\\\n        else {\\\\n            uint256 msb = 192;\\\\n            uint256 xc = x >> 192;\\\\n            if (xc >= 0x100000000) {\\\\n                xc >>= 32;\\\\n                msb += 32;\\\\n            }\\\\n            if (xc >= 0x10000) {\\\\n                xc >>= 16;\\\\n                msb += 16;\\\\n            }\\\\n            if (xc >= 0x100) {\\\\n                xc >>= 8;\\\\n                msb += 8;\\\\n            }\\\\n            if (xc >= 0x10) {\\\\n                xc >>= 4;\\\\n                msb += 4;\\\\n            }\\\\n            if (xc >= 0x4) {\\\\n                xc >>= 2;\\\\n                msb += 2;\\\\n            }\\\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF1\\\\\\\");\\\\n\\\\n            uint256 hi = result * (y >> 128);\\\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\\\n\\\\n            uint256 xh = x >> 192;\\\\n            uint256 xl = x << 64;\\\\n\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n            lo = hi << 128;\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n\\\\n            assert(xh == hi >> 128);\\\\n\\\\n            result += xl / y;\\\\n        }\\\\n\\\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF2\\\\\\\");\\\\n        return uint128(result);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x56efa7c16e4fffb37ad80af15bd042d9f92532a4553d6b12915e3fa21609ad66\\\",\\\"license\\\":\\\"BSD-4-Clause\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x611035610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80632cbbdee514610050578063fc193cf214610087578063fc505d37146100a7575b600080fd5b6100706004803603602081101561006657600080fd5b5035600f0b6100ca565b60408051600f9290920b8252519081900360200190f35b6100706004803603602081101561009d57600080fd5b5035600f0b6101f8565b610070600480360360408110156100bd57600080fd5b5080359060200135610d19565b60008082600f0b13610123576040805162461bcd60e51b815260206004820152600860248201527f4c4f475f322d5830000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000600f83900b680100000000000000008112610142576040918201911d5b6401000000008112610156576020918201911d5b620100008112610168576010918201911d5b6101008112610179576008918201911d5b60108112610189576004918201911d5b60048112610199576002918201911d5b600281126101a8576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b60008113156101eb5790800260ff81901c8281029390930192607f011c9060011d6101c5565b509093505050505b919050565b60006840000000000000000082600f0b1261025a576040805162461bcd60e51b815260206004820152600860248201527f4558505f322d4f46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b683fffffffffffffffff1982600f0b1215610277575060006101f3565b6f8000000000000000000000000000000060006780000000000000008416600f0b13156102b55770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b60008367400000000000000016600f0b13156102e2577001306fe0a31b7152de8d5a46305c85edec0260801c5b60008367200000000000000016600f0b131561030f577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b60008367100000000000000016600f0b131561033c5770010b5586cf9890f6298b92b71842a983630260801c5b60008367080000000000000016600f0b1315610369577001059b0d31585743ae7c548eb68ca417fd0260801c5b60008367040000000000000016600f0b131561039657700102c9a3e778060ee6f7caca4f7a29bde80260801c5b60008367020000000000000016600f0b13156103c35770010163da9fb33356d84a66ae336dcdfa3f0260801c5b60008367010000000000000016600f0b13156103f057700100b1afa5abcbed6129ab13ec11dc95430260801c5b600083668000000000000016600f0b131561041c5770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600083664000000000000016600f0b1315610448577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600083662000000000000016600f0b131561047457700100162f3904051fa128bca9c55c31e5df0260801c5b600083661000000000000016600f0b13156104a0577001000b175effdc76ba38e31671ca9397250260801c5b600083660800000000000016600f0b13156104cc57700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600083660400000000000016600f0b13156104f85770010002c5cc37da9491d0985c348c68e7b30260801c5b600083660200000000000016600f0b1315610524577001000162e525ee054754457d59952920260260801c5b600083660100000000000016600f0b13156105505770010000b17255775c040618bf4a4ade83fc0260801c5b6000836580000000000016600f0b131561057b577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6000836540000000000016600f0b13156105a657700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6000836520000000000016600f0b13156105d15770010000162e43f4f831060e02d839a9d16d0260801c5b6000836510000000000016600f0b13156105fc57700100000b1721bcfc99d9f890ea069117630260801c5b6000836508000000000016600f0b13156106275770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6000836504000000000016600f0b1315610652577001000002c5c863b73f016468f6bac5ca2b0260801c5b6000836502000000000016600f0b131561067d57700100000162e430e5a18f6119e3c02282a50260801c5b6000836501000000000016600f0b13156106a8577001000000b1721835514b86e6d96efd1bfe0260801c5b60008364800000000016600f0b13156106d257700100000058b90c0b48c6be5df846c5b2ef0260801c5b60008364400000000016600f0b13156106fc5770010000002c5c8601cc6b9e94213c72737a0260801c5b60008364200000000016600f0b1315610726577001000000162e42fff037df38aa2b219f060260801c5b60008364100000000016600f0b13156107505770010000000b17217fba9c739aa5819f44f90260801c5b60008364080000000016600f0b131561077a577001000000058b90bfcdee5acd3c1cedc8230260801c5b60008364040000000016600f0b13156107a457700100000002c5c85fe31f35a6a30da1be500260801c5b60008364020000000016600f0b13156107ce5770010000000162e42ff0999ce3541b9fffcf0260801c5b60008364010000000016600f0b13156107f857700100000000b17217f80f4ef5aadda455540260801c5b600083638000000016600f0b13156108215770010000000058b90bfbf8479bd5a81b51ad0260801c5b600083634000000016600f0b131561084a577001000000002c5c85fdf84bd62ae30a74cc0260801c5b600083632000000016600f0b131561087357700100000000162e42fefb2fed257559bdaa0260801c5b600083631000000016600f0b131561089c577001000000000b17217f7d5a7716bba4a9ae0260801c5b600083630800000016600f0b13156108c557700100000000058b90bfbe9ddbac5e109cce0260801c5b600083630400000016600f0b13156108ee5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600083630200000016600f0b1315610917577001000000000162e42fefa494f1478fde050260801c5b600083630100000016600f0b13156109405770010000000000b17217f7d20cf927c8e94c0260801c5b6000836280000016600f0b1315610968577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6000836240000016600f0b131561099057700100000000002c5c85fdf477b662b269450260801c5b6000836220000016600f0b13156109b85770010000000000162e42fefa3ae53369388c0260801c5b6000836210000016600f0b13156109e057700100000000000b17217f7d1d351a389d400260801c5b6000836208000016600f0b1315610a085770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6000836204000016600f0b1315610a30577001000000000002c5c85fdf4741bea6e77e0260801c5b6000836202000016600f0b1315610a5857700100000000000162e42fefa39fe95583c20260801c5b6000836201000016600f0b1315610a80577001000000000000b17217f7d1cfb72b45e10260801c5b60008361800016600f0b1315610aa757700100000000000058b90bfbe8e7cc35c3f00260801c5b60008361400016600f0b1315610ace5770010000000000002c5c85fdf473e242ea380260801c5b60008361200016600f0b1315610af5577001000000000000162e42fefa39f02b772c0260801c5b60008361100016600f0b1315610b1c5770010000000000000b17217f7d1cf7d83c1a0260801c5b60008361080016600f0b1315610b43577001000000000000058b90bfbe8e7bdcbe2e0260801c5b60008361040016600f0b1315610b6a57700100000000000002c5c85fdf473dea871f0260801c5b60008361020016600f0b1315610b915770010000000000000162e42fefa39ef44d910260801c5b60008361010016600f0b1315610bb857700100000000000000b17217f7d1cf79e9490260801c5b600083608016600f0b1315610bde5770010000000000000058b90bfbe8e7bce5440260801c5b600083604016600f0b1315610c04577001000000000000002c5c85fdf473de6eca0260801c5b600083602016600f0b1315610c2a57700100000000000000162e42fefa39ef366f0260801c5b600083601016600f0b1315610c50577001000000000000000b17217f7d1cf79afa0260801c5b600083600816600f0b1315610c7657700100000000000000058b90bfbe8e7bcd6d0260801c5b600083600416600f0b1315610c9c5770010000000000000002c5c85fdf473de6b20260801c5b600083600216600f0b1315610cc2577001000000000000000162e42fefa39ef3580260801c5b600083600116600f0b1315610ce85770010000000000000000b17217f7d1cf79ab0260801c5b600f83810b60401d603f03900b1c6f7fffffffffffffffffffffffffffffff811115610d1357600080fd5b92915050565b600081610d6d576040805162461bcd60e51b815260206004820152600860248201527f444956552d494e46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000610d798484610df9565b90506f7fffffffffffffffffffffffffffffff6fffffffffffffffffffffffffffffffff82161115610df2576040805162461bcd60e51b815260206004820152600760248201527f444956552d4f4600000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b9392505050565b600081610e0557600080fd5b600077ffffffffffffffffffffffffffffffffffffffffffffffff8411610e3b5782604085901b81610e3357fe5b049050610f9a565b60c084811c6401000000008110610e54576020918201911c5b620100008110610e66576010918201911c5b6101008110610e77576008918201911c5b60108110610e87576004918201911c5b60048110610e97576002918201911c5b60028110610ea6576001820191505b60bf820360018603901c6001018260ff0387901b81610ec157fe5b0492506fffffffffffffffffffffffffffffffff831115610f29576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46310000000000000000000000000000000000000000000000604482015290519081900360640190fd5b608085901c83026fffffffffffffffffffffffffffffffff8616840260c088901c604089901b82811015610f5e576001820391505b608084901b92900382811015610f75576001820391505b829003608084901c8214610f8557fe5b888181610f8e57fe5b04870196505050505050505b6fffffffffffffffffffffffffffffffff811115610df2576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46320000000000000000000000000000000000000000000000604482015290519081900360640190fdfea2646970667358221220df4e4ccd16b278e7c05ac3ef1eb9305435ba9d3de32df96561025dbc371ca54e64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80632cbbdee514610050578063fc193cf214610087578063fc505d37146100a7575b600080fd5b6100706004803603602081101561006657600080fd5b5035600f0b6100ca565b60408051600f9290920b8252519081900360200190f35b6100706004803603602081101561009d57600080fd5b5035600f0b6101f8565b610070600480360360408110156100bd57600080fd5b5080359060200135610d19565b60008082600f0b13610123576040805162461bcd60e51b815260206004820152600860248201527f4c4f475f322d5830000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000600f83900b680100000000000000008112610142576040918201911d5b6401000000008112610156576020918201911d5b620100008112610168576010918201911d5b6101008112610179576008918201911d5b60108112610189576004918201911d5b60048112610199576002918201911d5b600281126101a8576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b60008113156101eb5790800260ff81901c8281029390930192607f011c9060011d6101c5565b509093505050505b919050565b60006840000000000000000082600f0b1261025a576040805162461bcd60e51b815260206004820152600860248201527f4558505f322d4f46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b683fffffffffffffffff1982600f0b1215610277575060006101f3565b6f8000000000000000000000000000000060006780000000000000008416600f0b13156102b55770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b60008367400000000000000016600f0b13156102e2577001306fe0a31b7152de8d5a46305c85edec0260801c5b60008367200000000000000016600f0b131561030f577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b60008367100000000000000016600f0b131561033c5770010b5586cf9890f6298b92b71842a983630260801c5b60008367080000000000000016600f0b1315610369577001059b0d31585743ae7c548eb68ca417fd0260801c5b60008367040000000000000016600f0b131561039657700102c9a3e778060ee6f7caca4f7a29bde80260801c5b60008367020000000000000016600f0b13156103c35770010163da9fb33356d84a66ae336dcdfa3f0260801c5b60008367010000000000000016600f0b13156103f057700100b1afa5abcbed6129ab13ec11dc95430260801c5b600083668000000000000016600f0b131561041c5770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600083664000000000000016600f0b1315610448577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600083662000000000000016600f0b131561047457700100162f3904051fa128bca9c55c31e5df0260801c5b600083661000000000000016600f0b13156104a0577001000b175effdc76ba38e31671ca9397250260801c5b600083660800000000000016600f0b13156104cc57700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600083660400000000000016600f0b13156104f85770010002c5cc37da9491d0985c348c68e7b30260801c5b600083660200000000000016600f0b1315610524577001000162e525ee054754457d59952920260260801c5b600083660100000000000016600f0b13156105505770010000b17255775c040618bf4a4ade83fc0260801c5b6000836580000000000016600f0b131561057b577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6000836540000000000016600f0b13156105a657700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6000836520000000000016600f0b13156105d15770010000162e43f4f831060e02d839a9d16d0260801c5b6000836510000000000016600f0b13156105fc57700100000b1721bcfc99d9f890ea069117630260801c5b6000836508000000000016600f0b13156106275770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6000836504000000000016600f0b1315610652577001000002c5c863b73f016468f6bac5ca2b0260801c5b6000836502000000000016600f0b131561067d57700100000162e430e5a18f6119e3c02282a50260801c5b6000836501000000000016600f0b13156106a8577001000000b1721835514b86e6d96efd1bfe0260801c5b60008364800000000016600f0b13156106d257700100000058b90c0b48c6be5df846c5b2ef0260801c5b60008364400000000016600f0b13156106fc5770010000002c5c8601cc6b9e94213c72737a0260801c5b60008364200000000016600f0b1315610726577001000000162e42fff037df38aa2b219f060260801c5b60008364100000000016600f0b13156107505770010000000b17217fba9c739aa5819f44f90260801c5b60008364080000000016600f0b131561077a577001000000058b90bfcdee5acd3c1cedc8230260801c5b60008364040000000016600f0b13156107a457700100000002c5c85fe31f35a6a30da1be500260801c5b60008364020000000016600f0b13156107ce5770010000000162e42ff0999ce3541b9fffcf0260801c5b60008364010000000016600f0b13156107f857700100000000b17217f80f4ef5aadda455540260801c5b600083638000000016600f0b13156108215770010000000058b90bfbf8479bd5a81b51ad0260801c5b600083634000000016600f0b131561084a577001000000002c5c85fdf84bd62ae30a74cc0260801c5b600083632000000016600f0b131561087357700100000000162e42fefb2fed257559bdaa0260801c5b600083631000000016600f0b131561089c577001000000000b17217f7d5a7716bba4a9ae0260801c5b600083630800000016600f0b13156108c557700100000000058b90bfbe9ddbac5e109cce0260801c5b600083630400000016600f0b13156108ee5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600083630200000016600f0b1315610917577001000000000162e42fefa494f1478fde050260801c5b600083630100000016600f0b13156109405770010000000000b17217f7d20cf927c8e94c0260801c5b6000836280000016600f0b1315610968577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6000836240000016600f0b131561099057700100000000002c5c85fdf477b662b269450260801c5b6000836220000016600f0b13156109b85770010000000000162e42fefa3ae53369388c0260801c5b6000836210000016600f0b13156109e057700100000000000b17217f7d1d351a389d400260801c5b6000836208000016600f0b1315610a085770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6000836204000016600f0b1315610a30577001000000000002c5c85fdf4741bea6e77e0260801c5b6000836202000016600f0b1315610a5857700100000000000162e42fefa39fe95583c20260801c5b6000836201000016600f0b1315610a80577001000000000000b17217f7d1cfb72b45e10260801c5b60008361800016600f0b1315610aa757700100000000000058b90bfbe8e7cc35c3f00260801c5b60008361400016600f0b1315610ace5770010000000000002c5c85fdf473e242ea380260801c5b60008361200016600f0b1315610af5577001000000000000162e42fefa39f02b772c0260801c5b60008361100016600f0b1315610b1c5770010000000000000b17217f7d1cf7d83c1a0260801c5b60008361080016600f0b1315610b43577001000000000000058b90bfbe8e7bdcbe2e0260801c5b60008361040016600f0b1315610b6a57700100000000000002c5c85fdf473dea871f0260801c5b60008361020016600f0b1315610b915770010000000000000162e42fefa39ef44d910260801c5b60008361010016600f0b1315610bb857700100000000000000b17217f7d1cf79e9490260801c5b600083608016600f0b1315610bde5770010000000000000058b90bfbe8e7bce5440260801c5b600083604016600f0b1315610c04577001000000000000002c5c85fdf473de6eca0260801c5b600083602016600f0b1315610c2a57700100000000000000162e42fefa39ef366f0260801c5b600083601016600f0b1315610c50577001000000000000000b17217f7d1cf79afa0260801c5b600083600816600f0b1315610c7657700100000000000000058b90bfbe8e7bcd6d0260801c5b600083600416600f0b1315610c9c5770010000000000000002c5c85fdf473de6b20260801c5b600083600216600f0b1315610cc2577001000000000000000162e42fefa39ef3580260801c5b600083600116600f0b1315610ce85770010000000000000000b17217f7d1cf79ab0260801c5b600f83810b60401d603f03900b1c6f7fffffffffffffffffffffffffffffff811115610d1357600080fd5b92915050565b600081610d6d576040805162461bcd60e51b815260206004820152600860248201527f444956552d494e46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000610d798484610df9565b90506f7fffffffffffffffffffffffffffffff6fffffffffffffffffffffffffffffffff82161115610df2576040805162461bcd60e51b815260206004820152600760248201527f444956552d4f4600000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b9392505050565b600081610e0557600080fd5b600077ffffffffffffffffffffffffffffffffffffffffffffffff8411610e3b5782604085901b81610e3357fe5b049050610f9a565b60c084811c6401000000008110610e54576020918201911c5b620100008110610e66576010918201911c5b6101008110610e77576008918201911c5b60108110610e87576004918201911c5b60048110610e97576002918201911c5b60028110610ea6576001820191505b60bf820360018603901c6001018260ff0387901b81610ec157fe5b0492506fffffffffffffffffffffffffffffffff831115610f29576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46310000000000000000000000000000000000000000000000604482015290519081900360640190fd5b608085901c83026fffffffffffffffffffffffffffffffff8616840260c088901c604089901b82811015610f5e576001820391505b608084901b92900382811015610f75576001820391505b829003608084901c8214610f8557fe5b888181610f8e57fe5b04870196505050505050505b6fffffffffffffffffffffffffffffffff811115610df2576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46320000000000000000000000000000000000000000000000604482015290519081900360640190fdfea2646970667358221220df4e4ccd16b278e7c05ac3ef1eb9305435ba9d3de32df96561025dbc371ca54e64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"divu(uint256,uint256)\": {\n        \"params\": {\n          \"x\": \"unsigned 256-bit integer number\",\n          \"y\": \"unsigned 256-bit integer number\"\n        },\n        \"returns\": {\n          \"_0\": \"signed 64.64-bit fixed point number\"\n        }\n      },\n      \"exp_2(int128)\": {\n        \"params\": {\n          \"x\": \"signed 64.64-bit fixed point number\"\n        },\n        \"returns\": {\n          \"_0\": \"signed 64.64-bit fixed point number\"\n        }\n      },\n      \"log_2(int128)\": {\n        \"params\": {\n          \"x\": \"signed 64.64-bit fixed point number\"\n        },\n        \"returns\": {\n          \"_0\": \"signed 64.64-bit fixed point number\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"divu(uint256,uint256)\": {\n        \"notice\": \"Calculate x / y rounding towards zero, where x and y are unsigned 256-bit integer numbers.  Revert on overflow or when y is zero.\"\n      },\n      \"exp_2(int128)\": {\n        \"notice\": \"Calculate binary exponent of x.  Revert on overflow.\"\n      },\n      \"log_2(int128)\": {\n        \"notice\": \"Calculate binary logarithm of x.  Revert if x <= 0.\"\n      }\n    },\n    \"notice\": \"Smart contract library of mathematical functions operating with signed 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is basically a simple fraction whose numerator is signed 128-bit integer and denominator is 2^64.  As long as denominator is always the same, there is no need to store it, thus in Solidity signed 64.64-bit fixed point numbers are represented by int128 type holding only the numerator. Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4 Changes - some function visibility switched to public, solidity version set to 0.7.x Changes (cont) - revert strings added solidity version set to ^0.7.0\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/Controller.json",
    "content": "{\n  \"address\": \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_oracle\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_shortPowerPerp\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wPowerPerp\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_weth\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_quoteCurrency\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_ethQuoteCurrencyPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wPowerPerpPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniPositionManager\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_feeTier\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"BurnShort\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"DepositCollateral\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"DepositUniPositionToken\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"oldFee\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newFee\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FeeRateUpdated\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"oldFeeRecipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"newFeeRecipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"FeeRecipientUpdated\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"liquidator\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"debtAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"collateralPaid\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Liquidate\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"MintShort\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"oldNormFactor\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newNormFactor\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"lastModificationTimestamp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"timestamp\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"NormalizationFactorUpdated\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"OpenVault\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"pausesLeft\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Paused\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"payoutAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"RedeemLong\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vauldId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"collateralAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"RedeemShort\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethRedeemed\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpRedeemed\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpBurned\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpExcess\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"bounty\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ReduceDebt\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"indexForSettlement\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Shutdown\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"unpauser\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"UnPaused\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"UpdateOperator\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawCollateral\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawUniPositionToken\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"FUNDING_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"TWAP_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"applyFunding\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_powerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_withdrawAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burnPowerPerpAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_withdrawAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burnWPowerPerpAmount\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"deposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniTokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"depositUniPositionToken\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"donate\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"ethQuoteCurrencyPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"feeRate\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"feeRecipient\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"feeTier\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getDenormalizedMark\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getDenormalizedMarkForFunding\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getExpectedNormalizationFactor\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getUnscaledIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"indexForSettlement\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isShutDown\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isSystemPaused\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"isVaultSafe\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"lastFundingUpdateTimestamp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"\",\n          \"type\": \"uint128\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"lastPauseTime\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxDebtAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"liquidate\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_powerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniTokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"mintPowerPerpAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniTokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"mintWPowerPerpAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"normalizationFactor\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"\",\n          \"type\": \"uint128\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onERC721Received\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"oracle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"pause\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"pausesLeft\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"quoteCurrency\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPerpAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"redeemLong\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"redeemShort\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"reduceDebt\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"reduceDebtShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_newFeeRate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setFeeRate\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_newFeeRecipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"setFeeRecipient\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"shortPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"shutDown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"unPauseAnyone\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"unPauseOwner\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_operator\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"updateOperator\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"vaults\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"NftCollateralId\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint96\",\n          \"name\": \"collateralAmount\",\n          \"type\": \"uint96\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"shortAmount\",\n          \"type\": \"uint128\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerpPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdrawUniPositionToken\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x7862c494ccacafdf2341ec21586d9b3c3849e2ad5191ef46abb534a5fd4a9afd\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n    \"transactionIndex\": 33,\n    \"gasUsed\": \"5402930\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000801000000000000000000000000000800400000000000000000000000010000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000020000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x120b7f2f676f228741b44fbb0ad417176cb27c4617f52fd0d24e4f72ec52c614\",\n    \"transactionHash\": \"0x7862c494ccacafdf2341ec21586d9b3c3849e2ad5191ef46abb534a5fd4a9afd\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 33,\n        \"blockNumber\": 8008092,\n        \"transactionHash\": \"0x7862c494ccacafdf2341ec21586d9b3c3849e2ad5191ef46abb534a5fd4a9afd\",\n        \"address\": \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n        \"topics\": [\n          \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000006326a0dfe0517ff46af3ad16bc40c26c26397f9e\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 108,\n        \"blockHash\": \"0x120b7f2f676f228741b44fbb0ad417176cb27c4617f52fd0d24e4f72ec52c614\"\n      }\n    ],\n    \"blockNumber\": 8008092,\n    \"cumulativeGasUsed\": \"14075295\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0xf7F94b4607Bcd1235212803bE8fD1B54D1D01b77\",\n    \"0xe85595e810B77cf606D0aFd7eB575BB025323beE\",\n    \"0x9421c968D28DD789363FbD8c9aA5cF2090F0a656\",\n    \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\n    \"0x306bf03b689f7d7e5e9D3aAC87a068F16AFF9482\",\n    \"0x5d3EfE9157003f05be0d4031F00D43F952d6F6b7\",\n    \"0xC3c29372B5138d48993F0699A129b9EADf5191Bf\",\n    \"0x24a66308bab3BEbC2821480adA395BF1C4ff8Bf2\",\n    3000\n  ],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_oracle\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_shortPowerPerp\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wPowerPerp\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_weth\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_quoteCurrency\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_ethQuoteCurrencyPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniPositionManager\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_feeTier\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"BurnShort\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"DepositCollateral\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"DepositUniPositionToken\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"oldFee\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newFee\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FeeRateUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"oldFeeRecipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newFeeRecipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"FeeRecipientUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"liquidator\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"debtAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralPaid\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Liquidate\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"MintShort\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"oldNormFactor\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newNormFactor\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"lastModificationTimestamp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"timestamp\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"NormalizationFactorUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"OpenVault\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"pausesLeft\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Paused\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"payoutAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"RedeemLong\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vauldId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"RedeemShort\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethRedeemed\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpRedeemed\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpBurned\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpExcess\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bounty\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ReduceDebt\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"indexForSettlement\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Shutdown\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"unpauser\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"UnPaused\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"UpdateOperator\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawCollateral\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawUniPositionToken\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"FUNDING_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"TWAP_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"applyFunding\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burnPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burnWPowerPerpAmount\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"deposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"depositUniPositionToken\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"donate\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"ethQuoteCurrencyPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"feeRate\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"feeRecipient\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"feeTier\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getDenormalizedMark\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getDenormalizedMarkForFunding\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getExpectedNormalizationFactor\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getUnscaledIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"indexForSettlement\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isShutDown\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isSystemPaused\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"isVaultSafe\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"lastFundingUpdateTimestamp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"lastPauseTime\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxDebtAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"liquidate\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mintPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mintWPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"normalizationFactor\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onERC721Received\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"oracle\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"pause\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"pausesLeft\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"quoteCurrency\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"redeemLong\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"redeemShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"reduceDebt\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"reduceDebtShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_newFeeRate\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setFeeRate\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_newFeeRecipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"setFeeRecipient\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"shortPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"shutDown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"unPauseAnyone\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"unPauseOwner\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"updateOperator\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"vaults\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"NftCollateralId\\\",\\\"type\\\":\\\"uint32\\\"},{\\\"internalType\\\":\\\"uint96\\\",\\\"name\\\":\\\"collateralAmount\\\",\\\"type\\\":\\\"uint96\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"shortAmount\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdrawUniPositionToken\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"burnPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_powerPerpAmount\\\":\\\"amount of powerPerp to burn\\\",\\\"_vaultId\\\":\\\"id of the vault\\\",\\\"_withdrawAmount\\\":\\\"amount of eth to withdraw\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"amount of wPowerPerp burned\\\"}},\\\"burnWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to burn\\\",\\\"_withdrawAmount\\\":\\\"amount of eth to withdraw\\\"}},\\\"constructor\\\":{\\\"params\\\":{\\\"_ethQuoteCurrencyPool\\\":\\\"uniswap v3 pool for weth / quoteCurrency\\\",\\\"_oracle\\\":\\\"oracle address\\\",\\\"_quoteCurrency\\\":\\\"quoteCurrency address\\\",\\\"_shortPowerPerp\\\":\\\"ERC721 token address representing the short position\\\",\\\"_uniPositionManager\\\":\\\"uniswap v3 position manager address\\\",\\\"_wPowerPerp\\\":\\\"ERC20 token address representing the long position\\\",\\\"_wPowerPerpPool\\\":\\\"uniswap v3 pool for wPowerPerp / weth\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"deposit(uint256)\\\":{\\\"details\\\":\\\"deposit collateral into a vault\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"depositUniPositionToken(uint256,uint256)\\\":{\\\"params\\\":{\\\"_uniTokenId\\\":\\\"uniswap position token id\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"getDenormalizedMark(uint32)\\\":{\\\"params\\\":{\\\"_period\\\":\\\"period of time for the twap in seconds\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"mark price denominated in $USD, scaled by 1e18\\\"}},\\\"getDenormalizedMarkForFunding(uint32)\\\":{\\\"details\\\":\\\"this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\\",\\\"params\\\":{\\\"_period\\\":\\\"period which you want to calculate twap with\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"mark price denominated in $USD, scaled by 1e18\\\"}},\\\"getExpectedNormalizationFactor()\\\":{\\\"details\\\":\\\"can be used for on-chain and off-chain calculations\\\"},\\\"getIndex(uint32)\\\":{\\\"details\\\":\\\"the index price is scaled down by INDEX_SCALE in the associated PowerXBase librarythis is the index price used when calculating funding and for collateralization\\\",\\\"params\\\":{\\\"_period\\\":\\\"period which you want to calculate twap with\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"index price denominated in $USD, scaled by 1e18\\\"}},\\\"getUnscaledIndex(uint32)\\\":{\\\"details\\\":\\\"this is the mark that would be be used for future funding after a new normalization factor is applied\\\",\\\"params\\\":{\\\"_period\\\":\\\"period which you want to calculate twap with\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"index price denominated in $USD, scaled by 1e18\\\"}},\\\"isVaultSafe(uint256)\\\":{\\\"details\\\":\\\"return if the vault is properly collateralized\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"true if the vault is properly collateralized\\\"}},\\\"liquidate(uint256,uint256)\\\":{\\\"details\\\":\\\"liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateralnormally can only liquidate 50% of a vault's debtif a vault is under dust limit after a liquidation can fully liquidatewill attempt to reduceDebt first, and can earn a bounty if sucessful\\\",\\\"params\\\":{\\\"_maxDebtAmount\\\":\\\"max amount of wPowerPerpetual to repay\\\",\\\"_vaultId\\\":\\\"vault to liquidate\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"amount of wPowerPerp repaid\\\"}},\\\"mintPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_powerPerpAmount\\\":\\\"amount of powerPerp to mint\\\",\\\"_uniTokenId\\\":\\\"uniswap v3 position token id (additional collateral)\\\",\\\"_vaultId\\\":\\\"vault to mint wPowerPerp in\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"vaultId\\\",\\\"_1\\\":\\\"amount of wPowerPerp minted\\\"}},\\\"mintWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_uniTokenId\\\":\\\"uniswap v3 position token id (additional collateral)\\\",\\\"_vaultId\\\":\\\"vault to mint wPowerPerp in\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to mint\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"vaultId\\\"}},\\\"onERC721Received(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"accept erc721 from safeTransferFrom and safeMint after callback\\\",\\\"returns\\\":{\\\"_0\\\":\\\"returns received selector\\\"}},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"pause()\\\":{\\\"details\\\":\\\"can only be called for 365 days since the contract was launched or 4 times\\\"},\\\"redeemLong(uint256)\\\":{\\\"params\\\":{\\\"_wPerpAmount\\\":\\\"amount of wPowerPerp to burn\\\"}},\\\"redeemShort(uint256)\\\":{\\\"details\\\":\\\"short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"vault id\\\"}},\\\"reduceDebt(uint256)\\\":{\\\"details\\\":\\\"the caller won't get any bounty. this is expected to be used by vault owner\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"target vault\\\"}},\\\"reduceDebtShutdown(uint256)\\\":{\\\"details\\\":\\\"the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"vault containing uniswap v3 position to liquidate\\\"}},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"setFeeRate(uint256)\\\":{\\\"details\\\":\\\"this function cannot be called if the feeRecipient is still un-set\\\",\\\"params\\\":{\\\"_newFeeRate\\\":\\\"new fee rate in basis points. can't be higher than 1%\\\"}},\\\"setFeeRecipient(address)\\\":{\\\"details\\\":\\\"this should be a contract handling insurance\\\",\\\"params\\\":{\\\"_newFeeRecipient\\\":\\\"new fee recipient\\\"}},\\\"shutDown()\\\":{\\\"details\\\":\\\"this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\\"},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"unPauseAnyone()\\\":{\\\"details\\\":\\\"anyone can unpause the contract after 24 hours\\\"},\\\"unPauseOwner()\\\":{\\\"details\\\":\\\"owner can unpause at any time\\\"},\\\"updateOperator(uint256,address)\\\":{\\\"details\\\":\\\"can be revoke by setting address to 0\\\",\\\"params\\\":{\\\"_operator\\\":\\\"new operator address\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"withdraw(uint256,uint256)\\\":{\\\"params\\\":{\\\"_amount\\\":\\\"amount of eth to withdraw\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"withdrawUniPositionToken(uint256)\\\":{\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"}}},\\\"stateVariables\\\":{\\\"ONE\\\":{\\\"details\\\":\\\"basic unit used for calculation\\\"},\\\"PAUSE_TIME_LIMIT\\\":{\\\"details\\\":\\\"system can only be paused for 182 days from deployment\\\"},\\\"feeRate\\\":{\\\"details\\\":\\\"fee rate in basis point. feeRate of 1 = 0.01%\\\"},\\\"indexForSettlement\\\":{\\\"details\\\":\\\"the settlement price for each wPowerPerp for settlement\\\"},\\\"vaults\\\":{\\\"details\\\":\\\"vault data storage\\\"},\\\"wPowerPerpPool\\\":{\\\"details\\\":\\\"address of the powerPerp/weth pool\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"events\\\":{\\\"OpenVault(address,uint256)\\\":{\\\"notice\\\":\\\"Events\\\"}},\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"applyFunding()\\\":{\\\"notice\\\":\\\"update the normalization factor as a way to pay funding\\\"},\\\"burnPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"burn powerPerp and remove collateral from a vault\\\"},\\\"burnWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"burn wPowerPerp and remove collateral from a vault\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"constructor\\\"},\\\"depositUniPositionToken(uint256,uint256)\\\":{\\\"notice\\\":\\\"deposit uniswap position token into a vault to increase collateral ratio\\\"},\\\"donate()\\\":{\\\"notice\\\":\\\"add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\\"},\\\"getDenormalizedMark(uint32)\\\":{\\\"notice\\\":\\\"get the expected mark price of powerPerp after funding has been applied\\\"},\\\"getDenormalizedMarkForFunding(uint32)\\\":{\\\"notice\\\":\\\"get the mark price of powerPerp before funding has been applied\\\"},\\\"getExpectedNormalizationFactor()\\\":{\\\"notice\\\":\\\"returns the expected normalization factor, if the funding is paid right now\\\"},\\\"getIndex(uint32)\\\":{\\\"notice\\\":\\\"get the index price of the powerPerp, scaled down\\\"},\\\"getUnscaledIndex(uint32)\\\":{\\\"notice\\\":\\\"the unscaled index of the power perp in USD, scaled by 18 decimals\\\"},\\\"liquidate(uint256,uint256)\\\":{\\\"notice\\\":\\\"if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\\"},\\\"mintPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\\"},\\\"mintWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"deposit collateral and mint wPowerPerp\\\"},\\\"pause()\\\":{\\\"notice\\\":\\\"pause the system for up to 24 hours after which any one can unpause\\\"},\\\"redeemLong(uint256)\\\":{\\\"notice\\\":\\\"redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\\"},\\\"redeemShort(uint256)\\\":{\\\"notice\\\":\\\"redeem short position when the system is shutdown\\\"},\\\"reduceDebt(uint256)\\\":{\\\"notice\\\":\\\"withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\\"},\\\"reduceDebtShutdown(uint256)\\\":{\\\"notice\\\":\\\"after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by forceif a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\\"},\\\"setFeeRate(uint256)\\\":{\\\"notice\\\":\\\"set the fee rate when user mints\\\"},\\\"setFeeRecipient(address)\\\":{\\\"notice\\\":\\\"set the recipient who will receive the fee\\\"},\\\"shutDown()\\\":{\\\"notice\\\":\\\"shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactorshort positions can be redeemed for vault collateral minus value of debtpause (if not paused) and then immediately shutdown the system, can be called when paused already\\\"},\\\"unPauseAnyone()\\\":{\\\"notice\\\":\\\"unpause the contract\\\"},\\\"unPauseOwner()\\\":{\\\"notice\\\":\\\"unpause the contract\\\"},\\\"updateOperator(uint256,address)\\\":{\\\"notice\\\":\\\"authorize an address to modify the vault\\\"},\\\"withdraw(uint256,uint256)\\\":{\\\"notice\\\":\\\"withdraw collateral from a vault\\\"},\\\"withdrawUniPositionToken(uint256)\\\":{\\\"notice\\\":\\\"withdraw uniswap v3 position token from a vault\\\"}},\\\"notice\\\":\\\"Error C0: Paused C1: Not paused C2: Shutdown C3: Not shutdown C4: Invalid oracle address C5: Invalid shortPowerPerp address C6: Invalid wPowerPerp address C7: Invalid weth address C8: Invalid quote currency address C9: Invalid eth:quoteCurrency pool address C10: Invalid wPowerPerp:eth pool address C11: Invalid Uniswap position manager C12: Can not liquidate safe vault C13: Invalid address C14: Set fee recipient first C15: Fee too high C16: Paused too many times C17: Pause time limit exceeded C18: Not enough paused time has passed C19: Cannot receive eth C20: Not allowed C21: Need full liquidation C22: Dust vault left C23: Invalid nft C24: Invalid state C25: 0 liquidity Uniswap position token C26: Wrong fee tier for NFT deposit\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/Controller.sol\\\":\\\"Controller\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/core/Controller.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IERC721Receiver} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\\\\\";\\\\n\\\\n//contract\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\nimport {ReentrancyGuard} from \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ABDKMath64x64} from \\\\\\\"../libs/ABDKMath64x64.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"../libs/Uint256Casting.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\n\\\\n/**\\\\n *\\\\n * Error\\\\n * C0: Paused\\\\n * C1: Not paused\\\\n * C2: Shutdown\\\\n * C3: Not shutdown\\\\n * C4: Invalid oracle address\\\\n * C5: Invalid shortPowerPerp address\\\\n * C6: Invalid wPowerPerp address\\\\n * C7: Invalid weth address\\\\n * C8: Invalid quote currency address\\\\n * C9: Invalid eth:quoteCurrency pool address\\\\n * C10: Invalid wPowerPerp:eth pool address\\\\n * C11: Invalid Uniswap position manager\\\\n * C12: Can not liquidate safe vault\\\\n * C13: Invalid address\\\\n * C14: Set fee recipient first\\\\n * C15: Fee too high\\\\n * C16: Paused too many times\\\\n * C17: Pause time limit exceeded\\\\n * C18: Not enough paused time has passed\\\\n * C19: Cannot receive eth\\\\n * C20: Not allowed\\\\n * C21: Need full liquidation\\\\n * C22: Dust vault left\\\\n * C23: Invalid nft\\\\n * C24: Invalid state\\\\n * C25: 0 liquidity Uniswap position token\\\\n * C26: Wrong fee tier for NFT deposit\\\\n */\\\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n    using ABDKMath64x64 for int128;\\\\n    using VaultLib for VaultLib.Vault;\\\\n    using Address for address payable;\\\\n\\\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\\\n    /// @dev system can only be paused for 182 days from deployment\\\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\\\n\\\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\\\n    uint24 public immutable feeTier;\\\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\\\n\\\\n    //80% of index\\\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\\\n    //140% of index\\\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\\\n    // 10%\\\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\\\n    // 2%\\\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\\\n\\\\n    /// @dev basic unit used for calculation\\\\n    uint256 private constant ONE = 1e18;\\\\n\\\\n    address public immutable weth;\\\\n    address public immutable quoteCurrency;\\\\n    address public immutable ethQuoteCurrencyPool;\\\\n    /// @dev address of the powerPerp/weth pool\\\\n    address public immutable wPowerPerpPool;\\\\n    address internal immutable uniswapPositionManager;\\\\n    address public immutable shortPowerPerp;\\\\n    address public immutable wPowerPerp;\\\\n    address public immutable oracle;\\\\n    address public feeRecipient;\\\\n\\\\n    uint256 internal immutable deployTimestamp;\\\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\\\n    uint256 public feeRate;\\\\n    /// @dev the settlement price for each wPowerPerp for settlement\\\\n    uint256 public indexForSettlement;\\\\n\\\\n    uint256 public pausesLeft = 4;\\\\n    uint256 public lastPauseTime;\\\\n\\\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\\\n    uint128 public normalizationFactor;\\\\n    uint128 public lastFundingUpdateTimestamp;\\\\n\\\\n    bool internal immutable isWethToken0;\\\\n    bool public isShutDown;\\\\n    bool public isSystemPaused;\\\\n\\\\n    /// @dev vault data storage\\\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\\\n\\\\n    /// Events\\\\n    event OpenVault(address sender, uint256 vaultId);\\\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\\\n    event ReduceDebt(\\\\n        address sender,\\\\n        uint256 vaultId,\\\\n        uint256 ethRedeemed,\\\\n        uint256 wPowerPerpRedeemed,\\\\n        uint256 wPowerPerpBurned,\\\\n        uint256 wPowerPerpExcess,\\\\n        uint256 bounty\\\\n    );\\\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\\\n    event NormalizationFactorUpdated(\\\\n        uint256 oldNormFactor,\\\\n        uint256 newNormFactor,\\\\n        uint256 lastModificationTimestamp,\\\\n        uint256 timestamp\\\\n    );\\\\n    event Paused(uint256 pausesLeft);\\\\n    event UnPaused(address unpauser);\\\\n    event Shutdown(uint256 indexForSettlement);\\\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\\\n\\\\n    modifier notPaused() {\\\\n        require(!isSystemPaused, \\\\\\\"C0\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier isPaused() {\\\\n        require(isSystemPaused, \\\\\\\"C1\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier notShutdown() {\\\\n        require(!isShutDown, \\\\\\\"C2\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier isShutdown() {\\\\n        require(isShutDown, \\\\\\\"C3\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice constructor\\\\n     * @param _oracle oracle address\\\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\\\n     * @param _wPowerPerp ERC20 token address representing the long position\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\\\n     * @param _uniPositionManager uniswap v3 position manager address\\\\n     */\\\\n    constructor(\\\\n        address _oracle,\\\\n        address _shortPowerPerp,\\\\n        address _wPowerPerp,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _wPowerPerpPool,\\\\n        address _uniPositionManager,\\\\n        uint24 _feeTier\\\\n    ) {\\\\n        require(_oracle != address(0), \\\\\\\"C4\\\\\\\");\\\\n        require(_shortPowerPerp != address(0), \\\\\\\"C5\\\\\\\");\\\\n        require(_wPowerPerp != address(0), \\\\\\\"C6\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"C7\\\\\\\");\\\\n        require(_quoteCurrency != address(0), \\\\\\\"C8\\\\\\\");\\\\n        require(_ethQuoteCurrencyPool != address(0), \\\\\\\"C9\\\\\\\");\\\\n        require(_wPowerPerpPool != address(0), \\\\\\\"C10\\\\\\\");\\\\n        require(_uniPositionManager != address(0), \\\\\\\"C11\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        shortPowerPerp = _shortPowerPerp;\\\\n        wPowerPerp = _wPowerPerp;\\\\n        weth = _weth;\\\\n        quoteCurrency = _quoteCurrency;\\\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\\\n        wPowerPerpPool = _wPowerPerpPool;\\\\n        uniswapPositionManager = _uniPositionManager;\\\\n        feeTier = _feeTier;\\\\n        isWethToken0 = _weth < _wPowerPerp;\\\\n\\\\n        normalizationFactor = 1e18;\\\\n        deployTimestamp = block.timestamp;\\\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * ======================\\\\n     * | External Functions |\\\\n     * ======================\\\\n     */\\\\n\\\\n    /**\\\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\\\n     * @dev can be used for on-chain and off-chain calculations\\\\n     */\\\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\\\n        return _getNewNormalizationFactor();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index price of the powerPerp, scaled down\\\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\\\n     * @dev this is the index price used when calculating funding and for collateralization\\\\n     * @param _period period which you want to calculate twap with\\\\n     * @return index price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getIndex(uint32 _period) external view returns (uint256) {\\\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\\\n     * @param _period period which you want to calculate twap with\\\\n     * @return index price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\\\n     * @param _period period of time for the twap in seconds\\\\n     * @return mark price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\\\n        return\\\\n            Power2Base._getDenormalizedMark(\\\\n                _period,\\\\n                oracle,\\\\n                wPowerPerpPool,\\\\n                ethQuoteCurrencyPool,\\\\n                weth,\\\\n                quoteCurrency,\\\\n                wPowerPerp,\\\\n                _getNewNormalizationFactor()\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the mark price of powerPerp before funding has been applied\\\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\\\n     * @param _period period which you want to calculate twap with\\\\n     * @return mark price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\\\n        return\\\\n            Power2Base._getDenormalizedMark(\\\\n                _period,\\\\n                oracle,\\\\n                wPowerPerpPool,\\\\n                ethQuoteCurrencyPool,\\\\n                weth,\\\\n                quoteCurrency,\\\\n                wPowerPerp,\\\\n                normalizationFactor\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev return if the vault is properly collateralized\\\\n     * @param _vaultId id of the vault\\\\n     * @return true if the vault is properly collateralized\\\\n     */\\\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\\\n     * @param _vaultId vault to mint wPowerPerp in\\\\n     * @param _powerPerpAmount amount of powerPerp to mint\\\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\\\n     * @return vaultId\\\\n     * @return amount of wPowerPerp minted\\\\n     */\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit collateral and mint wPowerPerp\\\\n     * @param _vaultId vault to mint wPowerPerp in\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\\\n     * @return vaultId\\\\n     */\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable notPaused nonReentrant returns (uint256) {\\\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev deposit collateral into a vault\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\\\n     * @param _vaultId id of the vault\\\\n     * @param _uniTokenId uniswap position token id\\\\n     */\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw collateral from a vault\\\\n     * @param _vaultId id of the vault\\\\n     * @param _amount amount of eth to withdraw\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n        payable(msg.sender).sendValue(_amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw uniswap v3 position token from a vault\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp and remove collateral from a vault\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\\\n     * @param _withdrawAmount amount of eth to withdraw\\\\n     */\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn powerPerp and remove collateral from a vault\\\\n     * @param _vaultId id of the vault\\\\n     * @param _powerPerpAmount amount of powerPerp to burn\\\\n     * @param _withdrawAmount amount of eth to withdraw\\\\n     * @return amount of wPowerPerp burned\\\\n     */\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external notPaused nonReentrant returns (uint256) {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\\\n     */\\\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\\\n     * @param _vaultId target vault\\\\n     */\\\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\\\n     * @dev normally can only liquidate 50% of a vault's debt\\\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\\\n     * @param _vaultId vault to liquidate\\\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\\\n     * @return amount of wPowerPerp repaid\\\\n     */\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\\\\\"C12\\\\\\\");\\\\n\\\\n        // try to save target vault before liquidation by reducing debt\\\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\\\n\\\\n        // if vault is safe after saving, pay bounty and return early\\\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\\\n            _writeVault(_vaultId, cachedVault);\\\\n            payable(msg.sender).sendValue(bounty);\\\\n            return 0;\\\\n        }\\\\n\\\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\\\n        cachedVault.addEthCollateral(bounty);\\\\n\\\\n        // if the vault is still not safe after saving, liquidate it\\\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\\\n            cachedVault,\\\\n            _maxDebtAmount,\\\\n            cachedNormFactor,\\\\n            msg.sender\\\\n        );\\\\n\\\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        // pay the liquidator\\\\n        payable(msg.sender).sendValue(collateralPaid);\\\\n\\\\n        return debtAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice authorize an address to modify the vault\\\\n     * @dev can be revoke by setting address to 0\\\\n     * @param _vaultId id of the vault\\\\n     * @param _operator new operator address\\\\n     */\\\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\\\n        require(\\\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\\\n            \\\\\\\"C20\\\\\\\"\\\\n        );\\\\n        vaults[_vaultId].operator = _operator;\\\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set the recipient who will receive the fee\\\\n     * @dev this should be a contract handling insurance\\\\n     * @param _newFeeRecipient new fee recipient\\\\n     */\\\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\\\n        require(_newFeeRecipient != address(0), \\\\\\\"C13\\\\\\\");\\\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\\\n        feeRecipient = _newFeeRecipient;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set the fee rate when user mints\\\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\\\n     */\\\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\\\n        require(feeRecipient != address(0), \\\\\\\"C14\\\\\\\");\\\\n        require(_newFeeRate <= 100, \\\\\\\"C15\\\\\\\");\\\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\\\n        feeRate = _newFeeRate;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\\\n     */\\\\n    function shutDown() external onlyOwner notShutdown {\\\\n        isSystemPaused = true;\\\\n        isShutDown = true;\\\\n        indexForSettlement = Power2Base._getScaledTwap(\\\\n            oracle,\\\\n            ethQuoteCurrencyPool,\\\\n            weth,\\\\n            quoteCurrency,\\\\n            TWAP_PERIOD,\\\\n            false\\\\n        );\\\\n        emit Shutdown(indexForSettlement);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\\\n     */\\\\n    function pause() external onlyOwner notShutdown notPaused {\\\\n        require(pausesLeft > 0, \\\\\\\"C16\\\\\\\");\\\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\\\\\"C17\\\\\\\");\\\\n        isSystemPaused = true;\\\\n        pausesLeft -= 1;\\\\n        lastPauseTime = block.timestamp;\\\\n\\\\n        emit Paused(pausesLeft);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice unpause the contract\\\\n     * @dev anyone can unpause the contract after 24 hours\\\\n     */\\\\n    function unPauseAnyone() external isPaused notShutdown {\\\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\\\\\"C18\\\\\\\");\\\\n        isSystemPaused = false;\\\\n        emit UnPaused(msg.sender);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice unpause the contract\\\\n     * @dev owner can unpause at any time\\\\n     */\\\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\\\n        isSystemPaused = false;\\\\n        emit UnPaused(msg.sender);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\\\n     */\\\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\\\n\\\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\\\n        payable(msg.sender).sendValue(longValue);\\\\n\\\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice redeem short position when the system is shutdown\\\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\\\n     * @param _vaultId vault id\\\\n     */\\\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        uint256 cachedNormFactor = normalizationFactor;\\\\n\\\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\\\n\\\\n        uint256 debt = Power2Base._getLongSettlementValue(\\\\n            cachedVault.shortAmount,\\\\n            indexForSettlement,\\\\n            cachedNormFactor\\\\n        );\\\\n        // if the debt is more than collateral, this line will revert\\\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\\\n\\\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\\\n        cachedVault.shortAmount = 0;\\\\n        cachedVault.collateralAmount = 0;\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        payable(msg.sender).sendValue(excess);\\\\n\\\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice update the normalization factor as a way to pay funding\\\\n     */\\\\n    function applyFunding() external notPaused {\\\\n        _applyFunding();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\\\n     */\\\\n    function donate() external payable isShutdown {}\\\\n\\\\n    /**\\\\n     * @notice fallback function to accept eth\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth, \\\\\\\"C19\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\\\n     * @return returns received selector\\\\n     */\\\\n    function onERC721Received(\\\\n        address,\\\\n        address,\\\\n        uint256,\\\\n        bytes memory\\\\n    ) public virtual override returns (bytes4) {\\\\n        return this.onERC721Received.selector;\\\\n    }\\\\n\\\\n    /*\\\\n     * ======================\\\\n     * | Internal Functions |\\\\n     * ======================\\\\n     */\\\\n\\\\n    /**\\\\n     * @notice check if an address can modify a vault\\\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\\\n     * @param _account the address to check if can modify the vault\\\\n     */\\\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\\\n        require(\\\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\\\n            \\\\\\\"C20\\\\\\\"\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\\\n     * @param _account account to receive wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _mintAmount amount to mint\\\\n     * @param _depositAmount amount of eth as collateral\\\\n     * @param _uniTokenId id of uniswap v3 position token\\\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\\\n     * @return the minted wPowerPerp amount\\\\n     */\\\\n    function _openDepositMint(\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _mintAmount,\\\\n        uint256 _depositAmount,\\\\n        uint256 _uniTokenId,\\\\n        bool _isWAmount\\\\n    ) internal returns (uint256, uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        uint256 depositAmountWithFee = _depositAmount;\\\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\\\n        uint256 feeAmount;\\\\n        VaultLib.Vault memory cachedVault;\\\\n\\\\n        // load vault or create new a new one\\\\n        if (_vaultId == 0) {\\\\n            (_vaultId, cachedVault) = _openVault(_account);\\\\n        } else {\\\\n            // make sure we're not accessing an unexistent vault.\\\\n            _checkCanModifyVault(_vaultId, msg.sender);\\\\n            cachedVault = vaults[_vaultId];\\\\n        }\\\\n\\\\n        if (wPowerPerpAmount > 0) {\\\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\\\n        }\\\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\\\n\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        // pay insurance fee\\\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\\\n\\\\n        return (_vaultId, wPowerPerpAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\\\n     * @param _account who should receive collateral\\\\n     * @param _vaultId id of the vault\\\\n     * @param _burnAmount amount of wPowerPerp to burn\\\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\\\n     * @return total burned wPowerPower amount\\\\n     */\\\\n    function _burnAndWithdraw(\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _burnAmount,\\\\n        uint256 _withdrawAmount,\\\\n        bool _isWAmount\\\\n    ) internal returns (uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\\\n\\\\n        return wBurnAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice open a new vault\\\\n     * @dev create a new vault and bind it with a new short vault id\\\\n     * @param _recipient owner of new vault\\\\n     * @return id of the new vault\\\\n     * @return new in-memory vault\\\\n     */\\\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\\\n\\\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\\\n            NftCollateralId: 0,\\\\n            collateralAmount: 0,\\\\n            shortAmount: 0,\\\\n            operator: address(0)\\\\n        });\\\\n        emit OpenVault(msg.sender, vaultId);\\\\n        return (vaultId, vault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit uniswap v3 position token into a vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account account to transfer the uniswap v3 position from\\\\n     * @param _vaultId id of the vault\\\\n     * @param _uniTokenId uniswap position token id\\\\n     */\\\\n    function _depositUniPositionToken(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _uniTokenId\\\\n    ) internal {\\\\n        //get tokens for uniswap NFT\\\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\\\n            uniswapPositionManager\\\\n        ).positions(_uniTokenId);\\\\n\\\\n        // require that liquidity is above 0\\\\n        require(liquidity > 0, \\\\\\\"C25\\\\\\\");\\\\n        // accept NFTs from only the wPowerPerp pool\\\\n        require(fee == feeTier, \\\\\\\"C26\\\\\\\");\\\\n        // check token0 and token1\\\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\\\\\"C23\\\\\\\");\\\\n\\\\n        _vault.addUniNftCollateral(_uniTokenId);\\\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral into a vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _vaultId id of the vault\\\\n     * @param _amount amount of eth adding to the vault\\\\n     */\\\\n    function _addEthCollateral(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _vaultId,\\\\n        uint256 _amount\\\\n    ) internal {\\\\n        _vault.addEthCollateral(_amount);\\\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap v3 position token from the vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account where to send the uni position token to\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function _withdrawUniPositionToken(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId\\\\n    ) internal {\\\\n        uint256 tokenId = _vault.NftCollateralId;\\\\n        _vault.removeUniNftCollateral();\\\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from the vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _vaultId id of the vault\\\\n     * @param _amount amount of eth to withdraw\\\\n     */\\\\n    function _withdrawCollateral(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _vaultId,\\\\n        uint256 _amount\\\\n    ) internal {\\\\n        _vault.removeEthCollateral(_amount);\\\\n\\\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp (ERC20) to an account\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account account to receive wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\\\n     */\\\\n    function _mintWPowerPerp(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount\\\\n    ) internal {\\\\n        _vault.addShort(_wPowerPerpAmount);\\\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\\\n\\\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp (ERC20) from an account\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account account burning the wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\\\n     */\\\\n    function _burnWPowerPerp(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount\\\\n    ) internal {\\\\n        _vault.removeShort(_wPowerPerpAmount);\\\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\\\n\\\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice liquidate a vault, pay the liquidator\\\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @param _liquidator liquidator address to receive eth\\\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\\\n     * @return collateralToPay amount of collateral paid to liquidator\\\\n     */\\\\n    function _liquidate(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _maxWPowerPerpAmount,\\\\n        uint256 _normalizationFactor,\\\\n        address _liquidator\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\\\n            _maxWPowerPerpAmount,\\\\n            uint256(_vault.shortAmount),\\\\n            uint256(_vault.collateralAmount)\\\\n        );\\\\n\\\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\\\\\"C21\\\\\\\");\\\\n\\\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\\\n        _vault.removeShort(liquidateAmount);\\\\n        _vault.removeEthCollateral(collateralToPay);\\\\n\\\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        require(!isDust, \\\\\\\"C22\\\\\\\");\\\\n\\\\n        return (liquidateAmount, collateralToPay);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\\\n     * @dev will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _owner account to send any excess\\\\n     * @param _vaultId id of the vault to reduce debt on\\\\n     * @param _payBounty true if paying caller 2% bounty\\\\n     * @return bounty amount of bounty paid for liquidator\\\\n     */\\\\n    function _reduceDebt(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _owner,\\\\n        uint256 _vaultId,\\\\n        bool _payBounty\\\\n    ) internal returns (uint256) {\\\\n        uint256 nftId = _vault.NftCollateralId;\\\\n        if (nftId == 0) return 0;\\\\n\\\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\\\n\\\\n        // change weth back to eth\\\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\\\n\\\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\\\n            _vault,\\\\n            withdrawnEthAmount,\\\\n            withdrawnWPowerPerpAmount,\\\\n            _payBounty\\\\n        );\\\\n\\\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\\\n\\\\n        emit ReduceDebt(\\\\n            msg.sender,\\\\n            _vaultId,\\\\n            withdrawnEthAmount,\\\\n            withdrawnWPowerPerpAmount,\\\\n            burnAmount,\\\\n            excess,\\\\n            bounty\\\\n        );\\\\n\\\\n        return bounty;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice pay fee recipient\\\\n     * @dev pay in eth from either the vault or the deposit amount\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\\\n     */\\\\n    function _getFee(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _depositAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 cachedFeeRate = feeRate;\\\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\\\n        uint256 depositAmountAfterFee;\\\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\\\n            _wPowerPerpAmount,\\\\n            oracle,\\\\n            wPowerPerpPool,\\\\n            wPowerPerp,\\\\n            weth\\\\n        );\\\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\\\n\\\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\\\n        if (_depositAmount > feeAmount) {\\\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\\\n            // if not, adjust the vault to pay from the vault collateral\\\\n        } else {\\\\n            _vault.removeEthCollateral(feeAmount);\\\\n            depositAmountAfterFee = _depositAmount;\\\\n        }\\\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\\\n        return (feeAmount, depositAmountAfterFee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice write vault to storage\\\\n     * @dev writes to vaults mapping\\\\n     */\\\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\\\n        vaults[_vaultId] = _vault;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\\\n     * @param _uniTokenId uniswap v3 position token id\\\\n     * @return wethAmount amount of weth withdrawn from uniswap\\\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\\\n     */\\\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\\\n\\\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\\\n\\\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\\\n            .DecreaseLiquidityParams({\\\\n                tokenId: _uniTokenId,\\\\n                liquidity: liquidity,\\\\n                amount0Min: 0,\\\\n                amount1Min: 0,\\\\n                deadline: block.timestamp\\\\n            });\\\\n\\\\n        positionManager.decreaseLiquidity(decreaseParams);\\\\n\\\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\\\n            tokenId: _uniTokenId,\\\\n            recipient: address(this),\\\\n            amount0Max: uint128(-1),\\\\n            amount1Max: uint128(-1)\\\\n        });\\\\n\\\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\\\n\\\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice update the normalization factor as a way to pay in-kind funding\\\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\\\n     * @return new normalization factor\\\\n     **/\\\\n    function _applyFunding() internal returns (uint256) {\\\\n        // only update the norm factor once per block\\\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\\\n\\\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\\\n\\\\n        emit NormalizationFactorUpdated(\\\\n            normalizationFactor,\\\\n            newNormalizationFactor,\\\\n            lastFundingUpdateTimestamp,\\\\n            block.timestamp\\\\n        );\\\\n\\\\n        // the following will be batch into 1 SSTORE because of type uint128\\\\n        normalizationFactor = newNormalizationFactor.toUint128();\\\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\\\n\\\\n        return newNormalizationFactor;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate new normalization factor base on the current timestamp\\\\n     * @return new normalization factor if funding happens in the current block\\\\n     */\\\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\\\n\\\\n        if (period == 0) {\\\\n            return normalizationFactor;\\\\n        }\\\\n\\\\n        // make sure we use the same period for mark and index\\\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\\\n\\\\n        // avoid reading normalizationFactor from storage multiple times\\\\n        uint256 cacheNormFactor = normalizationFactor;\\\\n\\\\n        uint256 mark = Power2Base._getDenormalizedMark(\\\\n            periodForOracle,\\\\n            oracle,\\\\n            wPowerPerpPool,\\\\n            ethQuoteCurrencyPool,\\\\n            weth,\\\\n            quoteCurrency,\\\\n            wPowerPerp,\\\\n            cacheNormFactor\\\\n        );\\\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\\\n\\\\n        //the fraction of the funding period. used to compound the funding rate\\\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\\\n\\\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\\\n        if (mark < lowerBound) {\\\\n            mark = lowerBound;\\\\n        } else {\\\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\\\n            if (mark > upperBound) mark = upperBound;\\\\n        }\\\\n\\\\n        // normFactor(new) = multiplier * normFactor(old)\\\\n        // multiplier = (index/mark)^rFunding\\\\n        // x^r = n^(log_n(x) * r)\\\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\\\n\\\\n        int128 base = ABDKMath64x64.divu(index, mark);\\\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\\\n        int128 multiplier = logTerm.exp_2();\\\\n        return multiplier.mulu(cacheNormFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if vault has enough collateral and is not a dust vault\\\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _normalizationFactor normalization factor\\\\n     */\\\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        require(isSafe, \\\\\\\"C24\\\\\\\");\\\\n        require(!isDust, \\\\\\\"C22\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check that the vault has enough collateral\\\\n     * @param _vault in-memory vault\\\\n     * @param _normalizationFactor normalization factor\\\\n     * @return true if the vault is properly collateralized\\\\n     */\\\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        return isSafe;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _normalizationFactor normalization factor\\\\n     * @return true if the vault is safe\\\\n     * @return true if the vault is a dust vault\\\\n     */\\\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\\\n        internal\\\\n        view\\\\n        returns (bool, bool)\\\\n    {\\\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\\\n            oracle,\\\\n            ethQuoteCurrencyPool,\\\\n            weth,\\\\n            quoteCurrency,\\\\n            TWAP_PERIOD,\\\\n            true // do not call more than maximum period so it does not revert\\\\n        );\\\\n        return\\\\n            VaultLib.getVaultStatus(\\\\n                _vault,\\\\n                uniswapPositionManager,\\\\n                _normalizationFactor,\\\\n                scaledEthPrice,\\\\n                MIN_COLLATERAL,\\\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\\\n                isWethToken0\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @return burnAmount amount of wPowerPerp that should be burned\\\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\\\n     * @return bounty amount of bounty should be paid out to caller\\\\n     */\\\\n    function _getReduceDebtResultInVault(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 nftEthAmount,\\\\n        uint256 nftWPowerperpAmount,\\\\n        bool _payBounty\\\\n    )\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            uint256,\\\\n            uint256,\\\\n            uint256\\\\n        )\\\\n    {\\\\n        uint256 bounty;\\\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\\\n\\\\n        uint256 burnAmount = nftWPowerperpAmount;\\\\n        uint256 wPowerPerpExcess;\\\\n\\\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\\\n            burnAmount = _vault.shortAmount;\\\\n        }\\\\n\\\\n        _vault.removeShort(burnAmount);\\\\n        _vault.removeUniNftCollateral();\\\\n        _vault.addEthCollateral(nftEthAmount);\\\\n        _vault.removeEthCollateral(bounty);\\\\n\\\\n        return (burnAmount, wPowerPerpExcess, bounty);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\\\n     * @dev bounty is 2% of the total value of the position token\\\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\\\n     */\\\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\\\n        return\\\\n            Power2Base\\\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\\\n                .add(_ethWithdrawn)\\\\n                .mul(REDUCE_DEBT_BOUNTY)\\\\n                .div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\\\\\"dust vault\\\\\\\"\\\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\\\n     * @param _vaultShortAmount the amount of short in the vault\\\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\\\n     */\\\\n    function _getLiquidationResult(\\\\n        uint256 _maxWPowerPerpAmount,\\\\n        uint256 _vaultShortAmount,\\\\n        uint256 _vaultCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        // try limiting liquidation amount to half of the vault debt\\\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\\\n            _maxWPowerPerpAmount,\\\\n            _vaultShortAmount.div(2)\\\\n        );\\\\n\\\\n        if (_vaultCollateralAmount > collateralToPay) {\\\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\\\n                // calculate the new liquidation amount and collateral again based on the new limit\\\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\\\n                    _maxWPowerPerpAmount,\\\\n                    _vaultShortAmount\\\\n                );\\\\n            }\\\\n        }\\\\n\\\\n        // check if final collateral to pay is greater than vault amount.\\\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\\\n        if (collateralToPay > _vaultCollateralAmount) {\\\\n            // force liquidator to pay full debt amount\\\\n            finalLiquidateAmount = _vaultShortAmount;\\\\n            collateralToPay = _vaultCollateralAmount;\\\\n        }\\\\n\\\\n        return (finalLiquidateAmount, collateralToPay);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\\\n     * @return collateralToPay total collateral the liquidator will get\\\\n     */\\\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\\\n        internal\\\\n        view\\\\n        returns (uint256, uint256)\\\\n    {\\\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\\\n            ? _maxLiquidatableWAmount\\\\n            : _maxInputWAmount;\\\\n\\\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\\\n            finalWAmountToLiquidate,\\\\n            oracle,\\\\n            wPowerPerpPool,\\\\n            wPowerPerp,\\\\n            weth\\\\n        );\\\\n\\\\n        // add 10% bonus for liquidators\\\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\\\n\\\\n        return (finalWAmountToLiquidate, collateralToPay);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\\\n     * @param _period max period that we intend to use\\\\n     * @return fair period not greator than _period to be used for both pools.\\\\n     */\\\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\\\n\\\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x105305cd28be74884264601c885af5bfe8cbc489ad3894c6d243425adc101aed\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/ABDKMath64x64.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: BSD-4-Clause\\\\n/*\\\\n * ABDK Math 64.64 Smart Contract Library.  Copyright \\\\u00a9 2019 by ABDK Consulting.\\\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\\\n * Copyright (c) 2019, ABDK Consulting\\\\n *\\\\n * All rights reserved.\\\\n *\\\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\\\n *\\\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\\\n */\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * Smart contract library of mathematical functions operating with signed\\\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\\\n * represented by int128 type holding only the numerator.\\\\n *\\\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\\\n * Changes (cont) - revert strings added\\\\n * solidity version set to ^0.7.0\\\\n */\\\\nlibrary ABDKMath64x64 {\\\\n    /*\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * -2^127\\\\n     */\\\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\\\n\\\\n    /*\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * 2^127-1\\\\n     */\\\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @param y signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\\\n        int256 result = (int256(x) * y) >> 64;\\\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\\\\\"MUL-OVUF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64 fixed point number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 256-bit integer number\\\\n     */\\\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\\\n        if (y == 0) return 0;\\\\n\\\\n        require(x >= 0, \\\\\\\"MULU-X0\\\\\\\");\\\\n\\\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\\\n        uint256 hi = uint256(x) * (y >> 128);\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"MULU-OF1\\\\\\\");\\\\n        hi <<= 64;\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\\\\\"MULU-OF2\\\\\\\");\\\\n        return hi + lo;\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\\\n        require(y != 0, \\\\\\\"DIVU-INF\\\\\\\");\\\\n        uint128 result = divuu(x, y);\\\\n        require(result <= uint128(MAX_64x64), \\\\\\\"DIVU-OF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function log_2(int128 x) public pure returns (int128) {\\\\n        require(x > 0, \\\\\\\"LOG_2-X0\\\\\\\");\\\\n\\\\n        int256 msb = 0;\\\\n        int256 xc = x;\\\\n        if (xc >= 0x10000000000000000) {\\\\n            xc >>= 64;\\\\n            msb += 64;\\\\n        }\\\\n        if (xc >= 0x100000000) {\\\\n            xc >>= 32;\\\\n            msb += 32;\\\\n        }\\\\n        if (xc >= 0x10000) {\\\\n            xc >>= 16;\\\\n            msb += 16;\\\\n        }\\\\n        if (xc >= 0x100) {\\\\n            xc >>= 8;\\\\n            msb += 8;\\\\n        }\\\\n        if (xc >= 0x10) {\\\\n            xc >>= 4;\\\\n            msb += 4;\\\\n        }\\\\n        if (xc >= 0x4) {\\\\n            xc >>= 2;\\\\n            msb += 2;\\\\n        }\\\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n        int256 result = (msb - 64) << 64;\\\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\\\n            ux *= ux;\\\\n            uint256 b = ux >> 255;\\\\n            ux >>= 127 + b;\\\\n            result += bit * int256(b);\\\\n        }\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary exponent of x.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function exp_2(int128 x) public pure returns (int128) {\\\\n        require(x < 0x400000000000000000, \\\\\\\"EXP_2-OF\\\\\\\"); // Overflow\\\\n\\\\n        if (x < -0x400000000000000000) return 0; // Underflow\\\\n\\\\n        uint256 result = 0x80000000000000000000000000000000;\\\\n\\\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\\\n\\\\n        result >>= uint256(63 - (x >> 64));\\\\n        require(result <= uint256(MAX_64x64));\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 64.64-bit fixed point number\\\\n     */\\\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\\\n        require(y != 0);\\\\n\\\\n        uint256 result;\\\\n\\\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\\\n        else {\\\\n            uint256 msb = 192;\\\\n            uint256 xc = x >> 192;\\\\n            if (xc >= 0x100000000) {\\\\n                xc >>= 32;\\\\n                msb += 32;\\\\n            }\\\\n            if (xc >= 0x10000) {\\\\n                xc >>= 16;\\\\n                msb += 16;\\\\n            }\\\\n            if (xc >= 0x100) {\\\\n                xc >>= 8;\\\\n                msb += 8;\\\\n            }\\\\n            if (xc >= 0x10) {\\\\n                xc >>= 4;\\\\n                msb += 4;\\\\n            }\\\\n            if (xc >= 0x4) {\\\\n                xc >>= 2;\\\\n                msb += 2;\\\\n            }\\\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF1\\\\\\\");\\\\n\\\\n            uint256 hi = result * (y >> 128);\\\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\\\n\\\\n            uint256 xh = x >> 192;\\\\n            uint256 xl = x << 64;\\\\n\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n            lo = hi << 128;\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n\\\\n            assert(xh == hi >> 128);\\\\n\\\\n            result += xl / y;\\\\n        }\\\\n\\\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF2\\\\\\\");\\\\n        return uint128(result);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x56efa7c16e4fffb37ad80af15bd042d9f92532a4553d6b12915e3fa21609ad66\\\",\\\"license\\\":\\\"BSD-4-Clause\\\"},\\\"contracts/libs/Power2Base.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary Power2Base {\\\\n    using SafeMath for uint256;\\\\n\\\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\\\n    uint256 private constant INDEX_SCALE = 1e4;\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    /**\\\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getUnscaledIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\\\n     */\\\\n    function _getDenormalizedMark(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _wSqueeth,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\\\n\\\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _weth weth address\\\\n     * @return returns value of debt in ETH\\\\n     */\\\\n    function _getDebtValueInEth(\\\\n        uint256 _debtAmount,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _wSqueeth,\\\\n        address _weth\\\\n    ) internal view returns (uint256) {\\\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle\\\\n     * @dev this will revert if period is > max period for the pool\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        // period reaching this point should be check, otherwise might revert\\\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\\\n     * @param _indexPriceForSettlement index price for settlement\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return amount in wei that should be paid to the token holder\\\\n     */\\\\n    function _getLongSettlementValue(\\\\n        uint256 _wsqueethAmount,\\\\n        uint256 _indexPriceForSettlement,\\\\n        uint256 _normalizationFactor\\\\n    ) internal pure returns (uint256) {\\\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1938180c41ec0ee817b841df605b199e15ffbbe94700b640d031b4e4665a89af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101e060405260046005553480156200001757600080fd5b5060405162006630380380620066308339810160408190526200003a916200032c565b600062000046620002c4565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600180556001600160a01b038916620000c65760405162461bcd60e51b8152600401620000bd9062000462565b60405180910390fd5b6001600160a01b038816620000ef5760405162461bcd60e51b8152600401620000bd90620004b6565b6001600160a01b038716620001185760405162461bcd60e51b8152600401620000bd90620003f0565b6001600160a01b038616620001415760405162461bcd60e51b8152600401620000bd9062000446565b6001600160a01b0385166200016a5760405162461bcd60e51b8152600401620000bd906200049a565b6001600160a01b038416620001935760405162461bcd60e51b8152600401620000bd906200047e565b6001600160a01b038316620001bc5760405162461bcd60e51b8152600401620000bd906200040c565b6001600160a01b038216620001e55760405162461bcd60e51b8152600401620000bd9062000429565b6001600160601b031960608a811b82166101805289811b82166101405288811b82166101605287811b821660a05286811b821660c05285811b821660e05284811b82166101005283901b16610120526001600160e81b031960e882901b166080526001600160a01b038781169087161060f81b6101c052600780546001600160801b031916670de0b6b3a7640000179055426101a081905262000297906200274f620002c8602090811b91909117901c565b600780546001600160801b03928316600160801b02921691909117905550620004d2975050505050505050565b3390565b806001600160801b03811681146200030f576040805162461bcd60e51b815260206004820152600560248201526409e8c6264760db1b604482015290519081900360640190fd5b919050565b80516001600160a01b03811681146200030f57600080fd5b60008060008060008060008060006101208a8c0312156200034b578485fd5b620003568a62000314565b98506200036660208b0162000314565b97506200037660408b0162000314565b96506200038660608b0162000314565b95506200039660808b0162000314565b9450620003a660a08b0162000314565b9350620003b660c08b0162000314565b9250620003c660e08b0162000314565b91506101008a015162ffffff81168114620003df578182fd5b809150509295985092959850929598565b602080825260029082015261219b60f11b604082015260600190565b60208082526003908201526204331360ec1b604082015260600190565b60208082526003908201526243313160e81b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526002908201526110cd60f21b604082015260600190565b602080825260029082015261433960f01b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b602080825260029082015261433560f01b604082015260600190565b60805160e81c60a05160601c60c05160601c60e05160601c6101005160601c6101205160601c6101405160601c6101605160601c6101805160601c6101a0516101c05160f81c615f2f620007016000398061465452806148f55250806115bc525080610af15280610bc95280610d3a52806113f9528061173c528061243c5280612ac65280612b9a5280613e765280614050528061411052806144d452806145945280614cd35280614d7e525080610ddf528061141d5280611b9952806124e15280612b6b52806135da52806136525280613897528061393f5280613b125280613eb85280613f6b52806144125280614d155280614dc0525080611a795280611d9f5280611de05280611ff352806121a6528061270f5280612f395280613d6452508061339352806134bb52806136ff52806145685280614769525080610d5b5280611d7b528061245d5280612ae75280613e97528061413f52806145c35280614cf45280614d9f525080610b125280610bea5280610d7c528061109e528061175d528061247e5280612b085280612bbb528061407f52806144f5525080610b545280610c2c5280610dbe52806114b1528061179f52806124c05280612b4a5280612bfd52806145375250806103535280610b335280610c0b5280610d9d5280610ebc528061177e528061249f5280612b295280612bdc5280613616528061368e52806137fa5280613ed952806145165280614d365280614de15250806113c152806135915250615f2f6000f3fe6080604052600436106103435760003560e01c80638456cb59116101b0578063b707ab99116100ec578063e74b981b11610095578063f2fde38b1161006f578063f2fde38b146108d0578063f90c3f27146108f0578063fbfc6bc014610905578063ff947525146109255761039b565b8063e74b981b14610888578063ed88c68e146108a8578063ee3189ff146108b05761039b565b8063d296d1f1116100c6578063d296d1f11461083e578063d52725841461085e578063de4a427a146108735761039b565b8063b707ab99146107e9578063c65a391d146107fe578063c9e77ee81461081e5761039b565b806391b8d34a116101595780639d4c9442116101335780639d4c944214610781578063a847e67414610796578063ac6cd5ef146107b6578063b6b55f25146107d65761039b565b806391b8d34a1461072c578063978bbdb91461074c57806397efa942146107615761039b565b80638cd21d7c1161018a5780638cd21d7c146106e25780638da5cb5b1461070257806391b4ded9146107175761039b565b80638456cb591461067d5780638632cb03146106925780638c64ea4a146106b25761039b565b806345596e2e1161027f57806372f5d98a116102285780637dc0d1d0116102025780637dc0d1d0146106295780637f07b1301461063e5780638146b09f1461065357806382564bca146106685761039b565b806372f5d98a146105c35780637691c4ac146105e55780637ca25184146106075761039b565b806363b38ae41161025957806363b38ae414610579578063713d517f1461058e578063715018a6146105ae5761039b565b806345596e2e1461052257806346904840146105425780634be2822c146105575761039b565b806324f5f531116102ec5780633fc8cef3116102c65780633fc8cef3146104ab5780634394318d146104cd578063441a3e70146104ed5780634468c0221461050d5761039b565b806324f5f53114610463578063377a19361461047857806339467918146104985761039b565b806315aded831161031d57806315aded83146104005780631bf7bf6c1461042d578063200f4b8d1461044e5761039b565b806307633669146103a057806310b9e583146103b5578063150b7a02146103ca5761039b565b3661039b57336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103995760405162461bcd60e51b815260040161039090615cc9565b60405180910390fd5b005b600080fd5b3480156103ac57600080fd5b5061039961093a565b3480156103c157600080fd5b50610399610a3d565b3480156103d657600080fd5b506103ea6103e5366004615662565b610bb0565b6040516103f79190615ad9565b60405180910390f35b34801561040c57600080fd5b5061042061041b36600461584f565b610bc1565b6040516103f79190615df3565b61044061043b366004615824565b610c58565b6040516103f7929190615dfc565b34801561045a57600080fd5b50610399610cef565b34801561046f57600080fd5b50610420610d22565b34801561048457600080fd5b5061042061049336600461584f565b610d32565b6104206104a6366004615824565b610e22565b3480156104b757600080fd5b506104c0610eba565b6040516103f79190615961565b3480156104d957600080fd5b506104206104e8366004615824565b610ede565b3480156104f957600080fd5b506103996105083660046157e0565b610f78565b34801561051957600080fd5b506104c061109c565b34801561052e57600080fd5b5061039961053d366004615781565b6110c0565b34801561054e57600080fd5b506104c06111bd565b34801561056357600080fd5b5061056c6111cc565b6040516103f79190615da5565b34801561058557600080fd5b506104206111e2565b34801561059a57600080fd5b506103996105a9366004615781565b6111e8565b3480156105ba57600080fd5b50610399611301565b3480156105cf57600080fd5b506105d86113bf565b6040516103f79190615de3565b3480156105f157600080fd5b506105fa6113e3565b6040516103f79190615ace565b34801561061357600080fd5b5061061c6113f1565b6040516103f79190615e0a565b34801561063557600080fd5b506104c06113f7565b34801561064a57600080fd5b506104c061141b565b34801561065f57600080fd5b5061039961143f565b34801561067457600080fd5b506104c06114af565b34801561068957600080fd5b506103996114d3565b34801561069e57600080fd5b506103996106ad366004615824565b61165c565b3480156106be57600080fd5b506106d26106cd366004615781565b6116e7565b6040516103f79493929190615a90565b3480156106ee57600080fd5b506104206106fd36600461584f565b611734565b34801561070e57600080fd5b506104c06117c3565b34801561072357600080fd5b506104206117d2565b34801561073857600080fd5b506103996107473660046157e0565b6117d8565b34801561075857600080fd5b506104206118d1565b34801561076d57600080fd5b5061039961077c366004615781565b6118d7565b34801561078d57600080fd5b506104c0611a77565b3480156107a257600080fd5b506105fa6107b1366004615781565b611a9b565b3480156107c257600080fd5b506103996107d1366004615781565b611b15565b6103996107e4366004615781565b611c6f565b3480156107f557600080fd5b506104c0611d79565b34801561080a57600080fd5b506103996108193660046157b1565b611d9d565b34801561082a57600080fd5b50610399610839366004615781565b611efb565b34801561084a57600080fd5b506104206108593660046157e0565b61208d565b34801561086a57600080fd5b5061056c6122f8565b34801561087f57600080fd5b50610420612307565b34801561089457600080fd5b506103996108a336600461562a565b61230d565b610399612410565b3480156108bc57600080fd5b506104206108cb36600461584f565b612434565b3480156108dc57600080fd5b506103996108eb36600461562a565b61250d565b3480156108fc57600080fd5b50610420612621565b34801561091157600080fd5b50610399610920366004615781565b612628565b34801561093157600080fd5b506105fa612746565b6109426127ad565b6001600160a01b03166109536117c3565b6001600160a01b0316146109ae576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600854610100900460ff166109d55760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156109f85760405162461bcd60e51b815260040161039090615b53565b6008805461ff00191690556040517fff2b959f2bcdb44c7ecb4b16dae055431019d7350607125cfc2b74a06632c90e90610a33903390615961565b60405180910390a1565b610a456127ad565b6001600160a01b0316610a566117c3565b6001600160a01b031614610ab1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff1615610ad45760405162461bcd60e51b815260040161039090615b53565b6008805460ff1961ff001990911661010017166001179055610b7d7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460006127b1565b60048190556040517f574214b195bf5273a95bb4498e35cf1fde0ce327c727a95ec2ab359f7ba4e11a91610a3391615df3565b630a85bd0160e11b5b949350505050565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006127de565b90505b919050565b6008546000908190610100900460ff1615610c855760405162461bcd60e51b815260040161039090615c39565b60026001541415610ccb576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610cdf33868634876000612819565b6001805590969095509350505050565b600854610100900460ff1615610d175760405162461bcd60e51b815260040161039090615c39565b610d1f61296a565b50565b6000610d2c612a58565b90505b90565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000600760009054906101000a90046001600160801b03166001600160801b0316612ee9565b600854600090610100900460ff1615610e4d5760405162461bcd60e51b815260040161039090615c39565b60026001541415610e93576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001819055506000610eac33868634876001612819565b506001805595945050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854600090610100900460ff1615610f095760405162461bcd60e51b815260040161039090615c39565b60026001541415610f4f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610f5e8433612f2d565b610f6c338585856000613021565b60018055949350505050565b600854610100900460ff1615610fa05760405162461bcd60e51b815260040161039090615c39565b60026001541415610fe6576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610ff58233612f2d565b6000610fff61296a565b600084815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915061107481858561310f565b61107e8183613159565b61108884826131ab565b611092338461327e565b5050600180555050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6110c86127ad565b6001600160a01b03166110d96117c3565b6001600160a01b031614611134576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6002546001600160a01b031661115c5760405162461bcd60e51b815260040161039090615afc565b606481111561117d5760405162461bcd60e51b815260040161039090615c55565b7f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957600354826040516111b0929190615dfc565b60405180910390a1600355565b6002546001600160a01b031681565b600754600160801b90046001600160801b031681565b60055481565b600854610100900460ff16156112105760405162461bcd60e51b815260040161039090615c39565b60026001541415611256576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556112658133612f2d565b600061126f61296a565b600083815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506112e4813385613368565b6112ee8183613159565b6112f883826131ab565b50506001805550565b6113096127ad565b6001600160a01b031661131a6117c3565b6001600160a01b031614611375576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff1681565b6101a481565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff166114665760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156114895760405162461bcd60e51b815260040161039090615b53565b600654620151800142116109f85760405162461bcd60e51b815260040161039090615be3565b7f000000000000000000000000000000000000000000000000000000000000000081565b6114db6127ad565b6001600160a01b03166114ec6117c3565b6001600160a01b031614611547576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff161561156a5760405162461bcd60e51b815260040161039090615b53565b600854610100900460ff16156115925760405162461bcd60e51b815260040161039090615c39565b6000600554116115b45760405162461bcd60e51b815260040161039090615b6f565b60006115e0427f000000000000000000000000000000000000000000000000000000000000000061343f565b905062eff10081106116045760405162461bcd60e51b815260040161039090615ce6565b6008805461ff001916610100179055600580546000190190819055426006556040517f32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e9161165191615df3565b60405180910390a150565b600854610100900460ff16156116845760405162461bcd60e51b815260040161039090615c39565b600260015414156116ca576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556116d98333612f2d565b611092338484846001613021565b600960205260009081526040902080546001909101546001600160a01b03821691600160a01b900463ffffffff16906001600160601b03811690600160601b90046001600160801b031684565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b6000546001600160a01b031690565b60065481565b600854610100900460ff16156118005760405162461bcd60e51b815260040161039090615c39565b60026001541415611846576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556118558233612f2d565b61185d61296a565b50600082815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201526112ee813385856134b3565b60035481565b60085460ff166118f95760405162461bcd60e51b815260040161039090615d03565b6002600154141561193f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b600260015561194e8133612f2d565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b03908116606083015260075491929116906119cc908390339086906137af565b5060006119e983606001516001600160801b0316600454846139fa565b90506000611a0d8285604001516001600160601b031661343f90919063ffffffff16565b60006060860181905260408601529050611a2785856131ab565b611a31338261327e565b7f7dff8cdaec6a8d4d1ad32d3c947ed0f0281c3d6456621ef928defae96ec6cddb338683604051611a64939291906159d5565b60405180910390a1505060018055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b0316606082015281611b09612a58565b9050610bb98282613a23565b60085460ff16611b375760405162461bcd60e51b815260040161039090615d03565b60026001541415611b7d576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90611bd09033908590600401615999565b600060405180830381600087803b158015611bea57600080fd5b505af1158015611bfe573d6000803e3d6000fd5b505060045460075460009350611c2092508491906001600160801b03166139fa565b9050611c2c338261327e565b7f2131ef4f2f82ca75fe7d2e646ebfa45b6be25e53510c829629c76b641500ec67338383604051611c5f939291906159d5565b60405180910390a1505060018055565b600854610100900460ff1615611c975760405162461bcd60e51b815260040161039090615c39565b60026001541415611cdd576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611cec8133612f2d565b611cf461296a565b50600081815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b03166060820152611d67818334613a39565b611d7182826131ab565b505060018055565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331480611e7857506040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611e1d908690600401615df3565b60206040518083038186803b158015611e3557600080fd5b505afa158015611e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6d9190615646565b6001600160a01b0316145b611e945760405162461bcd60e51b815260040161039090615b19565b6000828152600960205260409081902080546001600160a01b0319166001600160a01b038416179055517f3137fc9cd2e33c34f86e29c24d81f3c75b0bce639d3c4ed0d31eeff1160a7ff590611eef903390859085906159b2565b60405180910390a15050565b600854610100900460ff1615611f235760405162461bcd60e51b815260040161039090615c39565b60026001541415611f69576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611f788133612f2d565b600081815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093526001909101546001600160601b03811682850152600160601b90046001600160801b0316606082015291516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60206040518083038186803b15801561204257600080fd5b505afa158015612056573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207a9190615646565b8460006137af565b50611d7182826131ab565b600854600090610100900460ff16156120b85760405162461bcd60e51b815260040161039090615c39565b600260015414156120fe576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155600061210d61296a565b600085815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506121818183613a23565b1561219e5760405162461bcd60e51b815260040161039090615c72565b6000612248827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e896040518263ffffffff1660e01b81526004016121f09190615df3565b60206040518083038186803b15801561220857600080fd5b505afa15801561221c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122409190615646565b8860016137af565b90506122548284613a23565b156122795761226386836131ab565b61226d338261327e565b600093505050506122ee565b6122838282613a76565b60008061229284888733613aac565b915091507f158ba9ab7bbbd08eeffa4753bad41f4d450e24831d293427308badf3eadd8c76338984846040516122cb94939291906159f6565b60405180910390a16122dd88856131ab565b6122e7338261327e565b5093505050505b6001805592915050565b6007546001600160801b031681565b60045481565b6123156127ad565b6001600160a01b03166123266117c3565b6001600160a01b031614612381576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166123a75760405162461bcd60e51b815260040161039090615b8c565b6002546040517faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d3916123e6916001600160a01b03909116908490615a57565b60405180910390a1600280546001600160a01b0319166001600160a01b0392909216919091179055565b60085460ff166124325760405162461bcd60e51b815260040161039090615d03565b565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612508612a58565b612ee9565b6125156127ad565b6001600160a01b03166125266117c3565b6001600160a01b031614612581576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166125c65760405162461bcd60e51b8152600401808060200182810382526026815260200180615e796026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6217124081565b60085460ff1661264a5760405162461bcd60e51b815260040161039090615d03565b60026001541415612690576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001908155600082815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093529301546001600160601b03811684840152600160601b90046001600160801b0316606084015290516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60085460ff1681565b806001600160801b0381168114610c53576040805162461bcd60e51b815260206004820152600560248201527f4f46313238000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b3390565b6000806127c2888888888888613bd3565b90506127d081612710613c79565b9150505b9695505050505050565b6000806127f0868686868b6000613bd3565b905061280e670de0b6b3a76400006128088380613ce0565b90613c79565b979650505050505050565b600080600061282661296a565b90508560008561284b57612846836128088b670de0b6b3a7640000613ce0565b61284d565b885b905060006128596155bc565b8b612871576128678d613d40565b909c5090506128e4565b61287b8c33612f2d565b5060008b815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201525b8215612905576128f581848c613e53565b94509150612905818e8e86613f4a565b891561291657612916818d86613a39565b881561292857612928818e8e8c6134b3565b6129328186613159565b61293c8c826131ab565b811561295857600254612958906001600160a01b03168361327e565b50999b909a5098505050505050505050565b6007546000906001600160801b03600160801b9091041642141561299a57506007546001600160801b0316610d2f565b60006129a4612a58565b6007546040519192507f339e53729b0447795ff69e70a74fed98fc7fef6fe94b7521099b32f0f8de4822916129f3916001600160801b03808216928692600160801b9004909116904290615db9565b60405180910390a1612a048161274f565b600780546fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055612a364261274f565b600780546001600160801b03928316600160801b029216919091179055905090565b6007546000908190612a8490612a7f904290600160801b90046001600160801b031661343f565b614007565b905063ffffffff8116612aa45750506007546001600160801b0316610d2f565b6000612aaf8261404b565b6007549091506001600160801b03166000612b90837f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000089612ee9565b90506000612c21847f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b90506000734CA8F19f951052162Bda12D1db72dEDa489dBD8363fc505d3787621712406040518363ffffffff1660e01b8152600401612c61929190615e1b565b60206040518083038186803b158015612c7957600080fd5b505af4158015612c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb19190615746565b90506000612cd3670de0b6b3a764000061280885670b1a2bc2ec500000613ce0565b905080841015612ce557809350612d15565b6000612d05670de0b6b3a76400006128088667136dcc951d8c0000613ce0565b905080851115612d13578094505b505b60405163fc505d3760e01b8152600090734CA8F19f951052162Bda12D1db72dEDa489dBD839063fc505d3790612d519087908990600401615dfc565b60206040518083038186803b158015612d6957600080fd5b505af4158015612d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da19190615746565b90506000612e3984734CA8F19f951052162Bda12D1db72dEDa489dBD83632cbbdee5856040518263ffffffff1660e01b8152600401612de09190615aee565b60206040518083038186803b158015612df857600080fd5b505af4158015612e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e309190615746565b600f0b9061420f565b604051637e0c9e7960e11b8152909150600090734CA8F19f951052162Bda12D1db72dEDa489dBD839063fc193cf290612e7a90600f86900b90600401615aee565b60206040518083038186803b158015612e9257600080fd5b505af4158015612ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eca9190615746565b9050612eda600f82900b896142a0565b9a505050505050505050505090565b600080612efb898888888e60006127b1565b90506000612f0e8a8a878a8f6000613bd3565b9050612f1e846128088385613ce0565b9b9a5050505050505050505050565b806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e846040518263ffffffff1660e01b8152600401612f839190615df3565b60206040518083038186803b158015612f9b57600080fd5b505afa158015612faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd39190615646565b6001600160a01b0316148061300157506000828152600960205260409020546001600160a01b038281169116145b61301d5760405162461bcd60e51b815260040161039090615b19565b5050565b60008061302c61296a565b90506000836130505761304b8261280888670de0b6b3a7640000613ce0565b613052565b855b600088815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915081156130ce576130ce818a8a856143f1565b85156130df576130df81898861310f565b6130e98184613159565b6130f388826131ab565b851561310357613103338761327e565b50979650505050505050565b61311983826144ae565b7f627a692d5a03ab34732c0d2aa319f3ecdebdc4528f383eabcb25441dc0a70cfb33838360405161314c939291906159d5565b60405180910390a1505050565b60008061316684846144ca565b91509150816131875760405162461bcd60e51b815260040161039090615c8f565b80156131a55760405162461bcd60e51b815260040161039090615cac565b50505050565b600091825260096020908152604092839020825181549284015163ffffffff16600160a01b027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff6001600160a01b039092166001600160a01b0319909416939093171691909117815591810151600190920180546060909201516001600160801b0316600160601b027fffffffff00000000000000000000000000000000ffffffffffffffffffffffff6001600160601b039094166bffffffffffffffffffffffff199093169290921792909216179055565b804710156132d3576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d806000811461331e576040519150601f19603f3d011682016040523d82523d6000602084013e613323565b606091505b50509050806133635760405162461bcd60e51b815260040180806020018281038252603a815260200180615e9f603a913960400191505060405180910390fd5b505050565b602083015163ffffffff1661337c84614684565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906133cc90309087908690600401615975565b600060405180830381600087803b1580156133e657600080fd5b505af11580156133fa573d6000803e3d6000fd5b505050507fe59f38fa1264fc25c9f0185eee136eaf810d90b8e7293b342e4037c68720177a338383604051613431939291906159d5565b60405180910390a150505050565b600082821115613496576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000806127f0868686868b60006127b1565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166399fbab88866040518263ffffffff1660e01b81526004016135059190615df3565b6101806040518083038186803b15801561351e57600080fd5b505afa158015613532573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135569190615887565b505050509750505095509550955050506000816001600160801b03161161358f5760405162461bcd60e51b815260040161039090615bc6565b7f000000000000000000000000000000000000000000000000000000000000000062ffffff168262ffffff16146135d85760405162461bcd60e51b815260040161039090615b36565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614801561364a57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b806136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161480156136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b6136de5760405162461bcd60e51b815260040161039090615ba9565b6136e888866146cf565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613738908a9030908a90600401615975565b600060405180830381600087803b15801561375257600080fd5b505af1158015613766573d6000803e3d6000fd5b505050507f3917c2f26ce18614e3aedd1289da672ef6563c5c295f49e9b1697ae0ad31556233878760405161379d939291906159d5565b60405180910390a15050505050505050565b602084015160009063ffffffff16806137cc576000915050610bb9565b6000806137d883614764565b9092509050811561386257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061382f908590600401615df3565b600060405180830381600087803b15801561384957600080fd5b505af115801561385d573d6000803e3d6000fd5b505050505b60008060006138738b86868b614931565b9194509250905081156139225760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906138ce908d908690600401615999565b602060405180830381600087803b1580156138e857600080fd5b505af11580156138fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139209190615726565b505b82156139a957604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906139769030908790600401615999565b600060405180830381600087803b15801561399057600080fd5b505af11580156139a4573d6000803e3d6000fd5b505050505b7ffd0ae2fd36bd955810ae42615bc5ff277c0d0dfcb930f06c9f1777c0ef0752e3338a87878787876040516139e49796959493929190615a1c565b60405180910390a19a9950505050505050505050565b6000610bb96ec097ce7bc90715b34b9f100000000061280885613a1d8887613ce0565b90613ce0565b600080613a3084846144ca565b50949350505050565b613a438382613a76565b7f3ca13b7aab12bad7472691fe558faa6b25e99099824a0070a88bd5aa84be610f33838360405161314c939291906159d5565b6040820151613a9790613a92906001600160601b0316836149c7565b614a21565b6001600160601b031660409092019190915250565b600080600080613ad78789606001516001600160801b03168a604001516001600160601b0316614a68565b9150915081871015613afb5760405162461bcd60e51b815260040161039090615c00565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90613b499088908690600401615999565b600060405180830381600087803b158015613b6357600080fd5b505af1158015613b77573d6000803e3d6000fd5b50505050613b8e8289614ad090919063ffffffff16565b613b9888826144ae565b6000613ba489886144ca565b9150508015613bc55760405162461bcd60e51b815260040161039090615cac565b509097909650945050505050565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b158015613c4257600080fd5b505afa158015613c56573d6000803e3d6000fd5b505050506040513d6020811015613c6c57600080fd5b5051979650505050505050565b6000808211613ccf576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613cd857fe5b049392505050565b600082613cef5750600061349b565b82820282848281613cfc57fe5b0414613d395760405162461bcd60e51b8152600401808060200182810382526021815260200180615ed96021913960400191505060405180910390fd5b9392505050565b6000613d4a6155bc565b6040516354ba0f2760e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906354ba0f2790613d99908790600401615961565b602060405180830381600087803b158015613db357600080fd5b505af1158015613dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613deb9190615799565b6040805160808101825260008082526020820181905281830181905260608201529051919250907f25ff1e0131762176a9084e92880f880f39d6d0e62134607f37e631efe1bad87190613e419033908590615999565b60405180910390a19092509050915091565b600354600090819080613e6d576000849250925050613f42565b600080613efd877f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b90506000613f116127106128088487613ce0565b905080871115613f2c57613f25878261343f565b9250613f3a565b613f3689826144ae565b8692505b945090925050505b935093915050565b613f548482614b32565b6040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990613fa29086908590600401615999565b600060405180830381600087803b158015613fbc57600080fd5b505af1158015613fd0573d6000803e3d6000fd5b505050507fb19fa182730a088464dad0e9e0badeb470d0d8d937d854f5caf15c6ad1992c36338284604051613431939291906159d5565b8063ffffffff81168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a3199960e11b604482015290519081900360640190fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b81526004016140ba9190615961565b60206040518083038186803b1580156140d257600080fd5b505afa1580156140e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410a919061586b565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040161417a9190615961565b60206040518083038186803b15801561419257600080fd5b505afa1580156141a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141ca919061586b565b905060008163ffffffff168363ffffffff16116141e757826141e9565b815b90508063ffffffff168563ffffffff16116142045784614206565b805b95945050505050565b6000600f83810b9083900b0260401d6f7fffffffffffffffffffffffffffffff19811280159061424f57506f7fffffffffffffffffffffffffffffff8113155b613d39576040805162461bcd60e51b815260206004820152600860248201527f4d554c2d4f565546000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000816142af5750600061349b565b600083600f0b1215614308576040805162461bcd60e51b815260206004820152600760248201527f4d554c552d583000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600f83900b6001600160801b038316810260401c90608084901c0277ffffffffffffffffffffffffffffffffffffffffffffffff811115614390576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4631000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60401b81198111156143e9576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4632000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b019392505050565b6143fb8482614ad0565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906144499086908590600401615999565b600060405180830381600087803b15801561446357600080fd5b505af1158015614477573d6000803e3d6000fd5b505050507fea19ffc45b48de6d95594aacff7214dd24595fdb0c60e98c8f0b269058c2f792338284604051613431939291906159d5565b6040820151613a9790613a92906001600160601b03168361343f565b60008060006145607f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460016127b1565b9050614678857f000000000000000000000000000000000000000000000000000000000000000086846706f05b59d3b200007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634a0a96eb7f00000000000000000000000000000000000000000000000000000000000000006101a46040518363ffffffff1660e01b8152600401614602929190615a71565b60206040518083038186803b15801561461a57600080fd5b505afa15801561462e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146529190615767565b7f0000000000000000000000000000000000000000000000000000000000000000614b4e565b92509250509250929050565b602081015163ffffffff166146c5576040805162461bcd60e51b81526020600482015260026024820152612b1960f11b604482015290519081900360640190fd5b6000602090910152565b602082015163ffffffff1615614711576040805162461bcd60e51b8152602060048201526002602482015261563160f01b604482015290519081900360640190fd5b80614749576040805162461bcd60e51b815260206004820152600360248201526243323360e81b604482015290519081900360640190fd5b61475281614007565b63ffffffff1660209092019190915250565b6000807f0000000000000000000000000000000000000000000000000000000000000000816147938286614bf2565b50506040805160a0810182528981526001600160801b0383166020820152600081830181905260608201524260808201529051630624e65f60e11b815291945092506001600160a01b0385169150630c49ccbe906147f5908490600401615d62565b6040805180830381600087803b15801561480e57600080fd5b505af1158015614822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148469190615801565b5050604080516080810182528781523060208201526001600160801b038183018190526060820152905163fc6f786560e01b815260009081906001600160a01b0387169063fc6f78659061489e908690600401615d1f565b6040805180830381600087803b1580156148b757600080fd5b505af11580156148cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148ef9190615801565b915091507f000000000000000000000000000000000000000000000000000000000000000061491f578082614922565b81815b97509750505050505050915091565b600080600080841561494a576149478787614cb0565b90505b606088015186906000906001600160801b03168211156149905760608a015161497d9089906001600160801b031661343f565b905089606001516001600160801b031691505b61499a8a83614ad0565b6149a38a614684565b6149ad8a8a613a76565b6149b78a846144ae565b9099909850909650945050505050565b600082820183811015613d39576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b806001600160601b0381168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a31c9b60e11b604482015290519081900360640190fd5b6000808080614a8187614a7c886002613c79565b614d60565b9150915080851115614ab6576706f05b59d3b20000614aa0868361343f565b1015614ab657614ab08787614d60565b90925090505b84811115614ac45750849050835b90969095509350505050565b6060820151614af190614aec906001600160801b03168361343f565b61274f565b6001600160801b031660609092019190915250565b600080614b1a868686866101a46000613bd3565b905061280e670de0b6b3a76400006128088984613ce0565b6060820151614af190614aec906001600160801b0316836149c7565b60008088606001516001600160801b031660001415614b735750600190506000614be6565b6000614bac6ec097ce7bc90715b34b9f100000000061280889613a1d8c8f606001516001600160801b0316613ce090919063ffffffff16565b90506000614bbe8b8b8b8b8a8a614e3c565b90508681106000614bd0846003613ce0565b614bdb846002613ce0565b101595509093505050505b97509795505050505050565b6000806000806000808790506000806000806000856001600160a01b03166399fbab888d6040518263ffffffff1660e01b8152600401808281526020019150506101806040518083038186803b158015614c4b57600080fd5b505afa158015614c5f573d6000803e3d6000fd5b505050506040513d610180811015614c7657600080fd5b5060a081015160c082015160e083015161014084015161016090940151929e50909c509a5090985096505050505050509295509295909350565b6000613d39670de0b6b3a764000061280866470de4df820000613a1d87614d5a887f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b906149c7565b6000806000838511614d725784614d74565b835b90506000614e05827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b9050614e2f614e28670de0b6b3a76400006128088467016345785d8a0000613ce0565b82906149c7565b9196919550909350505050565b6000866020015163ffffffff1660001415614e65575060408601516001600160601b03166127d4565b600080614e7e888a6020015163ffffffff168787614ed3565b90925090506000614ea66ec097ce7bc90715b34b9f100000000061280889613a1d868d613ce0565b60408b0151909150614ec5906001600160601b0316614d5a85846149c7565b9a9950505050505050505050565b6000806000806000806000614ee88b8b614bf2565b94509450945094509450600080614f0187878d88614f54565b9150915089614f2757826001600160801b03168101846001600160801b03168301614f40565b836001600160801b03168201836001600160801b031682015b985098505050505050505094509492505050565b600080600073569292d3d8B44F02B11ef048A3Dd361e57880E8C63986cfba3866040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b158015614fab57600080fd5b505af4158015614fbf573d6000803e3d6000fd5b505050506040513d6020811015614fd557600080fd5b50519050600287810b9086900b12156151985773a932Db3b9f630436aeb5a9AF8687E521dc943569632c32d4b673569292d3d8B44F02B11ef048A3Dd361e57880E8C63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561505457600080fd5b505af4158015615068573d6000803e3d6000fd5b505050506040513d602081101561507e57600080fd5b50516040805163986cfba360e01b815260028b900b6004820152905173569292d3d8B44F02B11ef048A3Dd361e57880E8C9163986cfba3916024808301926020929190829003018186803b1580156150d557600080fd5b505af41580156150e9573d6000803e3d6000fd5b505050506040513d60208110156150ff57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561516557600080fd5b505af4158015615179573d6000803e3d6000fd5b505050506040513d602081101561518f57600080fd5b505192506155b2565b8560020b8560020b12156154065773a932Db3b9f630436aeb5a9AF8687E521dc943569632c32d4b68273569292d3d8B44F02B11ef048A3Dd361e57880E8C63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561521357600080fd5b505af4158015615227573d6000803e3d6000fd5b505050506040513d602081101561523d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156152a357600080fd5b505af41580156152b7573d6000803e3d6000fd5b505050506040513d60208110156152cd57600080fd5b50516040805163986cfba360e01b815260028a900b6004820152905191945073a932Db3b9f630436aeb5a9AF8687E521dc943569916348a0c5bd9173569292d3d8B44F02B11ef048A3Dd361e57880E8C9163986cfba391602480820192602092909190829003018186803b15801561534457600080fd5b505af4158015615358573d6000803e3d6000fd5b505050506040513d602081101561536e57600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b03928316600482015291851660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156153d357600080fd5b505af41580156153e7573d6000803e3d6000fd5b505050506040513d60208110156153fd57600080fd5b505191506155b2565b73a932Db3b9f630436aeb5a9AF8687E521dc9435696348a0c5bd73569292d3d8B44F02B11ef048A3Dd361e57880E8C63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561547257600080fd5b505af4158015615486573d6000803e3d6000fd5b505050506040513d602081101561549c57600080fd5b50516040805163986cfba360e01b815260028b900b6004820152905173569292d3d8B44F02B11ef048A3Dd361e57880E8C9163986cfba3916024808301926020929190829003018186803b1580156154f357600080fd5b505af4158015615507573d6000803e3d6000fd5b505050506040513d602081101561551d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561558357600080fd5b505af4158015615597573d6000803e3d6000fd5b505050506040513d60208110156155ad57600080fd5b505191505b5094509492505050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b8051610c5381615e31565b8051600281900b8114610c5357600080fd5b80516001600160801b0381168114610c5357600080fd5b805162ffffff81168114610c5357600080fd5b60006020828403121561563b578081fd5b8135613d3981615e31565b600060208284031215615657578081fd5b8151613d3981615e31565b60008060008060808587031215615677578283fd5b843561568281615e31565b935060208581013561569381615e31565b935060408601359250606086013567ffffffffffffffff808211156156b6578384fd5b818801915088601f8301126156c9578384fd5b8135818111156156d557fe5b604051601f8201601f19168101850183811182821017156156f257fe5b60405281815283820185018b1015615708578586fd5b81858501868301379081019093019390935250939692955090935050565b600060208284031215615737578081fd5b81518015158114613d39578182fd5b600060208284031215615757578081fd5b815180600f0b8114613d39578182fd5b600060208284031215615778578081fd5b613d39826155ee565b600060208284031215615792578081fd5b5035919050565b6000602082840312156157aa578081fd5b5051919050565b600080604083850312156157c3578182fd5b8235915060208301356157d581615e31565b809150509250929050565b600080604083850312156157f2578182fd5b50508035926020909101359150565b60008060408385031215615813578182fd5b505080516020909101519092909150565b600080600060608486031215615838578283fd5b505081359360208301359350604090920135919050565b600060208284031215615860578081fd5b8135613d3981615e46565b60006020828403121561587c578081fd5b8151613d3981615e46565b6000806000806000806000806000806000806101808d8f0312156158a957898afd5b8c516001600160601b03811681146158bf578a8bfd5b9b506158cd60208e016155e3565b9a506158db60408e016155e3565b99506158e960608e016155e3565b98506158f760808e01615617565b975061590560a08e016155ee565b965061591360c08e016155ee565b955061592160e08e01615600565b94506101008d015193506101208d015192506159406101408e01615600565b915061594f6101608e01615600565b90509295989b509295989b509295989b565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b03979097168752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0392909216825263ffffffff16602082015260400190565b6001600160a01b0394909416845263ffffffff9290921660208401526001600160601b031660408301526001600160801b0316606082015260800190565b901515815260200190565b6001600160e01b031991909116815260200190565b600f9190910b815260200190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b602080825260029082015261043360f41b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b602080825260029082015261433360f01b604082015260600190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b6001600160801b0391909116815260200190565b6001600160801b039485168152602081019390935292166040820152606081019190915260800190565b62ffffff91909116815260200190565b90815260200190565b918252602082015260400190565b63ffffffff91909116815260200190565b63ffffffff929092168252602082015260400190565b6001600160a01b0381168114610d1f57600080fd5b63ffffffff81168114610d1f57600080fdfe5265656e7472616e637947756172643a207265656e7472616e742063616c6c004f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122067c719aed0ae3307dbebb58cfa90077cc4cbc9d365114aa9321da3e54e97944d64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x6080604052600436106103435760003560e01c80638456cb59116101b0578063b707ab99116100ec578063e74b981b11610095578063f2fde38b1161006f578063f2fde38b146108d0578063f90c3f27146108f0578063fbfc6bc014610905578063ff947525146109255761039b565b8063e74b981b14610888578063ed88c68e146108a8578063ee3189ff146108b05761039b565b8063d296d1f1116100c6578063d296d1f11461083e578063d52725841461085e578063de4a427a146108735761039b565b8063b707ab99146107e9578063c65a391d146107fe578063c9e77ee81461081e5761039b565b806391b8d34a116101595780639d4c9442116101335780639d4c944214610781578063a847e67414610796578063ac6cd5ef146107b6578063b6b55f25146107d65761039b565b806391b8d34a1461072c578063978bbdb91461074c57806397efa942146107615761039b565b80638cd21d7c1161018a5780638cd21d7c146106e25780638da5cb5b1461070257806391b4ded9146107175761039b565b80638456cb591461067d5780638632cb03146106925780638c64ea4a146106b25761039b565b806345596e2e1161027f57806372f5d98a116102285780637dc0d1d0116102025780637dc0d1d0146106295780637f07b1301461063e5780638146b09f1461065357806382564bca146106685761039b565b806372f5d98a146105c35780637691c4ac146105e55780637ca25184146106075761039b565b806363b38ae41161025957806363b38ae414610579578063713d517f1461058e578063715018a6146105ae5761039b565b806345596e2e1461052257806346904840146105425780634be2822c146105575761039b565b806324f5f531116102ec5780633fc8cef3116102c65780633fc8cef3146104ab5780634394318d146104cd578063441a3e70146104ed5780634468c0221461050d5761039b565b806324f5f53114610463578063377a19361461047857806339467918146104985761039b565b806315aded831161031d57806315aded83146104005780631bf7bf6c1461042d578063200f4b8d1461044e5761039b565b806307633669146103a057806310b9e583146103b5578063150b7a02146103ca5761039b565b3661039b57336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103995760405162461bcd60e51b815260040161039090615cc9565b60405180910390fd5b005b600080fd5b3480156103ac57600080fd5b5061039961093a565b3480156103c157600080fd5b50610399610a3d565b3480156103d657600080fd5b506103ea6103e5366004615662565b610bb0565b6040516103f79190615ad9565b60405180910390f35b34801561040c57600080fd5b5061042061041b36600461584f565b610bc1565b6040516103f79190615df3565b61044061043b366004615824565b610c58565b6040516103f7929190615dfc565b34801561045a57600080fd5b50610399610cef565b34801561046f57600080fd5b50610420610d22565b34801561048457600080fd5b5061042061049336600461584f565b610d32565b6104206104a6366004615824565b610e22565b3480156104b757600080fd5b506104c0610eba565b6040516103f79190615961565b3480156104d957600080fd5b506104206104e8366004615824565b610ede565b3480156104f957600080fd5b506103996105083660046157e0565b610f78565b34801561051957600080fd5b506104c061109c565b34801561052e57600080fd5b5061039961053d366004615781565b6110c0565b34801561054e57600080fd5b506104c06111bd565b34801561056357600080fd5b5061056c6111cc565b6040516103f79190615da5565b34801561058557600080fd5b506104206111e2565b34801561059a57600080fd5b506103996105a9366004615781565b6111e8565b3480156105ba57600080fd5b50610399611301565b3480156105cf57600080fd5b506105d86113bf565b6040516103f79190615de3565b3480156105f157600080fd5b506105fa6113e3565b6040516103f79190615ace565b34801561061357600080fd5b5061061c6113f1565b6040516103f79190615e0a565b34801561063557600080fd5b506104c06113f7565b34801561064a57600080fd5b506104c061141b565b34801561065f57600080fd5b5061039961143f565b34801561067457600080fd5b506104c06114af565b34801561068957600080fd5b506103996114d3565b34801561069e57600080fd5b506103996106ad366004615824565b61165c565b3480156106be57600080fd5b506106d26106cd366004615781565b6116e7565b6040516103f79493929190615a90565b3480156106ee57600080fd5b506104206106fd36600461584f565b611734565b34801561070e57600080fd5b506104c06117c3565b34801561072357600080fd5b506104206117d2565b34801561073857600080fd5b506103996107473660046157e0565b6117d8565b34801561075857600080fd5b506104206118d1565b34801561076d57600080fd5b5061039961077c366004615781565b6118d7565b34801561078d57600080fd5b506104c0611a77565b3480156107a257600080fd5b506105fa6107b1366004615781565b611a9b565b3480156107c257600080fd5b506103996107d1366004615781565b611b15565b6103996107e4366004615781565b611c6f565b3480156107f557600080fd5b506104c0611d79565b34801561080a57600080fd5b506103996108193660046157b1565b611d9d565b34801561082a57600080fd5b50610399610839366004615781565b611efb565b34801561084a57600080fd5b506104206108593660046157e0565b61208d565b34801561086a57600080fd5b5061056c6122f8565b34801561087f57600080fd5b50610420612307565b34801561089457600080fd5b506103996108a336600461562a565b61230d565b610399612410565b3480156108bc57600080fd5b506104206108cb36600461584f565b612434565b3480156108dc57600080fd5b506103996108eb36600461562a565b61250d565b3480156108fc57600080fd5b50610420612621565b34801561091157600080fd5b50610399610920366004615781565b612628565b34801561093157600080fd5b506105fa612746565b6109426127ad565b6001600160a01b03166109536117c3565b6001600160a01b0316146109ae576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600854610100900460ff166109d55760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156109f85760405162461bcd60e51b815260040161039090615b53565b6008805461ff00191690556040517fff2b959f2bcdb44c7ecb4b16dae055431019d7350607125cfc2b74a06632c90e90610a33903390615961565b60405180910390a1565b610a456127ad565b6001600160a01b0316610a566117c3565b6001600160a01b031614610ab1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff1615610ad45760405162461bcd60e51b815260040161039090615b53565b6008805460ff1961ff001990911661010017166001179055610b7d7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460006127b1565b60048190556040517f574214b195bf5273a95bb4498e35cf1fde0ce327c727a95ec2ab359f7ba4e11a91610a3391615df3565b630a85bd0160e11b5b949350505050565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006127de565b90505b919050565b6008546000908190610100900460ff1615610c855760405162461bcd60e51b815260040161039090615c39565b60026001541415610ccb576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610cdf33868634876000612819565b6001805590969095509350505050565b600854610100900460ff1615610d175760405162461bcd60e51b815260040161039090615c39565b610d1f61296a565b50565b6000610d2c612a58565b90505b90565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000600760009054906101000a90046001600160801b03166001600160801b0316612ee9565b600854600090610100900460ff1615610e4d5760405162461bcd60e51b815260040161039090615c39565b60026001541415610e93576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001819055506000610eac33868634876001612819565b506001805595945050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854600090610100900460ff1615610f095760405162461bcd60e51b815260040161039090615c39565b60026001541415610f4f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610f5e8433612f2d565b610f6c338585856000613021565b60018055949350505050565b600854610100900460ff1615610fa05760405162461bcd60e51b815260040161039090615c39565b60026001541415610fe6576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610ff58233612f2d565b6000610fff61296a565b600084815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915061107481858561310f565b61107e8183613159565b61108884826131ab565b611092338461327e565b5050600180555050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6110c86127ad565b6001600160a01b03166110d96117c3565b6001600160a01b031614611134576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6002546001600160a01b031661115c5760405162461bcd60e51b815260040161039090615afc565b606481111561117d5760405162461bcd60e51b815260040161039090615c55565b7f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957600354826040516111b0929190615dfc565b60405180910390a1600355565b6002546001600160a01b031681565b600754600160801b90046001600160801b031681565b60055481565b600854610100900460ff16156112105760405162461bcd60e51b815260040161039090615c39565b60026001541415611256576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556112658133612f2d565b600061126f61296a565b600083815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506112e4813385613368565b6112ee8183613159565b6112f883826131ab565b50506001805550565b6113096127ad565b6001600160a01b031661131a6117c3565b6001600160a01b031614611375576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff1681565b6101a481565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff166114665760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156114895760405162461bcd60e51b815260040161039090615b53565b600654620151800142116109f85760405162461bcd60e51b815260040161039090615be3565b7f000000000000000000000000000000000000000000000000000000000000000081565b6114db6127ad565b6001600160a01b03166114ec6117c3565b6001600160a01b031614611547576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff161561156a5760405162461bcd60e51b815260040161039090615b53565b600854610100900460ff16156115925760405162461bcd60e51b815260040161039090615c39565b6000600554116115b45760405162461bcd60e51b815260040161039090615b6f565b60006115e0427f000000000000000000000000000000000000000000000000000000000000000061343f565b905062eff10081106116045760405162461bcd60e51b815260040161039090615ce6565b6008805461ff001916610100179055600580546000190190819055426006556040517f32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e9161165191615df3565b60405180910390a150565b600854610100900460ff16156116845760405162461bcd60e51b815260040161039090615c39565b600260015414156116ca576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556116d98333612f2d565b611092338484846001613021565b600960205260009081526040902080546001909101546001600160a01b03821691600160a01b900463ffffffff16906001600160601b03811690600160601b90046001600160801b031684565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b6000546001600160a01b031690565b60065481565b600854610100900460ff16156118005760405162461bcd60e51b815260040161039090615c39565b60026001541415611846576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556118558233612f2d565b61185d61296a565b50600082815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201526112ee813385856134b3565b60035481565b60085460ff166118f95760405162461bcd60e51b815260040161039090615d03565b6002600154141561193f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b600260015561194e8133612f2d565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b03908116606083015260075491929116906119cc908390339086906137af565b5060006119e983606001516001600160801b0316600454846139fa565b90506000611a0d8285604001516001600160601b031661343f90919063ffffffff16565b60006060860181905260408601529050611a2785856131ab565b611a31338261327e565b7f7dff8cdaec6a8d4d1ad32d3c947ed0f0281c3d6456621ef928defae96ec6cddb338683604051611a64939291906159d5565b60405180910390a1505060018055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b0316606082015281611b09612a58565b9050610bb98282613a23565b60085460ff16611b375760405162461bcd60e51b815260040161039090615d03565b60026001541415611b7d576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90611bd09033908590600401615999565b600060405180830381600087803b158015611bea57600080fd5b505af1158015611bfe573d6000803e3d6000fd5b505060045460075460009350611c2092508491906001600160801b03166139fa565b9050611c2c338261327e565b7f2131ef4f2f82ca75fe7d2e646ebfa45b6be25e53510c829629c76b641500ec67338383604051611c5f939291906159d5565b60405180910390a1505060018055565b600854610100900460ff1615611c975760405162461bcd60e51b815260040161039090615c39565b60026001541415611cdd576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611cec8133612f2d565b611cf461296a565b50600081815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b03166060820152611d67818334613a39565b611d7182826131ab565b505060018055565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331480611e7857506040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611e1d908690600401615df3565b60206040518083038186803b158015611e3557600080fd5b505afa158015611e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6d9190615646565b6001600160a01b0316145b611e945760405162461bcd60e51b815260040161039090615b19565b6000828152600960205260409081902080546001600160a01b0319166001600160a01b038416179055517f3137fc9cd2e33c34f86e29c24d81f3c75b0bce639d3c4ed0d31eeff1160a7ff590611eef903390859085906159b2565b60405180910390a15050565b600854610100900460ff1615611f235760405162461bcd60e51b815260040161039090615c39565b60026001541415611f69576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611f788133612f2d565b600081815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093526001909101546001600160601b03811682850152600160601b90046001600160801b0316606082015291516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60206040518083038186803b15801561204257600080fd5b505afa158015612056573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207a9190615646565b8460006137af565b50611d7182826131ab565b600854600090610100900460ff16156120b85760405162461bcd60e51b815260040161039090615c39565b600260015414156120fe576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155600061210d61296a565b600085815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506121818183613a23565b1561219e5760405162461bcd60e51b815260040161039090615c72565b6000612248827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e896040518263ffffffff1660e01b81526004016121f09190615df3565b60206040518083038186803b15801561220857600080fd5b505afa15801561221c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122409190615646565b8860016137af565b90506122548284613a23565b156122795761226386836131ab565b61226d338261327e565b600093505050506122ee565b6122838282613a76565b60008061229284888733613aac565b915091507f158ba9ab7bbbd08eeffa4753bad41f4d450e24831d293427308badf3eadd8c76338984846040516122cb94939291906159f6565b60405180910390a16122dd88856131ab565b6122e7338261327e565b5093505050505b6001805592915050565b6007546001600160801b031681565b60045481565b6123156127ad565b6001600160a01b03166123266117c3565b6001600160a01b031614612381576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166123a75760405162461bcd60e51b815260040161039090615b8c565b6002546040517faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d3916123e6916001600160a01b03909116908490615a57565b60405180910390a1600280546001600160a01b0319166001600160a01b0392909216919091179055565b60085460ff166124325760405162461bcd60e51b815260040161039090615d03565b565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612508612a58565b612ee9565b6125156127ad565b6001600160a01b03166125266117c3565b6001600160a01b031614612581576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166125c65760405162461bcd60e51b8152600401808060200182810382526026815260200180615e796026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6217124081565b60085460ff1661264a5760405162461bcd60e51b815260040161039090615d03565b60026001541415612690576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001908155600082815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093529301546001600160601b03811684840152600160601b90046001600160801b0316606084015290516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60085460ff1681565b806001600160801b0381168114610c53576040805162461bcd60e51b815260206004820152600560248201527f4f46313238000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b3390565b6000806127c2888888888888613bd3565b90506127d081612710613c79565b9150505b9695505050505050565b6000806127f0868686868b6000613bd3565b905061280e670de0b6b3a76400006128088380613ce0565b90613c79565b979650505050505050565b600080600061282661296a565b90508560008561284b57612846836128088b670de0b6b3a7640000613ce0565b61284d565b885b905060006128596155bc565b8b612871576128678d613d40565b909c5090506128e4565b61287b8c33612f2d565b5060008b815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201525b8215612905576128f581848c613e53565b94509150612905818e8e86613f4a565b891561291657612916818d86613a39565b881561292857612928818e8e8c6134b3565b6129328186613159565b61293c8c826131ab565b811561295857600254612958906001600160a01b03168361327e565b50999b909a5098505050505050505050565b6007546000906001600160801b03600160801b9091041642141561299a57506007546001600160801b0316610d2f565b60006129a4612a58565b6007546040519192507f339e53729b0447795ff69e70a74fed98fc7fef6fe94b7521099b32f0f8de4822916129f3916001600160801b03808216928692600160801b9004909116904290615db9565b60405180910390a1612a048161274f565b600780546fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055612a364261274f565b600780546001600160801b03928316600160801b029216919091179055905090565b6007546000908190612a8490612a7f904290600160801b90046001600160801b031661343f565b614007565b905063ffffffff8116612aa45750506007546001600160801b0316610d2f565b6000612aaf8261404b565b6007549091506001600160801b03166000612b90837f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000089612ee9565b90506000612c21847f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b9050600073__$f98cbc68e241c61b30349ba6b91a975736$__63fc505d3787621712406040518363ffffffff1660e01b8152600401612c61929190615e1b565b60206040518083038186803b158015612c7957600080fd5b505af4158015612c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb19190615746565b90506000612cd3670de0b6b3a764000061280885670b1a2bc2ec500000613ce0565b905080841015612ce557809350612d15565b6000612d05670de0b6b3a76400006128088667136dcc951d8c0000613ce0565b905080851115612d13578094505b505b60405163fc505d3760e01b815260009073__$f98cbc68e241c61b30349ba6b91a975736$__9063fc505d3790612d519087908990600401615dfc565b60206040518083038186803b158015612d6957600080fd5b505af4158015612d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da19190615746565b90506000612e398473__$f98cbc68e241c61b30349ba6b91a975736$__632cbbdee5856040518263ffffffff1660e01b8152600401612de09190615aee565b60206040518083038186803b158015612df857600080fd5b505af4158015612e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e309190615746565b600f0b9061420f565b604051637e0c9e7960e11b815290915060009073__$f98cbc68e241c61b30349ba6b91a975736$__9063fc193cf290612e7a90600f86900b90600401615aee565b60206040518083038186803b158015612e9257600080fd5b505af4158015612ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eca9190615746565b9050612eda600f82900b896142a0565b9a505050505050505050505090565b600080612efb898888888e60006127b1565b90506000612f0e8a8a878a8f6000613bd3565b9050612f1e846128088385613ce0565b9b9a5050505050505050505050565b806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e846040518263ffffffff1660e01b8152600401612f839190615df3565b60206040518083038186803b158015612f9b57600080fd5b505afa158015612faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd39190615646565b6001600160a01b0316148061300157506000828152600960205260409020546001600160a01b038281169116145b61301d5760405162461bcd60e51b815260040161039090615b19565b5050565b60008061302c61296a565b90506000836130505761304b8261280888670de0b6b3a7640000613ce0565b613052565b855b600088815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915081156130ce576130ce818a8a856143f1565b85156130df576130df81898861310f565b6130e98184613159565b6130f388826131ab565b851561310357613103338761327e565b50979650505050505050565b61311983826144ae565b7f627a692d5a03ab34732c0d2aa319f3ecdebdc4528f383eabcb25441dc0a70cfb33838360405161314c939291906159d5565b60405180910390a1505050565b60008061316684846144ca565b91509150816131875760405162461bcd60e51b815260040161039090615c8f565b80156131a55760405162461bcd60e51b815260040161039090615cac565b50505050565b600091825260096020908152604092839020825181549284015163ffffffff16600160a01b027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff6001600160a01b039092166001600160a01b0319909416939093171691909117815591810151600190920180546060909201516001600160801b0316600160601b027fffffffff00000000000000000000000000000000ffffffffffffffffffffffff6001600160601b039094166bffffffffffffffffffffffff199093169290921792909216179055565b804710156132d3576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d806000811461331e576040519150601f19603f3d011682016040523d82523d6000602084013e613323565b606091505b50509050806133635760405162461bcd60e51b815260040180806020018281038252603a815260200180615e9f603a913960400191505060405180910390fd5b505050565b602083015163ffffffff1661337c84614684565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906133cc90309087908690600401615975565b600060405180830381600087803b1580156133e657600080fd5b505af11580156133fa573d6000803e3d6000fd5b505050507fe59f38fa1264fc25c9f0185eee136eaf810d90b8e7293b342e4037c68720177a338383604051613431939291906159d5565b60405180910390a150505050565b600082821115613496576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000806127f0868686868b60006127b1565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166399fbab88866040518263ffffffff1660e01b81526004016135059190615df3565b6101806040518083038186803b15801561351e57600080fd5b505afa158015613532573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135569190615887565b505050509750505095509550955050506000816001600160801b03161161358f5760405162461bcd60e51b815260040161039090615bc6565b7f000000000000000000000000000000000000000000000000000000000000000062ffffff168262ffffff16146135d85760405162461bcd60e51b815260040161039090615b36565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614801561364a57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b806136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161480156136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b6136de5760405162461bcd60e51b815260040161039090615ba9565b6136e888866146cf565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613738908a9030908a90600401615975565b600060405180830381600087803b15801561375257600080fd5b505af1158015613766573d6000803e3d6000fd5b505050507f3917c2f26ce18614e3aedd1289da672ef6563c5c295f49e9b1697ae0ad31556233878760405161379d939291906159d5565b60405180910390a15050505050505050565b602084015160009063ffffffff16806137cc576000915050610bb9565b6000806137d883614764565b9092509050811561386257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061382f908590600401615df3565b600060405180830381600087803b15801561384957600080fd5b505af115801561385d573d6000803e3d6000fd5b505050505b60008060006138738b86868b614931565b9194509250905081156139225760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906138ce908d908690600401615999565b602060405180830381600087803b1580156138e857600080fd5b505af11580156138fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139209190615726565b505b82156139a957604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906139769030908790600401615999565b600060405180830381600087803b15801561399057600080fd5b505af11580156139a4573d6000803e3d6000fd5b505050505b7ffd0ae2fd36bd955810ae42615bc5ff277c0d0dfcb930f06c9f1777c0ef0752e3338a87878787876040516139e49796959493929190615a1c565b60405180910390a19a9950505050505050505050565b6000610bb96ec097ce7bc90715b34b9f100000000061280885613a1d8887613ce0565b90613ce0565b600080613a3084846144ca565b50949350505050565b613a438382613a76565b7f3ca13b7aab12bad7472691fe558faa6b25e99099824a0070a88bd5aa84be610f33838360405161314c939291906159d5565b6040820151613a9790613a92906001600160601b0316836149c7565b614a21565b6001600160601b031660409092019190915250565b600080600080613ad78789606001516001600160801b03168a604001516001600160601b0316614a68565b9150915081871015613afb5760405162461bcd60e51b815260040161039090615c00565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90613b499088908690600401615999565b600060405180830381600087803b158015613b6357600080fd5b505af1158015613b77573d6000803e3d6000fd5b50505050613b8e8289614ad090919063ffffffff16565b613b9888826144ae565b6000613ba489886144ca565b9150508015613bc55760405162461bcd60e51b815260040161039090615cac565b509097909650945050505050565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b158015613c4257600080fd5b505afa158015613c56573d6000803e3d6000fd5b505050506040513d6020811015613c6c57600080fd5b5051979650505050505050565b6000808211613ccf576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613cd857fe5b049392505050565b600082613cef5750600061349b565b82820282848281613cfc57fe5b0414613d395760405162461bcd60e51b8152600401808060200182810382526021815260200180615ed96021913960400191505060405180910390fd5b9392505050565b6000613d4a6155bc565b6040516354ba0f2760e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906354ba0f2790613d99908790600401615961565b602060405180830381600087803b158015613db357600080fd5b505af1158015613dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613deb9190615799565b6040805160808101825260008082526020820181905281830181905260608201529051919250907f25ff1e0131762176a9084e92880f880f39d6d0e62134607f37e631efe1bad87190613e419033908590615999565b60405180910390a19092509050915091565b600354600090819080613e6d576000849250925050613f42565b600080613efd877f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b90506000613f116127106128088487613ce0565b905080871115613f2c57613f25878261343f565b9250613f3a565b613f3689826144ae565b8692505b945090925050505b935093915050565b613f548482614b32565b6040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990613fa29086908590600401615999565b600060405180830381600087803b158015613fbc57600080fd5b505af1158015613fd0573d6000803e3d6000fd5b505050507fb19fa182730a088464dad0e9e0badeb470d0d8d937d854f5caf15c6ad1992c36338284604051613431939291906159d5565b8063ffffffff81168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a3199960e11b604482015290519081900360640190fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b81526004016140ba9190615961565b60206040518083038186803b1580156140d257600080fd5b505afa1580156140e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410a919061586b565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040161417a9190615961565b60206040518083038186803b15801561419257600080fd5b505afa1580156141a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141ca919061586b565b905060008163ffffffff168363ffffffff16116141e757826141e9565b815b90508063ffffffff168563ffffffff16116142045784614206565b805b95945050505050565b6000600f83810b9083900b0260401d6f7fffffffffffffffffffffffffffffff19811280159061424f57506f7fffffffffffffffffffffffffffffff8113155b613d39576040805162461bcd60e51b815260206004820152600860248201527f4d554c2d4f565546000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000816142af5750600061349b565b600083600f0b1215614308576040805162461bcd60e51b815260206004820152600760248201527f4d554c552d583000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600f83900b6001600160801b038316810260401c90608084901c0277ffffffffffffffffffffffffffffffffffffffffffffffff811115614390576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4631000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60401b81198111156143e9576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4632000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b019392505050565b6143fb8482614ad0565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906144499086908590600401615999565b600060405180830381600087803b15801561446357600080fd5b505af1158015614477573d6000803e3d6000fd5b505050507fea19ffc45b48de6d95594aacff7214dd24595fdb0c60e98c8f0b269058c2f792338284604051613431939291906159d5565b6040820151613a9790613a92906001600160601b03168361343f565b60008060006145607f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460016127b1565b9050614678857f000000000000000000000000000000000000000000000000000000000000000086846706f05b59d3b200007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634a0a96eb7f00000000000000000000000000000000000000000000000000000000000000006101a46040518363ffffffff1660e01b8152600401614602929190615a71565b60206040518083038186803b15801561461a57600080fd5b505afa15801561462e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146529190615767565b7f0000000000000000000000000000000000000000000000000000000000000000614b4e565b92509250509250929050565b602081015163ffffffff166146c5576040805162461bcd60e51b81526020600482015260026024820152612b1960f11b604482015290519081900360640190fd5b6000602090910152565b602082015163ffffffff1615614711576040805162461bcd60e51b8152602060048201526002602482015261563160f01b604482015290519081900360640190fd5b80614749576040805162461bcd60e51b815260206004820152600360248201526243323360e81b604482015290519081900360640190fd5b61475281614007565b63ffffffff1660209092019190915250565b6000807f0000000000000000000000000000000000000000000000000000000000000000816147938286614bf2565b50506040805160a0810182528981526001600160801b0383166020820152600081830181905260608201524260808201529051630624e65f60e11b815291945092506001600160a01b0385169150630c49ccbe906147f5908490600401615d62565b6040805180830381600087803b15801561480e57600080fd5b505af1158015614822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148469190615801565b5050604080516080810182528781523060208201526001600160801b038183018190526060820152905163fc6f786560e01b815260009081906001600160a01b0387169063fc6f78659061489e908690600401615d1f565b6040805180830381600087803b1580156148b757600080fd5b505af11580156148cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148ef9190615801565b915091507f000000000000000000000000000000000000000000000000000000000000000061491f578082614922565b81815b97509750505050505050915091565b600080600080841561494a576149478787614cb0565b90505b606088015186906000906001600160801b03168211156149905760608a015161497d9089906001600160801b031661343f565b905089606001516001600160801b031691505b61499a8a83614ad0565b6149a38a614684565b6149ad8a8a613a76565b6149b78a846144ae565b9099909850909650945050505050565b600082820183811015613d39576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b806001600160601b0381168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a31c9b60e11b604482015290519081900360640190fd5b6000808080614a8187614a7c886002613c79565b614d60565b9150915080851115614ab6576706f05b59d3b20000614aa0868361343f565b1015614ab657614ab08787614d60565b90925090505b84811115614ac45750849050835b90969095509350505050565b6060820151614af190614aec906001600160801b03168361343f565b61274f565b6001600160801b031660609092019190915250565b600080614b1a868686866101a46000613bd3565b905061280e670de0b6b3a76400006128088984613ce0565b6060820151614af190614aec906001600160801b0316836149c7565b60008088606001516001600160801b031660001415614b735750600190506000614be6565b6000614bac6ec097ce7bc90715b34b9f100000000061280889613a1d8c8f606001516001600160801b0316613ce090919063ffffffff16565b90506000614bbe8b8b8b8b8a8a614e3c565b90508681106000614bd0846003613ce0565b614bdb846002613ce0565b101595509093505050505b97509795505050505050565b6000806000806000808790506000806000806000856001600160a01b03166399fbab888d6040518263ffffffff1660e01b8152600401808281526020019150506101806040518083038186803b158015614c4b57600080fd5b505afa158015614c5f573d6000803e3d6000fd5b505050506040513d610180811015614c7657600080fd5b5060a081015160c082015160e083015161014084015161016090940151929e50909c509a5090985096505050505050509295509295909350565b6000613d39670de0b6b3a764000061280866470de4df820000613a1d87614d5a887f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b906149c7565b6000806000838511614d725784614d74565b835b90506000614e05827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b9050614e2f614e28670de0b6b3a76400006128088467016345785d8a0000613ce0565b82906149c7565b9196919550909350505050565b6000866020015163ffffffff1660001415614e65575060408601516001600160601b03166127d4565b600080614e7e888a6020015163ffffffff168787614ed3565b90925090506000614ea66ec097ce7bc90715b34b9f100000000061280889613a1d868d613ce0565b60408b0151909150614ec5906001600160601b0316614d5a85846149c7565b9a9950505050505050505050565b6000806000806000806000614ee88b8b614bf2565b94509450945094509450600080614f0187878d88614f54565b9150915089614f2757826001600160801b03168101846001600160801b03168301614f40565b836001600160801b03168201836001600160801b031682015b985098505050505050505094509492505050565b600080600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba3866040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b158015614fab57600080fd5b505af4158015614fbf573d6000803e3d6000fd5b505050506040513d6020811015614fd557600080fd5b50519050600287810b9086900b12156151985773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b673__$d199f155f9376dc21890c162698c9ef049$__63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561505457600080fd5b505af4158015615068573d6000803e3d6000fd5b505050506040513d602081101561507e57600080fd5b50516040805163986cfba360e01b815260028b900b6004820152905173__$d199f155f9376dc21890c162698c9ef049$__9163986cfba3916024808301926020929190829003018186803b1580156150d557600080fd5b505af41580156150e9573d6000803e3d6000fd5b505050506040513d60208110156150ff57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561516557600080fd5b505af4158015615179573d6000803e3d6000fd5b505050506040513d602081101561518f57600080fd5b505192506155b2565b8560020b8560020b12156154065773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b68273__$d199f155f9376dc21890c162698c9ef049$__63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561521357600080fd5b505af4158015615227573d6000803e3d6000fd5b505050506040513d602081101561523d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156152a357600080fd5b505af41580156152b7573d6000803e3d6000fd5b505050506040513d60208110156152cd57600080fd5b50516040805163986cfba360e01b815260028a900b6004820152905191945073__$a98c5df505b68ab2f483703658c95acb30$__916348a0c5bd9173__$d199f155f9376dc21890c162698c9ef049$__9163986cfba391602480820192602092909190829003018186803b15801561534457600080fd5b505af4158015615358573d6000803e3d6000fd5b505050506040513d602081101561536e57600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b03928316600482015291851660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156153d357600080fd5b505af41580156153e7573d6000803e3d6000fd5b505050506040513d60208110156153fd57600080fd5b505191506155b2565b73__$a98c5df505b68ab2f483703658c95acb30$__6348a0c5bd73__$d199f155f9376dc21890c162698c9ef049$__63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561547257600080fd5b505af4158015615486573d6000803e3d6000fd5b505050506040513d602081101561549c57600080fd5b50516040805163986cfba360e01b815260028b900b6004820152905173__$d199f155f9376dc21890c162698c9ef049$__9163986cfba3916024808301926020929190829003018186803b1580156154f357600080fd5b505af4158015615507573d6000803e3d6000fd5b505050506040513d602081101561551d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561558357600080fd5b505af4158015615597573d6000803e3d6000fd5b505050506040513d60208110156155ad57600080fd5b505191505b5094509492505050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b8051610c5381615e31565b8051600281900b8114610c5357600080fd5b80516001600160801b0381168114610c5357600080fd5b805162ffffff81168114610c5357600080fd5b60006020828403121561563b578081fd5b8135613d3981615e31565b600060208284031215615657578081fd5b8151613d3981615e31565b60008060008060808587031215615677578283fd5b843561568281615e31565b935060208581013561569381615e31565b935060408601359250606086013567ffffffffffffffff808211156156b6578384fd5b818801915088601f8301126156c9578384fd5b8135818111156156d557fe5b604051601f8201601f19168101850183811182821017156156f257fe5b60405281815283820185018b1015615708578586fd5b81858501868301379081019093019390935250939692955090935050565b600060208284031215615737578081fd5b81518015158114613d39578182fd5b600060208284031215615757578081fd5b815180600f0b8114613d39578182fd5b600060208284031215615778578081fd5b613d39826155ee565b600060208284031215615792578081fd5b5035919050565b6000602082840312156157aa578081fd5b5051919050565b600080604083850312156157c3578182fd5b8235915060208301356157d581615e31565b809150509250929050565b600080604083850312156157f2578182fd5b50508035926020909101359150565b60008060408385031215615813578182fd5b505080516020909101519092909150565b600080600060608486031215615838578283fd5b505081359360208301359350604090920135919050565b600060208284031215615860578081fd5b8135613d3981615e46565b60006020828403121561587c578081fd5b8151613d3981615e46565b6000806000806000806000806000806000806101808d8f0312156158a957898afd5b8c516001600160601b03811681146158bf578a8bfd5b9b506158cd60208e016155e3565b9a506158db60408e016155e3565b99506158e960608e016155e3565b98506158f760808e01615617565b975061590560a08e016155ee565b965061591360c08e016155ee565b955061592160e08e01615600565b94506101008d015193506101208d015192506159406101408e01615600565b915061594f6101608e01615600565b90509295989b509295989b509295989b565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b03979097168752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0392909216825263ffffffff16602082015260400190565b6001600160a01b0394909416845263ffffffff9290921660208401526001600160601b031660408301526001600160801b0316606082015260800190565b901515815260200190565b6001600160e01b031991909116815260200190565b600f9190910b815260200190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b602080825260029082015261043360f41b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b602080825260029082015261433360f01b604082015260600190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b6001600160801b0391909116815260200190565b6001600160801b039485168152602081019390935292166040820152606081019190915260800190565b62ffffff91909116815260200190565b90815260200190565b918252602082015260400190565b63ffffffff91909116815260200190565b63ffffffff929092168252602082015260400190565b6001600160a01b0381168114610d1f57600080fd5b63ffffffff81168114610d1f57600080fdfe5265656e7472616e637947756172643a207265656e7472616e742063616c6c004f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122067c719aed0ae3307dbebb58cfa90077cc4cbc9d365114aa9321da3e54e97944d64736f6c63430007060033\",\n  \"libraries\": {\n    \"ABDKMath64x64\": \"0x4CA8F19f951052162Bda12D1db72dEDa489dBD83\",\n    \"SqrtPriceMathPartial\": \"0xa932Db3b9f630436aeb5a9AF8687E521dc943569\",\n    \"TickMathExternal\": \"0x569292d3d8B44F02B11ef048A3Dd361e57880E8C\"\n  },\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"burnPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_powerPerpAmount\": \"amount of powerPerp to burn\",\n          \"_vaultId\": \"id of the vault\",\n          \"_withdrawAmount\": \"amount of eth to withdraw\"\n        },\n        \"returns\": {\n          \"_0\": \"amount of wPowerPerp burned\"\n        }\n      },\n      \"burnWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_vaultId\": \"id of the vault\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to burn\",\n          \"_withdrawAmount\": \"amount of eth to withdraw\"\n        }\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_ethQuoteCurrencyPool\": \"uniswap v3 pool for weth / quoteCurrency\",\n          \"_oracle\": \"oracle address\",\n          \"_quoteCurrency\": \"quoteCurrency address\",\n          \"_shortPowerPerp\": \"ERC721 token address representing the short position\",\n          \"_uniPositionManager\": \"uniswap v3 position manager address\",\n          \"_wPowerPerp\": \"ERC20 token address representing the long position\",\n          \"_wPowerPerpPool\": \"uniswap v3 pool for wPowerPerp / weth\",\n          \"_weth\": \"weth address\"\n        }\n      },\n      \"deposit(uint256)\": {\n        \"details\": \"deposit collateral into a vault\",\n        \"params\": {\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"depositUniPositionToken(uint256,uint256)\": {\n        \"params\": {\n          \"_uniTokenId\": \"uniswap position token id\",\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"getDenormalizedMark(uint32)\": {\n        \"params\": {\n          \"_period\": \"period of time for the twap in seconds\"\n        },\n        \"returns\": {\n          \"_0\": \"mark price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"getDenormalizedMarkForFunding(uint32)\": {\n        \"details\": \"this is the mark that would be used to calculate a new normalization factor if funding was calculated now\",\n        \"params\": {\n          \"_period\": \"period which you want to calculate twap with\"\n        },\n        \"returns\": {\n          \"_0\": \"mark price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"getExpectedNormalizationFactor()\": {\n        \"details\": \"can be used for on-chain and off-chain calculations\"\n      },\n      \"getIndex(uint32)\": {\n        \"details\": \"the index price is scaled down by INDEX_SCALE in the associated PowerXBase librarythis is the index price used when calculating funding and for collateralization\",\n        \"params\": {\n          \"_period\": \"period which you want to calculate twap with\"\n        },\n        \"returns\": {\n          \"_0\": \"index price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"getUnscaledIndex(uint32)\": {\n        \"details\": \"this is the mark that would be be used for future funding after a new normalization factor is applied\",\n        \"params\": {\n          \"_period\": \"period which you want to calculate twap with\"\n        },\n        \"returns\": {\n          \"_0\": \"index price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"isVaultSafe(uint256)\": {\n        \"details\": \"return if the vault is properly collateralized\",\n        \"params\": {\n          \"_vaultId\": \"id of the vault\"\n        },\n        \"returns\": {\n          \"_0\": \"true if the vault is properly collateralized\"\n        }\n      },\n      \"liquidate(uint256,uint256)\": {\n        \"details\": \"liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateralnormally can only liquidate 50% of a vault's debtif a vault is under dust limit after a liquidation can fully liquidatewill attempt to reduceDebt first, and can earn a bounty if sucessful\",\n        \"params\": {\n          \"_maxDebtAmount\": \"max amount of wPowerPerpetual to repay\",\n          \"_vaultId\": \"vault to liquidate\"\n        },\n        \"returns\": {\n          \"_0\": \"amount of wPowerPerp repaid\"\n        }\n      },\n      \"mintPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_powerPerpAmount\": \"amount of powerPerp to mint\",\n          \"_uniTokenId\": \"uniswap v3 position token id (additional collateral)\",\n          \"_vaultId\": \"vault to mint wPowerPerp in\"\n        },\n        \"returns\": {\n          \"_0\": \"vaultId\",\n          \"_1\": \"amount of wPowerPerp minted\"\n        }\n      },\n      \"mintWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_uniTokenId\": \"uniswap v3 position token id (additional collateral)\",\n          \"_vaultId\": \"vault to mint wPowerPerp in\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to mint\"\n        },\n        \"returns\": {\n          \"_0\": \"vaultId\"\n        }\n      },\n      \"onERC721Received(address,address,uint256,bytes)\": {\n        \"details\": \"accept erc721 from safeTransferFrom and safeMint after callback\",\n        \"returns\": {\n          \"_0\": \"returns received selector\"\n        }\n      },\n      \"owner()\": {\n        \"details\": \"Returns the address of the current owner.\"\n      },\n      \"pause()\": {\n        \"details\": \"can only be called for 365 days since the contract was launched or 4 times\"\n      },\n      \"redeemLong(uint256)\": {\n        \"params\": {\n          \"_wPerpAmount\": \"amount of wPowerPerp to burn\"\n        }\n      },\n      \"redeemShort(uint256)\": {\n        \"details\": \"short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\",\n        \"params\": {\n          \"_vaultId\": \"vault id\"\n        }\n      },\n      \"reduceDebt(uint256)\": {\n        \"details\": \"the caller won't get any bounty. this is expected to be used by vault owner\",\n        \"params\": {\n          \"_vaultId\": \"target vault\"\n        }\n      },\n      \"reduceDebtShutdown(uint256)\": {\n        \"details\": \"the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\",\n        \"params\": {\n          \"_vaultId\": \"vault containing uniswap v3 position to liquidate\"\n        }\n      },\n      \"renounceOwnership()\": {\n        \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n      },\n      \"setFeeRate(uint256)\": {\n        \"details\": \"this function cannot be called if the feeRecipient is still un-set\",\n        \"params\": {\n          \"_newFeeRate\": \"new fee rate in basis points. can't be higher than 1%\"\n        }\n      },\n      \"setFeeRecipient(address)\": {\n        \"details\": \"this should be a contract handling insurance\",\n        \"params\": {\n          \"_newFeeRecipient\": \"new fee recipient\"\n        }\n      },\n      \"shutDown()\": {\n        \"details\": \"this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\"\n      },\n      \"transferOwnership(address)\": {\n        \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n      },\n      \"unPauseAnyone()\": {\n        \"details\": \"anyone can unpause the contract after 24 hours\"\n      },\n      \"unPauseOwner()\": {\n        \"details\": \"owner can unpause at any time\"\n      },\n      \"updateOperator(uint256,address)\": {\n        \"details\": \"can be revoke by setting address to 0\",\n        \"params\": {\n          \"_operator\": \"new operator address\",\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"withdraw(uint256,uint256)\": {\n        \"params\": {\n          \"_amount\": \"amount of eth to withdraw\",\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"withdrawUniPositionToken(uint256)\": {\n        \"params\": {\n          \"_vaultId\": \"id of the vault\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"ONE\": {\n        \"details\": \"basic unit used for calculation\"\n      },\n      \"PAUSE_TIME_LIMIT\": {\n        \"details\": \"system can only be paused for 182 days from deployment\"\n      },\n      \"feeRate\": {\n        \"details\": \"fee rate in basis point. feeRate of 1 = 0.01%\"\n      },\n      \"indexForSettlement\": {\n        \"details\": \"the settlement price for each wPowerPerp for settlement\"\n      },\n      \"vaults\": {\n        \"details\": \"vault data storage\"\n      },\n      \"wPowerPerpPool\": {\n        \"details\": \"address of the powerPerp/weth pool\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"events\": {\n      \"OpenVault(address,uint256)\": {\n        \"notice\": \"Events\"\n      }\n    },\n    \"kind\": \"user\",\n    \"methods\": {\n      \"applyFunding()\": {\n        \"notice\": \"update the normalization factor as a way to pay funding\"\n      },\n      \"burnPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"burn powerPerp and remove collateral from a vault\"\n      },\n      \"burnWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"burn wPowerPerp and remove collateral from a vault\"\n      },\n      \"constructor\": {\n        \"notice\": \"constructor\"\n      },\n      \"depositUniPositionToken(uint256,uint256)\": {\n        \"notice\": \"deposit uniswap position token into a vault to increase collateral ratio\"\n      },\n      \"donate()\": {\n        \"notice\": \"add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\"\n      },\n      \"getDenormalizedMark(uint32)\": {\n        \"notice\": \"get the expected mark price of powerPerp after funding has been applied\"\n      },\n      \"getDenormalizedMarkForFunding(uint32)\": {\n        \"notice\": \"get the mark price of powerPerp before funding has been applied\"\n      },\n      \"getExpectedNormalizationFactor()\": {\n        \"notice\": \"returns the expected normalization factor, if the funding is paid right now\"\n      },\n      \"getIndex(uint32)\": {\n        \"notice\": \"get the index price of the powerPerp, scaled down\"\n      },\n      \"getUnscaledIndex(uint32)\": {\n        \"notice\": \"the unscaled index of the power perp in USD, scaled by 18 decimals\"\n      },\n      \"liquidate(uint256,uint256)\": {\n        \"notice\": \"if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\"\n      },\n      \"mintPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\"\n      },\n      \"mintWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"deposit collateral and mint wPowerPerp\"\n      },\n      \"pause()\": {\n        \"notice\": \"pause the system for up to 24 hours after which any one can unpause\"\n      },\n      \"redeemLong(uint256)\": {\n        \"notice\": \"redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\"\n      },\n      \"redeemShort(uint256)\": {\n        \"notice\": \"redeem short position when the system is shutdown\"\n      },\n      \"reduceDebt(uint256)\": {\n        \"notice\": \"withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\"\n      },\n      \"reduceDebtShutdown(uint256)\": {\n        \"notice\": \"after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by forceif a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\"\n      },\n      \"setFeeRate(uint256)\": {\n        \"notice\": \"set the fee rate when user mints\"\n      },\n      \"setFeeRecipient(address)\": {\n        \"notice\": \"set the recipient who will receive the fee\"\n      },\n      \"shutDown()\": {\n        \"notice\": \"shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactorshort positions can be redeemed for vault collateral minus value of debtpause (if not paused) and then immediately shutdown the system, can be called when paused already\"\n      },\n      \"unPauseAnyone()\": {\n        \"notice\": \"unpause the contract\"\n      },\n      \"unPauseOwner()\": {\n        \"notice\": \"unpause the contract\"\n      },\n      \"updateOperator(uint256,address)\": {\n        \"notice\": \"authorize an address to modify the vault\"\n      },\n      \"withdraw(uint256,uint256)\": {\n        \"notice\": \"withdraw collateral from a vault\"\n      },\n      \"withdrawUniPositionToken(uint256)\": {\n        \"notice\": \"withdraw uniswap v3 position token from a vault\"\n      }\n    },\n    \"notice\": \"Error C0: Paused C1: Not paused C2: Shutdown C3: Not shutdown C4: Invalid oracle address C5: Invalid shortPowerPerp address C6: Invalid wPowerPerp address C7: Invalid weth address C8: Invalid quote currency address C9: Invalid eth:quoteCurrency pool address C10: Invalid wPowerPerp:eth pool address C11: Invalid Uniswap position manager C12: Can not liquidate safe vault C13: Invalid address C14: Set fee recipient first C15: Fee too high C16: Paused too many times C17: Pause time limit exceeded C18: Not enough paused time has passed C19: Cannot receive eth C20: Not allowed C21: Need full liquidation C22: Dust vault left C23: Invalid nft C24: Invalid state C25: 0 liquidity Uniswap position token C26: Wrong fee tier for NFT deposit\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 7,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"_owner\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 4176,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7732,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"feeRecipient\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 7737,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"feeRate\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7740,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"indexForSettlement\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7743,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"pausesLeft\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7745,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"lastPauseTime\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7747,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"normalizationFactor\",\n        \"offset\": 0,\n        \"slot\": \"7\",\n        \"type\": \"t_uint128\"\n      },\n      {\n        \"astId\": 7749,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"lastFundingUpdateTimestamp\",\n        \"offset\": 16,\n        \"slot\": \"7\",\n        \"type\": \"t_uint128\"\n      },\n      {\n        \"astId\": 7753,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"isShutDown\",\n        \"offset\": 0,\n        \"slot\": \"8\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 7755,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"isSystemPaused\",\n        \"offset\": 1,\n        \"slot\": \"8\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 7760,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"vaults\",\n        \"offset\": 0,\n        \"slot\": \"9\",\n        \"type\": \"t_mapping(t_uint256,t_struct(Vault)14613_storage)\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_mapping(t_uint256,t_struct(Vault)14613_storage)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => struct VaultLib.Vault)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_struct(Vault)14613_storage\"\n      },\n      \"t_struct(Vault)14613_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct VaultLib.Vault\",\n        \"members\": [\n          {\n            \"astId\": 14606,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"operator\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_address\"\n          },\n          {\n            \"astId\": 14608,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"NftCollateralId\",\n            \"offset\": 20,\n            \"slot\": \"0\",\n            \"type\": \"t_uint32\"\n          },\n          {\n            \"astId\": 14610,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"collateralAmount\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_uint96\"\n          },\n          {\n            \"astId\": 14612,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"shortAmount\",\n            \"offset\": 12,\n            \"slot\": \"1\",\n            \"type\": \"t_uint128\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_uint128\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint128\",\n        \"numberOfBytes\": \"16\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint32\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint32\",\n        \"numberOfBytes\": \"4\"\n      },\n      \"t_uint96\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint96\",\n        \"numberOfBytes\": \"12\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/ControllerHelper.json",
    "content": "{\n  \"address\": \"0xef0F6F951F0e62774597eB29b86065498bB7aC32\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controller\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_nonfungiblePositionManager\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniswapFactory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_exec\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_euler\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_dToken\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"burnExactRemoved\",\n              \"type\": \"bool\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.CloseShortWithUserNftParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"closeShortWithUserNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"dToken\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"euler\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"exec\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToFlashloan\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"burnExactRemoved\",\n              \"type\": \"bool\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashloanCloseVaultLpNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmount\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToFlashloan\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToLp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashloanWMintLpDepositNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToMint\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToSell\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"minToReceive\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashSellLongWMintParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashswapSellLongWMint\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBuy\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"maxToPay\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashswapWBurnBuyLongParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashswapWBurnBuyLong\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"encodedData\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onDeferredLiquidityCheck\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onERC721Received\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_collateralToFlashloan\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"enum ControllerHelperDataType.RebalanceVaultNftType\",\n              \"name\": \"rebalanceLpInVaultType\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"bytes\",\n              \"name\": \"data\",\n              \"type\": \"bytes\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.RebalanceLpInVaultParams[]\",\n          \"name\": \"_params\",\n          \"type\": \"tuple[]\"\n        }\n      ],\n      \"name\": \"rebalanceLpInVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountDesired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wethAmountDesired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0DesiredMin\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1DesiredMin\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.RebalanceLpWithoutVaultParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"rebalanceLpWithoutVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.ReduceLiquidityAndSellParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"reduceLiquidityAndSell\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"token\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmount\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToLp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.MintAndLpParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"wMintLp\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x3ea9335b13de03d8fb51f27c688de7b47f5054d1af7233e3325793550b9dd151\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0xef0F6F951F0e62774597eB29b86065498bB7aC32\",\n    \"transactionIndex\": 35,\n    \"gasUsed\": \"5438367\",\n    \"logsBloom\": \"0x80008000000010000080000000000000000000100000000000000000000000000000000000000000000000000000000000040000000000000000100000200000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000001400000200000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000020000000000000000000000000000000000000000000080000000000000000000000000000000000200000000000000000000000000000000000080000000000010200800000000004000000000000000000000480000000000000000000000\",\n    \"blockHash\": \"0x14b0f91044ba5c4ca7e5e255142217b6f2f5e16fdb6fd4eaa6ca2e7ce71178f7\",\n    \"transactionHash\": \"0x3ea9335b13de03d8fb51f27c688de7b47f5054d1af7233e3325793550b9dd151\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 35,\n        \"blockNumber\": 8042203,\n        \"transactionHash\": \"0x3ea9335b13de03d8fb51f27c688de7b47f5054d1af7233e3325793550b9dd151\",\n        \"address\": \"0x9421c968D28DD789363FbD8c9aA5cF2090F0a656\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x000000000000000000000000ef0f6f951f0e62774597eb29b86065498bb7ac32\",\n          \"0x00000000000000000000000024a66308bab3bebc2821480ada395bf1c4ff8bf2\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 74,\n        \"blockHash\": \"0x14b0f91044ba5c4ca7e5e255142217b6f2f5e16fdb6fd4eaa6ca2e7ce71178f7\"\n      },\n      {\n        \"transactionIndex\": 35,\n        \"blockNumber\": 8042203,\n        \"transactionHash\": \"0x3ea9335b13de03d8fb51f27c688de7b47f5054d1af7233e3325793550b9dd151\",\n        \"address\": \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x000000000000000000000000ef0f6f951f0e62774597eb29b86065498bb7ac32\",\n          \"0x00000000000000000000000024a66308bab3bebc2821480ada395bf1c4ff8bf2\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 75,\n        \"blockHash\": \"0x14b0f91044ba5c4ca7e5e255142217b6f2f5e16fdb6fd4eaa6ca2e7ce71178f7\"\n      },\n      {\n        \"transactionIndex\": 35,\n        \"blockNumber\": 8042203,\n        \"transactionHash\": \"0x3ea9335b13de03d8fb51f27c688de7b47f5054d1af7233e3325793550b9dd151\",\n        \"address\": \"0x24a66308bab3BEbC2821480adA395BF1C4ff8Bf2\",\n        \"topics\": [\n          \"0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31\",\n          \"0x000000000000000000000000ef0f6f951f0e62774597eb29b86065498bb7ac32\",\n          \"0x0000000000000000000000006fc3f76f8a2d256cc091bd58bab8c2bc3f51d508\"\n        ],\n        \"data\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n        \"logIndex\": 76,\n        \"blockHash\": \"0x14b0f91044ba5c4ca7e5e255142217b6f2f5e16fdb6fd4eaa6ca2e7ce71178f7\"\n      }\n    ],\n    \"blockNumber\": 8042203,\n    \"cumulativeGasUsed\": \"11047115\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n    \"0x24a66308bab3BEbC2821480adA395BF1C4ff8Bf2\",\n    \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n    \"0x4b62EB6797526491eEf6eF36D3B9960E5d66C394\",\n    \"0x931172BB95549d0f29e10ae2D079ABA3C63318B3\",\n    \"0x356079240635B276A63065478471d89340443C49\"\n  ],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controller\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_nonfungiblePositionManager\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniswapFactory\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_exec\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_euler\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_dToken\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidityPercentage\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBurn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"burnExactRemoved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.CloseShortWithUserNftParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"closeShortWithUserNft\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"dToken\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"euler\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"exec\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"factory\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidityPercentage\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBurn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToFlashloan\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"burnExactRemoved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashloanCloseVaultLpNft\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToFlashloan\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToLp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"upperTick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashloanWMintLpDepositNft\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToMint\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToSell\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minToReceive\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashSellLongWMintParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashswapSellLongWMint\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBurn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBuy\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"maxToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashswapWBurnBuyLongParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashswapWBurnBuyLong\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"encodedData\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onDeferredLiquidityCheck\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onERC721Received\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_collateralToFlashloan\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"enum ControllerHelperDataType.RebalanceVaultNftType\\\",\\\"name\\\":\\\"rebalanceLpInVaultType\\\",\\\"type\\\":\\\"uint8\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.RebalanceLpInVaultParams[]\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple[]\\\"}],\\\"name\\\":\\\"rebalanceLpInVault\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountDesired\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wethAmountDesired\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0DesiredMin\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1DesiredMin\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"upperTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.RebalanceLpWithoutVaultParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"rebalanceLpWithoutVault\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidityPercentage\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.ReduceLiquidityAndSellParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"reduceLiquidityAndSell\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"token\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount0Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount1Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"uniswapV3SwapCallback\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToLp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"upperTick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.MintAndLpParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"wMintLp\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\\\":{\\\"details\\\":\\\"user should approve this contract for Uni NFT transfer\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.CloseShortWithUserNftParams struct\\\"}},\\\"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"details\\\":\\\"sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\\"}},\\\"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"details\\\":\\\"flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.FlashSellLongWMintParams struct\\\"}},\\\"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"details\\\":\\\"this function\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\\"}},\\\"onERC721Received(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"accept erc721 from safeTransferFrom and safeMint after callback\\\",\\\"returns\\\":{\\\"_0\\\":\\\"returns received selector\\\"}},\\\"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\\\":{\\\"params\\\":{\\\"_collateralToFlashloan\\\":\\\"collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\\",\\\"_params\\\":\\\"array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\\",\\\"_vaultId\\\":\\\"vault ID\\\"}},\\\"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\\\":{\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\\"}},\\\"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\\\":{\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\\"}},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"params\\\":{\\\"_data\\\":\\\"callback data encoded as SwapCallbackData struct\\\",\\\"amount0Delta\\\":\\\"amount of token0\\\",\\\"amount1Delta\\\":\\\"amount of token1\\\"}},\\\"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.MintAndLpParams struct\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\\\":{\\\"notice\\\":\\\"close short position with user Uniswap v3 LP NFT\\\"},\\\"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"notice\\\":\\\"FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\\"},\\\"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"notice\\\":\\\"sell long wPowerPerp and flashswap mint short position\\\"},\\\"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"notice\\\":\\\"flash close position and buy long squeeth\\\"},\\\"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\\\":{\\\"notice\\\":\\\"Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\\"},\\\"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\\\":{\\\"notice\\\":\\\"Rebalance LP nft through trading\\\"},\\\"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\\\":{\\\"notice\\\":\\\"sell all LP wPowerPerp amounts to WETH and send back to user\\\"},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"notice\\\":\\\"uniswap swap callback function for flashswap\\\"},\\\"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"notice\\\":\\\"mint WPowerPerp and LP into Uniswap v3 pool\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/periphery/ControllerHelper.sol\\\":\\\"ControllerHelper\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#flash\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\\\ninterface IUniswapV3FlashCallback {\\\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\\\n    function uniswapV3FlashCallback(\\\\n        uint256 fee0,\\\\n        uint256 fee1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x151ba1777392771025f0fca946c95fbc16ec4b5eff05e1f236115b99bd574de2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Safe casting methods\\\\n/// @notice Contains methods for safely casting between types\\\\nlibrary SafeCast {\\\\n    /// @notice Cast a uint256 to a uint160, revert on overflow\\\\n    /// @param y The uint256 to be downcasted\\\\n    /// @return z The downcasted integer, now type uint160\\\\n    function toUint160(uint256 y) internal pure returns (uint160 z) {\\\\n        require((z = uint160(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a int256 to a int128, revert on overflow or underflow\\\\n    /// @param y The int256 to be downcasted\\\\n    /// @return z The downcasted integer, now type int128\\\\n    function toInt128(int256 y) internal pure returns (int128 z) {\\\\n        require((z = int128(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a uint256 to a int256, revert on overflow\\\\n    /// @param y The uint256 to be casted\\\\n    /// @return z The casted integer, now type int256\\\\n    function toInt256(uint256 y) internal pure returns (int256 z) {\\\\n        require(y < 2**255);\\\\n        z = int256(y);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n/*\\\\n * @title Solidity Bytes Arrays Utils\\\\n * @author Gon\\\\u00e7alo S\\\\u00e1 <goncalo.sa@consensys.net>\\\\n *\\\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\\\n */\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nlibrary BytesLib {\\\\n    function slice(\\\\n        bytes memory _bytes,\\\\n        uint256 _start,\\\\n        uint256 _length\\\\n    ) internal pure returns (bytes memory) {\\\\n        require(_length + 31 >= _length, 'slice_overflow');\\\\n        require(_start + _length >= _start, 'slice_overflow');\\\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\\\n\\\\n        bytes memory tempBytes;\\\\n\\\\n        assembly {\\\\n            switch iszero(_length)\\\\n                case 0 {\\\\n                    // Get a location of some free memory and store it in tempBytes as\\\\n                    // Solidity does for memory variables.\\\\n                    tempBytes := mload(0x40)\\\\n\\\\n                    // The first word of the slice result is potentially a partial\\\\n                    // word read from the original array. To read it, we calculate\\\\n                    // the length of that partial word and start copying that many\\\\n                    // bytes into the array. The first word we copy will start with\\\\n                    // data we don't care about, but the last `lengthmod` bytes will\\\\n                    // land at the beginning of the contents of the new array. When\\\\n                    // we're done copying, we overwrite the full first word with\\\\n                    // the actual length of the slice.\\\\n                    let lengthmod := and(_length, 31)\\\\n\\\\n                    // The multiplication in the next line is necessary\\\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\\\n                    // the following copy loop was copying the origin's length\\\\n                    // and then ending prematurely not copying everything it should.\\\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\\\n                    let end := add(mc, _length)\\\\n\\\\n                    for {\\\\n                        // The multiplication in the next line has the same exact purpose\\\\n                        // as the one above.\\\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\\\n                    } lt(mc, end) {\\\\n                        mc := add(mc, 0x20)\\\\n                        cc := add(cc, 0x20)\\\\n                    } {\\\\n                        mstore(mc, mload(cc))\\\\n                    }\\\\n\\\\n                    mstore(tempBytes, _length)\\\\n\\\\n                    //update free-memory pointer\\\\n                    //allocating the array padded to 32 bytes like the compiler does now\\\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\\\n                }\\\\n                //if we want a zero-length slice let's just return a zero-length array\\\\n                default {\\\\n                    tempBytes := mload(0x40)\\\\n                    //zero out the 32 bytes slice we are about to return\\\\n                    //we need to do it because Solidity does not garbage collect\\\\n                    mstore(tempBytes, 0)\\\\n\\\\n                    mstore(0x40, add(tempBytes, 0x20))\\\\n                }\\\\n        }\\\\n\\\\n        return tempBytes;\\\\n    }\\\\n\\\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\\\n        address tempAddress;\\\\n\\\\n        assembly {\\\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\\\n        }\\\\n\\\\n        return tempAddress;\\\\n    }\\\\n\\\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\\\n        uint24 tempUint;\\\\n\\\\n        assembly {\\\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\\\n        }\\\\n\\\\n        return tempUint;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport './PoolAddress.sol';\\\\n\\\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\\\nlibrary CallbackValidation {\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param tokenA The contract address of either token0 or token1\\\\n    /// @param tokenB The contract address of the other token\\\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(\\\\n        address factory,\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool pool) {\\\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param poolKey The identifying key of the V3 pool\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\\\n        internal\\\\n        view\\\\n        returns (IUniswapV3Pool pool)\\\\n    {\\\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\\\n        require(msg.sender == address(pool));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.6.0;\\\\n\\\\nimport './BytesLib.sol';\\\\n\\\\n/// @title Functions for manipulating path data for multihop swaps\\\\nlibrary Path {\\\\n    using BytesLib for bytes;\\\\n\\\\n    /// @dev The length of the bytes encoded address\\\\n    uint256 private constant ADDR_SIZE = 20;\\\\n    /// @dev The length of the bytes encoded fee\\\\n    uint256 private constant FEE_SIZE = 3;\\\\n\\\\n    /// @dev The offset of a single token address and pool fee\\\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\\\n    /// @dev The offset of an encoded pool key\\\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\\\n\\\\n    /// @notice Returns true iff the path contains two or more pools\\\\n    /// @param path The encoded swap path\\\\n    /// @return True if path contains two or more pools, otherwise false\\\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\\\n    }\\\\n\\\\n    /// @notice Returns the number of pools in the path\\\\n    /// @param path The encoded swap path\\\\n    /// @return The number of pools in the path\\\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Decodes the first pool in path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return tokenA The first token of the given pool\\\\n    /// @return tokenB The second token of the given pool\\\\n    /// @return fee The fee level of the pool\\\\n    function decodeFirstPool(bytes memory path)\\\\n        internal\\\\n        pure\\\\n        returns (\\\\n            address tokenA,\\\\n            address tokenB,\\\\n            uint24 fee\\\\n        )\\\\n    {\\\\n        tokenA = path.toAddress(0);\\\\n        fee = path.toUint24(ADDR_SIZE);\\\\n        tokenB = path.toAddress(NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Gets the segment corresponding to the first pool in the path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return The segment containing all data necessary to target the first pool in the path\\\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(0, POP_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\\\n    /// @param path The swap path\\\\n    /// @return The remaining token + fee elements in the path\\\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IERC20Detailed.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// uniswap Library only works under 0.7.6\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IERC20Detailed is IERC20 {\\\\n    function decimals() external view returns (uint8);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcd59a0158d0711810c499904b9d37a71fdb34d1c4403f3cb67ca47de5e88bf7b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/ControllerHelper.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IERC721Receiver} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\\\\\";\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {UniswapControllerHelper} from \\\\\\\"./UniswapControllerHelper.sol\\\\\\\";\\\\nimport {EulerControllerHelper} from \\\\\\\"./EulerControllerHelper.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ControllerHelperDataType} from \\\\\\\"./lib/ControllerHelperDataType.sol\\\\\\\";\\\\nimport {ControllerHelperUtil} from \\\\\\\"./lib/ControllerHelperUtil.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    bool private immutable isWethToken0;\\\\n    address private immutable controller;\\\\n    address private immutable shortPowerPerp;\\\\n    address private immutable wPowerPerp;\\\\n    address private immutable weth;\\\\n    address private immutable nonfungiblePositionManager;\\\\n\\\\n    constructor(\\\\n        address _controller,\\\\n        address _nonfungiblePositionManager,\\\\n        address _uniswapFactory,\\\\n        address _exec,\\\\n        address _euler,\\\\n        address _dToken\\\\n    )\\\\n        UniswapControllerHelper(_uniswapFactory)\\\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\\\n    {\\\\n        controller = _controller;\\\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\\\n        wPowerPerp = IController(_controller).wPowerPerp();\\\\n        weth = IController(_controller).weth();\\\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\\\n\\\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\\\n\\\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\\\n\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\\\n     * @return returns received selector\\\\n     */\\\\n    function onERC721Received(\\\\n        address,\\\\n        address,\\\\n        uint256,\\\\n        bytes memory\\\\n    ) public virtual override returns (bytes4) {\\\\n        return this.onERC721Received.selector;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {}\\\\n\\\\n    /**\\\\n     * @notice flash close position and buy long squeeth\\\\n     * @dev this function\\\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\\\n     */\\\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        _checkAccess(_params.vaultId);\\\\n\\\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\\\n\\\\n        wrapInternal(msg.value);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            _params.poolFee,\\\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\\\n            _params.maxToPay,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\\\n            abi.encode(_params)\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sell long wPowerPerp and flashswap mint short position\\\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\\\n     */\\\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        if (_params.vaultId != 0) {\\\\n            _checkAccess(_params.vaultId);\\\\n        }\\\\n\\\\n        wrapInternal(msg.value);\\\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\\\n        // flashswap and mint short position\\\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            _params.poolFee,\\\\n            totalAmountIn,\\\\n            _params.minToReceive,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\\\n            abi.encode(_params)\\\\n        );\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice close short position with user Uniswap v3 LP NFT\\\\n     * @dev user should approve this contract for Uni NFT transfer\\\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\\\n     */\\\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        _checkAccess(_params.vaultId);\\\\n\\\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\\\n            msg.sender,\\\\n            address(this),\\\\n            _params.tokenId\\\\n        );\\\\n\\\\n        wrapInternal(msg.value);\\\\n\\\\n        // close LP position\\\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n            nonfungiblePositionManager,\\\\n            ControllerHelperDataType.CloseUniLpParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: _params.liquidity,\\\\n                liquidityPercentage: _params.liquidityPercentage,\\\\n                amount0Min: _params.amount0Min,\\\\n                amount1Min: _params.amount1Min\\\\n            }),\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\\\n        ControllerHelperUtil.checkClosedLp(\\\\n            msg.sender,\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            0,\\\\n            _params.tokenId,\\\\n            _params.liquidityPercentage\\\\n        );\\\\n        // burn vault debt using amounts withdrawn from LP position\\\\n        _closeShortWithAmountsFromLp(\\\\n            _params.vaultId,\\\\n            wPowerPerpAmountInLp,\\\\n            _params.wPowerPerpAmountToBurn,\\\\n            _params.collateralToWithdraw,\\\\n            _params.limitPriceEthPerPowerPerp,\\\\n            _params.poolFee,\\\\n            _params.burnExactRemoved\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        _checkAccess(_params.vaultId);\\\\n\\\\n        wrapInternal(msg.value);\\\\n        _flashLoan(\\\\n            weth,\\\\n            _params.collateralToFlashloan,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\\\n            abi.encode(_params)\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\\\n     */\\\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\\\n        if (_params.vaultId != 0) {\\\\n            _checkAccess(_params.vaultId);\\\\n        }\\\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\\\n\\\\n        wrapInternal(msg.value);\\\\n\\\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            _params,\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        // if openeded new vault, transfer vault NFT to user\\\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\\\n     */\\\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        if (_params.vaultId != 0) {\\\\n            _checkAccess(_params.vaultId);\\\\n        }\\\\n\\\\n        wrapInternal(msg.value);\\\\n        _flashLoan(\\\\n            weth,\\\\n            _params.collateralToFlashloan,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\\\n            abi.encode(_params)\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\\\n     */\\\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\\\n            msg.sender,\\\\n            address(this),\\\\n            _params.tokenId\\\\n        );\\\\n\\\\n        // close LP NFT and get Weth and WPowerPerp amounts\\\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n            nonfungiblePositionManager,\\\\n            ControllerHelperDataType.CloseUniLpParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: _params.liquidity,\\\\n                liquidityPercentage: _params.liquidityPercentage,\\\\n                amount0Min: uint128(_params.amount0Min),\\\\n                amount1Min: uint128(_params.amount1Min)\\\\n            }),\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        ControllerHelperUtil.checkClosedLp(\\\\n            msg.sender,\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            0,\\\\n            _params.tokenId,\\\\n            _params.liquidityPercentage\\\\n        );\\\\n\\\\n        if (wPowerPerpAmountInLp > 0) {\\\\n            _exactInFlashSwap(\\\\n                wPowerPerp,\\\\n                weth,\\\\n                _params.poolFee,\\\\n                wPowerPerpAmountInLp,\\\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\\\n                \\\\\\\"\\\\\\\"\\\\n            );\\\\n        }\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice Rebalance LP nft through trading\\\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\\\n     */\\\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        wrapInternal(msg.value);\\\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\\\n            msg.sender,\\\\n            address(this),\\\\n            _params.tokenId\\\\n        );\\\\n        // close LP NFT and get Weth and WPowerPerp amounts\\\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n            nonfungiblePositionManager,\\\\n            ControllerHelperDataType.CloseUniLpParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: _params.liquidity,\\\\n                liquidityPercentage: 1e18,\\\\n                amount0Min: uint128(_params.amount0Min),\\\\n                amount1Min: uint128(_params.amount1Min)\\\\n            }),\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        ControllerHelperUtil.checkClosedLp(\\\\n            msg.sender,\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            0,\\\\n            _params.tokenId,\\\\n            1e18\\\\n        );\\\\n\\\\n        uint256 wethAmountDesired;\\\\n        uint256 wPowerPerpAmountDesired;\\\\n\\\\n        if (isWethToken0) {\\\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\\\n                _params.wPowerPerpPool,\\\\n                _params.wethAmountDesired,\\\\n                _params.wPowerPerpAmountDesired,\\\\n                _params.lowerTick,\\\\n                _params.upperTick,\\\\n                isWethToken0\\\\n            );\\\\n        } else {\\\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\\\n                _params.wPowerPerpPool,\\\\n                _params.wethAmountDesired,\\\\n                _params.wPowerPerpAmountDesired,\\\\n                _params.lowerTick,\\\\n                _params.upperTick,\\\\n                isWethToken0\\\\n            );\\\\n        }\\\\n\\\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\\\n            _exactOutFlashSwap(\\\\n                weth,\\\\n                wPowerPerp,\\\\n                _params.poolFee,\\\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\\\n                \\\\\\\"\\\\\\\"\\\\n            );\\\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\\\n            _exactInFlashSwap(\\\\n                wPowerPerp,\\\\n                weth,\\\\n                _params.poolFee,\\\\n                wPowerPerpExcess,\\\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\\\n                \\\\\\\"\\\\\\\"\\\\n            );\\\\n        }\\\\n\\\\n        // mint new position\\\\n        ControllerHelperUtil.lpWPowerPerpPool(\\\\n            nonfungiblePositionManager,\\\\n            _params.wPowerPerpPool,\\\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\\\n                recipient: msg.sender,\\\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\\\n                amount0Min: _params.amount0DesiredMin,\\\\n                amount1Min: _params.amount1DesiredMin,\\\\n                lowerTick: _params.lowerTick,\\\\n                upperTick: _params.upperTick\\\\n            })\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\\\n     * @param _vaultId vault ID\\\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\\\n     */\\\\n    function rebalanceLpInVault(\\\\n        uint256 _vaultId,\\\\n        uint256 _collateralToFlashloan,\\\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\\\n    ) external payable {\\\\n        // check ownership\\\\n        _checkAccess(_vaultId);\\\\n\\\\n        wrapInternal(msg.value);\\\\n        _flashLoan(\\\\n            weth,\\\\n            _collateralToFlashloan,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\\\n            abi.encode(_vaultId, _params)\\\\n        );\\\\n\\\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice checks if the msg.sender is the owener of the vault\\\\n     * @param _vaultId vault ID\\\\n     */\\\\n    function _checkAccess(uint256 _vaultId) internal view {\\\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice gets the shortAmount that has been minted from a vault\\\\n     * @param _vaultId vault ID\\\\n     * @return short amount from vault\\\\n     */\\\\n\\\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\\\n\\\\n        return vault.shortAmount;\\\\n    }\\\\n\\\\n    function _flashCallback(\\\\n        address _initiator,\\\\n        address, /*_asset*/\\\\n        uint256 _amount,\\\\n        uint8 _callSource,\\\\n        bytes memory _calldata\\\\n    ) internal override {\\\\n        if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\\\n        ) {\\\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\\\n                _calldata,\\\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\\\n            );\\\\n\\\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\\\n                controller,\\\\n                nonfungiblePositionManager,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                ControllerHelperDataType.MintAndLpParams({\\\\n                    recipient: address(this),\\\\n                    wPowerPerpPool: data.wPowerPerpPool,\\\\n                    vaultId: data.vaultId,\\\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\\\n                    collateralToDeposit: data.collateralToDeposit,\\\\n                    collateralToLp: data.collateralToLp,\\\\n                    amount0Min: data.amount0Min,\\\\n                    amount1Min: data.amount1Min,\\\\n                    lowerTick: data.lowerTick,\\\\n                    upperTick: data.upperTick\\\\n                }),\\\\n                isWethToken0\\\\n            );\\\\n\\\\n            // deposit Uni NFT token in vault\\\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                vaultId,\\\\n                0,\\\\n                _amount.add(data.collateralToWithdraw)\\\\n            );\\\\n\\\\n            // if openeded new vault, transfer vault NFT to user\\\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\\\n        ) {\\\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\\\n                _calldata,\\\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\\\n            );\\\\n\\\\n            IWETH9(weth).withdraw(_amount);\\\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\\\n\\\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\\\n\\\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n                nonfungiblePositionManager,\\\\n                ControllerHelperDataType.CloseUniLpParams({\\\\n                    tokenId: data.tokenId,\\\\n                    liquidity: data.liquidity,\\\\n                    liquidityPercentage: data.liquidityPercentage,\\\\n                    amount0Min: data.amount0Min,\\\\n                    amount1Min: data.amount1Min\\\\n                }),\\\\n                isWethToken0\\\\n            );\\\\n\\\\n            ControllerHelperUtil.checkClosedLp(\\\\n                _initiator,\\\\n                controller,\\\\n                nonfungiblePositionManager,\\\\n                data.vaultId,\\\\n                data.tokenId,\\\\n                data.liquidityPercentage\\\\n            );\\\\n\\\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\\\n            _closeShortWithAmountsFromLp(\\\\n                data.vaultId,\\\\n                wPowerPerpAmountInLp,\\\\n                data.wPowerPerpAmountToBurn,\\\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\\\n                data.limitPriceEthPerPowerPerp,\\\\n                data.poolFee,\\\\n                data.burnExactRemoved\\\\n            );\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\\\n        ) {\\\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\\\n                _calldata,\\\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\\\n            );\\\\n\\\\n            // deposit collateral into vault and withdraw LP NFT\\\\n            IWETH9(weth).withdraw(_amount);\\\\n            IController(controller).deposit{value: _amount}(vaultId);\\\\n            IController(controller).withdrawUniPositionToken(vaultId);\\\\n            for (uint256 i; i < data.length; i++) {\\\\n                if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\\\n                ) {\\\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\\\n                    );\\\\n\\\\n                    ControllerHelperUtil.increaseLpLiquidity(\\\\n                        controller,\\\\n                        nonfungiblePositionManager,\\\\n                        wPowerPerp,\\\\n                        increaseLiquidityParam.wPowerPerpPool,\\\\n                        vaultId,\\\\n                        increaseLiquidityParam,\\\\n                        isWethToken0\\\\n                    );\\\\n\\\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\\\n                ) {\\\\n                    // decrease liquidity in LP\\\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\\\n                    );\\\\n\\\\n                    ControllerHelperUtil.closeUniLp(\\\\n                        nonfungiblePositionManager,\\\\n                        ControllerHelperDataType.CloseUniLpParams({\\\\n                            tokenId: decreaseLiquidityParam.tokenId,\\\\n                            liquidity: decreaseLiquidityParam.liquidity,\\\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\\\n                        }),\\\\n                        isWethToken0\\\\n                    );\\\\n\\\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\\\n                    ControllerHelperUtil.checkClosedLp(\\\\n                        _initiator,\\\\n                        controller,\\\\n                        nonfungiblePositionManager,\\\\n                        vaultId,\\\\n                        decreaseLiquidityParam.tokenId,\\\\n                        decreaseLiquidityParam.liquidityPercentage\\\\n                    );\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\\\n                ) {\\\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\\\n                    );\\\\n\\\\n                    // make sure not to fail\\\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\\\n\\\\n                    ControllerHelperUtil.mintDepositInVault(\\\\n                        controller,\\\\n                        weth,\\\\n                        vaultId,\\\\n                        depositIntoVaultParams.wPowerPerpToMint,\\\\n                        depositIntoVaultParams.collateralToDeposit\\\\n                    );\\\\n                } else if (\\\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\\\n                ) {\\\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\\\n                    );\\\\n\\\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\\\n\\\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\\\n                            controller,\\\\n                            weth,\\\\n                            vaultId,\\\\n                            currentBalance,\\\\n                            withdrawFromVaultParams.collateralToWithdraw\\\\n                        );\\\\n                    } else {\\\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\\\n                            controller,\\\\n                            weth,\\\\n                            vaultId,\\\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\\\n                            withdrawFromVaultParams.collateralToWithdraw\\\\n                        );\\\\n                    }\\\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.MintAndLpParams)\\\\n                    );\\\\n\\\\n                    uint256 tokenId;\\\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\\\n                        controller,\\\\n                        nonfungiblePositionManager,\\\\n                        wPowerPerp,\\\\n                        weth,\\\\n                        mintAndLpParams,\\\\n                        isWethToken0\\\\n                    );\\\\n                    // deposit Uni NFT token in vault\\\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\\\n                ) {\\\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.GeneralSwapParams)\\\\n                    );\\\\n\\\\n                    require(\\\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\\\n                    );\\\\n\\\\n                    _exactInFlashSwap(\\\\n                        swapParams.tokenIn,\\\\n                        swapParams.tokenOut,\\\\n                        swapParams.poolFee,\\\\n                        swapParams.amountIn,\\\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\\\n                        \\\\\\\"\\\\\\\"\\\\n                    );\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\\\n                ) {\\\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.CollectFeesParams)\\\\n                    );\\\\n\\\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\\\n                        .CollectParams({\\\\n                            tokenId: collectFeesParams.tokenId,\\\\n                            recipient: address(this),\\\\n                            amount0Max: collectFeesParams.amount0Max,\\\\n                            amount1Max: collectFeesParams.amount0Max\\\\n                        });\\\\n\\\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\\\n                ) {\\\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\\\n                    );\\\\n\\\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\\\n                }\\\\n            }\\\\n\\\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _swapCallback(\\\\n        address _caller,\\\\n        address _tokenIn,\\\\n        address _pool,\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\\\n        ) {\\\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\\\n                _callData,\\\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\\\n            );\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                data.vaultId,\\\\n                data.wPowerPerpAmountToBurn,\\\\n                data.collateralToWithdraw\\\\n            );\\\\n\\\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\\\n        ) {\\\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\\\n                _callData,\\\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\\\n            );\\\\n\\\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\\\n                    controller,\\\\n                    weth,\\\\n                    data.vaultId,\\\\n                    data.wPowerPerpAmountToMint,\\\\n                    data.collateralToDeposit\\\\n                );\\\\n\\\\n                // this is a newly open vault, transfer to the user\\\\n                if (data.vaultId == 0)\\\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\\\n            }\\\\n\\\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\\\n        ) {\\\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\\\n        ) {\\\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\\\n        ) {\\\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\\\n                _callData,\\\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\\\n            );\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                data.vaultId,\\\\n                data.wPowerPerpAmountToBurn,\\\\n                data.collateralToWithdraw\\\\n            );\\\\n\\\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\\\n        ) {\\\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice wrap ETH to WETH\\\\n     * @param _amount amount to wrap\\\\n     */\\\\n    function wrapInternal(uint256 _amount) internal {\\\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\\\n    }\\\\n\\\\n    function _closeShortWithAmountsFromLp(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _wPowerPerpAmountToBurn,\\\\n        uint256 _collateralToWithdraw,\\\\n        uint256 _limitPriceEthPerPowerPerp,\\\\n        uint24 _poolFee,\\\\n        bool burnExactRemoved\\\\n    ) private {\\\\n        if (burnExactRemoved) {\\\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                _vaultId,\\\\n                _wPowerPerpAmount,\\\\n                _collateralToWithdraw\\\\n            );\\\\n        } else {\\\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\\\n                // swap needed wPowerPerp amount to close short position\\\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\\\n\\\\n                _exactOutFlashSwap(\\\\n                    weth,\\\\n                    wPowerPerp,\\\\n                    _poolFee,\\\\n                    wPowerPerpDeficit,\\\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\\\n                );\\\\n            } else {\\\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\\\n                ControllerHelperUtil.burnWithdrawFromVault(\\\\n                    controller,\\\\n                    weth,\\\\n                    _vaultId,\\\\n                    _wPowerPerpAmountToBurn,\\\\n                    _collateralToWithdraw\\\\n                );\\\\n\\\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\\\n                if (wPowerPerpExcess > 0) {\\\\n                    _exactInFlashSwap(\\\\n                        wPowerPerp,\\\\n                        weth,\\\\n                        _poolFee,\\\\n                        wPowerPerpExcess,\\\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\\\n                        \\\\\\\"\\\\\\\"\\\\n                    );\\\\n                }\\\\n            }\\\\n        }\\\\n\\\\n        // wrap ETH to WETH\\\\n        wrapInternal(address(this).balance);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe9649979188ed6661ec0511b25ef05748ae61abd4ffc1f716ca7e89b7faf333e\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/EulerControllerHelper.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: agpl-3.0\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IERC20Detailed} from \\\\\\\"../interfaces/IERC20Detailed.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\\\ninterface IDeferredLiquidityCheck {\\\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\\\n}\\\\n\\\\ninterface IExec {\\\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\\\n}\\\\n\\\\ninterface IEulerDToken {\\\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\\\n\\\\n    function repay(uint256 subAccountId, uint256 amount) external;\\\\n}\\\\n\\\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\\\n    using SafeMath for uint256;\\\\n\\\\n    address public immutable exec;\\\\n    address public immutable euler;\\\\n    address public immutable token;\\\\n    address public immutable dToken;\\\\n\\\\n    struct FlashloanCallbackData {\\\\n        address caller;\\\\n        address assetToBorrow;\\\\n        uint256 amountToBorrow;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    constructor(\\\\n        address _exec,\\\\n        address _euler,\\\\n        address _token,\\\\n        address _dToken\\\\n    ) {\\\\n        exec = _exec;\\\\n        euler = _euler;\\\\n        token = _token;\\\\n        dToken = _dToken;\\\\n    }\\\\n\\\\n    function _flashCallback(\\\\n        address _initiator,\\\\n        address _asset,\\\\n        uint256 _amount,\\\\n        uint8 _callSource,\\\\n        bytes memory _calldata\\\\n    ) internal virtual {}\\\\n\\\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\\\n        // sanity checks\\\\n        require(msg.sender == euler);\\\\n\\\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\\\n\\\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\\\n\\\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\\\n\\\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\\\n    }\\\\n\\\\n    /**\\\\n     */\\\\n    function _flashLoan(\\\\n        address _asset,\\\\n        uint256 _amount,\\\\n        uint8 _callSource,\\\\n        bytes memory _data\\\\n    ) internal {\\\\n        // Disable the liquidity check for \\\\\\\"this\\\\\\\" and call-back into onDeferredLiquidityCheck:\\\\n        IExec(exec).deferLiquidityCheck(\\\\n            address(this),\\\\n            abi.encode(\\\\n                FlashloanCallbackData({\\\\n                    caller: msg.sender,\\\\n                    assetToBorrow: _asset,\\\\n                    amountToBorrow: _amount,\\\\n                    callSource: _callSource,\\\\n                    callData: _data\\\\n                })\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6a7f3fef2c2eca5a4851e75c632eff2e7c28b4b244ad9fb0bbe2247efe1b395c\\\",\\\"license\\\":\\\"agpl-3.0\\\"},\\\"contracts/periphery/UniswapControllerHelper.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\\\\\";\\\\n\\\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\\\n    using Path for bytes;\\\\n    using SafeCast for uint256;\\\\n    using LowGasSafeMath for uint256;\\\\n    using LowGasSafeMath for int256;\\\\n\\\\n    /// @dev Uniswap factory address\\\\n    address public immutable factory;\\\\n\\\\n    struct SwapCallbackData {\\\\n        bytes path;\\\\n        address caller;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev constructor\\\\n     * @param _factory uniswap factory address\\\\n     */\\\\n    constructor(address _factory) {\\\\n        require(_factory != address(0));\\\\n        factory = _factory;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap swap callback function for flashswap\\\\n     * @param amount0Delta amount of token0\\\\n     * @param amount1Delta amount of token1\\\\n     * @param _data callback data encoded as SwapCallbackData struct\\\\n     */\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata _data\\\\n    ) external override {\\\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\\\n\\\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //ensure that callback comes from uniswap pool\\\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\\\n\\\\n        //determine the amount that needs to be repaid as part of the flashswap\\\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\\\n\\\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountIn amount to sell\\\\n     * @param _amountOutMinimum minimum amount to receive\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call\\\\n     */\\\\n    function _exactInFlashSwap(\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        uint24 _fee,\\\\n        uint256 _amountIn,\\\\n        uint256 _amountOutMinimum,\\\\n        uint8 _callSource,\\\\n        bytes memory _data\\\\n    ) internal returns (uint256) {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountOut = _exactInputInternal(\\\\n            _amountIn,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({\\\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\\\n                caller: msg.sender,\\\\n                callSource: _callSource,\\\\n                callData: _data\\\\n            })\\\\n        );\\\\n\\\\n        //slippage limit check\\\\n        require(amountOut >= _amountOutMinimum);\\\\n\\\\n        return amountOut;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountOut exact amount to receive\\\\n     * @param _amountInMaximum maximum amount to sell\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call\\\\n     */\\\\n    function _exactOutFlashSwap(\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        uint24 _fee,\\\\n        uint256 _amountOut,\\\\n        uint256 _amountInMaximum,\\\\n        uint8 _callSource,\\\\n        bytes memory _data\\\\n    ) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountIn = _exactOutputInternal(\\\\n            _amountOut,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({\\\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\\\n                caller: msg.sender,\\\\n                callSource: _callSource,\\\\n                callData: _data\\\\n            })\\\\n        );\\\\n\\\\n        //slippage limit check\\\\n        require(amountIn <= _amountInMaximum);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice function to be called by uniswap callback.\\\\n     * @dev this function should be overridden by the child contract\\\\n     * param _caller initial strategy function caller\\\\n     * param _tokenIn token address sold\\\\n     * param _tokenOut token address bought\\\\n     * param _fee pool fee\\\\n     * param _amountToPay amount to pay for the pool second token\\\\n     * param _callData arbitrary data assigned with the flashswap call\\\\n     * param _callSource function call source\\\\n     */\\\\n    function _swapCallback(\\\\n        address _caller,\\\\n        address _tokenIn,\\\\n        address _pool,\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal virtual {}\\\\n\\\\n    /**\\\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\\\n     * @param _amountIn amount of token to pay\\\\n     * @param _recipient recipient for receive\\\\n     * @param _sqrtPriceLimitX96 price limit\\\\n     * @return amount of token bought (amountOut)\\\\n     */\\\\n    function _exactInputInternal(\\\\n        uint256 _amountIn,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\\\n            _recipient,\\\\n            zeroForOne,\\\\n            _amountIn.toInt256(),\\\\n            _sqrtPriceLimitX96 == 0\\\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                : _sqrtPriceLimitX96,\\\\n            abi.encode(data)\\\\n        );\\\\n\\\\n        //determine the amountOut based on which token has a lower address\\\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\\\n     * @param _amountOut amount of token to receive\\\\n     * @param _recipient recipient for receive\\\\n     * @param _sqrtPriceLimitX96 price limit\\\\n     * @return amount of token sold (amountIn)\\\\n     */\\\\n    function _exactOutputInternal(\\\\n        uint256 _amountOut,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\\\n            _recipient,\\\\n            zeroForOne,\\\\n            -_amountOut.toInt256(),\\\\n            _sqrtPriceLimitX96 == 0\\\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                : _sqrtPriceLimitX96,\\\\n            abi.encode(data)\\\\n        );\\\\n\\\\n        //determine the amountIn and amountOut based on which token has a lower address\\\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\\\n        // it's technically possible to not receive the full output amount,\\\\n        // so if no price limit has been specified, require this possibility away\\\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\\\n\\\\n        return amountIn;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice returns the uniswap pool for the given token pair and fee\\\\n     * @dev the pool contract may or may not exist\\\\n     * @param tokenA address of first token\\\\n     * @param tokenB address of second token\\\\n     * @param fee fee tier for pool\\\\n     */\\\\n    function _getPool(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (address) {\\\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x91b5e0a2bc1ce71c0c614f89c6304c2d9ea5052120bdc88f0cf62f694afd284e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/lib/ControllerHelperDataType.sol\\\":{\\\"content\\\":\\\"pragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperDataType {\\\\n    using SafeMath for uint256;\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum CALLBACK_SOURCE {\\\\n        FLASH_W_MINT,\\\\n        FLASH_W_BURN,\\\\n        FLASH_SELL_LONG_W_MINT,\\\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\\\n        GENERAL_SWAP\\\\n    }\\\\n\\\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\\\n    enum RebalanceVaultNftType {\\\\n        IncreaseLpLiquidity,\\\\n        DecreaseLpLiquidity,\\\\n        DepositIntoVault,\\\\n        WithdrawFromVault,\\\\n        MintNewLp,\\\\n        generalSwap,\\\\n        CollectFees, \\\\n        DepositExistingNft\\\\n    }\\\\n    \\\\n    /// @dev params for flashswapWBurnBuyLong()\\\\n    struct FlashswapWBurnBuyLongParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\\\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev params for flashswapSellLongWMint()\\\\n    struct FlashSellLongWMintParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\\\n    struct SwapExactoutEthWPowerPerpData {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\\\n    }\\\\n\\\\n    /// @dev params for CloseShortWithUserNft()\\\\n    struct CloseShortWithUserNftParams {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity;  // liquidity amount in LP \\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;      // uniswap pool fee\\\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for wMintLp()\\\\n    struct MintAndLpParams {\\\\n        address recipient;  // recipient address\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 collateralToLp; // collateral amount to LP\\\\n        uint256 amount0Min; // minimum amount to LP of asset0\\\\n        uint256 amount1Min; // minimum amount to LP of asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for flashloanWMintDepositNft()\\\\n    struct FlashloanWMintLpDepositNftParams {\\\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\\\n        uint256 vaultId; // vault ID (could be zero)\\\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\\\n        uint256 amount0Min; // minimum amount of token0 to LP\\\\n        uint256 amount1Min; // minimum amount of token1 to LP\\\\n        int24 lowerTick; // range lower tick to LP in\\\\n        int24 upperTick; // range upper tick to LP in\\\\n    }\\\\n\\\\n    /// @dev params for flashloanCloseVaultLpNft()\\\\n    struct FlashloanCloseVaultLpNftParam {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity; // amount of liquidity in LP position\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for _closeUniLp() \\\\n    struct CloseUniLpParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\\\n    }\\\\n\\\\n    /// @dev params for sellAll()\\\\n    struct ReduceLiquidityAndSellParams {\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpWithoutVault()\\\\n    struct RebalanceLpWithoutVaultParams {\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\\\n        uint256 wethAmountDesired;  // WETH amount to LP\\\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\\\n    struct LpWPowerPerpPoolParams {\\\\n        address recipient;  // recipient address\\\\n        uint256 amount0Desired; // amount desired to LP for asset0\\\\n        uint256 amount1Desired; // amount desired to LP for asset1\\\\n        uint256 amount0Min; // amount min to LP for asset0\\\\n        uint256 amount1Min; // amount min to LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpInVault()\\\\n    struct RebalanceLpInVaultParams {\\\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\\\n        bytes data;\\\\n    }\\\\n\\\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\\\n    struct IncreaseLpLiquidityParams {\\\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 wethAmountToLp; // WETH amount to LP\\\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for decrease liquidity in LP position\\\\n    struct DecreaseLpLiquidityParams {  \\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for minting into vault\\\\n    struct DepositIntoVaultParams {\\\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\\\n    }\\\\n\\\\n    /// @dev struct for withdrawing from vault\\\\n    struct withdrawFromVaultParams {  \\\\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\\\n    }\\\\n\\\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\\\n    struct GeneralSwapParams {\\\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\\\n        uint256 amountIn; // amount to swap in\\\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\\\n    struct CollectFeesParams {\\\\n        uint256 tokenId;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\\\n    struct DepositExistingNftParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x04a47d47c3e0a1ec4e834f9aa466960200084fbdee47f0f513990b2c4708b02a\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/ControllerHelperUtil.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ControllerHelperDataType} from \\\\\\\"./ControllerHelperDataType.sol\\\\\\\";\\\\nimport {LiquidityAmounts} from \\\\\\\"./LiquidityAmounts.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"../../libs/TickMathExternal.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperUtil {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /**\\\\n     * @notice fully or partially close Uni v3 LP\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return withdrawn wPowerPerp and WETH amounts\\\\n     */\\\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\\\n            .DecreaseLiquidityParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\\\n                amount0Min: _params.amount0Min,\\\\n                amount1Min: _params.amount1Min,\\\\n                deadline: block.timestamp\\\\n            });\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\\\n\\\\n        uint256 wethAmount;\\\\n        uint256 _wPowerPerpAmount;\\\\n        (_isWethToken0)\\\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n                INonfungiblePositionManager.CollectParams({\\\\n                    tokenId: _params.tokenId,\\\\n                    recipient: address(this),\\\\n                    amount0Max: type(uint128).max,\\\\n                    amount1Max: type(uint128).max\\\\n                })\\\\n            )\\\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n            INonfungiblePositionManager.CollectParams({\\\\n                tokenId: _params.tokenId,\\\\n                recipient: address(this),\\\\n                amount0Max: type(uint128).max,\\\\n                amount1Max: type(uint128).max\\\\n            })\\\\n        );\\\\n\\\\n        return (_wPowerPerpAmount, wethAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\\\n     * @param _collateralToLp amount of ETH collateral to LP\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\\\n     * @param _lowerTick LP position lower tick\\\\n     * @param _upperTick LP position upper tick\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return exact amount0 and amount1 to be LPed\\\\n     */\\\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\\\n        uint256 amount0Desired; \\\\n        uint256 amount1Desired;\\\\n\\\\n        {\\\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\\\n        }\\\\n        \\\\n        return (amount0Desired, amount1Desired);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\\\n     * @param _controller wPowerPerp controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return _vaultId and tokenId\\\\n     */\\\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\\\n\\\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\\\n                \\\\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\\\n                _mintAndLpParams.vaultId,\\\\n                amountToMint,\\\\n                0\\\\n            );\\\\n        }\\\\n        // LP amount0Desired and amount1Desired in Uni v3\\\\n        uint256 uniTokenId = lpWPowerPerpPool(\\\\n            _nonfungiblePositionManager,\\\\n            _mintAndLpParams.wPowerPerpPool,\\\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\\\n                recipient: _mintAndLpParams.recipient,\\\\n                amount0Desired: amount0Desired,\\\\n                amount1Desired: amount1Desired,\\\\n                amount0Min: _mintAndLpParams.amount0Min,\\\\n                amount1Min: _mintAndLpParams.amount1Min,\\\\n                lowerTick: _mintAndLpParams.lowerTick,\\\\n                upperTick: _mintAndLpParams.upperTick\\\\n            })\\\\n        );\\\\n        return (_vaultId, uniTokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice increase liquidityin Uni v3 position\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault Id\\\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     */\\\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\\\n            (\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                int24 tickLower,\\\\n                int24 tickUpper,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                \\\\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\\\n\\\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n\\\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\\\n                    _vaultId,\\\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\\\n                    0\\\\n                );\\\\n            }\\\\n        }\\\\n\\\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\\\n            tokenId: _increaseLiquidityParam.tokenId,\\\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\\\n            deadline: block.timestamp\\\\n        });\\\\n\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp in vault\\\\n     * @param _controller controller address\\\\n     * @param _weth WETH address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\\\n     * @param _collateralToDeposit amount of collateral to deposit\\\\n     */\\\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\\\n\\\\n        uint256 vaultId = _vaultId;\\\\n        if (_wPowerPerpToMint > 0) {\\\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\\\n                _vaultId,\\\\n                _wPowerPerpToMint,\\\\n                0\\\\n            );\\\\n        } else {\\\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\\\n        }\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\\\n     * @param _controller controller address\\\\n     * @param _weth weth address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     */\\\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\\\n        IController(_controller).burnWPowerPerpAmount(\\\\n            _vaultId,\\\\n            _wPowerPerpToBurn,\\\\n            _collateralToWithdraw\\\\n        );\\\\n\\\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice LP into Uniswap V3 pool\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\\\n     */\\\\n    function lpWPowerPerpPool(\\\\n        address _nonfungiblePositionManager,\\\\n        address _wPowerPerpPool,\\\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\\\n    ) public returns (uint256) {\\\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\\\n            tickLower: int24(_params.lowerTick),\\\\n            tickUpper: int24(_params.upperTick),\\\\n            amount0Desired: _params.amount0Desired,\\\\n            amount1Desired: _params.amount1Desired,\\\\n            amount0Min: _params.amount0Min,\\\\n            amount1Min: _params.amount1Min,\\\\n            recipient: _params.recipient,\\\\n            deadline: block.timestamp\\\\n        });\\\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\\\n            mintParams\\\\n        );\\\\n        return tokenId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\\\n     * @param _user user address\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault ID\\\\n     * @param _tokenId Uni LP NFT id\\\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\\\n     */\\\\n    function checkClosedLp(\\\\n        address _user,\\\\n        address _controller,\\\\n        address _nonfungiblePositionManager,\\\\n        uint256 _vaultId,\\\\n        uint256 _tokenId,\\\\n        uint256 _liquidityPercentage\\\\n    ) public {\\\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\\\n                address(this),\\\\n                _user,\\\\n                _tokenId\\\\n            );\\\\n        } else {\\\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice send ETH and wPowerPerp\\\\n     * @param _weth WETH address\\\\n     * @param _wPowerPerp wPowerPerp address\\\\n     */\\\\n    function sendBack(address _weth, address _wPowerPerp) public {\\\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n        if (wPowerPerpBalance > 0) {\\\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x51c6185083d747a36ee8543219c0e7a326b866c0bdc113e82956cd4e226f7ba3\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/LiquidityAmounts.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"../../libs/SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\n\\\\n\\\\n/// @title Liquidity amount functions\\\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\\\nlibrary LiquidityAmounts {\\\\n    /// @notice Downcasts uint256 to uint128\\\\n    /// @param x The uint258 to be downcasted\\\\n    /// @return y The passed value, downcasted to uint128\\\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\\\n        require((y = uint128(x)) == x);\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount0 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount0(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount1 The amount1 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount1(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount of token0 being sent in\\\\n    /// @param amount1 The amount of token1 being sent in\\\\n    /// @return liquidity The maximum amount of liquidity received\\\\n    function getLiquidityForAmounts(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\\\n\\\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\\\n        } else {\\\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\\\n        }\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    function getAmount0ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            FullMath.mulDiv(\\\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\\\n                sqrtRatioBX96 - sqrtRatioAX96,\\\\n                sqrtRatioBX96\\\\n            ) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmount1ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n\\\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmountsForLiquidity(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\\\n        } else {\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        }\\\\n    }\\\\n\\\\n    function getAmountsFromLiquidity(        \\\\n        uint160 sqrtRatioX96,\\\\n        int24 currentTick,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (currentTick < tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else if (currentTick < tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtRatioX96,\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                sqrtRatioX96,\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            }\\\\n    \\\\n    }\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb4b0f464529a43f3ca7a9d6afc5976902c0a004649bdf3239ca77469d26b7cf2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101e06040523480156200001257600080fd5b5060405162006a3e38038062006a3e833981016040819052620000359162000679565b8282876001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200007157600080fd5b505afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac919062000655565b83876001600160a01b038116620000c257600080fd5b6001600160601b0319606091821b811660805294811b851660a05292831b841660c05290821b831660e052811b82166101005287901b166101405260408051634ea64a2160e11b815290516001600160a01b03881691639d4c9442916004808301926020929190829003018186803b1580156200013e57600080fd5b505afa15801562000153573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000179919062000655565b6001600160a01b0316610160816001600160a01b031660601b81525050856001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b158015620001d057600080fd5b505afa158015620001e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200020b919062000655565b6001600160a01b0316610180816001600160a01b031660601b81525050856001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200026257600080fd5b505afa15801562000277573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029d919062000655565b6001600160601b0319606091821b81166101a0529086901b166101c052604080516307f07b1360e41b815290516001600160a01b03881691637f07b130916004808301926020929190829003018186803b158015620002fb57600080fd5b505afa15801562000310573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000336919062000655565b6001600160a01b0316866001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200037957600080fd5b505afa1580156200038e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003b4919062000655565b6001600160a01b031610151561012081151560f81b81525050856001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b1580156200040757600080fd5b505afa1580156200041c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000442919062000655565b6001600160a01b031663095ea7b3866000196040518363ffffffff1660e01b81526004016200047392919062000736565b602060405180830381600087803b1580156200048e57600080fd5b505af1158015620004a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c99190620006f9565b50856001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200050457600080fd5b505afa15801562000519573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200053f919062000655565b6001600160a01b031663095ea7b3866000196040518363ffffffff1660e01b81526004016200057092919062000736565b602060405180830381600087803b1580156200058b57600080fd5b505af1158015620005a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c69190620006f9565b5060405163a22cb46560e01b81526001600160a01b0386169063a22cb46590620005f89089906001906004016200071b565b600060405180830381600087803b1580156200061357600080fd5b505af115801562000628573d6000803e3d6000fd5b505050505050505050506200074f565b80516001600160a01b03811681146200065057600080fd5b919050565b60006020828403121562000667578081fd5b620006728262000638565b9392505050565b60008060008060008060c0878903121562000692578182fd5b6200069d8762000638565b9550620006ad6020880162000638565b9450620006bd6040880162000638565b9350620006cd6060880162000638565b9250620006dd6080880162000638565b9150620006ed60a0880162000638565b90509295509295509295565b6000602082840312156200070b578081fd5b8151801515811462000672578182fd5b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6101205160f81c6101405160601c6101605160601c6101805160601c6101a05160601c6101c05160601c615fe162000a5d600039806102f452806103dc52806104cd52806108aa5280610b315280610cca5280610efc5280610f8652806110f1528061183f52806118d55280611a4152806120bc52806125eb528061274a5280612a5f5280612bff5280612d5552806132cb528061367e52508061074952806108275280610a385280610acf5280610bef5280610d0e5280610e67528061118252806111fc528061125e52806112c4528061136652806113d3528061177a5280611c0552806120fe52806122f5528061246852806128405280612e0b5280612f13528061310852806131d0528061330d528061349b528061355b528061384d528061392552806139a45280613a6a5280613b0b5280613c405280613cad5280613df5528061404e528061411d52508061076a52806108065280610a5a5280610c115280610cec5280610e895280611161528061121e52806112e652806113f452806116ae528061175952806120dd5280612a815280612ff352806132ec52806134db528061351b52806139c55280613aea5280613f165280613f86525080610dcc5280611e7252806123a25280613e915250806104ab5280610ca852806110cf5280611a1f528061209b528061224f52806122d452806124e65280612565528061272852806128bc528061293b5280612a3d5280612b145280612d335280612ef152806130e652806131ae52806132aa52806133da5280613789528061382b52806139035280613a485280613c1e5280613dd352806140fb52806144985250806103ff528061053d52806105b852806106a852806108f252806109245280610d32528061100d528061195e52806121a4528061265b5280612aa85280612c6d528061332f5250806114b052806116195280611aea525080611bdb52508061146c52806115695280611b0e5250806117d85280611f145250806117fc5280611b7752806147505250615fe16000f3fe6080604052600436106101125760003560e01c8063a15db5c5116100a5578063d8fa26f011610074578063db661b7111610059578063db661b711461027a578063fa461e331461028f578063fc0c546a146102af57610119565b8063d8fa26f014610252578063d9d7858a1461026557610119565b8063a15db5c5146101e8578063bc638a7914610208578063c1c0e9c41461021b578063c45a01551461023d57610119565b80633ca8402b116100e15780633ca8402b1461018f5780634fc5864f146101af57806383b17e4d146101c2578063923247ae146101d557610119565b8063150b7a021461011e57806315d23b04146101545780632ef1f08214610169578063334cc3651461017c57610119565b3661011957005b600080fd5b34801561012a57600080fd5b5061013e610139366004614aaf565b6102c4565b60405161014b9190615b22565b60405180910390f35b6101676101623660046151a6565b6102d4565b005b610167610177366004615506565b610ab8565b61016761018a3660046150fe565b610c39565b34801561019b57600080fd5b506101676101aa3660046151b8565b610ee5565b6101676101bd366004614ea3565b611246565b6101676101d0366004614c3e565b611341565b6101676101e3366004614db7565b61139d565b3480156101f457600080fd5b50610167610203366004614b51565b611461565b610167610216366004614db7565b61167d565b34801561022757600080fd5b506102306117d6565b60405161014b91906156ad565b34801561024957600080fd5b506102306117fa565b610167610260366004614c3e565b61181e565b34801561027157600080fd5b50610230611ae8565b34801561028657600080fd5b50610230611b0c565b34801561029b57600080fd5b506101676102aa366004614bc3565b611b30565b3480156102bb57600080fd5b50610230611bd9565b630a85bd0160e11b949350505050565b6102dd34611bfd565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061033190339030906020870135906004016156c1565b600060405180830381600087803b15801561034b57600080fd5b505af115801561035f573d6000803e3d6000fd5b50506040805160a08101825260208086013582528583013590820152670de0b6b3a7640000818301526001600160801b0361010086013581166060830152610120860135166080820152905163760a3f2b60e11b8152600093507385F983af83101600672180Dfc1d840827c4759B5925063ec147e5691610427917f000000000000000000000000000000000000000000000000000000000000000091907f000000000000000000000000000000000000000000000000000000000000000090600401615a6c565b604080518083038186803b15801561043e57600080fd5b505af4158015610452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104769190614ba0565b50604051630725e4e160e31b81529091507385F983af83101600672180Dfc1d840827c4759B59063392f2708906105089033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a013590670de0b6b3a7640000906004016156e5565b60006040518083038186803b15801561052057600080fd5b505af4158015610534573d6000803e3d6000fd5b505050506000807f000000000000000000000000000000000000000000000000000000000000000015610651577385F983af83101600672180Dfc1d840827c4759B563b573fa8b6105886020870187614a77565b608087013560608801356105a46101608a016101408b01614b84565b6105b66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016105f896959493929190615ae7565b604080518083038186803b15801561060f57600080fd5b505af4158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190614ba0565b909250905061073c565b7385F983af83101600672180Dfc1d840827c4759B563b573fa8b6106786020870187614a77565b608087013560608801356106946101608a016101408b01614b84565b6106a66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016106e896959493929190615ae7565b604080518083038186803b1580156106ff57600080fd5b505af4158015610713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107379190614ba0565b925090505b828111156107eb576107e67f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061079b6101a0880161018089016153db565b6107a58588611c61565b6107cf670de0b6b3a76400006107c96107be898c611c61565b60e08d013590611cc3565b90611d23565b600460405180602001604052806000815250611d8a565b61088e565b8281101561088e5760006107ff8483611c61565b905061088b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006108586101a089016101808a016153db565b84610873670de0b6b3a76400006107c960e08d013584611cc3565b60035b60405180602001604052806000815250611dee565b50505b7385F983af83101600672180Dfc1d840827c4759B563aee2533b7f00000000000000000000000000000000000000000000000000000000000000006108d66020880188614a77565b6040518060e00160405280336001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000061091b578661091d565b875b81526020017f000000000000000000000000000000000000000000000000000000000000000061094d578761094f565b865b815260a08a0135602082015260c08a0135604082015260600161097a6101608b016101408c01614b84565b60020b81526020016109946101808b016101608c01614b84565b60020b8152506040518463ffffffff1660e01b81526004016109b89392919061596c565b60206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0891906153f7565b506040516328bb252f60e11b81527385F983af83101600672180Dfc1d840827c4759B5906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610a9a57600080fd5b505af4158015610aae573d6000803e3d6000fd5b5050505050505050565b610ac184611e61565b610aca34611bfd565b610b1a7f0000000000000000000000000000000000000000000000000000000000000000846008878686604051602001610b0693929190615dc6565b604051602081830303815290604052611f12565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190610b669030906004016156ad565b60206040518083038186803b158015610b7e57600080fd5b505afa158015610b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb691906153f7565b15610bc057600080fd5b6040516328bb252f60e11b81527385F983af83101600672180Dfc1d840827c4759B5906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b604081013515610c5057610c508160400135611e61565b610c62608082013560a0830135611fe8565b3414610c6d57600080fd5b610c7634611bfd565b6040516308e6940f60e41b81526000907385F983af83101600672180Dfc1d840827c4759B590638e6940f090610d5a907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009089907f000000000000000000000000000000000000000000000000000000000000000090600401615738565b604080518083038186803b158015610d7157600080fd5b505af4158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190614ba0565b5090506040820135610e3857604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610e05903090339086906004016156c1565b600060405180830381600087803b158015610e1f57600080fd5b505af1158015610e33573d6000803e3d6000fd5b505050505b6040516328bb252f60e11b81527385F983af83101600672180Dfc1d840827c4759B5906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610ec957600080fd5b505af4158015610edd573d6000803e3d6000fd5b505050505050565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610f3690339030908635906004016156c1565b600060405180830381600087803b158015610f5057600080fd5b505af1158015610f64573d6000803e3d6000fd5b5050505060007385F983af83101600672180Dfc1d840827c4759B563ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a00160405280866000013581526020018660200135815260200186604001358152602001866060016020810190610fe191906153bf565b6001600160801b03168152602001610fff60a08801608089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161104a93929190615a6c565b604080518083038186803b15801561106157600080fd5b505af4158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190614ba0565b5060408051630725e4e160e31b81529192507385F983af83101600672180Dfc1d840827c4759B59163392f2708916111239133917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000916000918a35918b0135906004016156e5565b60006040518083038186803b15801561113b57600080fd5b505af415801561114f573d6000803e3d6000fd5b505050506000811115610e38576111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006111b160e0860160c087016153db565b84610873670de0b6b3a76400006107c960a08a013584611cc3565b506040516328bb252f60e11b81527385F983af83101600672180Dfc1d840827c4759B5906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b6112508135611e61565b61125934611bfd565b6112957f000000000000000000000000000000000000000000000000000000000000000060a0830135600784604051602001610b069190615c01565b6040516328bb252f60e11b81527385F983af83101600672180Dfc1d840827c4759B5906351764a5e9061130e907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b15801561132657600080fd5b505af415801561133a573d6000803e3d6000fd5b5050505050565b602081013515611358576113588160200135611e61565b61136134611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000006080830135600684604051602001610b069190615cca565b6113a78135611e61565b6113b5606082013534611fe8565b816080013511156113c557600080fd5b6113ce34611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061142360c0850160a086016153db565b61143560208601356040870135611fe8565b608086013560018760405160200161144d9190615ba0565b604051602081830303815290604052611d8a565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461149657600080fd5b6000818060200190518101906114ac9190614ded565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ecbcdab600083604001516040518363ffffffff1660e01b8152600401611501929190615b4f565b600060405180830381600087803b15801561151b57600080fd5b505af115801561152f573d6000803e3d6000fd5b5050505061155481600001518260200151836040015184606001518560800151612042565b80602001516001600160a01b031663095ea7b37f000000000000000000000000000000000000000000000000000000000000000083604001516040518363ffffffff1660e01b81526004016115aa929190615ace565b602060405180830381600087803b1580156115c457600080fd5b505af11580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614b35565b50604080820151905163d8aed14560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163d8aed1459161164f91600091600401615b4f565b600060405180830381600087803b15801561166957600080fd5b505af1158015610edd573d6000803e3d6000fd5b80351561168e5761168e8135611e61565b61169734611bfd565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906116eb90339030906060870135906004016156c1565b602060405180830381600087803b15801561170557600080fd5b505af1158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190614b35565b50600061175260208301356060840135611fe8565b90506111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006117a960c0860160a087016153db565b8460808701356002886040516020016117c29190615ba0565b604051602081830303815290604052611dee565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6118288135611e61565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061187c90339030906020870135906004016156c1565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050506118b734611bfd565b60007385F983af83101600672180Dfc1d840827c4759B563ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200135815260200186604001358152602001866060013581526020018660e001602081019061193091906153bf565b6001600160801b03168152602001611950610120880161010089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161199b93929190615a6c565b604080518083038186803b1580156119b257600080fd5b505af41580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614ba0565b50604051630725e4e160e31b81529091507385F983af83101600672180Dfc1d840827c4759B59063392f270890611a789033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a01359060608b0135906004016156e5565b60006040518083038186803b158015611a9057600080fd5b505af4158015611aa4573d6000803e3d6000fd5b50610e389250508335905082608085013560a086013560c0870135611ad161014089016101208a016153db565b611ae36101608a016101408b01614b19565b6138b5565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000841380611b3f5750600083135b611b4857600080fd5b6000611b56828401846151c9565b90506000806000611b6a8460000151613b58565b9250925092506000611b9e7f0000000000000000000000000000000000000000000000000000000000000000858585613b89565b90506000808a13611baf5788611bb1565b895b9050611bcd86602001518684848a606001518b60400151613ba8565b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8015611c5e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166957600080fd5b50565b600082821115611cb8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600082611cd257506000611cbd565b82820282848281611cdf57fe5b0414611d1c5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f8b6021913960400191505060405180910390fd5b9392505050565b6000808211611d79576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611d8257fe5b049392505050565b6000611ddf8530600060405180608001604052808c8c8f604051602001611db393929190615644565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526141e7565b905083811115610aae57600080fd5b600080611e448630600060405180608001604052808e8d8f604051602001611e1893929190615644565b60408051601f1981840301815291815290825233602083015260ff8b1690820152606001889052614354565b905084811015611e5357600080fd5b90505b979650505050505050565b6040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611eaf908590600401615dbd565b60206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190614a93565b6001600160a01b031614611c5e57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060a00160405280336001600160a01b03168152602001886001600160a01b031681526020018781526020018660ff16815260200185815250604051602001611f8e9190615bae565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611fba929190615a4a565b600060405180830381600087803b158015611fd457600080fd5b505af1158015610aae573d6000803e3d6000fd5b600082820183811015611d1c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60068260ff16600981111561205357fe5b600981111561205e57fe5b14156124165760008180602001905181019061207a9190614f6c565b90506000807385F983af83101600672180Dfc1d840827c4759B5638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000604051806101400160405280306001600160a01b031681526020018a600001516001600160a01b031681526020018a6020015181526020018a6040015181526020018a6060015181526020018a60a0015181526020018a60e0015181526020018a610100015181526020018a610120015160020b81526020018a610140015160020b8152507f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016121e496959493929190615818565b604080518083038186803b1580156121fb57600080fd5b505af415801561220f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122339190614ba0565b6040516348dc69a560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906122869085908590600401615b4f565b600060405180830381600087803b1580156122a057600080fd5b505af11580156122b4573d6000803e3d6000fd5b505050507385F983af83101600672180Dfc1d840827c4759B56363410a867f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085600061232e8960c001518d611fe890919063ffffffff16565b6040518663ffffffff1660e01b815260040161234e9594939291906159df565b60006040518083038186803b15801561236657600080fd5b505af415801561237a573d6000803e3d6000fd5b5050505082602001516000141561240e57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906123db9030908c9087906004016156c1565b600060405180830381600087803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050505b50505061133a565b60078260ff16600981111561242757fe5b600981111561243257fe5b14156127eb5760008180602001905181019061244e9190614eb5565b604051632e1a7d4d60e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061249d908790600401615dbd565b600060405180830381600087803b1580156124b757600080fd5b505af11580156124cb573d6000803e3d6000fd5b5050825160405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063b6b55f259250879161251d91600401615dbd565b6000604051808303818588803b15801561253657600080fd5b505af115801561254a573d6000803e3d6000fd5b5050835160405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016945063713d517f935061259b9250600401615dbd565b600060405180830381600087803b1580156125b557600080fd5b505af11580156125c9573d6000803e3d6000fd5b5050505060007385F983af83101600672180Dfc1d840827c4759B563ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200151815260200186604001518152602001866060015181526020018661010001516001600160801b031681526020018661012001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161269893929190615a6c565b604080518083038186803b1580156126af57600080fd5b505af41580156126c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e79190614ba0565b50825160208401516060850151604051630725e4e160e31b81529394507385F983af83101600672180Dfc1d840827c4759B59363392f270893612775938d937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000939291906004016156e5565b60006040518083038186803b15801561278d57600080fd5b505af41580156127a1573d6000803e3d6000fd5b505050506127e482600001518284608001516127ce8660a001518760c00151611fe890919063ffffffff16565b8660e001518761014001518861016001516138b5565b505061133a565b60088260ff1660098111156127fc57fe5b600981111561280757fe5b141561133a5760008082806020019051810190612824919061540f565b604051632e1a7d4d60e01b815291935091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612875908890600401615dbd565b600060405180830381600087803b15801561288f57600080fd5b505af11580156128a3573d6000803e3d6000fd5b505060405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063b6b55f25915087906128f5908690600401615dbd565b6000604051808303818588803b15801561290e57600080fd5b505af1158015612922573d6000803e3d6000fd5b505060405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063713d517f925061297391508590600401615dbd565b600060405180830381600087803b15801561298d57600080fd5b505af11580156129a1573d6000803e3d6000fd5b5050505060005b81518110156137fb5760008282815181106129bf57fe5b60200260200101516000015160078111156129d657fe5b1415612b895760008282815181106129ea57fe5b602002602001015160200151806020019051810190612a09919061507c565b8051604051637a04dbd760e01b81529192507385F983af83101600672180Dfc1d840827c4759B591637a04dbd791612ad0917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091908b9089907f0000000000000000000000000000000000000000000000000000000000000000906004016158d4565b60006040518083038186803b158015612ae857600080fd5b505af4158015612afc573d6000803e3d6000fd5b5050505060208101516040516348dc69a560e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916391b8d34a91612b51918891600401615b4f565b600060405180830381600087803b158015612b6b57600080fd5b505af1158015612b7f573d6000803e3d6000fd5b50505050506137f3565b6001828281518110612b9757fe5b6020026020010151600001516007811115612bae57fe5b1415612dad576000828281518110612bc257fe5b602002602001015160200151806020019051810190612be19190614cbc565b90507385F983af83101600672180Dfc1d840827c4759B563ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a0016040528085600001518152602001856020015181526020018560400151815260200185606001516001600160801b0316815260200185608001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401612caa93929190615a6c565b604080518083038186803b158015612cc157600080fd5b505af4158015612cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf99190614ba0565b505080516040808301519051630725e4e160e31b81527385F983af83101600672180Dfc1d840827c4759B59263392f270892612d81928e927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c9291906004016156e5565b60006040518083038186803b158015612d9957600080fd5b505af4158015612b7f573d6000803e3d6000fd5b6002828281518110612dbb57fe5b6020026020010151600001516007811115612dd257fe5b1415612f95576000828281518110612de657fe5b602002602001015160200151806020019051810190612e059190614d6f565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612e5591906156ad565b60206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906153f7565b90508160200151811015612ebb57602082018190525b81516020830151604051639f70f9e560e01b81527385F983af83101600672180Dfc1d840827c4759B592639f70f9e592612f3d927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60206040518083038186803b158015612f5557600080fd5b505af4158015612f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8d91906153f7565b5050506137f3565b6003828281518110612fa357fe5b6020026020010151600001516007811115612fba57fe5b1415613232576000828281518110612fce57fe5b602002602001015160200151806020019051810190612fed9190615370565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161303d91906156ad565b60206040518083038186803b15801561305557600080fd5b505afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d91906153f7565b905081604001511561316b5760006130a486614493565b9050818110156130b2578091505b60208301516040516331a0854360e11b81527385F983af83101600672180Dfc1d840827c4759B5916363410a8691613135917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918c918991906004016159df565b60006040518083038186803b15801561314d57600080fd5b505af4158015613161573d6000803e3d6000fd5b505050505061322b565b8151811015613178578082525b815160208301516040516331a0854360e11b81527385F983af83101600672180Dfc1d840827c4759B5926363410a86926131fa927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60006040518083038186803b15801561321257600080fd5b505af4158015613226573d6000803e3d6000fd5b505050505b50506137f3565b600482828151811061324057fe5b602002602001015160000151600781111561325757fe5b141561343f57600082828151811061326b57fe5b60200260200101516020015180602001905181019061328a9190615110565b905060007385F983af83101600672180Dfc1d840827c4759B5638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000877f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b815260040161336f96959493929190615818565b604080518083038186803b15801561338657600080fd5b505af415801561339a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133be9190614ba0565b6040516348dc69a560e11b815291965091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906134119088908590600401615b4f565b600060405180830381600087803b15801561342b57600080fd5b505af1158015613226573d6000803e3d6000fd5b600582828151811061344d57fe5b602002602001015160000151600781111561346457fe5b14156135e157600082828151811061347857fe5b6020026020010151602001518060200190518101906134979190615007565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561351357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b8061359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b61359c57600080fd5b61322b81600001518260200151836080015184604001516135da670de0b6b3a76400006107c988604001518960600151611cc390919063ffffffff16565b6009610876565b60068282815181106135ef57fe5b602002602001015160000151600781111561360657fe5b141561371557600082828151811061361a57fe5b6020026020010151602001518060200190518101906136399190614c5a565b604080516080810182528251815230602080830191909152830180516001600160801b03908116838501529051166060820152905163fc6f786560e01b8152919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fc6f7865906136bb908490600401615b5d565b6040805180830381600087803b1580156136d457600080fd5b505af11580156136e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370c9190614ba0565b505050506137f3565b600782828151811061372357fe5b602002602001015160000151600781111561373a57fe5b14156137f357600082828151811061374e57fe5b60200260200101516020015180602001905181019061376d9190614d34565b80516040516348dc69a560e11b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916391b8d34a916137bf91889190600401615b4f565b600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b50505050505b6001016129a8565b506040516331a0854360e11b81527385F983af83101600672180Dfc1d840827c4759B5906363410a869061387c907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009087906000908c906004016159df565b60006040518083038186803b15801561389457600080fd5b505af41580156138a8573d6000803e3d6000fd5b5050505050505050505050565b80156139895760006138c688614493565b9050868110156138d4578096505b6040516331a0854360e11b81527385F983af83101600672180Dfc1d840827c4759B5906363410a8690613953907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908d908d908c906004016159df565b60006040518083038186803b15801561396b57600080fd5b505af415801561397f573d6000803e3d6000fd5b5050505050613b46565b84861015613a1957600061399d8688611c61565b9050613a137f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085846139fc670de0b6b3a76400006107c98b84611cc3565b60058e8d8d60405160200161144d93929190615697565b50613b46565b6040516331a0854360e11b81527385F983af83101600672180Dfc1d840827c4759B5906363410a8690613a98907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c908b908b906004016159df565b60006040518083038186803b158015613ab057600080fd5b505af4158015613ac4573d6000803e3d6000fd5b505050506000613add8688611c6190919063ffffffff16565b90508015613b4457613b427f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008584610873670de0b6b3a76400006107c98b84611cc3565b505b505b613b4f47611bfd565b50505050505050565b60008080613b668482614548565b9250613b73846014614614565b9050613b80846017614548565b91509193909250565b6000613b9f85613b9a8686866146d0565b614726565b95945050505050565b60018160ff166009811115613bb957fe5b6009811115613bc457fe5b1415613d3f57600082806020019051810190613be09190614dd2565b8051602082015160608301516040516331a0854360e11b81529394507385F983af83101600672180Dfc1d840827c4759B5936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60006040518083038186803b158015613c8057600080fd5b505af4158015613c94573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb9150613ce69088908890600401615ace565b602060405180830381600087803b158015613d0057600080fd5b505af1158015613d14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d389190614b35565b5050610edd565b60028160ff166009811115613d5057fe5b6009811115613d5b57fe5b1415613f4d57600082806020019051810190613d779190614dd2565b9050600081602001511180613d90575060008160400151115b15613eff57805160208201516040808401519051639f70f9e560e01b81526000937385F983af83101600672180Dfc1d840827c4759B593639f70f9e593613e21937f0000000000000000000000000000000000000000000000000000000000000000937f000000000000000000000000000000000000000000000000000000000000000093909290916004016159df565b60206040518083038186803b158015613e3957600080fd5b505af4158015613e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7191906153f7565b8251909150613efd57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613eca9030908c9086906004016156c1565b600060405180830381600087803b158015613ee457600080fd5b505af1158015613ef8573d6000803e3d6000fd5b505050505b505b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ce69088908890600401615ace565b60038160ff166009811115613f5e57fe5b6009811115613f6957fe5b14156140155760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b602060405180830381600087803b158015613fd757600080fd5b505af1158015613feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400f9190614b35565b50610edd565b60048160ff16600981111561402657fe5b600981111561403157fe5b14156140855760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b60058160ff16600981111561409657fe5b60098111156140a157fe5b1415614145576000828060200190518101906140bd9190615287565b8051602082015160408084015190516331a0854360e11b81529394507385F983af83101600672180Dfc1d840827c4759B5936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60098160ff16600981111561415657fe5b600981111561416157fe5b1415610edd5760405163a9059cbb60e01b81526001600160a01b0386169063a9059cbb906141959087908790600401615ace565b602060405180830381600087803b1580156141af57600080fd5b505af11580156141c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4f9190614b35565b6000806000806141fa8560000151613b58565b919450925090506001600160a01b038084169083161060008061421e858786614749565b6001600160a01b031663128acb088b856142378f614787565b6000036001600160a01b038e161561424f578d614275565b8761426e5773fffd8963efd1fc6a506488495d951d5263988d25614275565b6401000276a45b8d6040516020016142869190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142b5959493929190615a10565b6040805180830381600087803b1580156142ce57600080fd5b505af11580156142e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143069190614ba0565b915091506000808461431c578284600003614322565b83836000035b915091508a6001600160a01b031660001415614344578c811461434457600080fd5b509b9a5050505050505050505050565b6000806000806143678560000151613b58565b919450925090506001600160a01b038083169084161060008061438b868686614749565b6001600160a01b031663128acb088b856143a48f614787565b6001600160a01b038e16156143b9578d6143df565b876143d85773fffd8963efd1fc6a506488495d951d5263988d256143df565b6401000276a45b8d6040516020016143f09190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161441f959493929190615a10565b6040805180830381600087803b15801561443857600080fd5b505af115801561444c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144709190614ba0565b915091508261447f5781614481565b805b6000039b9a5050505050505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c64ea4a846040518263ffffffff1660e01b81526004016144e29190615dbd565b60806040518083038186803b1580156144fa57600080fd5b505afa15801561450e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453291906152dc565b606001516001600160801b03169150505b919050565b6000818260140110156145a2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b81601401835110156145fb576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b60008182600301101561466e576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156146c7576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6146d8614899565b826001600160a01b0316846001600160a01b031611156146f6579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614732838361479d565b9050336001600160a01b03821614611cbd57600080fd5b600061477f7f000000000000000000000000000000000000000000000000000000000000000061477a8686866146d0565b61479d565b949350505050565b6000600160ff1b821061479957600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b0316106147c557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561454381615f16565b805161454381615f16565b803561454381615f2b565b805161454381615f2b565b600082601f8301126148f5578081fd5b813561490861490382615ec4565b615ea0565b81815284602083860101111561491c578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614946578081fd5b815161495461490382615ec4565b818152846020838601011115614968578283fd5b61477f826020830160208701615ee6565b803561454381615f46565b805161454381615f46565b600061016082840312156149a1578081fd5b50919050565b600060c082840312156149a1578081fd5b600060c082840312156149c9578081fd5b60405160c0810181811067ffffffffffffffff821117156149e657fe5b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151614a2881615f6a565b60a0919091015292915050565b803561454381615f55565b805161454381615f55565b803561454381615f6a565b805161454381615f6a565b803561454381615f7b565b805161454381615f7b565b600060208284031215614a88578081fd5b8135611d1c81615f16565b600060208284031215614aa4578081fd5b8151611d1c81615f16565b60008060008060808587031215614ac4578283fd5b8435614acf81615f16565b93506020850135614adf81615f16565b925060408501359150606085013567ffffffffffffffff811115614b01578182fd5b614b0d878288016148e5565b91505092959194509250565b600060208284031215614b2a578081fd5b8135611d1c81615f2b565b600060208284031215614b46578081fd5b8151611d1c81615f2b565b600060208284031215614b62578081fd5b813567ffffffffffffffff811115614b78578182fd5b61477f848285016148e5565b600060208284031215614b95578081fd5b8135611d1c81615f46565b60008060408385031215614bb2578182fd5b505080516020909101519092909150565b60008060008060608587031215614bd8578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614bfd578384fd5b818701915087601f830112614c10578384fd5b813581811115614c1e578485fd5b886020828501011115614c2f578485fd5b95989497505060200194505050565b60006101608284031215614c50578081fd5b611d1c838361498f565b600060608284031215614c6b578081fd5b6040516060810181811067ffffffffffffffff82111715614c8857fe5b604052825181526020830151614c9d81615f55565b60208201526040830151614cb081615f55565b60408201529392505050565b600060a08284031215614ccd578081fd5b60405160a0810181811067ffffffffffffffff82111715614cea57fe5b80604052508251815260208301516020820152604083015160408201526060830151614d1581615f55565b60608201526080830151614d2881615f55565b60808201529392505050565b600060208284031215614d45578081fd5b6040516020810181811067ffffffffffffffff82111715614d6257fe5b6040529151825250919050565b600060408284031215614d80578081fd5b6040516040810181811067ffffffffffffffff82111715614d9d57fe5b604052825181526020928301519281019290925250919050565b600060c08284031215614dc8578081fd5b611d1c83836149a7565b600060c08284031215614de3578081fd5b611d1c83836149b8565b600060208284031215614dfe578081fd5b815167ffffffffffffffff80821115614e15578283fd5b9083019060a08286031215614e28578283fd5b60405160a081018181108382111715614e3d57fe5b604052614e49836148c4565b8152614e57602084016148c4565b602082015260408301516040820152614e7260608401614a6c565b6060820152608083015182811115614e88578485fd5b614e9487828601614936565b60808301525095945050505050565b600061018082840312156149a1578081fd5b6000610180808385031215614ec8578182fd5b614ed181615ea0565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100614f2b818501614a40565b90820152610120614f3d848201614a40565b90820152610140614f4f848201614a56565b90820152610160614f618482016148da565b908201529392505050565b6000610160808385031215614f7f578182fd5b614f8881615ea0565b9050614f93836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120614ff5818501614984565b90820152610140614f61848201614984565b600060a08284031215615018578081fd5b60405160a0810181811067ffffffffffffffff8211171561503557fe5b604052825161504381615f16565b8152602083015161505381615f16565b8060208301525060408301516040820152606083015160608201526080830151614d2881615f6a565b600060e0828403121561508d578081fd5b60405160e0810181811067ffffffffffffffff821117156150aa57fe5b6040526150b6836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600061014082840312156149a1578081fd5b6000610140808385031215615123578182fd5b61512c81615ea0565b9050615137836148c4565b8152615145602084016148c4565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100615194818501614984565b90820152610120614f61848201614984565b60006101a082840312156149a1578081fd5b600060e082840312156149a1578081fd5b6000602082840312156151da578081fd5b813567ffffffffffffffff808211156151f1578283fd5b9083019060808286031215615204578283fd5b60405160808101818110838211171561521957fe5b60405282358281111561522a578485fd5b615236878286016148e5565b825250615245602084016148b9565b602082015261525660408401614a61565b604082015260608301358281111561526c578485fd5b615278878286016148e5565b60608301525095945050505050565b600060608284031215615298578081fd5b6040516060810181811067ffffffffffffffff821117156152b557fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000608082840312156152ed578081fd5b6040516080810181811067ffffffffffffffff8211171561530a57fe5b604052825161531881615f16565b8152602083015163ffffffff81168114615330578283fd5b602082015260408301516bffffffffffffffffffffffff81168114615353578283fd5b604082015261536460608401614a40565b60608201529392505050565b600060608284031215615381578081fd5b6040516060810181811067ffffffffffffffff8211171561539e57fe5b806040525082518152602083015160208201526040830151614cb081615f2b565b6000602082840312156153d0578081fd5b8135611d1c81615f55565b6000602082840312156153ec578081fd5b8135611d1c81615f6a565b600060208284031215615408578081fd5b5051919050565b60008060408385031215615421578182fd5b8251915060208084015167ffffffffffffffff80821115615440578384fd5b818601915086601f830112615453578384fd5b81518181111561545f57fe5b61546c8485830201615ea0565b81815284810190848601875b848110156154f557815187016040818e03601f1901121561549757898afd5b6040516040810181811089821117156154ac57fe5b604052818a01516154bc81615f39565b81526040820151888111156154cf578b8cfd5b6154dd8f8c83860101614936565b828c0152508552509287019290870190600101615478565b50979a909950975050505050505050565b6000806000806060858703121561551b578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615540578384fd5b818701915087601f830112615553578384fd5b813581811115615561578485fd5b8860208083028501011115614c2f578485fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526155c9816020860160208601615ee6565b601f01601f19169290920160200192915050565b60020b9052565b803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a081013561561e81615f6a565b62ffffff811660a0840152505050565b6001600160801b03169052565b62ffffff169052565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286811660208301528581166040830152841660608201526101e0810161577660808301615771866148b9565b615574565b615782602085016148b9565b61578f60a0840182615574565b50604084013560c0830152606084013560e083015261010060808501358184015261012060a08601358185015260c086013561014085015260e08601356101608501526157dd828701614979565b91506157ed6101808501836155dd565b6157f8818701614979565b9150506158096101a08401826155dd565b50611e566101c0830184615581565b6001600160a01b038781168252868116602083015285811660408301528416606082015282516101e0820190615852906080840190615574565b602084015161586460a0840182615574565b50604084015160c0830152606084015160e08301526080840151610100818185015260a08601519150610120828186015260c087015161014086015260e08701516101608601528187015192506158bf6101808601846155dd565b860151915061580990506101a08401826155dd565b60006101a0820190506001600160a01b03808a1683528089166020840152808816604084015280871660608401528560808401528085511660a084015250602084015160c0830152604084015160e08301526060840151610100830152608084015161012083015260a084015161014083015260c0840151610160830152615960610180830184615581565b98975050505050505050565b6000610120820190506001600160a01b0380861683528085166020840152808451166040840152506020830151606083015260408301516080830152606083015160a0830152608083015160c083015260a083015160020b60e083015260c083015160020b610100830152949350505050565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152611e5660a08301846155b1565b60006001600160a01b03841682526040602083015261477f60408301846155b1565b600060e0820190506001600160a01b038516825283516020830152602084015160408301526040840151606083015260608401516001600160801b0380821660808501528060808701511660a0850152505082151560c0830152949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396909616865260208601949094526040850192909252600290810b60608501520b6080830152151560a082015260c00190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b918252602082015260400190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b60c08101611cbd82846155e4565b6000602082526001600160a01b03808451166020840152806020850151166040840152506040830151606083015260ff6060840151166080830152608083015160a08084015261477f60c08401826155b1565b600061018082019050823582526020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100615c62818501614a35565b615c6e8285018261562e565b5050610120615c7e818501614a35565b615c8a8285018261562e565b5050610140615c9a818501614a4b565b615ca68285018261563b565b5050610160615cb68185016148cf565b615cc282850182615581565b505092915050565b6101608101615cdc82615771856148b9565b6020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100808401358184015250610120615d3c818501614979565b615d48828501826155dd565b5050610140615d58818501614979565b615cc2828501826155dd565b600060208252825160806020840152615d8060a08401826155b1565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f19848303016080850152613b9f82826155b1565b90815260200190565b6000604080830186845260208281860152818683526060860190506060828802870101925087855b88811015615e9157878503605f190183528135368b9003603e19018112615e13578788fd5b8a018035615e2081615f39565b60088110615e2a57fe5b86528085013536829003601e19018112615e42578889fd5b8101803567ffffffffffffffff811115615e5a57898afd5b803603831315615e6857898afd5b8887890152615e7c89890182898501615587565b97505050928401925090830190600101615dee565b50929998505050505050505050565b60405181810167ffffffffffffffff81118282101715615ebc57fe5b604052919050565b600067ffffffffffffffff821115615ed857fe5b50601f01601f191660200190565b60005b83811015615f01578181015183820152602001615ee9565b83811115615f10576000848401525b50505050565b6001600160a01b0381168114611c5e57600080fd5b8015158114611c5e57600080fd5b60088110611c5e57600080fd5b8060020b8114611c5e57600080fd5b6001600160801b0381168114611c5e57600080fd5b62ffffff81168114611c5e57600080fd5b60ff81168114611c5e57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220564c27264bc33c078d9c75afb2f26fb0c092712e686cacc101aaeee9df569b6e64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x6080604052600436106101125760003560e01c8063a15db5c5116100a5578063d8fa26f011610074578063db661b7111610059578063db661b711461027a578063fa461e331461028f578063fc0c546a146102af57610119565b8063d8fa26f014610252578063d9d7858a1461026557610119565b8063a15db5c5146101e8578063bc638a7914610208578063c1c0e9c41461021b578063c45a01551461023d57610119565b80633ca8402b116100e15780633ca8402b1461018f5780634fc5864f146101af57806383b17e4d146101c2578063923247ae146101d557610119565b8063150b7a021461011e57806315d23b04146101545780632ef1f08214610169578063334cc3651461017c57610119565b3661011957005b600080fd5b34801561012a57600080fd5b5061013e610139366004614aaf565b6102c4565b60405161014b9190615b22565b60405180910390f35b6101676101623660046151a6565b6102d4565b005b610167610177366004615506565b610ab8565b61016761018a3660046150fe565b610c39565b34801561019b57600080fd5b506101676101aa3660046151b8565b610ee5565b6101676101bd366004614ea3565b611246565b6101676101d0366004614c3e565b611341565b6101676101e3366004614db7565b61139d565b3480156101f457600080fd5b50610167610203366004614b51565b611461565b610167610216366004614db7565b61167d565b34801561022757600080fd5b506102306117d6565b60405161014b91906156ad565b34801561024957600080fd5b506102306117fa565b610167610260366004614c3e565b61181e565b34801561027157600080fd5b50610230611ae8565b34801561028657600080fd5b50610230611b0c565b34801561029b57600080fd5b506101676102aa366004614bc3565b611b30565b3480156102bb57600080fd5b50610230611bd9565b630a85bd0160e11b949350505050565b6102dd34611bfd565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061033190339030906020870135906004016156c1565b600060405180830381600087803b15801561034b57600080fd5b505af115801561035f573d6000803e3d6000fd5b50506040805160a08101825260208086013582528583013590820152670de0b6b3a7640000818301526001600160801b0361010086013581166060830152610120860135166080820152905163760a3f2b60e11b81526000935073__$561e80098325da493156966792c25e3551$__925063ec147e5691610427917f000000000000000000000000000000000000000000000000000000000000000091907f000000000000000000000000000000000000000000000000000000000000000090600401615a6c565b604080518083038186803b15801561043e57600080fd5b505af4158015610452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104769190614ba0565b50604051630725e4e160e31b815290915073__$561e80098325da493156966792c25e3551$__9063392f2708906105089033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a013590670de0b6b3a7640000906004016156e5565b60006040518083038186803b15801561052057600080fd5b505af4158015610534573d6000803e3d6000fd5b505050506000807f0000000000000000000000000000000000000000000000000000000000000000156106515773__$561e80098325da493156966792c25e3551$__63b573fa8b6105886020870187614a77565b608087013560608801356105a46101608a016101408b01614b84565b6105b66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016105f896959493929190615ae7565b604080518083038186803b15801561060f57600080fd5b505af4158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190614ba0565b909250905061073c565b73__$561e80098325da493156966792c25e3551$__63b573fa8b6106786020870187614a77565b608087013560608801356106946101608a016101408b01614b84565b6106a66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016106e896959493929190615ae7565b604080518083038186803b1580156106ff57600080fd5b505af4158015610713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107379190614ba0565b925090505b828111156107eb576107e67f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061079b6101a0880161018089016153db565b6107a58588611c61565b6107cf670de0b6b3a76400006107c96107be898c611c61565b60e08d013590611cc3565b90611d23565b600460405180602001604052806000815250611d8a565b61088e565b8281101561088e5760006107ff8483611c61565b905061088b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006108586101a089016101808a016153db565b84610873670de0b6b3a76400006107c960e08d013584611cc3565b60035b60405180602001604052806000815250611dee565b50505b73__$561e80098325da493156966792c25e3551$__63aee2533b7f00000000000000000000000000000000000000000000000000000000000000006108d66020880188614a77565b6040518060e00160405280336001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000061091b578661091d565b875b81526020017f000000000000000000000000000000000000000000000000000000000000000061094d578761094f565b865b815260a08a0135602082015260c08a0135604082015260600161097a6101608b016101408c01614b84565b60020b81526020016109946101808b016101608c01614b84565b60020b8152506040518463ffffffff1660e01b81526004016109b89392919061596c565b60206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0891906153f7565b506040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610a9a57600080fd5b505af4158015610aae573d6000803e3d6000fd5b5050505050505050565b610ac184611e61565b610aca34611bfd565b610b1a7f0000000000000000000000000000000000000000000000000000000000000000846008878686604051602001610b0693929190615dc6565b604051602081830303815290604052611f12565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190610b669030906004016156ad565b60206040518083038186803b158015610b7e57600080fd5b505afa158015610b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb691906153f7565b15610bc057600080fd5b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b604081013515610c5057610c508160400135611e61565b610c62608082013560a0830135611fe8565b3414610c6d57600080fd5b610c7634611bfd565b6040516308e6940f60e41b815260009073__$561e80098325da493156966792c25e3551$__90638e6940f090610d5a907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009089907f000000000000000000000000000000000000000000000000000000000000000090600401615738565b604080518083038186803b158015610d7157600080fd5b505af4158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190614ba0565b5090506040820135610e3857604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610e05903090339086906004016156c1565b600060405180830381600087803b158015610e1f57600080fd5b505af1158015610e33573d6000803e3d6000fd5b505050505b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610ec957600080fd5b505af4158015610edd573d6000803e3d6000fd5b505050505050565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610f3690339030908635906004016156c1565b600060405180830381600087803b158015610f5057600080fd5b505af1158015610f64573d6000803e3d6000fd5b50505050600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a00160405280866000013581526020018660200135815260200186604001358152602001866060016020810190610fe191906153bf565b6001600160801b03168152602001610fff60a08801608089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161104a93929190615a6c565b604080518083038186803b15801561106157600080fd5b505af4158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190614ba0565b5060408051630725e4e160e31b815291925073__$561e80098325da493156966792c25e3551$__9163392f2708916111239133917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000916000918a35918b0135906004016156e5565b60006040518083038186803b15801561113b57600080fd5b505af415801561114f573d6000803e3d6000fd5b505050506000811115610e38576111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006111b160e0860160c087016153db565b84610873670de0b6b3a76400006107c960a08a013584611cc3565b506040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b6112508135611e61565b61125934611bfd565b6112957f000000000000000000000000000000000000000000000000000000000000000060a0830135600784604051602001610b069190615c01565b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e9061130e907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b15801561132657600080fd5b505af415801561133a573d6000803e3d6000fd5b5050505050565b602081013515611358576113588160200135611e61565b61136134611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000006080830135600684604051602001610b069190615cca565b6113a78135611e61565b6113b5606082013534611fe8565b816080013511156113c557600080fd5b6113ce34611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061142360c0850160a086016153db565b61143560208601356040870135611fe8565b608086013560018760405160200161144d9190615ba0565b604051602081830303815290604052611d8a565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461149657600080fd5b6000818060200190518101906114ac9190614ded565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ecbcdab600083604001516040518363ffffffff1660e01b8152600401611501929190615b4f565b600060405180830381600087803b15801561151b57600080fd5b505af115801561152f573d6000803e3d6000fd5b5050505061155481600001518260200151836040015184606001518560800151612042565b80602001516001600160a01b031663095ea7b37f000000000000000000000000000000000000000000000000000000000000000083604001516040518363ffffffff1660e01b81526004016115aa929190615ace565b602060405180830381600087803b1580156115c457600080fd5b505af11580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614b35565b50604080820151905163d8aed14560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163d8aed1459161164f91600091600401615b4f565b600060405180830381600087803b15801561166957600080fd5b505af1158015610edd573d6000803e3d6000fd5b80351561168e5761168e8135611e61565b61169734611bfd565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906116eb90339030906060870135906004016156c1565b602060405180830381600087803b15801561170557600080fd5b505af1158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190614b35565b50600061175260208301356060840135611fe8565b90506111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006117a960c0860160a087016153db565b8460808701356002886040516020016117c29190615ba0565b604051602081830303815290604052611dee565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6118288135611e61565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061187c90339030906020870135906004016156c1565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050506118b734611bfd565b600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200135815260200186604001358152602001866060013581526020018660e001602081019061193091906153bf565b6001600160801b03168152602001611950610120880161010089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161199b93929190615a6c565b604080518083038186803b1580156119b257600080fd5b505af41580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614ba0565b50604051630725e4e160e31b815290915073__$561e80098325da493156966792c25e3551$__9063392f270890611a789033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a01359060608b0135906004016156e5565b60006040518083038186803b158015611a9057600080fd5b505af4158015611aa4573d6000803e3d6000fd5b50610e389250508335905082608085013560a086013560c0870135611ad161014089016101208a016153db565b611ae36101608a016101408b01614b19565b6138b5565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000841380611b3f5750600083135b611b4857600080fd5b6000611b56828401846151c9565b90506000806000611b6a8460000151613b58565b9250925092506000611b9e7f0000000000000000000000000000000000000000000000000000000000000000858585613b89565b90506000808a13611baf5788611bb1565b895b9050611bcd86602001518684848a606001518b60400151613ba8565b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8015611c5e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166957600080fd5b50565b600082821115611cb8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600082611cd257506000611cbd565b82820282848281611cdf57fe5b0414611d1c5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f8b6021913960400191505060405180910390fd5b9392505050565b6000808211611d79576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611d8257fe5b049392505050565b6000611ddf8530600060405180608001604052808c8c8f604051602001611db393929190615644565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526141e7565b905083811115610aae57600080fd5b600080611e448630600060405180608001604052808e8d8f604051602001611e1893929190615644565b60408051601f1981840301815291815290825233602083015260ff8b1690820152606001889052614354565b905084811015611e5357600080fd5b90505b979650505050505050565b6040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611eaf908590600401615dbd565b60206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190614a93565b6001600160a01b031614611c5e57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060a00160405280336001600160a01b03168152602001886001600160a01b031681526020018781526020018660ff16815260200185815250604051602001611f8e9190615bae565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611fba929190615a4a565b600060405180830381600087803b158015611fd457600080fd5b505af1158015610aae573d6000803e3d6000fd5b600082820183811015611d1c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60068260ff16600981111561205357fe5b600981111561205e57fe5b14156124165760008180602001905181019061207a9190614f6c565b905060008073__$561e80098325da493156966792c25e3551$__638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000604051806101400160405280306001600160a01b031681526020018a600001516001600160a01b031681526020018a6020015181526020018a6040015181526020018a6060015181526020018a60a0015181526020018a60e0015181526020018a610100015181526020018a610120015160020b81526020018a610140015160020b8152507f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016121e496959493929190615818565b604080518083038186803b1580156121fb57600080fd5b505af415801561220f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122339190614ba0565b6040516348dc69a560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906122869085908590600401615b4f565b600060405180830381600087803b1580156122a057600080fd5b505af11580156122b4573d6000803e3d6000fd5b5050505073__$561e80098325da493156966792c25e3551$__6363410a867f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085600061232e8960c001518d611fe890919063ffffffff16565b6040518663ffffffff1660e01b815260040161234e9594939291906159df565b60006040518083038186803b15801561236657600080fd5b505af415801561237a573d6000803e3d6000fd5b5050505082602001516000141561240e57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906123db9030908c9087906004016156c1565b600060405180830381600087803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050505b50505061133a565b60078260ff16600981111561242757fe5b600981111561243257fe5b14156127eb5760008180602001905181019061244e9190614eb5565b604051632e1a7d4d60e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061249d908790600401615dbd565b600060405180830381600087803b1580156124b757600080fd5b505af11580156124cb573d6000803e3d6000fd5b5050825160405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063b6b55f259250879161251d91600401615dbd565b6000604051808303818588803b15801561253657600080fd5b505af115801561254a573d6000803e3d6000fd5b5050835160405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016945063713d517f935061259b9250600401615dbd565b600060405180830381600087803b1580156125b557600080fd5b505af11580156125c9573d6000803e3d6000fd5b50505050600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200151815260200186604001518152602001866060015181526020018661010001516001600160801b031681526020018661012001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161269893929190615a6c565b604080518083038186803b1580156126af57600080fd5b505af41580156126c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e79190614ba0565b50825160208401516060850151604051630725e4e160e31b815293945073__$561e80098325da493156966792c25e3551$__9363392f270893612775938d937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000939291906004016156e5565b60006040518083038186803b15801561278d57600080fd5b505af41580156127a1573d6000803e3d6000fd5b505050506127e482600001518284608001516127ce8660a001518760c00151611fe890919063ffffffff16565b8660e001518761014001518861016001516138b5565b505061133a565b60088260ff1660098111156127fc57fe5b600981111561280757fe5b141561133a5760008082806020019051810190612824919061540f565b604051632e1a7d4d60e01b815291935091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612875908890600401615dbd565b600060405180830381600087803b15801561288f57600080fd5b505af11580156128a3573d6000803e3d6000fd5b505060405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063b6b55f25915087906128f5908690600401615dbd565b6000604051808303818588803b15801561290e57600080fd5b505af1158015612922573d6000803e3d6000fd5b505060405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063713d517f925061297391508590600401615dbd565b600060405180830381600087803b15801561298d57600080fd5b505af11580156129a1573d6000803e3d6000fd5b5050505060005b81518110156137fb5760008282815181106129bf57fe5b60200260200101516000015160078111156129d657fe5b1415612b895760008282815181106129ea57fe5b602002602001015160200151806020019051810190612a09919061507c565b8051604051637a04dbd760e01b815291925073__$561e80098325da493156966792c25e3551$__91637a04dbd791612ad0917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091908b9089907f0000000000000000000000000000000000000000000000000000000000000000906004016158d4565b60006040518083038186803b158015612ae857600080fd5b505af4158015612afc573d6000803e3d6000fd5b5050505060208101516040516348dc69a560e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916391b8d34a91612b51918891600401615b4f565b600060405180830381600087803b158015612b6b57600080fd5b505af1158015612b7f573d6000803e3d6000fd5b50505050506137f3565b6001828281518110612b9757fe5b6020026020010151600001516007811115612bae57fe5b1415612dad576000828281518110612bc257fe5b602002602001015160200151806020019051810190612be19190614cbc565b905073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a0016040528085600001518152602001856020015181526020018560400151815260200185606001516001600160801b0316815260200185608001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401612caa93929190615a6c565b604080518083038186803b158015612cc157600080fd5b505af4158015612cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf99190614ba0565b505080516040808301519051630725e4e160e31b815273__$561e80098325da493156966792c25e3551$__9263392f270892612d81928e927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c9291906004016156e5565b60006040518083038186803b158015612d9957600080fd5b505af4158015612b7f573d6000803e3d6000fd5b6002828281518110612dbb57fe5b6020026020010151600001516007811115612dd257fe5b1415612f95576000828281518110612de657fe5b602002602001015160200151806020019051810190612e059190614d6f565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612e5591906156ad565b60206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906153f7565b90508160200151811015612ebb57602082018190525b81516020830151604051639f70f9e560e01b815273__$561e80098325da493156966792c25e3551$__92639f70f9e592612f3d927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60206040518083038186803b158015612f5557600080fd5b505af4158015612f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8d91906153f7565b5050506137f3565b6003828281518110612fa357fe5b6020026020010151600001516007811115612fba57fe5b1415613232576000828281518110612fce57fe5b602002602001015160200151806020019051810190612fed9190615370565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161303d91906156ad565b60206040518083038186803b15801561305557600080fd5b505afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d91906153f7565b905081604001511561316b5760006130a486614493565b9050818110156130b2578091505b60208301516040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__916363410a8691613135917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918c918991906004016159df565b60006040518083038186803b15801561314d57600080fd5b505af4158015613161573d6000803e3d6000fd5b505050505061322b565b8151811015613178578082525b815160208301516040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__926363410a86926131fa927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60006040518083038186803b15801561321257600080fd5b505af4158015613226573d6000803e3d6000fd5b505050505b50506137f3565b600482828151811061324057fe5b602002602001015160000151600781111561325757fe5b141561343f57600082828151811061326b57fe5b60200260200101516020015180602001905181019061328a9190615110565b9050600073__$561e80098325da493156966792c25e3551$__638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000877f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b815260040161336f96959493929190615818565b604080518083038186803b15801561338657600080fd5b505af415801561339a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133be9190614ba0565b6040516348dc69a560e11b815291965091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906134119088908590600401615b4f565b600060405180830381600087803b15801561342b57600080fd5b505af1158015613226573d6000803e3d6000fd5b600582828151811061344d57fe5b602002602001015160000151600781111561346457fe5b14156135e157600082828151811061347857fe5b6020026020010151602001518060200190518101906134979190615007565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561351357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b8061359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b61359c57600080fd5b61322b81600001518260200151836080015184604001516135da670de0b6b3a76400006107c988604001518960600151611cc390919063ffffffff16565b6009610876565b60068282815181106135ef57fe5b602002602001015160000151600781111561360657fe5b141561371557600082828151811061361a57fe5b6020026020010151602001518060200190518101906136399190614c5a565b604080516080810182528251815230602080830191909152830180516001600160801b03908116838501529051166060820152905163fc6f786560e01b8152919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fc6f7865906136bb908490600401615b5d565b6040805180830381600087803b1580156136d457600080fd5b505af11580156136e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370c9190614ba0565b505050506137f3565b600782828151811061372357fe5b602002602001015160000151600781111561373a57fe5b14156137f357600082828151811061374e57fe5b60200260200101516020015180602001905181019061376d9190614d34565b80516040516348dc69a560e11b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916391b8d34a916137bf91889190600401615b4f565b600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b50505050505b6001016129a8565b506040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a869061387c907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009087906000908c906004016159df565b60006040518083038186803b15801561389457600080fd5b505af41580156138a8573d6000803e3d6000fd5b5050505050505050505050565b80156139895760006138c688614493565b9050868110156138d4578096505b6040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a8690613953907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908d908d908c906004016159df565b60006040518083038186803b15801561396b57600080fd5b505af415801561397f573d6000803e3d6000fd5b5050505050613b46565b84861015613a1957600061399d8688611c61565b9050613a137f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085846139fc670de0b6b3a76400006107c98b84611cc3565b60058e8d8d60405160200161144d93929190615697565b50613b46565b6040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a8690613a98907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c908b908b906004016159df565b60006040518083038186803b158015613ab057600080fd5b505af4158015613ac4573d6000803e3d6000fd5b505050506000613add8688611c6190919063ffffffff16565b90508015613b4457613b427f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008584610873670de0b6b3a76400006107c98b84611cc3565b505b505b613b4f47611bfd565b50505050505050565b60008080613b668482614548565b9250613b73846014614614565b9050613b80846017614548565b91509193909250565b6000613b9f85613b9a8686866146d0565b614726565b95945050505050565b60018160ff166009811115613bb957fe5b6009811115613bc457fe5b1415613d3f57600082806020019051810190613be09190614dd2565b8051602082015160608301516040516331a0854360e11b815293945073__$561e80098325da493156966792c25e3551$__936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60006040518083038186803b158015613c8057600080fd5b505af4158015613c94573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb9150613ce69088908890600401615ace565b602060405180830381600087803b158015613d0057600080fd5b505af1158015613d14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d389190614b35565b5050610edd565b60028160ff166009811115613d5057fe5b6009811115613d5b57fe5b1415613f4d57600082806020019051810190613d779190614dd2565b9050600081602001511180613d90575060008160400151115b15613eff57805160208201516040808401519051639f70f9e560e01b815260009373__$561e80098325da493156966792c25e3551$__93639f70f9e593613e21937f0000000000000000000000000000000000000000000000000000000000000000937f000000000000000000000000000000000000000000000000000000000000000093909290916004016159df565b60206040518083038186803b158015613e3957600080fd5b505af4158015613e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7191906153f7565b8251909150613efd57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613eca9030908c9086906004016156c1565b600060405180830381600087803b158015613ee457600080fd5b505af1158015613ef8573d6000803e3d6000fd5b505050505b505b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ce69088908890600401615ace565b60038160ff166009811115613f5e57fe5b6009811115613f6957fe5b14156140155760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b602060405180830381600087803b158015613fd757600080fd5b505af1158015613feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400f9190614b35565b50610edd565b60048160ff16600981111561402657fe5b600981111561403157fe5b14156140855760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b60058160ff16600981111561409657fe5b60098111156140a157fe5b1415614145576000828060200190518101906140bd9190615287565b8051602082015160408084015190516331a0854360e11b815293945073__$561e80098325da493156966792c25e3551$__936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60098160ff16600981111561415657fe5b600981111561416157fe5b1415610edd5760405163a9059cbb60e01b81526001600160a01b0386169063a9059cbb906141959087908790600401615ace565b602060405180830381600087803b1580156141af57600080fd5b505af11580156141c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4f9190614b35565b6000806000806141fa8560000151613b58565b919450925090506001600160a01b038084169083161060008061421e858786614749565b6001600160a01b031663128acb088b856142378f614787565b6000036001600160a01b038e161561424f578d614275565b8761426e5773fffd8963efd1fc6a506488495d951d5263988d25614275565b6401000276a45b8d6040516020016142869190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142b5959493929190615a10565b6040805180830381600087803b1580156142ce57600080fd5b505af11580156142e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143069190614ba0565b915091506000808461431c578284600003614322565b83836000035b915091508a6001600160a01b031660001415614344578c811461434457600080fd5b509b9a5050505050505050505050565b6000806000806143678560000151613b58565b919450925090506001600160a01b038083169084161060008061438b868686614749565b6001600160a01b031663128acb088b856143a48f614787565b6001600160a01b038e16156143b9578d6143df565b876143d85773fffd8963efd1fc6a506488495d951d5263988d256143df565b6401000276a45b8d6040516020016143f09190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161441f959493929190615a10565b6040805180830381600087803b15801561443857600080fd5b505af115801561444c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144709190614ba0565b915091508261447f5781614481565b805b6000039b9a5050505050505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c64ea4a846040518263ffffffff1660e01b81526004016144e29190615dbd565b60806040518083038186803b1580156144fa57600080fd5b505afa15801561450e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453291906152dc565b606001516001600160801b03169150505b919050565b6000818260140110156145a2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b81601401835110156145fb576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b60008182600301101561466e576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156146c7576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6146d8614899565b826001600160a01b0316846001600160a01b031611156146f6579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614732838361479d565b9050336001600160a01b03821614611cbd57600080fd5b600061477f7f000000000000000000000000000000000000000000000000000000000000000061477a8686866146d0565b61479d565b949350505050565b6000600160ff1b821061479957600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b0316106147c557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561454381615f16565b805161454381615f16565b803561454381615f2b565b805161454381615f2b565b600082601f8301126148f5578081fd5b813561490861490382615ec4565b615ea0565b81815284602083860101111561491c578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614946578081fd5b815161495461490382615ec4565b818152846020838601011115614968578283fd5b61477f826020830160208701615ee6565b803561454381615f46565b805161454381615f46565b600061016082840312156149a1578081fd5b50919050565b600060c082840312156149a1578081fd5b600060c082840312156149c9578081fd5b60405160c0810181811067ffffffffffffffff821117156149e657fe5b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151614a2881615f6a565b60a0919091015292915050565b803561454381615f55565b805161454381615f55565b803561454381615f6a565b805161454381615f6a565b803561454381615f7b565b805161454381615f7b565b600060208284031215614a88578081fd5b8135611d1c81615f16565b600060208284031215614aa4578081fd5b8151611d1c81615f16565b60008060008060808587031215614ac4578283fd5b8435614acf81615f16565b93506020850135614adf81615f16565b925060408501359150606085013567ffffffffffffffff811115614b01578182fd5b614b0d878288016148e5565b91505092959194509250565b600060208284031215614b2a578081fd5b8135611d1c81615f2b565b600060208284031215614b46578081fd5b8151611d1c81615f2b565b600060208284031215614b62578081fd5b813567ffffffffffffffff811115614b78578182fd5b61477f848285016148e5565b600060208284031215614b95578081fd5b8135611d1c81615f46565b60008060408385031215614bb2578182fd5b505080516020909101519092909150565b60008060008060608587031215614bd8578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614bfd578384fd5b818701915087601f830112614c10578384fd5b813581811115614c1e578485fd5b886020828501011115614c2f578485fd5b95989497505060200194505050565b60006101608284031215614c50578081fd5b611d1c838361498f565b600060608284031215614c6b578081fd5b6040516060810181811067ffffffffffffffff82111715614c8857fe5b604052825181526020830151614c9d81615f55565b60208201526040830151614cb081615f55565b60408201529392505050565b600060a08284031215614ccd578081fd5b60405160a0810181811067ffffffffffffffff82111715614cea57fe5b80604052508251815260208301516020820152604083015160408201526060830151614d1581615f55565b60608201526080830151614d2881615f55565b60808201529392505050565b600060208284031215614d45578081fd5b6040516020810181811067ffffffffffffffff82111715614d6257fe5b6040529151825250919050565b600060408284031215614d80578081fd5b6040516040810181811067ffffffffffffffff82111715614d9d57fe5b604052825181526020928301519281019290925250919050565b600060c08284031215614dc8578081fd5b611d1c83836149a7565b600060c08284031215614de3578081fd5b611d1c83836149b8565b600060208284031215614dfe578081fd5b815167ffffffffffffffff80821115614e15578283fd5b9083019060a08286031215614e28578283fd5b60405160a081018181108382111715614e3d57fe5b604052614e49836148c4565b8152614e57602084016148c4565b602082015260408301516040820152614e7260608401614a6c565b6060820152608083015182811115614e88578485fd5b614e9487828601614936565b60808301525095945050505050565b600061018082840312156149a1578081fd5b6000610180808385031215614ec8578182fd5b614ed181615ea0565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100614f2b818501614a40565b90820152610120614f3d848201614a40565b90820152610140614f4f848201614a56565b90820152610160614f618482016148da565b908201529392505050565b6000610160808385031215614f7f578182fd5b614f8881615ea0565b9050614f93836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120614ff5818501614984565b90820152610140614f61848201614984565b600060a08284031215615018578081fd5b60405160a0810181811067ffffffffffffffff8211171561503557fe5b604052825161504381615f16565b8152602083015161505381615f16565b8060208301525060408301516040820152606083015160608201526080830151614d2881615f6a565b600060e0828403121561508d578081fd5b60405160e0810181811067ffffffffffffffff821117156150aa57fe5b6040526150b6836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600061014082840312156149a1578081fd5b6000610140808385031215615123578182fd5b61512c81615ea0565b9050615137836148c4565b8152615145602084016148c4565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100615194818501614984565b90820152610120614f61848201614984565b60006101a082840312156149a1578081fd5b600060e082840312156149a1578081fd5b6000602082840312156151da578081fd5b813567ffffffffffffffff808211156151f1578283fd5b9083019060808286031215615204578283fd5b60405160808101818110838211171561521957fe5b60405282358281111561522a578485fd5b615236878286016148e5565b825250615245602084016148b9565b602082015261525660408401614a61565b604082015260608301358281111561526c578485fd5b615278878286016148e5565b60608301525095945050505050565b600060608284031215615298578081fd5b6040516060810181811067ffffffffffffffff821117156152b557fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000608082840312156152ed578081fd5b6040516080810181811067ffffffffffffffff8211171561530a57fe5b604052825161531881615f16565b8152602083015163ffffffff81168114615330578283fd5b602082015260408301516bffffffffffffffffffffffff81168114615353578283fd5b604082015261536460608401614a40565b60608201529392505050565b600060608284031215615381578081fd5b6040516060810181811067ffffffffffffffff8211171561539e57fe5b806040525082518152602083015160208201526040830151614cb081615f2b565b6000602082840312156153d0578081fd5b8135611d1c81615f55565b6000602082840312156153ec578081fd5b8135611d1c81615f6a565b600060208284031215615408578081fd5b5051919050565b60008060408385031215615421578182fd5b8251915060208084015167ffffffffffffffff80821115615440578384fd5b818601915086601f830112615453578384fd5b81518181111561545f57fe5b61546c8485830201615ea0565b81815284810190848601875b848110156154f557815187016040818e03601f1901121561549757898afd5b6040516040810181811089821117156154ac57fe5b604052818a01516154bc81615f39565b81526040820151888111156154cf578b8cfd5b6154dd8f8c83860101614936565b828c0152508552509287019290870190600101615478565b50979a909950975050505050505050565b6000806000806060858703121561551b578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615540578384fd5b818701915087601f830112615553578384fd5b813581811115615561578485fd5b8860208083028501011115614c2f578485fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526155c9816020860160208601615ee6565b601f01601f19169290920160200192915050565b60020b9052565b803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a081013561561e81615f6a565b62ffffff811660a0840152505050565b6001600160801b03169052565b62ffffff169052565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286811660208301528581166040830152841660608201526101e0810161577660808301615771866148b9565b615574565b615782602085016148b9565b61578f60a0840182615574565b50604084013560c0830152606084013560e083015261010060808501358184015261012060a08601358185015260c086013561014085015260e08601356101608501526157dd828701614979565b91506157ed6101808501836155dd565b6157f8818701614979565b9150506158096101a08401826155dd565b50611e566101c0830184615581565b6001600160a01b038781168252868116602083015285811660408301528416606082015282516101e0820190615852906080840190615574565b602084015161586460a0840182615574565b50604084015160c0830152606084015160e08301526080840151610100818185015260a08601519150610120828186015260c087015161014086015260e08701516101608601528187015192506158bf6101808601846155dd565b860151915061580990506101a08401826155dd565b60006101a0820190506001600160a01b03808a1683528089166020840152808816604084015280871660608401528560808401528085511660a084015250602084015160c0830152604084015160e08301526060840151610100830152608084015161012083015260a084015161014083015260c0840151610160830152615960610180830184615581565b98975050505050505050565b6000610120820190506001600160a01b0380861683528085166020840152808451166040840152506020830151606083015260408301516080830152606083015160a0830152608083015160c083015260a083015160020b60e083015260c083015160020b610100830152949350505050565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152611e5660a08301846155b1565b60006001600160a01b03841682526040602083015261477f60408301846155b1565b600060e0820190506001600160a01b038516825283516020830152602084015160408301526040840151606083015260608401516001600160801b0380821660808501528060808701511660a0850152505082151560c0830152949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396909616865260208601949094526040850192909252600290810b60608501520b6080830152151560a082015260c00190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b918252602082015260400190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b60c08101611cbd82846155e4565b6000602082526001600160a01b03808451166020840152806020850151166040840152506040830151606083015260ff6060840151166080830152608083015160a08084015261477f60c08401826155b1565b600061018082019050823582526020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100615c62818501614a35565b615c6e8285018261562e565b5050610120615c7e818501614a35565b615c8a8285018261562e565b5050610140615c9a818501614a4b565b615ca68285018261563b565b5050610160615cb68185016148cf565b615cc282850182615581565b505092915050565b6101608101615cdc82615771856148b9565b6020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100808401358184015250610120615d3c818501614979565b615d48828501826155dd565b5050610140615d58818501614979565b615cc2828501826155dd565b600060208252825160806020840152615d8060a08401826155b1565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f19848303016080850152613b9f82826155b1565b90815260200190565b6000604080830186845260208281860152818683526060860190506060828802870101925087855b88811015615e9157878503605f190183528135368b9003603e19018112615e13578788fd5b8a018035615e2081615f39565b60088110615e2a57fe5b86528085013536829003601e19018112615e42578889fd5b8101803567ffffffffffffffff811115615e5a57898afd5b803603831315615e6857898afd5b8887890152615e7c89890182898501615587565b97505050928401925090830190600101615dee565b50929998505050505050505050565b60405181810167ffffffffffffffff81118282101715615ebc57fe5b604052919050565b600067ffffffffffffffff821115615ed857fe5b50601f01601f191660200190565b60005b83811015615f01578181015183820152602001615ee9565b83811115615f10576000848401525b50505050565b6001600160a01b0381168114611c5e57600080fd5b8015158114611c5e57600080fd5b60088110611c5e57600080fd5b8060020b8114611c5e57600080fd5b6001600160801b0381168114611c5e57600080fd5b62ffffff81168114611c5e57600080fd5b60ff81168114611c5e57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220564c27264bc33c078d9c75afb2f26fb0c092712e686cacc101aaeee9df569b6e64736f6c63430007060033\",\n  \"libraries\": {\n    \"ControllerHelperUtil\": \"0x85F983af83101600672180Dfc1d840827c4759B5\"\n  },\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\": {\n        \"details\": \"user should approve this contract for Uni NFT transfer\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.CloseShortWithUserNftParams struct\"\n        }\n      },\n      \"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"details\": \"sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\"\n        }\n      },\n      \"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"details\": \"flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.FlashSellLongWMintParams struct\"\n        }\n      },\n      \"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"details\": \"this function\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\"\n        }\n      },\n      \"onERC721Received(address,address,uint256,bytes)\": {\n        \"details\": \"accept erc721 from safeTransferFrom and safeMint after callback\",\n        \"returns\": {\n          \"_0\": \"returns received selector\"\n        }\n      },\n      \"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\": {\n        \"params\": {\n          \"_collateralToFlashloan\": \"collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\",\n          \"_params\": \"array of ControllerHelperDataType.RebalanceLpInVaultParams structs\",\n          \"_vaultId\": \"vault ID\"\n        }\n      },\n      \"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\": {\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\"\n        }\n      },\n      \"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\": {\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.ReduceLiquidityAndSellParams struct\"\n        }\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"params\": {\n          \"_data\": \"callback data encoded as SwapCallbackData struct\",\n          \"amount0Delta\": \"amount of token0\",\n          \"amount1Delta\": \"amount of token1\"\n        }\n      },\n      \"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.MintAndLpParams struct\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\": {\n        \"notice\": \"close short position with user Uniswap v3 LP NFT\"\n      },\n      \"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"notice\": \"FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\"\n      },\n      \"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"notice\": \"sell long wPowerPerp and flashswap mint short position\"\n      },\n      \"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"notice\": \"flash close position and buy long squeeth\"\n      },\n      \"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\": {\n        \"notice\": \"Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\"\n      },\n      \"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\": {\n        \"notice\": \"Rebalance LP nft through trading\"\n      },\n      \"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\": {\n        \"notice\": \"sell all LP wPowerPerp amounts to WETH and send back to user\"\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"notice\": \"uniswap swap callback function for flashswap\"\n      },\n      \"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"notice\": \"mint WPowerPerp and LP into Uniswap v3 pool\"\n      }\n    },\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/ControllerHelperUtil.json",
    "content": "{\n  \"address\": \"0x85F983af83101600672180Dfc1d840827c4759B5\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wPowerPerpPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_collateralToLp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"_lowerTick\",\n          \"type\": \"int24\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"_upperTick\",\n          \"type\": \"int24\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_isWethToken0\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getAmountsToLp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x6e02773e56eee0cc2cf63e49a1c5493190b5514e04ffcbf04faf864a08693f10\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x85F983af83101600672180Dfc1d840827c4759B5\",\n    \"transactionIndex\": 140,\n    \"gasUsed\": \"2335067\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x0cf0eeb1e5d7bfc88295076005581a6d62e3b1ee41a0796a6b666519f648b917\",\n    \"transactionHash\": \"0x6e02773e56eee0cc2cf63e49a1c5493190b5514e04ffcbf04faf864a08693f10\",\n    \"logs\": [],\n    \"blockNumber\": 8042201,\n    \"cumulativeGasUsed\": \"25162484\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_collateralToLp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"_lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"_upperTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_isWethToken0\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getAmountsToLp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_collateralToWithdraw\\\":\\\"amount of collateral to withdraw\\\",\\\"_controller\\\":\\\"controller address\\\",\\\"_vaultId\\\":\\\"vault Id\\\",\\\"_wPowerPerpToBurn\\\":\\\"amount of wPowerPerp to burn\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"checkClosedLp(address,address,address,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\",\\\"_liquidityPercentage\\\":\\\"percentage of liquidity that was closed from total amount\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_tokenId\\\":\\\"Uni LP NFT id\\\",\\\"_user\\\":\\\"user address\\\",\\\"_vaultId\\\":\\\"vault ID\\\"}},\\\"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\\\":{\\\"params\\\":{\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_params\\\":\\\"ControllerHelperDataType.CloseUniLpParams struct \\\"},\\\"returns\\\":{\\\"_0\\\":\\\"withdrawn wPowerPerp and WETH amounts\\\"}},\\\"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\\\":{\\\"params\\\":{\\\"_collateralToLp\\\":\\\"amount of ETH collateral to LP\\\",\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_lowerTick\\\":\\\"LP position lower tick\\\",\\\"_upperTick\\\":\\\"LP position upper tick\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to LP\\\",\\\"_wPowerPerpPool\\\":\\\"wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"exact amount0 and amount1 to be LPed\\\"}},\\\"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\",\\\"_increaseLiquidityParam\\\":\\\"ControllerHelperDataType.IncreaseLpLiquidityParams struct\\\",\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_vaultId\\\":\\\"vault Id\\\"}},\\\"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\\\":{\\\"params\\\":{\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_params\\\":\\\"ControllerHelperDataType.LpWPowerPerpPoolParams struct\\\",\\\"_wPowerPerpPool\\\":\\\"wPowerpPerp pool address in Uni v3\\\"}},\\\"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"wPowerPerp controller address\\\",\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_mintAndLpParams\\\":\\\"ControllerHelperDataType.MintAndLpParams struct\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"_vaultId and tokenId\\\"}},\\\"mintDepositInVault(address,address,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_collateralToDeposit\\\":\\\"amount of collateral to deposit\\\",\\\"_controller\\\":\\\"controller address\\\",\\\"_vaultId\\\":\\\"vault Id\\\",\\\"_wPowerPerpToMint\\\":\\\"amount of wPowerPerp to mint\\\",\\\"_weth\\\":\\\"WETH address\\\"}},\\\"sendBack(address,address)\\\":{\\\"params\\\":{\\\"_wPowerPerp\\\":\\\"wPowerPerp address\\\",\\\"_weth\\\":\\\"WETH address\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"burn wPowerPerp or just withdraw collateral from vault (or both)\\\"},\\\"checkClosedLp(address,address,address,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\\"},\\\"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\\\":{\\\"notice\\\":\\\"fully or partially close Uni v3 LP\\\"},\\\"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\\\":{\\\"notice\\\":\\\"get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\\"},\\\"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\\\":{\\\"notice\\\":\\\"increase liquidityin Uni v3 position\\\"},\\\"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\\\":{\\\"notice\\\":\\\"LP into Uniswap V3 pool\\\"},\\\"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\\\":{\\\"notice\\\":\\\"minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\\"},\\\"mintDepositInVault(address,address,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"mint wPowerPerp in vault\\\"},\\\"sendBack(address,address)\\\":{\\\"notice\\\":\\\"send ETH and wPowerPerp\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/periphery/lib/ControllerHelperUtil.sol\\\":\\\"ControllerHelperUtil\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/lib/ControllerHelperDataType.sol\\\":{\\\"content\\\":\\\"pragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperDataType {\\\\n    using SafeMath for uint256;\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum CALLBACK_SOURCE {\\\\n        FLASH_W_MINT,\\\\n        FLASH_W_BURN,\\\\n        FLASH_SELL_LONG_W_MINT,\\\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\\\n        GENERAL_SWAP\\\\n    }\\\\n\\\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\\\n    enum RebalanceVaultNftType {\\\\n        IncreaseLpLiquidity,\\\\n        DecreaseLpLiquidity,\\\\n        DepositIntoVault,\\\\n        WithdrawFromVault,\\\\n        MintNewLp,\\\\n        generalSwap,\\\\n        CollectFees, \\\\n        DepositExistingNft\\\\n    }\\\\n    \\\\n    /// @dev params for flashswapWBurnBuyLong()\\\\n    struct FlashswapWBurnBuyLongParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\\\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev params for flashswapSellLongWMint()\\\\n    struct FlashSellLongWMintParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\\\n    struct SwapExactoutEthWPowerPerpData {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\\\n    }\\\\n\\\\n    /// @dev params for CloseShortWithUserNft()\\\\n    struct CloseShortWithUserNftParams {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity;  // liquidity amount in LP \\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;      // uniswap pool fee\\\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for wMintLp()\\\\n    struct MintAndLpParams {\\\\n        address recipient;  // recipient address\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 collateralToLp; // collateral amount to LP\\\\n        uint256 amount0Min; // minimum amount to LP of asset0\\\\n        uint256 amount1Min; // minimum amount to LP of asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for flashloanWMintDepositNft()\\\\n    struct FlashloanWMintLpDepositNftParams {\\\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\\\n        uint256 vaultId; // vault ID (could be zero)\\\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\\\n        uint256 amount0Min; // minimum amount of token0 to LP\\\\n        uint256 amount1Min; // minimum amount of token1 to LP\\\\n        int24 lowerTick; // range lower tick to LP in\\\\n        int24 upperTick; // range upper tick to LP in\\\\n    }\\\\n\\\\n    /// @dev params for flashloanCloseVaultLpNft()\\\\n    struct FlashloanCloseVaultLpNftParam {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity; // amount of liquidity in LP position\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for _closeUniLp() \\\\n    struct CloseUniLpParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\\\n    }\\\\n\\\\n    /// @dev params for sellAll()\\\\n    struct ReduceLiquidityAndSellParams {\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpWithoutVault()\\\\n    struct RebalanceLpWithoutVaultParams {\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\\\n        uint256 wethAmountDesired;  // WETH amount to LP\\\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\\\n    struct LpWPowerPerpPoolParams {\\\\n        address recipient;  // recipient address\\\\n        uint256 amount0Desired; // amount desired to LP for asset0\\\\n        uint256 amount1Desired; // amount desired to LP for asset1\\\\n        uint256 amount0Min; // amount min to LP for asset0\\\\n        uint256 amount1Min; // amount min to LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpInVault()\\\\n    struct RebalanceLpInVaultParams {\\\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\\\n        bytes data;\\\\n    }\\\\n\\\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\\\n    struct IncreaseLpLiquidityParams {\\\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 wethAmountToLp; // WETH amount to LP\\\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for decrease liquidity in LP position\\\\n    struct DecreaseLpLiquidityParams {  \\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for minting into vault\\\\n    struct DepositIntoVaultParams {\\\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\\\n    }\\\\n\\\\n    /// @dev struct for withdrawing from vault\\\\n    struct withdrawFromVaultParams {  \\\\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\\\n    }\\\\n\\\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\\\n    struct GeneralSwapParams {\\\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\\\n        uint256 amountIn; // amount to swap in\\\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\\\n    struct CollectFeesParams {\\\\n        uint256 tokenId;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\\\n    struct DepositExistingNftParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x04a47d47c3e0a1ec4e834f9aa466960200084fbdee47f0f513990b2c4708b02a\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/ControllerHelperUtil.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ControllerHelperDataType} from \\\\\\\"./ControllerHelperDataType.sol\\\\\\\";\\\\nimport {LiquidityAmounts} from \\\\\\\"./LiquidityAmounts.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"../../libs/TickMathExternal.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperUtil {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /**\\\\n     * @notice fully or partially close Uni v3 LP\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return withdrawn wPowerPerp and WETH amounts\\\\n     */\\\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\\\n            .DecreaseLiquidityParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\\\n                amount0Min: _params.amount0Min,\\\\n                amount1Min: _params.amount1Min,\\\\n                deadline: block.timestamp\\\\n            });\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\\\n\\\\n        uint256 wethAmount;\\\\n        uint256 _wPowerPerpAmount;\\\\n        (_isWethToken0)\\\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n                INonfungiblePositionManager.CollectParams({\\\\n                    tokenId: _params.tokenId,\\\\n                    recipient: address(this),\\\\n                    amount0Max: type(uint128).max,\\\\n                    amount1Max: type(uint128).max\\\\n                })\\\\n            )\\\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n            INonfungiblePositionManager.CollectParams({\\\\n                tokenId: _params.tokenId,\\\\n                recipient: address(this),\\\\n                amount0Max: type(uint128).max,\\\\n                amount1Max: type(uint128).max\\\\n            })\\\\n        );\\\\n\\\\n        return (_wPowerPerpAmount, wethAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\\\n     * @param _collateralToLp amount of ETH collateral to LP\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\\\n     * @param _lowerTick LP position lower tick\\\\n     * @param _upperTick LP position upper tick\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return exact amount0 and amount1 to be LPed\\\\n     */\\\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\\\n        uint256 amount0Desired; \\\\n        uint256 amount1Desired;\\\\n\\\\n        {\\\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\\\n        }\\\\n        \\\\n        return (amount0Desired, amount1Desired);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\\\n     * @param _controller wPowerPerp controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return _vaultId and tokenId\\\\n     */\\\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\\\n\\\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\\\n                \\\\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\\\n                _mintAndLpParams.vaultId,\\\\n                amountToMint,\\\\n                0\\\\n            );\\\\n        }\\\\n        // LP amount0Desired and amount1Desired in Uni v3\\\\n        uint256 uniTokenId = lpWPowerPerpPool(\\\\n            _nonfungiblePositionManager,\\\\n            _mintAndLpParams.wPowerPerpPool,\\\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\\\n                recipient: _mintAndLpParams.recipient,\\\\n                amount0Desired: amount0Desired,\\\\n                amount1Desired: amount1Desired,\\\\n                amount0Min: _mintAndLpParams.amount0Min,\\\\n                amount1Min: _mintAndLpParams.amount1Min,\\\\n                lowerTick: _mintAndLpParams.lowerTick,\\\\n                upperTick: _mintAndLpParams.upperTick\\\\n            })\\\\n        );\\\\n        return (_vaultId, uniTokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice increase liquidityin Uni v3 position\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault Id\\\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     */\\\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\\\n            (\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                int24 tickLower,\\\\n                int24 tickUpper,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                \\\\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\\\n\\\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n\\\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\\\n                    _vaultId,\\\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\\\n                    0\\\\n                );\\\\n            }\\\\n        }\\\\n\\\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\\\n            tokenId: _increaseLiquidityParam.tokenId,\\\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\\\n            deadline: block.timestamp\\\\n        });\\\\n\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp in vault\\\\n     * @param _controller controller address\\\\n     * @param _weth WETH address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\\\n     * @param _collateralToDeposit amount of collateral to deposit\\\\n     */\\\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\\\n\\\\n        uint256 vaultId = _vaultId;\\\\n        if (_wPowerPerpToMint > 0) {\\\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\\\n                _vaultId,\\\\n                _wPowerPerpToMint,\\\\n                0\\\\n            );\\\\n        } else {\\\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\\\n        }\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\\\n     * @param _controller controller address\\\\n     * @param _weth weth address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     */\\\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\\\n        IController(_controller).burnWPowerPerpAmount(\\\\n            _vaultId,\\\\n            _wPowerPerpToBurn,\\\\n            _collateralToWithdraw\\\\n        );\\\\n\\\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice LP into Uniswap V3 pool\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\\\n     */\\\\n    function lpWPowerPerpPool(\\\\n        address _nonfungiblePositionManager,\\\\n        address _wPowerPerpPool,\\\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\\\n    ) public returns (uint256) {\\\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\\\n            tickLower: int24(_params.lowerTick),\\\\n            tickUpper: int24(_params.upperTick),\\\\n            amount0Desired: _params.amount0Desired,\\\\n            amount1Desired: _params.amount1Desired,\\\\n            amount0Min: _params.amount0Min,\\\\n            amount1Min: _params.amount1Min,\\\\n            recipient: _params.recipient,\\\\n            deadline: block.timestamp\\\\n        });\\\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\\\n            mintParams\\\\n        );\\\\n        return tokenId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\\\n     * @param _user user address\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault ID\\\\n     * @param _tokenId Uni LP NFT id\\\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\\\n     */\\\\n    function checkClosedLp(\\\\n        address _user,\\\\n        address _controller,\\\\n        address _nonfungiblePositionManager,\\\\n        uint256 _vaultId,\\\\n        uint256 _tokenId,\\\\n        uint256 _liquidityPercentage\\\\n    ) public {\\\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\\\n                address(this),\\\\n                _user,\\\\n                _tokenId\\\\n            );\\\\n        } else {\\\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice send ETH and wPowerPerp\\\\n     * @param _weth WETH address\\\\n     * @param _wPowerPerp wPowerPerp address\\\\n     */\\\\n    function sendBack(address _weth, address _wPowerPerp) public {\\\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n        if (wPowerPerpBalance > 0) {\\\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x51c6185083d747a36ee8543219c0e7a326b866c0bdc113e82956cd4e226f7ba3\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/LiquidityAmounts.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"../../libs/SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\n\\\\n\\\\n/// @title Liquidity amount functions\\\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\\\nlibrary LiquidityAmounts {\\\\n    /// @notice Downcasts uint256 to uint128\\\\n    /// @param x The uint258 to be downcasted\\\\n    /// @return y The passed value, downcasted to uint128\\\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\\\n        require((y = uint128(x)) == x);\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount0 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount0(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount1 The amount1 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount1(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount of token0 being sent in\\\\n    /// @param amount1 The amount of token1 being sent in\\\\n    /// @return liquidity The maximum amount of liquidity received\\\\n    function getLiquidityForAmounts(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\\\n\\\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\\\n        } else {\\\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\\\n        }\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    function getAmount0ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            FullMath.mulDiv(\\\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\\\n                sqrtRatioBX96 - sqrtRatioAX96,\\\\n                sqrtRatioBX96\\\\n            ) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmount1ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n\\\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmountsForLiquidity(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\\\n        } else {\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        }\\\\n    }\\\\n\\\\n    function getAmountsFromLiquidity(        \\\\n        uint160 sqrtRatioX96,\\\\n        int24 currentTick,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (currentTick < tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else if (currentTick < tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtRatioX96,\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                sqrtRatioX96,\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            }\\\\n    \\\\n    }\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb4b0f464529a43f3ca7a9d6afc5976902c0a004649bdf3239ca77469d26b7cf2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x61294e610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100ad5760003560e01c80638e6940f011610080578063aee2533b11610065578063aee2533b14610198578063b573fa8b146101b8578063ec147e56146101cb576100ad565b80638e6940f0146101345780639f70f9e51461016b576100ad565b8063392f2708146100b257806351764a5e146100d457806363410a86146100f45780637a04dbd714610114575b600080fd5b8180156100be57600080fd5b506100d26100cd366004612153565b6101eb565b005b8180156100e057600080fd5b506100d26100ef366004611f91565b6102d4565b81801561010057600080fd5b506100d261010f366004612282565b6104c1565b81801561012057600080fd5b506100d261012f366004612056565b61056e565b81801561014057600080fd5b5061015461014f366004611fc9565b610865565b60405161016292919061284f565b60405180910390f35b81801561017757600080fd5b5061018b610186366004612282565b610b78565b6040516101629190612846565b8180156101a457600080fd5b5061018b6101b33660046121b7565b610cdf565b6101546101c636600461237c565b610f52565b8180156101d757600080fd5b506101546101e63660046122d2565b6111bd565b8215806101ff575080670de0b6b3a7640000145b1561026b57604051632142170760e11b81526001600160a01b038516906342842e0e906102349030908a90879060040161269c565b600060405180830381600087803b15801561024e57600080fd5b505af1158015610262573d6000803e3d6000fd5b505050506102cc565b6040516348dc69a560e11b81526001600160a01b038616906391b8d34a90610299908690869060040161284f565b600060405180830381600087803b1580156102b357600080fd5b505af11580156102c7573d6000803e3d6000fd5b505050505b505050505050565b6040516370a0823160e01b81526001600160a01b03831690632e1a7d4d9082906370a082319061030890309060040161266f565b60206040518083038186803b15801561032057600080fd5b505afa158015610334573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035891906124fb565b6040518263ffffffff1660e01b81526004016103749190612846565b600060405180830381600087803b15801561038e57600080fd5b505af11580156103a2573d6000803e3d6000fd5b506103b39250339150479050611424565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906103e290309060040161266f565b60206040518083038186803b1580156103fa57600080fd5b505afa15801561040e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043291906124fb565b905080156104bc5760405163a9059cbb60e01b81526001600160a01b0383169063a9059cbb906104689033908590600401612683565b602060405180830381600087803b15801561048257600080fd5b505af1158015610496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ba91906123dd565b505b505050565b604051638632cb0360e01b81526001600160a01b03861690638632cb03906104f19086908690869060040161285d565b600060405180830381600087803b15801561050b57600080fd5b505af115801561051f573d6000803e3d6000fd5b50505050600081111561056757836001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156102b357600080fd5b5050505050565b60408201511561077557600080876001600160a01b03166399fbab8885602001516040518263ffffffff1660e01b81526004016105ab9190612846565b6101806040518083038186803b1580156105c457600080fd5b505afa1580156105d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fc9190612573565b5050505050965096505050505050600080610623888760800151886040015187878a610f52565b9150915084610633578181610636565b80825b6080880152604080880191909152516370a0823160e01b81526000906001600160a01b038b16906370a082319061067190309060040161266f565b60206040518083038186803b15801561068957600080fd5b505afa15801561069d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c191906124fb565b9050866040015181101561076f578b6001600160a01b0316633946791888606001518a6106fb858c6040015161150990919063ffffffff16565b60006040518563ffffffff1660e01b815260040161071b9392919061285d565b6020604051808303818588803b15801561073457600080fd5b505af1158015610748573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061076d91906124fb565b505b50505050505b60006040518060c00160405280846020015181526020018361079b5784604001516107a1565b84608001515b8152602001836107b55784608001516107bb565b84604001515b81526020018460a0015181526020018460c001518152602001428152509050866001600160a01b031663219f5d17826040518263ffffffff1660e01b81526004016108069190612754565b606060405180830381600087803b15801561082057600080fd5b505af1158015610834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108589190612415565b5050505050505050505050565b600080846001600160a01b0316632e1a7d4d85608001356040518263ffffffff1660e01b81526004016108989190612846565b600060405180830381600087803b1580156108b257600080fd5b505af11580156108c6573d6000803e3d6000fd5b505050506000806109178660200160208101906108e39190611f59565b60a088013560608901356108ff6101208b016101008c016123f9565b6109116101408c016101208d016123f9565b8a610f52565b9092509050604086013560008661092e5783610930565b825b9050808a6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161095f919061266f565b60206040518083038186803b15801561097757600080fd5b505afa15801561098b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109af91906124fb565b1015610acd576040516370a0823160e01b8152610a3c906001600160a01b038c16906370a08231906109e590309060040161266f565b60206040518083038186803b1580156109fd57600080fd5b505afa158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3591906124fb565b8290611509565b90508b6001600160a01b0316633946791889608001358a604001358460006040518563ffffffff1660e01b8152600401610a789392919061285d565b6020604051808303818588803b158015610a9157600080fd5b505af1158015610aa5573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610aca91906124fb565b91505b6000610b648c610ae360408c0160208d01611f59565b6040805160e0810190915280610afc60208f018f611f59565b6001600160a01b031681526020018981526020018881526020018d60c0013581526020018d60e0013581526020018d610100016020810190610b3e91906123f9565b60020b81526020018d610120016020810190610b5a91906123f9565b60020b9052610cdf565b929d929c50919a5050505050505050505050565b60008115610bdf57604051632e1a7d4d60e01b81526001600160a01b03861690632e1a7d4d90610bac908590600401612846565b600060405180830381600087803b158015610bc657600080fd5b505af1158015610bda573d6000803e3d6000fd5b505050505b838315610c7257604051630728cf2360e31b81526001600160a01b038816906339467918908590610c19908990899060009060040161285d565b6020604051808303818588803b158015610c3257600080fd5b505af1158015610c46573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610c6b91906124fb565b9050610cd3565b60405163b6b55f2560e01b81526001600160a01b0388169063b6b55f25908590610ca0908990600401612846565b6000604051808303818588803b158015610cb957600080fd5b505af1158015610ccd573d6000803e3d6000fd5b50505050505b90505b95945050505050565b600080604051806101600160405280856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d2757600080fd5b505afa158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f9190611f75565b6001600160a01b03168152602001856001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610da657600080fd5b505afa158015610dba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dde9190611f75565b6001600160a01b03168152602001856001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610e2557600080fd5b505afa158015610e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5d91906124e1565b62ffffff1681526020018460a0015160020b81526020018460c0015160020b81526020018460200151815260200184604001518152602001846060015181526020018460800151815260200184600001516001600160a01b031681526020014281525090506000856001600160a01b03166388316456836040518263ffffffff1660e01b8152600401610ef09190612798565b608060405180830381600087803b158015610f0a57600080fd5b505af1158015610f1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f429190612513565b50919450505050505b9392505050565b60008060008060008a6001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610f9357600080fd5b505afa158015610fa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcb919061244b565b5050505050915050600073569292d3d8B44F02B11ef048A3Dd361e57880E8C63986cfba3836040518263ffffffff1660e01b815260040161100c91906126c0565b60206040518083038186803b15801561102457600080fd5b505af4158015611038573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105c9190611f75565b9050600073569292d3d8B44F02B11ef048A3Dd361e57880E8C63986cfba38b6040518263ffffffff1660e01b815260040161109791906126c0565b60206040518083038186803b1580156110af57600080fd5b505af41580156110c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e79190611f75565b9050600073569292d3d8B44F02B11ef048A3Dd361e57880E8C63986cfba38b6040518263ffffffff1660e01b815260040161112291906126c0565b60206040518083038186803b15801561113a57600080fd5b505af415801561114e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111729190611f75565b905088611180578b8d611183565b8c8c5b909650945060006111978484848a8a61156b565b90506111a684868e8e85611623565b909950975050505050505050965096945050505050565b60008060006040518060a0016040528086600001518152602001611204670de0b6b3a76400006111fe89604001518a6020015161196490919063ffffffff16565b906119bd565b6001600160801b0316815260200186606001516001600160801b0316815260200186608001516001600160801b03168152602001428152509050856001600160a01b0316630c49ccbe826040518263ffffffff1660e01b815260040161126a9190612711565b6040805180830381600087803b15801561128357600080fd5b505af1158015611297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bb9190612550565b5050600080856113705760408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f78659161131691906004016126ce565b6040805180830381600087803b15801561132f57600080fd5b505af1158015611343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113679190612550565b92509050611418565b60408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f7865916113c191906004016126ce565b6040805180830381600087803b1580156113da57600080fd5b505af11580156113ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114129190612550565b90925090505b97909650945050505050565b80471015611479576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146114c4576040519150601f19603f3d011682016040523d82523d6000602084013e6114c9565b606091505b50509050806104bc5760405162461bcd60e51b815260040180806020018281038252603a8152602001806128be603a913960400191505060405180910390fd5b600082821115611560576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000836001600160a01b0316856001600160a01b0316111561158b579293925b846001600160a01b0316866001600160a01b0316116115b6576115af858585611a24565b9050610cd6565b836001600160a01b0316866001600160a01b031610156116185760006115dd878686611a24565b905060006115ec878986611a90565b9050806001600160801b0316826001600160801b03161061160d578061160f565b815b92505050610cd6565b610cd3858584611a90565b6000808460020b8660020b12156116fc5773a932Db3b9f630436aeb5a9AF8687E521dc943569632c32d4b661165787611ade565b61166087611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b1580156116c957600080fd5b505af41580156116dd573d6000803e3d6000fd5b505050506040513d60208110156116f357600080fd5b5051915061195a565b8360020b8660020b12156118965773a932Db3b9f630436aeb5a9AF8687E521dc943569632c32d4b68861172e87611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561179757600080fd5b505af41580156117ab573d6000803e3d6000fd5b505050506040513d60208110156117c157600080fd5b5051915073a932Db3b9f630436aeb5a9AF8687E521dc9435696348a0c5bd6117e887611ade565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039283166004820152918b1660248301526001600160801b038716604483015260006064830152516084808301926020929190829003018186803b15801561186357600080fd5b505af4158015611877573d6000803e3d6000fd5b505050506040513d602081101561188d57600080fd5b5051905061195a565b73a932Db3b9f630436aeb5a9AF8687E521dc9435696348a0c5bd6118b987611ade565b6118c287611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561192b57600080fd5b505af415801561193f573d6000803e3d6000fd5b505050506040513d602081101561195557600080fd5b505190505b9550959350505050565b60008261197357506000611565565b8282028284828161198057fe5b0414610f4b5760405162461bcd60e51b81526004018080602001828103825260218152602001806128f86021913960400191505060405180910390fd5b6000808211611a13576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611a1c57fe5b049392505050565b6000826001600160a01b0316846001600160a01b03161115611a44579192915b6000611a70856001600160a01b0316856001600160a01b03166c01000000000000000000000000611e1d565b9050610cd6611a8b84838888036001600160a01b0316611e1d565b611ecc565b6000826001600160a01b0316846001600160a01b03161115611ab0579192915b611ad6611a8b836c010000000000000000000000008787036001600160a01b0316611e1d565b949350505050565b60008060008360020b12611af5578260020b611afd565b8260020b6000035b9050620d89e8811115611b3b576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216611b5c57700100000000000000000000000000000000611b6e565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615611ba2576ffff97272373d413259a46990580e213a0260801c5b6004821615611bc1576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615611be0576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615611bff576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615611c1e576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615611c3d576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615611c5c576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615611c7c576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615611c9c576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615611cbc576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615611cdc576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615611cfc576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615611d1c576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615611d3c576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615611d5c576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615611d7d576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615611d9d576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615611dbc576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615611dd9576b048a170391f7dc42444e8fa20260801c5b60008460020b1315611df4578060001981611df057fe5b0490505b640100000000810615611e08576001611e0b565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080611e535760008411611e4857600080fd5b508290049050610f4b565b808411611e5f57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b806001600160801b0381168114611ee257600080fd5b919050565b8035611ee281612873565b8051611ee281612873565b8035611ee28161288b565b8035611ee281612899565b8051611ee281612899565b8035611ee2816128a8565b8051611ee2816128a8565b805161ffff81168114611ee257600080fd5b805162ffffff81168114611ee257600080fd5b600060208284031215611f6a578081fd5b8135610f4b81612873565b600060208284031215611f86578081fd5b8151610f4b81612873565b60008060408385031215611fa3578081fd5b8235611fae81612873565b91506020830135611fbe81612873565b809150509250929050565b6000806000806000808688036101e0811215611fe3578283fd5b8735611fee81612873565b96506020880135611ffe81612873565b9550604088013561200e81612873565b9450606088013561201e81612873565b9350610140607f1982011215612032578283fd5b506080870191506101c08701356120488161288b565b809150509295509295509295565b60008060008060008060008789036101a0811215612072578182fd5b883561207d81612873565b9750602089013561208d81612873565b9650604089013561209d81612873565b955060608901356120ad81612873565b94506080890135935060e0609f19820112156120c7578182fd5b5060405160e0810181811067ffffffffffffffff821117156120e557fe5b6040526120f460a08a01611ee7565b815260c089810135602083015260e08a013560408301526101008a013560608301526101208a013560808301526101408a013560a08301526101608a01359082015291506121456101808901611efd565b905092959891949750929550565b60008060008060008060c0878903121561216b578384fd5b863561217681612873565b9550602087013561218681612873565b9450604087013561219681612873565b959894975094956060810135955060808101359460a0909101359350915050565b60008060008385036101208112156121cd578182fd5b84356121d881612873565b935060208501356121e881612873565b925060e0603f19820112156121fb578182fd5b5060405160e0810181811067ffffffffffffffff8211171561221957fe5b806040525061222a60408601611ee7565b8152606085013560208201526080850135604082015260a0850135606082015260c0850135608082015261226060e08601611f08565b60a08201526122726101008601611f08565b60c0820152809150509250925092565b600080600080600060a08688031215612299578283fd5b85356122a481612873565b945060208601356122b481612873565b94979496505050506040830135926060810135926080909101359150565b600080600083850360e08112156122e7578182fd5b84356122f281612873565b935060a0601f1982011215612305578182fd5b5060405160a0810181811067ffffffffffffffff8211171561232357fe5b806040525060208501358152604085013560208201526060850135604082015261234f60808601611f1e565b606082015261236060a08601611f1e565b6080820152915061237360c08501611efd565b90509250925092565b60008060008060008060c08789031215612394578384fd5b863561239f81612873565b9550602087013594506040870135935060608701356123bd81612899565b925060808701356123cd81612899565b915060a08701356120488161288b565b6000602082840312156123ee578081fd5b8151610f4b8161288b565b60006020828403121561240a578081fd5b8135610f4b81612899565b600080600060608486031215612429578081fd5b8351612434816128a8565b602085015160409095015190969495509392505050565b600080600080600080600060e0888a031215612465578081fd5b875161247081612873565b602089015190975061248181612899565b955061248f60408901611f34565b945061249d60608901611f34565b93506124ab60808901611f34565b925060a088015160ff811681146124c0578182fd5b60c08901519092506124d18161288b565b8091505092959891949750929550565b6000602082840312156124f2578081fd5b610f4b82611f46565b60006020828403121561250c578081fd5b5051919050565b60008060008060808587031215612528578182fd5b84519350602085015161253a816128a8565b6040860151606090960151949790965092505050565b60008060408385031215612562578182fd5b505080516020909101519092909150565b6000806000806000806000806000806000806101808d8f031215612595578586fd5b8c516bffffffffffffffffffffffff811681146125b0578687fd5b9b506125be60208e01611ef2565b9a506125cc60408e01611ef2565b99506125da60608e01611ef2565b98506125e860808e01611f46565b97506125f660a08e01611f13565b965061260460c08e01611f13565b955061261260e08e01611f29565b94506101008d015193506101208d015192506126316101408e01611f29565b91506126406101608e01611f29565b90509295989b509295989b509295989b565b6001600160a01b03169052565b60020b9052565b62ffffff169052565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60029190910b815260200190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6000610160820190506127ac828451612652565b60208301516127be6020840182612652565b5060408301516127d16040840182612666565b5060608301516127e4606084018261265f565b5060808301516127f7608084018261265f565b5060a083015160a083015260c083015160c083015260e083015160e08301526101008084015181840152506101208084015161283582850182612652565b505061014092830151919092015290565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b6001600160a01b038116811461288857600080fd5b50565b801515811461288857600080fd5b8060020b811461288857600080fd5b6001600160801b038116811461288857600080fdfe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220cfb89b72f5833964391283454a5a095d88e171c58035cad9299687278c762ec164736f6c63430007060033\",\n  \"deployedBytecode\": \"0x73000000000000000000000000000000000000000030146080604052600436106100ad5760003560e01c80638e6940f011610080578063aee2533b11610065578063aee2533b14610198578063b573fa8b146101b8578063ec147e56146101cb576100ad565b80638e6940f0146101345780639f70f9e51461016b576100ad565b8063392f2708146100b257806351764a5e146100d457806363410a86146100f45780637a04dbd714610114575b600080fd5b8180156100be57600080fd5b506100d26100cd366004612153565b6101eb565b005b8180156100e057600080fd5b506100d26100ef366004611f91565b6102d4565b81801561010057600080fd5b506100d261010f366004612282565b6104c1565b81801561012057600080fd5b506100d261012f366004612056565b61056e565b81801561014057600080fd5b5061015461014f366004611fc9565b610865565b60405161016292919061284f565b60405180910390f35b81801561017757600080fd5b5061018b610186366004612282565b610b78565b6040516101629190612846565b8180156101a457600080fd5b5061018b6101b33660046121b7565b610cdf565b6101546101c636600461237c565b610f52565b8180156101d757600080fd5b506101546101e63660046122d2565b6111bd565b8215806101ff575080670de0b6b3a7640000145b1561026b57604051632142170760e11b81526001600160a01b038516906342842e0e906102349030908a90879060040161269c565b600060405180830381600087803b15801561024e57600080fd5b505af1158015610262573d6000803e3d6000fd5b505050506102cc565b6040516348dc69a560e11b81526001600160a01b038616906391b8d34a90610299908690869060040161284f565b600060405180830381600087803b1580156102b357600080fd5b505af11580156102c7573d6000803e3d6000fd5b505050505b505050505050565b6040516370a0823160e01b81526001600160a01b03831690632e1a7d4d9082906370a082319061030890309060040161266f565b60206040518083038186803b15801561032057600080fd5b505afa158015610334573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035891906124fb565b6040518263ffffffff1660e01b81526004016103749190612846565b600060405180830381600087803b15801561038e57600080fd5b505af11580156103a2573d6000803e3d6000fd5b506103b39250339150479050611424565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906103e290309060040161266f565b60206040518083038186803b1580156103fa57600080fd5b505afa15801561040e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043291906124fb565b905080156104bc5760405163a9059cbb60e01b81526001600160a01b0383169063a9059cbb906104689033908590600401612683565b602060405180830381600087803b15801561048257600080fd5b505af1158015610496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ba91906123dd565b505b505050565b604051638632cb0360e01b81526001600160a01b03861690638632cb03906104f19086908690869060040161285d565b600060405180830381600087803b15801561050b57600080fd5b505af115801561051f573d6000803e3d6000fd5b50505050600081111561056757836001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156102b357600080fd5b5050505050565b60408201511561077557600080876001600160a01b03166399fbab8885602001516040518263ffffffff1660e01b81526004016105ab9190612846565b6101806040518083038186803b1580156105c457600080fd5b505afa1580156105d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fc9190612573565b5050505050965096505050505050600080610623888760800151886040015187878a610f52565b9150915084610633578181610636565b80825b6080880152604080880191909152516370a0823160e01b81526000906001600160a01b038b16906370a082319061067190309060040161266f565b60206040518083038186803b15801561068957600080fd5b505afa15801561069d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c191906124fb565b9050866040015181101561076f578b6001600160a01b0316633946791888606001518a6106fb858c6040015161150990919063ffffffff16565b60006040518563ffffffff1660e01b815260040161071b9392919061285d565b6020604051808303818588803b15801561073457600080fd5b505af1158015610748573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061076d91906124fb565b505b50505050505b60006040518060c00160405280846020015181526020018361079b5784604001516107a1565b84608001515b8152602001836107b55784608001516107bb565b84604001515b81526020018460a0015181526020018460c001518152602001428152509050866001600160a01b031663219f5d17826040518263ffffffff1660e01b81526004016108069190612754565b606060405180830381600087803b15801561082057600080fd5b505af1158015610834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108589190612415565b5050505050505050505050565b600080846001600160a01b0316632e1a7d4d85608001356040518263ffffffff1660e01b81526004016108989190612846565b600060405180830381600087803b1580156108b257600080fd5b505af11580156108c6573d6000803e3d6000fd5b505050506000806109178660200160208101906108e39190611f59565b60a088013560608901356108ff6101208b016101008c016123f9565b6109116101408c016101208d016123f9565b8a610f52565b9092509050604086013560008661092e5783610930565b825b9050808a6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161095f919061266f565b60206040518083038186803b15801561097757600080fd5b505afa15801561098b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109af91906124fb565b1015610acd576040516370a0823160e01b8152610a3c906001600160a01b038c16906370a08231906109e590309060040161266f565b60206040518083038186803b1580156109fd57600080fd5b505afa158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3591906124fb565b8290611509565b90508b6001600160a01b0316633946791889608001358a604001358460006040518563ffffffff1660e01b8152600401610a789392919061285d565b6020604051808303818588803b158015610a9157600080fd5b505af1158015610aa5573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610aca91906124fb565b91505b6000610b648c610ae360408c0160208d01611f59565b6040805160e0810190915280610afc60208f018f611f59565b6001600160a01b031681526020018981526020018881526020018d60c0013581526020018d60e0013581526020018d610100016020810190610b3e91906123f9565b60020b81526020018d610120016020810190610b5a91906123f9565b60020b9052610cdf565b929d929c50919a5050505050505050505050565b60008115610bdf57604051632e1a7d4d60e01b81526001600160a01b03861690632e1a7d4d90610bac908590600401612846565b600060405180830381600087803b158015610bc657600080fd5b505af1158015610bda573d6000803e3d6000fd5b505050505b838315610c7257604051630728cf2360e31b81526001600160a01b038816906339467918908590610c19908990899060009060040161285d565b6020604051808303818588803b158015610c3257600080fd5b505af1158015610c46573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610c6b91906124fb565b9050610cd3565b60405163b6b55f2560e01b81526001600160a01b0388169063b6b55f25908590610ca0908990600401612846565b6000604051808303818588803b158015610cb957600080fd5b505af1158015610ccd573d6000803e3d6000fd5b50505050505b90505b95945050505050565b600080604051806101600160405280856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d2757600080fd5b505afa158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f9190611f75565b6001600160a01b03168152602001856001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610da657600080fd5b505afa158015610dba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dde9190611f75565b6001600160a01b03168152602001856001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610e2557600080fd5b505afa158015610e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5d91906124e1565b62ffffff1681526020018460a0015160020b81526020018460c0015160020b81526020018460200151815260200184604001518152602001846060015181526020018460800151815260200184600001516001600160a01b031681526020014281525090506000856001600160a01b03166388316456836040518263ffffffff1660e01b8152600401610ef09190612798565b608060405180830381600087803b158015610f0a57600080fd5b505af1158015610f1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f429190612513565b50919450505050505b9392505050565b60008060008060008a6001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610f9357600080fd5b505afa158015610fa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcb919061244b565b5050505050915050600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba3836040518263ffffffff1660e01b815260040161100c91906126c0565b60206040518083038186803b15801561102457600080fd5b505af4158015611038573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105c9190611f75565b9050600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba38b6040518263ffffffff1660e01b815260040161109791906126c0565b60206040518083038186803b1580156110af57600080fd5b505af41580156110c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e79190611f75565b9050600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba38b6040518263ffffffff1660e01b815260040161112291906126c0565b60206040518083038186803b15801561113a57600080fd5b505af415801561114e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111729190611f75565b905088611180578b8d611183565b8c8c5b909650945060006111978484848a8a61156b565b90506111a684868e8e85611623565b909950975050505050505050965096945050505050565b60008060006040518060a0016040528086600001518152602001611204670de0b6b3a76400006111fe89604001518a6020015161196490919063ffffffff16565b906119bd565b6001600160801b0316815260200186606001516001600160801b0316815260200186608001516001600160801b03168152602001428152509050856001600160a01b0316630c49ccbe826040518263ffffffff1660e01b815260040161126a9190612711565b6040805180830381600087803b15801561128357600080fd5b505af1158015611297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bb9190612550565b5050600080856113705760408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f78659161131691906004016126ce565b6040805180830381600087803b15801561132f57600080fd5b505af1158015611343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113679190612550565b92509050611418565b60408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f7865916113c191906004016126ce565b6040805180830381600087803b1580156113da57600080fd5b505af11580156113ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114129190612550565b90925090505b97909650945050505050565b80471015611479576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146114c4576040519150601f19603f3d011682016040523d82523d6000602084013e6114c9565b606091505b50509050806104bc5760405162461bcd60e51b815260040180806020018281038252603a8152602001806128be603a913960400191505060405180910390fd5b600082821115611560576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000836001600160a01b0316856001600160a01b0316111561158b579293925b846001600160a01b0316866001600160a01b0316116115b6576115af858585611a24565b9050610cd6565b836001600160a01b0316866001600160a01b031610156116185760006115dd878686611a24565b905060006115ec878986611a90565b9050806001600160801b0316826001600160801b03161061160d578061160f565b815b92505050610cd6565b610cd3858584611a90565b6000808460020b8660020b12156116fc5773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b661165787611ade565b61166087611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b1580156116c957600080fd5b505af41580156116dd573d6000803e3d6000fd5b505050506040513d60208110156116f357600080fd5b5051915061195a565b8360020b8660020b12156118965773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b68861172e87611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561179757600080fd5b505af41580156117ab573d6000803e3d6000fd5b505050506040513d60208110156117c157600080fd5b5051915073__$a98c5df505b68ab2f483703658c95acb30$__6348a0c5bd6117e887611ade565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039283166004820152918b1660248301526001600160801b038716604483015260006064830152516084808301926020929190829003018186803b15801561186357600080fd5b505af4158015611877573d6000803e3d6000fd5b505050506040513d602081101561188d57600080fd5b5051905061195a565b73__$a98c5df505b68ab2f483703658c95acb30$__6348a0c5bd6118b987611ade565b6118c287611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561192b57600080fd5b505af415801561193f573d6000803e3d6000fd5b505050506040513d602081101561195557600080fd5b505190505b9550959350505050565b60008261197357506000611565565b8282028284828161198057fe5b0414610f4b5760405162461bcd60e51b81526004018080602001828103825260218152602001806128f86021913960400191505060405180910390fd5b6000808211611a13576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611a1c57fe5b049392505050565b6000826001600160a01b0316846001600160a01b03161115611a44579192915b6000611a70856001600160a01b0316856001600160a01b03166c01000000000000000000000000611e1d565b9050610cd6611a8b84838888036001600160a01b0316611e1d565b611ecc565b6000826001600160a01b0316846001600160a01b03161115611ab0579192915b611ad6611a8b836c010000000000000000000000008787036001600160a01b0316611e1d565b949350505050565b60008060008360020b12611af5578260020b611afd565b8260020b6000035b9050620d89e8811115611b3b576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216611b5c57700100000000000000000000000000000000611b6e565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615611ba2576ffff97272373d413259a46990580e213a0260801c5b6004821615611bc1576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615611be0576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615611bff576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615611c1e576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615611c3d576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615611c5c576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615611c7c576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615611c9c576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615611cbc576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615611cdc576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615611cfc576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615611d1c576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615611d3c576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615611d5c576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615611d7d576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615611d9d576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615611dbc576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615611dd9576b048a170391f7dc42444e8fa20260801c5b60008460020b1315611df4578060001981611df057fe5b0490505b640100000000810615611e08576001611e0b565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080611e535760008411611e4857600080fd5b508290049050610f4b565b808411611e5f57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b806001600160801b0381168114611ee257600080fd5b919050565b8035611ee281612873565b8051611ee281612873565b8035611ee28161288b565b8035611ee281612899565b8051611ee281612899565b8035611ee2816128a8565b8051611ee2816128a8565b805161ffff81168114611ee257600080fd5b805162ffffff81168114611ee257600080fd5b600060208284031215611f6a578081fd5b8135610f4b81612873565b600060208284031215611f86578081fd5b8151610f4b81612873565b60008060408385031215611fa3578081fd5b8235611fae81612873565b91506020830135611fbe81612873565b809150509250929050565b6000806000806000808688036101e0811215611fe3578283fd5b8735611fee81612873565b96506020880135611ffe81612873565b9550604088013561200e81612873565b9450606088013561201e81612873565b9350610140607f1982011215612032578283fd5b506080870191506101c08701356120488161288b565b809150509295509295509295565b60008060008060008060008789036101a0811215612072578182fd5b883561207d81612873565b9750602089013561208d81612873565b9650604089013561209d81612873565b955060608901356120ad81612873565b94506080890135935060e0609f19820112156120c7578182fd5b5060405160e0810181811067ffffffffffffffff821117156120e557fe5b6040526120f460a08a01611ee7565b815260c089810135602083015260e08a013560408301526101008a013560608301526101208a013560808301526101408a013560a08301526101608a01359082015291506121456101808901611efd565b905092959891949750929550565b60008060008060008060c0878903121561216b578384fd5b863561217681612873565b9550602087013561218681612873565b9450604087013561219681612873565b959894975094956060810135955060808101359460a0909101359350915050565b60008060008385036101208112156121cd578182fd5b84356121d881612873565b935060208501356121e881612873565b925060e0603f19820112156121fb578182fd5b5060405160e0810181811067ffffffffffffffff8211171561221957fe5b806040525061222a60408601611ee7565b8152606085013560208201526080850135604082015260a0850135606082015260c0850135608082015261226060e08601611f08565b60a08201526122726101008601611f08565b60c0820152809150509250925092565b600080600080600060a08688031215612299578283fd5b85356122a481612873565b945060208601356122b481612873565b94979496505050506040830135926060810135926080909101359150565b600080600083850360e08112156122e7578182fd5b84356122f281612873565b935060a0601f1982011215612305578182fd5b5060405160a0810181811067ffffffffffffffff8211171561232357fe5b806040525060208501358152604085013560208201526060850135604082015261234f60808601611f1e565b606082015261236060a08601611f1e565b6080820152915061237360c08501611efd565b90509250925092565b60008060008060008060c08789031215612394578384fd5b863561239f81612873565b9550602087013594506040870135935060608701356123bd81612899565b925060808701356123cd81612899565b915060a08701356120488161288b565b6000602082840312156123ee578081fd5b8151610f4b8161288b565b60006020828403121561240a578081fd5b8135610f4b81612899565b600080600060608486031215612429578081fd5b8351612434816128a8565b602085015160409095015190969495509392505050565b600080600080600080600060e0888a031215612465578081fd5b875161247081612873565b602089015190975061248181612899565b955061248f60408901611f34565b945061249d60608901611f34565b93506124ab60808901611f34565b925060a088015160ff811681146124c0578182fd5b60c08901519092506124d18161288b565b8091505092959891949750929550565b6000602082840312156124f2578081fd5b610f4b82611f46565b60006020828403121561250c578081fd5b5051919050565b60008060008060808587031215612528578182fd5b84519350602085015161253a816128a8565b6040860151606090960151949790965092505050565b60008060408385031215612562578182fd5b505080516020909101519092909150565b6000806000806000806000806000806000806101808d8f031215612595578586fd5b8c516bffffffffffffffffffffffff811681146125b0578687fd5b9b506125be60208e01611ef2565b9a506125cc60408e01611ef2565b99506125da60608e01611ef2565b98506125e860808e01611f46565b97506125f660a08e01611f13565b965061260460c08e01611f13565b955061261260e08e01611f29565b94506101008d015193506101208d015192506126316101408e01611f29565b91506126406101608e01611f29565b90509295989b509295989b509295989b565b6001600160a01b03169052565b60020b9052565b62ffffff169052565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60029190910b815260200190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6000610160820190506127ac828451612652565b60208301516127be6020840182612652565b5060408301516127d16040840182612666565b5060608301516127e4606084018261265f565b5060808301516127f7608084018261265f565b5060a083015160a083015260c083015160c083015260e083015160e08301526101008084015181840152506101208084015161283582850182612652565b505061014092830151919092015290565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b6001600160a01b038116811461288857600080fd5b50565b801515811461288857600080fd5b8060020b811461288857600080fd5b6001600160801b038116811461288857600080fdfe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220cfb89b72f5833964391283454a5a095d88e171c58035cad9299687278c762ec164736f6c63430007060033\",\n  \"libraries\": {\n    \"TickMathExternal\": \"0x569292d3d8B44F02B11ef048A3Dd361e57880E8C\",\n    \"SqrtPriceMathPartial\": \"0xa932Db3b9f630436aeb5a9AF8687E521dc943569\"\n  },\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_collateralToWithdraw\": \"amount of collateral to withdraw\",\n          \"_controller\": \"controller address\",\n          \"_vaultId\": \"vault Id\",\n          \"_wPowerPerpToBurn\": \"amount of wPowerPerp to burn\",\n          \"_weth\": \"weth address\"\n        }\n      },\n      \"checkClosedLp(address,address,address,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_controller\": \"controller address\",\n          \"_liquidityPercentage\": \"percentage of liquidity that was closed from total amount\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_tokenId\": \"Uni LP NFT id\",\n          \"_user\": \"user address\",\n          \"_vaultId\": \"vault ID\"\n        }\n      },\n      \"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\": {\n        \"params\": {\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_params\": \"ControllerHelperDataType.CloseUniLpParams struct \"\n        },\n        \"returns\": {\n          \"_0\": \"withdrawn wPowerPerp and WETH amounts\"\n        }\n      },\n      \"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\": {\n        \"params\": {\n          \"_collateralToLp\": \"amount of ETH collateral to LP\",\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_lowerTick\": \"LP position lower tick\",\n          \"_upperTick\": \"LP position upper tick\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to LP\",\n          \"_wPowerPerpPool\": \"wPowerPerp Uni v3 pool (oSQTH/ETH pool)\"\n        },\n        \"returns\": {\n          \"_0\": \"exact amount0 and amount1 to be LPed\"\n        }\n      },\n      \"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\": {\n        \"params\": {\n          \"_controller\": \"controller address\",\n          \"_increaseLiquidityParam\": \"ControllerHelperDataType.IncreaseLpLiquidityParams struct\",\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_vaultId\": \"vault Id\"\n        }\n      },\n      \"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\": {\n        \"params\": {\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_params\": \"ControllerHelperDataType.LpWPowerPerpPoolParams struct\",\n          \"_wPowerPerpPool\": \"wPowerpPerp pool address in Uni v3\"\n        }\n      },\n      \"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\": {\n        \"params\": {\n          \"_controller\": \"wPowerPerp controller address\",\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_mintAndLpParams\": \"ControllerHelperDataType.MintAndLpParams struct\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\"\n        },\n        \"returns\": {\n          \"_0\": \"_vaultId and tokenId\"\n        }\n      },\n      \"mintDepositInVault(address,address,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_collateralToDeposit\": \"amount of collateral to deposit\",\n          \"_controller\": \"controller address\",\n          \"_vaultId\": \"vault Id\",\n          \"_wPowerPerpToMint\": \"amount of wPowerPerp to mint\",\n          \"_weth\": \"WETH address\"\n        }\n      },\n      \"sendBack(address,address)\": {\n        \"params\": {\n          \"_wPowerPerp\": \"wPowerPerp address\",\n          \"_weth\": \"WETH address\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\": {\n        \"notice\": \"burn wPowerPerp or just withdraw collateral from vault (or both)\"\n      },\n      \"checkClosedLp(address,address,address,uint256,uint256,uint256)\": {\n        \"notice\": \"transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\"\n      },\n      \"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\": {\n        \"notice\": \"fully or partially close Uni v3 LP\"\n      },\n      \"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\": {\n        \"notice\": \"get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\"\n      },\n      \"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\": {\n        \"notice\": \"increase liquidityin Uni v3 position\"\n      },\n      \"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\": {\n        \"notice\": \"LP into Uniswap V3 pool\"\n      },\n      \"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\": {\n        \"notice\": \"minth amount of wPowerPerp and LP in weth/wPowerPerp pool\"\n      },\n      \"mintDepositInVault(address,address,uint256,uint256,uint256)\": {\n        \"notice\": \"mint wPowerPerp in vault\"\n      },\n      \"sendBack(address,address)\": {\n        \"notice\": \"send ETH and wPowerPerp\"\n      }\n    },\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/CrabHelper.json",
    "content": "{\n  \"address\": \"0xFB02DBd2f3803d660413335789291186A0390E35\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_crab\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_swapRouter\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"depositedERC20\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"depositedAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"depositedEthAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"returnedEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDepositERC20\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawnERC20\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"withdrawnAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"withdrawnEthAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdrawERC20\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"crab\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToDeposit\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amountIn\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minEthToGet\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_erc20Fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_wPowerPerpFee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_tokenIn\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"flashDepositERC20\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxEthToPay\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_tokenOut\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minAmountOut\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_erc20Fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_wPowerPerpFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashWithdrawERC20\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"swapRouter\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract ISwapRouter\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0xdcac8d8feddb168721dabd92614b48baf29e20b50e7c5f07ef3188c486924f90\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0xFB02DBd2f3803d660413335789291186A0390E35\",\n    \"transactionIndex\": 36,\n    \"gasUsed\": \"821234\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x53c923caed0257bed62dba32ac58f8fe2c5a22047cc62f21668cf8258491b4c6\",\n    \"transactionHash\": \"0xdcac8d8feddb168721dabd92614b48baf29e20b50e7c5f07ef3188c486924f90\",\n    \"logs\": [],\n    \"blockNumber\": 8014068,\n    \"cumulativeGasUsed\": \"7924875\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x3fF39f6BF8156bdA997D93E3EFF6904c2bc4481f\",\n    \"0x833A158dA5ceBc44901211427E9Df936023EC0d3\"\n  ],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_crab\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_swapRouter\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositedERC20\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"depositedAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"depositedEthAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"returnedEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDepositERC20\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawnERC20\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"withdrawnAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"withdrawnEthAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdrawERC20\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"crab\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amountIn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minEthToGet\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_erc20Fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_wPowerPerpFee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_tokenIn\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"flashDepositERC20\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxEthToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minAmountOut\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_erc20Fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_wPowerPerpFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashWithdrawERC20\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"swapRouter\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract ISwapRouter\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"author\\\":\\\"Opyn team\\\",\\\"details\\\":\\\"CrabHelper contract\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"constructor\\\":{\\\"params\\\":{\\\"_crab\\\":\\\"address of crabV2 contract\\\",\\\"_swapRouter\\\":\\\"address of Uniswap swap router\\\"}},\\\"flashDepositERC20(uint256,uint256,uint256,uint24,uint24,address)\\\":{\\\"params\\\":{\\\"_amountIn\\\":\\\"amount of ERC20 token to swap for weth\\\",\\\"_erc20Fee\\\":\\\"pool fee for transfer ERC20/eth pool (3000 = 30bps)\\\",\\\"_ethToDeposit\\\":\\\"amount of ETH to deposit\\\",\\\"_minEthToGet\\\":\\\"min amount of ETH to receive in the swap\\\",\\\"_tokenIn\\\":\\\"ERC20 token to pay\\\",\\\"_wPowerPerpFee\\\":\\\"pool fee for wPowerPerp/eth pool (3000 = 30bps)\\\"}},\\\"flashWithdrawERC20(uint256,uint256,address,uint256,uint24,uint24)\\\":{\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of crab shares to withdraw\\\",\\\"_erc20Fee\\\":\\\"pool fee for transfer ERC20/eth pool (3000 = 30bps)\\\",\\\"_maxEthToPay\\\":\\\"max eth to pay in swap for wPowerPerp\\\",\\\"_minAmountOut\\\":\\\"min amount of ERC20 to receive\\\",\\\"_tokenOut\\\":\\\"ERC20 token to receive\\\",\\\"_wPowerPerpFee\\\":\\\"pool fee for wPowerPerp/eth pool (3000 = 30bps)\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"constructor\\\":{\\\"notice\\\":\\\"constructor\\\"},\\\"flashDepositERC20(uint256,uint256,uint256,uint24,uint24,address)\\\":{\\\"notice\\\":\\\"allows user to flash deposit into crab from an aribtrary ERC20\\\"},\\\"flashWithdrawERC20(uint256,uint256,address,uint256,uint24,uint24)\\\":{\\\"notice\\\":\\\"allows user to flash withdraw from crab to an aribtrary ERC20\\\"}},\\\"notice\\\":\\\"Contract for Crab helper functions\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/strategy/CrabHelper.sol\\\":\\\"CrabHelper\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\\\n\\\\n/// @title Router token swapping functionality\\\\n/// @notice Functions for swapping tokens via Uniswap V3\\\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\\\n    struct ExactInputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactInputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactOutputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\\\n\\\\n    struct ExactOutputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9bfaf1feb32814623e627ab70f2409760b15d95f1f9b058e2b3399a8bb732975\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/ICrabStrategyV2.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\ninterface ICrabStrategyV2 {\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\\\\n\\\\n    function flashWithdraw(\\\\n        uint256 _crabAmount,\\\\n        uint256 _maxEthToPay,\\\\n        uint24 _poolFee\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xabf84430d693a3a3ef9c04147da7c26f9698fdbb14abeab60a6ec1c8f24cbeab\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/strategy/CrabHelper.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {ICrabStrategyV2} from \\\\\\\"../interfaces/ICrabStrategyV2.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\nimport \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n\\\\nimport {StrategySwap} from \\\\\\\"./helper/StrategySwap.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev CrabHelper contract\\\\n * @notice Contract for Crab helper functions\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\\\n    using Address for address payable;\\\\n\\\\n    address public immutable crab;\\\\n    address public immutable weth;\\\\n\\\\n    event FlashDepositERC20(\\\\n        address indexed depositor,\\\\n        address depositedERC20,\\\\n        uint256 depositedAmount,\\\\n        uint256 depositedEthAmount,\\\\n        uint256 crabAmount,\\\\n        uint256 returnedEth\\\\n    );\\\\n\\\\n    event FlashWithdrawERC20(\\\\n        address indexed withdrawer,\\\\n        address withdrawnERC20,\\\\n        uint256 withdrawnAmount,\\\\n        uint256 withdrawnEthAmount,\\\\n        uint256 crabAmount\\\\n    );\\\\n\\\\n    /**\\\\n     * @notice constructor\\\\n     * @param _crab address of crabV2 contract\\\\n     * @param _swapRouter address of Uniswap swap router\\\\n     */\\\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\\\n        require(_crab != address(0), \\\\\\\"Invalid crab address\\\\\\\");\\\\n\\\\n        crab = _crab;\\\\n        weth = ICrabStrategyV2(_crab).weth();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\\\\n     * @param _ethToDeposit amount of ETH to deposit\\\\n     * @param _amountIn amount of ERC20 token to swap for weth\\\\n     * @param _minEthToGet min amount of ETH to receive in the swap\\\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\\\n     * @param _tokenIn ERC20 token to pay\\\\n     */\\\\n    function flashDepositERC20(\\\\n        uint256 _ethToDeposit,\\\\n        uint256 _amountIn,\\\\n        uint256 _minEthToGet,\\\\n        uint24 _erc20Fee,\\\\n        uint24 _wPowerPerpFee,\\\\n        address _tokenIn\\\\n    ) external nonReentrant {\\\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\\\\n\\\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\\\\n\\\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\\\n\\\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\\\n\\\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\\\n\\\\n        if (address(this).balance > 0) {\\\\n            payable(msg.sender).sendValue(address(this).balance);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\\\\n     * @param _crabAmount amount of crab shares to withdraw\\\\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\\\\n     * @param _tokenOut ERC20 token to receive\\\\n     * @param _minAmountOut min amount of ERC20 to receive\\\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\\\n     */\\\\n    function flashWithdrawERC20(\\\\n        uint256 _crabAmount,\\\\n        uint256 _maxEthToPay,\\\\n        address _tokenOut,\\\\n        uint256 _minAmountOut,\\\\n        uint24 _erc20Fee,\\\\n        uint24 _wPowerPerpFee\\\\n    ) external nonReentrant {\\\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\\\n\\\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\\\\n\\\\n        uint256 ethBalance = address(this).balance;\\\\n        IWETH9(weth).deposit{value: ethBalance}();\\\\n        uint256 tokenReceived = _swapExactInputSingle(\\\\n            weth,\\\\n            _tokenOut,\\\\n            address(this),\\\\n            msg.sender,\\\\n            ethBalance,\\\\n            _minAmountOut,\\\\n            _erc20Fee\\\\n        );\\\\n\\\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == crab, \\\\\\\"Cannot receive eth\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4775406a9d21e895ccc6b03f91263810aa4a000cf573cb8883f3500d826e911e\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/strategy/helper/StrategySwap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\\\\\";\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ncontract StrategySwap {\\\\n    ISwapRouter public immutable swapRouter;\\\\n\\\\n    constructor(address _swapRouter) {\\\\n        require(_swapRouter != address(0), \\\\\\\"invalid swap router address\\\\\\\");\\\\n        swapRouter = ISwapRouter(_swapRouter);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _from from which user we are selling\\\\n     * @param _to Recipient to get the tokens\\\\n     * @param _amountIn Exact amount to sell\\\\n     * @param _minAmountOut Minimum amount to be paid\\\\n     * @param _fee pool fee\\\\n     * @return amountOut The amount of WETH9 received.\\\\n     */\\\\n    function _swapExactInputSingle(\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        address _from,\\\\n        address _to,\\\\n        uint256 _amountIn,\\\\n        uint256 _minAmountOut,\\\\n        uint24 _fee\\\\n    ) internal returns (uint256 amountOut) {\\\\n        // _from must approve this contract\\\\n\\\\n        // Transfer the specified amount of tokenIn to this contract.\\\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\\\n\\\\n        // Approve the router to spend tokenIn.\\\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\\\n\\\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\\\n            tokenIn: _tokenIn,\\\\n            tokenOut: _tokenOut,\\\\n            fee: _fee,\\\\n            recipient: _to,\\\\n            deadline: block.timestamp,\\\\n            amountIn: _amountIn,\\\\n            amountOutMinimum: _minAmountOut,\\\\n            sqrtPriceLimitX96: 0\\\\n        });\\\\n\\\\n        // The call to `exactInputSingle` executes the swap.\\\\n        amountOut = swapRouter.exactInputSingle(params);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x06b92720043fa9d2999d0d895ee3d058999a297e97b592a5d61ad00d09051e24\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60e060405234801561001057600080fd5b50604051610f84380380610f848339818101604052604081101561003357600080fd5b508051602090910151806001600160a01b03811661006c5760405162461bcd60e51b815260040161006390610176565b60405180910390fd5b60601b6001600160601b03191660805260016000556001600160a01b0382166100dc576040805162461bcd60e51b815260206004820152601460248201527f496e76616c696420637261622061646472657373000000000000000000000000604482015290519081900360640190fd5b816001600160a01b031660a0816001600160a01b031660601b81525050816001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b15801561013257600080fd5b505afa158015610146573d6000803e3d6000fd5b505050506040513d602081101561015c57600080fd5b505160601b6001600160601b03191660c052506101ad9050565b6020808252601b908201527f696e76616c6964207377617020726f7574657220616464726573730000000000604082015260600190565b60805160601c60a05160601c60c05160601c610d6361022160003980606e52806103c3528061043c52806104cc528061057552806105bf52508060a052806102b4528061035d52806104f052806106a9528061073752806108505250806108e452806109b05280610a8a5250610d636000f3fe60806040526004361061005e5760003560e01c80634285512d116100435780634285512d146101a3578063bca4f628146101b8578063c31c9c071461021357610115565b806302c6600c1461011a5780633fc8cef31461017257610115565b3661011557336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100c25750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610113576040805162461bcd60e51b815260206004820152601260248201527f43616e6e6f742072656365697665206574680000000000000000000000000000604482015290519081900360640190fd5b005b600080fd5b34801561012657600080fd5b50610113600480360360c081101561013d57600080fd5b508035906020810135906001600160a01b036040820135169060608101359062ffffff608082013581169160a0013516610228565b34801561017e57600080fd5b506101876104ca565b604080516001600160a01b039092168252519081900360200190f35b3480156101af57600080fd5b506101876104ee565b3480156101c457600080fd5b50610113600480360360c08110156101db57600080fd5b50803590602081013590604081013590606081013562ffffff9081169160808101359091169060a001356001600160a01b0316610512565b34801561021f57600080fd5b506101876108e2565b60026000541415610280576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000908155604080516323b872dd60e01b81523360048201523060248201526044810189905290516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926323b872dd92606480820193602093909283900390910190829087803b1580156102fe57600080fd5b505af1158015610312573d6000803e3d6000fd5b505050506040513d602081101561032857600080fd5b505060408051630b52b7ff60e41b8152600481018890526024810187905262ffffff8316604482015290516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163b52b7ff091606480830192600092919082900301818387803b1580156103a457600080fd5b505af11580156103b8573d6000803e3d6000fd5b5050505060004790507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561041c57600080fd5b505af1158015610430573d6000803e3d6000fd5b505050505060006104667f0000000000000000000000000000000000000000000000000000000000000000873033868a8a610906565b604080516001600160a01b038916815260208101839052808201859052606081018b9052905191925033917f614f663be393aac8fd2c2993040a634f5b013b3d5f418cc59ad013e96eef53f99181900360800190a250506001600055505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6002600054141561056a576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260005561059e817f00000000000000000000000000000000000000000000000000000000000000003330898989610906565b50604080516370a0823160e01b815230600482015290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691632e1a7d4d9183916370a08231916024808301926020929190829003018186803b15801561060d57600080fd5b505afa158015610621573d6000803e3d6000fd5b505050506040513d602081101561063757600080fd5b5051604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925251602480830192600092919082900301818387803b15801561068f57600080fd5b505af11580156106a3573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fc5b73ff4788856040518463ffffffff1660e01b8152600401808381526020018262ffffff168152602001925050506000604051808303818588803b15801561071a57600080fd5b505af115801561072e573d6000803e3d6000fd5b505050505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156107a257600080fd5b505afa1580156107b6573d6000803e3d6000fd5b505050506040513d60208110156107cc57600080fd5b5051604080516001600160a01b0385168152602081018990528082018a905260608101839052476080820152905191925033917fc723e34ef5da33ff97116afe67fb4330d3189467330363a49eb6c9d2fd762a8c9181900360a00190a26040805163a9059cbb60e01b81523360048201526024810183905290516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb9160448083019260209291908290030181600087803b15801561089857600080fd5b505af11580156108ac573d6000803e3d6000fd5b505050506040513d60208110156108c257600080fd5b505047156108d4576108d43347610b1e565b505060016000555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516323b872dd60e01b81526000906001600160a01b038916906323b872dd9061093990899030908990600401610c47565b602060405180830381600087803b15801561095357600080fd5b505af1158015610967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098b9190610c08565b5060405163095ea7b360e01b81526001600160a01b0389169063095ea7b3906109da907f0000000000000000000000000000000000000000000000000000000000000000908890600401610c6b565b602060405180830381600087803b1580156109f457600080fd5b505af1158015610a08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2c9190610c08565b5060408051610100810182526001600160a01b03808b168252898116602083015262ffffff851682840152878116606083015242608083015260a0820187905260c08201869052600060e0830152915163414bf38960e01b815290917f0000000000000000000000000000000000000000000000000000000000000000169063414bf38990610abf908490600401610c84565b602060405180830381600087803b158015610ad957600080fd5b505af1158015610aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b119190610c2f565b9998505050505050505050565b80471015610b73576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610bbe576040519150601f19603f3d011682016040523d82523d6000602084013e610bc3565b606091505b5050905080610c035760405162461bcd60e51b815260040180806020018281038252603a815260200180610cf4603a913960400191505060405180910390fd5b505050565b600060208284031215610c19578081fd5b81518015158114610c28578182fd5b9392505050565b600060208284031215610c40578081fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6000610100820190506001600160a01b0380845116835280602085015116602084015262ffffff60408501511660408401528060608501511660608401526080840151608084015260a084015160a084015260c084015160c08401528060e08501511660e0840152509291505056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a2646970667358221220fcd43e471a4f1be2f1f1ccf4169e3d06484dd0cc15e022ffbfc5207a7fbbdf4664736f6c63430007060033\",\n  \"deployedBytecode\": \"0x60806040526004361061005e5760003560e01c80634285512d116100435780634285512d146101a3578063bca4f628146101b8578063c31c9c071461021357610115565b806302c6600c1461011a5780633fc8cef31461017257610115565b3661011557336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100c25750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610113576040805162461bcd60e51b815260206004820152601260248201527f43616e6e6f742072656365697665206574680000000000000000000000000000604482015290519081900360640190fd5b005b600080fd5b34801561012657600080fd5b50610113600480360360c081101561013d57600080fd5b508035906020810135906001600160a01b036040820135169060608101359062ffffff608082013581169160a0013516610228565b34801561017e57600080fd5b506101876104ca565b604080516001600160a01b039092168252519081900360200190f35b3480156101af57600080fd5b506101876104ee565b3480156101c457600080fd5b50610113600480360360c08110156101db57600080fd5b50803590602081013590604081013590606081013562ffffff9081169160808101359091169060a001356001600160a01b0316610512565b34801561021f57600080fd5b506101876108e2565b60026000541415610280576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000908155604080516323b872dd60e01b81523360048201523060248201526044810189905290516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926323b872dd92606480820193602093909283900390910190829087803b1580156102fe57600080fd5b505af1158015610312573d6000803e3d6000fd5b505050506040513d602081101561032857600080fd5b505060408051630b52b7ff60e41b8152600481018890526024810187905262ffffff8316604482015290516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163b52b7ff091606480830192600092919082900301818387803b1580156103a457600080fd5b505af11580156103b8573d6000803e3d6000fd5b5050505060004790507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561041c57600080fd5b505af1158015610430573d6000803e3d6000fd5b505050505060006104667f0000000000000000000000000000000000000000000000000000000000000000873033868a8a610906565b604080516001600160a01b038916815260208101839052808201859052606081018b9052905191925033917f614f663be393aac8fd2c2993040a634f5b013b3d5f418cc59ad013e96eef53f99181900360800190a250506001600055505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6002600054141561056a576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260005561059e817f00000000000000000000000000000000000000000000000000000000000000003330898989610906565b50604080516370a0823160e01b815230600482015290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691632e1a7d4d9183916370a08231916024808301926020929190829003018186803b15801561060d57600080fd5b505afa158015610621573d6000803e3d6000fd5b505050506040513d602081101561063757600080fd5b5051604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925251602480830192600092919082900301818387803b15801561068f57600080fd5b505af11580156106a3573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fc5b73ff4788856040518463ffffffff1660e01b8152600401808381526020018262ffffff168152602001925050506000604051808303818588803b15801561071a57600080fd5b505af115801561072e573d6000803e3d6000fd5b505050505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156107a257600080fd5b505afa1580156107b6573d6000803e3d6000fd5b505050506040513d60208110156107cc57600080fd5b5051604080516001600160a01b0385168152602081018990528082018a905260608101839052476080820152905191925033917fc723e34ef5da33ff97116afe67fb4330d3189467330363a49eb6c9d2fd762a8c9181900360a00190a26040805163a9059cbb60e01b81523360048201526024810183905290516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb9160448083019260209291908290030181600087803b15801561089857600080fd5b505af11580156108ac573d6000803e3d6000fd5b505050506040513d60208110156108c257600080fd5b505047156108d4576108d43347610b1e565b505060016000555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516323b872dd60e01b81526000906001600160a01b038916906323b872dd9061093990899030908990600401610c47565b602060405180830381600087803b15801561095357600080fd5b505af1158015610967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098b9190610c08565b5060405163095ea7b360e01b81526001600160a01b0389169063095ea7b3906109da907f0000000000000000000000000000000000000000000000000000000000000000908890600401610c6b565b602060405180830381600087803b1580156109f457600080fd5b505af1158015610a08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2c9190610c08565b5060408051610100810182526001600160a01b03808b168252898116602083015262ffffff851682840152878116606083015242608083015260a0820187905260c08201869052600060e0830152915163414bf38960e01b815290917f0000000000000000000000000000000000000000000000000000000000000000169063414bf38990610abf908490600401610c84565b602060405180830381600087803b158015610ad957600080fd5b505af1158015610aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b119190610c2f565b9998505050505050505050565b80471015610b73576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610bbe576040519150601f19603f3d011682016040523d82523d6000602084013e610bc3565b606091505b5050905080610c035760405162461bcd60e51b815260040180806020018281038252603a815260200180610cf4603a913960400191505060405180910390fd5b505050565b600060208284031215610c19578081fd5b81518015158114610c28578182fd5b9392505050565b600060208284031215610c40578081fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6000610100820190506001600160a01b0380845116835280602085015116602084015262ffffff60408501511660408401528060608501511660608401526080840151608084015260a084015160a084015260c084015160c08401528060e08501511660e0840152509291505056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a2646970667358221220fcd43e471a4f1be2f1f1ccf4169e3d06484dd0cc15e022ffbfc5207a7fbbdf4664736f6c63430007060033\",\n  \"devdoc\": {\n    \"author\": \"Opyn team\",\n    \"details\": \"CrabHelper contract\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"constructor\": {\n        \"params\": {\n          \"_crab\": \"address of crabV2 contract\",\n          \"_swapRouter\": \"address of Uniswap swap router\"\n        }\n      },\n      \"flashDepositERC20(uint256,uint256,uint256,uint24,uint24,address)\": {\n        \"params\": {\n          \"_amountIn\": \"amount of ERC20 token to swap for weth\",\n          \"_erc20Fee\": \"pool fee for transfer ERC20/eth pool (3000 = 30bps)\",\n          \"_ethToDeposit\": \"amount of ETH to deposit\",\n          \"_minEthToGet\": \"min amount of ETH to receive in the swap\",\n          \"_tokenIn\": \"ERC20 token to pay\",\n          \"_wPowerPerpFee\": \"pool fee for wPowerPerp/eth pool (3000 = 30bps)\"\n        }\n      },\n      \"flashWithdrawERC20(uint256,uint256,address,uint256,uint24,uint24)\": {\n        \"params\": {\n          \"_crabAmount\": \"amount of crab shares to withdraw\",\n          \"_erc20Fee\": \"pool fee for transfer ERC20/eth pool (3000 = 30bps)\",\n          \"_maxEthToPay\": \"max eth to pay in swap for wPowerPerp\",\n          \"_minAmountOut\": \"min amount of ERC20 to receive\",\n          \"_tokenOut\": \"ERC20 token to receive\",\n          \"_wPowerPerpFee\": \"pool fee for wPowerPerp/eth pool (3000 = 30bps)\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"constructor\": {\n        \"notice\": \"constructor\"\n      },\n      \"flashDepositERC20(uint256,uint256,uint256,uint24,uint24,address)\": {\n        \"notice\": \"allows user to flash deposit into crab from an aribtrary ERC20\"\n      },\n      \"flashWithdrawERC20(uint256,uint256,address,uint256,uint24,uint24)\": {\n        \"notice\": \"allows user to flash withdraw from crab to an aribtrary ERC20\"\n      }\n    },\n    \"notice\": \"Contract for Crab helper functions\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 4176,\n        \"contract\": \"contracts/strategy/CrabHelper.sol:CrabHelper\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_uint256\"\n      }\n    ],\n    \"types\": {\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/CrabStrategyDeployment.json",
    "content": "{\n  \"address\": \"0x9a23a941F5e70F6960a0E39B8a3964ef83DCbe91\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wSqueethController\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_oracle\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_weth\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniswapFactory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_ethWSqueethPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgePriceThreshold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_auctionTime\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minPriceMultiplier\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxPriceMultiplier\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"lpAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Deposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"seller\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethBought\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethSold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isHedgingOnUniswap\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"ExecuteBuyAuction\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"buyer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethSold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethBought\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isHedgingOnUniswap\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"ExecuteSellAuction\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"depositedAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tradedAmountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDeposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDepositCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdrawCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"auctionType\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"hedgerPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethHedgeTargetAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethHedgetargetAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Hedge\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"auctionType\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethHedgeTargetAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethHedgetargetAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"HedgeOnUniswap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"auctionType\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"hedgerPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionTriggerTimestamp\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"PriceHedge\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"hedgeTimestamp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionTriggerTimestamp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"minWSqueeth\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"minEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"PriceHedgeOnUniswap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newAuctionTime\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetAuctionTime\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newDeltaHedgeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetDeltaHedgeThreshold\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newHedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetHedgePriceThreshold\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newHedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetHedgeTimeThreshold\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint32\",\n          \"name\": \"newHedgingTwapPeriod\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"SetHedgingTwapPeriod\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newMaxPriceMultiplier\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetMaxPriceMultiplier\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newMinPriceMultiplier\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetMinPriceMultiplier\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newCapAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetStrategyCap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"auctionType\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"hedgerPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionTriggerTimestamp\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"TimeHedge\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"hedgeTimestamp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionTriggerTimestamp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"minWSqueeth\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"minEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"TimeHedgeOnUniswap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Withdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawShutdown\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"POWER_PERP_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"auctionTime\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_auctionTriggerTime\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"checkPriceHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"checkTimeHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"subtractedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"decreaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"deltaHedgeThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"deposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"ethQuoteCurrencyPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"ethWSqueethPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToDeposit\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"flashDeposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxEthToPay\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"flashWithdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_auctionTriggerTime\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getAuctionDetails\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getStrategyVaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getVaultDetails\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getWsqueethFromCrabAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgePriceThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgeTimeThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgingTwapPeriod\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"addedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"increaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"maxPriceMultiplier\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"minPriceMultiplier\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"oracle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"powerTokenController\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IController\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"priceAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_auctionTriggerTime\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_isStrategySellingWSqueeth\",\n          \"type\": \"bool\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_limitPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"priceHedge\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_auctionTriggerTime\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minWSqueeth\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"priceHedgeOnUniswap\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"quoteCurrency\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"redeemShortShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_auctionTime\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setAuctionTime\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_deltaHedgeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setDeltaHedgeThreshold\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setHedgePriceThreshold\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setHedgeTimeThreshold\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_hedgingTwapPeriod\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"setHedgingTwapPeriod\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxPriceMultiplier\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setMaxPriceMultiplier\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minPriceMultiplier\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setMinPriceMultiplier\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_capAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setStrategyCap\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"strategyCap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"timeAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_isStrategySellingWSqueeth\",\n          \"type\": \"bool\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_limitPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"timeHedge\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minWSqueeth\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"timeHedgeOnUniswap\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"vaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdrawShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x1194172df420aab22136c318e4d55f03da78965d1fd3e15f76be6fe64c2b2490\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x9a23a941F5e70F6960a0E39B8a3964ef83DCbe91\",\n    \"transactionIndex\": 10,\n    \"gasUsed\": \"5963677\",\n    \"logsBloom\": \"0x00004000000008000004000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000001500040000000000001000000000000008000000000001000000040000000000000000000000000000020240400000000008000801000000000000000020000010000800c00000000000000001000000010000000000000000000000000000000000000000000000000200000000000000000000024000000000000000000000200000000010000002000000000000000000000000000000000000000000004000000060000000000000000000000800000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x1db74393369c1270eeb8de520027f48c2fc760fa524f7a75a2f666590f543006\",\n    \"transactionHash\": \"0x1194172df420aab22136c318e4d55f03da78965d1fd3e15f76be6fe64c2b2490\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 10,\n        \"blockNumber\": 8008121,\n        \"transactionHash\": \"0x1194172df420aab22136c318e4d55f03da78965d1fd3e15f76be6fe64c2b2490\",\n        \"address\": \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n        \"topics\": [\n          \"0x339e53729b0447795ff69e70a74fed98fc7fef6fe94b7521099b32f0f8de4822\"\n        ],\n        \"data\": \"0x0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6ad4cf7c7b600000000000000000000000000000000000000000000000000000000637ebb2c00000000000000000000000000000000000000000000000000000000637ebcd0\",\n        \"logIndex\": 21,\n        \"blockHash\": \"0x1db74393369c1270eeb8de520027f48c2fc760fa524f7a75a2f666590f543006\"\n      },\n      {\n        \"transactionIndex\": 10,\n        \"blockNumber\": 8008121,\n        \"transactionHash\": \"0x1194172df420aab22136c318e4d55f03da78965d1fd3e15f76be6fe64c2b2490\",\n        \"address\": \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n        \"topics\": [\n          \"0x3137fc9cd2e33c34f86e29c24d81f3c75b0bce639d3c4ed0d31eeff1160a7ff5\"\n        ],\n        \"data\": \"0x000000000000000000000000e85595e810b77cf606d0afd7eb575bb025323bee00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000\",\n        \"logIndex\": 22,\n        \"blockHash\": \"0x1db74393369c1270eeb8de520027f48c2fc760fa524f7a75a2f666590f543006\"\n      },\n      {\n        \"transactionIndex\": 10,\n        \"blockNumber\": 8008121,\n        \"transactionHash\": \"0x1194172df420aab22136c318e4d55f03da78965d1fd3e15f76be6fe64c2b2490\",\n        \"address\": \"0xe85595e810B77cf606D0aFd7eB575BB025323beE\",\n        \"topics\": [\n          \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000009a23a941f5e70f6960a0e39b8a3964ef83dcbe91\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000001\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 23,\n        \"blockHash\": \"0x1db74393369c1270eeb8de520027f48c2fc760fa524f7a75a2f666590f543006\"\n      },\n      {\n        \"transactionIndex\": 10,\n        \"blockNumber\": 8008121,\n        \"transactionHash\": \"0x1194172df420aab22136c318e4d55f03da78965d1fd3e15f76be6fe64c2b2490\",\n        \"address\": \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n        \"topics\": [\n          \"0x25ff1e0131762176a9084e92880f880f39d6d0e62134607f37e631efe1bad871\"\n        ],\n        \"data\": \"0x0000000000000000000000009a23a941f5e70f6960a0e39b8a3964ef83dcbe910000000000000000000000000000000000000000000000000000000000000001\",\n        \"logIndex\": 24,\n        \"blockHash\": \"0x1db74393369c1270eeb8de520027f48c2fc760fa524f7a75a2f666590f543006\"\n      },\n      {\n        \"transactionIndex\": 10,\n        \"blockNumber\": 8008121,\n        \"transactionHash\": \"0x1194172df420aab22136c318e4d55f03da78965d1fd3e15f76be6fe64c2b2490\",\n        \"address\": \"0x9a23a941F5e70F6960a0E39B8a3964ef83DCbe91\",\n        \"topics\": [\n          \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000006326a0dfe0517ff46af3ad16bc40c26c26397f9e\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 25,\n        \"blockHash\": \"0x1db74393369c1270eeb8de520027f48c2fc760fa524f7a75a2f666590f543006\"\n      }\n    ],\n    \"blockNumber\": 8008121,\n    \"cumulativeGasUsed\": \"8573403\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n    \"0xf7F94b4607Bcd1235212803bE8fD1B54D1D01b77\",\n    \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\n    \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n    \"0xC3c29372B5138d48993F0699A129b9EADf5191Bf\",\n    86400,\n    \"10000000000000000\",\n    3600,\n    \"950000000000000000\",\n    \"1050000000000000000\"\n  ],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wSqueethController\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_oracle\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_weth\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniswapFactory\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_ethWSqueethPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_auctionTime\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minPriceMultiplier\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxPriceMultiplier\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"lpAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Deposit\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"seller\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethBought\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethSold\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isHedgingOnUniswap\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"ExecuteBuyAuction\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"buyer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethSold\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethBought\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isHedgingOnUniswap\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"ExecuteSellAuction\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"depositedAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tradedAmountOut\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDeposit\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"flashswapDebt\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excess\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDepositCallback\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"flashswapDebt\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excess\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdrawCallback\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"auctionType\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"hedgerPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethHedgeTargetAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethHedgetargetAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Hedge\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"auctionType\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethHedgeTargetAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethHedgetargetAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"HedgeOnUniswap\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"auctionType\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"hedgerPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionTriggerTimestamp\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"PriceHedge\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"hedgeTimestamp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionTriggerTimestamp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minWSqueeth\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"PriceHedgeOnUniswap\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newAuctionTime\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetAuctionTime\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newDeltaHedgeThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetDeltaHedgeThreshold\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newHedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetHedgePriceThreshold\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newHedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetHedgeTimeThreshold\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"newHedgingTwapPeriod\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"SetHedgingTwapPeriod\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newMaxPriceMultiplier\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetMaxPriceMultiplier\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newMinPriceMultiplier\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetMinPriceMultiplier\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newCapAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetStrategyCap\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"auctionType\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"hedgerPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionTriggerTimestamp\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"TimeHedge\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"hedgeTimestamp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionTriggerTimestamp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minWSqueeth\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"TimeHedgeOnUniswap\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethWithdrawn\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Withdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethWithdrawn\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawShutdown\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"POWER_PERP_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"auctionTime\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_auctionTriggerTime\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"checkPriceHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"checkTimeHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"subtractedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"decreaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"deltaHedgeThreshold\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"deposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"ethQuoteCurrencyPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"ethWSqueethPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"factory\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToDeposit\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"flashDeposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxEthToPay\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"flashWithdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_auctionTriggerTime\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"getAuctionDetails\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getStrategyVaultId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getVaultDetails\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"getWsqueethFromCrabAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgePriceThreshold\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgeTimeThreshold\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgingTwapPeriod\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"addedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"increaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"maxPriceMultiplier\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"minPriceMultiplier\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"oracle\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"powerTokenController\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IController\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"priceAtLastHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_auctionTriggerTime\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_isStrategySellingWSqueeth\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_limitPrice\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"priceHedge\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_auctionTriggerTime\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minWSqueeth\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"priceHedgeOnUniswap\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"quoteCurrency\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"redeemShortShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_auctionTime\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setAuctionTime\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_deltaHedgeThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setDeltaHedgeThreshold\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setHedgePriceThreshold\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setHedgeTimeThreshold\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_hedgingTwapPeriod\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"setHedgingTwapPeriod\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxPriceMultiplier\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setMaxPriceMultiplier\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minPriceMultiplier\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setMinPriceMultiplier\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_capAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setStrategyCap\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"strategyCap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"timeAtLastHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_isStrategySellingWSqueeth\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_limitPrice\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"timeHedge\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minWSqueeth\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"timeHedgeOnUniswap\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount0Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount1Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"uniswapV3SwapCallback\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"vaultId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdrawShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"author\\\":\\\"Opyn team\\\",\\\"details\\\":\\\"CrabStrategy contract\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"allowance(address,address)\\\":{\\\"details\\\":\\\"See {IERC20-allowance}.\\\"},\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC20-balanceOf}.\\\"},\\\"checkPriceHedge(uint256)\\\":{\\\"params\\\":{\\\"_auctionTriggerTime\\\":\\\"the time when the price deviation threshold was exceeded and when the auction started\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"true if hedging is allowed\\\"}},\\\"checkTimeHedge()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"isTimeHedgeAllowed true if hedging is allowed\\\",\\\"_1\\\":\\\"auctionTriggertime auction trigger timestamp\\\"}},\\\"constructor\\\":{\\\"details\\\":\\\"this will open a vault in the power token contract and store the vault ID\\\",\\\"params\\\":{\\\"_auctionTime\\\":\\\"auction duration (seconds)\\\",\\\"_ethWSqueethPool\\\":\\\"eth:wSqueeth uniswap pool address\\\",\\\"_hedgePriceThreshold\\\":\\\"hedge price threshold (0.1*1e18 = 10%)\\\",\\\"_hedgeTimeThreshold\\\":\\\"hedge time threshold (seconds)\\\",\\\"_maxPriceMultiplier\\\":\\\"maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\\",\\\"_minPriceMultiplier\\\":\\\"minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\\",\\\"_oracle\\\":\\\"oracle address\\\",\\\"_uniswapFactory\\\":\\\"uniswap factory address\\\",\\\"_wSqueethController\\\":\\\"power token controller address\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"decimals()\\\":{\\\"details\\\":\\\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\\\"},\\\"decreaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\\\"},\\\"deposit()\\\":{\\\"details\\\":\\\"provide ETH, return wSqueeth and strategy token\\\"},\\\"flashDeposit(uint256)\\\":{\\\"details\\\":\\\"this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth_ethToDeposit must be less than msg.value plus the proceeds from the flash swapthe difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\",\\\"params\\\":{\\\"_ethToDeposit\\\":\\\"total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\"}},\\\"flashWithdraw(uint256,uint256)\\\":{\\\"details\\\":\\\"this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\",\\\"params\\\":{\\\"_crabAmount\\\":\\\"strategy token amount to burn\\\",\\\"_maxEthToPay\\\":\\\"maximum ETH to pay to buy back the owed wSqueeth debt\\\"}},\\\"getAuctionDetails(uint256)\\\":{\\\"params\\\":{\\\"_auctionTriggerTime\\\":\\\"timestamp where auction started\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\\"}},\\\"getStrategyVaultId()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"vault ID\\\"}},\\\"getVaultDetails()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"operator\\\",\\\"_1\\\":\\\"nft collateral id\\\",\\\"_2\\\":\\\"collateral amount\\\",\\\"_3\\\":\\\"short amount\\\"}},\\\"getWsqueethFromCrabAmount(uint256)\\\":{\\\"params\\\":{\\\"_crabAmount\\\":\\\"strategy token amount\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"wSqueeth amount\\\"}},\\\"increaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\\\"},\\\"name()\\\":{\\\"details\\\":\\\"Returns the name of the token.\\\"},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"priceHedge(uint256,bool,uint256)\\\":{\\\"details\\\":\\\"need to attach msg.value if buying WSqueeth\\\",\\\"params\\\":{\\\"_auctionTriggerTime\\\":\\\"the time when the price deviation threshold was exceeded and when the auction started\\\",\\\"_isStrategySellingWSqueeth\\\":\\\"specify the direction of the trade that you expect, this choice impacts the limit price chosen\\\",\\\"_limitPrice\\\":\\\"the min or max price that you will trade at, depending on if buying or selling\\\"}},\\\"priceHedgeOnUniswap(uint256,uint256,uint256)\\\":{\\\"details\\\":\\\"this function atomically hedges on uniswap and provides a bounty to the caller based on the differencebetween uniswap execution price and the price of the hedging auction\\\",\\\"params\\\":{\\\"_auctionTriggerTime\\\":\\\"the time when the price deviation threshold was exceeded and when the auction started\\\",\\\"_minEth\\\":\\\"minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\\",\\\"_minWSqueeth\\\":\\\"minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\\"}},\\\"redeemShortShutdown()\\\":{\\\"details\\\":\\\"needs to be called 1 time before users can exit the strategy using withdrawShutdown\\\"},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"setAuctionTime(uint256)\\\":{\\\"params\\\":{\\\"_auctionTime\\\":\\\"the length of the hedge auction in seconds\\\"}},\\\"setDeltaHedgeThreshold(uint256)\\\":{\\\"details\\\":\\\"the strategy will not allow a hedge if the trade size is below this threshold\\\",\\\"params\\\":{\\\"_deltaHedgeThreshold\\\":\\\"minimum hedge size in a percent of ETH collateral\\\"}},\\\"setHedgePriceThreshold(uint256)\\\":{\\\"params\\\":{\\\"_hedgePriceThreshold\\\":\\\"the hedge price threshold, in percent, scaled by 1e18\\\"}},\\\"setHedgeTimeThreshold(uint256)\\\":{\\\"params\\\":{\\\"_hedgeTimeThreshold\\\":\\\"the hedge time threshold, in seconds\\\"}},\\\"setHedgingTwapPeriod(uint32)\\\":{\\\"params\\\":{\\\"_hedgingTwapPeriod\\\":\\\"the twap period, in seconds\\\"}},\\\"setMaxPriceMultiplier(uint256)\\\":{\\\"details\\\":\\\"the max price multiplier is multiplied by the TWAP price to get the final auction price\\\",\\\"params\\\":{\\\"_maxPriceMultiplier\\\":\\\"the max price multiplier, a percentage, scaled by 1e18\\\"}},\\\"setMinPriceMultiplier(uint256)\\\":{\\\"details\\\":\\\"the min price multiplier is multiplied by the TWAP price to get the intial auction price\\\",\\\"params\\\":{\\\"_minPriceMultiplier\\\":\\\"the min price multiplier, a percentage, scaled by 1e18\\\"}},\\\"setStrategyCap(uint256)\\\":{\\\"details\\\":\\\"deposits are rejected if it would put the strategy above the cap amountstrategy collateral can be above the cap amount due to hedging activities\\\",\\\"params\\\":{\\\"_capAmount\\\":\\\"the maximum strategy collateral in ETH, checked on deposits\\\"}},\\\"symbol()\\\":{\\\"details\\\":\\\"Returns the symbol of the token, usually a shorter version of the name.\\\"},\\\"timeHedge(bool,uint256)\\\":{\\\"details\\\":\\\"need to attach msg.value if buying WSqueeth\\\",\\\"params\\\":{\\\"_isStrategySellingWSqueeth\\\":\\\"sell or buy auction, true for sell auction\\\",\\\"_limitPrice\\\":\\\"hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\\"}},\\\"timeHedgeOnUniswap(uint256,uint256)\\\":{\\\"details\\\":\\\"this function atomically hedges on uniswap and provides a bounty to the caller based on the differencebetween uniswap execution price and the price of the hedging auction\\\",\\\"params\\\":{\\\"_minEth\\\":\\\"minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\\",\\\"_minWSqueeth\\\":\\\"minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\\"}},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC20-totalSupply}.\\\"},\\\"transfer(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\\\"},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"params\\\":{\\\"_data\\\":\\\"callback data encoded as SwapCallbackData struct\\\",\\\"amount0Delta\\\":\\\"amount of token0\\\",\\\"amount1Delta\\\":\\\"amount of token1\\\"}},\\\"withdraw(uint256)\\\":{\\\"details\\\":\\\"provide strategy tokens and wSqueeth, returns eth\\\",\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of strategy token to burn\\\"}},\\\"withdrawShutdown(uint256)\\\":{\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of strategy token to burn\\\"}}},\\\"stateVariables\\\":{\\\"POWER_PERP_PERIOD\\\":{\\\"details\\\":\\\"the TWAP_PERIOD used in the PowerPerp Controller contract\\\"},\\\"auctionTime\\\":{\\\"details\\\":\\\"hedge auction duration (seconds)\\\"},\\\"deltaHedgeThreshold\\\":{\\\"details\\\":\\\"strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\\"},\\\"ethWSqueethPool\\\":{\\\"details\\\":\\\"ETH:WSqueeth uniswap pool\\\"},\\\"hasRedeemedInShutdown\\\":{\\\"details\\\":\\\"set to true when redeemShortShutdown has been called\\\"},\\\"hedgePriceThreshold\\\":{\\\"details\\\":\\\"price movement to trigger a hedge (0.1*1e18 = 10%)\\\"},\\\"hedgeTimeThreshold\\\":{\\\"details\\\":\\\"time difference to trigger a hedge (seconds)\\\"},\\\"hedgingTwapPeriod\\\":{\\\"details\\\":\\\"twap period to use for hedge calculations\\\"},\\\"maxPriceMultiplier\\\":{\\\"details\\\":\\\"start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\\"},\\\"minPriceMultiplier\\\":{\\\"details\\\":\\\"start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\\"},\\\"oracle\\\":{\\\"details\\\":\\\"strategy uniswap oracle\\\"},\\\"priceAtLastHedge\\\":{\\\"details\\\":\\\"WSqueeth/Eth price when last hedge executed\\\"},\\\"strategyCap\\\":{\\\"details\\\":\\\"the cap in ETH for the strategy, above which deposits will be rejected\\\"},\\\"timeAtLastHedge\\\":{\\\"details\\\":\\\"timestamp when last hedge executed\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"checkPriceHedge(uint256)\\\":{\\\"notice\\\":\\\"check if hedging based on price threshold is allowed\\\"},\\\"checkTimeHedge()\\\":{\\\"notice\\\":\\\"check if hedging based on time threshold is allowed\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"strategy constructor\\\"},\\\"deposit()\\\":{\\\"notice\\\":\\\"deposit ETH into strategy\\\"},\\\"flashDeposit(uint256)\\\":{\\\"notice\\\":\\\"flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\"},\\\"flashWithdraw(uint256,uint256)\\\":{\\\"notice\\\":\\\"flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\"},\\\"getAuctionDetails(uint256)\\\":{\\\"notice\\\":\\\"get current auction details\\\"},\\\"getStrategyVaultId()\\\":{\\\"notice\\\":\\\"get power token strategy vault ID \\\"},\\\"getVaultDetails()\\\":{\\\"notice\\\":\\\"get the vault composition of the strategy \\\"},\\\"getWsqueethFromCrabAmount(uint256)\\\":{\\\"notice\\\":\\\"get wSqueeth debt amount associated with strategy token amount\\\"},\\\"priceHedge(uint256,bool,uint256)\\\":{\\\"notice\\\":\\\"strategy hedging based on price threshold\\\"},\\\"priceHedgeOnUniswap(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"hedge startegy based on price threshold with uniswap arbing\\\"},\\\"redeemShortShutdown()\\\":{\\\"notice\\\":\\\"called to redeem the net value of a vault post shutdown\\\"},\\\"setAuctionTime(uint256)\\\":{\\\"notice\\\":\\\"owner can set the auction time, in seconds, that a hedge auction runs for\\\"},\\\"setDeltaHedgeThreshold(uint256)\\\":{\\\"notice\\\":\\\"owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\\"},\\\"setHedgePriceThreshold(uint256)\\\":{\\\"notice\\\":\\\"owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\"},\\\"setHedgeTimeThreshold(uint256)\\\":{\\\"notice\\\":\\\"owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\"},\\\"setHedgingTwapPeriod(uint32)\\\":{\\\"notice\\\":\\\"owner can set the twap period in seconds that is used for calculating twaps for hedging\\\"},\\\"setMaxPriceMultiplier(uint256)\\\":{\\\"notice\\\":\\\"owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\\"},\\\"setMinPriceMultiplier(uint256)\\\":{\\\"notice\\\":\\\"owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\\"},\\\"setStrategyCap(uint256)\\\":{\\\"notice\\\":\\\"owner can set the strategy cap in ETH collateral terms\\\"},\\\"timeHedge(bool,uint256)\\\":{\\\"notice\\\":\\\"strategy hedging based on time threshold\\\"},\\\"timeHedgeOnUniswap(uint256,uint256)\\\":{\\\"notice\\\":\\\"hedge startegy based on time threshold with uniswap arbing\\\"},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"notice\\\":\\\"uniswap swap callback function for flashes\\\"},\\\"withdraw(uint256)\\\":{\\\"notice\\\":\\\"withdraw WETH from strategy\\\"},\\\"withdrawShutdown(uint256)\\\":{\\\"notice\\\":\\\"called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\"}},\\\"notice\\\":\\\"Contract for Crab strategy\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/strategy/CrabStrategy.sol\\\":\\\"CrabStrategy\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Safe casting methods\\\\n/// @notice Contains methods for safely casting between types\\\\nlibrary SafeCast {\\\\n    /// @notice Cast a uint256 to a uint160, revert on overflow\\\\n    /// @param y The uint256 to be downcasted\\\\n    /// @return z The downcasted integer, now type uint160\\\\n    function toUint160(uint256 y) internal pure returns (uint160 z) {\\\\n        require((z = uint160(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a int256 to a int128, revert on overflow or underflow\\\\n    /// @param y The int256 to be downcasted\\\\n    /// @return z The downcasted integer, now type int128\\\\n    function toInt128(int256 y) internal pure returns (int128 z) {\\\\n        require((z = int128(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a uint256 to a int256, revert on overflow\\\\n    /// @param y The uint256 to be casted\\\\n    /// @return z The casted integer, now type int256\\\\n    function toInt256(uint256 y) internal pure returns (int256 z) {\\\\n        require(y < 2**255);\\\\n        z = int256(y);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n/*\\\\n * @title Solidity Bytes Arrays Utils\\\\n * @author Gon\\\\u00e7alo S\\\\u00e1 <goncalo.sa@consensys.net>\\\\n *\\\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\\\n */\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nlibrary BytesLib {\\\\n    function slice(\\\\n        bytes memory _bytes,\\\\n        uint256 _start,\\\\n        uint256 _length\\\\n    ) internal pure returns (bytes memory) {\\\\n        require(_length + 31 >= _length, 'slice_overflow');\\\\n        require(_start + _length >= _start, 'slice_overflow');\\\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\\\n\\\\n        bytes memory tempBytes;\\\\n\\\\n        assembly {\\\\n            switch iszero(_length)\\\\n                case 0 {\\\\n                    // Get a location of some free memory and store it in tempBytes as\\\\n                    // Solidity does for memory variables.\\\\n                    tempBytes := mload(0x40)\\\\n\\\\n                    // The first word of the slice result is potentially a partial\\\\n                    // word read from the original array. To read it, we calculate\\\\n                    // the length of that partial word and start copying that many\\\\n                    // bytes into the array. The first word we copy will start with\\\\n                    // data we don't care about, but the last `lengthmod` bytes will\\\\n                    // land at the beginning of the contents of the new array. When\\\\n                    // we're done copying, we overwrite the full first word with\\\\n                    // the actual length of the slice.\\\\n                    let lengthmod := and(_length, 31)\\\\n\\\\n                    // The multiplication in the next line is necessary\\\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\\\n                    // the following copy loop was copying the origin's length\\\\n                    // and then ending prematurely not copying everything it should.\\\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\\\n                    let end := add(mc, _length)\\\\n\\\\n                    for {\\\\n                        // The multiplication in the next line has the same exact purpose\\\\n                        // as the one above.\\\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\\\n                    } lt(mc, end) {\\\\n                        mc := add(mc, 0x20)\\\\n                        cc := add(cc, 0x20)\\\\n                    } {\\\\n                        mstore(mc, mload(cc))\\\\n                    }\\\\n\\\\n                    mstore(tempBytes, _length)\\\\n\\\\n                    //update free-memory pointer\\\\n                    //allocating the array padded to 32 bytes like the compiler does now\\\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\\\n                }\\\\n                //if we want a zero-length slice let's just return a zero-length array\\\\n                default {\\\\n                    tempBytes := mload(0x40)\\\\n                    //zero out the 32 bytes slice we are about to return\\\\n                    //we need to do it because Solidity does not garbage collect\\\\n                    mstore(tempBytes, 0)\\\\n\\\\n                    mstore(0x40, add(tempBytes, 0x20))\\\\n                }\\\\n        }\\\\n\\\\n        return tempBytes;\\\\n    }\\\\n\\\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\\\n        address tempAddress;\\\\n\\\\n        assembly {\\\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\\\n        }\\\\n\\\\n        return tempAddress;\\\\n    }\\\\n\\\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\\\n        uint24 tempUint;\\\\n\\\\n        assembly {\\\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\\\n        }\\\\n\\\\n        return tempUint;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport './PoolAddress.sol';\\\\n\\\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\\\nlibrary CallbackValidation {\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param tokenA The contract address of either token0 or token1\\\\n    /// @param tokenB The contract address of the other token\\\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(\\\\n        address factory,\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool pool) {\\\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param poolKey The identifying key of the V3 pool\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\\\n        internal\\\\n        view\\\\n        returns (IUniswapV3Pool pool)\\\\n    {\\\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\\\n        require(msg.sender == address(pool));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.6.0;\\\\n\\\\nimport './BytesLib.sol';\\\\n\\\\n/// @title Functions for manipulating path data for multihop swaps\\\\nlibrary Path {\\\\n    using BytesLib for bytes;\\\\n\\\\n    /// @dev The length of the bytes encoded address\\\\n    uint256 private constant ADDR_SIZE = 20;\\\\n    /// @dev The length of the bytes encoded fee\\\\n    uint256 private constant FEE_SIZE = 3;\\\\n\\\\n    /// @dev The offset of a single token address and pool fee\\\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\\\n    /// @dev The offset of an encoded pool key\\\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\\\n\\\\n    /// @notice Returns true iff the path contains two or more pools\\\\n    /// @param path The encoded swap path\\\\n    /// @return True if path contains two or more pools, otherwise false\\\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\\\n    }\\\\n\\\\n    /// @notice Returns the number of pools in the path\\\\n    /// @param path The encoded swap path\\\\n    /// @return The number of pools in the path\\\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Decodes the first pool in path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return tokenA The first token of the given pool\\\\n    /// @return tokenB The second token of the given pool\\\\n    /// @return fee The fee level of the pool\\\\n    function decodeFirstPool(bytes memory path)\\\\n        internal\\\\n        pure\\\\n        returns (\\\\n            address tokenA,\\\\n            address tokenB,\\\\n            uint24 fee\\\\n        )\\\\n    {\\\\n        tokenA = path.toAddress(0);\\\\n        fee = path.toUint24(ADDR_SIZE);\\\\n        tokenB = path.toAddress(NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Gets the segment corresponding to the first pool in the path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return The segment containing all data necessary to target the first pool in the path\\\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(0, POP_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\\\n    /// @param path The swap path\\\\n    /// @return The remaining token + fee elements in the path\\\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/Power2Base.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary Power2Base {\\\\n    using SafeMath for uint256;\\\\n\\\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\\\n    uint256 private constant INDEX_SCALE = 1e4;\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    /**\\\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getUnscaledIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\\\n     */\\\\n    function _getDenormalizedMark(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _wSqueeth,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\\\n\\\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _weth weth address\\\\n     * @return returns value of debt in ETH\\\\n     */\\\\n    function _getDebtValueInEth(\\\\n        uint256 _debtAmount,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _wSqueeth,\\\\n        address _weth\\\\n    ) internal view returns (uint256) {\\\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle\\\\n     * @dev this will revert if period is > max period for the pool\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        // period reaching this point should be check, otherwise might revert\\\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\\\n     * @param _indexPriceForSettlement index price for settlement\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return amount in wei that should be paid to the token holder\\\\n     */\\\\n    function _getLongSettlementValue(\\\\n        uint256 _wsqueethAmount,\\\\n        uint256 _indexPriceForSettlement,\\\\n        uint256 _normalizationFactor\\\\n    ) internal pure returns (uint256) {\\\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1938180c41ec0ee817b841df605b199e15ffbbe94700b640d031b4e4665a89af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/CrabStrategy.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {StrategyBase} from \\\\\\\"./base/StrategyBase.sol\\\\\\\";\\\\nimport {StrategyFlashSwap} from \\\\\\\"./base/StrategyFlashSwap.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./base/StrategyMath.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev CrabStrategy contract\\\\n * @notice Contract for Crab strategy\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\\\n    uint256 public strategyCap;\\\\n\\\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\\\n    /// @dev twap period to use for hedge calculations\\\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum FLASH_SOURCE {\\\\n        FLASH_DEPOSIT,\\\\n        FLASH_WITHDRAW,\\\\n        FLASH_HEDGE_SELL,\\\\n        FLASH_HEDGE_BUY\\\\n    }\\\\n\\\\n    /// @dev ETH:WSqueeth uniswap pool\\\\n    address public immutable ethWSqueethPool;\\\\n    /// @dev strategy uniswap oracle\\\\n    address public immutable oracle;\\\\n    address public immutable ethQuoteCurrencyPool;\\\\n    address public immutable quoteCurrency;\\\\n\\\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\\\n    uint256 public deltaHedgeThreshold = 1e15;\\\\n    /// @dev time difference to trigger a hedge (seconds)\\\\n    uint256 public hedgeTimeThreshold;\\\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\\\n    uint256 public hedgePriceThreshold;\\\\n    /// @dev hedge auction duration (seconds)\\\\n    uint256 public auctionTime;\\\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\\\n    uint256 public minPriceMultiplier;\\\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\\\n    uint256 public maxPriceMultiplier;\\\\n\\\\n    /// @dev timestamp when last hedge executed\\\\n    uint256 public timeAtLastHedge;\\\\n    /// @dev WSqueeth/Eth price when last hedge executed\\\\n    uint256 public priceAtLastHedge;\\\\n\\\\n    /// @dev set to true when redeemShortShutdown has been called\\\\n    bool private hasRedeemedInShutdown;\\\\n\\\\n    struct FlashDepositData {\\\\n        uint256 totalDeposit;\\\\n    }\\\\n\\\\n    struct FlashWithdrawData {\\\\n        uint256 crabAmount;\\\\n    }\\\\n\\\\n    struct FlashHedgeData {\\\\n        uint256 wSqueethAmount;\\\\n        uint256 ethProceeds;\\\\n        uint256 minWSqueeth;\\\\n        uint256 minEth;\\\\n    }\\\\n\\\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\\\n    event TimeHedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        uint256 hedgeTimestamp,\\\\n        uint256 auctionTriggerTimestamp,\\\\n        uint256 minWSqueeth,\\\\n        uint256 minEth\\\\n    );\\\\n    event PriceHedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        uint256 hedgeTimestamp,\\\\n        uint256 auctionTriggerTimestamp,\\\\n        uint256 minWSqueeth,\\\\n        uint256 minEth\\\\n    );\\\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\\\n    event Hedge(\\\\n        address indexed hedger,\\\\n        bool auctionType,\\\\n        uint256 hedgerPrice,\\\\n        uint256 auctionPrice,\\\\n        uint256 wSqueethHedgeTargetAmount,\\\\n        uint256 ethHedgetargetAmount\\\\n    );\\\\n    event HedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        bool auctionType,\\\\n        uint256 auctionPrice,\\\\n        uint256 wSqueethHedgeTargetAmount,\\\\n        uint256 ethHedgetargetAmount\\\\n    );\\\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\\\n    event SetStrategyCap(uint256 newCapAmount);\\\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\\\n    event SetAuctionTime(uint256 newAuctionTime);\\\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\\\n\\\\n    /**\\\\n     * @notice strategy constructor\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _wSqueethController power token controller address\\\\n     * @param _oracle oracle address\\\\n     * @param _weth weth address\\\\n     * @param _uniswapFactory uniswap factory address\\\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\\\n     * @param _auctionTime auction duration (seconds)\\\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\\\n     */\\\\n    constructor(\\\\n        address _wSqueethController,\\\\n        address _oracle,\\\\n        address _weth,\\\\n        address _uniswapFactory,\\\\n        address _ethWSqueethPool,\\\\n        uint256 _hedgeTimeThreshold,\\\\n        uint256 _hedgePriceThreshold,\\\\n        uint256 _auctionTime,\\\\n        uint256 _minPriceMultiplier,\\\\n        uint256 _maxPriceMultiplier\\\\n    ) StrategyBase(_wSqueethController, _weth, \\\\\\\"Crab Strategy\\\\\\\", \\\\\\\"Crab\\\\\\\") StrategyFlashSwap(_uniswapFactory) {\\\\n        require(_oracle != address(0), \\\\\\\"invalid oracle address\\\\\\\");\\\\n        require(_ethWSqueethPool != address(0), \\\\\\\"invalid ETH:WSqueeth address\\\\\\\");\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"invalid hedge time threshold\\\\\\\");\\\\n        require(_hedgePriceThreshold > 0, \\\\\\\"invalid hedge price threshold\\\\\\\");\\\\n        require(_auctionTime > 0, \\\\\\\"invalid auction time\\\\\\\");\\\\n        require(_minPriceMultiplier < 1e18, \\\\\\\"min price multiplier too high\\\\\\\");\\\\n        require(_minPriceMultiplier > 0, \\\\\\\"invalid min price multiplier\\\\\\\");\\\\n        require(_maxPriceMultiplier > 1e18, \\\\\\\"max price multiplier too low\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        ethWSqueethPool = _ethWSqueethPool;\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n        auctionTime = _auctionTime;\\\\n        minPriceMultiplier = _minPriceMultiplier;\\\\n        maxPriceMultiplier = _maxPriceMultiplier;\\\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\\\\\"Cannot receive eth\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the strategy cap in ETH collateral terms\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\\\n        strategyCap = _capAmount;\\\\n\\\\n        emit SetStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to redeem the net value of a vault post shutdown\\\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\\\n     */\\\\n    function redeemShortShutdown() external {\\\\n        hasRedeemedInShutdown = true;\\\\n        powerTokenController.redeemShort(vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\\n     */\\\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\\\n            _ethToDeposit,\\\\n            cachedStrategyDebt,\\\\n            cachedStrategyCollateral\\\\n        );\\\\n\\\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\\\n            // store hedge data as strategy is delta neutral at this point\\\\n            // only execute this upon first deposit\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\\\n                ethWSqueethPool,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                hedgingTwapPeriod,\\\\n                true\\\\n            );\\\\n            timeAtLastHedge = block.timestamp;\\\\n            priceAtLastHedge = wSqueethEthPrice;\\\\n        }\\\\n\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n            wSqueethToMint,\\\\n            _ethToDeposit.sub(msg.value),\\\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\\\n            abi.encodePacked(_ethToDeposit)\\\\n        );\\\\n\\\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\\n     * @param _crabAmount strategy token amount to burn\\\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\\\n     */\\\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n            exactWSqueethNeeded,\\\\n            _maxEthToPay,\\\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\\\n            abi.encodePacked(_crabAmount)\\\\n        );\\\\n\\\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit ETH into strategy\\\\n     * @dev provide ETH, return wSqueeth and strategy token\\\\n     */\\\\n    function deposit() external payable nonReentrant {\\\\n        uint256 amount = msg.value;\\\\n\\\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\\\n\\\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\\\n\\\\n        // send back ETH collateral\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n\\\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\\\n        require(powerTokenController.isShutDown(), \\\\\\\"Squeeth contracts not shut down\\\\\\\");\\\\n        require(hasRedeemedInShutdown, \\\\\\\"Crab must redeemShortShutdown\\\\\\\");\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\\\n        _burn(msg.sender, _crabAmount);\\\\n\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\\\n     * @dev between uniswap execution price and the price of the hedging auction\\\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\\\n     */\\\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\\\n\\\\n        require(isTimeHedgeAllowed, \\\\\\\"Time hedging is not allowed\\\\\\\");\\\\n\\\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\\\n\\\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\\\n     * @dev between uniswap execution price and the price of the hedging auction\\\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\\\n     */\\\\n    function priceHedgeOnUniswap(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _minWSqueeth,\\\\n        uint256 _minEth\\\\n    ) external payable {\\\\n        require(_isPriceHedge(_auctionTriggerTime), \\\\\\\"Price hedging not allowed\\\\\\\");\\\\n\\\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\\\n\\\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy hedging based on time threshold\\\\n     * @dev need to attach msg.value if buying WSqueeth\\\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\\\n     */\\\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\\\n\\\\n        require(isTimeHedgeAllowed, \\\\\\\"Time hedging is not allowed\\\\\\\");\\\\n\\\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\\\n\\\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy hedging based on price threshold\\\\n     * @dev need to attach msg.value if buying WSqueeth\\\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\\\n     */\\\\n    function priceHedge(\\\\n        uint256 _auctionTriggerTime,\\\\n        bool _isStrategySellingWSqueeth,\\\\n        uint256 _limitPrice\\\\n    ) external payable nonReentrant {\\\\n        require(_isPriceHedge(_auctionTriggerTime), \\\\\\\"Price hedging not allowed\\\\\\\");\\\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\\\n\\\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\\\n        return _isPriceHedge(_auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\\\n     * @return auctionTriggertime auction trigger timestamp\\\\n     */\\\\n    function checkTimeHedge() external view returns (bool, uint256) {\\\\n        return _isTimeHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\\\n     * @param _crabAmount strategy token amount\\\\n     * @return wSqueeth amount\\\\n     */\\\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\\\n        return _getDebtFromStrategyAmount(_crabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\\\n     */\\\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\\\n\\\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\\\n     */\\\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\\\n        require(_hedgingTwapPeriod >= 180, \\\\\\\"twap period is too short\\\\\\\");\\\\n\\\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\\\n\\\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\\\n     */\\\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"invalid hedge time threshold\\\\\\\");\\\\n\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n\\\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\\\n     */\\\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\\\n        require(_hedgePriceThreshold > 0, \\\\\\\"invalid hedge price threshold\\\\\\\");\\\\n\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n\\\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\\\n     * @param _auctionTime the length of the hedge auction in seconds\\\\n     */\\\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\\\n        require(_auctionTime > 0, \\\\\\\"invalid auction time\\\\\\\");\\\\n\\\\n        auctionTime = _auctionTime;\\\\n\\\\n        emit SetAuctionTime(_auctionTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\\\n     */\\\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\\\n        require(_minPriceMultiplier < 1e18, \\\\\\\"min price multiplier too high\\\\\\\");\\\\n\\\\n        minPriceMultiplier = _minPriceMultiplier;\\\\n\\\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\\\n     */\\\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\\\n        require(_maxPriceMultiplier > 1e18, \\\\\\\"max price multiplier too low\\\\\\\");\\\\n\\\\n        maxPriceMultiplier = _maxPriceMultiplier;\\\\n\\\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get current auction details\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\\\n     */\\\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            bool,\\\\n            uint256,\\\\n            uint256,\\\\n            uint256,\\\\n            bool\\\\n        )\\\\n    {\\\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            hedgingTwapPeriod,\\\\n            true\\\\n        );\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\\\n            strategyDebt,\\\\n            ethDelta,\\\\n            auctionWSqueethEthPrice,\\\\n            feeAdjustment\\\\n        );\\\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\\\n\\\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a user deposit puts the strategy above the cap\\\\n     * @dev reverts if a deposit amount puts strategy over the cap\\\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\\\n     * @param _depositAmount the user deposit amount in ETH\\\\n     * @param _strategyCollateral the updated strategy collateral\\\\n     */\\\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\\\\\"Deposit exceeds strategy cap\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _strategyFlash(\\\\n        address _caller,\\\\n        address, /*_tokenIn*/\\\\n        address, /*_tokenOut*/\\\\n        uint24, /*_fee*/\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n\\\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\\\n            //will revert if data.totalDeposit is > eth balance in contract\\\\n            _deposit(_caller, data.totalDeposit, true);\\\\n\\\\n            //repay the flash swap\\\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\\\n\\\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\\\n\\\\n            //return excess eth to the user that was not needed for slippage\\\\n            if (address(this).balance > 0) {\\\\n                payable(_caller).sendValue(address(this).balance);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\\\n\\\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\\\n            uint256 ethToWithdraw = _withdraw(\\\\n                _caller,\\\\n                data.crabAmount,\\\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\\\n                true\\\\n            );\\\\n\\\\n            //use some amount of withdrawn ETH to repay flash swap\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\\\n\\\\n            //excess ETH not used to repay flash swap is transferred to the user\\\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\\\n\\\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\\\n\\\\n            if (proceeds > 0) {\\\\n                payable(_caller).sendValue(proceeds);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\\\n            //strategy is selling wSqueeth for ETH\\\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\\\n\\\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\\\n\\\\n            //minimum profit check for hedger\\\\n            require(wSqueethProfit >= data.minWSqueeth, \\\\\\\"profit is less than min wSqueeth\\\\\\\");\\\\n\\\\n            //repay flash swap and transfer profit to hedger\\\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\\\n            //strategy is buying wSqueeth for ETH\\\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\\\n\\\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\\\n\\\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\\\n\\\\n            //minimum profit check for hedger\\\\n            require(ethProfit >= data.minEth, \\\\\\\"profit is less than min ETH\\\\\\\");\\\\n\\\\n            //repay flash swap and transfer profit to hedger\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\\\n            payable(_caller).sendValue(ethProfit);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit into strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _depositor depositor address\\\\n     * @param _amount amount of ETH collateral to deposit\\\\n     * @param _isFlashDeposit true if called by flashDeposit\\\\n     * @return wSqueethToMint minted amount of WSqueeth\\\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\\\n     */\\\\n    function _deposit(\\\\n        address _depositor,\\\\n        uint256 _amount,\\\\n        bool _isFlashDeposit\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_amount, strategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\\\n\\\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\\\n\\\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\\\n            // store hedge data as strategy is delta neutral at this point\\\\n            // only execute this upon first deposit\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\\\n                ethWSqueethPool,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                hedgingTwapPeriod,\\\\n                true\\\\n            );\\\\n            timeAtLastHedge = block.timestamp;\\\\n            priceAtLastHedge = wSqueethEthPrice;\\\\n        }\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\\\n\\\\n        return (wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\\\n     * @return ETH amount to withdraw\\\\n     */\\\\n    function _withdraw(\\\\n        address _from,\\\\n        uint256 _crabAmount,\\\\n        uint256 _wSqueethAmount,\\\\n        bool _isFlashWithdraw\\\\n    ) internal returns (uint256) {\\\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\\\n\\\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\\\n        _burn(_from, _crabAmount);\\\\n\\\\n        return ethToWithdraw;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\\\n     */\\\\n    function _hedge(\\\\n        uint256 _auctionTriggerTime,\\\\n        bool _isStrategySellingWSqueeth,\\\\n        uint256 _limitPrice\\\\n    ) internal {\\\\n        (\\\\n            bool isSellingAuction,\\\\n            uint256 wSqueethToAuction,\\\\n            uint256 ethProceeds,\\\\n            uint256 auctionWSqueethEthPrice\\\\n        ) = _startAuction(_auctionTriggerTime);\\\\n\\\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\\\\\"wrong auction type\\\\\\\");\\\\n\\\\n        if (isSellingAuction) {\\\\n            // Receiving ETH and paying wSqueeth\\\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\\\\\"Auction price > max price\\\\\\\");\\\\n            require(msg.value >= ethProceeds, \\\\\\\"Low ETH amount received\\\\\\\");\\\\n\\\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\\\n        } else {\\\\n            require(msg.value == 0, \\\\\\\"ETH attached for buy auction\\\\\\\");\\\\n            // Receiving wSqueeth and paying ETH\\\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\\\\\"Auction price < min price\\\\\\\");\\\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\\\n        }\\\\n\\\\n        emit Hedge(\\\\n            msg.sender,\\\\n            _isStrategySellingWSqueeth,\\\\n            _limitPrice,\\\\n            auctionWSqueethEthPrice,\\\\n            wSqueethToAuction,\\\\n            ethProceeds\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute arb between auction price and uniswap price\\\\n     * @param _auctionTriggerTime auction starting time\\\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\\\n     */\\\\n    function _hedgeOnUniswap(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _minWSqueeth,\\\\n        uint256 _minEth\\\\n    ) internal {\\\\n        (\\\\n            bool isSellingAuction,\\\\n            uint256 wSqueethToAuction,\\\\n            uint256 ethProceeds,\\\\n            uint256 auctionWSqueethEthPrice\\\\n        ) = _startAuction(_auctionTriggerTime);\\\\n\\\\n        if (isSellingAuction) {\\\\n            _exactOutFlashSwap(\\\\n                wPowerPerp,\\\\n                weth,\\\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n                ethProceeds,\\\\n                wSqueethToAuction,\\\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\\\n            );\\\\n        } else {\\\\n            _exactOutFlashSwap(\\\\n                weth,\\\\n                wPowerPerp,\\\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n                wSqueethToAuction,\\\\n                ethProceeds,\\\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\\\n            );\\\\n        }\\\\n\\\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute sell auction based on the parameters calculated\\\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\\\n     * @param _buyer buyer address\\\\n     * @param _buyerAmount buyer ETH amount sent\\\\n     * @param _wSqueethToSell wSqueeth amount to sell\\\\n     * @param _ethToBuy ETH amount to buy\\\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\\\n     */\\\\n    function _executeSellAuction(\\\\n        address _buyer,\\\\n        uint256 _buyerAmount,\\\\n        uint256 _wSqueethToSell,\\\\n        uint256 _ethToBuy,\\\\n        bool _isHedgingOnUniswap\\\\n    ) internal {\\\\n        if (_isHedgingOnUniswap) {\\\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\\\n        } else {\\\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\\\n\\\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\\\n\\\\n            if (remainingEth > 0) {\\\\n                payable(_buyer).sendValue(remainingEth);\\\\n            }\\\\n        }\\\\n\\\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute buy auction based on the parameters calculated\\\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\\\n     * @param _seller seller address\\\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\\\n     * @param _ethToSell ETH amount to sell\\\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\\\n     */\\\\n    function _executeBuyAuction(\\\\n        address _seller,\\\\n        uint256 _wSqueethToBuy,\\\\n        uint256 _ethToSell,\\\\n        bool _isHedgingOnUniswap\\\\n    ) internal {\\\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\\\n\\\\n        if (!_isHedgingOnUniswap) {\\\\n            payable(_seller).sendValue(_ethToSell);\\\\n        }\\\\n\\\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\\\n     * @param _auctionTriggerTime auction starting time\\\\n     * @return auction type\\\\n     * @return WSqueeth amount to sell or buy\\\\n     * @return ETH to sell/buy\\\\n     * @return auction WSqueeth/ETH price\\\\n     */\\\\n    function _startAuction(uint256 _auctionTriggerTime)\\\\n        internal\\\\n        returns (\\\\n            bool,\\\\n            uint256,\\\\n            uint256,\\\\n            uint256\\\\n        )\\\\n    {\\\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            hedgingTwapPeriod,\\\\n            true\\\\n        );\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\\\n            strategyDebt,\\\\n            ethDelta,\\\\n            auctionWSqueethEthPrice,\\\\n            feeAdjustment\\\\n        );\\\\n\\\\n        require(isSellingAuction == isStillSellingAuction, \\\\\\\"auction direction changed\\\\\\\");\\\\n\\\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\\\n\\\\n        timeAtLastHedge = block.timestamp;\\\\n        priceAtLastHedge = currentWSqueethPrice;\\\\n\\\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sync strategy debt and collateral amount from vault\\\\n     * @return synced debt amount\\\\n     * @return synced collateral amount\\\\n     */\\\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\\\n\\\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\\\n     * @return the fee adjustment factor\\\\n     */\\\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\\\n            oracle,\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            POWER_PERP_PERIOD,\\\\n            false\\\\n        );\\\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\\\n     * @param _depositedAmount amount of deposited WETH\\\\n     * @param _strategyDebtAmount amount of strategy debt\\\\n     * @param _strategyCollateralAmount collateral amount in strategy\\\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\\\n     */\\\\n    function _calcWsqueethToMintAndFee(\\\\n        uint256 _depositedAmount,\\\\n        uint256 _strategyDebtAmount,\\\\n        uint256 _strategyCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 wSqueethToMint;\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n\\\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\\\n            require(totalSupply() == 0, \\\\\\\"Crab contracts shut down\\\\\\\");\\\\n\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\\\n                ethWSqueethPool,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                hedgingTwapPeriod,\\\\n                true\\\\n            );\\\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\\\n        } else {\\\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\\\n            );\\\\n        }\\\\n\\\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\\\n\\\\n        return (wSqueethToMint, fee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if time hedging is allowed\\\\n     * @return auction trigger timestamp\\\\n     */\\\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\\\n\\\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\\\n            secondsToPriceHedgeTrigger\\\\n        );\\\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\\\n\\\\n        return priceThreshold >= hedgePriceThreshold;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\\\n     * @return auction price\\\\n     */\\\\n    function _getAuctionPrice(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _wSqueethEthPrice,\\\\n        bool _isSellingAuction\\\\n    ) internal view returns (uint256) {\\\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\\\n            ? 1e18\\\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\\\n\\\\n        uint256 priceMultiplier;\\\\n        if (_isSellingAuction) {\\\\n            priceMultiplier = maxPriceMultiplier.sub(\\\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\\\n            );\\\\n        } else {\\\\n            priceMultiplier = minPriceMultiplier.add(\\\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\\\n            );\\\\n        }\\\\n\\\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\\\n     * @param _debt strategy debt\\\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\\\n     */\\\\n    function _checkAuctionType(\\\\n        uint256 _debt,\\\\n        uint256 _ethDelta,\\\\n        uint256 _wSqueethEthPrice,\\\\n        uint256 _feeAdjustment\\\\n    ) internal view returns (bool, uint256) {\\\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\\\n\\\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\\\n            wSqueethDelta,\\\\n            _ethDelta,\\\\n            _wSqueethEthPrice,\\\\n            _feeAdjustment\\\\n        );\\\\n\\\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\\\\\"strategy is delta neutral\\\\\\\");\\\\n\\\\n        return (isSellingAuction, targetHedge);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate amount of strategy token to mint for depositor\\\\n     * @param _amount amount of ETH deposited\\\\n     * @param _strategyCollateralAmount amount of strategy collateral\\\\n     * @param _crabTotalSupply total supply of strategy token\\\\n     * @return amount of strategy token to mint\\\\n     */\\\\n    function _calcSharesToMint(\\\\n        uint256 _amount,\\\\n        uint256 _strategyCollateralAmount,\\\\n        uint256 _crabTotalSupply\\\\n    ) internal pure returns (uint256) {\\\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\\\n\\\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\\\n\\\\n        return _amount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\\\n     * @param _crabAmount strategy token amount\\\\n     * @param _totalSupply strategy total supply\\\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\\\n     */\\\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\\\n        return _crabAmount.wdiv(_totalSupply);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\\\n     * @param _crabRatio crab ratio\\\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\\\n     * @return amount of ETH allowed to withdraw\\\\n     */\\\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine target hedge and auction type (selling/buying auction)\\\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\\\n     * @param _wSqueethDelta WSqueeth delta\\\\n     * @param _ethDelta ETH delta\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\\\n     * @return target hedge in wSqueeth\\\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\\\n     */\\\\n    function _getTargetHedgeAndAuctionType(\\\\n        uint256 _wSqueethDelta,\\\\n        uint256 _ethDelta,\\\\n        uint256 _wSqueethEthPrice,\\\\n        uint256 _feeAdjustment\\\\n    ) internal pure returns (uint256, bool) {\\\\n        return\\\\n            (_wSqueethDelta > _ethDelta)\\\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86a9d034ce1d510b05c23a0e2d42865823c676e17685494bde6c954504062366\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyBase.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./StrategyMath.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../../libs/VaultLib.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev StrategyBase contract\\\\n * @notice base contract for PowerToken strategy\\\\n * @author opyn team\\\\n */\\\\ncontract StrategyBase is ERC20 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev power token controller\\\\n    IController public powerTokenController;\\\\n\\\\n    /// @dev WETH token\\\\n    address public immutable weth;\\\\n    address public immutable wPowerPerp;\\\\n\\\\n    /// @dev power token strategy vault ID\\\\n    uint256 public immutable vaultId;\\\\n\\\\n    /**\\\\n     * @notice constructor for StrategyBase\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _powerTokenController power token controller address\\\\n     * @param _weth weth token address\\\\n     * @param _name token name for strategy ERC20 token\\\\n     * @param _symbol token symbol for strategy ERC20 token\\\\n     */\\\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\\\n        require(_powerTokenController != address(0), \\\\\\\"invalid controller address\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"invalid weth address\\\\\\\");\\\\n\\\\n        weth = _weth;\\\\n        powerTokenController = IController(_powerTokenController);\\\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\\\n    }\\\\n    /**\\\\n     * @notice get power token strategy vault ID \\\\n     * @return vault ID\\\\n     */\\\\n    function getStrategyVaultId() external view returns (uint256) {\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n    */\\\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\\\n        return _getVaultDetails();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint WPowerPerp and deposit collateral\\\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\\\n     * @param _to receiver address\\\\n     * @param _wAmount amount of WPowerPerp to mint\\\\n     * @param _collateral amount of collateral to deposit\\\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\\\n     */\\\\n    function _mintWPowerPerp(\\\\n        address _to,\\\\n        uint256 _wAmount,\\\\n        uint256 _collateral,\\\\n        bool _keepWsqueeth\\\\n    ) internal {\\\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\\\n\\\\n        if (!_keepWsqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn WPowerPerp and withdraw collateral\\\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\\\n     * @param _from WPowerPerp holder address\\\\n     * @param _amount amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\\\n     */\\\\n    function _burnWPowerPerp(\\\\n        address _from,\\\\n        uint256 _amount,\\\\n        uint256 _collateralToWithdraw,\\\\n        bool _isOwnedWSqueeth\\\\n    ) internal {\\\\n        if (!_isOwnedWSqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\\\n        }\\\\n\\\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint strategy token\\\\n     * @param _to recepient address\\\\n     * @param _amount token amount\\\\n     */\\\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\\\n        _mint(_to, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get strategy debt amount for a specific strategy token amount\\\\n     * @param _strategyAmount strategy amount\\\\n     * @return debt amount\\\\n     */\\\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n     */\\\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\\\n\\\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\\\n    }\\\\n}\\\\n\\\\n\\\",\\\"keccak256\\\":\\\"0xa18ad4c34899e27bdf048a866834e05dda91ee8ff904fac23587dddf69a5d675\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyFlashSwap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\\\n\\\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\\\n    using Path for bytes;\\\\n    using SafeCast for uint256;\\\\n    using LowGasSafeMath for uint256;\\\\n    using LowGasSafeMath for int256;\\\\n\\\\n    /// @dev Uniswap factory address\\\\n    address public immutable factory;\\\\n\\\\n    struct SwapCallbackData {\\\\n        bytes path;\\\\n        address caller;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev constructor\\\\n     * @param _factory uniswap factory address\\\\n     */\\\\n    constructor(\\\\n        address _factory\\\\n    ) {\\\\n        require(_factory != address(0), \\\\\\\"invalid factory address\\\\\\\");\\\\n        factory = _factory;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap swap callback function for flashes\\\\n     * @param amount0Delta amount of token0\\\\n     * @param amount1Delta amount of token1\\\\n     * @param _data callback data encoded as SwapCallbackData struct\\\\n     */\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata _data\\\\n    ) external override {\\\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\\\n\\\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //ensure that callback comes from uniswap pool\\\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\\\n\\\\n        //determine the amount that needs to be repaid as part of the flashswap\\\\n        uint256 amountToPay =\\\\n            amount0Delta > 0\\\\n                ?  uint256(amount0Delta)\\\\n                :  uint256(amount1Delta);\\\\n        \\\\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountIn amount to sell\\\\n     * @param _amountOutMinimum minimum amount to receive\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountOut = _exactInputInternal(\\\\n            _amountIn,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n       \\\\n        //slippage limit check\\\\n        require(amountOut >= _amountOutMinimum, \\\\\\\"amount out less than min\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountOut exact amount to receive\\\\n     * @param _amountInMaximum maximum amount to sell\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountIn = _exactOutputInternal(\\\\n            _amountOut,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n        \\\\n        //slippage limit check\\\\n        require(amountIn <= _amountInMaximum, \\\\\\\"amount in greater than max\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice function to be called by uniswap callback. \\\\n     * @dev this function should be overridden by the child contract\\\\n     * param _caller initial strategy function caller\\\\n     * param _tokenIn token address sold\\\\n     * param _tokenOut token address bought\\\\n     * param _fee pool fee\\\\n     * param _amountToPay amount to pay for the pool second token\\\\n     * param _callData arbitrary data assigned with the flashswap call \\\\n     * param _callSource function call source\\\\n     */\\\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\\\n    \\\\n    /** \\\\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\\\n    * @param _amountIn amount of token to pay\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token bought (amountOut)\\\\n    */\\\\n    function _exactInputInternal(\\\\n        uint256 _amountIn,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n       \\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0, int256 amount1) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                _amountIn.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n        \\\\n        //determine the amountOut based on which token has a lower address\\\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\\\n    * @param _amountOut amount of token to receive\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token sold (amountIn)\\\\n    */\\\\n    function _exactOutputInternal(\\\\n        uint256 _amountOut,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n        \\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0Delta, int256 amount1Delta) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                -_amountOut.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n\\\\n        //determine the amountIn and amountOut based on which token has a lower address\\\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\\\n        // it's technically possible to not receive the full output amount,\\\\n        // so if no price limit has been specified, require this possibility away\\\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\\\n\\\\n        return amountIn;\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice returns the uniswap pool for the given token pair and fee\\\\n    * @dev the pool contract may or may not exist\\\\n    * @param tokenA address of first token \\\\n    * @param tokenB address of second token \\\\n    * @param fee fee tier for pool\\\\n    */\\\\n    function _getPool(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool) {\\\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x91b49caf229fd114fbb589e73056772cf15a0adaba0a6f5eca4dff9cd12b9575\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/base/StrategyMath.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: AGPL-3.0-only\\\\n\\\\n/// math.sol -- mixin for inline numerical wizardry\\\\n\\\\n// This program is free software: you can redistribute it and/or modify\\\\n// it under the terms of the GNU General Public License as published by\\\\n// the Free Software Foundation, either version 3 of the License, or\\\\n// (at your option) any later version.\\\\n\\\\n// This program is distributed in the hope that it will be useful,\\\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\\\n// GNU General Public License for more details.\\\\n\\\\n// You should have received a copy of the GNU General Public License\\\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\\\n\\\\npragma solidity >0.4.13;\\\\n\\\\n\\\\n/**\\\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\\\n * @dev change contract to library, added div() function\\\\n */\\\\nlibrary StrategyMath {\\\\n    function add(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x + y) >= x, \\\\\\\"ds-math-add-overflow\\\\\\\");\\\\n    }\\\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x - y) <= x, \\\\\\\"ds-math-sub-underflow\\\\\\\");\\\\n    }\\\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\\\n        require(y == 0 || (z = x * y) / y == x, \\\\\\\"ds-math-mul-overflow\\\\\\\");\\\\n    }\\\\n\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    function min(uint x, uint y) internal pure returns (uint z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function max(uint x, uint y) internal pure returns (uint z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n    function imin(int x, int y) internal pure returns (int z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function imax(int x, int y) internal pure returns (int z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n\\\\n    uint constant WAD = 10 ** 18;\\\\n    uint constant RAY = 10 ** 27;\\\\n\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), WAD / 2) / WAD;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), RAY / 2) / RAY;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, WAD), y / 2) / y;\\\\n    }\\\\n    //rounds to zero if x*y < RAY / 2\\\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, RAY), y / 2) / y;\\\\n    }\\\\n\\\\n    // Ceil A to a multiple m\\\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(sub(add(a, m), 1), m), m);\\\\n    }\\\\n\\\\n    // Floor A to a multiple m\\\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(a, m), m);\\\\n    }\\\\n\\\\n    // This famous algorithm is called \\\\\\\"exponentiation by squaring\\\\\\\"\\\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\\\n    //\\\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\\\n    //\\\\n    // These facts are why it works:\\\\n    //\\\\n    //  If n is even, then x^n = (x^2)^(n/2).\\\\n    //  If n is odd,  then x^n = x * x^(n-1),\\\\n    //   and applying the equation for even x gives\\\\n    //    x^n = x * (x^2)^((n-1) / 2).\\\\n    //\\\\n    //  Also, EVM division is flooring and\\\\n    //    floor[(n-1) / 2] = floor[n / 2].\\\\n    //\\\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\\\n        z = n % 2 != 0 ? x : RAY;\\\\n\\\\n        for (n /= 2; n != 0; n /= 2) {\\\\n            x = rmul(x, x);\\\\n\\\\n            if (n % 2 != 0) {\\\\n                z = rmul(z, x);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0xfec6fa07fbbb639f94321d6503f5363286776cf831215017ce28aae67295613b\\\",\\\"license\\\":\\\"AGPL-3.0-only\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101806040526009805463ffffffff19166101a417905566038d7ea4c68000600a553480156200002e57600080fd5b5060405162006b8838038062006b888339810160408190526200005191620006af565b868a896040518060400160405280600d81526020016c4372616220537472617465677960981b8152506040518060400160405280600481526020016321b930b160e11b81525081818160039080519060200190620000b1929190620005c2565b508051620000c7906004906020840190620005c2565b50506005805460ff19166012179055506001600160a01b038416620001095760405162461bcd60e51b8152600401620001009062000892565b60405180910390fd5b6001600160a01b038316620001325760405162461bcd60e51b81526004016200010090620008c9565b606083901b6001600160601b03191660805260058054610100600160a81b0319166101006001600160a01b0387811682029290921792839055604080516307f07b1360e41b815290519190930490911691637f07b130916004808301926020929190829003018186803b158015620001a957600080fd5b505afa158015620001be573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001e491906200068b565b6001600160601b031960609190911b1660a052600554604051630728cf2360e31b81526101009091046001600160a01b03169063394679189062000232906000908190819060040162000769565b602060405180830381600087803b1580156200024d57600080fd5b505af115801562000262573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000288919062000750565b60c052505050506001600160a01b038116620002b85760405162461bcd60e51b815260040162000100906200085b565b60601b6001600160601b03191660e05260016006556000620002d9620005be565b600780546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b038916620003505760405162461bcd60e51b8152600401620001009062000824565b6001600160a01b038616620003795760405162461bcd60e51b8152600401620001009062000937565b600085116200039c5760405162461bcd60e51b81526004016200010090620007ed565b60008411620003bf5760405162461bcd60e51b81526004016200010090620007b6565b60008311620003e25760405162461bcd60e51b815260040162000100906200077f565b670de0b6b3a764000082106200040c5760405162461bcd60e51b815260040162000100906200096e565b600082116200042f5760405162461bcd60e51b81526004016200010090620009a5565b670de0b6b3a76400008111620004595760405162461bcd60e51b8152600401620001009062000900565b6001600160601b031960608a811b82166101205287901b1661010052600b859055600c849055600d839055600e829055600f81905560408051632234601160e11b815290516001600160a01b038c1691634468c022916004808301926020929190829003018186803b158015620004cf57600080fd5b505afa158015620004e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200050a91906200068b565b6001600160a01b0316610140816001600160a01b031660601b81525050896001600160a01b03166382564bca6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200056157600080fd5b505afa15801562000576573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200059c91906200068b565b60601b6001600160601b0319166101605250620009dc98505050505050505050565b3390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620005fa576000855562000645565b82601f106200061557805160ff191683800117855562000645565b8280016001018555821562000645579182015b828111156200064557825182559160200191906001019062000628565b506200065392915062000657565b5090565b5b8082111562000653576000815560010162000658565b80516001600160a01b03811681146200068657600080fd5b919050565b6000602082840312156200069d578081fd5b620006a8826200066e565b9392505050565b6000806000806000806000806000806101408b8d031215620006cf578586fd5b620006da8b6200066e565b9950620006ea60208c016200066e565b9850620006fa60408c016200066e565b97506200070a60608c016200066e565b96506200071a60808c016200066e565b955060a08b0151945060c08b0151935060e08b015192506101008b015191506101208b015190509295989b9194979a5092959850565b60006020828403121562000762578081fd5b5051919050565b9283526020830191909152604082015260600190565b60208082526014908201527f696e76616c69642061756374696f6e2074696d65000000000000000000000000604082015260600190565b6020808252601d908201527f696e76616c6964206865646765207072696365207468726573686f6c64000000604082015260600190565b6020808252601c908201527f696e76616c69642068656467652074696d65207468726573686f6c6400000000604082015260600190565b60208082526016908201527f696e76616c6964206f7261636c65206164647265737300000000000000000000604082015260600190565b60208082526017908201527f696e76616c696420666163746f72792061646472657373000000000000000000604082015260600190565b6020808252601a908201527f696e76616c696420636f6e74726f6c6c65722061646472657373000000000000604082015260600190565b60208082526014908201527f696e76616c696420776574682061646472657373000000000000000000000000604082015260600190565b6020808252601c908201527f6d6178207072696365206d756c7469706c69657220746f6f206c6f7700000000604082015260600190565b6020808252601c908201527f696e76616c6964204554483a5753717565657468206164647265737300000000604082015260600190565b6020808252601d908201527f6d696e207072696365206d756c7469706c69657220746f6f2068696768000000604082015260600190565b6020808252601c908201527f696e76616c6964206d696e207072696365206d756c7469706c69657200000000604082015260600190565b60805160601c60a05160601c60c05160e05160601c6101005160601c6101205160601c6101405160601c6101605160601c615ff962000b8f6000398061189f5250806114e8525080610c6d52806118575280611fbf528061254f5280612f585280613360528061348a5280614467525080610c9a5280610db05280610ff8528061150c5280611fec528061257c5280612f855280613116528061320d528061338d52806134ab52806138ef5280613b705280613e1a52806140765280614494525080611d3052806123525280614de35250806112a052806115da5280611aca5280612e5752806147ba52806148ee525080610cbc5280610d6e5280610fd7528061187b528061200e528061259e5280612fa752806130d452806131ec52806133af52806134cc52806138c25280613a155280613ded5280613eae52806144b65280614701528061498a5250806103a05280610cde5280610d8f5280610fb652806114c4528061203052806125c05280612fc952806130f552806131cb52806133d152806134ed52806137be5280613aba5280613b405280613cb15280613fc0528061404652806144d85250615ff96000f3fe6080604052600436106103905760003560e01c80637bcdc16e116101dc578063bdd438b811610102578063dfc19520116100a0578063f5d278e41161006f578063f5d278e4146109e2578063f73e19c3146109f7578063fa004fbf14610a17578063fa461e3314610a3757610402565b8063dfc195201461095c578063f101d92f1461097c578063f20e5e3514610991578063f2fde38b146109c257610402565b8063cae74029116100dc578063cae74029146108ff578063d0e30db014610914578063d4aec8171461091c578063dd62ed3e1461093c57610402565b8063bdd438b8146108a7578063c2451689146108c7578063c45a0155146108ea57610402565b8063955a15e81161017a578063a457c2d711610149578063a457c2d714610827578063a54c889914610847578063a9059cbb14610867578063b0b934611461088757610402565b8063955a15e8146107c857806395d89b41146107dd5780639c1ab1b8146107f2578063a319b29f1461081257610402565b806382564bca116101b657806382564bca146107695780638da5cb5b1461077e5780638ec4b721146107935780638f8b8dbc146107a857610402565b80637bcdc16e1461071f5780637dc0d1d01461073f5780637f07b1301461075457610402565b8063395ebb69116102c15780635e5cdcd71161025f5780636c1040a91161022e5780636c1040a9146106c257806370749b44146106d757806370a08231146106ea578063715018a61461070a57610402565b80635e5cdcd71461067057806363bbc4b61461068357806366a91b761461069857806367b8c345146106ad57610402565b80633fc8cef31161029b5780633fc8cef31461060c5780634468c022146106215780634d76e6fc14610636578063533092ef1461064b57610402565b8063395ebb69146105a85780633d3a62ee146105ca5780633dcb0c5d146105ea57610402565b806323ccafd91161032e5780632e1a7d4d116103085780632e1a7d4d14610531578063313ce5671461055157806333194c0a14610573578063395093511461058857610402565b806323ccafd9146104e957806325d7707c146105095780632a3400561461051c57610402565b8063155f586d1161036a578063155f586d1461047f57806318160ddd146104a15780631a5af342146104b657806323b872dd146104c957610402565b806306fdde0314610407578063095ea7b3146104325780630ca514cd1461045f57610402565b3661040257336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103db575060055461010090046001600160a01b031633145b6104005760405162461bcd60e51b81526004016103f790615b26565b60405180910390fd5b005b600080fd5b34801561041357600080fd5b5061041c610a57565b60405161042991906157da565b60405180910390f35b34801561043e57600080fd5b5061045261044d36600461519c565b610aed565b604051610429919061573e565b34801561046b57600080fd5b5061040061047a36600461549b565b610b0b565b34801561048b57600080fd5b50610494610bad565b60405161042991906155f7565b3480156104ad57600080fd5b50610494610bb3565b6104006104c436600461549b565b610bb9565b3480156104d557600080fd5b506104526104e436600461515c565b610ebf565b3480156104f557600080fd5b506104006105043660046154f1565b610f47565b6104006105173660046151e3565b6110fd565b34801561052857600080fd5b506104946111cd565b34801561053d57600080fd5b5061040061054c36600461549b565b6111d3565b34801561055d57600080fd5b50610566611295565b6040516104299190615db9565b34801561057f57600080fd5b5061049461129e565b34801561059457600080fd5b506104526105a336600461519c565b6112c2565b3480156105b457600080fd5b506105bd611310565b6040516104299190615da8565b3480156105d657600080fd5b506104006105e536600461549b565b611316565b3480156105f657600080fd5b506105ff6114ae565b604051610429919061561b565b34801561061857600080fd5b506105ff6114c2565b34801561062d57600080fd5b506105ff6114e6565b34801561064257600080fd5b506105ff61150a565b34801561065757600080fd5b5061066061152e565b6040516104299493929190615718565b61040061067e366004615512565b61154a565b34801561068f57600080fd5b506104946115c6565b3480156106a457600080fd5b506104946115cc565b3480156106b957600080fd5b506104946115d2565b3480156106ce57600080fd5b506104946115d8565b6104006106e53660046154cb565b6115fc565b3480156106f657600080fd5b50610494610705366004615108565b6116c6565b34801561071657600080fd5b506104006116e5565b34801561072b57600080fd5b5061040061073a36600461549b565b61179e565b34801561074b57600080fd5b506105ff611855565b34801561076057600080fd5b506105ff611879565b34801561077557600080fd5b506105ff61189d565b34801561078a57600080fd5b506105ff6118c1565b34801561079f57600080fd5b506104946118d0565b3480156107b457600080fd5b506104006107c336600461553d565b6118d6565b3480156107d457600080fd5b506104946119a4565b3480156107e957600080fd5b5061041c6119aa565b3480156107fe57600080fd5b5061040061080d3660046154f1565b611a0b565b34801561081e57600080fd5b50610400611a8f565b34801561083357600080fd5b5061045261084236600461519c565b611b26565b34801561085357600080fd5b5061040061086236600461549b565b611b8e565b34801561087357600080fd5b5061045261088236600461519c565b611c45565b34801561089357600080fd5b506104526108a236600461549b565b611c59565b3480156108b357600080fd5b506104006108c236600461549b565b611c64565b3480156108d357600080fd5b506108dc611d1b565b604051610429929190615749565b3480156108f657600080fd5b506105ff611d2e565b34801561090b57600080fd5b50610494611d52565b610400611d58565b34801561092857600080fd5b5061040061093736600461549b565b611e03565b34801561094857600080fd5b50610494610957366004615124565b611e9a565b34801561096857600080fd5b5061040061097736600461549b565b611ec5565b34801561098857600080fd5b50610494611f83565b34801561099d57600080fd5b506109b16109ac36600461549b565b611f89565b60405161042995949392919061578e565b3480156109ce57600080fd5b506104006109dd366004615108565b612128565b3480156109ee57600080fd5b506105bd612238565b348015610a0357600080fd5b50610494610a1236600461549b565b612244565b348015610a2357600080fd5b50610400610a3236600461549b565b61224f565b348015610a4357600080fd5b50610400610a52366004615223565b61230d565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ae35780601f10610ab857610100808354040283529160200191610ae3565b820191906000526020600020905b815481529060010190602001808311610ac657829003601f168201915b5050505050905090565b6000610b01610afa6123b3565b84846123b7565b5060015b92915050565b610b136123b3565b6001600160a01b0316610b246118c1565b6001600160a01b031614610b6d576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b60088190556040517f29600e2e028c8c5c2b112d021938e0d0237d8fafcbb20394c56cf9fa4661ca2790610ba29083906155f7565b60405180910390a150565b600d5481565b60025490565b60026006541415610c11576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600080610c216124a3565b91509150610c2f83826124bd565b6000610c3c8484846124ec565b50905082158015610c4b575081155b15610d695760095460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591610d10917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff169060019060040161562f565b60206040518083038186803b158015610d2857600080fd5b505afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6091906154b3565b42601055601155505b610e717f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610e0757600080fd5b505afa158015610e1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3f9190615478565b84610e4a89346126bc565b60008a604051602001610e5d91906155f7565b604051602081830303815290604052612714565b336001600160a01b03167f5d85169ff8329e90f3225f9798e0eba54d00c55d3bbfe201a0d1606febb23a8e8583604051610eac929190615d6c565b60405180910390a2505060016006555050565b6000610ecc848484612795565b610f3c84610ed86123b3565b610f3785604051806060016040528060288152602001615eed602891396001600160a01b038a16600090815260016020526040812090610f166123b3565b6001600160a01b0316815260208101919091526040016000205491906128f0565b6123b7565b5060015b9392505050565b60026006541415610f9f576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610faf83612987565b90506110b07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b15801561104f57600080fd5b505afa158015611063573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110879190615478565b848660018960405160200161109c91906155f7565b6040516020818303038152906040526129ac565b336001600160a01b03167fa13b272c1cf13ba724064d3d4809d9f557aab8da2bb582cba031a2f57e728e9d84836040516110eb929190615d6c565b60405180910390a25050600160065550565b60026006541415611155576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600080611165612a23565b91509150816111865760405162461bcd60e51b81526004016103f790615aef565b611191818585612a4c565b336001600160a01b03167eb3acebad2d25b9626850dd370eadbf46d6a94dd0fab19c061f97e1dd4a9639858584604051610eac93929190615759565b600e5481565b6002600654141561122b576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600061123b82612987565b9050600061124c3384846000612b7c565b90506112583382612bc9565b336001600160a01b03167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca948484846040516110eb93929190615d92565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610b016112cf6123b3565b84610f3785600160006112e06123b3565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490612cb3565b6101a481565b6002600654141561136e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600681905550600560019054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156113c657600080fd5b505af11580156113da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113fe91906151c7565b61141a5760405162461bcd60e51b81526004016103f790615c37565b60125460ff1661143c5760405162461bcd60e51b81526004016103f79061596e565b600061144f8261144a610bb3565b612d0d565b9050600061145d8247612d19565b90506114693384612d25565b6114733382612bc9565b336001600160a01b03167fe9ab9870b9093d99f8e981919f65ad09b7ae90ff80f1031639af9e0357eb9ed684836040516110eb929190615d6c565b60055461010090046001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008061153c612e21565b935093509350935090919293565b61155383612f18565b61156f5760405162461bcd60e51b81526004016103f7906159dc565b61157a8383836130b2565b336001600160a01b03167ff99cce6ee3154fddfc55959dd136665c7351fe51c0ea58392ca454be8180dcd4428585856040516115b99493929190615600565b60405180910390a2505050565b60115481565b600b5481565b60105481565b7f000000000000000000000000000000000000000000000000000000000000000090565b60026006541415611654576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065561166283612f18565b61167e5760405162461bcd60e51b81526004016103f7906159dc565b611689838383612a4c565b336001600160a01b03167fa6806e5672ec1827d23bd4a25f4a41c8d0b055720c40081e3803f6b0a957f7978383866040516110eb93929190615759565b6001600160a01b0381166000908152602081905260409020545b919050565b6116ed6123b3565b6001600160a01b03166116fe6118c1565b6001600160a01b031614611747576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b6007546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36007805473ffffffffffffffffffffffffffffffffffffffff19169055565b6117a66123b3565b6001600160a01b03166117b76118c1565b6001600160a01b031614611800576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b600081116118205760405162461bcd60e51b81526004016103f7906158c9565b600b8190556040517f28e0e4ee0b14d4b056ce88e1bcd890ccd32b22e213723c8765901381b5eae70590610ba29083906155f7565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6007546001600160a01b031690565b600f5481565b6118de6123b3565b6001600160a01b03166118ef6118c1565b6001600160a01b031614611938576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b60b48163ffffffff16101561195f5760405162461bcd60e51b81526004016103f790615ca5565b6009805463ffffffff191663ffffffff83161790556040517f1cd9c7f99a5530a38c8f2b387dcc78e8a76cb5b203e0c4316a66777d993dee3590610ba2908390615da8565b600a5481565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ae35780601f10610ab857610100808354040283529160200191610ae3565b600080611a16612a23565b9150915081611a375760405162461bcd60e51b81526004016103f790615aef565b611a428185856130b2565b336001600160a01b03167f6c3a0d23de8295593e3e236062f9103f4a66c6d8de92b9425a2e17ae3baca67742838787604051611a819493929190615600565b60405180910390a250505050565b60128054600160ff19909116179055600554604051634bf7d4a160e11b81526101009091046001600160a01b0316906397efa94290611af2907f0000000000000000000000000000000000000000000000000000000000000000906004016155f7565b600060405180830381600087803b158015611b0c57600080fd5b505af1158015611b20573d6000803e3d6000fd5b50505050565b6000610b01611b336123b3565b84610f3785604051806060016040528060258152602001615f9f6025913960016000611b5d6123b3565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906128f0565b611b966123b3565b6001600160a01b0316611ba76118c1565b6001600160a01b031614611bf0576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b60008111611c105760405162461bcd60e51b81526004016103f79061585b565b600d8190556040517f6405fa008c5cc5710b13a509f31e7596708bdbc2a52c85a15f9992697a791b2090610ba29083906155f7565b6000610b01611c526123b3565b8484612795565b6000610b0582612f18565b611c6c6123b3565b6001600160a01b0316611c7d6118c1565b6001600160a01b031614611cc6576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b60008111611ce65760405162461bcd60e51b81526004016103f790615892565b600c8190556040517f789e4b8ad1c375952cea7f07c9b3b6619a84b406432b948246cecb8ced96b9fa90610ba29083906155f7565b600080611d26612a23565b915091509091565b7f000000000000000000000000000000000000000000000000000000000000000081565b60085481565b60026006541415611db0576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065534600080611dc43384836132e4565b91509150336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1583836040516110eb929190615d6c565b611e0b6123b3565b6001600160a01b0316611e1c6118c1565b6001600160a01b031614611e65576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b600a8190556040517f48100eb8aecbbf59b3665ff2a7b2d7257a218196dec79a67ca870fca43cdff6290610ba29083906155f7565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b611ecd6123b3565b6001600160a01b0316611ede6118c1565b6001600160a01b031614611f27576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b670de0b6b3a76400008111611f4e5760405162461bcd60e51b81526004016103f790615c00565b600f8190556040517fce6ae334d464afcb4f9f5f5218c4e3b0d5d227a821cb8a76bbff56da8f5f0b8890610ba29083906155f7565b600c5481565b6000806000806000806000611f9c6124a3565b60095460405163cce79bd560e01b81529294509092506000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591612064917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff9091169060019060040161562f565b60206040518083038186803b15801561207c57600080fd5b505afa158015612090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b491906154b3565b905060006120c0613482565b905060006120d0858585856135bf565b50905060006120e08c8584613630565b90506000806120f1888885886135bf565b90925090508315158215151415600061210a83866136e3565b959e50919c50939a5091985091965050505050505091939590929450565b6121306123b3565b6001600160a01b03166121416118c1565b6001600160a01b03161461218a576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b6001600160a01b0381166121cf5760405162461bcd60e51b8152600401808060200182810382526026815260200180615e456026913960400191505060405180910390fd5b6007546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60095463ffffffff1681565b6000610b0582612987565b6122576123b3565b6001600160a01b03166122686118c1565b6001600160a01b0316146122b1576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b670de0b6b3a764000081106122d85760405162461bcd60e51b81526004016103f790615c6e565b600e8190556040517f07515fe9cd564f272668faa064c14bc4cec5f75710703ff96a21a47b680ce28f90610ba29083906155f7565b600084138061231c5750600083135b61232557600080fd5b600061233382840184615318565b90506000806000612347846000015161371c565b9250925092506123797f000000000000000000000000000000000000000000000000000000000000000084848461374d565b506000808913612389578761238b565b885b90506123a88560200151858585858a606001518b6040015161376c565b505050505050505050565b3390565b6001600160a01b0383166123fc5760405162461bcd60e51b8152600401808060200182810382526024815260200180615f7b6024913960400191505060405180910390fd5b6001600160a01b0382166124415760405162461bcd60e51b8152600401808060200182810382526022815260200180615e6b6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6000806000806124b1612e21565b96509450505050509091565b6008546124ca828461410f565b11156124e85760405162461bcd60e51b81526004016103f790615b5d565b5050565b6000806000806124fa613482565b905085158015612508575084155b1561267757612515610bb3565b156125325760405162461bcd60e51b81526004016103f790615a81565b60095460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd5916125f2917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff169060019060040161562f565b60206040518083038186803b15801561260a57600080fd5b505afa15801561261e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264291906154b3565b9050600061265882671bc16d674ec800006136e3565b905061266e612667828561410f565b8a90614167565b935050506126a1565b61269e61268e61268788846136e3565b879061410f565b61269889896136e3565b90614167565b91505b60006126ad83836136e3565b92989297509195505050505050565b80820382811115610b05576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b60006127698530600060405180608001604052808d8c8e60405160200161273d939291906155a4565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052614187565b90508381101561278b5760405162461bcd60e51b81526004016103f790615824565b5050505050505050565b6001600160a01b0383166127da5760405162461bcd60e51b8152600401808060200182810382526025815260200180615f566025913960400191505060405180910390fd5b6001600160a01b03821661281f5760405162461bcd60e51b8152600401808060200182810382526023815260200180615e006023913960400191505060405180910390fd5b61282a838383612cae565b61286781604051806060016040528060268152602001615e8d602691396001600160a01b03861660009081526020819052604090205491906128f0565b6001600160a01b0380851660009081526020819052604080822093909355908416815220546128969082612cb3565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000818484111561297f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561294457818101518382015260200161292c565b50505050905090810190601f1680156129715780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600080612992612e21565b9350505050610f406129a2610bb3565b61269883866136e3565b6000612a018530600060405180608001604052808c8c8f6040516020016129d5939291906155a4565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526142c6565b90508381111561278b5760405162461bcd60e51b81526004016103f7906159a5565b6000806000612a3f600b5460105461410f90919063ffffffff16565b4281111593509150509091565b600080600080612a5b87614433565b935093509350935083151586151514612a865760405162461bcd60e51b81526004016103f790615937565b8315612adf5784811115612aac5760405162461bcd60e51b81526004016103f790615a4a565b81341015612acc5760405162461bcd60e51b81526004016103f790615900565b612ada3334858560006145ea565b612b2a565b3415612afd5760405162461bcd60e51b81526004016103f790615b94565b84811015612b1d5760405162461bcd60e51b81526004016103f7906157ed565b612b2a3384846000614684565b336001600160a01b03167f878fd3ca52ad322c7535f559ee7c91afc67363073783360ef1b1420589dc61748787848787604051612b6b9594939291906157b5565b60405180910390a250505050505050565b600080612b876124a3565b9150506000612b988661144a610bb3565b90506000612ba68284612d19565b9050612bb4888783886146e5565b612bbe8888612d25565b979650505050505050565b80471015612c1e576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114612c69576040519150601f19603f3d011682016040523d82523d6000602084013e612c6e565b606091505b5050905080612cae5760405162461bcd60e51b815260040180806020018281038252603a815260200180615eb3603a913960400191505060405180910390fd5b505050565b600082820183811015610f40576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610f408383614167565b6000610f4082846136e3565b6001600160a01b038216612d6a5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f356021913960400191505060405180910390fd5b612d7682600083612cae565b612db381604051806060016040528060228152602001615e23602291396001600160a01b03851660009081526020819052604090205491906128f0565b6001600160a01b038316600090815260208190526040902055600254612dd99082614814565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600554604051634632752560e11b8152600091829182918291829161010090046001600160a01b031690638c64ea4a90612e7f907f0000000000000000000000000000000000000000000000000000000000000000906004016155f7565b60806040518083038186803b158015612e9757600080fd5b505afa158015612eab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ecf91906153d6565b805160208201516040830151606090930151919863ffffffff90911697506bffffffffffffffffffffffff90921695506fffffffffffffffffffffffffffffffff169350915050565b6000601054821015612f2c575060006116e0565b6000612f3842846126bc565b600954604051634ac78d1160e01b81529192506000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691634ac78d1191612ffe917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff9091168901908990600401615668565b60206040518083038186803b15801561301657600080fd5b505afa15801561302a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061304e91906154b3565b905060006130676011548361416790919063ffffffff16565b90506000670de0b6b3a764000082116130915761308c670de0b6b3a7640000836126bc565b6130a3565b6130a382670de0b6b3a76400006126bc565b600c5411159695505050505050565b6000806000806130c187614433565b935093509350935083156131c6576131c17f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b15801561316d57600080fd5b505afa158015613181573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131a59190615478565b858760025b89898e8e60405160200161109c9493929190615600565b6132a5565b6132a57f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b15801561326457600080fd5b505afa158015613278573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061329c9190615478565b868660036131aa565b336001600160a01b03167f4c1a959210172325f5c6678421c3834b04ae8ce57f7a7c0c0bbfbb62bca37e3485838686604051612b6b9493929190615771565b6000806000806132f26124a3565b9150915061330086826124bd565b60008061330e8885856124ec565b909250905060006133306133228a846126bc565b8561332b610bb3565b614871565b90508415801561333e575083155b1561345c5760095460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591613403917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff169060019060040161562f565b60206040518083038186803b15801561341b57600080fd5b505afa15801561342f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061345391906154b3565b42601055601155505b6134688a848b8b6148c0565b6134728a82614a1a565b9199919850909650505050505050565b6000806135167f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a46000614a24565b90506000600560019054906101000a90046001600160a01b03166001600160a01b031663978bbdb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561356857600080fd5b505afa15801561357c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135a091906154b3565b90506135b86127106135b28484614aca565b90614b36565b9250505090565b600080806135df856135d989671bc16d674ec800006136e3565b906136e3565b90506000806135f083898989614b95565b600a54919350915061360689612698858b6136e3565b116136235760405162461bcd60e51b81526004016103f790615cdc565b9890975095505050505050565b600d54600090819061364242876126bc565b101561365e57600d546136599061269842886126bc565b613668565b670de0b6b3a76400005b9050600083156136a65761369f61369661368f600e54600f546126bc90919063ffffffff16565b84906136e3565b600f54906126bc565b90506136cf565b6136cc6136c361368f600e54600f546126bc90919063ffffffff16565b600e549061410f565b90505b6136d985826136e3565b9695505050505050565b6000670de0b6b3a764000061370d6136fb8585614aca565b6002670de0b6b3a76400005b0461410f565b8161371457fe5b049392505050565b6000808061372a8482614bdb565b9250613737846014614ca7565b9050613744846017614bdb565b91509193909250565b60006137638561375e868686614d63565b614db9565b95945050505050565b60008160ff16600381111561377d57fe5b600381111561378857fe5b14156139ce576000828060200190518101906137a4919061529e565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906137fb90309060040161561b565b60206040518083038186803b15801561381357600080fd5b505afa158015613827573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061384b91906154b3565b6040518263ffffffff1660e01b815260040161386791906155f7565b600060405180830381600087803b15801561388157600080fd5b505af1158015613895573d6000803e3d6000fd5b505050506138a988826000015160016132e4565b505060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613919907f00000000000000000000000000000000000000000000000000000000000000009088906004016156ff565b602060405180830381600087803b15801561393357600080fd5b505af1158015613947573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061396b91906151c7565b50876001600160a01b03167fc355ebece16d7e85e486911f0cde1074bc4bd3fec251c88cdddc7076d3e99adb85476040516139a7929190615d6c565b60405180910390a247156139c8576139c86001600160a01b03891647612bc9565b50614106565b60018160ff1660038111156139df57fe5b60038111156139ea57fe5b1415613c5f57600082806020019051810190613a06919061529e565b90506000613ab68983600001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401613a5f919061561b565b60206040518083038186803b158015613a7757600080fd5b505afa158015613a8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aaf91906154b3565b6001612b7c565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b158015613b1357600080fd5b505af1158015613b27573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250613b9a91507f00000000000000000000000000000000000000000000000000000000000000009089906004016156ff565b602060405180830381600087803b158015613bb457600080fd5b505af1158015613bc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bec91906151c7565b506000613bf982876126bc565b9050896001600160a01b03167f6f3269a64126ef2a1959892f3d921e81865181e09a7f72f55d3a49550c53b48d8783604051613c36929190615d6c565b60405180910390a28015613c5757613c576001600160a01b038b1682612bc9565b505050614106565b60028160ff166003811115613c7057fe5b6003811115613c7b57fe5b1415613f3757600082806020019051810190613c9791906152b9565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a0823190613cee90309060040161561b565b60206040518083038186803b158015613d0657600080fd5b505afa158015613d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d3e91906154b3565b6040518263ffffffff1660e01b8152600401613d5a91906155f7565b600060405180830381600087803b158015613d7457600080fd5b505af1158015613d88573d6000803e3d6000fd5b5050505060208101518151613da1918a918160016145ea565b8051600090613db090866126bc565b90508160400151811015613dd65760405162461bcd60e51b81526004016103f790615bcb565b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613e44907f00000000000000000000000000000000000000000000000000000000000000009089906004016156ff565b602060405180830381600087803b158015613e5e57600080fd5b505af1158015613e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e9691906151c7565b5060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ee5908c9085906004016156ff565b602060405180830381600087803b158015613eff57600080fd5b505af1158015613f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c5791906151c7565b60038160ff166003811115613f4857fe5b6003811115613f5357fe5b141561410657600082806020019051810190613f6f91906152b9565b9050613f8688826000015183602001516001614684565b6020810151600090613f9890866126bc565b90508160600151811015613fbe5760405162461bcd60e51b81526004016103f790615ab8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b15801561401957600080fd5b505af115801561402d573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb92506140a091507f00000000000000000000000000000000000000000000000000000000000000009089906004016156ff565b602060405180830381600087803b1580156140ba57600080fd5b505af11580156140ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140f291906151c7565b506123a86001600160a01b038a1682612bc9565b50505050505050565b80820182811015610b05576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b60008161370d61417f85670de0b6b3a7640000614aca565b600285613707565b60008060008061419a856000015161371c565b919450925090506001600160a01b03808316908416106000806141be868686614ddc565b6001600160a01b031663128acb088b856141d78f614e1a565b6001600160a01b038e16156141ec578d614212565b8761420b5773fffd8963efd1fc6a506488495d951d5263988d25614212565b6401000276a45b8d6040516020016142239190615d13565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142529594939291906156c5565b6040805180830381600087803b15801561426b57600080fd5b505af115801561427f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142a39190615200565b91509150826142b257816142b4565b805b6000039b9a5050505050505050505050565b6000806000806142d9856000015161371c565b919450925090506001600160a01b03808416908316106000806142fd858786614ddc565b6001600160a01b031663128acb088b856143168f614e1a565b6000036001600160a01b038e161561432e578d614354565b8761434d5773fffd8963efd1fc6a506488495d951d5263988d25614354565b6401000276a45b8d6040516020016143659190615d13565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016143949594939291906156c5565b6040805180830381600087803b1580156143ad57600080fd5b505af11580156143c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143e59190615200565b91509150600080846143fb578284600003614401565b83836000035b915091508a6001600160a01b031660001415614423578c811461442357600080fd5b509b9a5050505050505050505050565b6000806000806000806144446124a3565b60095460405163cce79bd560e01b81529294509092506000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd59161450c917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff9091169060019060040161562f565b60206040518083038186803b15801561452457600080fd5b505afa158015614538573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061455c91906154b3565b90506000614568613482565b90506000614578858585856135bf565b50905060006145888b8584613630565b9050600080614599888885886135bf565b91509150811515841515146145c05760405162461bcd60e51b81526004016103f790615a13565b60006145cc82856136e3565b4260105560119790975550929c929b50939950975095505050505050565b8015614602576145fd85848460016148c0565b614638565b61460f85848460006148c0565b600061461b85846126bc565b90508015614636576146366001600160a01b03871682612bc9565b505b846001600160a01b03167f2af3664d72ebbec5e92c3a487f09a4ecd9ef50177eced03cc2b05892b5e0c91584848460405161467593929190615d7a565b60405180910390a25050505050565b614690848484846146e5565b806146a8576146a86001600160a01b03851683612bc9565b836001600160a01b03167fc7472bd0a757f40f801e047dd4f4ec901314e95afcbfed844e62af18401e0e6b848484604051611a8193929190615d7a565b8061478e576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd9061473a908790309088906004016156a1565b602060405180830381600087803b15801561475457600080fd5b505af1158015614768573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061478c91906151c7565b505b600554604051638632cb0360e01b81526101009091046001600160a01b031690638632cb03906147e6907f00000000000000000000000000000000000000000000000000000000000000009087908790600401615d92565b600060405180830381600087803b15801561480057600080fd5b505af115801561278b573d6000803e3d6000fd5b60008282111561486b576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600080614888614881858761410f565b8690614167565b905082156148b7576148af6148a5670de0b6b3a7640000836126bc565b61269885846136e3565b915050610f40565b50929392505050565b600554604051630728cf2360e31b81526101009091046001600160a01b031690633946791890849061491b907f0000000000000000000000000000000000000000000000000000000000000000908890600090600401615d92565b6020604051808303818588803b15801561493457600080fd5b505af1158015614948573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061496d91906154b3565b5080611b205760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906149c190879087906004016156ff565b602060405180830381600087803b1580156149db57600080fd5b505af11580156149ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a1391906151c7565b5050505050565b6124e88282614e30565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b158015614a9357600080fd5b505afa158015614aa7573d6000803e3d6000fd5b505050506040513d6020811015614abd57600080fd5b5051979650505050505050565b6000811580614ae557505080820282828281614ae257fe5b04145b610b05576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000808211614b8c576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161371457fe5b600080848611614bbd57614bb6614bac858561410f565b61269887896126bc565b6001614bce565b614bcb8461269888886126bc565b60005b9150915094509492505050565b600081826014011015614c35576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b8160140183511015614c8e576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015614d01576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b8160030183511015614d5a576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b614d6b61501c565b826001600160a01b0316846001600160a01b03161115614d89579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614dc58383614f20565b9050336001600160a01b03821614610b0557600080fd5b6000614e127f0000000000000000000000000000000000000000000000000000000000000000614e0d868686614d63565b614f20565b949350505050565b6000600160ff1b8210614e2c57600080fd5b5090565b6001600160a01b038216614e8b576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b614e9760008383612cae565b600254614ea49082612cb3565b6002556001600160a01b038216600090815260208190526040902054614eca9082612cb3565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600081602001516001600160a01b031682600001516001600160a01b031610614f4857600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b80356116e081615dc7565b600082601f830112615057578081fd5b813567ffffffffffffffff8082111561506c57fe5b604051601f8301601f19168101602001828111828210171561508a57fe5b6040528281528483016020018610156150a1578384fd5b82602086016020830137918201602001929092529392505050565b6000602082840312156150cd578081fd5b6040516020810181811067ffffffffffffffff821117156150ea57fe5b6040529151825250919050565b803560ff811681146116e057600080fd5b600060208284031215615119578081fd5b8135610f4081615dc7565b60008060408385031215615136578081fd5b823561514181615dc7565b9150602083013561515181615dc7565b809150509250929050565b600080600060608486031215615170578081fd5b833561517b81615dc7565b9250602084013561518b81615dc7565b929592945050506040919091013590565b600080604083850312156151ae578182fd5b82356151b981615dc7565b946020939093013593505050565b6000602082840312156151d8578081fd5b8151610f4081615ddf565b600080604083850312156151f5578182fd5b82356151b981615ddf565b60008060408385031215615212578182fd5b505080516020909101519092909150565b60008060008060608587031215615238578182fd5b8435935060208501359250604085013567ffffffffffffffff8082111561525d578384fd5b818701915087601f830112615270578384fd5b81358181111561527e578485fd5b88602082850101111561528f578485fd5b95989497505060200194505050565b6000602082840312156152af578081fd5b610f4083836150bc565b6000608082840312156152ca578081fd5b6040516080810181811067ffffffffffffffff821117156152e757fe5b8060405250825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b600060208284031215615329578081fd5b813567ffffffffffffffff80821115615340578283fd5b9083019060808286031215615353578283fd5b60405160808101818110838211171561536857fe5b604052823582811115615379578485fd5b61538587828601615047565b8252506153946020840161503c565b60208201526153a5604084016150f7565b60408201526060830135828111156153bb578485fd5b6153c787828601615047565b60608301525095945050505050565b6000608082840312156153e7578081fd5b6040516080810181811067ffffffffffffffff8211171561540457fe5b604052825161541281615dc7565b8152602083015161542281615ded565b602082015260408301516bffffffffffffffffffffffff81168114615445578283fd5b604082015260608301516fffffffffffffffffffffffffffffffff8116811461546c578283fd5b60608201529392505050565b600060208284031215615489578081fd5b815162ffffff81168114610f40578182fd5b6000602082840312156154ac578081fd5b5035919050565b6000602082840312156154c4578081fd5b5051919050565b6000806000606084860312156154df578081fd5b83359250602084013561518b81615ddf565b60008060408385031215615503578182fd5b50508035926020909101359150565b600080600060608486031215615526578081fd5b505081359360208301359350604090920135919050565b60006020828403121561554e578081fd5b8135610f4081615ded565b60008151808452815b8181101561557e57602081850181015186830182015201615562565b8181111561558f5782602083870101525b50601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b90815260200190565b93845260208401929092526040830152606082015260800190565b6001600160a01b0391909116815260200190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9283166060830152909116608082015260a00190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152612bbe60a0830184615559565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b901515815260200190565b9115158252602082015260400190565b92151583526020830191909152604082015260600190565b931515845260208401929092526040830152606082015260800190565b94151585526020850193909352604084019190915260608301521515608082015260a00190565b9415158552602085019390935260408401919091526060830152608082015260a00190565b600060208252610f406020830184615559565b60208082526019908201527f41756374696f6e207072696365203c206d696e20707269636500000000000000604082015260600190565b60208082526018908201527f616d6f756e74206f7574206c657373207468616e206d696e0000000000000000604082015260600190565b60208082526014908201527f696e76616c69642061756374696f6e2074696d65000000000000000000000000604082015260600190565b6020808252601d908201527f696e76616c6964206865646765207072696365207468726573686f6c64000000604082015260600190565b6020808252601c908201527f696e76616c69642068656467652074696d65207468726573686f6c6400000000604082015260600190565b60208082526017908201527f4c6f772045544820616d6f756e74207265636569766564000000000000000000604082015260600190565b60208082526012908201527f77726f6e672061756374696f6e20747970650000000000000000000000000000604082015260600190565b6020808252601d908201527f43726162206d7573742072656465656d53686f727453687574646f776e000000604082015260600190565b6020808252601a908201527f616d6f756e7420696e2067726561746572207468616e206d6178000000000000604082015260600190565b60208082526019908201527f50726963652068656467696e67206e6f7420616c6c6f77656400000000000000604082015260600190565b60208082526019908201527f61756374696f6e20646972656374696f6e206368616e67656400000000000000604082015260600190565b60208082526019908201527f41756374696f6e207072696365203e206d617820707269636500000000000000604082015260600190565b60208082526018908201527f4372616220636f6e747261637473207368757420646f776e0000000000000000604082015260600190565b6020808252601b908201527f70726f666974206973206c657373207468616e206d696e204554480000000000604082015260600190565b6020808252601b908201527f54696d652068656467696e67206973206e6f7420616c6c6f7765640000000000604082015260600190565b60208082526012908201527f43616e6e6f742072656365697665206574680000000000000000000000000000604082015260600190565b6020808252601c908201527f4465706f73697420657863656564732073747261746567792063617000000000604082015260600190565b6020808252601c908201527f45544820617474616368656420666f72206275792061756374696f6e00000000604082015260600190565b6020808252818101527f70726f666974206973206c657373207468616e206d696e207753717565657468604082015260600190565b6020808252601c908201527f6d6178207072696365206d756c7469706c69657220746f6f206c6f7700000000604082015260600190565b6020808252601f908201527f5371756565746820636f6e747261637473206e6f74207368757420646f776e00604082015260600190565b6020808252601d908201527f6d696e207072696365206d756c7469706c69657220746f6f2068696768000000604082015260600190565b60208082526018908201527f7477617020706572696f6420697320746f6f2073686f72740000000000000000604082015260600190565b60208082526019908201527f73747261746567792069732064656c7461206e65757472616c00000000000000604082015260600190565b600060208252825160806020840152615d2f60a0840182615559565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f198483030160808501526137638282615559565b918252602082015260400190565b92835260208301919091521515604082015260600190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b6001600160a01b0381168114615ddc57600080fd5b50565b8015158114615ddc57600080fd5b63ffffffff81168114615ddc57600080fdfe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657245524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220b6220299744f8371a8b07d2b42ceb0dcc3bf021647d610cbc929bed10b8e0d8164736f6c63430007060033\",\n  \"deployedBytecode\": \"0x6080604052600436106103905760003560e01c80637bcdc16e116101dc578063bdd438b811610102578063dfc19520116100a0578063f5d278e41161006f578063f5d278e4146109e2578063f73e19c3146109f7578063fa004fbf14610a17578063fa461e3314610a3757610402565b8063dfc195201461095c578063f101d92f1461097c578063f20e5e3514610991578063f2fde38b146109c257610402565b8063cae74029116100dc578063cae74029146108ff578063d0e30db014610914578063d4aec8171461091c578063dd62ed3e1461093c57610402565b8063bdd438b8146108a7578063c2451689146108c7578063c45a0155146108ea57610402565b8063955a15e81161017a578063a457c2d711610149578063a457c2d714610827578063a54c889914610847578063a9059cbb14610867578063b0b934611461088757610402565b8063955a15e8146107c857806395d89b41146107dd5780639c1ab1b8146107f2578063a319b29f1461081257610402565b806382564bca116101b657806382564bca146107695780638da5cb5b1461077e5780638ec4b721146107935780638f8b8dbc146107a857610402565b80637bcdc16e1461071f5780637dc0d1d01461073f5780637f07b1301461075457610402565b8063395ebb69116102c15780635e5cdcd71161025f5780636c1040a91161022e5780636c1040a9146106c257806370749b44146106d757806370a08231146106ea578063715018a61461070a57610402565b80635e5cdcd71461067057806363bbc4b61461068357806366a91b761461069857806367b8c345146106ad57610402565b80633fc8cef31161029b5780633fc8cef31461060c5780634468c022146106215780634d76e6fc14610636578063533092ef1461064b57610402565b8063395ebb69146105a85780633d3a62ee146105ca5780633dcb0c5d146105ea57610402565b806323ccafd91161032e5780632e1a7d4d116103085780632e1a7d4d14610531578063313ce5671461055157806333194c0a14610573578063395093511461058857610402565b806323ccafd9146104e957806325d7707c146105095780632a3400561461051c57610402565b8063155f586d1161036a578063155f586d1461047f57806318160ddd146104a15780631a5af342146104b657806323b872dd146104c957610402565b806306fdde0314610407578063095ea7b3146104325780630ca514cd1461045f57610402565b3661040257336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103db575060055461010090046001600160a01b031633145b6104005760405162461bcd60e51b81526004016103f790615b26565b60405180910390fd5b005b600080fd5b34801561041357600080fd5b5061041c610a57565b60405161042991906157da565b60405180910390f35b34801561043e57600080fd5b5061045261044d36600461519c565b610aed565b604051610429919061573e565b34801561046b57600080fd5b5061040061047a36600461549b565b610b0b565b34801561048b57600080fd5b50610494610bad565b60405161042991906155f7565b3480156104ad57600080fd5b50610494610bb3565b6104006104c436600461549b565b610bb9565b3480156104d557600080fd5b506104526104e436600461515c565b610ebf565b3480156104f557600080fd5b506104006105043660046154f1565b610f47565b6104006105173660046151e3565b6110fd565b34801561052857600080fd5b506104946111cd565b34801561053d57600080fd5b5061040061054c36600461549b565b6111d3565b34801561055d57600080fd5b50610566611295565b6040516104299190615db9565b34801561057f57600080fd5b5061049461129e565b34801561059457600080fd5b506104526105a336600461519c565b6112c2565b3480156105b457600080fd5b506105bd611310565b6040516104299190615da8565b3480156105d657600080fd5b506104006105e536600461549b565b611316565b3480156105f657600080fd5b506105ff6114ae565b604051610429919061561b565b34801561061857600080fd5b506105ff6114c2565b34801561062d57600080fd5b506105ff6114e6565b34801561064257600080fd5b506105ff61150a565b34801561065757600080fd5b5061066061152e565b6040516104299493929190615718565b61040061067e366004615512565b61154a565b34801561068f57600080fd5b506104946115c6565b3480156106a457600080fd5b506104946115cc565b3480156106b957600080fd5b506104946115d2565b3480156106ce57600080fd5b506104946115d8565b6104006106e53660046154cb565b6115fc565b3480156106f657600080fd5b50610494610705366004615108565b6116c6565b34801561071657600080fd5b506104006116e5565b34801561072b57600080fd5b5061040061073a36600461549b565b61179e565b34801561074b57600080fd5b506105ff611855565b34801561076057600080fd5b506105ff611879565b34801561077557600080fd5b506105ff61189d565b34801561078a57600080fd5b506105ff6118c1565b34801561079f57600080fd5b506104946118d0565b3480156107b457600080fd5b506104006107c336600461553d565b6118d6565b3480156107d457600080fd5b506104946119a4565b3480156107e957600080fd5b5061041c6119aa565b3480156107fe57600080fd5b5061040061080d3660046154f1565b611a0b565b34801561081e57600080fd5b50610400611a8f565b34801561083357600080fd5b5061045261084236600461519c565b611b26565b34801561085357600080fd5b5061040061086236600461549b565b611b8e565b34801561087357600080fd5b5061045261088236600461519c565b611c45565b34801561089357600080fd5b506104526108a236600461549b565b611c59565b3480156108b357600080fd5b506104006108c236600461549b565b611c64565b3480156108d357600080fd5b506108dc611d1b565b604051610429929190615749565b3480156108f657600080fd5b506105ff611d2e565b34801561090b57600080fd5b50610494611d52565b610400611d58565b34801561092857600080fd5b5061040061093736600461549b565b611e03565b34801561094857600080fd5b50610494610957366004615124565b611e9a565b34801561096857600080fd5b5061040061097736600461549b565b611ec5565b34801561098857600080fd5b50610494611f83565b34801561099d57600080fd5b506109b16109ac36600461549b565b611f89565b60405161042995949392919061578e565b3480156109ce57600080fd5b506104006109dd366004615108565b612128565b3480156109ee57600080fd5b506105bd612238565b348015610a0357600080fd5b50610494610a1236600461549b565b612244565b348015610a2357600080fd5b50610400610a3236600461549b565b61224f565b348015610a4357600080fd5b50610400610a52366004615223565b61230d565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ae35780601f10610ab857610100808354040283529160200191610ae3565b820191906000526020600020905b815481529060010190602001808311610ac657829003601f168201915b5050505050905090565b6000610b01610afa6123b3565b84846123b7565b5060015b92915050565b610b136123b3565b6001600160a01b0316610b246118c1565b6001600160a01b031614610b6d576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b60088190556040517f29600e2e028c8c5c2b112d021938e0d0237d8fafcbb20394c56cf9fa4661ca2790610ba29083906155f7565b60405180910390a150565b600d5481565b60025490565b60026006541415610c11576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600080610c216124a3565b91509150610c2f83826124bd565b6000610c3c8484846124ec565b50905082158015610c4b575081155b15610d695760095460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591610d10917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff169060019060040161562f565b60206040518083038186803b158015610d2857600080fd5b505afa158015610d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6091906154b3565b42601055601155505b610e717f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610e0757600080fd5b505afa158015610e1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3f9190615478565b84610e4a89346126bc565b60008a604051602001610e5d91906155f7565b604051602081830303815290604052612714565b336001600160a01b03167f5d85169ff8329e90f3225f9798e0eba54d00c55d3bbfe201a0d1606febb23a8e8583604051610eac929190615d6c565b60405180910390a2505060016006555050565b6000610ecc848484612795565b610f3c84610ed86123b3565b610f3785604051806060016040528060288152602001615eed602891396001600160a01b038a16600090815260016020526040812090610f166123b3565b6001600160a01b0316815260208101919091526040016000205491906128f0565b6123b7565b5060015b9392505050565b60026006541415610f9f576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610faf83612987565b90506110b07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b15801561104f57600080fd5b505afa158015611063573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110879190615478565b848660018960405160200161109c91906155f7565b6040516020818303038152906040526129ac565b336001600160a01b03167fa13b272c1cf13ba724064d3d4809d9f557aab8da2bb582cba031a2f57e728e9d84836040516110eb929190615d6c565b60405180910390a25050600160065550565b60026006541415611155576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600080611165612a23565b91509150816111865760405162461bcd60e51b81526004016103f790615aef565b611191818585612a4c565b336001600160a01b03167eb3acebad2d25b9626850dd370eadbf46d6a94dd0fab19c061f97e1dd4a9639858584604051610eac93929190615759565b600e5481565b6002600654141561122b576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600061123b82612987565b9050600061124c3384846000612b7c565b90506112583382612bc9565b336001600160a01b03167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca948484846040516110eb93929190615d92565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610b016112cf6123b3565b84610f3785600160006112e06123b3565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490612cb3565b6101a481565b6002600654141561136e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600681905550600560019054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156113c657600080fd5b505af11580156113da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113fe91906151c7565b61141a5760405162461bcd60e51b81526004016103f790615c37565b60125460ff1661143c5760405162461bcd60e51b81526004016103f79061596e565b600061144f8261144a610bb3565b612d0d565b9050600061145d8247612d19565b90506114693384612d25565b6114733382612bc9565b336001600160a01b03167fe9ab9870b9093d99f8e981919f65ad09b7ae90ff80f1031639af9e0357eb9ed684836040516110eb929190615d6c565b60055461010090046001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008061153c612e21565b935093509350935090919293565b61155383612f18565b61156f5760405162461bcd60e51b81526004016103f7906159dc565b61157a8383836130b2565b336001600160a01b03167ff99cce6ee3154fddfc55959dd136665c7351fe51c0ea58392ca454be8180dcd4428585856040516115b99493929190615600565b60405180910390a2505050565b60115481565b600b5481565b60105481565b7f000000000000000000000000000000000000000000000000000000000000000090565b60026006541415611654576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065561166283612f18565b61167e5760405162461bcd60e51b81526004016103f7906159dc565b611689838383612a4c565b336001600160a01b03167fa6806e5672ec1827d23bd4a25f4a41c8d0b055720c40081e3803f6b0a957f7978383866040516110eb93929190615759565b6001600160a01b0381166000908152602081905260409020545b919050565b6116ed6123b3565b6001600160a01b03166116fe6118c1565b6001600160a01b031614611747576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b6007546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36007805473ffffffffffffffffffffffffffffffffffffffff19169055565b6117a66123b3565b6001600160a01b03166117b76118c1565b6001600160a01b031614611800576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b600081116118205760405162461bcd60e51b81526004016103f7906158c9565b600b8190556040517f28e0e4ee0b14d4b056ce88e1bcd890ccd32b22e213723c8765901381b5eae70590610ba29083906155f7565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6007546001600160a01b031690565b600f5481565b6118de6123b3565b6001600160a01b03166118ef6118c1565b6001600160a01b031614611938576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b60b48163ffffffff16101561195f5760405162461bcd60e51b81526004016103f790615ca5565b6009805463ffffffff191663ffffffff83161790556040517f1cd9c7f99a5530a38c8f2b387dcc78e8a76cb5b203e0c4316a66777d993dee3590610ba2908390615da8565b600a5481565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ae35780601f10610ab857610100808354040283529160200191610ae3565b600080611a16612a23565b9150915081611a375760405162461bcd60e51b81526004016103f790615aef565b611a428185856130b2565b336001600160a01b03167f6c3a0d23de8295593e3e236062f9103f4a66c6d8de92b9425a2e17ae3baca67742838787604051611a819493929190615600565b60405180910390a250505050565b60128054600160ff19909116179055600554604051634bf7d4a160e11b81526101009091046001600160a01b0316906397efa94290611af2907f0000000000000000000000000000000000000000000000000000000000000000906004016155f7565b600060405180830381600087803b158015611b0c57600080fd5b505af1158015611b20573d6000803e3d6000fd5b50505050565b6000610b01611b336123b3565b84610f3785604051806060016040528060258152602001615f9f6025913960016000611b5d6123b3565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906128f0565b611b966123b3565b6001600160a01b0316611ba76118c1565b6001600160a01b031614611bf0576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b60008111611c105760405162461bcd60e51b81526004016103f79061585b565b600d8190556040517f6405fa008c5cc5710b13a509f31e7596708bdbc2a52c85a15f9992697a791b2090610ba29083906155f7565b6000610b01611c526123b3565b8484612795565b6000610b0582612f18565b611c6c6123b3565b6001600160a01b0316611c7d6118c1565b6001600160a01b031614611cc6576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b60008111611ce65760405162461bcd60e51b81526004016103f790615892565b600c8190556040517f789e4b8ad1c375952cea7f07c9b3b6619a84b406432b948246cecb8ced96b9fa90610ba29083906155f7565b600080611d26612a23565b915091509091565b7f000000000000000000000000000000000000000000000000000000000000000081565b60085481565b60026006541415611db0576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065534600080611dc43384836132e4565b91509150336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1583836040516110eb929190615d6c565b611e0b6123b3565b6001600160a01b0316611e1c6118c1565b6001600160a01b031614611e65576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b600a8190556040517f48100eb8aecbbf59b3665ff2a7b2d7257a218196dec79a67ca870fca43cdff6290610ba29083906155f7565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b611ecd6123b3565b6001600160a01b0316611ede6118c1565b6001600160a01b031614611f27576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b670de0b6b3a76400008111611f4e5760405162461bcd60e51b81526004016103f790615c00565b600f8190556040517fce6ae334d464afcb4f9f5f5218c4e3b0d5d227a821cb8a76bbff56da8f5f0b8890610ba29083906155f7565b600c5481565b6000806000806000806000611f9c6124a3565b60095460405163cce79bd560e01b81529294509092506000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591612064917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff9091169060019060040161562f565b60206040518083038186803b15801561207c57600080fd5b505afa158015612090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b491906154b3565b905060006120c0613482565b905060006120d0858585856135bf565b50905060006120e08c8584613630565b90506000806120f1888885886135bf565b90925090508315158215151415600061210a83866136e3565b959e50919c50939a5091985091965050505050505091939590929450565b6121306123b3565b6001600160a01b03166121416118c1565b6001600160a01b03161461218a576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b6001600160a01b0381166121cf5760405162461bcd60e51b8152600401808060200182810382526026815260200180615e456026913960400191505060405180910390fd5b6007546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60095463ffffffff1681565b6000610b0582612987565b6122576123b3565b6001600160a01b03166122686118c1565b6001600160a01b0316146122b1576040805162461bcd60e51b81526020600482018190526024820152600080516020615f15833981519152604482015290519081900360640190fd5b670de0b6b3a764000081106122d85760405162461bcd60e51b81526004016103f790615c6e565b600e8190556040517f07515fe9cd564f272668faa064c14bc4cec5f75710703ff96a21a47b680ce28f90610ba29083906155f7565b600084138061231c5750600083135b61232557600080fd5b600061233382840184615318565b90506000806000612347846000015161371c565b9250925092506123797f000000000000000000000000000000000000000000000000000000000000000084848461374d565b506000808913612389578761238b565b885b90506123a88560200151858585858a606001518b6040015161376c565b505050505050505050565b3390565b6001600160a01b0383166123fc5760405162461bcd60e51b8152600401808060200182810382526024815260200180615f7b6024913960400191505060405180910390fd5b6001600160a01b0382166124415760405162461bcd60e51b8152600401808060200182810382526022815260200180615e6b6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6000806000806124b1612e21565b96509450505050509091565b6008546124ca828461410f565b11156124e85760405162461bcd60e51b81526004016103f790615b5d565b5050565b6000806000806124fa613482565b905085158015612508575084155b1561267757612515610bb3565b156125325760405162461bcd60e51b81526004016103f790615a81565b60095460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd5916125f2917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff169060019060040161562f565b60206040518083038186803b15801561260a57600080fd5b505afa15801561261e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264291906154b3565b9050600061265882671bc16d674ec800006136e3565b905061266e612667828561410f565b8a90614167565b935050506126a1565b61269e61268e61268788846136e3565b879061410f565b61269889896136e3565b90614167565b91505b60006126ad83836136e3565b92989297509195505050505050565b80820382811115610b05576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b60006127698530600060405180608001604052808d8c8e60405160200161273d939291906155a4565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052614187565b90508381101561278b5760405162461bcd60e51b81526004016103f790615824565b5050505050505050565b6001600160a01b0383166127da5760405162461bcd60e51b8152600401808060200182810382526025815260200180615f566025913960400191505060405180910390fd5b6001600160a01b03821661281f5760405162461bcd60e51b8152600401808060200182810382526023815260200180615e006023913960400191505060405180910390fd5b61282a838383612cae565b61286781604051806060016040528060268152602001615e8d602691396001600160a01b03861660009081526020819052604090205491906128f0565b6001600160a01b0380851660009081526020819052604080822093909355908416815220546128969082612cb3565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000818484111561297f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561294457818101518382015260200161292c565b50505050905090810190601f1680156129715780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600080612992612e21565b9350505050610f406129a2610bb3565b61269883866136e3565b6000612a018530600060405180608001604052808c8c8f6040516020016129d5939291906155a4565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526142c6565b90508381111561278b5760405162461bcd60e51b81526004016103f7906159a5565b6000806000612a3f600b5460105461410f90919063ffffffff16565b4281111593509150509091565b600080600080612a5b87614433565b935093509350935083151586151514612a865760405162461bcd60e51b81526004016103f790615937565b8315612adf5784811115612aac5760405162461bcd60e51b81526004016103f790615a4a565b81341015612acc5760405162461bcd60e51b81526004016103f790615900565b612ada3334858560006145ea565b612b2a565b3415612afd5760405162461bcd60e51b81526004016103f790615b94565b84811015612b1d5760405162461bcd60e51b81526004016103f7906157ed565b612b2a3384846000614684565b336001600160a01b03167f878fd3ca52ad322c7535f559ee7c91afc67363073783360ef1b1420589dc61748787848787604051612b6b9594939291906157b5565b60405180910390a250505050505050565b600080612b876124a3565b9150506000612b988661144a610bb3565b90506000612ba68284612d19565b9050612bb4888783886146e5565b612bbe8888612d25565b979650505050505050565b80471015612c1e576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114612c69576040519150601f19603f3d011682016040523d82523d6000602084013e612c6e565b606091505b5050905080612cae5760405162461bcd60e51b815260040180806020018281038252603a815260200180615eb3603a913960400191505060405180910390fd5b505050565b600082820183811015610f40576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610f408383614167565b6000610f4082846136e3565b6001600160a01b038216612d6a5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f356021913960400191505060405180910390fd5b612d7682600083612cae565b612db381604051806060016040528060228152602001615e23602291396001600160a01b03851660009081526020819052604090205491906128f0565b6001600160a01b038316600090815260208190526040902055600254612dd99082614814565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600554604051634632752560e11b8152600091829182918291829161010090046001600160a01b031690638c64ea4a90612e7f907f0000000000000000000000000000000000000000000000000000000000000000906004016155f7565b60806040518083038186803b158015612e9757600080fd5b505afa158015612eab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ecf91906153d6565b805160208201516040830151606090930151919863ffffffff90911697506bffffffffffffffffffffffff90921695506fffffffffffffffffffffffffffffffff169350915050565b6000601054821015612f2c575060006116e0565b6000612f3842846126bc565b600954604051634ac78d1160e01b81529192506000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691634ac78d1191612ffe917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff9091168901908990600401615668565b60206040518083038186803b15801561301657600080fd5b505afa15801561302a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061304e91906154b3565b905060006130676011548361416790919063ffffffff16565b90506000670de0b6b3a764000082116130915761308c670de0b6b3a7640000836126bc565b6130a3565b6130a382670de0b6b3a76400006126bc565b600c5411159695505050505050565b6000806000806130c187614433565b935093509350935083156131c6576131c17f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b15801561316d57600080fd5b505afa158015613181573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131a59190615478565b858760025b89898e8e60405160200161109c9493929190615600565b6132a5565b6132a57f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b15801561326457600080fd5b505afa158015613278573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061329c9190615478565b868660036131aa565b336001600160a01b03167f4c1a959210172325f5c6678421c3834b04ae8ce57f7a7c0c0bbfbb62bca37e3485838686604051612b6b9493929190615771565b6000806000806132f26124a3565b9150915061330086826124bd565b60008061330e8885856124ec565b909250905060006133306133228a846126bc565b8561332b610bb3565b614871565b90508415801561333e575083155b1561345c5760095460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591613403917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff169060019060040161562f565b60206040518083038186803b15801561341b57600080fd5b505afa15801561342f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061345391906154b3565b42601055601155505b6134688a848b8b6148c0565b6134728a82614a1a565b9199919850909650505050505050565b6000806135167f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a46000614a24565b90506000600560019054906101000a90046001600160a01b03166001600160a01b031663978bbdb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561356857600080fd5b505afa15801561357c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135a091906154b3565b90506135b86127106135b28484614aca565b90614b36565b9250505090565b600080806135df856135d989671bc16d674ec800006136e3565b906136e3565b90506000806135f083898989614b95565b600a54919350915061360689612698858b6136e3565b116136235760405162461bcd60e51b81526004016103f790615cdc565b9890975095505050505050565b600d54600090819061364242876126bc565b101561365e57600d546136599061269842886126bc565b613668565b670de0b6b3a76400005b9050600083156136a65761369f61369661368f600e54600f546126bc90919063ffffffff16565b84906136e3565b600f54906126bc565b90506136cf565b6136cc6136c361368f600e54600f546126bc90919063ffffffff16565b600e549061410f565b90505b6136d985826136e3565b9695505050505050565b6000670de0b6b3a764000061370d6136fb8585614aca565b6002670de0b6b3a76400005b0461410f565b8161371457fe5b049392505050565b6000808061372a8482614bdb565b9250613737846014614ca7565b9050613744846017614bdb565b91509193909250565b60006137638561375e868686614d63565b614db9565b95945050505050565b60008160ff16600381111561377d57fe5b600381111561378857fe5b14156139ce576000828060200190518101906137a4919061529e565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906137fb90309060040161561b565b60206040518083038186803b15801561381357600080fd5b505afa158015613827573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061384b91906154b3565b6040518263ffffffff1660e01b815260040161386791906155f7565b600060405180830381600087803b15801561388157600080fd5b505af1158015613895573d6000803e3d6000fd5b505050506138a988826000015160016132e4565b505060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613919907f00000000000000000000000000000000000000000000000000000000000000009088906004016156ff565b602060405180830381600087803b15801561393357600080fd5b505af1158015613947573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061396b91906151c7565b50876001600160a01b03167fc355ebece16d7e85e486911f0cde1074bc4bd3fec251c88cdddc7076d3e99adb85476040516139a7929190615d6c565b60405180910390a247156139c8576139c86001600160a01b03891647612bc9565b50614106565b60018160ff1660038111156139df57fe5b60038111156139ea57fe5b1415613c5f57600082806020019051810190613a06919061529e565b90506000613ab68983600001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401613a5f919061561b565b60206040518083038186803b158015613a7757600080fd5b505afa158015613a8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aaf91906154b3565b6001612b7c565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b158015613b1357600080fd5b505af1158015613b27573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250613b9a91507f00000000000000000000000000000000000000000000000000000000000000009089906004016156ff565b602060405180830381600087803b158015613bb457600080fd5b505af1158015613bc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bec91906151c7565b506000613bf982876126bc565b9050896001600160a01b03167f6f3269a64126ef2a1959892f3d921e81865181e09a7f72f55d3a49550c53b48d8783604051613c36929190615d6c565b60405180910390a28015613c5757613c576001600160a01b038b1682612bc9565b505050614106565b60028160ff166003811115613c7057fe5b6003811115613c7b57fe5b1415613f3757600082806020019051810190613c9791906152b9565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a0823190613cee90309060040161561b565b60206040518083038186803b158015613d0657600080fd5b505afa158015613d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d3e91906154b3565b6040518263ffffffff1660e01b8152600401613d5a91906155f7565b600060405180830381600087803b158015613d7457600080fd5b505af1158015613d88573d6000803e3d6000fd5b5050505060208101518151613da1918a918160016145ea565b8051600090613db090866126bc565b90508160400151811015613dd65760405162461bcd60e51b81526004016103f790615bcb565b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613e44907f00000000000000000000000000000000000000000000000000000000000000009089906004016156ff565b602060405180830381600087803b158015613e5e57600080fd5b505af1158015613e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e9691906151c7565b5060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ee5908c9085906004016156ff565b602060405180830381600087803b158015613eff57600080fd5b505af1158015613f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c5791906151c7565b60038160ff166003811115613f4857fe5b6003811115613f5357fe5b141561410657600082806020019051810190613f6f91906152b9565b9050613f8688826000015183602001516001614684565b6020810151600090613f9890866126bc565b90508160600151811015613fbe5760405162461bcd60e51b81526004016103f790615ab8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b15801561401957600080fd5b505af115801561402d573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb92506140a091507f00000000000000000000000000000000000000000000000000000000000000009089906004016156ff565b602060405180830381600087803b1580156140ba57600080fd5b505af11580156140ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140f291906151c7565b506123a86001600160a01b038a1682612bc9565b50505050505050565b80820182811015610b05576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b60008161370d61417f85670de0b6b3a7640000614aca565b600285613707565b60008060008061419a856000015161371c565b919450925090506001600160a01b03808316908416106000806141be868686614ddc565b6001600160a01b031663128acb088b856141d78f614e1a565b6001600160a01b038e16156141ec578d614212565b8761420b5773fffd8963efd1fc6a506488495d951d5263988d25614212565b6401000276a45b8d6040516020016142239190615d13565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142529594939291906156c5565b6040805180830381600087803b15801561426b57600080fd5b505af115801561427f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142a39190615200565b91509150826142b257816142b4565b805b6000039b9a5050505050505050505050565b6000806000806142d9856000015161371c565b919450925090506001600160a01b03808416908316106000806142fd858786614ddc565b6001600160a01b031663128acb088b856143168f614e1a565b6000036001600160a01b038e161561432e578d614354565b8761434d5773fffd8963efd1fc6a506488495d951d5263988d25614354565b6401000276a45b8d6040516020016143659190615d13565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016143949594939291906156c5565b6040805180830381600087803b1580156143ad57600080fd5b505af11580156143c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143e59190615200565b91509150600080846143fb578284600003614401565b83836000035b915091508a6001600160a01b031660001415614423578c811461442357600080fd5b509b9a5050505050505050505050565b6000806000806000806144446124a3565b60095460405163cce79bd560e01b81529294509092506000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd59161450c917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff9091169060019060040161562f565b60206040518083038186803b15801561452457600080fd5b505afa158015614538573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061455c91906154b3565b90506000614568613482565b90506000614578858585856135bf565b50905060006145888b8584613630565b9050600080614599888885886135bf565b91509150811515841515146145c05760405162461bcd60e51b81526004016103f790615a13565b60006145cc82856136e3565b4260105560119790975550929c929b50939950975095505050505050565b8015614602576145fd85848460016148c0565b614638565b61460f85848460006148c0565b600061461b85846126bc565b90508015614636576146366001600160a01b03871682612bc9565b505b846001600160a01b03167f2af3664d72ebbec5e92c3a487f09a4ecd9ef50177eced03cc2b05892b5e0c91584848460405161467593929190615d7a565b60405180910390a25050505050565b614690848484846146e5565b806146a8576146a86001600160a01b03851683612bc9565b836001600160a01b03167fc7472bd0a757f40f801e047dd4f4ec901314e95afcbfed844e62af18401e0e6b848484604051611a8193929190615d7a565b8061478e576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd9061473a908790309088906004016156a1565b602060405180830381600087803b15801561475457600080fd5b505af1158015614768573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061478c91906151c7565b505b600554604051638632cb0360e01b81526101009091046001600160a01b031690638632cb03906147e6907f00000000000000000000000000000000000000000000000000000000000000009087908790600401615d92565b600060405180830381600087803b15801561480057600080fd5b505af115801561278b573d6000803e3d6000fd5b60008282111561486b576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600080614888614881858761410f565b8690614167565b905082156148b7576148af6148a5670de0b6b3a7640000836126bc565b61269885846136e3565b915050610f40565b50929392505050565b600554604051630728cf2360e31b81526101009091046001600160a01b031690633946791890849061491b907f0000000000000000000000000000000000000000000000000000000000000000908890600090600401615d92565b6020604051808303818588803b15801561493457600080fd5b505af1158015614948573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061496d91906154b3565b5080611b205760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906149c190879087906004016156ff565b602060405180830381600087803b1580156149db57600080fd5b505af11580156149ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a1391906151c7565b5050505050565b6124e88282614e30565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b158015614a9357600080fd5b505afa158015614aa7573d6000803e3d6000fd5b505050506040513d6020811015614abd57600080fd5b5051979650505050505050565b6000811580614ae557505080820282828281614ae257fe5b04145b610b05576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000808211614b8c576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161371457fe5b600080848611614bbd57614bb6614bac858561410f565b61269887896126bc565b6001614bce565b614bcb8461269888886126bc565b60005b9150915094509492505050565b600081826014011015614c35576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b8160140183511015614c8e576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015614d01576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b8160030183511015614d5a576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b614d6b61501c565b826001600160a01b0316846001600160a01b03161115614d89579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614dc58383614f20565b9050336001600160a01b03821614610b0557600080fd5b6000614e127f0000000000000000000000000000000000000000000000000000000000000000614e0d868686614d63565b614f20565b949350505050565b6000600160ff1b8210614e2c57600080fd5b5090565b6001600160a01b038216614e8b576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b614e9760008383612cae565b600254614ea49082612cb3565b6002556001600160a01b038216600090815260208190526040902054614eca9082612cb3565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600081602001516001600160a01b031682600001516001600160a01b031610614f4857600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b80356116e081615dc7565b600082601f830112615057578081fd5b813567ffffffffffffffff8082111561506c57fe5b604051601f8301601f19168101602001828111828210171561508a57fe5b6040528281528483016020018610156150a1578384fd5b82602086016020830137918201602001929092529392505050565b6000602082840312156150cd578081fd5b6040516020810181811067ffffffffffffffff821117156150ea57fe5b6040529151825250919050565b803560ff811681146116e057600080fd5b600060208284031215615119578081fd5b8135610f4081615dc7565b60008060408385031215615136578081fd5b823561514181615dc7565b9150602083013561515181615dc7565b809150509250929050565b600080600060608486031215615170578081fd5b833561517b81615dc7565b9250602084013561518b81615dc7565b929592945050506040919091013590565b600080604083850312156151ae578182fd5b82356151b981615dc7565b946020939093013593505050565b6000602082840312156151d8578081fd5b8151610f4081615ddf565b600080604083850312156151f5578182fd5b82356151b981615ddf565b60008060408385031215615212578182fd5b505080516020909101519092909150565b60008060008060608587031215615238578182fd5b8435935060208501359250604085013567ffffffffffffffff8082111561525d578384fd5b818701915087601f830112615270578384fd5b81358181111561527e578485fd5b88602082850101111561528f578485fd5b95989497505060200194505050565b6000602082840312156152af578081fd5b610f4083836150bc565b6000608082840312156152ca578081fd5b6040516080810181811067ffffffffffffffff821117156152e757fe5b8060405250825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b600060208284031215615329578081fd5b813567ffffffffffffffff80821115615340578283fd5b9083019060808286031215615353578283fd5b60405160808101818110838211171561536857fe5b604052823582811115615379578485fd5b61538587828601615047565b8252506153946020840161503c565b60208201526153a5604084016150f7565b60408201526060830135828111156153bb578485fd5b6153c787828601615047565b60608301525095945050505050565b6000608082840312156153e7578081fd5b6040516080810181811067ffffffffffffffff8211171561540457fe5b604052825161541281615dc7565b8152602083015161542281615ded565b602082015260408301516bffffffffffffffffffffffff81168114615445578283fd5b604082015260608301516fffffffffffffffffffffffffffffffff8116811461546c578283fd5b60608201529392505050565b600060208284031215615489578081fd5b815162ffffff81168114610f40578182fd5b6000602082840312156154ac578081fd5b5035919050565b6000602082840312156154c4578081fd5b5051919050565b6000806000606084860312156154df578081fd5b83359250602084013561518b81615ddf565b60008060408385031215615503578182fd5b50508035926020909101359150565b600080600060608486031215615526578081fd5b505081359360208301359350604090920135919050565b60006020828403121561554e578081fd5b8135610f4081615ded565b60008151808452815b8181101561557e57602081850181015186830182015201615562565b8181111561558f5782602083870101525b50601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b90815260200190565b93845260208401929092526040830152606082015260800190565b6001600160a01b0391909116815260200190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9283166060830152909116608082015260a00190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152612bbe60a0830184615559565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b901515815260200190565b9115158252602082015260400190565b92151583526020830191909152604082015260600190565b931515845260208401929092526040830152606082015260800190565b94151585526020850193909352604084019190915260608301521515608082015260a00190565b9415158552602085019390935260408401919091526060830152608082015260a00190565b600060208252610f406020830184615559565b60208082526019908201527f41756374696f6e207072696365203c206d696e20707269636500000000000000604082015260600190565b60208082526018908201527f616d6f756e74206f7574206c657373207468616e206d696e0000000000000000604082015260600190565b60208082526014908201527f696e76616c69642061756374696f6e2074696d65000000000000000000000000604082015260600190565b6020808252601d908201527f696e76616c6964206865646765207072696365207468726573686f6c64000000604082015260600190565b6020808252601c908201527f696e76616c69642068656467652074696d65207468726573686f6c6400000000604082015260600190565b60208082526017908201527f4c6f772045544820616d6f756e74207265636569766564000000000000000000604082015260600190565b60208082526012908201527f77726f6e672061756374696f6e20747970650000000000000000000000000000604082015260600190565b6020808252601d908201527f43726162206d7573742072656465656d53686f727453687574646f776e000000604082015260600190565b6020808252601a908201527f616d6f756e7420696e2067726561746572207468616e206d6178000000000000604082015260600190565b60208082526019908201527f50726963652068656467696e67206e6f7420616c6c6f77656400000000000000604082015260600190565b60208082526019908201527f61756374696f6e20646972656374696f6e206368616e67656400000000000000604082015260600190565b60208082526019908201527f41756374696f6e207072696365203e206d617820707269636500000000000000604082015260600190565b60208082526018908201527f4372616220636f6e747261637473207368757420646f776e0000000000000000604082015260600190565b6020808252601b908201527f70726f666974206973206c657373207468616e206d696e204554480000000000604082015260600190565b6020808252601b908201527f54696d652068656467696e67206973206e6f7420616c6c6f7765640000000000604082015260600190565b60208082526012908201527f43616e6e6f742072656365697665206574680000000000000000000000000000604082015260600190565b6020808252601c908201527f4465706f73697420657863656564732073747261746567792063617000000000604082015260600190565b6020808252601c908201527f45544820617474616368656420666f72206275792061756374696f6e00000000604082015260600190565b6020808252818101527f70726f666974206973206c657373207468616e206d696e207753717565657468604082015260600190565b6020808252601c908201527f6d6178207072696365206d756c7469706c69657220746f6f206c6f7700000000604082015260600190565b6020808252601f908201527f5371756565746820636f6e747261637473206e6f74207368757420646f776e00604082015260600190565b6020808252601d908201527f6d696e207072696365206d756c7469706c69657220746f6f2068696768000000604082015260600190565b60208082526018908201527f7477617020706572696f6420697320746f6f2073686f72740000000000000000604082015260600190565b60208082526019908201527f73747261746567792069732064656c7461206e65757472616c00000000000000604082015260600190565b600060208252825160806020840152615d2f60a0840182615559565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f198483030160808501526137638282615559565b918252602082015260400190565b92835260208301919091521515604082015260600190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b6001600160a01b0381168114615ddc57600080fd5b50565b8015158114615ddc57600080fd5b63ffffffff81168114615ddc57600080fdfe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657245524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220b6220299744f8371a8b07d2b42ceb0dcc3bf021647d610cbc929bed10b8e0d8164736f6c63430007060033\",\n  \"devdoc\": {\n    \"author\": \"Opyn team\",\n    \"details\": \"CrabStrategy contract\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"allowance(address,address)\": {\n        \"details\": \"See {IERC20-allowance}.\"\n      },\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC20-balanceOf}.\"\n      },\n      \"checkPriceHedge(uint256)\": {\n        \"params\": {\n          \"_auctionTriggerTime\": \"the time when the price deviation threshold was exceeded and when the auction started\"\n        },\n        \"returns\": {\n          \"_0\": \"true if hedging is allowed\"\n        }\n      },\n      \"checkTimeHedge()\": {\n        \"returns\": {\n          \"_0\": \"isTimeHedgeAllowed true if hedging is allowed\",\n          \"_1\": \"auctionTriggertime auction trigger timestamp\"\n        }\n      },\n      \"constructor\": {\n        \"details\": \"this will open a vault in the power token contract and store the vault ID\",\n        \"params\": {\n          \"_auctionTime\": \"auction duration (seconds)\",\n          \"_ethWSqueethPool\": \"eth:wSqueeth uniswap pool address\",\n          \"_hedgePriceThreshold\": \"hedge price threshold (0.1*1e18 = 10%)\",\n          \"_hedgeTimeThreshold\": \"hedge time threshold (seconds)\",\n          \"_maxPriceMultiplier\": \"maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\",\n          \"_minPriceMultiplier\": \"minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\",\n          \"_oracle\": \"oracle address\",\n          \"_uniswapFactory\": \"uniswap factory address\",\n          \"_wSqueethController\": \"power token controller address\",\n          \"_weth\": \"weth address\"\n        }\n      },\n      \"decimals()\": {\n        \"details\": \"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"\n      },\n      \"decreaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"\n      },\n      \"deposit()\": {\n        \"details\": \"provide ETH, return wSqueeth and strategy token\"\n      },\n      \"flashDeposit(uint256)\": {\n        \"details\": \"this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth_ethToDeposit must be less than msg.value plus the proceeds from the flash swapthe difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\",\n        \"params\": {\n          \"_ethToDeposit\": \"total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\"\n        }\n      },\n      \"flashWithdraw(uint256,uint256)\": {\n        \"details\": \"this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\",\n        \"params\": {\n          \"_crabAmount\": \"strategy token amount to burn\",\n          \"_maxEthToPay\": \"maximum ETH to pay to buy back the owed wSqueeth debt\"\n        }\n      },\n      \"getAuctionDetails(uint256)\": {\n        \"params\": {\n          \"_auctionTriggerTime\": \"timestamp where auction started\"\n        },\n        \"returns\": {\n          \"_0\": \"if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\"\n        }\n      },\n      \"getStrategyVaultId()\": {\n        \"returns\": {\n          \"_0\": \"vault ID\"\n        }\n      },\n      \"getVaultDetails()\": {\n        \"returns\": {\n          \"_0\": \"operator\",\n          \"_1\": \"nft collateral id\",\n          \"_2\": \"collateral amount\",\n          \"_3\": \"short amount\"\n        }\n      },\n      \"getWsqueethFromCrabAmount(uint256)\": {\n        \"params\": {\n          \"_crabAmount\": \"strategy token amount\"\n        },\n        \"returns\": {\n          \"_0\": \"wSqueeth amount\"\n        }\n      },\n      \"increaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"name()\": {\n        \"details\": \"Returns the name of the token.\"\n      },\n      \"owner()\": {\n        \"details\": \"Returns the address of the current owner.\"\n      },\n      \"priceHedge(uint256,bool,uint256)\": {\n        \"details\": \"need to attach msg.value if buying WSqueeth\",\n        \"params\": {\n          \"_auctionTriggerTime\": \"the time when the price deviation threshold was exceeded and when the auction started\",\n          \"_isStrategySellingWSqueeth\": \"specify the direction of the trade that you expect, this choice impacts the limit price chosen\",\n          \"_limitPrice\": \"the min or max price that you will trade at, depending on if buying or selling\"\n        }\n      },\n      \"priceHedgeOnUniswap(uint256,uint256,uint256)\": {\n        \"details\": \"this function atomically hedges on uniswap and provides a bounty to the caller based on the differencebetween uniswap execution price and the price of the hedging auction\",\n        \"params\": {\n          \"_auctionTriggerTime\": \"the time when the price deviation threshold was exceeded and when the auction started\",\n          \"_minEth\": \"minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\",\n          \"_minWSqueeth\": \"minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\"\n        }\n      },\n      \"redeemShortShutdown()\": {\n        \"details\": \"needs to be called 1 time before users can exit the strategy using withdrawShutdown\"\n      },\n      \"renounceOwnership()\": {\n        \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n      },\n      \"setAuctionTime(uint256)\": {\n        \"params\": {\n          \"_auctionTime\": \"the length of the hedge auction in seconds\"\n        }\n      },\n      \"setDeltaHedgeThreshold(uint256)\": {\n        \"details\": \"the strategy will not allow a hedge if the trade size is below this threshold\",\n        \"params\": {\n          \"_deltaHedgeThreshold\": \"minimum hedge size in a percent of ETH collateral\"\n        }\n      },\n      \"setHedgePriceThreshold(uint256)\": {\n        \"params\": {\n          \"_hedgePriceThreshold\": \"the hedge price threshold, in percent, scaled by 1e18\"\n        }\n      },\n      \"setHedgeTimeThreshold(uint256)\": {\n        \"params\": {\n          \"_hedgeTimeThreshold\": \"the hedge time threshold, in seconds\"\n        }\n      },\n      \"setHedgingTwapPeriod(uint32)\": {\n        \"params\": {\n          \"_hedgingTwapPeriod\": \"the twap period, in seconds\"\n        }\n      },\n      \"setMaxPriceMultiplier(uint256)\": {\n        \"details\": \"the max price multiplier is multiplied by the TWAP price to get the final auction price\",\n        \"params\": {\n          \"_maxPriceMultiplier\": \"the max price multiplier, a percentage, scaled by 1e18\"\n        }\n      },\n      \"setMinPriceMultiplier(uint256)\": {\n        \"details\": \"the min price multiplier is multiplied by the TWAP price to get the intial auction price\",\n        \"params\": {\n          \"_minPriceMultiplier\": \"the min price multiplier, a percentage, scaled by 1e18\"\n        }\n      },\n      \"setStrategyCap(uint256)\": {\n        \"details\": \"deposits are rejected if it would put the strategy above the cap amountstrategy collateral can be above the cap amount due to hedging activities\",\n        \"params\": {\n          \"_capAmount\": \"the maximum strategy collateral in ETH, checked on deposits\"\n        }\n      },\n      \"symbol()\": {\n        \"details\": \"Returns the symbol of the token, usually a shorter version of the name.\"\n      },\n      \"timeHedge(bool,uint256)\": {\n        \"details\": \"need to attach msg.value if buying WSqueeth\",\n        \"params\": {\n          \"_isStrategySellingWSqueeth\": \"sell or buy auction, true for sell auction\",\n          \"_limitPrice\": \"hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\"\n        }\n      },\n      \"timeHedgeOnUniswap(uint256,uint256)\": {\n        \"details\": \"this function atomically hedges on uniswap and provides a bounty to the caller based on the differencebetween uniswap execution price and the price of the hedging auction\",\n        \"params\": {\n          \"_minEth\": \"minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\",\n          \"_minWSqueeth\": \"minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\"\n        }\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC20-totalSupply}.\"\n      },\n      \"transfer(address,uint256)\": {\n        \"details\": \"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"\n      },\n      \"transferOwnership(address)\": {\n        \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"params\": {\n          \"_data\": \"callback data encoded as SwapCallbackData struct\",\n          \"amount0Delta\": \"amount of token0\",\n          \"amount1Delta\": \"amount of token1\"\n        }\n      },\n      \"withdraw(uint256)\": {\n        \"details\": \"provide strategy tokens and wSqueeth, returns eth\",\n        \"params\": {\n          \"_crabAmount\": \"amount of strategy token to burn\"\n        }\n      },\n      \"withdrawShutdown(uint256)\": {\n        \"params\": {\n          \"_crabAmount\": \"amount of strategy token to burn\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"POWER_PERP_PERIOD\": {\n        \"details\": \"the TWAP_PERIOD used in the PowerPerp Controller contract\"\n      },\n      \"auctionTime\": {\n        \"details\": \"hedge auction duration (seconds)\"\n      },\n      \"deltaHedgeThreshold\": {\n        \"details\": \"strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\"\n      },\n      \"ethWSqueethPool\": {\n        \"details\": \"ETH:WSqueeth uniswap pool\"\n      },\n      \"hasRedeemedInShutdown\": {\n        \"details\": \"set to true when redeemShortShutdown has been called\"\n      },\n      \"hedgePriceThreshold\": {\n        \"details\": \"price movement to trigger a hedge (0.1*1e18 = 10%)\"\n      },\n      \"hedgeTimeThreshold\": {\n        \"details\": \"time difference to trigger a hedge (seconds)\"\n      },\n      \"hedgingTwapPeriod\": {\n        \"details\": \"twap period to use for hedge calculations\"\n      },\n      \"maxPriceMultiplier\": {\n        \"details\": \"start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\"\n      },\n      \"minPriceMultiplier\": {\n        \"details\": \"start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\"\n      },\n      \"oracle\": {\n        \"details\": \"strategy uniswap oracle\"\n      },\n      \"priceAtLastHedge\": {\n        \"details\": \"WSqueeth/Eth price when last hedge executed\"\n      },\n      \"strategyCap\": {\n        \"details\": \"the cap in ETH for the strategy, above which deposits will be rejected\"\n      },\n      \"timeAtLastHedge\": {\n        \"details\": \"timestamp when last hedge executed\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"checkPriceHedge(uint256)\": {\n        \"notice\": \"check if hedging based on price threshold is allowed\"\n      },\n      \"checkTimeHedge()\": {\n        \"notice\": \"check if hedging based on time threshold is allowed\"\n      },\n      \"constructor\": {\n        \"notice\": \"strategy constructor\"\n      },\n      \"deposit()\": {\n        \"notice\": \"deposit ETH into strategy\"\n      },\n      \"flashDeposit(uint256)\": {\n        \"notice\": \"flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\"\n      },\n      \"flashWithdraw(uint256,uint256)\": {\n        \"notice\": \"flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\"\n      },\n      \"getAuctionDetails(uint256)\": {\n        \"notice\": \"get current auction details\"\n      },\n      \"getStrategyVaultId()\": {\n        \"notice\": \"get power token strategy vault ID \"\n      },\n      \"getVaultDetails()\": {\n        \"notice\": \"get the vault composition of the strategy \"\n      },\n      \"getWsqueethFromCrabAmount(uint256)\": {\n        \"notice\": \"get wSqueeth debt amount associated with strategy token amount\"\n      },\n      \"priceHedge(uint256,bool,uint256)\": {\n        \"notice\": \"strategy hedging based on price threshold\"\n      },\n      \"priceHedgeOnUniswap(uint256,uint256,uint256)\": {\n        \"notice\": \"hedge startegy based on price threshold with uniswap arbing\"\n      },\n      \"redeemShortShutdown()\": {\n        \"notice\": \"called to redeem the net value of a vault post shutdown\"\n      },\n      \"setAuctionTime(uint256)\": {\n        \"notice\": \"owner can set the auction time, in seconds, that a hedge auction runs for\"\n      },\n      \"setDeltaHedgeThreshold(uint256)\": {\n        \"notice\": \"owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\"\n      },\n      \"setHedgePriceThreshold(uint256)\": {\n        \"notice\": \"owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\"\n      },\n      \"setHedgeTimeThreshold(uint256)\": {\n        \"notice\": \"owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\"\n      },\n      \"setHedgingTwapPeriod(uint32)\": {\n        \"notice\": \"owner can set the twap period in seconds that is used for calculating twaps for hedging\"\n      },\n      \"setMaxPriceMultiplier(uint256)\": {\n        \"notice\": \"owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\"\n      },\n      \"setMinPriceMultiplier(uint256)\": {\n        \"notice\": \"owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\"\n      },\n      \"setStrategyCap(uint256)\": {\n        \"notice\": \"owner can set the strategy cap in ETH collateral terms\"\n      },\n      \"timeHedge(bool,uint256)\": {\n        \"notice\": \"strategy hedging based on time threshold\"\n      },\n      \"timeHedgeOnUniswap(uint256,uint256)\": {\n        \"notice\": \"hedge startegy based on time threshold with uniswap arbing\"\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"notice\": \"uniswap swap callback function for flashes\"\n      },\n      \"withdraw(uint256)\": {\n        \"notice\": \"withdraw WETH from strategy\"\n      },\n      \"withdrawShutdown(uint256)\": {\n        \"notice\": \"called to exit a vault if the Squeeth Power Perp contracts are shutdown\"\n      }\n    },\n    \"notice\": \"Contract for Crab strategy\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 881,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_balances\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 887,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_allowances\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n      },\n      {\n        \"astId\": 889,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_totalSupply\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 891,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 893,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 895,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_decimals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint8\"\n      },\n      {\n        \"astId\": 27353,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"powerTokenController\",\n        \"offset\": 1,\n        \"slot\": \"5\",\n        \"type\": \"t_contract(IController)11604\"\n      },\n      {\n        \"astId\": 4176,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_owner\",\n        \"offset\": 0,\n        \"slot\": \"7\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 22823,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"strategyCap\",\n        \"offset\": 0,\n        \"slot\": \"8\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 22831,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"hedgingTwapPeriod\",\n        \"offset\": 0,\n        \"slot\": \"9\",\n        \"type\": \"t_uint32\"\n      },\n      {\n        \"astId\": 22850,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"deltaHedgeThreshold\",\n        \"offset\": 0,\n        \"slot\": \"10\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 22853,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"hedgeTimeThreshold\",\n        \"offset\": 0,\n        \"slot\": \"11\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 22856,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"hedgePriceThreshold\",\n        \"offset\": 0,\n        \"slot\": \"12\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 22859,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"auctionTime\",\n        \"offset\": 0,\n        \"slot\": \"13\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 22862,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"minPriceMultiplier\",\n        \"offset\": 0,\n        \"slot\": \"14\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 22865,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"maxPriceMultiplier\",\n        \"offset\": 0,\n        \"slot\": \"15\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 22868,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"timeAtLastHedge\",\n        \"offset\": 0,\n        \"slot\": \"16\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 22871,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"priceAtLastHedge\",\n        \"offset\": 0,\n        \"slot\": \"17\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 22874,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"hasRedeemedInShutdown\",\n        \"offset\": 0,\n        \"slot\": \"18\",\n        \"type\": \"t_bool\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_contract(IController)11604\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"contract IController\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => uint256))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_uint256)\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint32\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint32\",\n        \"numberOfBytes\": \"4\"\n      },\n      \"t_uint8\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint8\",\n        \"numberOfBytes\": \"1\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/CrabStrategyV2.json",
    "content": "{\n  \"address\": \"0x3fF39f6BF8156bdA997D93E3EFF6904c2bc4481f\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wSqueethController\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_oracle\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_weth\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniswapFactory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_ethWSqueethPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_timelock\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_crabMigration\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"lpAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Deposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"depositedAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tradedAmountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDeposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDepositCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdrawCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"bidId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"quantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"clearingPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"HedgeOTC\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"trader\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"bidId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"quantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"price\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"clearingPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"HedgeOTCSingle\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newHedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetHedgePriceThreshold\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newHedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetHedgeTimeThreshold\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint32\",\n          \"name\": \"newHedgingTwapPeriod\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"SetHedgingTwapPeriod\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"otcPriceTolerance\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetOTCPriceTolerance\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newCapAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetStrategyCap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newStrategy\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"VaultTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Withdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawShutdown\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"DOMAIN_SEPARATOR\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"MAX_OTC_PRICE_TOLERANCE\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"POWER_PERP_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"checkPriceHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"checkTimeHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"crabMigration\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"subtractedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"decreaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"deposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"ethWSqueethPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToDeposit\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashDeposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxEthToPay\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashWithdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getStrategyVaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getVaultDetails\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getWsqueethFromCrabAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_totalQuantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_clearingPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_isHedgeBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"bidId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"trader\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"quantity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"price\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"isBuying\",\n              \"type\": \"bool\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"expiry\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"nonce\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint8\",\n              \"name\": \"v\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"bytes32\",\n              \"name\": \"r\",\n              \"type\": \"bytes32\"\n            },\n            {\n              \"internalType\": \"bytes32\",\n              \"name\": \"s\",\n              \"type\": \"bytes32\"\n            }\n          ],\n          \"internalType\": \"struct CrabStrategyV2.Order[]\",\n          \"name\": \"_orders\",\n          \"type\": \"tuple[]\"\n        }\n      ],\n      \"name\": \"hedgeOTC\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgePriceThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgeTimeThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgingTwapPeriod\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"addedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"increaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wSqueethToMint\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabSharesToMint\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_timeAtLastHedge\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_priceAtLastHedge\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_strategyCap\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"initialize\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isInitialized\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"nonces\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"oracle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"otcPriceTolerance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"powerTokenController\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IController\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"priceAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"redeemShortShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setHedgePriceThreshold\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setHedgeTimeThreshold\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_hedgingTwapPeriod\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"setHedgingTwapPeriod\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_nonce\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setNonceTrue\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_otcPriceTolerance\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setOTCPriceTolerance\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_capAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setStrategyCap\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"strategyCap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"timeAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"timelock\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_newStrategy\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"vaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdrawShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0xccb7d2f57a6ad3351d48ed2ce235bb99322b9718de46acb7d910a2b08a411050\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x3fF39f6BF8156bdA997D93E3EFF6904c2bc4481f\",\n    \"transactionIndex\": 27,\n    \"gasUsed\": \"5447694\",\n    \"logsBloom\": \"0x0400400000000800000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000020000000150000000000000000100000000000000c000000000001000000000000000000000000000000000000020240000000000000000801000004000000000020000010000800400001000000000001000000010000000000000000000000000000000200000000000000000200000000000100000000024000000000000000000000000000000000000002000000000000000000000000000000000000000000204000000020000000000000000000000800000000000000000000008000000000000000000000\",\n    \"blockHash\": \"0x7220d75e66108f18d257ba4789fd17eac57e696c83df46c3f30724dad64a47b5\",\n    \"transactionHash\": \"0xccb7d2f57a6ad3351d48ed2ce235bb99322b9718de46acb7d910a2b08a411050\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 27,\n        \"blockNumber\": 8014067,\n        \"transactionHash\": \"0xccb7d2f57a6ad3351d48ed2ce235bb99322b9718de46acb7d910a2b08a411050\",\n        \"address\": \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n        \"topics\": [\n          \"0x339e53729b0447795ff69e70a74fed98fc7fef6fe94b7521099b32f0f8de4822\"\n        ],\n        \"data\": \"0x0000000000000000000000000000000000000000000000000de0b6ad4cf7c7b60000000000000000000000000000000000000000000000000de0b1d643c4705300000000000000000000000000000000000000000000000000000000637ebcd000000000000000000000000000000000000000000000000000000000637ffcb0\",\n        \"logIndex\": 151,\n        \"blockHash\": \"0x7220d75e66108f18d257ba4789fd17eac57e696c83df46c3f30724dad64a47b5\"\n      },\n      {\n        \"transactionIndex\": 27,\n        \"blockNumber\": 8014067,\n        \"transactionHash\": \"0xccb7d2f57a6ad3351d48ed2ce235bb99322b9718de46acb7d910a2b08a411050\",\n        \"address\": \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n        \"topics\": [\n          \"0x3137fc9cd2e33c34f86e29c24d81f3c75b0bce639d3c4ed0d31eeff1160a7ff5\"\n        ],\n        \"data\": \"0x000000000000000000000000e85595e810b77cf606d0afd7eb575bb025323bee00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000\",\n        \"logIndex\": 152,\n        \"blockHash\": \"0x7220d75e66108f18d257ba4789fd17eac57e696c83df46c3f30724dad64a47b5\"\n      },\n      {\n        \"transactionIndex\": 27,\n        \"blockNumber\": 8014067,\n        \"transactionHash\": \"0xccb7d2f57a6ad3351d48ed2ce235bb99322b9718de46acb7d910a2b08a411050\",\n        \"address\": \"0xe85595e810B77cf606D0aFd7eB575BB025323beE\",\n        \"topics\": [\n          \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000003ff39f6bf8156bda997d93e3eff6904c2bc4481f\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000002\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 153,\n        \"blockHash\": \"0x7220d75e66108f18d257ba4789fd17eac57e696c83df46c3f30724dad64a47b5\"\n      },\n      {\n        \"transactionIndex\": 27,\n        \"blockNumber\": 8014067,\n        \"transactionHash\": \"0xccb7d2f57a6ad3351d48ed2ce235bb99322b9718de46acb7d910a2b08a411050\",\n        \"address\": \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n        \"topics\": [\n          \"0x25ff1e0131762176a9084e92880f880f39d6d0e62134607f37e631efe1bad871\"\n        ],\n        \"data\": \"0x0000000000000000000000003ff39f6bf8156bda997d93e3eff6904c2bc4481f0000000000000000000000000000000000000000000000000000000000000002\",\n        \"logIndex\": 154,\n        \"blockHash\": \"0x7220d75e66108f18d257ba4789fd17eac57e696c83df46c3f30724dad64a47b5\"\n      },\n      {\n        \"transactionIndex\": 27,\n        \"blockNumber\": 8014067,\n        \"transactionHash\": \"0xccb7d2f57a6ad3351d48ed2ce235bb99322b9718de46acb7d910a2b08a411050\",\n        \"address\": \"0x3fF39f6BF8156bdA997D93E3EFF6904c2bc4481f\",\n        \"topics\": [\n          \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000006326a0dfe0517ff46af3ad16bc40c26c26397f9e\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 155,\n        \"blockHash\": \"0x7220d75e66108f18d257ba4789fd17eac57e696c83df46c3f30724dad64a47b5\"\n      }\n    ],\n    \"blockNumber\": 8014067,\n    \"cumulativeGasUsed\": \"12947389\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n    \"0xf7F94b4607Bcd1235212803bE8fD1B54D1D01b77\",\n    \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\n    \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n    \"0xC3c29372B5138d48993F0699A129b9EADf5191Bf\",\n    \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    3600,\n    \"200000000000000000\"\n  ],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wSqueethController\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_oracle\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_weth\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniswapFactory\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_ethWSqueethPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_timelock\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_crabMigration\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"lpAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Deposit\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"depositedAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tradedAmountOut\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDeposit\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"flashswapDebt\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excess\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDepositCallback\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"flashswapDebt\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excess\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdrawCallback\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bidId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"quantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"clearingPrice\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"HedgeOTC\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"trader\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bidId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"quantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"price\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"clearingPrice\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"HedgeOTCSingle\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newHedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetHedgePriceThreshold\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newHedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetHedgeTimeThreshold\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"newHedgingTwapPeriod\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"SetHedgingTwapPeriod\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"otcPriceTolerance\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetOTCPriceTolerance\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newCapAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetStrategyCap\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newStrategy\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"VaultTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethWithdrawn\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Withdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethWithdrawn\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawShutdown\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"DOMAIN_SEPARATOR\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"MAX_OTC_PRICE_TOLERANCE\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"POWER_PERP_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"checkPriceHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"checkTimeHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"crabMigration\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"subtractedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"decreaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"deposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"ethWSqueethPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"factory\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashDeposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxEthToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashWithdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getStrategyVaultId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getVaultDetails\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"getWsqueethFromCrabAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_totalQuantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_clearingPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_isHedgeBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bidId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"trader\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"quantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"price\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"expiry\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"nonce\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"v\\\",\\\"type\\\":\\\"uint8\\\"},{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"r\\\",\\\"type\\\":\\\"bytes32\\\"},{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"s\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"internalType\\\":\\\"struct CrabStrategyV2.Order[]\\\",\\\"name\\\":\\\"_orders\\\",\\\"type\\\":\\\"tuple[]\\\"}],\\\"name\\\":\\\"hedgeOTC\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgePriceThreshold\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgeTimeThreshold\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgingTwapPeriod\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"addedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"increaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wSqueethToMint\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabSharesToMint\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_timeAtLastHedge\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_priceAtLastHedge\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_strategyCap\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"initialize\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isInitialized\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"nonces\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"oracle\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"otcPriceTolerance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"powerTokenController\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IController\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"priceAtLastHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"redeemShortShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setHedgePriceThreshold\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setHedgeTimeThreshold\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_hedgingTwapPeriod\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"setHedgingTwapPeriod\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_nonce\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setNonceTrue\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_otcPriceTolerance\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setOTCPriceTolerance\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_capAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setStrategyCap\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"strategyCap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"timeAtLastHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"timelock\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_newStrategy\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferVault\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount0Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount1Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"uniswapV3SwapCallback\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"vaultId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdrawShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"author\\\":\\\"Opyn team\\\",\\\"details\\\":\\\"CrabStrategyV2 contract\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"DOMAIN_SEPARATOR()\\\":{\\\"details\\\":\\\"view function to get the domain seperator used in signing\\\"},\\\"allowance(address,address)\\\":{\\\"details\\\":\\\"See {IERC20-allowance}.\\\"},\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC20-balanceOf}.\\\"},\\\"checkPriceHedge()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"true if hedging is allowed\\\"}},\\\"checkTimeHedge()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"true if hedging is allowed\\\"}},\\\"constructor\\\":{\\\"details\\\":\\\"this will open a vault in the power token contract and store the vault ID\\\",\\\"params\\\":{\\\"_crabMigration\\\":\\\"crab migration contract address\\\",\\\"_ethWSqueethPool\\\":\\\"eth:wSqueeth uniswap pool address\\\",\\\"_hedgePriceThreshold\\\":\\\"hedge price threshold (0.1*1e18 = 10%)\\\",\\\"_hedgeTimeThreshold\\\":\\\"hedge time threshold (seconds)\\\",\\\"_oracle\\\":\\\"oracle address\\\",\\\"_timelock\\\":\\\"timelock contract address\\\",\\\"_uniswapFactory\\\":\\\"uniswap factory address\\\",\\\"_wSqueethController\\\":\\\"power token controller address\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"decimals()\\\":{\\\"details\\\":\\\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\\\"},\\\"decreaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\\\"},\\\"deposit()\\\":{\\\"details\\\":\\\"provide ETH, return wSqueeth and strategy token\\\"},\\\"flashDeposit(uint256,uint24)\\\":{\\\"details\\\":\\\"this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth_ethToDeposit must be less than msg.value plus the proceeds from the flash swapthe difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\",\\\"params\\\":{\\\"_ethToDeposit\\\":\\\"total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\",\\\"_poolFee\\\":\\\"Uniswap pool fee\\\"}},\\\"flashWithdraw(uint256,uint256,uint24)\\\":{\\\"details\\\":\\\"this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\",\\\"params\\\":{\\\"_crabAmount\\\":\\\"strategy token amount to burn\\\",\\\"_maxEthToPay\\\":\\\"maximum ETH to pay to buy back the wSqueeth debt\\\",\\\"_poolFee\\\":\\\"Uniswap pool fee\\\"}},\\\"getStrategyVaultId()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"vault ID\\\"}},\\\"getVaultDetails()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"operator\\\",\\\"_1\\\":\\\"nft collateral id\\\",\\\"_2\\\":\\\"collateral amount\\\",\\\"_3\\\":\\\"short amount\\\"}},\\\"getWsqueethFromCrabAmount(uint256)\\\":{\\\"params\\\":{\\\"_crabAmount\\\":\\\"strategy token amount\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"wSqueeth amount\\\"}},\\\"hedgeOTC(uint256,uint256,bool,(uint256,address,uint256,uint256,bool,uint256,uint256,uint8,bytes32,bytes32)[])\\\":{\\\"details\\\":\\\"hedge function to reduce delta using an array of signed orders\\\",\\\"params\\\":{\\\"_clearingPrice\\\":\\\"clearing price in weth\\\",\\\"_isHedgeBuying\\\":\\\"direction of hedge trade\\\",\\\"_orders\\\":\\\"an array of signed order to swap tokens\\\",\\\"_totalQuantity\\\":\\\"quantity the manager wants to trade\\\"}},\\\"increaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\\\"},\\\"initialize(uint256,uint256,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_crabSharesToMint\\\":\\\"crab shares to mint\\\",\\\"_priceAtLastHedge\\\":\\\"price at last hedge for crab V1\\\",\\\"_strategyCap\\\":\\\"strategy cap for crab V2\\\",\\\"_timeAtLastHedge\\\":\\\"time at last hedge for crab V1\\\",\\\"_wSqueethToMint\\\":\\\"amount of wPowerPerp to mint\\\"}},\\\"name()\\\":{\\\"details\\\":\\\"Returns the name of the token.\\\"},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"redeemShortShutdown()\\\":{\\\"details\\\":\\\"needs to be called before users can exit strategy using withdrawShutdown\\\"},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"setHedgePriceThreshold(uint256)\\\":{\\\"params\\\":{\\\"_hedgePriceThreshold\\\":\\\"the hedge price threshold, in percent, scaled by 1e18\\\"}},\\\"setHedgeTimeThreshold(uint256)\\\":{\\\"params\\\":{\\\"_hedgeTimeThreshold\\\":\\\"the hedge time threshold, in seconds\\\"}},\\\"setHedgingTwapPeriod(uint32)\\\":{\\\"params\\\":{\\\"_hedgingTwapPeriod\\\":\\\"the twap period, in seconds\\\"}},\\\"setNonceTrue(uint256)\\\":{\\\"params\\\":{\\\"_nonce\\\":\\\"the number to be set true\\\"}},\\\"setOTCPriceTolerance(uint256)\\\":{\\\"params\\\":{\\\"_otcPriceTolerance\\\":\\\"the OTC price tolerance, in percent, scaled by 1e18\\\"}},\\\"setStrategyCap(uint256)\\\":{\\\"details\\\":\\\"deposits are rejected if it would put the strategy above the cap amountstrategy collateral can be above the cap amount due to hedging activities\\\",\\\"params\\\":{\\\"_capAmount\\\":\\\"the maximum strategy collateral in ETH, checked on deposits\\\"}},\\\"symbol()\\\":{\\\"details\\\":\\\"Returns the symbol of the token, usually a shorter version of the name.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC20-totalSupply}.\\\"},\\\"transfer(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\\\"},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"transferVault(address)\\\":{\\\"details\\\":\\\"strategy cap is set to 0 to avoid future deposits\\\",\\\"params\\\":{\\\"_newStrategy\\\":\\\"new strategy contract address\\\"}},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"params\\\":{\\\"_data\\\":\\\"callback data encoded as SwapCallbackData struct\\\",\\\"amount0Delta\\\":\\\"amount of token0\\\",\\\"amount1Delta\\\":\\\"amount of token1\\\"}},\\\"withdraw(uint256)\\\":{\\\"details\\\":\\\"provide strategy tokens and wSqueeth, returns ETH\\\",\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of strategy token to burn\\\"}},\\\"withdrawShutdown(uint256)\\\":{\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of strategy token to burn\\\"}}},\\\"stateVariables\\\":{\\\"ONE\\\":{\\\"details\\\":\\\"basic unit used for calculation\\\"},\\\"POWER_PERP_PERIOD\\\":{\\\"details\\\":\\\"the TWAP_PERIOD used in the PowerPerp Controller contract\\\"},\\\"_CRAB_BALANCE_TYPEHASH\\\":{\\\"details\\\":\\\"typehash for signed orders\\\"},\\\"ethWSqueethPool\\\":{\\\"details\\\":\\\"ETH:wSqueeth uniswap pool\\\"},\\\"hasRedeemedInShutdown\\\":{\\\"details\\\":\\\"set to true when redeemShortShutdown has been called\\\"},\\\"hedgePriceThreshold\\\":{\\\"details\\\":\\\"price movement to trigger a hedge (0.1*1e18 = 10%)\\\"},\\\"hedgeTimeThreshold\\\":{\\\"details\\\":\\\"time difference to trigger a hedge (seconds)\\\"},\\\"hedgingTwapPeriod\\\":{\\\"details\\\":\\\"twap period to use for hedge calculations\\\"},\\\"isInitialized\\\":{\\\"details\\\":\\\"true if CrabV2 was initialized\\\"},\\\"nonces\\\":{\\\"details\\\":\\\"store the used flag for a nonce for each address\\\"},\\\"oracle\\\":{\\\"details\\\":\\\"strategy uniswap oracle\\\"},\\\"priceAtLastHedge\\\":{\\\"details\\\":\\\"wSqueeth/Eth price when last hedge executed\\\"},\\\"strategyCap\\\":{\\\"details\\\":\\\"the cap in ETH for the strategy, above which deposits will be rejected\\\"},\\\"timeAtLastHedge\\\":{\\\"details\\\":\\\"timestamp when last hedge executed\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"checkPriceHedge()\\\":{\\\"notice\\\":\\\"check if hedging based on price threshold is allowed\\\"},\\\"checkTimeHedge()\\\":{\\\"notice\\\":\\\"check if hedging based on time threshold is allowed\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"strategy constructor\\\"},\\\"deposit()\\\":{\\\"notice\\\":\\\"deposit ETH into strategy\\\"},\\\"flashDeposit(uint256,uint24)\\\":{\\\"notice\\\":\\\"flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\"},\\\"flashWithdraw(uint256,uint256,uint24)\\\":{\\\"notice\\\":\\\"flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\"},\\\"getStrategyVaultId()\\\":{\\\"notice\\\":\\\"get power token strategy vault ID \\\"},\\\"getVaultDetails()\\\":{\\\"notice\\\":\\\"get the vault composition of the strategy \\\"},\\\"getWsqueethFromCrabAmount(uint256)\\\":{\\\"notice\\\":\\\"get wSqueeth debt amount associated with strategy token amount\\\"},\\\"initialize(uint256,uint256,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"initializes the collateral ratio after the first migration\\\"},\\\"redeemShortShutdown()\\\":{\\\"notice\\\":\\\"called to redeem the net value of a vault post shutdown\\\"},\\\"setHedgePriceThreshold(uint256)\\\":{\\\"notice\\\":\\\"owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\"},\\\"setHedgeTimeThreshold(uint256)\\\":{\\\"notice\\\":\\\"owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\"},\\\"setHedgingTwapPeriod(uint32)\\\":{\\\"notice\\\":\\\"owner can set the twap period in seconds that is used for calculating twaps for hedging\\\"},\\\"setNonceTrue(uint256)\\\":{\\\"notice\\\":\\\"set nonce to true\\\"},\\\"setOTCPriceTolerance(uint256)\\\":{\\\"notice\\\":\\\"owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\\"},\\\"setStrategyCap(uint256)\\\":{\\\"notice\\\":\\\"owner can set the strategy cap in ETH collateral terms\\\"},\\\"transferVault(address)\\\":{\\\"notice\\\":\\\"transfer vault NFT to new contract\\\"},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"notice\\\":\\\"uniswap swap callback function for flashes\\\"},\\\"withdraw(uint256)\\\":{\\\"notice\\\":\\\"withdraw WETH from strategy\\\"},\\\"withdrawShutdown(uint256)\\\":{\\\"notice\\\":\\\"called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\"}},\\\"notice\\\":\\\"Contract for Crab strategy\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/strategy/CrabStrategyV2.sol\\\":\\\"CrabStrategyV2\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\\\n *\\\\n * These functions can be used to verify that a message was signed by the holder\\\\n * of the private keys of a given address.\\\\n */\\\\nlibrary ECDSA {\\\\n    /**\\\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\\\n     * `signature`. This address can then be used for verification purposes.\\\\n     *\\\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\\\n     * this function rejects them by requiring the `s` value to be in the lower\\\\n     * half order, and the `v` value to be either 27 or 28.\\\\n     *\\\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\\\n     * verification to be secure: it is possible to craft signatures that\\\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\\\n     * this is by receiving a hash of the original message (which may otherwise\\\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\\\n     */\\\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\\\n        // Check the signature length\\\\n        if (signature.length != 65) {\\\\n            revert(\\\\\\\"ECDSA: invalid signature length\\\\\\\");\\\\n        }\\\\n\\\\n        // Divide the signature in r, s and v variables\\\\n        bytes32 r;\\\\n        bytes32 s;\\\\n        uint8 v;\\\\n\\\\n        // ecrecover takes the signature parameters, and the only way to get them\\\\n        // currently is to use assembly.\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly {\\\\n            r := mload(add(signature, 0x20))\\\\n            s := mload(add(signature, 0x40))\\\\n            v := byte(0, mload(add(signature, 0x60)))\\\\n        }\\\\n\\\\n        return recover(hash, v, r, s);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\\\n     * `r` and `s` signature fields separately.\\\\n     */\\\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\\\n        // the valid range for s in (281): 0 < s < secp256k1n \\\\u00f7 2 + 1, and for v in (282): v \\\\u2208 {27, 28}. Most\\\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\\\n        //\\\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\\\n        // these malleable signatures as well.\\\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\\\\\"ECDSA: invalid signature 's' value\\\\\\\");\\\\n        require(v == 27 || v == 28, \\\\\\\"ECDSA: invalid signature 'v' value\\\\\\\");\\\\n\\\\n        // If the signature is valid (and not malleable), return the signer address\\\\n        address signer = ecrecover(hash, v, r, s);\\\\n        require(signer != address(0), \\\\\\\"ECDSA: invalid signature\\\\\\\");\\\\n\\\\n        return signer;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\\\n     * replicates the behavior of the\\\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\\\n     * JSON-RPC method.\\\\n     *\\\\n     * See {recover}.\\\\n     */\\\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\\\n        // 32 is the length in bytes of hash,\\\\n        // enforced by the type signature above\\\\n        return keccak256(abi.encodePacked(\\\\\\\"\\\\\\\\x19Ethereum Signed Message:\\\\\\\\n32\\\\\\\", hash));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc80ce3fcc5e444a2c5bdb902fe4d4f4ecba04e9b416425697d00ae95c1955f82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/drafts/EIP712.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <0.8.0;\\\\n\\\\n/**\\\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\\\n *\\\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\\\n *\\\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\\\n * ({_hashTypedDataV4}).\\\\n *\\\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\\\n *\\\\n * NOTE: This contract implements the version of the encoding known as \\\\\\\"v4\\\\\\\", as implemented by the JSON RPC method\\\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\\\n *\\\\n * _Available since v3.4._\\\\n */\\\\nabstract contract EIP712 {\\\\n    /* solhint-disable var-name-mixedcase */\\\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\\\n    // invalidate the cached domain separator if the chain id changes.\\\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\\\n    uint256 private immutable _CACHED_CHAIN_ID;\\\\n\\\\n    bytes32 private immutable _HASHED_NAME;\\\\n    bytes32 private immutable _HASHED_VERSION;\\\\n    bytes32 private immutable _TYPE_HASH;\\\\n    /* solhint-enable var-name-mixedcase */\\\\n\\\\n    /**\\\\n     * @dev Initializes the domain separator and parameter caches.\\\\n     *\\\\n     * The meaning of `name` and `version` is specified in\\\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\\\n     *\\\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\\\n     * - `version`: the current major version of the signing domain.\\\\n     *\\\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\\\n     * contract upgrade].\\\\n     */\\\\n    constructor(string memory name, string memory version) {\\\\n        bytes32 hashedName = keccak256(bytes(name));\\\\n        bytes32 hashedVersion = keccak256(bytes(version));\\\\n        bytes32 typeHash = keccak256(\\\\\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\\\\\");\\\\n        _HASHED_NAME = hashedName;\\\\n        _HASHED_VERSION = hashedVersion;\\\\n        _CACHED_CHAIN_ID = _getChainId();\\\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\\\n        _TYPE_HASH = typeHash;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the domain separator for the current chain.\\\\n     */\\\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\\\n            return _CACHED_DOMAIN_SEPARATOR;\\\\n        } else {\\\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\\\n        }\\\\n    }\\\\n\\\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\\\n        return keccak256(\\\\n            abi.encode(\\\\n                typeHash,\\\\n                name,\\\\n                version,\\\\n                _getChainId(),\\\\n                address(this)\\\\n            )\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\\\n     *\\\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\\\n     *\\\\n     * ```solidity\\\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\\\n     *     keccak256(\\\\\\\"Mail(address to,string contents)\\\\\\\"),\\\\n     *     mailTo,\\\\n     *     keccak256(bytes(mailContents))\\\\n     * )));\\\\n     * address signer = ECDSA.recover(digest, signature);\\\\n     * ```\\\\n     */\\\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\\\n        return keccak256(abi.encodePacked(\\\\\\\"\\\\\\\\x19\\\\\\\\x01\\\\\\\", _domainSeparatorV4(), structHash));\\\\n    }\\\\n\\\\n    function _getChainId() private view returns (uint256 chainId) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly {\\\\n            chainId := chainid()\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4bc5cda2bfee483ff10334881c9ea5cc4df7faa7b18a5a4b8f02fc51cf8adca\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Safe casting methods\\\\n/// @notice Contains methods for safely casting between types\\\\nlibrary SafeCast {\\\\n    /// @notice Cast a uint256 to a uint160, revert on overflow\\\\n    /// @param y The uint256 to be downcasted\\\\n    /// @return z The downcasted integer, now type uint160\\\\n    function toUint160(uint256 y) internal pure returns (uint160 z) {\\\\n        require((z = uint160(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a int256 to a int128, revert on overflow or underflow\\\\n    /// @param y The int256 to be downcasted\\\\n    /// @return z The downcasted integer, now type int128\\\\n    function toInt128(int256 y) internal pure returns (int128 z) {\\\\n        require((z = int128(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a uint256 to a int256, revert on overflow\\\\n    /// @param y The uint256 to be casted\\\\n    /// @return z The casted integer, now type int256\\\\n    function toInt256(uint256 y) internal pure returns (int256 z) {\\\\n        require(y < 2**255);\\\\n        z = int256(y);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n/*\\\\n * @title Solidity Bytes Arrays Utils\\\\n * @author Gon\\\\u00e7alo S\\\\u00e1 <goncalo.sa@consensys.net>\\\\n *\\\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\\\n */\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nlibrary BytesLib {\\\\n    function slice(\\\\n        bytes memory _bytes,\\\\n        uint256 _start,\\\\n        uint256 _length\\\\n    ) internal pure returns (bytes memory) {\\\\n        require(_length + 31 >= _length, 'slice_overflow');\\\\n        require(_start + _length >= _start, 'slice_overflow');\\\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\\\n\\\\n        bytes memory tempBytes;\\\\n\\\\n        assembly {\\\\n            switch iszero(_length)\\\\n                case 0 {\\\\n                    // Get a location of some free memory and store it in tempBytes as\\\\n                    // Solidity does for memory variables.\\\\n                    tempBytes := mload(0x40)\\\\n\\\\n                    // The first word of the slice result is potentially a partial\\\\n                    // word read from the original array. To read it, we calculate\\\\n                    // the length of that partial word and start copying that many\\\\n                    // bytes into the array. The first word we copy will start with\\\\n                    // data we don't care about, but the last `lengthmod` bytes will\\\\n                    // land at the beginning of the contents of the new array. When\\\\n                    // we're done copying, we overwrite the full first word with\\\\n                    // the actual length of the slice.\\\\n                    let lengthmod := and(_length, 31)\\\\n\\\\n                    // The multiplication in the next line is necessary\\\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\\\n                    // the following copy loop was copying the origin's length\\\\n                    // and then ending prematurely not copying everything it should.\\\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\\\n                    let end := add(mc, _length)\\\\n\\\\n                    for {\\\\n                        // The multiplication in the next line has the same exact purpose\\\\n                        // as the one above.\\\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\\\n                    } lt(mc, end) {\\\\n                        mc := add(mc, 0x20)\\\\n                        cc := add(cc, 0x20)\\\\n                    } {\\\\n                        mstore(mc, mload(cc))\\\\n                    }\\\\n\\\\n                    mstore(tempBytes, _length)\\\\n\\\\n                    //update free-memory pointer\\\\n                    //allocating the array padded to 32 bytes like the compiler does now\\\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\\\n                }\\\\n                //if we want a zero-length slice let's just return a zero-length array\\\\n                default {\\\\n                    tempBytes := mload(0x40)\\\\n                    //zero out the 32 bytes slice we are about to return\\\\n                    //we need to do it because Solidity does not garbage collect\\\\n                    mstore(tempBytes, 0)\\\\n\\\\n                    mstore(0x40, add(tempBytes, 0x20))\\\\n                }\\\\n        }\\\\n\\\\n        return tempBytes;\\\\n    }\\\\n\\\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\\\n        address tempAddress;\\\\n\\\\n        assembly {\\\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\\\n        }\\\\n\\\\n        return tempAddress;\\\\n    }\\\\n\\\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\\\n        uint24 tempUint;\\\\n\\\\n        assembly {\\\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\\\n        }\\\\n\\\\n        return tempUint;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport './PoolAddress.sol';\\\\n\\\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\\\nlibrary CallbackValidation {\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param tokenA The contract address of either token0 or token1\\\\n    /// @param tokenB The contract address of the other token\\\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(\\\\n        address factory,\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool pool) {\\\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param poolKey The identifying key of the V3 pool\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\\\n        internal\\\\n        view\\\\n        returns (IUniswapV3Pool pool)\\\\n    {\\\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\\\n        require(msg.sender == address(pool));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.6.0;\\\\n\\\\nimport './BytesLib.sol';\\\\n\\\\n/// @title Functions for manipulating path data for multihop swaps\\\\nlibrary Path {\\\\n    using BytesLib for bytes;\\\\n\\\\n    /// @dev The length of the bytes encoded address\\\\n    uint256 private constant ADDR_SIZE = 20;\\\\n    /// @dev The length of the bytes encoded fee\\\\n    uint256 private constant FEE_SIZE = 3;\\\\n\\\\n    /// @dev The offset of a single token address and pool fee\\\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\\\n    /// @dev The offset of an encoded pool key\\\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\\\n\\\\n    /// @notice Returns true iff the path contains two or more pools\\\\n    /// @param path The encoded swap path\\\\n    /// @return True if path contains two or more pools, otherwise false\\\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\\\n    }\\\\n\\\\n    /// @notice Returns the number of pools in the path\\\\n    /// @param path The encoded swap path\\\\n    /// @return The number of pools in the path\\\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Decodes the first pool in path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return tokenA The first token of the given pool\\\\n    /// @return tokenB The second token of the given pool\\\\n    /// @return fee The fee level of the pool\\\\n    function decodeFirstPool(bytes memory path)\\\\n        internal\\\\n        pure\\\\n        returns (\\\\n            address tokenA,\\\\n            address tokenB,\\\\n            uint24 fee\\\\n        )\\\\n    {\\\\n        tokenA = path.toAddress(0);\\\\n        fee = path.toUint24(ADDR_SIZE);\\\\n        tokenB = path.toAddress(NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Gets the segment corresponding to the first pool in the path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return The segment containing all data necessary to target the first pool in the path\\\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(0, POP_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\\\n    /// @param path The swap path\\\\n    /// @return The remaining token + fee elements in the path\\\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/Power2Base.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary Power2Base {\\\\n    using SafeMath for uint256;\\\\n\\\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\\\n    uint256 private constant INDEX_SCALE = 1e4;\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    /**\\\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getUnscaledIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\\\n     */\\\\n    function _getDenormalizedMark(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _wSqueeth,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\\\n\\\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _weth weth address\\\\n     * @return returns value of debt in ETH\\\\n     */\\\\n    function _getDebtValueInEth(\\\\n        uint256 _debtAmount,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _wSqueeth,\\\\n        address _weth\\\\n    ) internal view returns (uint256) {\\\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle\\\\n     * @dev this will revert if period is > max period for the pool\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        // period reaching this point should be check, otherwise might revert\\\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\\\n     * @param _indexPriceForSettlement index price for settlement\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return amount in wei that should be paid to the token holder\\\\n     */\\\\n    function _getLongSettlementValue(\\\\n        uint256 _wsqueethAmount,\\\\n        uint256 _indexPriceForSettlement,\\\\n        uint256 _normalizationFactor\\\\n    ) internal pure returns (uint256) {\\\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1938180c41ec0ee817b841df605b199e15ffbbe94700b640d031b4e4665a89af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/CrabStrategyV2.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {StrategyBase} from \\\\\\\"./base/StrategyBase.sol\\\\\\\";\\\\nimport {StrategyFlashSwap} from \\\\\\\"./base/StrategyFlashSwap.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\nimport {EIP712} from \\\\\\\"@openzeppelin/contracts/drafts/EIP712.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./base/StrategyMath.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\nimport {ECDSA} from \\\\\\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Crab V2 Error Codes:\\\\n * C1: Caller is not timelock\\\\n * C2: Contract not yet initialized\\\\n * C3: Invalid oracle address\\\\n * C4: Invalid timelock address\\\\n * C5: Invalid ETH:WSqueeth address\\\\n * C6: Invalid crabMigration address\\\\n * C7: Invalid hedge time threshold\\\\n * C8: Invalid hedge price threshold\\\\n * C9: Cannot receive ETH\\\\n * C10: Caller not Crab Migration contract\\\\n * C11: Crab V2 already initialized\\\\n * C12: Squeeth contracts not shut down\\\\n * C13: Crab must redeemShortShutdown\\\\n * C14: Twap period is too short\\\\n * C15: Price tolerance is too high\\\\n * C16: Deposit exceeds strategy cap\\\\n * C17: Clearing Price should be below bid price\\\\n * C18: Clearing Price should be above offer price\\\\n * C19: Invalid offer signature\\\\n * C20: Order has expired\\\\n * C21: Manager Price should be greater than 0\\\\n * C22: Not a valid Time or Price hedge\\\\n * C23: Orders must take the opposite side of the hedge\\\\n * C24: All orders must be either buying or selling\\\\n * C25: Orders are not arranged properly\\\\n * C26: Crab contracts shut down\\\\n *  C27: Nonce already used.\\\\n */\\\\n\\\\n/**\\\\n * @dev CrabStrategyV2 contract\\\\n * @notice Contract for Crab strategy\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\\\n    uint256 public strategyCap;\\\\n\\\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\\\n\\\\n    /// @dev basic unit used for calculation\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    // @dev OTC price must be within this distance of the uniswap twap price\\\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\\\n\\\\n    // @dev OTC price tolerance cannot exceed 20%\\\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\\\n\\\\n    /// @dev twap period to use for hedge calculations\\\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\\\n    /// @dev true if CrabV2 was initialized\\\\n    bool public isInitialized;\\\\n\\\\n    /// @dev typehash for signed orders\\\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\\\n        keccak256(\\\\n            \\\\\\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\\\\\"\\\\n        );\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum FLASH_SOURCE {\\\\n        FLASH_DEPOSIT,\\\\n        FLASH_WITHDRAW\\\\n    }\\\\n\\\\n    /// @dev ETH:wSqueeth uniswap pool\\\\n    address public immutable ethWSqueethPool;\\\\n    /// @dev strategy uniswap oracle\\\\n    address public immutable oracle;\\\\n    address public immutable timelock;\\\\n    address public immutable crabMigration;\\\\n\\\\n    /// @dev time difference to trigger a hedge (seconds)\\\\n    uint256 public hedgeTimeThreshold;\\\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\\\n    uint256 public hedgePriceThreshold;\\\\n\\\\n    /// @dev timestamp when last hedge executed\\\\n    uint256 public timeAtLastHedge;\\\\n    /// @dev wSqueeth/Eth price when last hedge executed\\\\n    uint256 public priceAtLastHedge;\\\\n\\\\n    /// @dev set to true when redeemShortShutdown has been called\\\\n    bool private hasRedeemedInShutdown;\\\\n\\\\n    /// @dev store the used flag for a nonce for each address\\\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\\\n\\\\n    struct FlashDepositData {\\\\n        uint256 totalDeposit;\\\\n    }\\\\n\\\\n    struct FlashWithdrawData {\\\\n        uint256 crabAmount;\\\\n    }\\\\n\\\\n    struct Order {\\\\n        uint256 bidId;\\\\n        address trader;\\\\n        uint256 quantity;\\\\n        uint256 price;\\\\n        bool isBuying;\\\\n        uint256 expiry;\\\\n        uint256 nonce;\\\\n        uint8 v;\\\\n        bytes32 r;\\\\n        bytes32 s;\\\\n    }\\\\n\\\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\\\n    event HedgeOTCSingle(\\\\n        address trader,\\\\n        uint256 bidId,\\\\n        uint256 quantity,\\\\n        uint256 price,\\\\n        bool isBuying,\\\\n        uint256 clearingPrice\\\\n    );\\\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\\\n    event SetStrategyCap(uint256 newCapAmount);\\\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\\\n\\\\n    modifier onlyTimelock() {\\\\n        require(msg.sender == timelock, \\\\\\\"C1\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier afterInitialization() {\\\\n        require(isInitialized, \\\\\\\"C2\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy constructor\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _wSqueethController power token controller address\\\\n     * @param _oracle oracle address\\\\n     * @param _weth weth address\\\\n     * @param _uniswapFactory uniswap factory address\\\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\\\n     * @param _timelock timelock contract address\\\\n     * @param _crabMigration crab migration contract address\\\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\\\n     */\\\\n    constructor(\\\\n        address _wSqueethController,\\\\n        address _oracle,\\\\n        address _weth,\\\\n        address _uniswapFactory,\\\\n        address _ethWSqueethPool,\\\\n        address _timelock,\\\\n        address _crabMigration,\\\\n        uint256 _hedgeTimeThreshold,\\\\n        uint256 _hedgePriceThreshold\\\\n    )\\\\n        StrategyBase(_wSqueethController, _weth, \\\\\\\"Crab Strategy v2\\\\\\\", \\\\\\\"Crabv2\\\\\\\")\\\\n        StrategyFlashSwap(_uniswapFactory)\\\\n        EIP712(\\\\\\\"CrabOTC\\\\\\\", \\\\\\\"2\\\\\\\")\\\\n    {\\\\n        require(_oracle != address(0), \\\\\\\"C3\\\\\\\");\\\\n        require(_timelock != address(0), \\\\\\\"C4\\\\\\\");\\\\n        require(_ethWSqueethPool != address(0), \\\\\\\"C5\\\\\\\");\\\\n        require(_crabMigration != address(0), \\\\\\\"C6\\\\\\\");\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"C7\\\\\\\");\\\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\\\\\"C8\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        ethWSqueethPool = _ethWSqueethPool;\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n        timelock = _timelock;\\\\n        crabMigration = _crabMigration;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\\\\\"C9\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice initializes the collateral ratio after the first migration\\\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\\\n     * @param _crabSharesToMint crab shares to mint\\\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\\\n     * @param _strategyCap strategy cap for crab V2\\\\n     */\\\\n    function initialize(\\\\n        uint256 _wSqueethToMint,\\\\n        uint256 _crabSharesToMint,\\\\n        uint256 _timeAtLastHedge,\\\\n        uint256 _priceAtLastHedge,\\\\n        uint256 _strategyCap\\\\n    ) external payable {\\\\n        require(msg.sender == crabMigration, \\\\\\\"C10\\\\\\\");\\\\n        require(!isInitialized, \\\\\\\"C11\\\\\\\");\\\\n\\\\n        _setStrategyCap(_strategyCap);\\\\n\\\\n        uint256 amount = msg.value;\\\\n\\\\n        _checkStrategyCap(amount, 0);\\\\n\\\\n        // store hedge data from crab V1\\\\n        timeAtLastHedge = _timeAtLastHedge;\\\\n        priceAtLastHedge = _priceAtLastHedge;\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\\\n\\\\n        isInitialized = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice transfer vault NFT to new contract\\\\n     * @dev strategy cap is set to 0 to avoid future deposits\\\\n     * @param _newStrategy new strategy contract address\\\\n     */\\\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\\\n        _setStrategyCap(0);\\\\n\\\\n        emit VaultTransferred(_newStrategy, vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the strategy cap in ETH collateral terms\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\\\n        _setStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set strategy cap amount\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function _setStrategyCap(uint256 _capAmount) internal {\\\\n        strategyCap = _capAmount;\\\\n        emit SetStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to redeem the net value of a vault post shutdown\\\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\\\n     */\\\\n    function redeemShortShutdown() external afterInitialization {\\\\n        hasRedeemedInShutdown = true;\\\\n        powerTokenController.redeemShort(vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\\n     * @param _poolFee Uniswap pool fee\\\\n     */\\\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\\\n            _ethToDeposit,\\\\n            cachedStrategyDebt,\\\\n            cachedStrategyCollateral\\\\n        );\\\\n\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            _poolFee,\\\\n            wSqueethToMint,\\\\n            _ethToDeposit.sub(msg.value),\\\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\\\n            abi.encodePacked(_ethToDeposit)\\\\n        );\\\\n\\\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\\n     * @param _crabAmount strategy token amount to burn\\\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\\\n     * @param _poolFee Uniswap pool fee\\\\n\\\\n     */\\\\n    function flashWithdraw(\\\\n        uint256 _crabAmount,\\\\n        uint256 _maxEthToPay,\\\\n        uint24 _poolFee\\\\n    ) external nonReentrant {\\\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            _poolFee,\\\\n            exactWSqueethNeeded,\\\\n            _maxEthToPay,\\\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\\\n            abi.encodePacked(_crabAmount)\\\\n        );\\\\n\\\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit ETH into strategy\\\\n     * @dev provide ETH, return wSqueeth and strategy token\\\\n     */\\\\n    function deposit() external payable nonReentrant {\\\\n        uint256 amount = msg.value;\\\\n\\\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\\\n\\\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\\\n\\\\n        // send back ETH collateral\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n\\\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\\\n        require(powerTokenController.isShutDown(), \\\\\\\"C12\\\\\\\");\\\\n        require(hasRedeemedInShutdown, \\\\\\\"C13\\\\\\\");\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\\\n        _burn(msg.sender, _crabAmount);\\\\n\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set nonce to true\\\\n     * @param _nonce the number to be set true\\\\n     */\\\\n    function setNonceTrue(uint256 _nonce) external {\\\\n        nonces[msg.sender][_nonce] = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\\\n     * @param _crabAmount strategy token amount\\\\n     * @return wSqueeth amount\\\\n     */\\\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\\\n        return _getDebtFromStrategyAmount(_crabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\\\n     */\\\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\\\n        require(_hedgingTwapPeriod >= 180, \\\\\\\"C14\\\\\\\");\\\\n\\\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\\\n\\\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\\\n     */\\\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"C7\\\\\\\");\\\\n\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n\\\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\\\n     */\\\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\\\\\"C8\\\\\\\");\\\\n\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n\\\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\\\n     */\\\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\\\n        // Tolerance cannot be more than 20%\\\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\\\\\"C15\\\\\\\");\\\\n\\\\n        otcPriceTolerance = _otcPriceTolerance;\\\\n\\\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a user deposit puts the strategy above the cap\\\\n     * @dev reverts if a deposit amount puts strategy over the cap\\\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\\\n     * @param _depositAmount the user deposit amount in ETH\\\\n     * @param _strategyCollateral the updated strategy collateral\\\\n     */\\\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\\\\\"C16\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _strategyFlash(\\\\n        address _caller,\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        uint24 _fee,\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n\\\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\\\n            // will revert if data.totalDeposit is > eth balance in contract\\\\n            _deposit(_caller, data.totalDeposit, true);\\\\n\\\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\\\n\\\\n            // repay the flash swap\\\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\\\n\\\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\\\n\\\\n            // return excess eth to the user that was not needed for slippage\\\\n            if (address(this).balance > 0) {\\\\n                payable(_caller).sendValue(address(this).balance);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\\\n\\\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\\\n            uint256 ethToWithdraw = _withdraw(\\\\n                _caller,\\\\n                data.crabAmount,\\\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\\\n                true\\\\n            );\\\\n\\\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\\\n\\\\n            // use some amount of withdrawn ETH to repay flash swap\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\\\n\\\\n            // excess ETH not used to repay flash swap is transferred to the user\\\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\\\n\\\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\\\n\\\\n            if (proceeds > 0) {\\\\n                payable(_caller).sendValue(proceeds);\\\\n            }\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit into strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _depositor depositor address\\\\n     * @param _amount amount of ETH collateral to deposit\\\\n     * @param _isFlashDeposit true if called by flashDeposit\\\\n     * @return wSqueethToMint minted amount of WSqueeth\\\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\\\n     */\\\\n    function _deposit(\\\\n        address _depositor,\\\\n        uint256 _amount,\\\\n        bool _isFlashDeposit\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_amount, strategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\\\n\\\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\\\n\\\\n        return (wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\\\n     * @return ETH amount to withdraw\\\\n     */\\\\n    function _withdraw(\\\\n        address _from,\\\\n        uint256 _crabAmount,\\\\n        uint256 _wSqueethAmount,\\\\n        bool _isFlashWithdraw\\\\n    ) internal returns (uint256) {\\\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\\\n\\\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\\\n        _burn(_from, _crabAmount);\\\\n\\\\n        return ethToWithdraw;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev set nonce flag of the trader to true\\\\n     * @param _trader address of the signer\\\\n     * @param _nonce number that is to be traded only once\\\\n     */\\\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\\\n        require(!nonces[_trader][_nonce], \\\\\\\"C27\\\\\\\");\\\\n        nonces[_trader][_nonce] = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev view function to get the domain seperator used in signing\\\\n     */\\\\n    // solhint-disable-next-line func-name-mixedcase\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\\\n        return _domainSeparatorV4();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev check the signer and swap tokens in the order\\\\n     * @param _remainingAmount quantity the manager wants to trade\\\\n     * @param _clearingPrice the price at which all orders are traded\\\\n     * @param _order a signed order to swap tokens\\\\n     */\\\\n    function _execOrder(\\\\n        uint256 _remainingAmount,\\\\n        uint256 _clearingPrice,\\\\n        Order memory _order\\\\n    ) internal {\\\\n        // check that order beats clearing price\\\\n        if (_order.isBuying) {\\\\n            require(_clearingPrice <= _order.price, \\\\\\\"C17\\\\\\\");\\\\n        } else {\\\\n            require(_clearingPrice >= _order.price, \\\\\\\"C18\\\\\\\");\\\\n        }\\\\n\\\\n        _useNonce(_order.trader, _order.nonce);\\\\n        bytes32 structHash = keccak256(\\\\n            abi.encode(\\\\n                _CRAB_BALANCE_TYPEHASH,\\\\n                _order.bidId,\\\\n                _order.trader,\\\\n                _order.quantity,\\\\n                _order.price,\\\\n                _order.isBuying,\\\\n                _order.expiry,\\\\n                _order.nonce\\\\n            )\\\\n        );\\\\n\\\\n        bytes32 hash = _hashTypedDataV4(structHash);\\\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\\\n        require(offerSigner == _order.trader, \\\\\\\"C19\\\\\\\");\\\\n        require(_order.expiry >= block.timestamp, \\\\\\\"C20\\\\\\\");\\\\n\\\\n        // adjust quantity for partial fills\\\\n        if (_remainingAmount < _order.quantity) {\\\\n            _order.quantity = _remainingAmount;\\\\n        }\\\\n        // weth clearing price for the order\\\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\\\n\\\\n        if (_order.isBuying) {\\\\n            // trader sends weth and receives oSQTH\\\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\\\n            IWETH9(weth).withdraw(wethAmount);\\\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\\\n        } else {\\\\n            // trader sends oSQTH and receives weth\\\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\\\n            // wrap it\\\\n            IWETH9(weth).deposit{value: wethAmount}();\\\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\\\n        }\\\\n\\\\n        emit HedgeOTCSingle(\\\\n            _order.trader, // market maker\\\\n            _order.bidId,\\\\n            _order.quantity, // order oSQTH quantity\\\\n            _order.price, // order price\\\\n            _order.isBuying, // order direction\\\\n            _clearingPrice // executed price for order\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev hedge function to reduce delta using an array of signed orders\\\\n     * @param _totalQuantity quantity the manager wants to trade\\\\n     * @param _clearingPrice clearing price in weth\\\\n     * @param _isHedgeBuying direction of hedge trade\\\\n     * @param _orders an array of signed order to swap tokens\\\\n     */\\\\n    function hedgeOTC(\\\\n        uint256 _totalQuantity,\\\\n        uint256 _clearingPrice,\\\\n        bool _isHedgeBuying,\\\\n        Order[] memory _orders\\\\n    ) external onlyOwner afterInitialization {\\\\n        require(_clearingPrice > 0, \\\\\\\"C21\\\\\\\");\\\\n        require(_isTimeHedge() || _isPriceHedge(), \\\\\\\"C22\\\\\\\");\\\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\\\n\\\\n        timeAtLastHedge = block.timestamp;\\\\n        priceAtLastHedge = _clearingPrice;\\\\n\\\\n        uint256 remainingAmount = _totalQuantity;\\\\n        uint256 prevPrice = _orders[0].price;\\\\n        uint256 currentPrice = _orders[0].price;\\\\n        bool isOrderBuying = _orders[0].isBuying;\\\\n        require(_isHedgeBuying != isOrderBuying, \\\\\\\"C23\\\\\\\");\\\\n\\\\n        // iterate through order array and execute if valid\\\\n        for (uint256 i; i < _orders.length; ++i) {\\\\n            currentPrice = _orders[i].price;\\\\n            require(_orders[i].isBuying == isOrderBuying, \\\\\\\"C24\\\\\\\");\\\\n            if (_isHedgeBuying) {\\\\n                require(currentPrice >= prevPrice, \\\\\\\"C25\\\\\\\");\\\\n            } else {\\\\n                require(currentPrice <= prevPrice, \\\\\\\"C25\\\\\\\");\\\\n            }\\\\n            prevPrice = currentPrice;\\\\n\\\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\\\n\\\\n            if (remainingAmount > _orders[i].quantity) {\\\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\\\n            } else {\\\\n                break;\\\\n            }\\\\n        }\\\\n\\\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\\\n     * @param _price clearing price provided by manager\\\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\\\n     */\\\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\\\n        // Get twap\\\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\\\n\\\\n        if (_isHedgeBuying) {\\\\n            require(\\\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\\\n                \\\\\\\"Price too high relative to Uniswap twap.\\\\\\\"\\\\n            );\\\\n        } else {\\\\n            require(\\\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\\\n                \\\\\\\"Price too low relative to Uniswap twap.\\\\\\\"\\\\n            );\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sync strategy debt and collateral amount from vault\\\\n     * @return synced debt amount\\\\n     * @return synced collateral amount\\\\n     */\\\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\\\n\\\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\\\n     * @return the fee adjustment factor\\\\n     */\\\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\\\n            oracle,\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            POWER_PERP_PERIOD,\\\\n            false\\\\n        );\\\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\\\n     * @param _depositedAmount amount of deposited WETH\\\\n     * @param _strategyDebtAmount amount of strategy debt\\\\n     * @param _strategyCollateralAmount collateral amount in strategy\\\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\\\n     */\\\\n    function _calcWsqueethToMintAndFee(\\\\n        uint256 _depositedAmount,\\\\n        uint256 _strategyDebtAmount,\\\\n        uint256 _strategyCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 wSqueethToMint;\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\\\n        require(!isShutdown, \\\\\\\"C26\\\\\\\");\\\\n\\\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\\\n        );\\\\n\\\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\\\n\\\\n        return (wSqueethToMint, fee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if time hedging is allowed\\\\n     */\\\\n    function _isTimeHedge() internal view returns (bool) {\\\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function _isPriceHedge() internal view returns (bool) {\\\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\\\n\\\\n        return priceThreshold >= hedgePriceThreshold;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkPriceHedge() external view returns (bool) {\\\\n        return _isPriceHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkTimeHedge() external view returns (bool) {\\\\n        return _isTimeHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate amount of strategy token to mint for depositor\\\\n     * @param _amount amount of ETH deposited\\\\n     * @param _strategyCollateralAmount amount of strategy collateral\\\\n     * @param _crabTotalSupply total supply of strategy token\\\\n     * @return amount of strategy token to mint\\\\n     */\\\\n    function _calcSharesToMint(\\\\n        uint256 _amount,\\\\n        uint256 _strategyCollateralAmount,\\\\n        uint256 _crabTotalSupply\\\\n    ) internal pure returns (uint256) {\\\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\\\n\\\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\\\n\\\\n        return _amount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\\\n     * @param _crabAmount strategy token amount\\\\n     * @param _totalSupply strategy total supply\\\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\\\n     */\\\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\\\n        return _crabAmount.wdiv(_totalSupply);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\\\n     * @param _crabRatio crab ratio\\\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\\\n     * @return amount of ETH allowed to withdraw\\\\n     */\\\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8b1900ce7c5c79e38af489819462339a27d677e2bb8626f7aa6f784409cbf3fa\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyBase.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./StrategyMath.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../../libs/VaultLib.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev StrategyBase contract\\\\n * @notice base contract for PowerToken strategy\\\\n * @author opyn team\\\\n */\\\\ncontract StrategyBase is ERC20 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev power token controller\\\\n    IController public powerTokenController;\\\\n\\\\n    /// @dev WETH token\\\\n    address public immutable weth;\\\\n    address public immutable wPowerPerp;\\\\n\\\\n    /// @dev power token strategy vault ID\\\\n    uint256 public immutable vaultId;\\\\n\\\\n    /**\\\\n     * @notice constructor for StrategyBase\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _powerTokenController power token controller address\\\\n     * @param _weth weth token address\\\\n     * @param _name token name for strategy ERC20 token\\\\n     * @param _symbol token symbol for strategy ERC20 token\\\\n     */\\\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\\\n        require(_powerTokenController != address(0), \\\\\\\"invalid controller address\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"invalid weth address\\\\\\\");\\\\n\\\\n        weth = _weth;\\\\n        powerTokenController = IController(_powerTokenController);\\\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\\\n    }\\\\n    /**\\\\n     * @notice get power token strategy vault ID \\\\n     * @return vault ID\\\\n     */\\\\n    function getStrategyVaultId() external view returns (uint256) {\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n    */\\\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\\\n        return _getVaultDetails();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint WPowerPerp and deposit collateral\\\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\\\n     * @param _to receiver address\\\\n     * @param _wAmount amount of WPowerPerp to mint\\\\n     * @param _collateral amount of collateral to deposit\\\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\\\n     */\\\\n    function _mintWPowerPerp(\\\\n        address _to,\\\\n        uint256 _wAmount,\\\\n        uint256 _collateral,\\\\n        bool _keepWsqueeth\\\\n    ) internal {\\\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\\\n\\\\n        if (!_keepWsqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn WPowerPerp and withdraw collateral\\\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\\\n     * @param _from WPowerPerp holder address\\\\n     * @param _amount amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\\\n     */\\\\n    function _burnWPowerPerp(\\\\n        address _from,\\\\n        uint256 _amount,\\\\n        uint256 _collateralToWithdraw,\\\\n        bool _isOwnedWSqueeth\\\\n    ) internal {\\\\n        if (!_isOwnedWSqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\\\n        }\\\\n\\\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint strategy token\\\\n     * @param _to recepient address\\\\n     * @param _amount token amount\\\\n     */\\\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\\\n        _mint(_to, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get strategy debt amount for a specific strategy token amount\\\\n     * @param _strategyAmount strategy amount\\\\n     * @return debt amount\\\\n     */\\\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n     */\\\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\\\n\\\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\\\n    }\\\\n}\\\\n\\\\n\\\",\\\"keccak256\\\":\\\"0xa18ad4c34899e27bdf048a866834e05dda91ee8ff904fac23587dddf69a5d675\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyFlashSwap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\\\n\\\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\\\n    using Path for bytes;\\\\n    using SafeCast for uint256;\\\\n    using LowGasSafeMath for uint256;\\\\n    using LowGasSafeMath for int256;\\\\n\\\\n    /// @dev Uniswap factory address\\\\n    address public immutable factory;\\\\n\\\\n    struct SwapCallbackData {\\\\n        bytes path;\\\\n        address caller;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev constructor\\\\n     * @param _factory uniswap factory address\\\\n     */\\\\n    constructor(\\\\n        address _factory\\\\n    ) {\\\\n        require(_factory != address(0), \\\\\\\"invalid factory address\\\\\\\");\\\\n        factory = _factory;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap swap callback function for flashes\\\\n     * @param amount0Delta amount of token0\\\\n     * @param amount1Delta amount of token1\\\\n     * @param _data callback data encoded as SwapCallbackData struct\\\\n     */\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata _data\\\\n    ) external override {\\\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\\\n\\\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //ensure that callback comes from uniswap pool\\\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\\\n\\\\n        //determine the amount that needs to be repaid as part of the flashswap\\\\n        uint256 amountToPay =\\\\n            amount0Delta > 0\\\\n                ?  uint256(amount0Delta)\\\\n                :  uint256(amount1Delta);\\\\n        \\\\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountIn amount to sell\\\\n     * @param _amountOutMinimum minimum amount to receive\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountOut = _exactInputInternal(\\\\n            _amountIn,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n       \\\\n        //slippage limit check\\\\n        require(amountOut >= _amountOutMinimum, \\\\\\\"amount out less than min\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountOut exact amount to receive\\\\n     * @param _amountInMaximum maximum amount to sell\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountIn = _exactOutputInternal(\\\\n            _amountOut,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n        \\\\n        //slippage limit check\\\\n        require(amountIn <= _amountInMaximum, \\\\\\\"amount in greater than max\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice function to be called by uniswap callback. \\\\n     * @dev this function should be overridden by the child contract\\\\n     * param _caller initial strategy function caller\\\\n     * param _tokenIn token address sold\\\\n     * param _tokenOut token address bought\\\\n     * param _fee pool fee\\\\n     * param _amountToPay amount to pay for the pool second token\\\\n     * param _callData arbitrary data assigned with the flashswap call \\\\n     * param _callSource function call source\\\\n     */\\\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\\\n    \\\\n    /** \\\\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\\\n    * @param _amountIn amount of token to pay\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token bought (amountOut)\\\\n    */\\\\n    function _exactInputInternal(\\\\n        uint256 _amountIn,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n       \\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0, int256 amount1) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                _amountIn.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n        \\\\n        //determine the amountOut based on which token has a lower address\\\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\\\n    * @param _amountOut amount of token to receive\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token sold (amountIn)\\\\n    */\\\\n    function _exactOutputInternal(\\\\n        uint256 _amountOut,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n        \\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0Delta, int256 amount1Delta) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                -_amountOut.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n\\\\n        //determine the amountIn and amountOut based on which token has a lower address\\\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\\\n        // it's technically possible to not receive the full output amount,\\\\n        // so if no price limit has been specified, require this possibility away\\\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\\\n\\\\n        return amountIn;\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice returns the uniswap pool for the given token pair and fee\\\\n    * @dev the pool contract may or may not exist\\\\n    * @param tokenA address of first token \\\\n    * @param tokenB address of second token \\\\n    * @param fee fee tier for pool\\\\n    */\\\\n    function _getPool(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool) {\\\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x91b49caf229fd114fbb589e73056772cf15a0adaba0a6f5eca4dff9cd12b9575\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/base/StrategyMath.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: AGPL-3.0-only\\\\n\\\\n/// math.sol -- mixin for inline numerical wizardry\\\\n\\\\n// This program is free software: you can redistribute it and/or modify\\\\n// it under the terms of the GNU General Public License as published by\\\\n// the Free Software Foundation, either version 3 of the License, or\\\\n// (at your option) any later version.\\\\n\\\\n// This program is distributed in the hope that it will be useful,\\\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\\\n// GNU General Public License for more details.\\\\n\\\\n// You should have received a copy of the GNU General Public License\\\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\\\n\\\\npragma solidity >0.4.13;\\\\n\\\\n\\\\n/**\\\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\\\n * @dev change contract to library, added div() function\\\\n */\\\\nlibrary StrategyMath {\\\\n    function add(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x + y) >= x, \\\\\\\"ds-math-add-overflow\\\\\\\");\\\\n    }\\\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x - y) <= x, \\\\\\\"ds-math-sub-underflow\\\\\\\");\\\\n    }\\\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\\\n        require(y == 0 || (z = x * y) / y == x, \\\\\\\"ds-math-mul-overflow\\\\\\\");\\\\n    }\\\\n\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    function min(uint x, uint y) internal pure returns (uint z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function max(uint x, uint y) internal pure returns (uint z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n    function imin(int x, int y) internal pure returns (int z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function imax(int x, int y) internal pure returns (int z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n\\\\n    uint constant WAD = 10 ** 18;\\\\n    uint constant RAY = 10 ** 27;\\\\n\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), WAD / 2) / WAD;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), RAY / 2) / RAY;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, WAD), y / 2) / y;\\\\n    }\\\\n    //rounds to zero if x*y < RAY / 2\\\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, RAY), y / 2) / y;\\\\n    }\\\\n\\\\n    // Ceil A to a multiple m\\\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(sub(add(a, m), 1), m), m);\\\\n    }\\\\n\\\\n    // Floor A to a multiple m\\\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(a, m), m);\\\\n    }\\\\n\\\\n    // This famous algorithm is called \\\\\\\"exponentiation by squaring\\\\\\\"\\\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\\\n    //\\\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\\\n    //\\\\n    // These facts are why it works:\\\\n    //\\\\n    //  If n is even, then x^n = (x^2)^(n/2).\\\\n    //  If n is odd,  then x^n = x * x^(n-1),\\\\n    //   and applying the equation for even x gives\\\\n    //    x^n = x * (x^2)^((n-1) / 2).\\\\n    //\\\\n    //  Also, EVM division is flooring and\\\\n    //    floor[(n-1) / 2] = floor[n / 2].\\\\n    //\\\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\\\n        z = n % 2 != 0 ? x : RAY;\\\\n\\\\n        for (n /= 2; n != 0; n /= 2) {\\\\n            x = rmul(x, x);\\\\n\\\\n            if (n % 2 != 0) {\\\\n                z = rmul(z, x);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0xfec6fa07fbbb639f94321d6503f5363286776cf831215017ce28aae67295613b\\\",\\\"license\\\":\\\"AGPL-3.0-only\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x61022060405266b1a2bc2ec50000600955600a805463ffffffff19166101a41790553480156200002e57600080fd5b506040516200621538038062006215833981016040819052620000519162000669565b60405180604001604052806007815260200166437261624f544360c81b815250604051806040016040528060018152602001601960f91b815250878b8a6040518060400160405280601081526020016f21b930b11029ba3930ba32b3bc903b1960811b8152506040518060400160405280600681526020016521b930b13b1960d11b81525081818160039080519060200190620000f09291906200057c565b508051620001069060049060208401906200057c565b50506005805460ff19166012179055506001600160a01b038416620001485760405162461bcd60e51b81526004016200013f90620007af565b60405180910390fd5b6001600160a01b038316620001715760405162461bcd60e51b81526004016200013f90620007e6565b606083901b6001600160601b03191660805260058054610100600160a81b0319166101006001600160a01b0387811682029290921792839055604080516307f07b1360e41b815290519190930490911691637f07b130916004808301926020929190829003018186803b158015620001e857600080fd5b505afa158015620001fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000223919062000645565b6001600160601b031960609190911b1660a052600554604051630728cf2360e31b81526101009091046001600160a01b0316906339467918906200027190600090819081906004016200072a565b602060405180830381600087803b1580156200028c57600080fd5b505af1158015620002a1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002c7919062000711565b60c052505050506001600160a01b038116620002f75760405162461bcd60e51b81526004016200013f906200075c565b60601b6001600160601b03191660e052600160065560006200031862000510565b600780546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35081516020808401919091208251918301919091206101408290526101608190527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620003b162000514565b61012052620003c281848462000518565b6101005261018052505050506001600160a01b038816620003f75760405162461bcd60e51b81526004016200013f9062000855565b6001600160a01b038416620004205760405162461bcd60e51b81526004016200013f906200081d565b6001600160a01b038516620004495760405162461bcd60e51b81526004016200013f9062000871565b6001600160a01b038316620004725760405162461bcd60e51b81526004016200013f9062000740565b60008211620004955760405162461bcd60e51b81526004016200013f9062000793565b600081118015620004ae5750670de0b6b3a76400008111155b620004cd5760405162461bcd60e51b81526004016200013f9062000839565b6001600160601b0319606098891b81166101c05294881b85166101a052600b91909155600c5590851b82166101e05290931b90921661020052506200088d915050565b3390565b4690565b60008383836200052762000514565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620005b45760008555620005ff565b82601f10620005cf57805160ff1916838001178555620005ff565b82800160010185558215620005ff579182015b82811115620005ff578251825591602001919060010190620005e2565b506200060d92915062000611565b5090565b5b808211156200060d576000815560010162000612565b80516001600160a01b03811681146200064057600080fd5b919050565b60006020828403121562000657578081fd5b620006628262000628565b9392505050565b60008060008060008060008060006101208a8c03121562000688578485fd5b620006938a62000628565b9850620006a360208b0162000628565b9750620006b360408b0162000628565b9650620006c360608b0162000628565b9550620006d360808b0162000628565b9450620006e360a08b0162000628565b9350620006f360c08b0162000628565b925060e08a015191506101008a015190509295985092959850929598565b60006020828403121562000723578081fd5b5051919050565b9283526020830191909152604082015260600190565b602080825260029082015261219b60f11b604082015260600190565b60208082526017908201527f696e76616c696420666163746f72792061646472657373000000000000000000604082015260600190565b602080825260029082015261433760f01b604082015260600190565b6020808252601a908201527f696e76616c696420636f6e74726f6c6c65722061646472657373000000000000604082015260600190565b60208082526014908201527f696e76616c696420776574682061646472657373000000000000000000000000604082015260600190565b60208082526002908201526110cd60f21b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b602080825260029082015261433360f01b604082015260600190565b602080825260029082015261433560f01b604082015260600190565b60805160601c60a05160601c60c05160e05160601c61010051610120516101405161016051610180516101a05160601c6101c05160601c6101e05160601c6102005160601c615820620009f560003980610bb55280611d54525080611b495280611d2752508061119852806129395280612ace52806144a2525080610f4452806129665280612afb52806144c352508061264852508061268a5250806126695250806125ef52508061261f525080611a5f5280611fc45280614463525080610cb65280610fb6528061146e5280611c485280611cee5280612859528061328d5280613b3a5250806111bc52806118df52806120b052806129885280612b1d5280613329528061357952806136ad5280613a8152806144e452508061037f5280610f2052806118be52806120d152806129aa5280612b3f5280612e345280612ed65280612f6e5280612ff35280613465528061376152806137e7528061450552506158206000f3fe60806040526004361061036f5760003560e01c80637f07b130116101c6578063cae74029116100f7578063e9c3cb4f11610095578063f5d278e41161006f578063f5d278e41461095e578063f73e19c314610973578063fa461e3314610993578063fc5b73ff146109b3576103e1565b8063e9c3cb4f14610914578063f101d92f14610929578063f2fde38b1461093e576103e1565b8063d2dd9f79116100d1578063d2dd9f79146108ac578063d33219b4146108cc578063dcbab608146108e1578063dd62ed3e146108f4576103e1565b8063cae740291461087a578063cfa70b181461088f578063d0e30db0146108a4576103e1565b8063a457c2d711610164578063b52b7ff01161013e578063b52b7ff014610810578063bdd438b814610830578063c245168914610850578063c45a015514610865576103e1565b8063a457c2d7146107b0578063a9059cbb146107d0578063b24f719b146107f0576103e1565b80638f8b8dbc116101a05780638f8b8dbc1461074657806395d89b41146107665780639ff69a511461077b578063a319b29f1461079b576103e1565b80637f07b1301461070757806388626eb81461071c5780638da5cb5b14610731576103e1565b80633d65fdac116102a057806366a91b761161023e57806370a082311161021857806370a082311461069d578063715018a6146106bd5780637bcdc16e146106d25780637dc0d1d0146106f2576103e1565b806366a91b761461065e57806367b8c345146106735780636c1040a914610688576103e1565b80634d76e6fc1161027a5780634d76e6fc146105ef578063502e1a1614610604578063533092ef1461062457806363bbc4b614610649576103e1565b80633d65fdac146105a55780633dcb0c5d146105c55780633fc8cef3146105da576103e1565b8063313ce5671161030d578063392e53cd116102e7578063392e53cd1461052e5780633950935114610543578063395ebb69146105635780633d3a62ee14610585576103e1565b8063313ce567146104e257806333194c0a146105045780633644e51514610519576103e1565b806318160ddd1161034957806318160ddd1461045e57806323b872dd14610480578063281e78d1146104a05780632e1a7d4d146104c2576103e1565b806306fdde03146103e6578063095ea7b3146104115780630ca514cd1461043e576103e1565b366103e157336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103ba575060055461010090046001600160a01b031633145b6103df5760405162461bcd60e51b81526004016103d69061547e565b60405180910390fd5b005b600080fd5b3480156103f257600080fd5b506103fb6109c6565b604051610408919061511f565b60405180910390f35b34801561041d57600080fd5b5061043161042c366004614a72565b610a5d565b60405161040891906150d3565b34801561044a57600080fd5b506103df610459366004614cd2565b610a7b565b34801561046a57600080fd5b50610473610b25565b6040516104089190614fab565b34801561048c57600080fd5b5061043161049b366004614a32565b610b2b565b3480156104ac57600080fd5b506104b5610bb3565b6040516104089190614fb4565b3480156104ce57600080fd5b506103df6104dd366004614cd2565b610bd7565b3480156104ee57600080fd5b506104f7610cab565b604051610408919061559b565b34801561051057600080fd5b50610473610cb4565b34801561052557600080fd5b50610473610cd8565b34801561053a57600080fd5b50610431610ce7565b34801561054f57600080fd5b5061043161055e366004614a72565b610cf8565b34801561056f57600080fd5b50610578610d46565b604051610408919061558a565b34801561059157600080fd5b506103df6105a0366004614cd2565b610d4c565b3480156105b157600080fd5b506103df6105c0366004614cd2565b610ee4565b3480156105d157600080fd5b506104b5610f0a565b3480156105e657600080fd5b506104b5610f1e565b3480156105fb57600080fd5b506104b5610f42565b34801561061057600080fd5b5061043161061f366004614a72565b610f66565b34801561063057600080fd5b50610639610f86565b6040516104089493929190615078565b34801561065557600080fd5b50610473610fa2565b34801561066a57600080fd5b50610473610fa8565b34801561067f57600080fd5b50610473610fae565b34801561069457600080fd5b50610473610fb4565b3480156106a957600080fd5b506104736106b83660046149c2565b610fd8565b3480156106c957600080fd5b506103df610ff7565b3480156106de57600080fd5b506103df6106ed366004614cd2565b6110c2565b3480156106fe57600080fd5b506104b5611196565b34801561071357600080fd5b506104b56111ba565b34801561072857600080fd5b506104316111de565b34801561073d57600080fd5b506104b56111e8565b34801561075257600080fd5b506103df610761366004614ef1565b6111f7565b34801561077257600080fd5b506103fb6112d7565b34801561078757600080fd5b506103df610796366004614cd2565b611338565b3480156107a757600080fd5b506103df611409565b3480156107bc57600080fd5b506104316107cb366004614a72565b6114ca565b3480156107dc57600080fd5b506104316107eb366004614a72565b611532565b3480156107fc57600080fd5b506103df61080b366004614d2d565b611546565b34801561081c57600080fd5b506103df61082b366004614e83565b61184f565b34801561083c57600080fd5b506103df61084b366004614cd2565b611976565b34801561085c57600080fd5b50610431611a53565b34801561087157600080fd5b506104b5611a5d565b34801561088657600080fd5b50610473611a81565b34801561089b57600080fd5b50610473611a87565b6103df611a93565b3480156108b857600080fd5b506103df6108c73660046149c2565b611b3e565b3480156108d857600080fd5b506104b5611d25565b6103df6108ef366004614eb7565b611d49565b34801561090057600080fd5b5061047361090f3660046149fa565b611e0f565b34801561092057600080fd5b50610473611e3a565b34801561093557600080fd5b50610473611e40565b34801561094a57600080fd5b506103df6109593660046149c2565b611e46565b34801561096a57600080fd5b50610578611f68565b34801561097f57600080fd5b5061047361098e366004614cd2565b611f74565b34801561099f57600080fd5b506103df6109ae366004614adc565b611f7f565b6103df6109c1366004614d02565b612025565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b820191906000526020600020905b815481529060010190602001808311610a3557829003601f168201915b505050505090505b90565b6000610a71610a6a612172565b8484612176565b5060015b92915050565b610a83612172565b6001600160a01b0316610a946111e8565b6001600160a01b031614610aef576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff16610b195760405162461bcd60e51b81526004016103d6906151f7565b610b2281612262565b50565b60025490565b6000610b38848484612297565b610ba884610b44612172565b610ba385604051806060016040528060288152602001615734602891396001600160a01b038a16600090815260016020526040812090610b82612172565b6001600160a01b0316815260208101919091526040016000205491906123f2565b612176565b5060015b9392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60026006541415610c2f576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610c3f82612489565b90506000610c5033848460006124b4565b9050610c5c3382612501565b336001600160a01b03167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94848484604051610c9993929190615574565b60405180910390a25050600160065550565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce26125eb565b905090565b600a54640100000000900460ff1681565b6000610a71610d05612172565b84610ba38560016000610d16612172565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906126b5565b6101a481565b60026006541415610da4576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600681905550600560019054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610dfc57600080fd5b505af1158015610e10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e349190614a9d565b610e505760405162461bcd60e51b81526004016103d6906153ee565b600f5460ff16610e725760405162461bcd60e51b81526004016103d6906152aa565b6000610e8582610e80610b25565b61270f565b90506000610e93824761271b565b9050610e9f3384612727565b610ea93382612501565b336001600160a01b03167fe9ab9870b9093d99f8e981919f65ad09b7ae90ff80f1031639af9e0357eb9ed68483604051610c99929190615549565b33600090815260106020908152604080832093835292905220805460ff19166001179055565b60055461010090046001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b601060209081526000928352604080842090915290825290205460ff1681565b600080600080610f94612823565b935093509350935090919293565b600e5481565b600b5481565b600d5481565b7f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0381166000908152602081905260409020545b919050565b610fff612172565b6001600160a01b03166110106111e8565b6001600160a01b03161461106b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6007546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36007805473ffffffffffffffffffffffffffffffffffffffff19169055565b6110ca612172565b6001600160a01b03166110db6111e8565b6001600160a01b031614611136576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081116111565760405162461bcd60e51b81526004016103d69061540b565b600b8190556040517f28e0e4ee0b14d4b056ce88e1bcd890ccd32b22e213723c8765901381b5eae7059061118b908390614fab565b60405180910390a150565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce261291a565b6007546001600160a01b031690565b6111ff612172565b6001600160a01b03166112106111e8565b6001600160a01b03161461126b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60b48163ffffffff1610156112925760405162461bcd60e51b81526004016103d690615169565b600a805463ffffffff191663ffffffff83161790556040517f1cd9c7f99a5530a38c8f2b387dcc78e8a76cb5b203e0c4316a66777d993dee359061118b90839061558a565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b611340612172565b6001600160a01b03166113516111e8565b6001600160a01b0316146113ac576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6702c68af0bb1400008111156113d45760405162461bcd60e51b81526004016103d6906153d1565b60098190556040517f829c71710efa317bbdb8e5c4ca2b6d2551b7c2d7d37ea199975807eb3f5c0e7c9061118b908390614fab565b600a54640100000000900460ff166114335760405162461bcd60e51b81526004016103d6906151f7565b600f8054600160ff19909116179055600554604051634bf7d4a160e11b81526101009091046001600160a01b0316906397efa94290611496907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b600060405180830381600087803b1580156114b057600080fd5b505af11580156114c4573d6000803e3d6000fd5b50505050565b6000610a716114d7612172565b84610ba3856040518060600160405280602581526020016157c66025913960016000611501612172565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906123f2565b6000610a7161153f612172565b8484612297565b61154e612172565b6001600160a01b031661155f6111e8565b6001600160a01b0316146115ba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff166115e45760405162461bcd60e51b81526004016103d6906151f7565b600083116116045760405162461bcd60e51b81526004016103d690615398565b61160c612a90565b8061161a575061161a61291a565b6116365760405162461bcd60e51b81526004016103d690615444565b6116408383612ab1565b42600d55600e839055805184906000908390829061165a57fe5b602002602001015160600151905060008360008151811061167757fe5b602002602001015160600151905060008460008151811061169457fe5b602002602001015160800151905080151586151514156116c65760405162461bcd60e51b81526004016103d690615324565b60005b85518110156117ef578581815181106116de57fe5b60200260200101516060015192508115158682815181106116fb57fe5b6020026020010151608001511515146117265760405162461bcd60e51b81526004016103d690615427565b8615611751578383101561174c5760405162461bcd60e51b81526004016103d690615341565b611771565b838311156117715760405162461bcd60e51b81526004016103d690615341565b829350611792858988848151811061178557fe5b6020026020010151612c71565b85818151811061179e57fe5b6020026020010151604001518511156117e2576117db8682815181106117c057fe5b602002602001015160400151866130e390919063ffffffff16565b94506117e7565b6117ef565b6001016116c9565b507fbbc3ba742efe346cfdf333000069964e0ee3087c68da267dac977d299f2366fb8560008151811061181e57fe5b60200260200101516000015189888a60405161183d9493929190615557565b60405180910390a15050505050505050565b600260065414156118a7576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560006118b784612489565b90506119287f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084848760018a6040516020016119149190614fab565b60405160208183030381529060405261313b565b336001600160a01b03167fa13b272c1cf13ba724064d3d4809d9f557aab8da2bb582cba031a2f57e728e9d8583604051611963929190615549565b60405180910390a2505060016006555050565b61197e612172565b6001600160a01b031661198f6111e8565b6001600160a01b0316146119ea576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081118015611a025750670de0b6b3a76400008111155b611a1e5760405162461bcd60e51b81526004016103d6906154d4565b600c8190556040517f789e4b8ad1c375952cea7f07c9b3b6619a84b406432b948246cecb8ced96b9fa9061118b908390614fab565b6000610ce2612a90565b7f000000000000000000000000000000000000000000000000000000000000000081565b60085481565b6702c68af0bb14000081565b60026006541415611aeb576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065534600080611aff3384836131bc565b91509150336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158383604051610c99929190615549565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611b865760405162461bcd60e51b81526004016103d6906153b5565b600a54640100000000900460ff16611bb05760405162461bcd60e51b81526004016103d6906151f7565b600560019054906101000a90046001600160a01b03166001600160a01b0316639d4c94426040518163ffffffff1660e01b815260040160206040518083038186803b158015611bfe57600080fd5b505afa158015611c12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3691906149de565b6001600160a01b03166342842e0e30837f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401611c8593929190614fc8565b600060405180830381600087803b158015611c9f57600080fd5b505af1158015611cb3573d6000803e3d6000fd5b50505050611cc16000612262565b806001600160a01b03167fae97956757017853415251f661bfe857898f44ddb9c90b2483065719b84b0c697f0000000000000000000000000000000000000000000000000000000000000000604051611d1a9190614fab565b60405180910390a250565b7f000000000000000000000000000000000000000000000000000000000000000081565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611d915760405162461bcd60e51b81526004016103d69061528d565b600a54640100000000900460ff1615611dbc5760405162461bcd60e51b81526004016103d69061535e565b611dc581612262565b34611dd1816000613230565b600d849055600e839055611de8338783600061325f565b611df233866133b9565b5050600a805464ff00000000191664010000000017905550505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60095481565b600c5481565b611e4e612172565b6001600160a01b0316611e5f6111e8565b6001600160a01b031614611eba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611eff5760405162461bcd60e51b81526004018080602001828103825260268152602001806156486026913960400191505060405180910390fd5b6007546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600a5463ffffffff1681565b6000610a7582612489565b6000841380611f8e5750600083135b611f9757600080fd5b6000611fa582840184614b72565b90506000806000611fb984600001516133c3565b925092509250611feb7f00000000000000000000000000000000000000000000000000000000000000008484846133f4565b506000808913611ffb5787611ffd565b885b905061201a8560200151858585858a606001518b60400151613413565b505050505050505050565b6002600654141561207d576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560008061208d6138ec565b9150915061209b8482613230565b60006120a8858484613906565b5090506121237f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086846120fc8a346130e3565b60008b60405160200161210f9190614fab565b604051602081830303815290604052613995565b336001600160a01b03167f5d85169ff8329e90f3225f9798e0eba54d00c55d3bbfe201a0d1606febb23a8e868360405161215e929190615549565b60405180910390a250506001600655505050565b3390565b6001600160a01b0383166121bb5760405162461bcd60e51b81526004018080602001828103825260248152602001806157a26024913960400191505060405180910390fd5b6001600160a01b0382166122005760405162461bcd60e51b815260040180806020018281038252602281526020018061566e6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60088190556040517f29600e2e028c8c5c2b112d021938e0d0237d8fafcbb20394c56cf9fa4661ca279061118b908390614fab565b6001600160a01b0383166122dc5760405162461bcd60e51b815260040180806020018281038252602581526020018061577d6025913960400191505060405180910390fd5b6001600160a01b0382166123215760405162461bcd60e51b81526004018080602001828103825260238152602001806156036023913960400191505060405180910390fd5b61232c8383836125e6565b61236981604051806060016040528060268152602001615690602691396001600160a01b03861660009081526020819052604090205491906123f2565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461239890826126b5565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156124815760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561244657818101518382015260200161242e565b50505050905090810190601f1680156124735780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600080612494612823565b9350505050610bac6124a4610b25565b6124ae8386613a0c565b90613a45565b6000806124bf6138ec565b91505060006124d086610e80610b25565b905060006124de828461271b565b90506124ec88878388613a65565b6124f68888612727565b979650505050505050565b80471015612556576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146125a1576040519150601f19603f3d011682016040523d82523d6000602084013e6125a6565b606091505b50509050806125e65760405162461bcd60e51b815260040180806020018281038252603a8152602001806156b6603a913960400191505060405180910390fd5b505050565b60007f0000000000000000000000000000000000000000000000000000000000000000612616613b94565b141561264357507f0000000000000000000000000000000000000000000000000000000000000000610a5a565b6126ae7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000613b98565b9050610a5a565b600082820183811015610bac576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610bac8383613a45565b6000610bac8284613a0c565b6001600160a01b03821661276c5760405162461bcd60e51b815260040180806020018281038252602181526020018061575c6021913960400191505060405180910390fd5b612778826000836125e6565b6127b581604051806060016040528060228152602001615626602291396001600160a01b03851660009081526020819052604090205491906123f2565b6001600160a01b0383166000908152602081905260409020556002546127db9082613bfa565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600554604051634632752560e11b8152600091829182918291829161010090046001600160a01b031690638c64ea4a90612881907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b60806040518083038186803b15801561289957600080fd5b505afa1580156128ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d19190614c30565b805160208201516040830151606090930151919863ffffffff90911697506bffffffffffffffffffffffff90921695506fffffffffffffffffffffffffffffffff169350915050565b600a5460405163cce79bd560e01b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd5916129de917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff90911690600190600401614fec565b60206040518083038186803b1580156129f657600080fd5b505afa158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190614cea565b90506000612a47600e5483613a4590919063ffffffff16565b90506000670de0b6b3a76400008211612a7157612a6c670de0b6b3a7640000836130e3565b612a83565b612a8382670de0b6b3a76400006130e3565b600c541115935050505090565b6000612aa9600b54600d54613c5790919063ffffffff16565b421015905090565b600a5460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591612b71917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff1690600190600401614fec565b60206040518083038186803b158015612b8957600080fd5b505afa158015612b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc19190614cea565b90508115612c2657612c02670de0b6b3a7640000612bfc612bf5600954670de0b6b3a7640000613c5790919063ffffffff16565b8490613caf565b90613d1b565b831115612c215760405162461bcd60e51b81526004016103d6906152c7565b6125e6565b612c52670de0b6b3a7640000612bfc612bf5600954670de0b6b3a76400006130e390919063ffffffff16565b8310156125e65760405162461bcd60e51b81526004016103d690615230565b806080015115612ca4578060600151821115612c9f5760405162461bcd60e51b81526004016103d69061549a565b612cc8565b8060600151821015612cc85760405162461bcd60e51b81526004016103d69061537b565b612cda81602001518260c00151613d7a565b60007fc8aea8e60353611f3ed5409dad2d3173390bd252431198e7300eda67fefb66b1826000015183602001518460400151856060015186608001518760a001518860c00151604051602001612d379897969594939291906150de565b6040516020818303038152906040528051906020012090506000612d5a82613dee565b90506000612d78828560e00151866101000151876101200151613e3a565b905083602001516001600160a01b0316816001600160a01b031614612daf5760405162461bcd60e51b81526004016103d690615461565b428460a001511015612dd35760405162461bcd60e51b81526004016103d690615186565b8360400151861015612de757604084018690525b6000612e0c670de0b6b3a7640000612bfc888860400151613caf90919063ffffffff16565b9050846080015115612f575760208501516040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916323b872dd91612e6c919030908690600401614fc8565b602060405180830381600087803b158015612e8657600080fd5b505af1158015612e9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ebe9190614a9d565b50604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612f0b908490600401614fab565b600060405180830381600087803b158015612f2557600080fd5b505af1158015612f39573d6000803e3d6000fd5b50505050612f528560200151866040015183600061325f565b613085565b612f6c85602001518660400151836000613a65565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612fc757600080fd5b505af1158015612fdb573d6000803e3d6000fd5b50505050602086015160405163a9059cbb60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063a9059cbb9161303191859060040161505f565b602060405180830381600087803b15801561304b57600080fd5b505af115801561305f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130839190614a9d565b505b7f68c36f17c620d197a81d3aeff305f83abf3bb29943a38cd6efc299041238652d856020015186600001518760400151886060015189608001518b6040516130d29695949392919061509e565b60405180910390a150505050505050565b80820382811115610a75576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b60006131908530600060405180608001604052808c8c8f60405160200161316493929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052613faf565b9050838111156131b25760405162461bcd60e51b81526004016103d6906151c0565b5050505050505050565b6000806000806131ca6138ec565b915091506131d88682613230565b6000806131e6888585613906565b909250905060006132086131fa8a846130e3565b85613203610b25565b61411c565b90506132168a848b8b61325f565b6132208a826133b9565b9199919850909650505050505050565b60085461323d8284613c57565b111561325b5760405162461bcd60e51b81526004016103d690615213565b5050565b600554604051630728cf2360e31b81526101009091046001600160a01b03169063394679189084906132ba907f0000000000000000000000000000000000000000000000000000000000000000908890600090600401615574565b6020604051808303818588803b1580156132d357600080fd5b505af11580156132e7573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061330c9190614cea565b50806114c45760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613360908790879060040161505f565b602060405180830381600087803b15801561337a57600080fd5b505af115801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b29190614a9d565b5050505050565b61325b828261416b565b600080806133d1848261425b565b92506133de846014614327565b90506133eb84601761425b565b91509193909250565b600061340a856134058686866143e3565b614439565b95945050505050565b60008160ff16600181111561342457fe5b600181111561342f57fe5b14156136665760008280602001905181019061344b9190614b57565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906134a2903090600401614fb4565b60206040518083038186803b1580156134ba57600080fd5b505afa1580156134ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f29190614cea565b6040518263ffffffff1660e01b815260040161350e9190614fab565b600060405180830381600087803b15801561352857600080fd5b505af115801561353c573d6000803e3d6000fd5b5050505061355088826000015160016131bc565b5050600061355f88888861445c565b60405163a9059cbb60e01b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906135b0908490899060040161505f565b602060405180830381600087803b1580156135ca57600080fd5b505af11580156135de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136029190614a9d565b50886001600160a01b03167fc355ebece16d7e85e486911f0cde1074bc4bd3fec251c88cdddc7076d3e99adb864760405161363e929190615549565b60405180910390a2471561365f5761365f6001600160a01b038a1647612501565b50506138e3565b60018160ff16600181111561367757fe5b600181111561368257fe5b14156138e35760008280602001905181019061369e9190614b57565b9050600061374e8983600001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016136f79190614fb4565b60206040518083038186803b15801561370f57600080fd5b505afa158015613723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137479190614cea565b60016124b4565b9050600061375d89898961445c565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b1580156137ba57600080fd5b505af11580156137ce573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250613821915084908a9060040161505f565b602060405180830381600087803b15801561383b57600080fd5b505af115801561384f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138739190614a9d565b50600061388083886130e3565b90508a6001600160a01b03167f6f3269a64126ef2a1959892f3d921e81865181e09a7f72f55d3a49550c53b48d88836040516138bd929190615549565b60405180910390a280156138de576138de6001600160a01b038c1682612501565b505050505b50505050505050565b6000806000806138fa612823565b96509450505050509091565b60008060008061391461449a565b9050600086158015613924575085155b80156139365750613933610b25565b15155b905080156139565760405162461bcd60e51b81526004016103d6906151a3565b61397761396d6139668985613a0c565b8890613c57565b6124ae8a8a613a0c565b925060006139858484613a0c565b9399939850929650505050505050565b60006139ea8530600060405180608001604052808d8c8e6040516020016139be93929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526145d1565b9050838110156131b25760405162461bcd60e51b81526004016103d690615132565b6000670de0b6b3a7640000613a36613a248585613caf565b6002670de0b6b3a76400005b04613c57565b81613a3d57fe5b049392505050565b600081613a36613a5d85670de0b6b3a7640000613caf565b600285613a30565b80613b0e576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90613aba90879030908890600401614fc8565b602060405180830381600087803b158015613ad457600080fd5b505af1158015613ae8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b0c9190614a9d565b505b600554604051638632cb0360e01b81526101009091046001600160a01b031690638632cb0390613b66907f00000000000000000000000000000000000000000000000000000000000000009087908790600401615574565b600060405180830381600087803b158015613b8057600080fd5b505af11580156131b2573d6000803e3d6000fd5b4690565b6000838383613ba5613b94565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b600082821115613c51576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b80820182811015610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000811580613cca57505080820282828281613cc757fe5b04145b610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000808211613d71576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613a3d57fe5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff1615613dbe5760405162461bcd60e51b81526004016103d6906154b7565b6001600160a01b03909116600090815260106020908152604080832093835292905220805460ff19166001179055565b6000613df86125eb565b82604051602001808061190160f01b81525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613e9b5760405162461bcd60e51b81526004018080602001828103825260228152602001806156f06022913960400191505060405180910390fd5b8360ff16601b1480613eb057508360ff16601c145b613eeb5760405162461bcd60e51b81526004018080602001828103825260228152602001806157126022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613f47573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661340a576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b600080600080613fc285600001516133c3565b919450925090506001600160a01b0380841690831610600080613fe685878661445c565b6001600160a01b031663128acb088b85613fff8f614710565b6000036001600160a01b038e1615614017578d61403d565b876140365773fffd8963efd1fc6a506488495d951d5263988d2561403d565b6401000276a45b8d60405160200161404e91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161407d959493929190615025565b6040805180830381600087803b15801561409657600080fd5b505af11580156140aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140ce9190614ab9565b91509150600080846140e45782846000036140ea565b83836000035b915091508a6001600160a01b03166000141561410c578c811461410c57600080fd5b509b9a5050505050505050505050565b60008061413361412c8587613c57565b8690613a45565b905082156141625761415a614150670de0b6b3a7640000836130e3565b6124ae8584613a0c565b915050610bac565b50929392505050565b6001600160a01b0382166141c6576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6141d2600083836125e6565b6002546141df90826126b5565b6002556001600160a01b03821660009081526020819052604090205461420590826126b5565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000818260140110156142b5576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b816014018351101561430e576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015614381576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156143da576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6143eb6148c8565b826001600160a01b0316846001600160a01b03161115614409579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b60006144458383614726565b9050336001600160a01b03821614610a7557600080fd5b60006144927f000000000000000000000000000000000000000000000000000000000000000061448d8686866143e3565b614726565b949350505050565b60008061452e7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a46000614822565b90506000600560019054906101000a90046001600160a01b03166001600160a01b031663978bbdb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561458057600080fd5b505afa158015614594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145b89190614cea565b90506145ca612710612bfc8484613caf565b9250505090565b6000806000806145e485600001516133c3565b919450925090506001600160a01b038083169084161060008061460886868661445c565b6001600160a01b031663128acb088b856146218f614710565b6001600160a01b038e1615614636578d61465c565b876146555773fffd8963efd1fc6a506488495d951d5263988d2561465c565b6401000276a45b8d60405160200161466d91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161469c959493929190615025565b6040805180830381600087803b1580156146b557600080fd5b505af11580156146c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146ed9190614ab9565b91509150826146fc57816146fe565b805b6000039b9a5050505050505050505050565b6000600160ff1b821061472257600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b03161061474e57600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b15801561489157600080fd5b505afa1580156148a5573d6000803e3d6000fd5b505050506040513d60208110156148bb57600080fd5b5051979650505050505050565b604080516060810182526000808252602082018190529181019190915290565b8035610ff2816155cd565b8035610ff2816155e2565b600082601f83011261490e578081fd5b813567ffffffffffffffff81111561492257fe5b614935601f8201601f19166020016155a9565b818152846020838601011115614949578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215614974578081fd5b6040516020810181811067ffffffffffffffff8211171561499157fe5b6040529151825250919050565b803562ffffff81168114610ff257600080fd5b803560ff81168114610ff257600080fd5b6000602082840312156149d3578081fd5b8135610bac816155cd565b6000602082840312156149ef578081fd5b8151610bac816155cd565b60008060408385031215614a0c578081fd5b8235614a17816155cd565b91506020830135614a27816155cd565b809150509250929050565b600080600060608486031215614a46578081fd5b8335614a51816155cd565b92506020840135614a61816155cd565b929592945050506040919091013590565b60008060408385031215614a84578182fd5b8235614a8f816155cd565b946020939093013593505050565b600060208284031215614aae578081fd5b8151610bac816155e2565b60008060408385031215614acb578182fd5b505080516020909101519092909150565b60008060008060608587031215614af1578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614b16578384fd5b818701915087601f830112614b29578384fd5b813581811115614b37578485fd5b886020828501011115614b48578485fd5b95989497505060200194505050565b600060208284031215614b68578081fd5b610bac8383614963565b600060208284031215614b83578081fd5b813567ffffffffffffffff80821115614b9a578283fd5b9083019060808286031215614bad578283fd5b604051608081018181108382111715614bc257fe5b604052823582811115614bd3578485fd5b614bdf878286016148fe565b825250614bee602084016148e8565b6020820152614bff604084016149b1565b6040820152606083013582811115614c15578485fd5b614c21878286016148fe565b60608301525095945050505050565b600060808284031215614c41578081fd5b6040516080810181811067ffffffffffffffff82111715614c5e57fe5b6040528251614c6c816155cd565b81526020830151614c7c816155f0565b602082015260408301516bffffffffffffffffffffffff81168114614c9f578283fd5b604082015260608301516fffffffffffffffffffffffffffffffff81168114614cc6578283fd5b60608201529392505050565b600060208284031215614ce3578081fd5b5035919050565b600060208284031215614cfb578081fd5b5051919050565b60008060408385031215614d14578182fd5b82359150614d246020840161499e565b90509250929050565b60008060008060808587031215614d42578182fd5b843593506020808601359350604080870135614d5d816155e2565b9350606087013567ffffffffffffffff80821115614d79578485fd5b818901915089601f830112614d8c578485fd5b813581811115614d9857fe5b614da585868302016155a9565b8181528581019250838601610140808402860188018e1015614dc5578889fd5b8895505b83861015614e6f5780828f031215614ddf578889fd5b614de8816155a9565b82358152614df78984016148e8565b89820152878301358882015260608301356060820152614e19608084016148f3565b608082015260a0838101359082015260c0808401359082015260e0614e3f8185016149b1565b90820152610100838101359082015261012080840135908201528552600195909501949387019390810190614dc9565b505080965050505050505092959194509250565b600080600060608486031215614e97578081fd5b8335925060208401359150614eae6040850161499e565b90509250925092565b600080600080600060a08688031215614ece578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b600060208284031215614f02578081fd5b8135610bac816155f0565b60008151808452815b81811015614f3257602081850181015186830182015201614f16565b81811115614f435782602083870101525b50601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b90815260200190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a060808301526124f660a0830184614f0d565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b039690961686526020860194909452604085019290925260608401521515608083015260a082015260c00190565b901515815260200190565b97885260208801969096526001600160a01b0394909416604087015260608601929092526080850152151560a084015260c083015260e08201526101000190565b600060208252610bac6020830184614f0d565b60208082526018908201527f616d6f756e74206f7574206c657373207468616e206d696e0000000000000000604082015260600190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b6020808252601a908201527f616d6f756e7420696e2067726561746572207468616e206d6178000000000000604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526027908201527f507269636520746f6f206c6f772072656c617469766520746f20556e6973776160408201527f7020747761702e00000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526204331360ec1b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526028908201527f507269636520746f6f20686967682072656c617469766520746f20556e69737760408201527f617020747761702e000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526243313160e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b602080825260029082015261433960f01b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b60208082526003908201526243323760e81b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b60006020825282516080602084015261550c60a0840182614f0d565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f1984830301608085015261340a8282614f0d565b918252602082015260400190565b938452602084019290925215156040830152606082015260800190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b60405181810167ffffffffffffffff811182821017156155c557fe5b604052919050565b6001600160a01b0381168114610b2257600080fd5b8015158114610b2257600080fd5b63ffffffff81168114610b2257600080fdfe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445434453413a20696e76616c6964207369676e6174757265202773272076616c756545434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212205588e36b593aca521cd7221641031ca4fe125d2300af7c70ba2abc8ce18bf28564736f6c63430007060033\",\n  \"deployedBytecode\": \"0x60806040526004361061036f5760003560e01c80637f07b130116101c6578063cae74029116100f7578063e9c3cb4f11610095578063f5d278e41161006f578063f5d278e41461095e578063f73e19c314610973578063fa461e3314610993578063fc5b73ff146109b3576103e1565b8063e9c3cb4f14610914578063f101d92f14610929578063f2fde38b1461093e576103e1565b8063d2dd9f79116100d1578063d2dd9f79146108ac578063d33219b4146108cc578063dcbab608146108e1578063dd62ed3e146108f4576103e1565b8063cae740291461087a578063cfa70b181461088f578063d0e30db0146108a4576103e1565b8063a457c2d711610164578063b52b7ff01161013e578063b52b7ff014610810578063bdd438b814610830578063c245168914610850578063c45a015514610865576103e1565b8063a457c2d7146107b0578063a9059cbb146107d0578063b24f719b146107f0576103e1565b80638f8b8dbc116101a05780638f8b8dbc1461074657806395d89b41146107665780639ff69a511461077b578063a319b29f1461079b576103e1565b80637f07b1301461070757806388626eb81461071c5780638da5cb5b14610731576103e1565b80633d65fdac116102a057806366a91b761161023e57806370a082311161021857806370a082311461069d578063715018a6146106bd5780637bcdc16e146106d25780637dc0d1d0146106f2576103e1565b806366a91b761461065e57806367b8c345146106735780636c1040a914610688576103e1565b80634d76e6fc1161027a5780634d76e6fc146105ef578063502e1a1614610604578063533092ef1461062457806363bbc4b614610649576103e1565b80633d65fdac146105a55780633dcb0c5d146105c55780633fc8cef3146105da576103e1565b8063313ce5671161030d578063392e53cd116102e7578063392e53cd1461052e5780633950935114610543578063395ebb69146105635780633d3a62ee14610585576103e1565b8063313ce567146104e257806333194c0a146105045780633644e51514610519576103e1565b806318160ddd1161034957806318160ddd1461045e57806323b872dd14610480578063281e78d1146104a05780632e1a7d4d146104c2576103e1565b806306fdde03146103e6578063095ea7b3146104115780630ca514cd1461043e576103e1565b366103e157336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103ba575060055461010090046001600160a01b031633145b6103df5760405162461bcd60e51b81526004016103d69061547e565b60405180910390fd5b005b600080fd5b3480156103f257600080fd5b506103fb6109c6565b604051610408919061511f565b60405180910390f35b34801561041d57600080fd5b5061043161042c366004614a72565b610a5d565b60405161040891906150d3565b34801561044a57600080fd5b506103df610459366004614cd2565b610a7b565b34801561046a57600080fd5b50610473610b25565b6040516104089190614fab565b34801561048c57600080fd5b5061043161049b366004614a32565b610b2b565b3480156104ac57600080fd5b506104b5610bb3565b6040516104089190614fb4565b3480156104ce57600080fd5b506103df6104dd366004614cd2565b610bd7565b3480156104ee57600080fd5b506104f7610cab565b604051610408919061559b565b34801561051057600080fd5b50610473610cb4565b34801561052557600080fd5b50610473610cd8565b34801561053a57600080fd5b50610431610ce7565b34801561054f57600080fd5b5061043161055e366004614a72565b610cf8565b34801561056f57600080fd5b50610578610d46565b604051610408919061558a565b34801561059157600080fd5b506103df6105a0366004614cd2565b610d4c565b3480156105b157600080fd5b506103df6105c0366004614cd2565b610ee4565b3480156105d157600080fd5b506104b5610f0a565b3480156105e657600080fd5b506104b5610f1e565b3480156105fb57600080fd5b506104b5610f42565b34801561061057600080fd5b5061043161061f366004614a72565b610f66565b34801561063057600080fd5b50610639610f86565b6040516104089493929190615078565b34801561065557600080fd5b50610473610fa2565b34801561066a57600080fd5b50610473610fa8565b34801561067f57600080fd5b50610473610fae565b34801561069457600080fd5b50610473610fb4565b3480156106a957600080fd5b506104736106b83660046149c2565b610fd8565b3480156106c957600080fd5b506103df610ff7565b3480156106de57600080fd5b506103df6106ed366004614cd2565b6110c2565b3480156106fe57600080fd5b506104b5611196565b34801561071357600080fd5b506104b56111ba565b34801561072857600080fd5b506104316111de565b34801561073d57600080fd5b506104b56111e8565b34801561075257600080fd5b506103df610761366004614ef1565b6111f7565b34801561077257600080fd5b506103fb6112d7565b34801561078757600080fd5b506103df610796366004614cd2565b611338565b3480156107a757600080fd5b506103df611409565b3480156107bc57600080fd5b506104316107cb366004614a72565b6114ca565b3480156107dc57600080fd5b506104316107eb366004614a72565b611532565b3480156107fc57600080fd5b506103df61080b366004614d2d565b611546565b34801561081c57600080fd5b506103df61082b366004614e83565b61184f565b34801561083c57600080fd5b506103df61084b366004614cd2565b611976565b34801561085c57600080fd5b50610431611a53565b34801561087157600080fd5b506104b5611a5d565b34801561088657600080fd5b50610473611a81565b34801561089b57600080fd5b50610473611a87565b6103df611a93565b3480156108b857600080fd5b506103df6108c73660046149c2565b611b3e565b3480156108d857600080fd5b506104b5611d25565b6103df6108ef366004614eb7565b611d49565b34801561090057600080fd5b5061047361090f3660046149fa565b611e0f565b34801561092057600080fd5b50610473611e3a565b34801561093557600080fd5b50610473611e40565b34801561094a57600080fd5b506103df6109593660046149c2565b611e46565b34801561096a57600080fd5b50610578611f68565b34801561097f57600080fd5b5061047361098e366004614cd2565b611f74565b34801561099f57600080fd5b506103df6109ae366004614adc565b611f7f565b6103df6109c1366004614d02565b612025565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b820191906000526020600020905b815481529060010190602001808311610a3557829003601f168201915b505050505090505b90565b6000610a71610a6a612172565b8484612176565b5060015b92915050565b610a83612172565b6001600160a01b0316610a946111e8565b6001600160a01b031614610aef576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff16610b195760405162461bcd60e51b81526004016103d6906151f7565b610b2281612262565b50565b60025490565b6000610b38848484612297565b610ba884610b44612172565b610ba385604051806060016040528060288152602001615734602891396001600160a01b038a16600090815260016020526040812090610b82612172565b6001600160a01b0316815260208101919091526040016000205491906123f2565b612176565b5060015b9392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60026006541415610c2f576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610c3f82612489565b90506000610c5033848460006124b4565b9050610c5c3382612501565b336001600160a01b03167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94848484604051610c9993929190615574565b60405180910390a25050600160065550565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce26125eb565b905090565b600a54640100000000900460ff1681565b6000610a71610d05612172565b84610ba38560016000610d16612172565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906126b5565b6101a481565b60026006541415610da4576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600681905550600560019054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610dfc57600080fd5b505af1158015610e10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e349190614a9d565b610e505760405162461bcd60e51b81526004016103d6906153ee565b600f5460ff16610e725760405162461bcd60e51b81526004016103d6906152aa565b6000610e8582610e80610b25565b61270f565b90506000610e93824761271b565b9050610e9f3384612727565b610ea93382612501565b336001600160a01b03167fe9ab9870b9093d99f8e981919f65ad09b7ae90ff80f1031639af9e0357eb9ed68483604051610c99929190615549565b33600090815260106020908152604080832093835292905220805460ff19166001179055565b60055461010090046001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b601060209081526000928352604080842090915290825290205460ff1681565b600080600080610f94612823565b935093509350935090919293565b600e5481565b600b5481565b600d5481565b7f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0381166000908152602081905260409020545b919050565b610fff612172565b6001600160a01b03166110106111e8565b6001600160a01b03161461106b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6007546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36007805473ffffffffffffffffffffffffffffffffffffffff19169055565b6110ca612172565b6001600160a01b03166110db6111e8565b6001600160a01b031614611136576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081116111565760405162461bcd60e51b81526004016103d69061540b565b600b8190556040517f28e0e4ee0b14d4b056ce88e1bcd890ccd32b22e213723c8765901381b5eae7059061118b908390614fab565b60405180910390a150565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce261291a565b6007546001600160a01b031690565b6111ff612172565b6001600160a01b03166112106111e8565b6001600160a01b03161461126b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60b48163ffffffff1610156112925760405162461bcd60e51b81526004016103d690615169565b600a805463ffffffff191663ffffffff83161790556040517f1cd9c7f99a5530a38c8f2b387dcc78e8a76cb5b203e0c4316a66777d993dee359061118b90839061558a565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b611340612172565b6001600160a01b03166113516111e8565b6001600160a01b0316146113ac576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6702c68af0bb1400008111156113d45760405162461bcd60e51b81526004016103d6906153d1565b60098190556040517f829c71710efa317bbdb8e5c4ca2b6d2551b7c2d7d37ea199975807eb3f5c0e7c9061118b908390614fab565b600a54640100000000900460ff166114335760405162461bcd60e51b81526004016103d6906151f7565b600f8054600160ff19909116179055600554604051634bf7d4a160e11b81526101009091046001600160a01b0316906397efa94290611496907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b600060405180830381600087803b1580156114b057600080fd5b505af11580156114c4573d6000803e3d6000fd5b50505050565b6000610a716114d7612172565b84610ba3856040518060600160405280602581526020016157c66025913960016000611501612172565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906123f2565b6000610a7161153f612172565b8484612297565b61154e612172565b6001600160a01b031661155f6111e8565b6001600160a01b0316146115ba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff166115e45760405162461bcd60e51b81526004016103d6906151f7565b600083116116045760405162461bcd60e51b81526004016103d690615398565b61160c612a90565b8061161a575061161a61291a565b6116365760405162461bcd60e51b81526004016103d690615444565b6116408383612ab1565b42600d55600e839055805184906000908390829061165a57fe5b602002602001015160600151905060008360008151811061167757fe5b602002602001015160600151905060008460008151811061169457fe5b602002602001015160800151905080151586151514156116c65760405162461bcd60e51b81526004016103d690615324565b60005b85518110156117ef578581815181106116de57fe5b60200260200101516060015192508115158682815181106116fb57fe5b6020026020010151608001511515146117265760405162461bcd60e51b81526004016103d690615427565b8615611751578383101561174c5760405162461bcd60e51b81526004016103d690615341565b611771565b838311156117715760405162461bcd60e51b81526004016103d690615341565b829350611792858988848151811061178557fe5b6020026020010151612c71565b85818151811061179e57fe5b6020026020010151604001518511156117e2576117db8682815181106117c057fe5b602002602001015160400151866130e390919063ffffffff16565b94506117e7565b6117ef565b6001016116c9565b507fbbc3ba742efe346cfdf333000069964e0ee3087c68da267dac977d299f2366fb8560008151811061181e57fe5b60200260200101516000015189888a60405161183d9493929190615557565b60405180910390a15050505050505050565b600260065414156118a7576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560006118b784612489565b90506119287f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084848760018a6040516020016119149190614fab565b60405160208183030381529060405261313b565b336001600160a01b03167fa13b272c1cf13ba724064d3d4809d9f557aab8da2bb582cba031a2f57e728e9d8583604051611963929190615549565b60405180910390a2505060016006555050565b61197e612172565b6001600160a01b031661198f6111e8565b6001600160a01b0316146119ea576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081118015611a025750670de0b6b3a76400008111155b611a1e5760405162461bcd60e51b81526004016103d6906154d4565b600c8190556040517f789e4b8ad1c375952cea7f07c9b3b6619a84b406432b948246cecb8ced96b9fa9061118b908390614fab565b6000610ce2612a90565b7f000000000000000000000000000000000000000000000000000000000000000081565b60085481565b6702c68af0bb14000081565b60026006541415611aeb576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065534600080611aff3384836131bc565b91509150336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158383604051610c99929190615549565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611b865760405162461bcd60e51b81526004016103d6906153b5565b600a54640100000000900460ff16611bb05760405162461bcd60e51b81526004016103d6906151f7565b600560019054906101000a90046001600160a01b03166001600160a01b0316639d4c94426040518163ffffffff1660e01b815260040160206040518083038186803b158015611bfe57600080fd5b505afa158015611c12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3691906149de565b6001600160a01b03166342842e0e30837f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401611c8593929190614fc8565b600060405180830381600087803b158015611c9f57600080fd5b505af1158015611cb3573d6000803e3d6000fd5b50505050611cc16000612262565b806001600160a01b03167fae97956757017853415251f661bfe857898f44ddb9c90b2483065719b84b0c697f0000000000000000000000000000000000000000000000000000000000000000604051611d1a9190614fab565b60405180910390a250565b7f000000000000000000000000000000000000000000000000000000000000000081565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611d915760405162461bcd60e51b81526004016103d69061528d565b600a54640100000000900460ff1615611dbc5760405162461bcd60e51b81526004016103d69061535e565b611dc581612262565b34611dd1816000613230565b600d849055600e839055611de8338783600061325f565b611df233866133b9565b5050600a805464ff00000000191664010000000017905550505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60095481565b600c5481565b611e4e612172565b6001600160a01b0316611e5f6111e8565b6001600160a01b031614611eba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611eff5760405162461bcd60e51b81526004018080602001828103825260268152602001806156486026913960400191505060405180910390fd5b6007546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600a5463ffffffff1681565b6000610a7582612489565b6000841380611f8e5750600083135b611f9757600080fd5b6000611fa582840184614b72565b90506000806000611fb984600001516133c3565b925092509250611feb7f00000000000000000000000000000000000000000000000000000000000000008484846133f4565b506000808913611ffb5787611ffd565b885b905061201a8560200151858585858a606001518b60400151613413565b505050505050505050565b6002600654141561207d576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560008061208d6138ec565b9150915061209b8482613230565b60006120a8858484613906565b5090506121237f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086846120fc8a346130e3565b60008b60405160200161210f9190614fab565b604051602081830303815290604052613995565b336001600160a01b03167f5d85169ff8329e90f3225f9798e0eba54d00c55d3bbfe201a0d1606febb23a8e868360405161215e929190615549565b60405180910390a250506001600655505050565b3390565b6001600160a01b0383166121bb5760405162461bcd60e51b81526004018080602001828103825260248152602001806157a26024913960400191505060405180910390fd5b6001600160a01b0382166122005760405162461bcd60e51b815260040180806020018281038252602281526020018061566e6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60088190556040517f29600e2e028c8c5c2b112d021938e0d0237d8fafcbb20394c56cf9fa4661ca279061118b908390614fab565b6001600160a01b0383166122dc5760405162461bcd60e51b815260040180806020018281038252602581526020018061577d6025913960400191505060405180910390fd5b6001600160a01b0382166123215760405162461bcd60e51b81526004018080602001828103825260238152602001806156036023913960400191505060405180910390fd5b61232c8383836125e6565b61236981604051806060016040528060268152602001615690602691396001600160a01b03861660009081526020819052604090205491906123f2565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461239890826126b5565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156124815760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561244657818101518382015260200161242e565b50505050905090810190601f1680156124735780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600080612494612823565b9350505050610bac6124a4610b25565b6124ae8386613a0c565b90613a45565b6000806124bf6138ec565b91505060006124d086610e80610b25565b905060006124de828461271b565b90506124ec88878388613a65565b6124f68888612727565b979650505050505050565b80471015612556576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146125a1576040519150601f19603f3d011682016040523d82523d6000602084013e6125a6565b606091505b50509050806125e65760405162461bcd60e51b815260040180806020018281038252603a8152602001806156b6603a913960400191505060405180910390fd5b505050565b60007f0000000000000000000000000000000000000000000000000000000000000000612616613b94565b141561264357507f0000000000000000000000000000000000000000000000000000000000000000610a5a565b6126ae7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000613b98565b9050610a5a565b600082820183811015610bac576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610bac8383613a45565b6000610bac8284613a0c565b6001600160a01b03821661276c5760405162461bcd60e51b815260040180806020018281038252602181526020018061575c6021913960400191505060405180910390fd5b612778826000836125e6565b6127b581604051806060016040528060228152602001615626602291396001600160a01b03851660009081526020819052604090205491906123f2565b6001600160a01b0383166000908152602081905260409020556002546127db9082613bfa565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600554604051634632752560e11b8152600091829182918291829161010090046001600160a01b031690638c64ea4a90612881907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b60806040518083038186803b15801561289957600080fd5b505afa1580156128ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d19190614c30565b805160208201516040830151606090930151919863ffffffff90911697506bffffffffffffffffffffffff90921695506fffffffffffffffffffffffffffffffff169350915050565b600a5460405163cce79bd560e01b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd5916129de917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff90911690600190600401614fec565b60206040518083038186803b1580156129f657600080fd5b505afa158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190614cea565b90506000612a47600e5483613a4590919063ffffffff16565b90506000670de0b6b3a76400008211612a7157612a6c670de0b6b3a7640000836130e3565b612a83565b612a8382670de0b6b3a76400006130e3565b600c541115935050505090565b6000612aa9600b54600d54613c5790919063ffffffff16565b421015905090565b600a5460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591612b71917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff1690600190600401614fec565b60206040518083038186803b158015612b8957600080fd5b505afa158015612b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc19190614cea565b90508115612c2657612c02670de0b6b3a7640000612bfc612bf5600954670de0b6b3a7640000613c5790919063ffffffff16565b8490613caf565b90613d1b565b831115612c215760405162461bcd60e51b81526004016103d6906152c7565b6125e6565b612c52670de0b6b3a7640000612bfc612bf5600954670de0b6b3a76400006130e390919063ffffffff16565b8310156125e65760405162461bcd60e51b81526004016103d690615230565b806080015115612ca4578060600151821115612c9f5760405162461bcd60e51b81526004016103d69061549a565b612cc8565b8060600151821015612cc85760405162461bcd60e51b81526004016103d69061537b565b612cda81602001518260c00151613d7a565b60007fc8aea8e60353611f3ed5409dad2d3173390bd252431198e7300eda67fefb66b1826000015183602001518460400151856060015186608001518760a001518860c00151604051602001612d379897969594939291906150de565b6040516020818303038152906040528051906020012090506000612d5a82613dee565b90506000612d78828560e00151866101000151876101200151613e3a565b905083602001516001600160a01b0316816001600160a01b031614612daf5760405162461bcd60e51b81526004016103d690615461565b428460a001511015612dd35760405162461bcd60e51b81526004016103d690615186565b8360400151861015612de757604084018690525b6000612e0c670de0b6b3a7640000612bfc888860400151613caf90919063ffffffff16565b9050846080015115612f575760208501516040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916323b872dd91612e6c919030908690600401614fc8565b602060405180830381600087803b158015612e8657600080fd5b505af1158015612e9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ebe9190614a9d565b50604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612f0b908490600401614fab565b600060405180830381600087803b158015612f2557600080fd5b505af1158015612f39573d6000803e3d6000fd5b50505050612f528560200151866040015183600061325f565b613085565b612f6c85602001518660400151836000613a65565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612fc757600080fd5b505af1158015612fdb573d6000803e3d6000fd5b50505050602086015160405163a9059cbb60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063a9059cbb9161303191859060040161505f565b602060405180830381600087803b15801561304b57600080fd5b505af115801561305f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130839190614a9d565b505b7f68c36f17c620d197a81d3aeff305f83abf3bb29943a38cd6efc299041238652d856020015186600001518760400151886060015189608001518b6040516130d29695949392919061509e565b60405180910390a150505050505050565b80820382811115610a75576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b60006131908530600060405180608001604052808c8c8f60405160200161316493929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052613faf565b9050838111156131b25760405162461bcd60e51b81526004016103d6906151c0565b5050505050505050565b6000806000806131ca6138ec565b915091506131d88682613230565b6000806131e6888585613906565b909250905060006132086131fa8a846130e3565b85613203610b25565b61411c565b90506132168a848b8b61325f565b6132208a826133b9565b9199919850909650505050505050565b60085461323d8284613c57565b111561325b5760405162461bcd60e51b81526004016103d690615213565b5050565b600554604051630728cf2360e31b81526101009091046001600160a01b03169063394679189084906132ba907f0000000000000000000000000000000000000000000000000000000000000000908890600090600401615574565b6020604051808303818588803b1580156132d357600080fd5b505af11580156132e7573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061330c9190614cea565b50806114c45760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613360908790879060040161505f565b602060405180830381600087803b15801561337a57600080fd5b505af115801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b29190614a9d565b5050505050565b61325b828261416b565b600080806133d1848261425b565b92506133de846014614327565b90506133eb84601761425b565b91509193909250565b600061340a856134058686866143e3565b614439565b95945050505050565b60008160ff16600181111561342457fe5b600181111561342f57fe5b14156136665760008280602001905181019061344b9190614b57565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906134a2903090600401614fb4565b60206040518083038186803b1580156134ba57600080fd5b505afa1580156134ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f29190614cea565b6040518263ffffffff1660e01b815260040161350e9190614fab565b600060405180830381600087803b15801561352857600080fd5b505af115801561353c573d6000803e3d6000fd5b5050505061355088826000015160016131bc565b5050600061355f88888861445c565b60405163a9059cbb60e01b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906135b0908490899060040161505f565b602060405180830381600087803b1580156135ca57600080fd5b505af11580156135de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136029190614a9d565b50886001600160a01b03167fc355ebece16d7e85e486911f0cde1074bc4bd3fec251c88cdddc7076d3e99adb864760405161363e929190615549565b60405180910390a2471561365f5761365f6001600160a01b038a1647612501565b50506138e3565b60018160ff16600181111561367757fe5b600181111561368257fe5b14156138e35760008280602001905181019061369e9190614b57565b9050600061374e8983600001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016136f79190614fb4565b60206040518083038186803b15801561370f57600080fd5b505afa158015613723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137479190614cea565b60016124b4565b9050600061375d89898961445c565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b1580156137ba57600080fd5b505af11580156137ce573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250613821915084908a9060040161505f565b602060405180830381600087803b15801561383b57600080fd5b505af115801561384f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138739190614a9d565b50600061388083886130e3565b90508a6001600160a01b03167f6f3269a64126ef2a1959892f3d921e81865181e09a7f72f55d3a49550c53b48d88836040516138bd929190615549565b60405180910390a280156138de576138de6001600160a01b038c1682612501565b505050505b50505050505050565b6000806000806138fa612823565b96509450505050509091565b60008060008061391461449a565b9050600086158015613924575085155b80156139365750613933610b25565b15155b905080156139565760405162461bcd60e51b81526004016103d6906151a3565b61397761396d6139668985613a0c565b8890613c57565b6124ae8a8a613a0c565b925060006139858484613a0c565b9399939850929650505050505050565b60006139ea8530600060405180608001604052808d8c8e6040516020016139be93929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526145d1565b9050838110156131b25760405162461bcd60e51b81526004016103d690615132565b6000670de0b6b3a7640000613a36613a248585613caf565b6002670de0b6b3a76400005b04613c57565b81613a3d57fe5b049392505050565b600081613a36613a5d85670de0b6b3a7640000613caf565b600285613a30565b80613b0e576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90613aba90879030908890600401614fc8565b602060405180830381600087803b158015613ad457600080fd5b505af1158015613ae8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b0c9190614a9d565b505b600554604051638632cb0360e01b81526101009091046001600160a01b031690638632cb0390613b66907f00000000000000000000000000000000000000000000000000000000000000009087908790600401615574565b600060405180830381600087803b158015613b8057600080fd5b505af11580156131b2573d6000803e3d6000fd5b4690565b6000838383613ba5613b94565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b600082821115613c51576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b80820182811015610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000811580613cca57505080820282828281613cc757fe5b04145b610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000808211613d71576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613a3d57fe5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff1615613dbe5760405162461bcd60e51b81526004016103d6906154b7565b6001600160a01b03909116600090815260106020908152604080832093835292905220805460ff19166001179055565b6000613df86125eb565b82604051602001808061190160f01b81525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613e9b5760405162461bcd60e51b81526004018080602001828103825260228152602001806156f06022913960400191505060405180910390fd5b8360ff16601b1480613eb057508360ff16601c145b613eeb5760405162461bcd60e51b81526004018080602001828103825260228152602001806157126022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613f47573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661340a576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b600080600080613fc285600001516133c3565b919450925090506001600160a01b0380841690831610600080613fe685878661445c565b6001600160a01b031663128acb088b85613fff8f614710565b6000036001600160a01b038e1615614017578d61403d565b876140365773fffd8963efd1fc6a506488495d951d5263988d2561403d565b6401000276a45b8d60405160200161404e91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161407d959493929190615025565b6040805180830381600087803b15801561409657600080fd5b505af11580156140aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140ce9190614ab9565b91509150600080846140e45782846000036140ea565b83836000035b915091508a6001600160a01b03166000141561410c578c811461410c57600080fd5b509b9a5050505050505050505050565b60008061413361412c8587613c57565b8690613a45565b905082156141625761415a614150670de0b6b3a7640000836130e3565b6124ae8584613a0c565b915050610bac565b50929392505050565b6001600160a01b0382166141c6576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6141d2600083836125e6565b6002546141df90826126b5565b6002556001600160a01b03821660009081526020819052604090205461420590826126b5565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000818260140110156142b5576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b816014018351101561430e576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015614381576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156143da576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6143eb6148c8565b826001600160a01b0316846001600160a01b03161115614409579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b60006144458383614726565b9050336001600160a01b03821614610a7557600080fd5b60006144927f000000000000000000000000000000000000000000000000000000000000000061448d8686866143e3565b614726565b949350505050565b60008061452e7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a46000614822565b90506000600560019054906101000a90046001600160a01b03166001600160a01b031663978bbdb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561458057600080fd5b505afa158015614594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145b89190614cea565b90506145ca612710612bfc8484613caf565b9250505090565b6000806000806145e485600001516133c3565b919450925090506001600160a01b038083169084161060008061460886868661445c565b6001600160a01b031663128acb088b856146218f614710565b6001600160a01b038e1615614636578d61465c565b876146555773fffd8963efd1fc6a506488495d951d5263988d2561465c565b6401000276a45b8d60405160200161466d91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161469c959493929190615025565b6040805180830381600087803b1580156146b557600080fd5b505af11580156146c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146ed9190614ab9565b91509150826146fc57816146fe565b805b6000039b9a5050505050505050505050565b6000600160ff1b821061472257600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b03161061474e57600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b15801561489157600080fd5b505afa1580156148a5573d6000803e3d6000fd5b505050506040513d60208110156148bb57600080fd5b5051979650505050505050565b604080516060810182526000808252602082018190529181019190915290565b8035610ff2816155cd565b8035610ff2816155e2565b600082601f83011261490e578081fd5b813567ffffffffffffffff81111561492257fe5b614935601f8201601f19166020016155a9565b818152846020838601011115614949578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215614974578081fd5b6040516020810181811067ffffffffffffffff8211171561499157fe5b6040529151825250919050565b803562ffffff81168114610ff257600080fd5b803560ff81168114610ff257600080fd5b6000602082840312156149d3578081fd5b8135610bac816155cd565b6000602082840312156149ef578081fd5b8151610bac816155cd565b60008060408385031215614a0c578081fd5b8235614a17816155cd565b91506020830135614a27816155cd565b809150509250929050565b600080600060608486031215614a46578081fd5b8335614a51816155cd565b92506020840135614a61816155cd565b929592945050506040919091013590565b60008060408385031215614a84578182fd5b8235614a8f816155cd565b946020939093013593505050565b600060208284031215614aae578081fd5b8151610bac816155e2565b60008060408385031215614acb578182fd5b505080516020909101519092909150565b60008060008060608587031215614af1578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614b16578384fd5b818701915087601f830112614b29578384fd5b813581811115614b37578485fd5b886020828501011115614b48578485fd5b95989497505060200194505050565b600060208284031215614b68578081fd5b610bac8383614963565b600060208284031215614b83578081fd5b813567ffffffffffffffff80821115614b9a578283fd5b9083019060808286031215614bad578283fd5b604051608081018181108382111715614bc257fe5b604052823582811115614bd3578485fd5b614bdf878286016148fe565b825250614bee602084016148e8565b6020820152614bff604084016149b1565b6040820152606083013582811115614c15578485fd5b614c21878286016148fe565b60608301525095945050505050565b600060808284031215614c41578081fd5b6040516080810181811067ffffffffffffffff82111715614c5e57fe5b6040528251614c6c816155cd565b81526020830151614c7c816155f0565b602082015260408301516bffffffffffffffffffffffff81168114614c9f578283fd5b604082015260608301516fffffffffffffffffffffffffffffffff81168114614cc6578283fd5b60608201529392505050565b600060208284031215614ce3578081fd5b5035919050565b600060208284031215614cfb578081fd5b5051919050565b60008060408385031215614d14578182fd5b82359150614d246020840161499e565b90509250929050565b60008060008060808587031215614d42578182fd5b843593506020808601359350604080870135614d5d816155e2565b9350606087013567ffffffffffffffff80821115614d79578485fd5b818901915089601f830112614d8c578485fd5b813581811115614d9857fe5b614da585868302016155a9565b8181528581019250838601610140808402860188018e1015614dc5578889fd5b8895505b83861015614e6f5780828f031215614ddf578889fd5b614de8816155a9565b82358152614df78984016148e8565b89820152878301358882015260608301356060820152614e19608084016148f3565b608082015260a0838101359082015260c0808401359082015260e0614e3f8185016149b1565b90820152610100838101359082015261012080840135908201528552600195909501949387019390810190614dc9565b505080965050505050505092959194509250565b600080600060608486031215614e97578081fd5b8335925060208401359150614eae6040850161499e565b90509250925092565b600080600080600060a08688031215614ece578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b600060208284031215614f02578081fd5b8135610bac816155f0565b60008151808452815b81811015614f3257602081850181015186830182015201614f16565b81811115614f435782602083870101525b50601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b90815260200190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a060808301526124f660a0830184614f0d565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b039690961686526020860194909452604085019290925260608401521515608083015260a082015260c00190565b901515815260200190565b97885260208801969096526001600160a01b0394909416604087015260608601929092526080850152151560a084015260c083015260e08201526101000190565b600060208252610bac6020830184614f0d565b60208082526018908201527f616d6f756e74206f7574206c657373207468616e206d696e0000000000000000604082015260600190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b6020808252601a908201527f616d6f756e7420696e2067726561746572207468616e206d6178000000000000604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526027908201527f507269636520746f6f206c6f772072656c617469766520746f20556e6973776160408201527f7020747761702e00000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526204331360ec1b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526028908201527f507269636520746f6f20686967682072656c617469766520746f20556e69737760408201527f617020747761702e000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526243313160e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b602080825260029082015261433960f01b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b60208082526003908201526243323760e81b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b60006020825282516080602084015261550c60a0840182614f0d565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f1984830301608085015261340a8282614f0d565b918252602082015260400190565b938452602084019290925215156040830152606082015260800190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b60405181810167ffffffffffffffff811182821017156155c557fe5b604052919050565b6001600160a01b0381168114610b2257600080fd5b8015158114610b2257600080fd5b63ffffffff81168114610b2257600080fdfe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445434453413a20696e76616c6964207369676e6174757265202773272076616c756545434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212205588e36b593aca521cd7221641031ca4fe125d2300af7c70ba2abc8ce18bf28564736f6c63430007060033\",\n  \"devdoc\": {\n    \"author\": \"Opyn team\",\n    \"details\": \"CrabStrategyV2 contract\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"DOMAIN_SEPARATOR()\": {\n        \"details\": \"view function to get the domain seperator used in signing\"\n      },\n      \"allowance(address,address)\": {\n        \"details\": \"See {IERC20-allowance}.\"\n      },\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC20-balanceOf}.\"\n      },\n      \"checkPriceHedge()\": {\n        \"returns\": {\n          \"_0\": \"true if hedging is allowed\"\n        }\n      },\n      \"checkTimeHedge()\": {\n        \"returns\": {\n          \"_0\": \"true if hedging is allowed\"\n        }\n      },\n      \"constructor\": {\n        \"details\": \"this will open a vault in the power token contract and store the vault ID\",\n        \"params\": {\n          \"_crabMigration\": \"crab migration contract address\",\n          \"_ethWSqueethPool\": \"eth:wSqueeth uniswap pool address\",\n          \"_hedgePriceThreshold\": \"hedge price threshold (0.1*1e18 = 10%)\",\n          \"_hedgeTimeThreshold\": \"hedge time threshold (seconds)\",\n          \"_oracle\": \"oracle address\",\n          \"_timelock\": \"timelock contract address\",\n          \"_uniswapFactory\": \"uniswap factory address\",\n          \"_wSqueethController\": \"power token controller address\",\n          \"_weth\": \"weth address\"\n        }\n      },\n      \"decimals()\": {\n        \"details\": \"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"\n      },\n      \"decreaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"\n      },\n      \"deposit()\": {\n        \"details\": \"provide ETH, return wSqueeth and strategy token\"\n      },\n      \"flashDeposit(uint256,uint24)\": {\n        \"details\": \"this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth_ethToDeposit must be less than msg.value plus the proceeds from the flash swapthe difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\",\n        \"params\": {\n          \"_ethToDeposit\": \"total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\",\n          \"_poolFee\": \"Uniswap pool fee\"\n        }\n      },\n      \"flashWithdraw(uint256,uint256,uint24)\": {\n        \"details\": \"this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\",\n        \"params\": {\n          \"_crabAmount\": \"strategy token amount to burn\",\n          \"_maxEthToPay\": \"maximum ETH to pay to buy back the wSqueeth debt\",\n          \"_poolFee\": \"Uniswap pool fee\"\n        }\n      },\n      \"getStrategyVaultId()\": {\n        \"returns\": {\n          \"_0\": \"vault ID\"\n        }\n      },\n      \"getVaultDetails()\": {\n        \"returns\": {\n          \"_0\": \"operator\",\n          \"_1\": \"nft collateral id\",\n          \"_2\": \"collateral amount\",\n          \"_3\": \"short amount\"\n        }\n      },\n      \"getWsqueethFromCrabAmount(uint256)\": {\n        \"params\": {\n          \"_crabAmount\": \"strategy token amount\"\n        },\n        \"returns\": {\n          \"_0\": \"wSqueeth amount\"\n        }\n      },\n      \"hedgeOTC(uint256,uint256,bool,(uint256,address,uint256,uint256,bool,uint256,uint256,uint8,bytes32,bytes32)[])\": {\n        \"details\": \"hedge function to reduce delta using an array of signed orders\",\n        \"params\": {\n          \"_clearingPrice\": \"clearing price in weth\",\n          \"_isHedgeBuying\": \"direction of hedge trade\",\n          \"_orders\": \"an array of signed order to swap tokens\",\n          \"_totalQuantity\": \"quantity the manager wants to trade\"\n        }\n      },\n      \"increaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"initialize(uint256,uint256,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_crabSharesToMint\": \"crab shares to mint\",\n          \"_priceAtLastHedge\": \"price at last hedge for crab V1\",\n          \"_strategyCap\": \"strategy cap for crab V2\",\n          \"_timeAtLastHedge\": \"time at last hedge for crab V1\",\n          \"_wSqueethToMint\": \"amount of wPowerPerp to mint\"\n        }\n      },\n      \"name()\": {\n        \"details\": \"Returns the name of the token.\"\n      },\n      \"owner()\": {\n        \"details\": \"Returns the address of the current owner.\"\n      },\n      \"redeemShortShutdown()\": {\n        \"details\": \"needs to be called before users can exit strategy using withdrawShutdown\"\n      },\n      \"renounceOwnership()\": {\n        \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n      },\n      \"setHedgePriceThreshold(uint256)\": {\n        \"params\": {\n          \"_hedgePriceThreshold\": \"the hedge price threshold, in percent, scaled by 1e18\"\n        }\n      },\n      \"setHedgeTimeThreshold(uint256)\": {\n        \"params\": {\n          \"_hedgeTimeThreshold\": \"the hedge time threshold, in seconds\"\n        }\n      },\n      \"setHedgingTwapPeriod(uint32)\": {\n        \"params\": {\n          \"_hedgingTwapPeriod\": \"the twap period, in seconds\"\n        }\n      },\n      \"setNonceTrue(uint256)\": {\n        \"params\": {\n          \"_nonce\": \"the number to be set true\"\n        }\n      },\n      \"setOTCPriceTolerance(uint256)\": {\n        \"params\": {\n          \"_otcPriceTolerance\": \"the OTC price tolerance, in percent, scaled by 1e18\"\n        }\n      },\n      \"setStrategyCap(uint256)\": {\n        \"details\": \"deposits are rejected if it would put the strategy above the cap amountstrategy collateral can be above the cap amount due to hedging activities\",\n        \"params\": {\n          \"_capAmount\": \"the maximum strategy collateral in ETH, checked on deposits\"\n        }\n      },\n      \"symbol()\": {\n        \"details\": \"Returns the symbol of the token, usually a shorter version of the name.\"\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC20-totalSupply}.\"\n      },\n      \"transfer(address,uint256)\": {\n        \"details\": \"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"\n      },\n      \"transferOwnership(address)\": {\n        \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n      },\n      \"transferVault(address)\": {\n        \"details\": \"strategy cap is set to 0 to avoid future deposits\",\n        \"params\": {\n          \"_newStrategy\": \"new strategy contract address\"\n        }\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"params\": {\n          \"_data\": \"callback data encoded as SwapCallbackData struct\",\n          \"amount0Delta\": \"amount of token0\",\n          \"amount1Delta\": \"amount of token1\"\n        }\n      },\n      \"withdraw(uint256)\": {\n        \"details\": \"provide strategy tokens and wSqueeth, returns ETH\",\n        \"params\": {\n          \"_crabAmount\": \"amount of strategy token to burn\"\n        }\n      },\n      \"withdrawShutdown(uint256)\": {\n        \"params\": {\n          \"_crabAmount\": \"amount of strategy token to burn\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"ONE\": {\n        \"details\": \"basic unit used for calculation\"\n      },\n      \"POWER_PERP_PERIOD\": {\n        \"details\": \"the TWAP_PERIOD used in the PowerPerp Controller contract\"\n      },\n      \"_CRAB_BALANCE_TYPEHASH\": {\n        \"details\": \"typehash for signed orders\"\n      },\n      \"ethWSqueethPool\": {\n        \"details\": \"ETH:wSqueeth uniswap pool\"\n      },\n      \"hasRedeemedInShutdown\": {\n        \"details\": \"set to true when redeemShortShutdown has been called\"\n      },\n      \"hedgePriceThreshold\": {\n        \"details\": \"price movement to trigger a hedge (0.1*1e18 = 10%)\"\n      },\n      \"hedgeTimeThreshold\": {\n        \"details\": \"time difference to trigger a hedge (seconds)\"\n      },\n      \"hedgingTwapPeriod\": {\n        \"details\": \"twap period to use for hedge calculations\"\n      },\n      \"isInitialized\": {\n        \"details\": \"true if CrabV2 was initialized\"\n      },\n      \"nonces\": {\n        \"details\": \"store the used flag for a nonce for each address\"\n      },\n      \"oracle\": {\n        \"details\": \"strategy uniswap oracle\"\n      },\n      \"priceAtLastHedge\": {\n        \"details\": \"wSqueeth/Eth price when last hedge executed\"\n      },\n      \"strategyCap\": {\n        \"details\": \"the cap in ETH for the strategy, above which deposits will be rejected\"\n      },\n      \"timeAtLastHedge\": {\n        \"details\": \"timestamp when last hedge executed\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"checkPriceHedge()\": {\n        \"notice\": \"check if hedging based on price threshold is allowed\"\n      },\n      \"checkTimeHedge()\": {\n        \"notice\": \"check if hedging based on time threshold is allowed\"\n      },\n      \"constructor\": {\n        \"notice\": \"strategy constructor\"\n      },\n      \"deposit()\": {\n        \"notice\": \"deposit ETH into strategy\"\n      },\n      \"flashDeposit(uint256,uint24)\": {\n        \"notice\": \"flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\"\n      },\n      \"flashWithdraw(uint256,uint256,uint24)\": {\n        \"notice\": \"flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\"\n      },\n      \"getStrategyVaultId()\": {\n        \"notice\": \"get power token strategy vault ID \"\n      },\n      \"getVaultDetails()\": {\n        \"notice\": \"get the vault composition of the strategy \"\n      },\n      \"getWsqueethFromCrabAmount(uint256)\": {\n        \"notice\": \"get wSqueeth debt amount associated with strategy token amount\"\n      },\n      \"initialize(uint256,uint256,uint256,uint256,uint256)\": {\n        \"notice\": \"initializes the collateral ratio after the first migration\"\n      },\n      \"redeemShortShutdown()\": {\n        \"notice\": \"called to redeem the net value of a vault post shutdown\"\n      },\n      \"setHedgePriceThreshold(uint256)\": {\n        \"notice\": \"owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\"\n      },\n      \"setHedgeTimeThreshold(uint256)\": {\n        \"notice\": \"owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\"\n      },\n      \"setHedgingTwapPeriod(uint32)\": {\n        \"notice\": \"owner can set the twap period in seconds that is used for calculating twaps for hedging\"\n      },\n      \"setNonceTrue(uint256)\": {\n        \"notice\": \"set nonce to true\"\n      },\n      \"setOTCPriceTolerance(uint256)\": {\n        \"notice\": \"owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\"\n      },\n      \"setStrategyCap(uint256)\": {\n        \"notice\": \"owner can set the strategy cap in ETH collateral terms\"\n      },\n      \"transferVault(address)\": {\n        \"notice\": \"transfer vault NFT to new contract\"\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"notice\": \"uniswap swap callback function for flashes\"\n      },\n      \"withdraw(uint256)\": {\n        \"notice\": \"withdraw WETH from strategy\"\n      },\n      \"withdrawShutdown(uint256)\": {\n        \"notice\": \"called to exit a vault if the Squeeth Power Perp contracts are shutdown\"\n      }\n    },\n    \"notice\": \"Contract for Crab strategy\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 881,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_balances\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 887,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_allowances\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n      },\n      {\n        \"astId\": 889,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_totalSupply\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 891,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 893,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 895,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_decimals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint8\"\n      },\n      {\n        \"astId\": 27353,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"powerTokenController\",\n        \"offset\": 1,\n        \"slot\": \"5\",\n        \"type\": \"t_contract(IController)11604\"\n      },\n      {\n        \"astId\": 4176,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_owner\",\n        \"offset\": 0,\n        \"slot\": \"7\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 25366,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"strategyCap\",\n        \"offset\": 0,\n        \"slot\": \"8\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25380,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"otcPriceTolerance\",\n        \"offset\": 0,\n        \"slot\": \"9\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25387,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hedgingTwapPeriod\",\n        \"offset\": 0,\n        \"slot\": \"10\",\n        \"type\": \"t_uint32\"\n      },\n      {\n        \"astId\": 25390,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"isInitialized\",\n        \"offset\": 4,\n        \"slot\": \"10\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 25412,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hedgeTimeThreshold\",\n        \"offset\": 0,\n        \"slot\": \"11\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25415,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hedgePriceThreshold\",\n        \"offset\": 0,\n        \"slot\": \"12\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25418,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"timeAtLastHedge\",\n        \"offset\": 0,\n        \"slot\": \"13\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25421,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"priceAtLastHedge\",\n        \"offset\": 0,\n        \"slot\": \"14\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25424,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hasRedeemedInShutdown\",\n        \"offset\": 0,\n        \"slot\": \"15\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 25431,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"nonces\",\n        \"offset\": 0,\n        \"slot\": \"16\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_uint256,t_bool))\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_contract(IController)11604\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"contract IController\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => uint256))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_uint256)\"\n      },\n      \"t_mapping(t_address,t_mapping(t_uint256,t_bool))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(uint256 => bool))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_uint256,t_bool)\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_mapping(t_uint256,t_bool)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => bool)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_bool\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint32\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint32\",\n        \"numberOfBytes\": \"4\"\n      },\n      \"t_uint8\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint8\",\n        \"numberOfBytes\": \"1\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/MockErc20.json",
    "content": "{\n  \"address\": \"0x306bf03b689f7d7e5e9D3aAC87a068F16AFF9482\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_name\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_symbol\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"_decimals\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"MinterBlacklisted\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"MinterWhitelisted\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"blacklistMinter\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burn\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"subtractedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"decreaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"addedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"increaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"isWhitelistedMinter\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"mint\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"whitelistMinter\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x4fa1253cbd721d0ed0e0dc26d71fe13bd088629a621bf62167a774ea46f36f34\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x306bf03b689f7d7e5e9D3aAC87a068F16AFF9482\",\n    \"transactionIndex\": 59,\n    \"gasUsed\": \"1208391\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000801000000000000000000000000000800400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000002000000000000000000000000004000000020000000000000000000000000000000000800000000000000000000000000000000\",\n    \"blockHash\": \"0x32b2f4e18dab9794de90cc89871219f177d2c785dc0ab5d2cb846bd742c2b448\",\n    \"transactionHash\": \"0x4fa1253cbd721d0ed0e0dc26d71fe13bd088629a621bf62167a774ea46f36f34\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 59,\n        \"blockNumber\": 8006325,\n        \"transactionHash\": \"0x4fa1253cbd721d0ed0e0dc26d71fe13bd088629a621bf62167a774ea46f36f34\",\n        \"address\": \"0x306bf03b689f7d7e5e9D3aAC87a068F16AFF9482\",\n        \"topics\": [\n          \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000006326a0dfe0517ff46af3ad16bc40c26c26397f9e\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 140,\n        \"blockHash\": \"0x32b2f4e18dab9794de90cc89871219f177d2c785dc0ab5d2cb846bd742c2b448\"\n      }\n    ],\n    \"blockNumber\": 8006325,\n    \"cumulativeGasUsed\": \"14483750\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"OpynUSDC\",\n    \"OpynUSDC\",\n    6\n  ],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_name\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_symbol\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"_decimals\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"MinterBlacklisted\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"MinterWhitelisted\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"blacklistMinter\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burn\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"subtractedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"decreaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"addedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"increaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"isWhitelistedMinter\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mint\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"whitelistMinter\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"allowance(address,address)\\\":{\\\"details\\\":\\\"See {IERC20-allowance}.\\\"},\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC20-balanceOf}.\\\"},\\\"blacklistMinter(address)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"address of minter to be blacklisted\\\"}},\\\"decimals()\\\":{\\\"details\\\":\\\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\\\"},\\\"decreaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\\\"},\\\"increaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\\\"},\\\"isWhitelistedMinter(address)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"address of minter\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"boolean, True if address is a whitelisted minter\\\"}},\\\"name()\\\":{\\\"details\\\":\\\"Returns the name of the token.\\\"},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"symbol()\\\":{\\\"details\\\":\\\"Returns the symbol of the token, usually a shorter version of the name.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC20-totalSupply}.\\\"},\\\"transfer(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\\\"},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"whitelistMinter(address)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"address of minter to be whitelisted\\\"}}},\\\"stateVariables\\\":{\\\"whitelistedMinters\\\":{\\\"details\\\":\\\"mapping to track whitelisted minters\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"events\\\":{\\\"MinterBlacklisted(address)\\\":{\\\"notice\\\":\\\"emits an event when a minter is blacklisted \\\"},\\\"MinterWhitelisted(address)\\\":{\\\"notice\\\":\\\"emits an event when a minter is whitelisted \\\"}},\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"blacklistMinter(address)\\\":{\\\"notice\\\":\\\"allow the minter to blacklist other minters\\\"},\\\"isWhitelistedMinter(address)\\\":{\\\"notice\\\":\\\"check if a minter is whitelisted\\\"},\\\"whitelistMinter(address)\\\":{\\\"notice\\\":\\\"allows the minter to whitelist other minters\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/mocks/MockErc20.sol\\\":\\\"MockErc20\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/mocks/MockErc20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\n\\\\ncontract MockErc20 is ERC20, Ownable {\\\\n\\\\n    /// @dev mapping to track whitelisted minters\\\\n    mapping(address => bool) internal whitelistedMinters;\\\\n    \\\\n    /// @notice emits an event when a minter is whitelisted \\\\n    event MinterWhitelisted(address indexed account );\\\\n\\\\n    /// @notice emits an event when a minter is blacklisted \\\\n    event MinterBlacklisted(address indexed account);\\\\n    \\\\n\\\\n    /**\\\\n     * @notice check if the sender is whitelistd\\\\n     */\\\\n    modifier onlyWhitelisted() {\\\\n        require(\\\\n            whitelistedMinters[msg.sender] || msg.sender == owner(),\\\\n            \\\\\\\"Address not a whitelisted minter\\\\\\\"\\\\n        );\\\\n        _;\\\\n    }\\\\n\\\\n    constructor(\\\\n        string memory _name,\\\\n        string memory _symbol,\\\\n        uint8 _decimals\\\\n    ) ERC20(_name, _symbol) {\\\\n        _setupDecimals(_decimals);\\\\n    }\\\\n\\\\n    function mint(address _account, uint256 _amount) external onlyWhitelisted {\\\\n        _mint(_account, _amount);\\\\n    }\\\\n\\\\n    function burn(address _account, uint256 _amount) external onlyWhitelisted {\\\\n        _burn(_account, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a minter is whitelisted\\\\n     * @param _account address of minter\\\\n     * @return boolean, True if address is a whitelisted minter\\\\n     */\\\\n    function isWhitelistedMinter(address _account) external view returns (bool) {\\\\n        return whitelistedMinters[_account];\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice allows the minter to whitelist other minters\\\\n     * @param _account address of minter to be whitelisted\\\\n     */\\\\n    function whitelistMinter(address _account) external onlyWhitelisted {\\\\n        whitelistedMinters[_account] = true;\\\\n\\\\n        emit MinterWhitelisted(_account);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice allow the minter to blacklist other minters\\\\n     * @param _account address of minter to be blacklisted\\\\n     */\\\\n    function blacklistMinter(address _account) external onlyWhitelisted {\\\\n        whitelistedMinters[_account] = false;\\\\n\\\\n        emit MinterBlacklisted(_account);\\\\n    }\\\\n\\\\n\\\\n  \\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1042bc59ae9e98b76a3fb45f1419a7cc1cdc958a0192d4c1c1fce21135467607\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60806040523480156200001157600080fd5b506040516200169238038062001692833981810160405260608110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200010a57600080fd5b9083019060208201858111156200012057600080fd5b82516401000000008111828201881017156200013b57600080fd5b82525081516020918201929091019080838360005b838110156200016a57818101518382015260200162000150565b50505050905090810190601f168015620001985780820380516001836020036101000a031916815260200191505b5060405260209081015185519093508592508491620001bd9160039185019062000273565b508051620001d390600490602084019062000273565b50506005805460ff19166012179055506000620001ef62000259565b60058054610100600160a81b0319166101006001600160a01b03841690810291909117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35062000250816200025d565b5050506200031f565b3390565b6005805460ff191660ff92909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620002ab5760008555620002f6565b82601f10620002c657805160ff1916838001178555620002f6565b82800160010185558215620002f6579182015b82811115620002f6578251825591602001919060010190620002d9565b506200030492915062000308565b5090565b5b8082111562000304576000815560010162000309565b611363806200032f6000396000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063715018a6116100cd578063a457c2d711610081578063dd62ed3e11610066578063dd62ed3e14610405578063e5affcb814610433578063f2fde38b1461045957610151565b8063a457c2d7146103ad578063a9059cbb146103d957610151565b806395d89b41116100b257806395d89b41146103535780639bb257ad1461035b5780639dc29fac1461038157610151565b8063715018a6146103275780638da5cb5b1461032f57610151565b8063313ce5671161012457806340c10f191161010957806340c10f19146102ad578063555c3002146102db57806370a082311461030157610151565b8063313ce56714610263578063395093511461028157610151565b806306fdde0314610156578063095ea7b3146101d357806318160ddd1461021357806323b872dd1461022d575b600080fd5b61015e61047f565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610198578181015183820152602001610180565b50505050905090810190601f1680156101c55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101ff600480360360408110156101e957600080fd5b506001600160a01b038135169060200135610515565b604080519115158252519081900360200190f35b61021b610532565b60408051918252519081900360200190f35b6101ff6004803603606081101561024357600080fd5b506001600160a01b03813581169160208101359091169060400135610538565b61026b6105bf565b6040805160ff9092168252519081900360200190f35b6101ff6004803603604081101561029757600080fd5b506001600160a01b0381351690602001356105c8565b6102d9600480360360408110156102c357600080fd5b506001600160a01b038135169060200135610616565b005b6101ff600480360360208110156102f157600080fd5b50356001600160a01b03166106ab565b61021b6004803603602081101561031757600080fd5b50356001600160a01b03166106c9565b6102d96106e4565b6103376107b5565b604080516001600160a01b039092168252519081900360200190f35b61015e6107c9565b6102d96004803603602081101561037157600080fd5b50356001600160a01b031661082a565b6102d96004803603604081101561039757600080fd5b506001600160a01b0381351690602001356108fd565b6101ff600480360360408110156103c357600080fd5b506001600160a01b03813516906020013561098e565b6101ff600480360360408110156103ef57600080fd5b506001600160a01b0381351690602001356109f6565b61021b6004803603604081101561041b57600080fd5b506001600160a01b0381358116916020013516610a0a565b6102d96004803603602081101561044957600080fd5b50356001600160a01b0316610a35565b6102d96004803603602081101561046f57600080fd5b50356001600160a01b0316610b05565b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561050b5780601f106104e05761010080835404028352916020019161050b565b820191906000526020600020905b8154815290600101906020018083116104ee57829003601f168201915b5050505050905090565b6000610529610522610c32565b8484610c36565b50600192915050565b60025490565b6000610545848484610d22565b6105b584610551610c32565b6105b085604051806060016040528060288152602001611277602891396001600160a01b038a1660009081526001602052604081209061058f610c32565b6001600160a01b031681526020810191909152604001600020549190610e7d565b610c36565b5060019392505050565b60055460ff1690565b60006105296105d5610c32565b846105b085600160006105e6610c32565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610f14565b3360009081526006602052604090205460ff168061064c57506106376107b5565b6001600160a01b0316336001600160a01b0316145b61069d576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6106a78282610f75565b5050565b6001600160a01b031660009081526006602052604090205460ff1690565b6001600160a01b031660009081526020819052604090205490565b6106ec610c32565b6001600160a01b03166106fd6107b5565b6001600160a01b031614610758576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60055460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36005805474ffffffffffffffffffffffffffffffffffffffff0019169055565b60055461010090046001600160a01b031690565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561050b5780601f106104e05761010080835404028352916020019161050b565b3360009081526006602052604090205460ff1680610860575061084b6107b5565b6001600160a01b0316336001600160a01b0316145b6108b1576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b038116600081815260066020526040808220805460ff19166001179055517feb61edd6570e8798f968e1e8c0114e1e25557b015c7ac44f7aeaf4a67ef3bc239190a250565b3360009081526006602052604090205460ff1680610933575061091e6107b5565b6001600160a01b0316336001600160a01b0316145b610984576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6106a78282611065565b600061052961099b610c32565b846105b08560405180606001604052806025815260200161130960259139600160006109c5610c32565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610e7d565b6000610529610a03610c32565b8484610d22565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3360009081526006602052604090205460ff1680610a6b5750610a566107b5565b6001600160a01b0316336001600160a01b0316145b610abc576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b038116600081815260066020526040808220805460ff19169055517feedc52ad501f0ddd2dca82b61f1b96f1f84b898d242eced1210037c8a569074e9190a250565b610b0d610c32565b6001600160a01b0316610b1e6107b5565b6001600160a01b031614610b79576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116610bbe5760405162461bcd60e51b81526004018080602001828103825260268152602001806112096026913960400191505060405180910390fd5b6005546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600580546001600160a01b039092166101000274ffffffffffffffffffffffffffffffffffffffff0019909216919091179055565b3390565b6001600160a01b038316610c7b5760405162461bcd60e51b81526004018080602001828103825260248152602001806112e56024913960400191505060405180910390fd5b6001600160a01b038216610cc05760405162461bcd60e51b815260040180806020018281038252602281526020018061122f6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610d675760405162461bcd60e51b81526004018080602001828103825260258152602001806112c06025913960400191505060405180910390fd5b6001600160a01b038216610dac5760405162461bcd60e51b81526004018080602001828103825260238152602001806111c46023913960400191505060405180910390fd5b610db7838383611161565b610df481604051806060016040528060268152602001611251602691396001600160a01b0386166000908152602081905260409020549190610e7d565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610e239082610f14565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610f0c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610ed1578181015183820152602001610eb9565b50505050905090810190601f168015610efe5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610f6e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610fd0576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610fdc60008383611161565b600254610fe99082610f14565b6002556001600160a01b03821660009081526020819052604090205461100f9082610f14565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b0382166110aa5760405162461bcd60e51b815260040180806020018281038252602181526020018061129f6021913960400191505060405180910390fd5b6110b682600083611161565b6110f3816040518060600160405280602281526020016111e7602291396001600160a01b0385166000908152602081905260409020549190610e7d565b6001600160a01b0383166000908152602081905260409020556002546111199082611166565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b505050565b6000828211156111bd576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220a39fba253f0b337163e8189855d1b968a7dc60c9ff4c9b34746d175c58e3cc8c64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101515760003560e01c8063715018a6116100cd578063a457c2d711610081578063dd62ed3e11610066578063dd62ed3e14610405578063e5affcb814610433578063f2fde38b1461045957610151565b8063a457c2d7146103ad578063a9059cbb146103d957610151565b806395d89b41116100b257806395d89b41146103535780639bb257ad1461035b5780639dc29fac1461038157610151565b8063715018a6146103275780638da5cb5b1461032f57610151565b8063313ce5671161012457806340c10f191161010957806340c10f19146102ad578063555c3002146102db57806370a082311461030157610151565b8063313ce56714610263578063395093511461028157610151565b806306fdde0314610156578063095ea7b3146101d357806318160ddd1461021357806323b872dd1461022d575b600080fd5b61015e61047f565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610198578181015183820152602001610180565b50505050905090810190601f1680156101c55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101ff600480360360408110156101e957600080fd5b506001600160a01b038135169060200135610515565b604080519115158252519081900360200190f35b61021b610532565b60408051918252519081900360200190f35b6101ff6004803603606081101561024357600080fd5b506001600160a01b03813581169160208101359091169060400135610538565b61026b6105bf565b6040805160ff9092168252519081900360200190f35b6101ff6004803603604081101561029757600080fd5b506001600160a01b0381351690602001356105c8565b6102d9600480360360408110156102c357600080fd5b506001600160a01b038135169060200135610616565b005b6101ff600480360360208110156102f157600080fd5b50356001600160a01b03166106ab565b61021b6004803603602081101561031757600080fd5b50356001600160a01b03166106c9565b6102d96106e4565b6103376107b5565b604080516001600160a01b039092168252519081900360200190f35b61015e6107c9565b6102d96004803603602081101561037157600080fd5b50356001600160a01b031661082a565b6102d96004803603604081101561039757600080fd5b506001600160a01b0381351690602001356108fd565b6101ff600480360360408110156103c357600080fd5b506001600160a01b03813516906020013561098e565b6101ff600480360360408110156103ef57600080fd5b506001600160a01b0381351690602001356109f6565b61021b6004803603604081101561041b57600080fd5b506001600160a01b0381358116916020013516610a0a565b6102d96004803603602081101561044957600080fd5b50356001600160a01b0316610a35565b6102d96004803603602081101561046f57600080fd5b50356001600160a01b0316610b05565b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561050b5780601f106104e05761010080835404028352916020019161050b565b820191906000526020600020905b8154815290600101906020018083116104ee57829003601f168201915b5050505050905090565b6000610529610522610c32565b8484610c36565b50600192915050565b60025490565b6000610545848484610d22565b6105b584610551610c32565b6105b085604051806060016040528060288152602001611277602891396001600160a01b038a1660009081526001602052604081209061058f610c32565b6001600160a01b031681526020810191909152604001600020549190610e7d565b610c36565b5060019392505050565b60055460ff1690565b60006105296105d5610c32565b846105b085600160006105e6610c32565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610f14565b3360009081526006602052604090205460ff168061064c57506106376107b5565b6001600160a01b0316336001600160a01b0316145b61069d576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6106a78282610f75565b5050565b6001600160a01b031660009081526006602052604090205460ff1690565b6001600160a01b031660009081526020819052604090205490565b6106ec610c32565b6001600160a01b03166106fd6107b5565b6001600160a01b031614610758576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60055460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36005805474ffffffffffffffffffffffffffffffffffffffff0019169055565b60055461010090046001600160a01b031690565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561050b5780601f106104e05761010080835404028352916020019161050b565b3360009081526006602052604090205460ff1680610860575061084b6107b5565b6001600160a01b0316336001600160a01b0316145b6108b1576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b038116600081815260066020526040808220805460ff19166001179055517feb61edd6570e8798f968e1e8c0114e1e25557b015c7ac44f7aeaf4a67ef3bc239190a250565b3360009081526006602052604090205460ff1680610933575061091e6107b5565b6001600160a01b0316336001600160a01b0316145b610984576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6106a78282611065565b600061052961099b610c32565b846105b08560405180606001604052806025815260200161130960259139600160006109c5610c32565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610e7d565b6000610529610a03610c32565b8484610d22565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3360009081526006602052604090205460ff1680610a6b5750610a566107b5565b6001600160a01b0316336001600160a01b0316145b610abc576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b038116600081815260066020526040808220805460ff19169055517feedc52ad501f0ddd2dca82b61f1b96f1f84b898d242eced1210037c8a569074e9190a250565b610b0d610c32565b6001600160a01b0316610b1e6107b5565b6001600160a01b031614610b79576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116610bbe5760405162461bcd60e51b81526004018080602001828103825260268152602001806112096026913960400191505060405180910390fd5b6005546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600580546001600160a01b039092166101000274ffffffffffffffffffffffffffffffffffffffff0019909216919091179055565b3390565b6001600160a01b038316610c7b5760405162461bcd60e51b81526004018080602001828103825260248152602001806112e56024913960400191505060405180910390fd5b6001600160a01b038216610cc05760405162461bcd60e51b815260040180806020018281038252602281526020018061122f6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610d675760405162461bcd60e51b81526004018080602001828103825260258152602001806112c06025913960400191505060405180910390fd5b6001600160a01b038216610dac5760405162461bcd60e51b81526004018080602001828103825260238152602001806111c46023913960400191505060405180910390fd5b610db7838383611161565b610df481604051806060016040528060268152602001611251602691396001600160a01b0386166000908152602081905260409020549190610e7d565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610e239082610f14565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610f0c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610ed1578181015183820152602001610eb9565b50505050905090810190601f168015610efe5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610f6e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610fd0576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610fdc60008383611161565b600254610fe99082610f14565b6002556001600160a01b03821660009081526020819052604090205461100f9082610f14565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b0382166110aa5760405162461bcd60e51b815260040180806020018281038252602181526020018061129f6021913960400191505060405180910390fd5b6110b682600083611161565b6110f3816040518060600160405280602281526020016111e7602291396001600160a01b0385166000908152602081905260409020549190610e7d565b6001600160a01b0383166000908152602081905260409020556002546111199082611166565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b505050565b6000828211156111bd576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220a39fba253f0b337163e8189855d1b968a7dc60c9ff4c9b34746d175c58e3cc8c64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"allowance(address,address)\": {\n        \"details\": \"See {IERC20-allowance}.\"\n      },\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC20-balanceOf}.\"\n      },\n      \"blacklistMinter(address)\": {\n        \"params\": {\n          \"_account\": \"address of minter to be blacklisted\"\n        }\n      },\n      \"decimals()\": {\n        \"details\": \"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"\n      },\n      \"decreaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"\n      },\n      \"increaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"isWhitelistedMinter(address)\": {\n        \"params\": {\n          \"_account\": \"address of minter\"\n        },\n        \"returns\": {\n          \"_0\": \"boolean, True if address is a whitelisted minter\"\n        }\n      },\n      \"name()\": {\n        \"details\": \"Returns the name of the token.\"\n      },\n      \"owner()\": {\n        \"details\": \"Returns the address of the current owner.\"\n      },\n      \"renounceOwnership()\": {\n        \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n      },\n      \"symbol()\": {\n        \"details\": \"Returns the symbol of the token, usually a shorter version of the name.\"\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC20-totalSupply}.\"\n      },\n      \"transfer(address,uint256)\": {\n        \"details\": \"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"\n      },\n      \"transferOwnership(address)\": {\n        \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n      },\n      \"whitelistMinter(address)\": {\n        \"params\": {\n          \"_account\": \"address of minter to be whitelisted\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"whitelistedMinters\": {\n        \"details\": \"mapping to track whitelisted minters\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"events\": {\n      \"MinterBlacklisted(address)\": {\n        \"notice\": \"emits an event when a minter is blacklisted \"\n      },\n      \"MinterWhitelisted(address)\": {\n        \"notice\": \"emits an event when a minter is whitelisted \"\n      }\n    },\n    \"kind\": \"user\",\n    \"methods\": {\n      \"blacklistMinter(address)\": {\n        \"notice\": \"allow the minter to blacklist other minters\"\n      },\n      \"isWhitelistedMinter(address)\": {\n        \"notice\": \"check if a minter is whitelisted\"\n      },\n      \"whitelistMinter(address)\": {\n        \"notice\": \"allows the minter to whitelist other minters\"\n      }\n    },\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 881,\n        \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n        \"label\": \"_balances\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 887,\n        \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n        \"label\": \"_allowances\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n      },\n      {\n        \"astId\": 889,\n        \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n        \"label\": \"_totalSupply\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 891,\n        \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 893,\n        \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 895,\n        \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n        \"label\": \"_decimals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint8\"\n      },\n      {\n        \"astId\": 7,\n        \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n        \"label\": \"_owner\",\n        \"offset\": 1,\n        \"slot\": \"5\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 15651,\n        \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n        \"label\": \"whitelistedMinters\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_mapping(t_address,t_bool)\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_mapping(t_address,t_bool)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => bool)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_bool\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => uint256))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_uint256)\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint8\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint8\",\n        \"numberOfBytes\": \"1\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/NonfungiblePositionManager.json",
    "content": "{\n  \"address\": \"0x24a66308bab3BEbC2821480adA395BF1C4ff8Bf2\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_factory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_WETH9\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_tokenDescriptor_\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"approved\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"approved\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"ApprovalForAll\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Collect\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"DecreaseLiquidity\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"IncreaseLiquidity\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"DOMAIN_SEPARATOR\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"PERMIT_TYPEHASH\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"WETH9\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"baseURI\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burn\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Max\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Max\",\n              \"type\": \"uint128\"\n            }\n          ],\n          \"internalType\": \"struct INonfungiblePositionManager.CollectParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"collect\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token0\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token1\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96\",\n          \"type\": \"uint160\"\n        }\n      ],\n      \"name\": \"createAndInitializePoolIfNecessary\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"pool\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct INonfungiblePositionManager.DecreaseLiquidityParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"decreaseLiquidity\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getApproved\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Desired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Desired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct INonfungiblePositionManager.IncreaseLiquidityParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"increaseLiquidity\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"isApprovedForAll\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"token0\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"token1\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"tickLower\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"tickUpper\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Desired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Desired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct INonfungiblePositionManager.MintParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"mint\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes[]\",\n          \"name\": \"data\",\n          \"type\": \"bytes[]\"\n        }\n      ],\n      \"name\": \"multicall\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes[]\",\n          \"name\": \"results\",\n          \"type\": \"bytes[]\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ownerOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"deadline\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"permit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"positions\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint96\",\n          \"name\": \"nonce\",\n          \"type\": \"uint96\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token0\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token1\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tickLower\",\n          \"type\": \"int24\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tickUpper\",\n          \"type\": \"int24\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"feeGrowthInside0LastX128\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"feeGrowthInside1LastX128\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"tokensOwed0\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"tokensOwed1\",\n          \"type\": \"uint128\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"refundETH\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"safeTransferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"safeTransferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"deadline\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"nonce\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"expiry\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitAllowed\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"nonce\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"expiry\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitAllowedIfNecessary\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"deadline\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitIfNecessary\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"approved\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"setApprovalForAll\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"interfaceId\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"name\": \"supportsInterface\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"sweepToken\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"index\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenByIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"index\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenOfOwnerByIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenURI\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0Owed\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1Owed\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3MintCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"unwrapWETH9\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x371362d27bf2715c1d616fc5ed3964941eb4fe18a8086a0290f16752c79112f6\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x24a66308bab3BEbC2821480adA395BF1C4ff8Bf2\",\n    \"transactionIndex\": 20,\n    \"gasUsed\": \"5471290\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x974ba55b29ad65f7fd71b7553b8f2759eab2896d3d132cd9d661282b25107109\",\n    \"transactionHash\": \"0x371362d27bf2715c1d616fc5ed3964941eb4fe18a8086a0290f16752c79112f6\",\n    \"logs\": [],\n    \"blockNumber\": 8007329,\n    \"cumulativeGasUsed\": \"12635340\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n    \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\n    \"0x0000000000000000000000000000000000000000\"\n  ],\n  \"bytecode\": \"0x610120604052600d80546001600160b01b0319166001176001600160b01b0316600160b01b1790553480156200003457600080fd5b50604051620062e9380380620062e98339810160408190526200005791620002db565b82826040518060400160405280601b81526020017f556e697377617020563320506f736974696f6e73204e46542d563100000000008152506040518060400160405280600a815260200169554e492d56332d504f5360b01b815250604051806040016040528060018152602001603160f81b8152508282620000e66301ffc9a760e01b6200018d60201b60201c565b8151620000fb90600690602085019062000212565b5080516200011190600790602084019062000212565b50620001246380ac58cd60e01b6200018d565b62000136635b5e139f60e01b6200018d565b6200014863780e9d6360e01b6200018d565b50508251602093840120608052805192019190912060a052506001600160601b0319606092831b811660c05290821b811660e05291901b166101005250620003249050565b6001600160e01b03198082161415620001ed576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152602081905260409020805460ff19166001179055565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826200024a576000855562000295565b82601f106200026557805160ff191683800117855562000295565b8280016001018555821562000295579182015b828111156200029557825182559160200191906001019062000278565b50620002a3929150620002a7565b5090565b5b80821115620002a35760008155600101620002a8565b80516001600160a01b0381168114620002d657600080fd5b919050565b600080600060608486031215620002f0578283fd5b620002fb84620002be565b92506200030b60208501620002be565b91506200031b60408501620002be565b90509250925092565b60805160a05160c05160601c60e05160601c6101005160601c615f40620003a960003980612a835250806102995280611718528061180e52806118965280613e5d5280613ea35280613f17525080610aa75280610dde5280610ea55280612a1d5280612b235280612e4452806136e15250806114ff5250806114de5250615f406000f3fe6080604052600436106102895760003560e01c80636352211e11610153578063ac9650d8116100cb578063d34879971161007f578063e985e9c511610064578063e985e9c5146106f5578063f3995c6714610715578063fc6f7865146107285761030d565b8063d3487997146106c2578063df2ab5bb146106e25761030d565b8063c2e3140a116100b0578063c2e3140a1461067a578063c45a01551461068d578063c87b56dd146106a25761030d565b8063ac9650d81461063a578063b88d4fde1461065a5761030d565b8063883164561161012257806399fbab881161010757806399fbab88146105cf578063a22cb46514610607578063a4a78f0c146106275761030d565b8063883164561461059757806395d89b41146105ba5761030d565b80636352211e1461052f5780636c0360eb1461054f57806370a08231146105645780637ac2ff7b146105845761030d565b806323b872dd1161020157806342966c68116101b557806349404b7c1161019a57806349404b7c146104e75780634aa4a4fc146104fa5780634f6ccce71461050f5761030d565b806342966c68146104c15780634659a494146104d45761030d565b806330adf81f116101e657806330adf81f146104775780633644e5151461048c57806342842e0e146104a15761030d565b806323b872dd146104375780632f745c59146104575761030d565b80630c49ccbe1161025857806313ead5621161023d57806313ead562146103e057806318160ddd146103f3578063219f5d17146104155761030d565b80630c49ccbe146103b757806312210e8a146103d85761030d565b806301ffc9a71461031257806306fdde0314610348578063081812fc1461036a578063095ea7b3146103975761030d565b3661030d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461030b576040805162461bcd60e51b815260206004820152600960248201527f4e6f742057455448390000000000000000000000000000000000000000000000604482015290519081900360640190fd5b005b600080fd5b34801561031e57600080fd5b5061033261032d3660046153a6565b61073b565b60405161033f919061591e565b60405180910390f35b34801561035457600080fd5b5061035d610776565b60405161033f9190615971565b34801561037657600080fd5b5061038a6103853660046156b8565b61080c565b60405161033f91906157e2565b3480156103a357600080fd5b5061030b6103b2366004615270565b610868565b6103ca6103c5366004615483565b61093e565b60405161033f929190615b42565b61030b610daa565b61038a6103ee366004615103565b610dbc565b3480156103ff57600080fd5b506104086110c9565b60405161033f9190615929565b610428610423366004615494565b6110da565b60405161033f93929190615afd565b34801561044357600080fd5b5061030b61045236600461515c565b611413565b34801561046357600080fd5b50610408610472366004615270565b61146a565b34801561048357600080fd5b50610408611495565b34801561049857600080fd5b506104086114b9565b3480156104ad57600080fd5b5061030b6104bc36600461515c565b611577565b61030b6104cf3660046156b8565b611592565b61030b6104e23660046152dc565b611661565b61030b6104f53660046156d0565b611714565b34801561050657600080fd5b5061038a611894565b34801561051b57600080fd5b5061040861052a3660046156b8565b6118b8565b34801561053b57600080fd5b5061038a61054a3660046156b8565b6118ce565b34801561055b57600080fd5b5061035d6118f6565b34801561057057600080fd5b5061040861057f3660046150af565b6118fb565b61030b6105923660046152dc565b611963565b6105aa6105a5366004615550565b611e0f565b60405161033f9493929190615b1e565b3480156105c657600080fd5b5061035d612370565b3480156105db57600080fd5b506105ef6105ea3660046156b8565b6123d1565b60405161033f9c9b9a99989796959493929190615b50565b34801561061357600080fd5b5061030b610622366004615243565b612600565b61030b6106353660046152dc565b612723565b61064d610648366004615337565b6127d5565b60405161033f91906158a0565b34801561066657600080fd5b5061030b61067536600461519c565b612915565b61030b6106883660046152dc565b612973565b34801561069957600080fd5b5061038a612a1b565b3480156106ae57600080fd5b5061035d6106bd3660046156b8565b612a3f565b3480156106ce57600080fd5b5061030b6106dd366004615717565b612b0e565b61030b6106f036600461529b565b612b8c565b34801561070157600080fd5b506103326107103660046150cb565b612c6f565b61030b6107233660046152dc565b612c9d565b6103ca61073636600461546c565b612d28565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081526020819052604090205460ff165b919050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156108025780601f106107d757610100808354040283529160200191610802565b820191906000526020600020905b8154815290600101906020018083116107e557829003601f168201915b5050505050905090565b600061081782613246565b61083c5760405162461bcd60e51b8152600401610833906159bb565b60405180910390fd5b506000908152600c60205260409020546c0100000000000000000000000090046001600160a01b031690565b6000610873826118ce565b9050806001600160a01b0316836001600160a01b031614156108c65760405162461bcd60e51b8152600401808060200182810382526021815260200180615ee26021913960400191505060405180910390fd5b806001600160a01b03166108d8613253565b6001600160a01b031614806108f457506108f481610710613253565b61092f5760405162461bcd60e51b8152600401808060200182810382526038815260200180615e0c6038913960400191505060405180910390fd5b6109398383613257565b505050565b600080823561094d33826132db565b6109695760405162461bcd60e51b815260040161083390615984565b836080013580610977613377565b11156109ca576040805162461bcd60e51b815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b60006109dc6040870160208801615562565b6001600160801b0316116109ef57600080fd5b84356000908152600c602090815260409182902060018101549092600160801b9091046001600160801b031691610a2a918901908901615562565b6001600160801b0316816001600160801b03161015610a4857600080fd5b60018281015469ffffffffffffffffffff166000908152600b60209081526040808320815160608101835281546001600160a01b039081168252919095015490811692850192909252600160a01b90910462ffffff1690830152610acc7f00000000000000000000000000000000000000000000000000000000000000008361337b565b60018501549091506001600160a01b0382169063a34123a7906a01000000000000000000008104600290810b91600160681b9004900b610b1260408e0160208f01615562565b6040518463ffffffff1660e01b8152600401610b309392919061594b565b6040805180830381600087803b158015610b4957600080fd5b505af1158015610b5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8191906156f4565b909850965060408901358810801590610b9e575088606001358710155b610bba5760405162461bcd60e51b815260040161083390615a18565b6001840154600090610bea9030906a01000000000000000000008104600290810b91600160681b9004900b613477565b9050600080836001600160a01b031663514ea4bf846040518263ffffffff1660e01b8152600401610c1b9190615929565b60a06040518083038186803b158015610c3357600080fd5b505afa158015610c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6b91906155ac565b50509250925050610c9087600201548303876001600160801b0316600160801b6134d1565b6004880180546fffffffffffffffffffffffffffffffff198116928e016001600160801b039182160181169290921790556003880154610cda91908303908816600160801b6134d1565b6004880180546001600160801b03808216938e01600160801b9283900482160116029190911790556002870182905560038701819055610d2060408d0160208e01615562565b86038760010160106101000a8154816001600160801b0302191690836001600160801b031602179055508b600001357f26f6a048ee9138f2c0ce266f322cb99228e8d619ae2bff30c67f8dcf9d2377b48d6020016020810190610d839190615562565b8d8d604051610d9493929190615afd565b60405180910390a2505050505050505050915091565b4715610dba57610dba3347613580565b565b6000836001600160a01b0316856001600160a01b031610610ddc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631698ee828686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018262ffffff168152602001935050505060206040518083038186803b158015610e6757600080fd5b505afa158015610e7b573d6000803e3d6000fd5b505050506040513d6020811015610e9157600080fd5b505190506001600160a01b038116610fe0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a16712958686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018262ffffff1681526020019350505050602060405180830381600087803b158015610f3057600080fd5b505af1158015610f44573d6000803e3d6000fd5b505050506040513d6020811015610f5a57600080fd5b5051604080517ff637731d0000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015291519293509083169163f637731d9160248082019260009290919082900301818387803b158015610fc357600080fd5b505af1158015610fd7573d6000803e3d6000fd5b505050506110c1565b6000816001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561101b57600080fd5b505afa15801561102f573d6000803e3d6000fd5b505050506040513d60e081101561104557600080fd5b505190506001600160a01b0381166110bf57816001600160a01b031663f637731d846040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156110a657600080fd5b505af11580156110ba573d6000803e3d6000fd5b505050505b505b949350505050565b60006110d56002613689565b905090565b60008060008360a00135806110ed613377565b1115611140576040805162461bcd60e51b815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b84356000908152600c6020908152604080832060018082015469ffffffffffffffffffff81168652600b855283862084516060808201875282546001600160a01b039081168352929094015480831682890190815262ffffff600160a01b9092048216838901908152885161014081018a528451861681529151909416818a01529251168287015230828501526a01000000000000000000008304600290810b810b608080850191909152600160681b909404810b900b60a0830152958c013560c0820152938b013560e0850152908a0135610100840152890135610120830152929061122c90613694565b6001870154939a50919850965091506000906112669030906a01000000000000000000008104600290810b91600160681b9004900b613477565b9050600080836001600160a01b031663514ea4bf846040518263ffffffff1660e01b81526004016112979190615929565b60a06040518083038186803b1580156112af57600080fd5b505afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e791906155ac565b50509250925050611323866002015483038760010160109054906101000a90046001600160801b03166001600160801b0316600160801b6134d1565b6004870180546001600160801b0380821690930183166fffffffffffffffffffffffffffffffff19909116179055600387015460018801546113739291840391600160801b9182900416906134d1565b6004870180546001600160801b03600160801b80830482169094018116840291811691909117909155600288018490556003880183905560018801805483810483168e018316909302929091169190911790556040518b35907f3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f906113fd908d908d908d90615afd565b60405180910390a2505050505050509193909250565b61142461141e613253565b826132db565b61145f5760405162461bcd60e51b8152600401808060200182810382526031815260200180615f036031913960400191505060405180910390fd5b6109398383836138cf565b6001600160a01b038216600090815260016020526040812061148c9083613a1b565b90505b92915050565b7f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad81565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611526613a27565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b031681526020019550505050505060405160208183030381529060405280519060200120905090565b61093983838360405180602001604052806000815250612915565b8061159d33826132db565b6115b95760405162461bcd60e51b815260040161083390615984565b6000828152600c602052604090206001810154600160801b90046001600160801b03161580156115f4575060048101546001600160801b0316155b801561161257506004810154600160801b90046001600160801b0316155b61162e5760405162461bcd60e51b815260040161083390615a86565b6000838152600c602052604081208181556001810182905560028101829055600381018290556004015561093983613a2b565b604080517f8fcbaf0c00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101879052606481018690526001608482015260ff851660a482015260c4810184905260e4810183905290516001600160a01b03881691638fcbaf0c9161010480830192600092919082900301818387803b1580156116f457600080fd5b505af1158015611708573d6000803e3d6000fd5b50505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561178357600080fd5b505afa158015611797573d6000803e3d6000fd5b505050506040513d60208110156117ad57600080fd5b5051905082811015611806576040805162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e742057455448390000000000000000000000000000604482015290519081900360640190fd5b8015610939577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561187257600080fd5b505af1158015611886573d6000803e3d6000fd5b505050506109398282613580565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806118c6600284613af8565b509392505050565b600061148f82604051806060016040528060298152602001615e6e6029913960029190613b16565b606090565b60006001600160a01b0382166119425760405162461bcd60e51b815260040180806020018281038252602a815260200180615e44602a913960400191505060405180910390fd5b6001600160a01b038216600090815260016020526040902061148f90613689565b8361196c613377565b11156119bf576040805162461bcd60e51b815260206004820152600e60248201527f5065726d69742065787069726564000000000000000000000000000000000000604482015290519081900360640190fd5b60006119c96114b9565b7f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad88886119f581613b23565b604080516020808201969096526001600160a01b03909416848201526060840192909252608083015260a08083018a90528151808403909101815260c0830182528051908401207f190100000000000000000000000000000000000000000000000000000000000060e084015260e283019490945261010280830194909452805180830390940184526101229091019052815191012090506000611a98876118ce565b9050806001600160a01b0316886001600160a01b03161415611aeb5760405162461bcd60e51b8152600401808060200182810382526027815260200180615d6f6027913960400191505060405180910390fd5b611af481613b62565b15611ccf576040805160208082018790528183018690527fff0000000000000000000000000000000000000000000000000000000000000060f889901b16606083015282516041818403018152606183018085527f1626ba7e0000000000000000000000000000000000000000000000000000000090526065830186815260858401948552815160a585015281516001600160a01b03871695631626ba7e958995919260c59091019185019080838360005b83811015611bbe578181015183820152602001611ba6565b50505050905090810190601f168015611beb5780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b158015611c0957600080fd5b505afa158015611c1d573d6000803e3d6000fd5b505050506040513d6020811015611c3357600080fd5b50517fffffffff00000000000000000000000000000000000000000000000000000000167f1626ba7e0000000000000000000000000000000000000000000000000000000014611cca576040805162461bcd60e51b815260206004820152600c60248201527f556e617574686f72697a65640000000000000000000000000000000000000000604482015290519081900360640190fd5b611dfb565b600060018387878760405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611d2b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611d93576040805162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015290519081900360640190fd5b816001600160a01b0316816001600160a01b031614611df9576040805162461bcd60e51b815260206004820152600c60248201527f556e617574686f72697a65640000000000000000000000000000000000000000604482015290519081900360640190fd5b505b611e058888613257565b5050505050505050565b60008060008084610140013580611e24613377565b1115611e77576040805162461bcd60e51b815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b604080516101408101909152600090611f439080611e9860208b018b6150af565b6001600160a01b03168152602001896020016020810190611eb991906150af565b6001600160a01b03168152602001611ed760608b0160408c0161569e565b62ffffff168152306020820152604001611ef760808b0160608c016153e6565b60020b8152602001611f0f60a08b0160808c016153e6565b60020b81526020018960a0013581526020018960c0013581526020018960e001358152602001896101000135815250613694565b92975090955093509050611fb7611f6261014089016101208a016150af565b600d80547fffffffffffffffffffff000000000000000000000000000000000000000000008116600175ffffffffffffffffffffffffffffffffffffffffffff92831690810190921617909155975087613b68565b6000611fe230611fcd60808b0160608c016153e6565b611fdd60a08c0160808d016153e6565b613477565b9050600080836001600160a01b031663514ea4bf846040518263ffffffff1660e01b81526004016120139190615929565b60a06040518083038186803b15801561202b57600080fd5b505afa15801561203f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206391906155ac565b5050925092505060006120dc8560405180606001604052808e600001602081019061208e91906150af565b6001600160a01b031681526020018e60200160208101906120af91906150af565b6001600160a01b031681526020018e60400160208101906120d0919061569e565b62ffffff169052613c96565b905060405180610140016040528060006bffffffffffffffffffffffff16815260200160006001600160a01b031681526020018269ffffffffffffffffffff1681526020018c606001602081019061213491906153e6565b60020b815260200161214c60a08e0160808f016153e6565b60020b81526020018a6001600160801b0316815260200184815260200183815260200160006001600160801b0316815260200160006001600160801b0316815250600c60008c815260200190815260200160002060008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160006101000a81548169ffffffffffffffffffff021916908369ffffffffffffffffffff160217905550606082015181600101600a6101000a81548162ffffff021916908360020b62ffffff160217905550608082015181600101600d6101000a81548162ffffff021916908360020b62ffffff16021790555060a08201518160010160106101000a8154816001600160801b0302191690836001600160801b0316021790555060c0820151816002015560e082015181600301556101008201518160040160006101000a8154816001600160801b0302191690836001600160801b031602179055506101208201518160040160106101000a8154816001600160801b0302191690836001600160801b03160217905550905050897f3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f8a8a8a60405161235b93929190615afd565b60405180910390a25050505050509193509193565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156108025780601f106107d757610100808354040283529160200191610802565b6000818152600c6020908152604080832081516101408101835281546bffffffffffffffffffffffff811682526001600160a01b036c010000000000000000000000009091041693810193909352600181015469ffffffffffffffffffff81169284018390526a01000000000000000000008104600290810b810b810b6060860152600160681b8204810b810b810b60808601526001600160801b03600160801b92839004811660a08701529083015460c0860152600383015460e0860152600490920154808316610100860152041661012083015282918291829182918291829182918291829182918291906124da5760405162461bcd60e51b815260040161083390615a4f565b6000600b6000836040015169ffffffffffffffffffff1669ffffffffffffffffffff1681526020019081526020016000206040518060600160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160149054906101000a900462ffffff1662ffffff1662ffffff1681525050905081600001518260200151826000015183602001518460400151866060015187608001518860a001518960c001518a60e001518b61010001518c61012001519d509d509d509d509d509d509d509d509d509d509d509d50505091939597999b5091939597999b565b612608613253565b6001600160a01b0316826001600160a01b0316141561266e576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b806005600061267b613253565b6001600160a01b0390811682526020808301939093526040918201600090812091871680825291909352912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016921515929092179091556126dd613253565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523360048201523060248201529051600019916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b15801561278d57600080fd5b505afa1580156127a1573d6000803e3d6000fd5b505050506040513d60208110156127b757600080fd5b505110156127cd576127cd868686868686611661565b505050505050565b60608167ffffffffffffffff811180156127ee57600080fd5b5060405190808252806020026020018201604052801561282257816020015b606081526020019060019003908161280d5790505b50905060005b8281101561290e576000803086868581811061284057fe5b90506020028101906128529190615bef565b6040516128609291906157d2565b600060405180830381855af49150503d806000811461289b576040519150601f19603f3d011682016040523d82523d6000602084013e6128a0565b606091505b5091509150816128ec576044815110156128b957600080fd5b600481019050808060200190518101906128d39190615402565b60405162461bcd60e51b81526004016108339190615971565b808484815181106128f957fe5b60209081029190910101525050600101612828565b5092915050565b612926612920613253565b836132db565b6129615760405162461bcd60e51b8152600401808060200182810382526031815260200180615f036031913960400191505060405180910390fd5b61296d84848484613de6565b50505050565b604080517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152905186916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b1580156129db57600080fd5b505afa1580156129ef573d6000803e3d6000fd5b505050506040513d6020811015612a0557600080fd5b505110156127cd576127cd868686868686612c9d565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060612a4a82613246565b612a5357600080fd5b6040517fe9dc63750000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e9dc637590612aba9030908690600401615932565b60006040518083038186803b158015612ad257600080fd5b505afa158015612ae6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261148f9190810190615402565b6000612b1c828401846154a5565b9050612b4c7f00000000000000000000000000000000000000000000000000000000000000008260000151613e38565b508415612b67578051516020820151612b6791903388613e5b565b8315612b8557612b8581600001516020015182602001513387613e5b565b5050505050565b6000836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612bdb57600080fd5b505afa158015612bef573d6000803e3d6000fd5b505050506040513d6020811015612c0557600080fd5b5051905082811015612c5e576040805162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e7420746f6b656e0000000000000000000000000000604482015290519081900360640190fd5b801561296d5761296d848383613feb565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b604080517fd505accf000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018790526064810186905260ff8516608482015260a4810184905260c4810183905290516001600160a01b0388169163d505accf9160e480830192600092919082900301818387803b1580156116f457600080fd5b6000808235612d3733826132db565b612d535760405162461bcd60e51b815260040161083390615984565b6000612d656060860160408701615562565b6001600160801b03161180612d9257506000612d876080860160608701615562565b6001600160801b0316115b612d9b57600080fd5b600080612dae60408701602088016150af565b6001600160a01b031614612dd157612dcc60408601602087016150af565b612dd3565b305b85356000908152600c6020908152604080832060018082015469ffffffffffffffffffff168552600b8452828520835160608101855281546001600160a01b039081168252919092015490811694820194909452600160a01b90930462ffffff169183019190915292935090612e697f00000000000000000000000000000000000000000000000000000000000000008361337b565b600484015460018501549192506001600160801b0380821692600160801b92839004821692900416156130865760018501546040517fa34123a70000000000000000000000000000000000000000000000000000000081526001600160a01b0385169163a34123a791612f00916a01000000000000000000008104600290810b92600160681b909204900b9060009060040161594b565b6040805180830381600087803b158015612f1957600080fd5b505af1158015612f2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5191906156f4565b5050600185015460009081906001600160a01b0386169063514ea4bf90612f969030906a01000000000000000000008104600290810b91600160681b9004900b613477565b6040518263ffffffff1660e01b8152600401612fb29190615929565b60a06040518083038186803b158015612fca57600080fd5b505afa158015612fde573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300291906155ac565b5050925092505061303e876002015483038860010160109054906101000a90046001600160801b03166001600160801b0316600160801b6134d1565b84019350613077876003015482038860010160109054906101000a90046001600160801b03166001600160801b0316600160801b6134d1565b60028801929092556003870155015b6000806001600160801b0384166130a360608e0160408f01615562565b6001600160801b0316116130c6576130c160608d0160408e01615562565b6130c8565b835b836001600160801b03168d60600160208101906130e59190615562565b6001600160801b0316116131085761310360808e0160608f01615562565b61310a565b835b60018901546040517f4f1eb3d80000000000000000000000000000000000000000000000000000000081529294509092506001600160a01b03871691634f1eb3d89161317d918c916a01000000000000000000008104600290810b92600160681b909204900b9088908890600401615839565b6040805180830381600087803b15801561319657600080fd5b505af11580156131aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ce919061557e565b6004890180546fffffffffffffffffffffffffffffffff196001600160801b03918216600160801b878a0384160217168689038216179091556040519281169d50169a508c35907f40d0efd1a53d60ecbf40971b9daf7dc90178c3aadc7aab1765632738fa8b8f0190610d94908b9086908690615876565b600061148f60028361417b565b3390565b6000818152600c6020526040902080546bffffffffffffffffffffffff166c010000000000000000000000006001600160a01b0385169081029190911790915581906132a2826118ce565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006132e682613246565b6133215760405162461bcd60e51b815260040180806020018281038252602c815260200180615de0602c913960400191505060405180910390fd5b600061332c836118ce565b9050806001600160a01b0316846001600160a01b031614806133675750836001600160a01b031661335c8461080c565b6001600160a01b0316145b806110c157506110c18185612c6f565b4290565b600081602001516001600160a01b031682600001516001600160a01b0316106133a357600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516bffffffffffffffffffffffff19606086901b16602080830191909152600285810b60e890811b60348501529085900b901b60378301528251601a818403018152603a90920190925280519101205b9392505050565b600080806000198587098686029250828110908390030390508061350757600084116134fc57600080fd5b5082900490506134ca565b80841161351357600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b604080516000808252602082019092526001600160a01b0384169083906040518082805190602001908083835b602083106135cc5780518252601f1990920191602091820191016135ad565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461362e576040519150601f19603f3d011682016040523d82523d6000602084013e613633565b606091505b5050905080610939576040805162461bcd60e51b815260206004820152600360248201527f5354450000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600061148f82614187565b6000806000806000604051806060016040528087600001516001600160a01b0316815260200187602001516001600160a01b03168152602001876040015162ffffff1681525090506137067f00000000000000000000000000000000000000000000000000000000000000008261337b565b91506000826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561374357600080fd5b505afa158015613757573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377b919061560d565b50505050505090506000613792886080015161418b565b905060006137a38960a0015161418b565b90506137ba8383838c60c001518d60e001516144d9565b9750505050816001600160a01b0316633c8a7d8d876060015188608001518960a00151896040518060400160405280888152602001336001600160a01b031681525060405160200161380c9190615abd565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161383b9594939291906157f6565b6040805180830381600087803b15801561385457600080fd5b505af1158015613868573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061388c91906156f4565b610100880151919550935084108015906138ab57508561012001518310155b6138c75760405162461bcd60e51b815260040161083390615a18565b509193509193565b826001600160a01b03166138e2826118ce565b6001600160a01b0316146139275760405162461bcd60e51b8152600401808060200182810382526029815260200180615eb96029913960400191505060405180910390fd5b6001600160a01b03821661396c5760405162461bcd60e51b8152600401808060200182810382526024815260200180615d966024913960400191505060405180910390fd5b613977838383610939565b613982600082613257565b6001600160a01b03831660009081526001602052604090206139a4908261459d565b506001600160a01b03821660009081526001602052604090206139c790826145a9565b506139d4600282846145b5565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061148c83836145cb565b4690565b6000613a36826118ce565b9050613a4481600084610939565b613a4f600083613257565b6000828152600860205260409020546002600019610100600184161502019091160415613a8d576000828152600860205260408120613a8d9161501f565b6001600160a01b0381166000908152600160205260409020613aaf908361459d565b50613abb60028361462f565b5060405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000808080613b07868661463b565b909450925050505b9250929050565b60006110c18484846146b6565b6000908152600c6020526040902080546bffffffffffffffffffffffff19811660016bffffffffffffffffffffffff9283169081019092161790915590565b3b151590565b6001600160a01b038216613bc3576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b613bcc81613246565b15613c1e576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b613c2a60008383610939565b6001600160a01b0382166000908152600160205260409020613c4c90826145a9565b50613c59600282846145b5565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6001600160a01b0382166000908152600a602052604090205469ffffffffffffffffffff168061148f5750600d8054600169ffffffffffffffffffff76010000000000000000000000000000000000000000000080840482168381019092160275ffffffffffffffffffffffffffffffffffffffffffff909316929092179092556001600160a01b038085166000908152600a6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffff000000000000000000001686179055848352600b825291829020865181549085167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617825591870151950180549287015162ffffff16600160a01b027fffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffff969094169290911691909117939093161790915592915050565b613df18484846138cf565b613dfd84848484614780565b61296d5760405162461bcd60e51b8152600401808060200182810382526032815260200180615d3d6032913960400191505060405180910390fd5b6000613e44838361337b565b9050336001600160a01b0382161461148f57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316148015613e9c5750804710155b15613fbe577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015613efc57600080fd5b505af1158015613f10573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015613f8c57600080fd5b505af1158015613fa0573d6000803e3d6000fd5b505050506040513d6020811015613fb657600080fd5b5061296d9050565b6001600160a01b038316301415613fdf57613fda848383613feb565b61296d565b61296d8484848461495c565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781529251825160009485949389169392918291908083835b602083106140955780518252601f199092019160209182019101614076565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146140f7576040519150601f19603f3d011682016040523d82523d6000602084013e6140fc565b606091505b509150915081801561412a57508051158061412a575080806020019051602081101561412757600080fd5b50515b612b85576040805162461bcd60e51b815260206004820152600260248201527f5354000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600061148c8383614af4565b5490565b60008060008360020b126141a2578260020b6141aa565b8260020b6000035b9050620d89e8811115614204576040805162461bcd60e51b815260206004820152600160248201527f5400000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60006001821661421857600160801b61422a565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561425e576ffff97272373d413259a46990580e213a0260801c5b600482161561427d576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b600882161561429c576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b60108216156142bb576fffcb9843d60f6159c9db58835c9266440260801c5b60208216156142da576fff973b41fa98c081472e6896dfb254c00260801c5b60408216156142f9576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615614318576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615614338576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615614358576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615614378576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615614398576fe7159475a2c29b7443b29c7fa6e889d90260801c5b6110008216156143b8576fd097f3bdfd2022b8845ad8f792aa58250260801c5b6120008216156143d8576fa9f746462d870fdf8a65dc1f90e061e50260801c5b6140008216156143f8576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615614418576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615614439576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615614459576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615614478576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615614495576b048a170391f7dc42444e8fa20260801c5b60008460020b13156144b05780600019816144ac57fe5b0490505b6401000000008106156144c45760016144c7565b60005b60ff16602082901c0192505050919050565b6000836001600160a01b0316856001600160a01b031611156144f9579293925b846001600160a01b0316866001600160a01b0316116145245761451d858585614b0c565b9050614594565b836001600160a01b0316866001600160a01b0316101561458657600061454b878686614b0c565b9050600061455a878986614b78565b9050806001600160801b0316826001600160801b03161061457b578061457d565b815b92505050614594565b614591858584614b78565b90505b95945050505050565b600061148c8383614bbe565b600061148c8383614c84565b60006110c184846001600160a01b038516614cce565b8154600090821061460d5760405162461bcd60e51b8152600401808060200182810382526022815260200180615d1b6022913960400191505060405180910390fd5b82600001828154811061461c57fe5b9060005260206000200154905092915050565b600061148c8383614d65565b81546000908190831061467f5760405162461bcd60e51b8152600401808060200182810382526022815260200180615e976022913960400191505060405180910390fd5b600084600001848154811061469057fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816147515760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156147165781810151838201526020016146fe565b50505050905090810190601f1680156147435780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5084600001600182038154811061476457fe5b9060005260206000209060020201600101549150509392505050565b6000614794846001600160a01b0316613b62565b6147a0575060016110c1565b60006148f17f150b7a02000000000000000000000000000000000000000000000000000000006147ce613253565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561483557818101518382015260200161481d565b50505050905090810190601f1680156148625780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001615d3d603291396001600160a01b0388169190614e39565b9050600081806020019051602081101561490a57600080fd5b50517fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001492505050949350505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000178152925182516000948594938a169392918291908083835b60208310614a0e5780518252601f1990920191602091820191016149ef565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614a70576040519150601f19603f3d011682016040523d82523d6000602084013e614a75565b606091505b5091509150818015614aa3575080511580614aa35750808060200190516020811015614aa057600080fd5b50515b6127cd576040805162461bcd60e51b815260206004820152600360248201527f5354460000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60009081526001919091016020526040902054151590565b6000826001600160a01b0316846001600160a01b03161115614b2c579192915b6000614b58856001600160a01b0316856001600160a01b03166c010000000000000000000000006134d1565b9050614594614b7384838888036001600160a01b03166134d1565b614e48565b6000826001600160a01b0316846001600160a01b03161115614b98579192915b6110c1614b73836c010000000000000000000000008787036001600160a01b03166134d1565b60008181526001830160205260408120548015614c7a5783546000198083019190810190600090879083908110614bf157fe5b9060005260206000200154905080876000018481548110614c0e57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080614c3e57fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061148f565b600091505061148f565b6000614c908383614af4565b614cc65750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561148f565b50600061148f565b600082815260018401602052604081205480614d335750506040805180820182528381526020808201848152865460018181018955600089815284812095516002909302909501918255915190820155865486845281880190925292909120556134ca565b82856000016001830381548110614d4657fe5b90600052602060002090600202016001018190555060009150506134ca565b60008181526001830160205260408120548015614c7a5783546000198083019190810190600090879083908110614d9857fe5b9060005260206000209060020201905080876000018481548110614db857fe5b600091825260208083208454600290930201918255600193840154918401919091558354825289830190526040902090840190558654879080614df757fe5b600082815260208082206002600019909401938402018281556001908101839055929093558881528982019092526040822091909155945061148f9350505050565b60606110c18484600085614e5e565b806001600160801b038116811461077157600080fd5b606082471015614e9f5760405162461bcd60e51b8152600401808060200182810382526026815260200180615dba6026913960400191505060405180910390fd5b614ea885613b62565b614ef9576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310614f375780518252601f199092019160209182019101614f18565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614f99576040519150601f19603f3d011682016040523d82523d6000602084013e614f9e565b606091505b5091509150614fae828286614fb9565b979650505050505050565b60608315614fc85750816134ca565b825115614fd85782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156147165781810151838201526020016146fe565b50805460018160011615610100020316600290046000825580601f106150455750615063565b601f0160209004906000526020600020908101906150639190615066565b50565b5b8082111561507b5760008155600101615067565b5090565b803561077181615cc4565b805161ffff8116811461077157600080fd5b803562ffffff8116811461077157600080fd5b6000602082840312156150c0578081fd5b81356134ca81615cc4565b600080604083850312156150dd578081fd5b82356150e881615cc4565b915060208301356150f881615cc4565b809150509250929050565b60008060008060808587031215615118578182fd5b843561512381615cc4565b9350602085013561513381615cc4565b92506151416040860161509c565b9150606085013561515181615cc4565b939692955090935050565b600080600060608486031215615170578081fd5b833561517b81615cc4565b9250602084013561518b81615cc4565b929592945050506040919091013590565b600080600080608085870312156151b1578182fd5b84356151bc81615cc4565b935060208501356151cc81615cc4565b925060408501359150606085013567ffffffffffffffff8111156151ee578182fd5b8501601f810187136151fe578182fd5b803561521161520c82615c76565b615c52565b818152886020838501011115615225578384fd5b81602084016020830137908101602001929092525092959194509250565b60008060408385031215615255578182fd5b823561526081615cc4565b915060208301356150f881615cd9565b60008060408385031215615282578182fd5b823561528d81615cc4565b946020939093013593505050565b6000806000606084860312156152af578081fd5b83356152ba81615cc4565b92506020840135915060408401356152d181615cc4565b809150509250925092565b60008060008060008060c087890312156152f4578384fd5b86356152ff81615cc4565b95506020870135945060408701359350606087013561531d81615d0b565b9598949750929560808101359460a0909101359350915050565b60008060208385031215615349578182fd5b823567ffffffffffffffff80821115615360578384fd5b818501915085601f830112615373578384fd5b813581811115615381578485fd5b8660208083028501011115615394578485fd5b60209290920196919550909350505050565b6000602082840312156153b7578081fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146134ca578182fd5b6000602082840312156153f7578081fd5b81356134ca81615ce7565b600060208284031215615413578081fd5b815167ffffffffffffffff811115615429578182fd5b8201601f81018413615439578182fd5b805161544761520c82615c76565b81815285602083850101111561545b578384fd5b614594826020830160208601615c98565b60006080828403121561547d578081fd5b50919050565b600060a0828403121561547d578081fd5b600060c0828403121561547d578081fd5b600081830360808112156154b7578182fd5b6040516040810167ffffffffffffffff82821081831117156154d557fe5b8160405260608412156154e6578485fd5b60a08301935081841081851117156154fa57fe5b50826040528435925061550c83615cc4565b91825260208401359161551e83615cc4565b8260608301526155306040860161509c565b608083015281526155436060850161507f565b6020820152949350505050565b6000610160828403121561547d578081fd5b600060208284031215615573578081fd5b81356134ca81615cf6565b60008060408385031215615590578182fd5b825161559b81615cf6565b60208401519092506150f881615cf6565b600080600080600060a086880312156155c3578283fd5b85516155ce81615cf6565b80955050602086015193506040860151925060608601516155ee81615cf6565b60808701519092506155ff81615cf6565b809150509295509295909350565b600080600080600080600060e0888a031215615627578485fd5b875161563281615cc4565b602089015190975061564381615ce7565b95506156516040890161508a565b945061565f6060890161508a565b935061566d6080890161508a565b925060a088015161567d81615d0b565b60c089015190925061568e81615cd9565b8091505092959891949750929550565b6000602082840312156156af578081fd5b61148c8261509c565b6000602082840312156156c9578081fd5b5035919050565b600080604083850312156156e2578182fd5b8235915060208301356150f881615cc4565b60008060408385031215615706578182fd5b505080516020909101519092909150565b6000806000806060858703121561572c578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615751578384fd5b818701915087601f830112615764578384fd5b813581811115615772578485fd5b886020828501011115615783578485fd5b95989497505060200194505050565b600081518084526157aa816020860160208601615c98565b601f01601f19169290920160200192915050565b60020b9052565b6001600160801b03169052565b6000828483379101908152919050565b6001600160a01b0391909116815260200190565b60006001600160a01b03871682528560020b60208301528460020b60408301526001600160801b038416606083015260a06080830152614fae60a0830184615792565b6001600160a01b03959095168552600293840b60208601529190920b60408401526001600160801b03918216606084015216608082015260a00190565b6001600160a01b039390931683526001600160801b03918216602084015216604082015260600190565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015615911577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526158ff858351615792565b945092850192908501906001016158c5565b5092979650505050505050565b901515815260200190565b90815260200190565b6001600160a01b03929092168252602082015260400190565b600293840b81529190920b60208201526001600160801b03909116604082015260600190565b60006020825261148c6020830184615792565b6020808252600c908201527f4e6f7420617070726f7665640000000000000000000000000000000000000000604082015260600190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201527f697374656e7420746f6b656e0000000000000000000000000000000000000000606082015260800190565b60208082526014908201527f507269636520736c69707061676520636865636b000000000000000000000000604082015260600190565b60208082526010908201527f496e76616c696420746f6b656e20494400000000000000000000000000000000604082015260600190565b6020808252600b908201527f4e6f7420636c6561726564000000000000000000000000000000000000000000604082015260600190565b815180516001600160a01b03908116835260208083015182168185015260409283015162ffffff1692840192909252920151909116606082015260800190565b6001600160801b039390931683526020830191909152604082015260600190565b9384526001600160801b039290921660208401526040830152606082015260800190565b918252602082015260400190565b6bffffffffffffffffffffffff8d1681526001600160a01b038c811660208301528b811660408301528a16606082015262ffffff89166080820152600288900b60a08201526101808101615ba760c08301896157be565b615bb460e08301886157c5565b8561010083015284610120830152615bd06101408301856157c5565b615bde6101608301846157c5565b9d9c50505050505050505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615c23578283fd5b83018035915067ffffffffffffffff821115615c3d578283fd5b602001915036819003821315613b0f57600080fd5b60405181810167ffffffffffffffff81118282101715615c6e57fe5b604052919050565b600067ffffffffffffffff821115615c8a57fe5b50601f01601f191660200190565b60005b83811015615cb3578181015183820152602001615c9b565b8381111561296d5750506000910152565b6001600160a01b038116811461506357600080fd5b801515811461506357600080fd5b8060020b811461506357600080fd5b6001600160801b038116811461506357600080fd5b60ff8116811461506357600080fdfe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732315065726d69743a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a164736f6c6343000706000a\"\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/OpynWETH9.json",
    "content": "{\n  \"address\": \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\n  \"abi\": [\n    {\n      \"inputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"src\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"guy\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wad\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"dst\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wad\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Deposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"MinterBlacklisted\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"MinterWhitelisted\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"src\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"dst\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wad\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"src\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wad\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Withdrawal\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"guy\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"wad\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"blacklistMinter\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burn\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"deposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"isWhitelistedMinter\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"mint\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"dst\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"wad\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"src\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"dst\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"wad\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"whitelistMinter\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"wad\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x437eb1333628108ad984adf8e359f57db03d1fe082939d0ff691fa2f6756f871\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\n    \"transactionIndex\": 23,\n    \"gasUsed\": \"789502\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x77d49ea04a4df167b4032bbb18e00fec5261a8188ad5bcf7dd1523669d8a92d5\",\n    \"transactionHash\": \"0x437eb1333628108ad984adf8e359f57db03d1fe082939d0ff691fa2f6756f871\",\n    \"logs\": [],\n    \"blockNumber\": 8006276,\n    \"cumulativeGasUsed\": \"6317618\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"31d85619debc3954507258d16df1741b\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"src\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"guy\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wad\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"dst\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wad\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Deposit\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"MinterBlacklisted\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"MinterWhitelisted\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"src\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"dst\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wad\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"src\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wad\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Withdrawal\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"guy\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wad\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"blacklistMinter\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burn\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"deposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"isWhitelistedMinter\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mint\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"dst\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wad\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"src\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"dst\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wad\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"whitelistMinter\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wad\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"blacklistMinter(address)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"address of minter to be blacklisted\\\"}},\\\"isWhitelistedMinter(address)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"address of minter\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"boolean, True if address is a whitelisted minter\\\"}},\\\"whitelistMinter(address)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"address of minter to be whitelisted\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"blacklistMinter(address)\\\":{\\\"notice\\\":\\\"allow the minter to blacklist other minters\\\"},\\\"isWhitelistedMinter(address)\\\":{\\\"notice\\\":\\\"check if a minter is whitelisted\\\"},\\\"whitelistMinter(address)\\\":{\\\"notice\\\":\\\"allows the minter to whitelist other minters\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/mocks/OpynWETH9.sol\\\":\\\"OpynWETH9\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"contracts/mocks/OpynWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ncontract OpynWETH9 {\\\\n    address owner;\\\\n\\\\n    string public name = \\\\\\\"Wrapped Opyn Ether\\\\\\\";\\\\n    string public symbol = \\\\\\\"OpynWETH\\\\\\\";\\\\n    uint8 public decimals = 18;\\\\n\\\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\\\n    event Deposit(address indexed dst, uint256 wad);\\\\n    event Withdrawal(address indexed src, uint256 wad);\\\\n    event MinterWhitelisted(address indexed account);\\\\n    event MinterBlacklisted(address indexed account);\\\\n\\\\n    mapping(address => uint256) public balanceOf;\\\\n    mapping(address => mapping(address => uint256)) public allowance;\\\\n    mapping(address => bool) internal whitelistedMinters;\\\\n   \\\\n   /**\\\\n     * @notice check if the sender is whitelistd\\\\n     */\\\\n    modifier onlyWhitelisted() {\\\\n        require(\\\\n            whitelistedMinters[msg.sender] || msg.sender == owner,\\\\n            \\\\\\\"Address not a whitelisted minter\\\\\\\"\\\\n        );\\\\n        _;\\\\n    }\\\\n\\\\n    constructor() {\\\\n        owner = msg.sender;\\\\n    }\\\\n\\\\n    receive() external payable {\\\\n        deposit();\\\\n    }\\\\n\\\\n    function mint(address _to, uint256 _amount) public onlyWhitelisted {\\\\n\\\\n        balanceOf[_to] += _amount;\\\\n        emit Deposit(_to, _amount);\\\\n    }\\\\n\\\\n    function burn(address _from, uint256 _amount) public onlyWhitelisted {\\\\n\\\\n        balanceOf[_from] -= _amount;\\\\n        emit Withdrawal(_from, _amount);\\\\n    }\\\\n\\\\n    function deposit() public payable {\\\\n        balanceOf[msg.sender] += msg.value;\\\\n        emit Deposit(msg.sender, msg.value);\\\\n    }\\\\n\\\\n    function withdraw(uint256 wad) public {\\\\n        require(balanceOf[msg.sender] >= wad);\\\\n        balanceOf[msg.sender] -= wad;\\\\n        msg.sender.transfer(wad);\\\\n        emit Withdrawal(msg.sender, wad);\\\\n    }\\\\n\\\\n    function totalSupply() public view returns (uint256) {\\\\n        return address(this).balance;\\\\n    }\\\\n\\\\n    function approve(address guy, uint256 wad) public returns (bool) {\\\\n        allowance[msg.sender][guy] = wad;\\\\n        emit Approval(msg.sender, guy, wad);\\\\n        return true;\\\\n    }\\\\n\\\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\\\n        return transferFrom(msg.sender, dst, wad);\\\\n    }\\\\n\\\\n    function transferFrom(\\\\n        address src,\\\\n        address dst,\\\\n        uint256 wad\\\\n    ) public returns (bool) {\\\\n        require(balanceOf[src] >= wad);\\\\n\\\\n        if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) {\\\\n            require(allowance[src][msg.sender] >= wad);\\\\n            allowance[src][msg.sender] -= wad;\\\\n        }\\\\n\\\\n        balanceOf[src] -= wad;\\\\n        balanceOf[dst] += wad;\\\\n\\\\n        emit Transfer(src, dst, wad);\\\\n\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a minter is whitelisted\\\\n     * @param _account address of minter\\\\n     * @return boolean, True if address is a whitelisted minter\\\\n     */\\\\n    function isWhitelistedMinter(address _account) external view returns (bool) {\\\\n        return whitelistedMinters[_account];\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice allows the minter to whitelist other minters\\\\n     * @param _account address of minter to be whitelisted\\\\n     */\\\\n    function whitelistMinter(address _account) external onlyWhitelisted {\\\\n        whitelistedMinters[_account] = true;\\\\n\\\\n        emit MinterWhitelisted(_account);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice allow the minter to blacklist other minters\\\\n     * @param _account address of minter to be blacklisted\\\\n     */\\\\n    function blacklistMinter(address _account) external onlyWhitelisted {\\\\n        whitelistedMinters[_account] = false;\\\\n\\\\n        emit MinterBlacklisted(_account);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd30707331953440bf964f1234166dac3950cae00698198dd340fa972e80c09c0\\\",\\\"license\\\":\\\"GPL-3.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60c060405260126080819052712bb930b83832b21027b83cb71022ba3432b960711b60a09081526100339160019190610095565b506040805180820190915260088082526709ee0f2dcae8aa8960c31b602090920191825261006391600291610095565b506003805460ff1916601217905534801561007d57600080fd5b50600080546001600160a01b03191633179055610136565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826100cb5760008555610111565b82601f106100e457805160ff1916838001178555610111565b82800160010185558215610111579182015b828111156101115782518255916020019190600101906100f6565b5061011d929150610121565b5090565b5b8082111561011d5760008155600101610122565b610b9f806101456000396000f3fe6080604052600436106100f75760003560e01c806370a082311161008a578063a9059cbb11610059578063a9059cbb146103c1578063d0e30db0146103fa578063dd62ed3e14610402578063e5affcb81461043d57610106565b806370a082311461030d57806395d89b41146103405780639bb257ad146103555780639dc29fac1461038857610106565b80632e1a7d4d116100c65780632e1a7d4d1461024c578063313ce5671461027657806340c10f19146102a1578063555c3002146102da57610106565b806306fdde031461010b578063095ea7b31461019557806318160ddd146101e257806323b872dd1461020957610106565b3661010657610104610470565b005b600080fd5b34801561011757600080fd5b506101206104bf565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015a578181015183820152602001610142565b50505050905090810190601f1680156101875780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101a157600080fd5b506101ce600480360360408110156101b857600080fd5b506001600160a01b03813516906020013561054c565b604080519115158252519081900360200190f35b3480156101ee57600080fd5b506101f76105b2565b60408051918252519081900360200190f35b34801561021557600080fd5b506101ce6004803603606081101561022c57600080fd5b506001600160a01b038135811691602081013590911690604001356105b6565b34801561025857600080fd5b506101046004803603602081101561026f57600080fd5b50356106ea565b34801561028257600080fd5b5061028b61077f565b6040805160ff9092168252519081900360200190f35b3480156102ad57600080fd5b50610104600480360360408110156102c457600080fd5b506001600160a01b038135169060200135610788565b3480156102e657600080fd5b506101ce600480360360208110156102fd57600080fd5b50356001600160a01b0316610858565b34801561031957600080fd5b506101f76004803603602081101561033057600080fd5b50356001600160a01b0316610876565b34801561034c57600080fd5b50610120610888565b34801561036157600080fd5b506101046004803603602081101561037857600080fd5b50356001600160a01b03166108e0565b34801561039457600080fd5b50610104600480360360408110156103ab57600080fd5b506001600160a01b0381351690602001356109a5565b3480156103cd57600080fd5b506101ce600480360360408110156103e457600080fd5b506001600160a01b038135169060200135610a76565b610104610470565b34801561040e57600080fd5b506101f76004803603604081101561042557600080fd5b506001600160a01b0381358116916020013516610a8a565b34801561044957600080fd5b506101046004803603602081101561046057600080fd5b50356001600160a01b0316610aa7565b33600081815260046020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105445780601f1061051957610100808354040283529160200191610544565b820191906000526020600020905b81548152906001019060200180831161052757829003601f168201915b505050505081565b3360008181526005602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b6001600160a01b0383166000908152600460205260408120548211156105db57600080fd5b6001600160a01b038416331480159061061957506001600160a01b038416600090815260056020908152604080832033845290915290205460001914155b15610679576001600160a01b038416600090815260056020908152604080832033845290915290205482111561064e57600080fd5b6001600160a01b03841660009081526005602090815260408083203384529091529020805483900390555b6001600160a01b03808516600081815260046020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526004602052604090205481111561070657600080fd5b33600081815260046020526040808220805485900390555183156108fc0291849190818181858888f19350505050158015610745573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60035460ff1681565b3360009081526006602052604090205460ff16806107b057506000546001600160a01b031633145b610801576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b038216600081815260046020908152604091829020805485019055815184815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a25050565b6001600160a01b031660009081526006602052604090205460ff1690565b60046020526000908152604090205481565b6002805460408051602060018416156101000260001901909316849004601f810184900484028201840190925281815292918301828280156105445780601f1061051957610100808354040283529160200191610544565b3360009081526006602052604090205460ff168061090857506000546001600160a01b031633145b610959576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b038116600081815260066020526040808220805460ff19166001179055517feb61edd6570e8798f968e1e8c0114e1e25557b015c7ac44f7aeaf4a67ef3bc239190a250565b3360009081526006602052604090205460ff16806109cd57506000546001600160a01b031633145b610a1e576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b03821660008181526004602090815260409182902080548590039055815184815291517f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659281900390910190a25050565b6000610a833384846105b6565b9392505050565b600560209081526000928352604080842090915290825290205481565b3360009081526006602052604090205460ff1680610acf57506000546001600160a01b031633145b610b20576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b038116600081815260066020526040808220805460ff19169055517feedc52ad501f0ddd2dca82b61f1b96f1f84b898d242eced1210037c8a569074e9190a25056fea2646970667358221220ec530975ca401232772f3a285d9b8886a8edcb1c247cd71c6d597b161a5bb7c464736f6c63430007060033\",\n  \"deployedBytecode\": \"0x6080604052600436106100f75760003560e01c806370a082311161008a578063a9059cbb11610059578063a9059cbb146103c1578063d0e30db0146103fa578063dd62ed3e14610402578063e5affcb81461043d57610106565b806370a082311461030d57806395d89b41146103405780639bb257ad146103555780639dc29fac1461038857610106565b80632e1a7d4d116100c65780632e1a7d4d1461024c578063313ce5671461027657806340c10f19146102a1578063555c3002146102da57610106565b806306fdde031461010b578063095ea7b31461019557806318160ddd146101e257806323b872dd1461020957610106565b3661010657610104610470565b005b600080fd5b34801561011757600080fd5b506101206104bf565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015a578181015183820152602001610142565b50505050905090810190601f1680156101875780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101a157600080fd5b506101ce600480360360408110156101b857600080fd5b506001600160a01b03813516906020013561054c565b604080519115158252519081900360200190f35b3480156101ee57600080fd5b506101f76105b2565b60408051918252519081900360200190f35b34801561021557600080fd5b506101ce6004803603606081101561022c57600080fd5b506001600160a01b038135811691602081013590911690604001356105b6565b34801561025857600080fd5b506101046004803603602081101561026f57600080fd5b50356106ea565b34801561028257600080fd5b5061028b61077f565b6040805160ff9092168252519081900360200190f35b3480156102ad57600080fd5b50610104600480360360408110156102c457600080fd5b506001600160a01b038135169060200135610788565b3480156102e657600080fd5b506101ce600480360360208110156102fd57600080fd5b50356001600160a01b0316610858565b34801561031957600080fd5b506101f76004803603602081101561033057600080fd5b50356001600160a01b0316610876565b34801561034c57600080fd5b50610120610888565b34801561036157600080fd5b506101046004803603602081101561037857600080fd5b50356001600160a01b03166108e0565b34801561039457600080fd5b50610104600480360360408110156103ab57600080fd5b506001600160a01b0381351690602001356109a5565b3480156103cd57600080fd5b506101ce600480360360408110156103e457600080fd5b506001600160a01b038135169060200135610a76565b610104610470565b34801561040e57600080fd5b506101f76004803603604081101561042557600080fd5b506001600160a01b0381358116916020013516610a8a565b34801561044957600080fd5b506101046004803603602081101561046057600080fd5b50356001600160a01b0316610aa7565b33600081815260046020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105445780601f1061051957610100808354040283529160200191610544565b820191906000526020600020905b81548152906001019060200180831161052757829003601f168201915b505050505081565b3360008181526005602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b6001600160a01b0383166000908152600460205260408120548211156105db57600080fd5b6001600160a01b038416331480159061061957506001600160a01b038416600090815260056020908152604080832033845290915290205460001914155b15610679576001600160a01b038416600090815260056020908152604080832033845290915290205482111561064e57600080fd5b6001600160a01b03841660009081526005602090815260408083203384529091529020805483900390555b6001600160a01b03808516600081815260046020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526004602052604090205481111561070657600080fd5b33600081815260046020526040808220805485900390555183156108fc0291849190818181858888f19350505050158015610745573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60035460ff1681565b3360009081526006602052604090205460ff16806107b057506000546001600160a01b031633145b610801576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b038216600081815260046020908152604091829020805485019055815184815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a25050565b6001600160a01b031660009081526006602052604090205460ff1690565b60046020526000908152604090205481565b6002805460408051602060018416156101000260001901909316849004601f810184900484028201840190925281815292918301828280156105445780601f1061051957610100808354040283529160200191610544565b3360009081526006602052604090205460ff168061090857506000546001600160a01b031633145b610959576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b038116600081815260066020526040808220805460ff19166001179055517feb61edd6570e8798f968e1e8c0114e1e25557b015c7ac44f7aeaf4a67ef3bc239190a250565b3360009081526006602052604090205460ff16806109cd57506000546001600160a01b031633145b610a1e576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b03821660008181526004602090815260409182902080548590039055815184815291517f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659281900390910190a25050565b6000610a833384846105b6565b9392505050565b600560209081526000928352604080842090915290825290205481565b3360009081526006602052604090205460ff1680610acf57506000546001600160a01b031633145b610b20576040805162461bcd60e51b815260206004820181905260248201527f41646472657373206e6f7420612077686974656c6973746564206d696e746572604482015290519081900360640190fd5b6001600160a01b038116600081815260066020526040808220805460ff19169055517feedc52ad501f0ddd2dca82b61f1b96f1f84b898d242eced1210037c8a569074e9190a25056fea2646970667358221220ec530975ca401232772f3a285d9b8886a8edcb1c247cd71c6d597b161a5bb7c464736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"blacklistMinter(address)\": {\n        \"params\": {\n          \"_account\": \"address of minter to be blacklisted\"\n        }\n      },\n      \"isWhitelistedMinter(address)\": {\n        \"params\": {\n          \"_account\": \"address of minter\"\n        },\n        \"returns\": {\n          \"_0\": \"boolean, True if address is a whitelisted minter\"\n        }\n      },\n      \"whitelistMinter(address)\": {\n        \"params\": {\n          \"_account\": \"address of minter to be whitelisted\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"blacklistMinter(address)\": {\n        \"notice\": \"allow the minter to blacklist other minters\"\n      },\n      \"isWhitelistedMinter(address)\": {\n        \"notice\": \"check if a minter is whitelisted\"\n      },\n      \"whitelistMinter(address)\": {\n        \"notice\": \"allows the minter to whitelist other minters\"\n      }\n    },\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 3,\n        \"contract\": \"contracts/mocks/OpynWETH9.sol:OpynWETH9\",\n        \"label\": \"owner\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 6,\n        \"contract\": \"contracts/mocks/OpynWETH9.sol:OpynWETH9\",\n        \"label\": \"name\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 9,\n        \"contract\": \"contracts/mocks/OpynWETH9.sol:OpynWETH9\",\n        \"label\": \"symbol\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 12,\n        \"contract\": \"contracts/mocks/OpynWETH9.sol:OpynWETH9\",\n        \"label\": \"decimals\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_uint8\"\n      },\n      {\n        \"astId\": 52,\n        \"contract\": \"contracts/mocks/OpynWETH9.sol:OpynWETH9\",\n        \"label\": \"balanceOf\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 58,\n        \"contract\": \"contracts/mocks/OpynWETH9.sol:OpynWETH9\",\n        \"label\": \"allowance\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n      },\n      {\n        \"astId\": 62,\n        \"contract\": \"contracts/mocks/OpynWETH9.sol:OpynWETH9\",\n        \"label\": \"whitelistedMinters\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_mapping(t_address,t_bool)\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_mapping(t_address,t_bool)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => bool)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_bool\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => uint256))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_uint256)\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint8\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint8\",\n        \"numberOfBytes\": \"1\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/Oracle.json",
    "content": "{\n  \"address\": \"0xf7F94b4607Bcd1235212803bE8fD1B54D1D01b77\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_base\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_quote\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_secondsAgoToStartOfTwap\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_secondsAgoToEndOfTwap\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getHistoricalTwap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"getMaxPeriod\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getTimeWeightedAverageTickSafe\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"timeWeightedAverageTick\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_base\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_quote\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_checkPeriod\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getTwap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0xd436ffbf68d9d86ebfd72e6de9c7e8aed718ce2e31fe3d4e3ac2ada002465a3e\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0xf7F94b4607Bcd1235212803bE8fD1B54D1D01b77\",\n    \"transactionIndex\": 28,\n    \"gasUsed\": \"874024\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x85c749aa4e450f215874aea8ac6ef8accf6fa23add59a9c1882f4e92a9469198\",\n    \"transactionHash\": \"0xd436ffbf68d9d86ebfd72e6de9c7e8aed718ce2e31fe3d4e3ac2ada002465a3e\",\n    \"logs\": [],\n    \"blockNumber\": 8008055,\n    \"cumulativeGasUsed\": \"5228998\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_base\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_quote\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_secondsAgoToStartOfTwap\\\",\\\"type\\\":\\\"uint32\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_secondsAgoToEndOfTwap\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getHistoricalTwap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"getMaxPeriod\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getTimeWeightedAverageTickSafe\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"timeWeightedAverageTick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_base\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_quote\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_checkPeriod\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getTwap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"details\\\":\\\"if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"getHistoricalTwap(address,address,address,uint32,uint32)\\\":{\\\"details\\\":\\\"if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\",\\\"params\\\":{\\\"_base\\\":\\\"base currency. to get eth/usd price, eth is base token\\\",\\\"_pool\\\":\\\"uniswap pool address\\\",\\\"_quote\\\":\\\"quote currency. to get eth/usd price, usd is the quote currency\\\",\\\"_secondsAgoToEndOfTwap\\\":\\\"amount of seconds in the past to end calculating time-weighted average\\\",\\\"_secondsAgoToStartOfTwap\\\":\\\"amount of seconds in the past to start calculating time-weighted average\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"price of 1 base currency in quote currency. scaled by 1e18\\\"}},\\\"getMaxPeriod(address)\\\":{\\\"params\\\":{\\\"_pool\\\":\\\"uniswap pool address\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"max period can be used to request twap\\\"}},\\\"getTimeWeightedAverageTickSafe(address,uint32)\\\":{\\\"details\\\":\\\"this function will not revert\\\",\\\"params\\\":{\\\"_period\\\":\\\"period in second that we want to calculate average on\\\",\\\"_pool\\\":\\\"address of the pool\\\"},\\\"returns\\\":{\\\"timeWeightedAverageTick\\\":\\\"the time weighted average tick\\\"}},\\\"getTwap(address,address,address,uint32,bool)\\\":{\\\"details\\\":\\\"if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\",\\\"params\\\":{\\\"_base\\\":\\\"base currency. to get eth/usd price, eth is base token\\\",\\\"_period\\\":\\\"number of seconds in the past to start calculating time-weighted average\\\",\\\"_pool\\\":\\\"uniswap pool address\\\",\\\"_quote\\\":\\\"quote currency. to get eth/usd price, usd is the quote currency\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"price of 1 base currency in quote currency. scaled by 1e18\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"getHistoricalTwap(address,address,address,uint32,uint32)\\\":{\\\"notice\\\":\\\"get twap for a specific period of time, converted with base & quote token decimals\\\"},\\\"getMaxPeriod(address)\\\":{\\\"notice\\\":\\\"get the max period that can be used to request twap\\\"},\\\"getTimeWeightedAverageTickSafe(address,uint32)\\\":{\\\"notice\\\":\\\"get time weighed average tick, not converted to price\\\"},\\\"getTwap(address,address,address,uint32,bool)\\\":{\\\"notice\\\":\\\"get twap converted with base & quote token decimals\\\"}},\\\"notice\\\":\\\"read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/Oracle.sol\\\":\\\"Oracle\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/core/Oracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\n// uniswap Library only works under 0.7.6\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IERC20Detailed} from \\\\\\\"../interfaces/IERC20Detailed.sol\\\\\\\";\\\\n\\\\n//library\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"../libs/Uint256Casting.sol\\\\\\\";\\\\nimport {OracleLibrary} from \\\\\\\"../libs/OracleLibrary.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\\\n */\\\\ncontract Oracle {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint128 private constant ONE = 1e18;\\\\n\\\\n    /**\\\\n     * @notice get twap converted with base & quote token decimals\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\\\n     */\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256) {\\\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\\\n\\\\n        // make sure the requested period < maxPeriod the pool recorded.\\\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\\\n     */\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _secondsAgoToStartOfTwap,\\\\n        uint32 _secondsAgoToEndOfTwap\\\\n    ) external view returns (uint256) {\\\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the max period that can be used to request twap\\\\n     * @param _pool uniswap pool address\\\\n     * @return max period can be used to request twap\\\\n     */\\\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\\\n        return _getMaxPeriod(_pool);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get time weighed average tick, not converted to price\\\\n     * @dev this function will not revert\\\\n     * @param _pool address of the pool\\\\n     * @param _period period in second that we want to calculate average on\\\\n     * @return timeWeightedAverageTick the time weighted average tick\\\\n     */\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick)\\\\n    {\\\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap converted with base & quote token decimals\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return twap price which is scaled\\\\n     */\\\\n    function _fetchTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\\\n\\\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\\\n\\\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\\\n\\\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get raw twap from the uniswap pool\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\".\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return amount of quote currency received for _amountIn of base currency\\\\n     */\\\\n    function _fetchRawTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\\\n     */\\\\n    function _fetchHistoricTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _secondsAgoToStartOfTwap,\\\\n        uint32 _secondsAgoToEndOfTwap\\\\n    ) internal view returns (uint256) {\\\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\\\n\\\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the max period that can be used to request twap\\\\n     * @param _pool uniswap pool address\\\\n     * @return max period can be used to request twap\\\\n     */\\\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\\\n        // observationIndex: the index of the last oracle observation that was written\\\\n        // cardinality: the current maximum number of observations stored in the pool\\\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\\\n\\\\n        // first observation index\\\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\\\n\\\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\\\n\\\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\\\n\\\\n        // (index + 1) % cardinality is not the oldest index,\\\\n        // probably because cardinality is increased after last observation.\\\\n        // in this case, observation at index 0 should be the oldest.\\\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\\\n\\\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc264ae8c3df6e1db22a95c30e3bbca563d4a351fbfc7d0428fb0da76567aa661\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IERC20Detailed.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// uniswap Library only works under 0.7.6\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IERC20Detailed is IERC20 {\\\\n    function decimals() external view returns (uint8);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcd59a0158d0711810c499904b9d37a71fdb34d1c4403f3cb67ca47de5e88bf7b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/OracleLibrary.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\n//interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\n\\\\n/// @title oracle library\\\\n/// @notice provides functions to integrate with uniswap v3 oracle\\\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\\\nlibrary OracleLibrary {\\\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\\\n    /// @dev written by opyn team\\\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\\\n    function consultAtHistoricTime(\\\\n        address pool,\\\\n        uint32 _secondsAgoToStartOfTwap,\\\\n        uint32 _secondsAgoToEndOfTwap\\\\n    ) internal view returns (int24) {\\\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\\\\\"BP\\\\\\\");\\\\n        int24 timeWeightedAverageTick;\\\\n        uint32[] memory secondAgos = new uint32[](2);\\\\n\\\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\\\n\\\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\\\n\\\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\\\n\\\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\\\n\\\\n        // Always round to negative infinity\\\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\\\n\\\\n        return timeWeightedAverageTick;\\\\n    }\\\\n\\\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\\\n    /// @param tick tick value used to calculate the quote\\\\n    /// @param baseAmount amount of token to be converted\\\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\\\n    function getQuoteAtTick(\\\\n        int24 tick,\\\\n        uint128 baseAmount,\\\\n        address baseToken,\\\\n        address quoteToken\\\\n    ) internal pure returns (uint256 quoteAmount) {\\\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\\\n\\\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\\\n        if (sqrtRatioX96 <= type(uint128).max) {\\\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\\\n            quoteAmount = baseToken < quoteToken\\\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\\\n        } else {\\\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\\\n            quoteAmount = baseToken < quoteToken\\\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x83858224ba4dc88b7ab7f26de42c32d2debfd48a59bd5d011afe7be5d7cbb24f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x608060405234801561001057600080fd5b50610edc806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634a0a96eb146100515780634ac78d111461009a578063cce79bd5146100f6578063de5a6e2214610140575b600080fd5b6100836004803603604081101561006757600080fd5b5080356001600160a01b0316906020013563ffffffff1661017f565b6040805160029290920b8252519081900360200190f35b6100e4600480360360a08110156100b057600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013581169160800135166101c3565b60408051918252519081900360200190f35b6100e4600480360360a081101561010c57600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013516906080013515156101de565b6101666004803603602081101561015657600080fd5b50356001600160a01b031661023c565b6040805163ffffffff9092168252519081900360200190f35b60008061018b8461024f565b905060008163ffffffff168463ffffffff16116101a857836101aa565b815b90506101b8858260006103fb565b925050505b92915050565b60006101d28686868686610713565b90505b95945050505050565b6000816101f8576101f186868686610742565b90506101d5565b60006102038761024f565b905060008163ffffffff168563ffffffff16116102205784610222565b815b905061023088888884610742565b98975050505050505050565b60006102478261024f565b90505b919050565b600080829050600080826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561029157600080fd5b505afa1580156102a5573d6000803e3d6000fd5b505050506040513d60e08110156102bb57600080fd5b5060408101516060909101519092509050600061ffff808316906001850116816102e157fe5b069050600080856001600160a01b031663252c09d7846040518263ffffffff1660e01b8152600401808261ffff16815260200191505060806040518083038186803b15801561032f57600080fd5b505afa158015610343573d6000803e3d6000fd5b505050506040513d608081101561035957600080fd5b5080516060909101519092509050801561037c57504203945061024a9350505050565b856001600160a01b031663252c09d760006040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b1580156103c157600080fd5b505afa1580156103d5573d6000803e3d6000fd5b505050506040513d60808110156103eb57600080fd5b5051420398975050505050505050565b60008163ffffffff168363ffffffff1611610442576040805162461bcd60e51b8152602060048201526002602482015261042560f41b604482015290519081900360640190fd5b6040805160028082526060820183526000928392919060208301908036833701905050905060008486039050858260008151811061047c57fe5b602002602001019063ffffffff16908163ffffffff168152505084826001815181106104a457fe5b63ffffffff90921660209283029190910182015260405163883bdbfd60e01b8152600481018281528451602483015284516000936001600160a01b038c169363883bdbfd938893909283926044019185820191028083838b5b838110156105155781810151838201526020016104fd565b505050509050019250505060006040518083038186803b15801561053857600080fd5b505afa15801561054c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604090815281101561057557600080fd5b810190808051604051939291908464010000000082111561059557600080fd5b9083019060208201858111156105aa57600080fd5b82518660208202830111640100000000821117156105c757600080fd5b82525081516020918201928201910280838360005b838110156105f45781810151838201526020016105dc565b505050509050016040526020018051604051939291908464010000000082111561061d57600080fd5b90830190602082018581111561063257600080fd5b825186602082028301116401000000008211171561064f57600080fd5b82525081516020918201928201910280838360005b8381101561067c578181015183820152602001610664565b5050505090500160405250505050905060008160008151811061069b57fe5b6020026020010151826001815181106106b057fe5b60200260200101510390508263ffffffff168160060b816106cd57fe5b05945060008160060b1280156106f757508263ffffffff168160060b816106f057fe5b0760060b15155b1561070457600019909401935b509293505050505b9392505050565b6000806107218785856103fb565b905061073781670de0b6b3a76400008888610891565b979650505050505050565b600080610751868686866109b5565b90506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561078e57600080fd5b505afa1580156107a2573d6000803e3d6000fd5b505050506040513d60208110156107b857600080fd5b50516040805163313ce56760e01b815290519192506000916001600160a01b0388169163313ce567916004808301926020929190829003018186803b15801561080057600080fd5b505afa158015610814573d6000803e3d6000fd5b505050506040513d602081101561082a57600080fd5b5051905060ff828116908216141561084757829350505050610889565b8060ff168260ff161115610871576108678360ff83850316600a0a6109e4565b9350505050610889565b6108838360ff84840316600a0a610a3d565b93505050505b949350505050565b60008061089d86610aa4565b90506fffffffffffffffffffffffffffffffff6001600160a01b03821611610927576001600160a01b03808216800290848116908616106108fe576108f9600160c01b876fffffffffffffffffffffffffffffffff1683610dd6565b61091f565b61091f81876fffffffffffffffffffffffffffffffff16600160c01b610dd6565b9250506109ac565b60006109466001600160a01b0383168068010000000000000000610dd6565b9050836001600160a01b0316856001600160a01b03161061098757610982600160801b876fffffffffffffffffffffffffffffffff1683610dd6565b6109a8565b6109a881876fffffffffffffffffffffffffffffffff16600160801b610dd6565b9250505b50949350505050565b6000806109c4868460006103fb565b90506109da81670de0b6b3a76400008787610891565b9695505050505050565b6000826109f3575060006101bd565b82820282848281610a0057fe5b041461070c5760405162461bcd60e51b8152600401808060200182810382526021815260200180610e866021913960400191505060405180910390fd5b6000808211610a93576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610a9c57fe5b049392505050565b60008060008360020b12610abb578260020b610ac3565b8260020b6000035b9050620d89e8811115610b01576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216610b1557600160801b610b27565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610b5b576ffff97272373d413259a46990580e213a0260801c5b6004821615610b7a576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615610b99576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610bb8576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610bd7576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610bf6576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610c15576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610c35576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615610c55576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615610c75576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615610c95576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610cb5576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610cd5576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610cf5576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610d15576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610d36576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615610d56576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615610d75576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615610d92576b048a170391f7dc42444e8fa20260801c5b60008460020b1315610dad578060001981610da957fe5b0490505b640100000000810615610dc1576001610dc4565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080610e0c5760008411610e0157600080fd5b50829004905061070c565b808411610e1857600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a0290910302918190038190046001018684119095039490940291909403929092049190911791909102915050939250505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220b0fc899a7fd2e3e0f61c4b7468f610970c734e3b1f6f41cd4c65ec5ba31990c264736f6c63430007060033\",\n  \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80634a0a96eb146100515780634ac78d111461009a578063cce79bd5146100f6578063de5a6e2214610140575b600080fd5b6100836004803603604081101561006757600080fd5b5080356001600160a01b0316906020013563ffffffff1661017f565b6040805160029290920b8252519081900360200190f35b6100e4600480360360a08110156100b057600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013581169160800135166101c3565b60408051918252519081900360200190f35b6100e4600480360360a081101561010c57600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013516906080013515156101de565b6101666004803603602081101561015657600080fd5b50356001600160a01b031661023c565b6040805163ffffffff9092168252519081900360200190f35b60008061018b8461024f565b905060008163ffffffff168463ffffffff16116101a857836101aa565b815b90506101b8858260006103fb565b925050505b92915050565b60006101d28686868686610713565b90505b95945050505050565b6000816101f8576101f186868686610742565b90506101d5565b60006102038761024f565b905060008163ffffffff168563ffffffff16116102205784610222565b815b905061023088888884610742565b98975050505050505050565b60006102478261024f565b90505b919050565b600080829050600080826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561029157600080fd5b505afa1580156102a5573d6000803e3d6000fd5b505050506040513d60e08110156102bb57600080fd5b5060408101516060909101519092509050600061ffff808316906001850116816102e157fe5b069050600080856001600160a01b031663252c09d7846040518263ffffffff1660e01b8152600401808261ffff16815260200191505060806040518083038186803b15801561032f57600080fd5b505afa158015610343573d6000803e3d6000fd5b505050506040513d608081101561035957600080fd5b5080516060909101519092509050801561037c57504203945061024a9350505050565b856001600160a01b031663252c09d760006040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b1580156103c157600080fd5b505afa1580156103d5573d6000803e3d6000fd5b505050506040513d60808110156103eb57600080fd5b5051420398975050505050505050565b60008163ffffffff168363ffffffff1611610442576040805162461bcd60e51b8152602060048201526002602482015261042560f41b604482015290519081900360640190fd5b6040805160028082526060820183526000928392919060208301908036833701905050905060008486039050858260008151811061047c57fe5b602002602001019063ffffffff16908163ffffffff168152505084826001815181106104a457fe5b63ffffffff90921660209283029190910182015260405163883bdbfd60e01b8152600481018281528451602483015284516000936001600160a01b038c169363883bdbfd938893909283926044019185820191028083838b5b838110156105155781810151838201526020016104fd565b505050509050019250505060006040518083038186803b15801561053857600080fd5b505afa15801561054c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604090815281101561057557600080fd5b810190808051604051939291908464010000000082111561059557600080fd5b9083019060208201858111156105aa57600080fd5b82518660208202830111640100000000821117156105c757600080fd5b82525081516020918201928201910280838360005b838110156105f45781810151838201526020016105dc565b505050509050016040526020018051604051939291908464010000000082111561061d57600080fd5b90830190602082018581111561063257600080fd5b825186602082028301116401000000008211171561064f57600080fd5b82525081516020918201928201910280838360005b8381101561067c578181015183820152602001610664565b5050505090500160405250505050905060008160008151811061069b57fe5b6020026020010151826001815181106106b057fe5b60200260200101510390508263ffffffff168160060b816106cd57fe5b05945060008160060b1280156106f757508263ffffffff168160060b816106f057fe5b0760060b15155b1561070457600019909401935b509293505050505b9392505050565b6000806107218785856103fb565b905061073781670de0b6b3a76400008888610891565b979650505050505050565b600080610751868686866109b5565b90506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561078e57600080fd5b505afa1580156107a2573d6000803e3d6000fd5b505050506040513d60208110156107b857600080fd5b50516040805163313ce56760e01b815290519192506000916001600160a01b0388169163313ce567916004808301926020929190829003018186803b15801561080057600080fd5b505afa158015610814573d6000803e3d6000fd5b505050506040513d602081101561082a57600080fd5b5051905060ff828116908216141561084757829350505050610889565b8060ff168260ff161115610871576108678360ff83850316600a0a6109e4565b9350505050610889565b6108838360ff84840316600a0a610a3d565b93505050505b949350505050565b60008061089d86610aa4565b90506fffffffffffffffffffffffffffffffff6001600160a01b03821611610927576001600160a01b03808216800290848116908616106108fe576108f9600160c01b876fffffffffffffffffffffffffffffffff1683610dd6565b61091f565b61091f81876fffffffffffffffffffffffffffffffff16600160c01b610dd6565b9250506109ac565b60006109466001600160a01b0383168068010000000000000000610dd6565b9050836001600160a01b0316856001600160a01b03161061098757610982600160801b876fffffffffffffffffffffffffffffffff1683610dd6565b6109a8565b6109a881876fffffffffffffffffffffffffffffffff16600160801b610dd6565b9250505b50949350505050565b6000806109c4868460006103fb565b90506109da81670de0b6b3a76400008787610891565b9695505050505050565b6000826109f3575060006101bd565b82820282848281610a0057fe5b041461070c5760405162461bcd60e51b8152600401808060200182810382526021815260200180610e866021913960400191505060405180910390fd5b6000808211610a93576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610a9c57fe5b049392505050565b60008060008360020b12610abb578260020b610ac3565b8260020b6000035b9050620d89e8811115610b01576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216610b1557600160801b610b27565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610b5b576ffff97272373d413259a46990580e213a0260801c5b6004821615610b7a576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615610b99576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610bb8576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610bd7576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610bf6576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610c15576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610c35576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615610c55576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615610c75576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615610c95576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610cb5576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610cd5576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610cf5576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610d15576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610d36576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615610d56576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615610d75576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615610d92576b048a170391f7dc42444e8fa20260801c5b60008460020b1315610dad578060001981610da957fe5b0490505b640100000000810615610dc1576001610dc4565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080610e0c5760008411610e0157600080fd5b50829004905061070c565b808411610e1857600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a0290910302918190038190046001018684119095039490940291909403929092049190911791909102915050939250505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220b0fc899a7fd2e3e0f61c4b7468f610970c734e3b1f6f41cd4c65ec5ba31990c264736f6c63430007060033\",\n  \"devdoc\": {\n    \"details\": \"if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"getHistoricalTwap(address,address,address,uint32,uint32)\": {\n        \"details\": \"if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\",\n        \"params\": {\n          \"_base\": \"base currency. to get eth/usd price, eth is base token\",\n          \"_pool\": \"uniswap pool address\",\n          \"_quote\": \"quote currency. to get eth/usd price, usd is the quote currency\",\n          \"_secondsAgoToEndOfTwap\": \"amount of seconds in the past to end calculating time-weighted average\",\n          \"_secondsAgoToStartOfTwap\": \"amount of seconds in the past to start calculating time-weighted average\"\n        },\n        \"returns\": {\n          \"_0\": \"price of 1 base currency in quote currency. scaled by 1e18\"\n        }\n      },\n      \"getMaxPeriod(address)\": {\n        \"params\": {\n          \"_pool\": \"uniswap pool address\"\n        },\n        \"returns\": {\n          \"_0\": \"max period can be used to request twap\"\n        }\n      },\n      \"getTimeWeightedAverageTickSafe(address,uint32)\": {\n        \"details\": \"this function will not revert\",\n        \"params\": {\n          \"_period\": \"period in second that we want to calculate average on\",\n          \"_pool\": \"address of the pool\"\n        },\n        \"returns\": {\n          \"timeWeightedAverageTick\": \"the time weighted average tick\"\n        }\n      },\n      \"getTwap(address,address,address,uint32,bool)\": {\n        \"details\": \"if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\",\n        \"params\": {\n          \"_base\": \"base currency. to get eth/usd price, eth is base token\",\n          \"_period\": \"number of seconds in the past to start calculating time-weighted average\",\n          \"_pool\": \"uniswap pool address\",\n          \"_quote\": \"quote currency. to get eth/usd price, usd is the quote currency\"\n        },\n        \"returns\": {\n          \"_0\": \"price of 1 base currency in quote currency. scaled by 1e18\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"getHistoricalTwap(address,address,address,uint32,uint32)\": {\n        \"notice\": \"get twap for a specific period of time, converted with base & quote token decimals\"\n      },\n      \"getMaxPeriod(address)\": {\n        \"notice\": \"get the max period that can be used to request twap\"\n      },\n      \"getTimeWeightedAverageTickSafe(address,uint32)\": {\n        \"notice\": \"get time weighed average tick, not converted to price\"\n      },\n      \"getTwap(address,address,address,uint32,bool)\": {\n        \"notice\": \"get twap converted with base & quote token decimals\"\n      }\n    },\n    \"notice\": \"read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/Quoter.json",
    "content": "{\n  \"address\": \"0x759442726c06F7938cd2cB63aC9Ae373Dc1dEcf6\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_factory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_WETH9\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"WETH9\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"path\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"quoteExactInput\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160[]\",\n          \"name\": \"sqrtPriceX96AfterList\",\n          \"type\": \"uint160[]\"\n        },\n        {\n          \"internalType\": \"uint32[]\",\n          \"name\": \"initializedTicksCrossedList\",\n          \"type\": \"uint32[]\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountIn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct IQuoterV2.QuoteExactInputSingleParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"quoteExactInputSingle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96After\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"initializedTicksCrossed\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"path\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"quoteExactOutput\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160[]\",\n          \"name\": \"sqrtPriceX96AfterList\",\n          \"type\": \"uint160[]\"\n        },\n        {\n          \"internalType\": \"uint32[]\",\n          \"name\": \"initializedTicksCrossedList\",\n          \"type\": \"uint32[]\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct IQuoterV2.QuoteExactOutputSingleParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"quoteExactOutputSingle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96After\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"initializedTicksCrossed\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"path\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x8662756f80cffc50cceda827664bf46ad0a9350a57597b3d68e978508a387879\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x759442726c06F7938cd2cB63aC9Ae373Dc1dEcf6\",\n    \"transactionIndex\": 19,\n    \"gasUsed\": \"1836365\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x0cd3c547e1aa61689863d79450b1c4a0f0310830d5941aaaa708c688291a0746\",\n    \"transactionHash\": \"0x8662756f80cffc50cceda827664bf46ad0a9350a57597b3d68e978508a387879\",\n    \"logs\": [],\n    \"blockNumber\": 8007331,\n    \"cumulativeGasUsed\": \"7712175\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n    \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\"\n  ],\n  \"bytecode\": \"0x60c06040523480156200001157600080fd5b506040516200212c3803806200212c833981016040819052620000349162000070565b6001600160601b0319606092831b8116608052911b1660a052620000a7565b80516001600160a01b03811681146200006b57600080fd5b919050565b6000806040838503121562000083578182fd5b6200008e8362000053565b91506200009e6020840162000053565b90509250929050565b60805160601c60a05160601c612051620000db60003980610321525080610577528061095d5280610b9252506120516000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063c45a01551161005b578063c45a0155146100e6578063c6a5026a146100ee578063cdca175314610101578063fa461e33146101145761007d565b80632f80bb1d146100825780634aa4a4fc146100ae578063bd21704a146100c3575b600080fd5b610095610090366004611b2b565b610129565b6040516100a59493929190611eac565b60405180910390f35b6100b661031f565b6040516100a59190611def565b6100d66100d1366004611c49565b610343565b6040516100a59493929190611f54565b6100b6610575565b6100d66100fc366004611c49565b610599565b61009561010f366004611b2b565b610754565b610127610122366004611b91565b61092c565b005b6000606080600061013986610ae8565b67ffffffffffffffff8111801561014f57600080fd5b50604051908082528060200260200182016040528015610179578160200160208202803683370190505b50925061018586610ae8565b67ffffffffffffffff8111801561019b57600080fd5b506040519080825280602002602001820160405280156101c5578160200160208202803683370190505b50915060005b60008060006101d98a610b17565b92509250925060008060008061025c6040518060a001604052808873ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018f81526020018762ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250610343565b9350935093509350828b898151811061027157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818a89815181106102b857fe5b63ffffffff90921660209283029190910190910152929b50968201966001909601958b926102e58e610b48565b156102fa576102f38e610b50565b9d5061030a565b8c9b505050505050505050610316565b505050505050506101cb565b92959194509250565b7f000000000000000000000000000000000000000000000000000000000000000081565b60208101518151606083015160009283928392839273ffffffffffffffffffffffffffffffffffffffff808216908416109284926103819290610b8b565b9050866080015173ffffffffffffffffffffffffffffffffffffffff16600014156103af5760408701516000555b60005a90508173ffffffffffffffffffffffffffffffffffffffff1663128acb0830856103df8c60400151610bc9565b6000038c6080015173ffffffffffffffffffffffffffffffffffffffff1660001461040e578c60800151610434565b8761042d5773fffd8963efd1fc6a506488495d951d5263988d25610434565b6401000276a45b8d602001518e606001518f6000015160405160200161045593929190611d89565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610484959493929190611e10565b6040805180830381600087803b15801561049d57600080fd5b505af19250505080156104eb575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526104e891810190611b6e565b60015b610568573d808015610519576040519150601f19603f3d011682016040523d82523d6000602084013e61051e565b606091505b505a82039450886080015173ffffffffffffffffffffffffffffffffffffffff166000141561054c57600080555b610557818487610bfb565b97509750975097505050505061056e565b50505050505b9193509193565b7f000000000000000000000000000000000000000000000000000000000000000081565b60208101518151606083015160009283928392839273ffffffffffffffffffffffffffffffffffffffff808216908416109284926105d79290610b8b565b905060005a90508173ffffffffffffffffffffffffffffffffffffffff1663128acb0830856106098c60400151610bc9565b60808d015173ffffffffffffffffffffffffffffffffffffffff1615610633578c60800151610659565b876106525773fffd8963efd1fc6a506488495d951d5263988d25610659565b6401000276a45b8d600001518e606001518f6020015160405160200161067a93929190611d89565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016106a9959493929190611e10565b6040805180830381600087803b1580156106c257600080fd5b505af1925050508015610710575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261070d91810190611b6e565b60015b610568573d80801561073e576040519150601f19603f3d011682016040523d82523d6000602084013e610743565b606091505b505a82039450610557818487610bfb565b6000606080600061076486610ae8565b67ffffffffffffffff8111801561077a57600080fd5b506040519080825280602002602001820160405280156107a4578160200160208202803683370190505b5092506107b086610ae8565b67ffffffffffffffff811180156107c657600080fd5b506040519080825280602002602001820160405280156107f0578160200160208202803683370190505b50915060005b60008060006108048a610b17565b9250925092506000806000806108876040518060a001604052808973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018f81526020018762ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250610599565b9350935093509350828b898151811061089c57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818a89815181106108e357fe5b63ffffffff90921660209283029190910190910152929b50968201966001909601958b926109108e610b48565b156102fa5761091e8e610b50565b9d50505050505050506107f6565b600083138061093b5750600082135b61094457600080fd5b600080600061095284610b17565b9250925092506109847f0000000000000000000000000000000000000000000000000000000000000000848484610ccf565b5060008060008089136109ca578573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1610888a6000036109ff565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161089896000035b9250925092506000610a12878787610b8b565b90506000808273ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610a5d57600080fd5b505afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190611c6b565b5050505050915091508515610abb57604051848152826020820152816040820152606081fd5b60005415610ad1576000548414610ad157600080fd5b604051858152826020820152816040820152606081fd5b805160177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec909101045b919050565b60008080610b258482610cee565b9250610b32846014610dee565b9050610b3f846017610cee565b91509193909250565b516042111590565b8051606090610b859083906017907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901610ede565b92915050565b6000610bc17f0000000000000000000000000000000000000000000000000000000000000000610bbc8686866110c5565b611142565b949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210610bf757600080fd5b5090565b6000806000806000808773ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610c4a57600080fd5b505afa158015610c5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c829190611c6b565b50939650610c9794508d935061127892505050565b91975095509050610cbf73ffffffffffffffffffffffffffffffffffffffff89168383611339565b9350869250505093509350935093565b6000610ce585610ce08686866110c5565b611991565b95945050505050565b600081826014011015610d6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b8160140183511015610dd557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015610e6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b8160030183511015610ed557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b60608182601f011015610f5257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b828284011015610fc357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b8183018451101561103557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015290519081900360640190fd5b60608215801561105457604051915060008252602082016040526110bc565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561108d578051835260209283019201611075565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6110cd6119fa565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161115611105579192915b506040805160608101825273ffffffffffffffffffffffffffffffffffffffff948516815292909316602083015262ffffff169181019190915290565b6000816020015173ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff161061118457600080fd5b508051602080830151604093840151845173ffffffffffffffffffffffffffffffffffffffff94851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b60008060008351606014611318576044845110156112cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c290611e75565b60405180910390fd5b600484019350838060200190518101906112e59190611bdf565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c29190611e62565b8380602001905181019061132c9190611d02565b9250925092509193909250565b60008060008060008060008060088b73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561138d57600080fd5b505afa1580156113a1573d6000803e3d6000fd5b505050506040513d60208110156113b757600080fd5b5051600290810b908c900b816113c957fe5b0560020b901d905060006101008c73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561141c57600080fd5b505afa158015611430573d6000803e3d6000fd5b505050506040513d602081101561144657600080fd5b5051600290810b908d900b8161145857fe5b0560020b8161146357fe5b079050600060088d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114b057600080fd5b505afa1580156114c4573d6000803e3d6000fd5b505050506040513d60208110156114da57600080fd5b5051600290810b908d900b816114ec57fe5b0560020b901d905060006101008e73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561153f57600080fd5b505afa158015611553573d6000803e3d6000fd5b505050506040513d602081101561156957600080fd5b5051600290810b908e900b8161157b57fe5b0560020b8161158657fe5b07905060008160ff166001901b8f73ffffffffffffffffffffffffffffffffffffffff16635339c296856040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b5051161180156116a457508d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561166257600080fd5b505afa158015611676573d6000803e3d6000fd5b505050506040513d602081101561168c57600080fd5b5051600290810b908d900b8161169e57fe5b0760020b155b80156116b557508b60020b8d60020b135b945060008360ff166001901b8f73ffffffffffffffffffffffffffffffffffffffff16635339c296876040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b15801561171557600080fd5b505afa158015611729573d6000803e3d6000fd5b505050506040513d602081101561173f57600080fd5b5051161180156117d257508d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561179057600080fd5b505afa1580156117a4573d6000803e3d6000fd5b505050506040513d60208110156117ba57600080fd5b5051600290810b908e900b816117cc57fe5b0760020b155b80156117e357508b60020b8d60020b125b95508160010b8460010b128061180f57508160010b8460010b14801561180f57508060ff168360ff1611155b1561182557839950829750819850809650611832565b8199508097508398508296505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff87161b9150505b8560010b8760010b13611969578560010b8760010b14156118a3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff858103161c165b6000818c73ffffffffffffffffffffffffffffffffffffffff16635339c2968a6040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b1580156118fa57600080fd5b505afa15801561190e573d6000803e3d6000fd5b505050506040513d602081101561192457600080fd5b5051169050611932816119c1565b61ffff16989098019750506001909501947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61185e565b8115611976576001880397505b8215611983576001880397505b505050505050509392505050565b600061199d8383611142565b90503373ffffffffffffffffffffffffffffffffffffffff821614610b8557600080fd5b6000805b8215610b85577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301909216916001016119c5565b604080516060810182526000808252602082018190529181019190915290565b600082601f830112611a2a578081fd5b8135611a3d611a3882611faf565b611f8b565b818152846020838601011115611a51578283fd5b816020850160208301379081016020019190915292915050565b8051600281900b8114610b1257600080fd5b600060a08284031215611a8e578081fd5b60405160a0810181811067ffffffffffffffff82111715611aab57fe5b6040529050808235611abc8161201f565b81526020830135611acc8161201f565b602082015260408381013590820152606083013562ffffff81168114611af157600080fd5b6060820152611b0260808401611b0e565b60808201525092915050565b8035610b128161201f565b805161ffff81168114610b1257600080fd5b60008060408385031215611b3d578182fd5b823567ffffffffffffffff811115611b53578283fd5b611b5f85828601611a1a565b95602094909401359450505050565b60008060408385031215611b80578182fd5b505080516020909101519092909150565b600080600060608486031215611ba5578081fd5b8335925060208401359150604084013567ffffffffffffffff811115611bc9578182fd5b611bd586828701611a1a565b9150509250925092565b600060208284031215611bf0578081fd5b815167ffffffffffffffff811115611c06578182fd5b8201601f81018413611c16578182fd5b8051611c24611a3882611faf565b818152856020838501011115611c38578384fd5b610ce5826020830160208601611fef565b600060a08284031215611c5a578081fd5b611c648383611a7d565b9392505050565b600080600080600080600060e0888a031215611c85578283fd5b8751611c908161201f565b9650611c9e60208901611a6b565b9550611cac60408901611b19565b9450611cba60608901611b19565b9350611cc860808901611b19565b925060a088015160ff81168114611cdd578283fd5b60c08901519092508015158114611cf2578182fd5b8091505092959891949750929550565b600080600060608486031215611d16578081fd5b835192506020840151611d288161201f565b9150611d3660408501611a6b565b90509250925092565b60008151808452611d57816020860160208601611fef565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a06080830152611e5760a0830184611d3f565b979650505050505050565b600060208252611c646020830184611d3f565b60208082526010908201527f556e6578706563746564206572726f7200000000000000000000000000000000604082015260600190565b600060808201868352602060808185015281875180845260a0860191508289019350845b81811015611f0257845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101611ed0565b505084810360408601528651808252908201925081870190845b81811015611f3e57825163ffffffff1685529383019391830191600101611f1c565b5050505060609290920192909252949350505050565b93845273ffffffffffffffffffffffffffffffffffffffff92909216602084015263ffffffff166040830152606082015260800190565b60405181810167ffffffffffffffff81118282101715611fa757fe5b604052919050565b600067ffffffffffffffff821115611fc357fe5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b8381101561200a578181015183820152602001611ff2565b83811115612019576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461204157600080fd5b5056fea164736f6c6343000706000a\"\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/ShortHelper.json",
    "content": "{\n  \"address\": \"0xE3606363ABE8fdE4A7f1A2058361976A4590e1e9\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controllerAddr\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_swapRouter\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wethAddr\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_withdrawAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOut\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountInMaximum\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactOutputSingleParams\",\n          \"name\": \"_exactOutputParams\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"closeShort\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"controller\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IController\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onERC721Received\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_powerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniNftId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountIn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOutMinimum\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactInputSingleParams\",\n          \"name\": \"_exactInputParams\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"openShort\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"router\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract ISwapRouter\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"shortPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IShortPowerPerp\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IWETH9\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x1fc4f7d08e0a583dbc8011d73a51ae7a21cd44f4ffaafb593f4e6fa5b06c833a\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0xE3606363ABE8fdE4A7f1A2058361976A4590e1e9\",\n    \"transactionIndex\": 27,\n    \"gasUsed\": \"1067535\",\n    \"logsBloom\": \"0x80000000000010000080000000000000000000000000000000000000000001000000000000000000000000000000000000040000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000010000001000000000000000000000000000000000000000000000000000020000000000000000000000000000020000000000020000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001000000000\",\n    \"blockHash\": \"0x64c2b707c7bf380c6d0ca1dc2eb604687e35d170495a235773b2315b64292475\",\n    \"transactionHash\": \"0x1fc4f7d08e0a583dbc8011d73a51ae7a21cd44f4ffaafb593f4e6fa5b06c833a\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 27,\n        \"blockNumber\": 8008115,\n        \"transactionHash\": \"0x1fc4f7d08e0a583dbc8011d73a51ae7a21cd44f4ffaafb593f4e6fa5b06c833a\",\n        \"address\": \"0x9421c968D28DD789363FbD8c9aA5cF2090F0a656\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x000000000000000000000000e3606363abe8fde4a7f1a2058361976a4590e1e9\",\n          \"0x000000000000000000000000833a158da5cebc44901211427e9df936023ec0d3\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 60,\n        \"blockHash\": \"0x64c2b707c7bf380c6d0ca1dc2eb604687e35d170495a235773b2315b64292475\"\n      },\n      {\n        \"transactionIndex\": 27,\n        \"blockNumber\": 8008115,\n        \"transactionHash\": \"0x1fc4f7d08e0a583dbc8011d73a51ae7a21cd44f4ffaafb593f4e6fa5b06c833a\",\n        \"address\": \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x000000000000000000000000e3606363abe8fde4a7f1a2058361976a4590e1e9\",\n          \"0x000000000000000000000000833a158da5cebc44901211427e9df936023ec0d3\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 61,\n        \"blockHash\": \"0x64c2b707c7bf380c6d0ca1dc2eb604687e35d170495a235773b2315b64292475\"\n      }\n    ],\n    \"blockNumber\": 8008115,\n    \"cumulativeGasUsed\": \"4692440\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n    \"0x833A158dA5ceBc44901211427E9Df936023EC0d3\",\n    \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\"\n  ],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controllerAddr\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_swapRouter\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wethAddr\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"deadline\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountOut\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountInMaximum\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceLimitX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"internalType\\\":\\\"struct ISwapRouter.ExactOutputSingleParams\\\",\\\"name\\\":\\\"_exactOutputParams\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"closeShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IController\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onERC721Received\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniNftId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"deadline\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountIn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountOutMinimum\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceLimitX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"internalType\\\":\\\"struct ISwapRouter.ExactInputSingleParams\\\",\\\"name\\\":\\\"_exactInputParams\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"openShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"router\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract ISwapRouter\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"shortPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IShortPowerPerp\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IWETH9\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"params\\\":{\\\"_vaultId\\\":\\\"short wPowerPerp vault id\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to burn\\\",\\\"_withdrawAmount\\\":\\\"amount to withdraw\\\"}},\\\"constructor\\\":{\\\"params\\\":{\\\"_controllerAddr\\\":\\\"controller address for wPowerPerp\\\",\\\"_swapRouter\\\":\\\"uniswap v3 swap router address\\\",\\\"_wethAddr\\\":\\\"weth address\\\"}},\\\"onERC721Received(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"accept erc721 from safeTransferFrom and safeMint after callback\\\",\\\"returns\\\":{\\\"_0\\\":\\\"returns received selector\\\"}},\\\"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"params\\\":{\\\"_powerPerpAmount\\\":\\\"amount of powerPerp to mint/sell\\\",\\\"_uniNftId\\\":\\\"uniswap v3 position token id\\\",\\\"_vaultId\\\":\\\"short wPowerPerp vault id\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"notice\\\":\\\"buy back wPowerPerp with eth on uniswap v3 and close position\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"constructor for short helper\\\"},\\\"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"notice\\\":\\\"mint power perp, trade with uniswap v3 and send back premium in eth\\\"}},\\\"notice\\\":\\\"contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/periphery/ShortHelper.sol\\\":\\\"ShortHelper\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\\\n\\\\n/// @title Router token swapping functionality\\\\n/// @notice Functions for swapping tokens via Uniswap V3\\\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\\\n    struct ExactInputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactInputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactOutputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\\\n\\\\n    struct ExactOutputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9bfaf1feb32814623e627ab70f2409760b15d95f1f9b058e2b3399a8bb732975\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/ShortHelper.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n// Interfaces\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\nimport {IERC721Receiver} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\\\\\";\\\\nimport {ISwapRouter} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\\\\\";\\\\n\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// Libraries\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ReentrancyGuard} from \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\\\n */\\\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    IController public immutable controller;\\\\n    ISwapRouter public immutable router;\\\\n    IWETH9 public immutable weth;\\\\n    IShortPowerPerp public immutable shortPowerPerp;\\\\n    address public immutable wPowerPerp;\\\\n\\\\n    /**\\\\n     * @notice constructor for short helper\\\\n     * @param _controllerAddr controller address for wPowerPerp\\\\n     * @param _swapRouter uniswap v3 swap router address\\\\n     * @param _wethAddr weth address\\\\n     */\\\\n    constructor(\\\\n        address _controllerAddr,\\\\n        address _swapRouter,\\\\n        address _wethAddr\\\\n    ) {\\\\n        require(_controllerAddr != address(0), \\\\\\\"Invalid controller address\\\\\\\");\\\\n        require(_swapRouter != address(0), \\\\\\\"Invalid swap router address\\\\\\\");\\\\n        require(_wethAddr != address(0), \\\\\\\"Invalid weth address\\\\\\\");\\\\n        IController _controller = IController(_controllerAddr);\\\\n        router = ISwapRouter(_swapRouter);\\\\n        wPowerPerp = _controller.wPowerPerp();\\\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\\\n        IWETH9 _weth = IWETH9(_wethAddr);\\\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\\\n        _weth.approve(_swapRouter, type(uint256).max);\\\\n\\\\n        // assign immutable variables\\\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\\\n        weth = _weth;\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\\\n     * @param _vaultId short wPowerPerp vault id\\\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\\\n     * @param _uniNftId uniswap v3 position token id\\\\n     */\\\\n    function openShort(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniNftId,\\\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\\\n    ) external payable nonReentrant {\\\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\\\\\"Not allowed\\\\\\\");\\\\n        require(\\\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\\\n            \\\\\\\"Wrong swap tokens\\\\\\\"\\\\n        );\\\\n\\\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\\\n            _vaultId,\\\\n            _powerPerpAmount,\\\\n            _uniNftId\\\\n        );\\\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\\\n\\\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\\\n\\\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\\\n        if (_exactInputParams.recipient == address(this)) {\\\\n            weth.withdraw(amountOut);\\\\n            payable(msg.sender).sendValue(amountOut);\\\\n        }\\\\n\\\\n        // this is a newly open vault, transfer to the user.\\\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\\\n     * @param _vaultId short wPowerPerp vault id\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\\\n     * @param _withdrawAmount amount to withdraw\\\\n     */\\\\n    function closeShort(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount,\\\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\\\n    ) external payable nonReentrant {\\\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\\\\\"Not allowed\\\\\\\");\\\\n        require(\\\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\\\n            \\\\\\\"Wrong swap tokens\\\\\\\"\\\\n        );\\\\n\\\\n        // wrap eth to weth\\\\n        weth.deposit{value: msg.value}();\\\\n\\\\n        // pay weth and get wPowerPerp in return.\\\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\\\n\\\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\\\n\\\\n        // send back unused eth and withdrawn collateral\\\\n        weth.withdraw(msg.value.sub(amountIn));\\\\n        // no eth should be left in the contract, so we send it all back\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev only receive eth from weth contract and controller.\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\\\\\"can't receive eth\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\\\n     * @return returns received selector\\\\n     */\\\\n    function onERC721Received(\\\\n        address,\\\\n        address,\\\\n        uint256,\\\\n        bytes memory\\\\n    ) public virtual override returns (bytes4) {\\\\n        return this.onERC721Received.selector;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x512bb00cb9e4a780ba460ef629f3c581feb8ca669373417beeefdcbc1233c4d1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101206040523480156200001257600080fd5b5060405162001643380380620016438339810160408190526200003591620003e6565b60016000556001600160a01b0383166200006c5760405162461bcd60e51b81526004016200006390620004a1565b60405180910390fd5b6001600160a01b038216620000955760405162461bcd60e51b81526004016200006390620004d8565b6001600160a01b038116620000be5760405162461bcd60e51b815260040162000063906200046a565b6000839050826001600160a01b031660a0816001600160a01b031660601b81525050806001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b1580156200011a57600080fd5b505afa1580156200012f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001559190620003c2565b6001600160a01b0316610100816001600160a01b031660601b815250506000816001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b158015620001ae57600080fd5b505afa158015620001c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001e99190620003c2565b60405163095ea7b360e01b815290915083906001600160a01b0383169063095ea7b390620002209088906000199060040162000451565b602060405180830381600087803b1580156200023b57600080fd5b505af115801562000250573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200027691906200042f565b5060405163095ea7b360e01b81526001600160a01b0382169063095ea7b390620002a99088906000199060040162000451565b602060405180830381600087803b158015620002c457600080fd5b505af1158015620002d9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ff91906200042f565b50826001600160a01b0316639d4c94426040518163ffffffff1660e01b815260040160206040518083038186803b1580156200033a57600080fd5b505afa1580156200034f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003759190620003c2565b6001600160601b0319606091821b811660e05291811b821660c0529290921b909116608052506200050f92505050565b80516001600160a01b0381168114620003bd57600080fd5b919050565b600060208284031215620003d4578081fd5b620003df82620003a5565b9392505050565b600080600060608486031215620003fb578182fd5b6200040684620003a5565b92506200041660208501620003a5565b91506200042660408501620003a5565b90509250925092565b60006020828403121562000441578081fd5b81518015158114620003df578182fd5b6001600160a01b03929092168252602082015260400190565b60208082526014908201527f496e76616c696420776574682061646472657373000000000000000000000000604082015260600190565b6020808252601a908201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604082015260600190565b6020808252601b908201527f496e76616c6964207377617020726f7574657220616464726573730000000000604082015260600190565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c611097620005ac60003980610314528061060a52806107b952508061025f528061062e52806106c45280610a1e525080608f528061035452806103aa528061054a52806105e65280610779528061098e52508061043452806108d85280610abe52508060c152806104d752806108125280610a9a52506110976000f3fe60806040526004361061007f5760003560e01c80639d4c94421161004e5780639d4c94421461018f578063e56cfbbe146101a4578063f77c4791146101b7578063f887ea40146101cc5761010a565b8063150b7a021461010f57806317fd9e0e146101455780633fc8cef3146101585780637f07b1301461017a5761010a565b3661010a57336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100e35750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6101085760405162461bcd60e51b81526004016100ff90610f86565b60405180910390fd5b005b600080fd5b34801561011b57600080fd5b5061012f61012a366004610d1e565b6101e1565b60405161013c9190610eeb565b60405180910390f35b610108610153366004610e0f565b6101f1565b34801561016457600080fd5b5061016d6105e4565b60405161013c9190610eb3565b34801561018657600080fd5b5061016d610608565b34801561019b57600080fd5b5061016d61062c565b6101086101b2366004610e0f565b610650565b3480156101c357600080fd5b5061016d610a98565b3480156101d857600080fd5b5061016d610abc565b630a85bd0160e11b949350505050565b60026000541415610249576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000556040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e9061029c908890600401610fcc565b60206040518083038186803b1580156102b457600080fd5b505afa1580156102c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ec9190610cfb565b6001600160a01b0316146103125760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b031614801561038c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b6103a85760405162461bcd60e51b81526004016100ff90610f18565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561040357600080fd5b505af1158015610417573d6000803e3d6000fd5b5050604051631b67c43360e31b8152600093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063db3e2198915061046b908590600401610fbd565b602060405180830381600087803b15801561048557600080fd5b505af1158015610499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104bd9190610dd4565b604051638632cb0360e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638632cb039061051090889088908890600401610fd5565b600060405180830381600087803b15801561052a57600080fd5b505af115801561053e573d6000803e3d6000fd5b50506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169150632e1a7d4d905061057d3484610ae0565b6040518263ffffffff1660e01b81526004016105999190610fcc565b600060405180830381600087803b1580156105b357600080fd5b505af11580156105c7573d6000803e3d6000fd5b506105d89250339150479050610b42565b50506001600055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600260005414156106a8576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000558315610777576040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90610701908890600401610fcc565b60206040518083038186803b15801561071957600080fd5b505afa15801561072d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107519190610cfb565b6001600160a01b0316146107775760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b03161480156107f157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b61080d5760405162461bcd60e51b81526004016100ff90610f18565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631bf7bf6c348888886040518563ffffffff1660e01b815260040161086193929190610fd5565b60408051808303818588803b15801561087957600080fd5b505af115801561088d573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906108b29190610dec565b60a0850181905260405163414bf38960e01b815291935091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063414bf3899061090d908790600401610fbd565b602060405180830381600087803b15801561092757600080fd5b505af115801561093b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095f9190610dd4565b60608501519091506001600160a01b0316301415610a0257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906109c3908490600401610fcc565b600060405180830381600087803b1580156109dd57600080fd5b505af11580156109f1573d6000803e3d6000fd5b50610a029250339150839050610b42565b86610a8a57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610a5790309033908890600401610ec7565b600060405180830381600087803b158015610a7157600080fd5b505af1158015610a85573d6000803e3d6000fd5b505050505b505060016000555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600082821115610b37576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b80471015610b97576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610be2576040519150601f19603f3d011682016040523d82523d6000602084013e610be7565b606091505b5050905080610c275760405162461bcd60e51b815260040180806020018281038252603a815260200180611028603a913960400191505060405180910390fd5b505050565b8035610c378161100f565b919050565b6000610100808385031215610c4f578182fd5b6040519081019067ffffffffffffffff82118183101715610c6c57fe5b81604052809250610c7c84610c2c565b8152610c8a60208501610c2c565b6020820152610c9b60408501610ce8565b6040820152610cac60608501610c2c565b60608201526080840135608082015260a084013560a082015260c084013560c0820152610cdb60e08501610c2c565b60e0820152505092915050565b803562ffffff81168114610c3757600080fd5b600060208284031215610d0c578081fd5b8151610d178161100f565b9392505050565b60008060008060808587031215610d33578283fd5b8435610d3e8161100f565b9350602085810135610d4f8161100f565b935060408601359250606086013567ffffffffffffffff80821115610d72578384fd5b818801915088601f830112610d85578384fd5b813581811115610d9157fe5b610da3601f8201601f19168501610feb565b91508082528984828501011115610db8578485fd5b8084840185840137810190920192909252939692955090935050565b600060208284031215610de5578081fd5b5051919050565b60008060408385031215610dfe578182fd5b505080516020909101519092909150565b6000806000806101608587031215610e25578384fd5b843593506020850135925060408501359150610e448660608701610c3c565b905092959194509250565b6001600160a01b0380825116835280602083015116602084015262ffffff60408301511660408401528060608301511660608401526080820151608084015260a082015160a084015260c082015160c08401528060e08301511660e0840152505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b60208082526011908201527f57726f6e67207377617020746f6b656e73000000000000000000000000000000604082015260600190565b6020808252600b908201527f4e6f7420616c6c6f776564000000000000000000000000000000000000000000604082015260600190565b60208082526011908201527f63616e2774207265636569766520657468000000000000000000000000000000604082015260600190565b6101008101610b3c8284610e4f565b90815260200190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561100757fe5b604052919050565b6001600160a01b038116811461102457600080fd5b5056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a26469706673582212201e0fa9dc632604f995da268103a510f921d4ea2855bf3d01b243e3a65cc2770164736f6c63430007060033\",\n  \"deployedBytecode\": \"0x60806040526004361061007f5760003560e01c80639d4c94421161004e5780639d4c94421461018f578063e56cfbbe146101a4578063f77c4791146101b7578063f887ea40146101cc5761010a565b8063150b7a021461010f57806317fd9e0e146101455780633fc8cef3146101585780637f07b1301461017a5761010a565b3661010a57336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100e35750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6101085760405162461bcd60e51b81526004016100ff90610f86565b60405180910390fd5b005b600080fd5b34801561011b57600080fd5b5061012f61012a366004610d1e565b6101e1565b60405161013c9190610eeb565b60405180910390f35b610108610153366004610e0f565b6101f1565b34801561016457600080fd5b5061016d6105e4565b60405161013c9190610eb3565b34801561018657600080fd5b5061016d610608565b34801561019b57600080fd5b5061016d61062c565b6101086101b2366004610e0f565b610650565b3480156101c357600080fd5b5061016d610a98565b3480156101d857600080fd5b5061016d610abc565b630a85bd0160e11b949350505050565b60026000541415610249576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000556040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e9061029c908890600401610fcc565b60206040518083038186803b1580156102b457600080fd5b505afa1580156102c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ec9190610cfb565b6001600160a01b0316146103125760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b031614801561038c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b6103a85760405162461bcd60e51b81526004016100ff90610f18565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561040357600080fd5b505af1158015610417573d6000803e3d6000fd5b5050604051631b67c43360e31b8152600093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063db3e2198915061046b908590600401610fbd565b602060405180830381600087803b15801561048557600080fd5b505af1158015610499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104bd9190610dd4565b604051638632cb0360e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638632cb039061051090889088908890600401610fd5565b600060405180830381600087803b15801561052a57600080fd5b505af115801561053e573d6000803e3d6000fd5b50506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169150632e1a7d4d905061057d3484610ae0565b6040518263ffffffff1660e01b81526004016105999190610fcc565b600060405180830381600087803b1580156105b357600080fd5b505af11580156105c7573d6000803e3d6000fd5b506105d89250339150479050610b42565b50506001600055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600260005414156106a8576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000558315610777576040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90610701908890600401610fcc565b60206040518083038186803b15801561071957600080fd5b505afa15801561072d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107519190610cfb565b6001600160a01b0316146107775760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b03161480156107f157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b61080d5760405162461bcd60e51b81526004016100ff90610f18565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631bf7bf6c348888886040518563ffffffff1660e01b815260040161086193929190610fd5565b60408051808303818588803b15801561087957600080fd5b505af115801561088d573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906108b29190610dec565b60a0850181905260405163414bf38960e01b815291935091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063414bf3899061090d908790600401610fbd565b602060405180830381600087803b15801561092757600080fd5b505af115801561093b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095f9190610dd4565b60608501519091506001600160a01b0316301415610a0257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906109c3908490600401610fcc565b600060405180830381600087803b1580156109dd57600080fd5b505af11580156109f1573d6000803e3d6000fd5b50610a029250339150839050610b42565b86610a8a57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610a5790309033908890600401610ec7565b600060405180830381600087803b158015610a7157600080fd5b505af1158015610a85573d6000803e3d6000fd5b505050505b505060016000555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600082821115610b37576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b80471015610b97576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610be2576040519150601f19603f3d011682016040523d82523d6000602084013e610be7565b606091505b5050905080610c275760405162461bcd60e51b815260040180806020018281038252603a815260200180611028603a913960400191505060405180910390fd5b505050565b8035610c378161100f565b919050565b6000610100808385031215610c4f578182fd5b6040519081019067ffffffffffffffff82118183101715610c6c57fe5b81604052809250610c7c84610c2c565b8152610c8a60208501610c2c565b6020820152610c9b60408501610ce8565b6040820152610cac60608501610c2c565b60608201526080840135608082015260a084013560a082015260c084013560c0820152610cdb60e08501610c2c565b60e0820152505092915050565b803562ffffff81168114610c3757600080fd5b600060208284031215610d0c578081fd5b8151610d178161100f565b9392505050565b60008060008060808587031215610d33578283fd5b8435610d3e8161100f565b9350602085810135610d4f8161100f565b935060408601359250606086013567ffffffffffffffff80821115610d72578384fd5b818801915088601f830112610d85578384fd5b813581811115610d9157fe5b610da3601f8201601f19168501610feb565b91508082528984828501011115610db8578485fd5b8084840185840137810190920192909252939692955090935050565b600060208284031215610de5578081fd5b5051919050565b60008060408385031215610dfe578182fd5b505080516020909101519092909150565b6000806000806101608587031215610e25578384fd5b843593506020850135925060408501359150610e448660608701610c3c565b905092959194509250565b6001600160a01b0380825116835280602083015116602084015262ffffff60408301511660408401528060608301511660608401526080820151608084015260a082015160a084015260c082015160c08401528060e08301511660e0840152505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b60208082526011908201527f57726f6e67207377617020746f6b656e73000000000000000000000000000000604082015260600190565b6020808252600b908201527f4e6f7420616c6c6f776564000000000000000000000000000000000000000000604082015260600190565b60208082526011908201527f63616e2774207265636569766520657468000000000000000000000000000000604082015260600190565b6101008101610b3c8284610e4f565b90815260200190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561100757fe5b604052919050565b6001600160a01b038116811461102457600080fd5b5056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a26469706673582212201e0fa9dc632604f995da268103a510f921d4ea2855bf3d01b243e3a65cc2770164736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"params\": {\n          \"_vaultId\": \"short wPowerPerp vault id\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to burn\",\n          \"_withdrawAmount\": \"amount to withdraw\"\n        }\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_controllerAddr\": \"controller address for wPowerPerp\",\n          \"_swapRouter\": \"uniswap v3 swap router address\",\n          \"_wethAddr\": \"weth address\"\n        }\n      },\n      \"onERC721Received(address,address,uint256,bytes)\": {\n        \"details\": \"accept erc721 from safeTransferFrom and safeMint after callback\",\n        \"returns\": {\n          \"_0\": \"returns received selector\"\n        }\n      },\n      \"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"params\": {\n          \"_powerPerpAmount\": \"amount of powerPerp to mint/sell\",\n          \"_uniNftId\": \"uniswap v3 position token id\",\n          \"_vaultId\": \"short wPowerPerp vault id\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"notice\": \"buy back wPowerPerp with eth on uniswap v3 and close position\"\n      },\n      \"constructor\": {\n        \"notice\": \"constructor for short helper\"\n      },\n      \"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"notice\": \"mint power perp, trade with uniswap v3 and send back premium in eth\"\n      }\n    },\n    \"notice\": \"contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 4176,\n        \"contract\": \"contracts/periphery/ShortHelper.sol:ShortHelper\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_uint256\"\n      }\n    ],\n    \"types\": {\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/ShortPowerPerp.json",
    "content": "{\n  \"address\": \"0xe85595e810B77cf606D0aFd7eB575BB025323beE\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_name\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_symbol\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"approved\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"approved\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"ApprovalForAll\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"baseURI\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"controller\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getApproved\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controller\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"init\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"isApprovedForAll\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_recipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"mintNFT\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"nextId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ownerOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"safeTransferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"safeTransferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"approved\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"setApprovalForAll\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"interfaceId\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"name\": \"supportsInterface\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"index\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenByIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"index\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenOfOwnerByIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenURI\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x6e61811643251637f29c7d0b4a0dfea8e26ca53ac845bdfee8cd4dc658df8c62\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0xe85595e810B77cf606D0aFd7eB575BB025323beE\",\n    \"transactionIndex\": 15,\n    \"gasUsed\": \"1944244\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x80307667ef3d4b3d5542edb6e342a9c2c6e6ca20df8558abeffba2a136d87f96\",\n    \"transactionHash\": \"0x6e61811643251637f29c7d0b4a0dfea8e26ca53ac845bdfee8cd4dc658df8c62\",\n    \"logs\": [],\n    \"blockNumber\": 8008056,\n    \"cumulativeGasUsed\": \"3126903\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"short Squeeth\",\n    \"sSQTH\"\n  ],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_name\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_symbol\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"ApprovalForAll\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"baseURI\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"getApproved\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controller\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"init\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"isApprovedForAll\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_recipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"mintNFT\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"nextId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ownerOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"safeTransferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"safeTransferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"setApprovalForAll\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"interfaceId\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"name\\\":\\\"supportsInterface\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"index\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenByIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"index\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenOfOwnerByIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenURI\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-approve}.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC721-balanceOf}.\\\"},\\\"baseURI()\\\":{\\\"details\\\":\\\"Returns the base URI set via {_setBaseURI}. This will be automatically added as a prefix in {tokenURI} to each token's URI, or to the token ID if no specific URI is set for that token ID.\\\"},\\\"constructor\\\":{\\\"params\\\":{\\\"_name\\\":\\\"token name for ERC721\\\",\\\"_symbol\\\":\\\"token symbol for ERC721\\\"}},\\\"getApproved(uint256)\\\":{\\\"details\\\":\\\"See {IERC721-getApproved}.\\\"},\\\"init(address)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\"}},\\\"isApprovedForAll(address,address)\\\":{\\\"details\\\":\\\"See {IERC721-isApprovedForAll}.\\\"},\\\"mintNFT(address)\\\":{\\\"details\\\":\\\"autoincrement tokenId starts at 1\\\",\\\"params\\\":{\\\"_recipient\\\":\\\"recipient address for NFT\\\"}},\\\"name()\\\":{\\\"details\\\":\\\"See {IERC721Metadata-name}.\\\"},\\\"ownerOf(uint256)\\\":{\\\"details\\\":\\\"See {IERC721-ownerOf}.\\\"},\\\"safeTransferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-safeTransferFrom}.\\\"},\\\"safeTransferFrom(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"See {IERC721-safeTransferFrom}.\\\"},\\\"setApprovalForAll(address,bool)\\\":{\\\"details\\\":\\\"See {IERC721-setApprovalForAll}.\\\"},\\\"supportsInterface(bytes4)\\\":{\\\"details\\\":\\\"See {IERC165-supportsInterface}. Time complexity O(1), guaranteed to always use less than 30 000 gas.\\\"},\\\"symbol()\\\":{\\\"details\\\":\\\"See {IERC721Metadata-symbol}.\\\"},\\\"tokenByIndex(uint256)\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-tokenByIndex}.\\\"},\\\"tokenOfOwnerByIndex(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-tokenOfOwnerByIndex}.\\\"},\\\"tokenURI(uint256)\\\":{\\\"details\\\":\\\"See {IERC721Metadata-tokenURI}.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-totalSupply}.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-transferFrom}.\\\"}},\\\"stateVariables\\\":{\\\"nextId\\\":{\\\"details\\\":\\\"tokenId for the next vault opened\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"constructor\\\":{\\\"notice\\\":\\\"short power perpetual constructor\\\"},\\\"init(address)\\\":{\\\"notice\\\":\\\"initialize short contract\\\"},\\\"mintNFT(address)\\\":{\\\"notice\\\":\\\"mint new NFT\\\"}},\\\"notice\\\":\\\"ERC721 NFT representing ownership of a vault (short position)\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/ShortPowerPerp.sol\\\":\\\"ShortPowerPerp\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/ERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Implementation of the {IERC165} interface.\\\\n *\\\\n * Contracts may inherit from this and call {_registerInterface} to declare\\\\n * their support of an interface.\\\\n */\\\\nabstract contract ERC165 is IERC165 {\\\\n    /*\\\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\\\n\\\\n    /**\\\\n     * @dev Mapping of interface ids to whether or not it's supported.\\\\n     */\\\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\\\n\\\\n    constructor () {\\\\n        // Derived contracts need only register support for their own interfaces,\\\\n        // we register support for ERC165 itself here\\\\n        _registerInterface(_INTERFACE_ID_ERC165);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC165-supportsInterface}.\\\\n     *\\\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\\\n        return _supportedInterfaces[interfaceId];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Registers the contract as an implementer of the interface defined by\\\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\\\n     * registering its interface id is not required.\\\\n     *\\\\n     * See {IERC165-supportsInterface}.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\\\n     */\\\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\\\n        require(interfaceId != 0xffffffff, \\\\\\\"ERC165: invalid interface id\\\\\\\");\\\\n        _supportedInterfaces[interfaceId] = true;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x234cdf2c3efd5f0dc17d32fe65d33c21674ca17de1e945eb60ac1076d7152d96\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// solhint-disable-next-line compiler-version\\\\npragma solidity >=0.4.24 <0.8.0;\\\\n\\\\nimport \\\\\\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\\\nabstract contract Initializable {\\\\n\\\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\\\n    function _isConstructor() private view returns (bool) {\\\\n        return !Address.isContract(address(this));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9abeffe138f098b16557187383ba0f9e8503602fa95cd668132986ee115237ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721Metadata.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721Enumerable.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721Receiver.sol\\\\\\\";\\\\nimport \\\\\\\"../../introspection/ERC165.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/Address.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/EnumerableSet.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/EnumerableMap.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/Strings.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\\\n    using SafeMath for uint256;\\\\n    using Address for address;\\\\n    using EnumerableSet for EnumerableSet.UintSet;\\\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\\\n    using Strings for uint256;\\\\n\\\\n    // Equals to `bytes4(keccak256(\\\\\\\"onERC721Received(address,address,uint256,bytes)\\\\\\\"))`\\\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\\\n\\\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\\\n\\\\n    // Enumerable mapping from token ids to their owners\\\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\\\n\\\\n    // Mapping from token ID to approved address\\\\n    mapping (uint256 => address) private _tokenApprovals;\\\\n\\\\n    // Mapping from owner to operator approvals\\\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\\\n\\\\n    // Token name\\\\n    string private _name;\\\\n\\\\n    // Token symbol\\\\n    string private _symbol;\\\\n\\\\n    // Optional mapping for token URIs\\\\n    mapping (uint256 => string) private _tokenURIs;\\\\n\\\\n    // Base URI\\\\n    string private _baseURI;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\\\n     *\\\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\\\n     *\\\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\\\n     *\\\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\\\n\\\\n    /**\\\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\\\n     */\\\\n    constructor (string memory name_, string memory symbol_) {\\\\n        _name = name_;\\\\n        _symbol = symbol_;\\\\n\\\\n        // register the supported interfaces to conform to ERC721 via ERC165\\\\n        _registerInterface(_INTERFACE_ID_ERC721);\\\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-balanceOf}.\\\\n     */\\\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\\\n        require(owner != address(0), \\\\\\\"ERC721: balance query for the zero address\\\\\\\");\\\\n        return _holderTokens[owner].length();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-ownerOf}.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\\\n        return _tokenOwners.get(tokenId, \\\\\\\"ERC721: owner query for nonexistent token\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-name}.\\\\n     */\\\\n    function name() public view virtual override returns (string memory) {\\\\n        return _name;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-symbol}.\\\\n     */\\\\n    function symbol() public view virtual override returns (string memory) {\\\\n        return _symbol;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-tokenURI}.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721Metadata: URI query for nonexistent token\\\\\\\");\\\\n\\\\n        string memory _tokenURI = _tokenURIs[tokenId];\\\\n        string memory base = baseURI();\\\\n\\\\n        // If there is no base URI, return the token URI.\\\\n        if (bytes(base).length == 0) {\\\\n            return _tokenURI;\\\\n        }\\\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\\\n        if (bytes(_tokenURI).length > 0) {\\\\n            return string(abi.encodePacked(base, _tokenURI));\\\\n        }\\\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\\\n        return string(abi.encodePacked(base, tokenId.toString()));\\\\n    }\\\\n\\\\n    /**\\\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\\\n    * to the token ID if no specific URI is set for that token ID.\\\\n    */\\\\n    function baseURI() public view virtual returns (string memory) {\\\\n        return _baseURI;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\\\n        return _holderTokens[owner].at(index);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-totalSupply}.\\\\n     */\\\\n    function totalSupply() public view virtual override returns (uint256) {\\\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\\\n        return _tokenOwners.length();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\\\n     */\\\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\\\n        return tokenId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-approve}.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) public virtual override {\\\\n        address owner = ERC721.ownerOf(tokenId);\\\\n        require(to != owner, \\\\\\\"ERC721: approval to current owner\\\\\\\");\\\\n\\\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\\\n            \\\\\\\"ERC721: approve caller is not owner nor approved for all\\\\\\\"\\\\n        );\\\\n\\\\n        _approve(to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-getApproved}.\\\\n     */\\\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721: approved query for nonexistent token\\\\\\\");\\\\n\\\\n        return _tokenApprovals[tokenId];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-setApprovalForAll}.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\\\n        require(operator != _msgSender(), \\\\\\\"ERC721: approve to caller\\\\\\\");\\\\n\\\\n        _operatorApprovals[_msgSender()][operator] = approved;\\\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-isApprovedForAll}.\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\\\n        return _operatorApprovals[owner][operator];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-transferFrom}.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\\\n        //solhint-disable-next-line max-line-length\\\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\\\\\"ERC721: transfer caller is not owner nor approved\\\\\\\");\\\\n\\\\n        _transfer(from, to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-safeTransferFrom}.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\\\n        safeTransferFrom(from, to, tokenId, \\\\\\\"\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-safeTransferFrom}.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\\\\\"ERC721: transfer caller is not owner nor approved\\\\\\\");\\\\n        _safeTransfer(from, to, tokenId, _data);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\\\n     *\\\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\\\n        _transfer(from, to, tokenId);\\\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns whether `tokenId` exists.\\\\n     *\\\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Tokens start existing when they are minted (`_mint`),\\\\n     * and stop existing when they are burned (`_burn`).\\\\n     */\\\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\\\n        return _tokenOwners.contains(tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721: operator query for nonexistent token\\\\\\\");\\\\n        address owner = ERC721.ownerOf(tokenId);\\\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\\\n     *\\\\n     * Requirements:\\\\n     d*\\\\n     * - `tokenId` must not exist.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\\\n        _safeMint(to, tokenId, \\\\\\\"\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\\\n     */\\\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\\\n        _mint(to, tokenId);\\\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Mints `tokenId` and transfers it to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must not exist.\\\\n     * - `to` cannot be the zero address.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _mint(address to, uint256 tokenId) internal virtual {\\\\n        require(to != address(0), \\\\\\\"ERC721: mint to the zero address\\\\\\\");\\\\n        require(!_exists(tokenId), \\\\\\\"ERC721: token already minted\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(address(0), to, tokenId);\\\\n\\\\n        _holderTokens[to].add(tokenId);\\\\n\\\\n        _tokenOwners.set(tokenId, to);\\\\n\\\\n        emit Transfer(address(0), to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Destroys `tokenId`.\\\\n     * The approval is cleared when the token is burned.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _burn(uint256 tokenId) internal virtual {\\\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\\\n\\\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\\\n\\\\n        // Clear approvals\\\\n        _approve(address(0), tokenId);\\\\n\\\\n        // Clear metadata (if any)\\\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\\\n            delete _tokenURIs[tokenId];\\\\n        }\\\\n\\\\n        _holderTokens[owner].remove(tokenId);\\\\n\\\\n        _tokenOwners.remove(tokenId);\\\\n\\\\n        emit Transfer(owner, address(0), tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` from `from` to `to`.\\\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\\\n        require(ERC721.ownerOf(tokenId) == from, \\\\\\\"ERC721: transfer of token that is not own\\\\\\\"); // internal owner\\\\n        require(to != address(0), \\\\\\\"ERC721: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(from, to, tokenId);\\\\n\\\\n        // Clear approvals from the previous owner\\\\n        _approve(address(0), tokenId);\\\\n\\\\n        _holderTokens[from].remove(tokenId);\\\\n        _holderTokens[to].add(tokenId);\\\\n\\\\n        _tokenOwners.set(tokenId, to);\\\\n\\\\n        emit Transfer(from, to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721Metadata: URI set of nonexistent token\\\\\\\");\\\\n        _tokenURIs[tokenId] = _tokenURI;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Internal function to set the base URI for all token IDs. It is\\\\n     * automatically added as a prefix to the value returned in {tokenURI},\\\\n     * or to the token ID if {tokenURI} is empty.\\\\n     */\\\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\\\n        _baseURI = baseURI_;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\\\n     * The call is not executed if the target address is not a contract.\\\\n     *\\\\n     * @param from address representing the previous owner of the given token ID\\\\n     * @param to target address that will receive the tokens\\\\n     * @param tokenId uint256 ID of the token to be transferred\\\\n     * @param _data bytes optional data to send along with the call\\\\n     * @return bool whether the call correctly returned the expected magic value\\\\n     */\\\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\\\n        private returns (bool)\\\\n    {\\\\n        if (!to.isContract()) {\\\\n            return true;\\\\n        }\\\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\\\n            IERC721Receiver(to).onERC721Received.selector,\\\\n            _msgSender(),\\\\n            from,\\\\n            tokenId,\\\\n            _data\\\\n        ), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\\\n        return (retval == _ERC721_RECEIVED);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Approve `to` to operate on `tokenId`\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function _approve(address to, uint256 tokenId) internal virtual {\\\\n        _tokenApprovals[tokenId] = to;\\\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Hook that is called before any token transfer. This includes minting\\\\n     * and burning.\\\\n     *\\\\n     * Calling conditions:\\\\n     *\\\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\\\n     * transferred to `to`.\\\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     *\\\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\\\n     */\\\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x93e4f65a89c3c888afbaa3ee18c3fa4f51c422419bbcd9cca47676a0f8e507ea\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/EnumerableMap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Library for managing an enumerable variant of Solidity's\\\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\\\n * type.\\\\n *\\\\n * Maps have the following properties:\\\\n *\\\\n * - Entries are added, removed, and checked for existence in constant time\\\\n * (O(1)).\\\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\\\n *\\\\n * ```\\\\n * contract Example {\\\\n *     // Add the library methods\\\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\\\n *\\\\n *     // Declare a set state variable\\\\n *     EnumerableMap.UintToAddressMap private myMap;\\\\n * }\\\\n * ```\\\\n *\\\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\\\n * supported.\\\\n */\\\\nlibrary EnumerableMap {\\\\n    // To implement this library for multiple types with as little code\\\\n    // repetition as possible, we write it in terms of a generic Map type with\\\\n    // bytes32 keys and values.\\\\n    // The Map implementation uses private functions, and user-facing\\\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\\\n    // the underlying Map.\\\\n    // This means that we can only create new EnumerableMaps for types that fit\\\\n    // in bytes32.\\\\n\\\\n    struct MapEntry {\\\\n        bytes32 _key;\\\\n        bytes32 _value;\\\\n    }\\\\n\\\\n    struct Map {\\\\n        // Storage of map keys and values\\\\n        MapEntry[] _entries;\\\\n\\\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\\\n        // because index 0 means a key is not in the map.\\\\n        mapping (bytes32 => uint256) _indexes;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\\\n     * key. O(1).\\\\n     *\\\\n     * Returns true if the key was added to the map, that is if it was not\\\\n     * already present.\\\\n     */\\\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\\\n        uint256 keyIndex = map._indexes[key];\\\\n\\\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\\\n            // The entry is stored at length-1, but we add 1 to all indexes\\\\n            // and use 0 as a sentinel value\\\\n            map._indexes[key] = map._entries.length;\\\\n            return true;\\\\n        } else {\\\\n            map._entries[keyIndex - 1]._value = value;\\\\n            return false;\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Removes a key-value pair from a map. O(1).\\\\n     *\\\\n     * Returns true if the key was removed from the map, that is if it was present.\\\\n     */\\\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\\\n        uint256 keyIndex = map._indexes[key];\\\\n\\\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\\\n            // This modifies the order of the array, as noted in {at}.\\\\n\\\\n            uint256 toDeleteIndex = keyIndex - 1;\\\\n            uint256 lastIndex = map._entries.length - 1;\\\\n\\\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\\\n\\\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\\\n\\\\n            // Move the last entry to the index where the entry to delete is\\\\n            map._entries[toDeleteIndex] = lastEntry;\\\\n            // Update the index for the moved entry\\\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\\\n\\\\n            // Delete the slot where the moved entry was stored\\\\n            map._entries.pop();\\\\n\\\\n            // Delete the index for the deleted slot\\\\n            delete map._indexes[key];\\\\n\\\\n            return true;\\\\n        } else {\\\\n            return false;\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns true if the key is in the map. O(1).\\\\n     */\\\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\\\n        return map._indexes[key] != 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\\\n     */\\\\n    function _length(Map storage map) private view returns (uint256) {\\\\n        return map._entries.length;\\\\n    }\\\\n\\\\n   /**\\\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\\\n    *\\\\n    * Note that there are no guarantees on the ordering of entries inside the\\\\n    * array, and it may change when more entries are added or removed.\\\\n    *\\\\n    * Requirements:\\\\n    *\\\\n    * - `index` must be strictly less than {length}.\\\\n    */\\\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\\\n        require(map._entries.length > index, \\\\\\\"EnumerableMap: index out of bounds\\\\\\\");\\\\n\\\\n        MapEntry storage entry = map._entries[index];\\\\n        return (entry._key, entry._value);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\\\n     * Does not revert if `key` is not in the map.\\\\n     */\\\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the value associated with `key`.  O(1).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `key` must be in the map.\\\\n     */\\\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        require(keyIndex != 0, \\\\\\\"EnumerableMap: nonexistent key\\\\\\\"); // Equivalent to contains(map, key)\\\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\\\n     */\\\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\\\n    }\\\\n\\\\n    // UintToAddressMap\\\\n\\\\n    struct UintToAddressMap {\\\\n        Map _inner;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\\\n     * key. O(1).\\\\n     *\\\\n     * Returns true if the key was added to the map, that is if it was not\\\\n     * already present.\\\\n     */\\\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Removes a value from a set. O(1).\\\\n     *\\\\n     * Returns true if the key was removed from the map, that is if it was present.\\\\n     */\\\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\\\n        return _remove(map._inner, bytes32(key));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns true if the key is in the map. O(1).\\\\n     */\\\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\\\n        return _contains(map._inner, bytes32(key));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the number of elements in the map. O(1).\\\\n     */\\\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\\\n        return _length(map._inner);\\\\n    }\\\\n\\\\n   /**\\\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\\\n        return (uint256(key), address(uint160(uint256(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\\\n     * Does not revert if `key` is not in the map.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\\\n        return (success, address(uint160(uint256(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the value associated with `key`.  O(1).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `key` must be in the map.\\\\n     */\\\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\\\n     */\\\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2114555153edb5f273008b3d34205f511db9af06b88f752e4c280dd612c4c549\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.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\\\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\\\n\\\\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] = toDeleteIndex + 1; // All indexes are 1-based\\\\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        require(set._values.length > index, \\\\\\\"EnumerableSet: index out of bounds\\\\\\\");\\\\n        return set._values[index];\\\\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    // 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    // 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\\\",\\\"keccak256\\\":\\\"0x9a2c1eebb65250f0e11882237038600f22a62376f0547db4acc0dfe0a3d8d34f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Strings.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev String operations.\\\\n */\\\\nlibrary Strings {\\\\n    /**\\\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\\\n        temp = value;\\\\n        while (temp != 0) {\\\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\\\n            temp /= 10;\\\\n        }\\\\n        return string(buffer);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x08e38e034333372aea8cb1b8846085b7fbab42c6b77a0af464d2c6827827c4f0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/core/ShortPowerPerp.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//contract\\\\nimport {ERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\\\\\";\\\\nimport {Initializable} from \\\\\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\\\n */\\\\ncontract ShortPowerPerp is ERC721, Initializable {\\\\n    /// @dev tokenId for the next vault opened\\\\n    uint256 public nextId = 1;\\\\n\\\\n    address public controller;\\\\n    address private immutable deployer;\\\\n\\\\n    modifier onlyController() {\\\\n        require(msg.sender == controller, \\\\\\\"Not controller\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice short power perpetual constructor\\\\n     * @param _name token name for ERC721\\\\n     * @param _symbol token symbol for ERC721\\\\n     */\\\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\\\n        deployer = msg.sender;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice initialize short contract\\\\n     * @param _controller controller address\\\\n     */\\\\n    function init(address _controller) public initializer {\\\\n        require(msg.sender == deployer, \\\\\\\"Invalid caller of init\\\\\\\");\\\\n        require(_controller != address(0), \\\\\\\"Invalid controller address\\\\\\\");\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint new NFT\\\\n     * @dev autoincrement tokenId starts at 1\\\\n     * @param _recipient recipient address for NFT\\\\n     */\\\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\\\n        // mint NFT\\\\n        _safeMint(_recipient, (tokenId = nextId++));\\\\n    }\\\\n\\\\n    function _beforeTokenTransfer(\\\\n        address, /* from */\\\\n        address, /* to */\\\\n        uint256 tokenId\\\\n    ) internal override {\\\\n        IController(controller).updateOperator(tokenId, address(0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5597686c00b4341803c9119e8402e9207b0d13ca722e724fa9d2c85e8ea6dbf5\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60a06040526001600b553480156200001657600080fd5b506040516200229c3803806200229c833981810160405260408110156200003c57600080fd5b81019080805160405193929190846401000000008211156200005d57600080fd5b9083019060208201858111156200007357600080fd5b82516401000000008111828201881017156200008e57600080fd5b82525081516020918201929091019080838360005b83811015620000bd578181015183820152602001620000a3565b50505050905090810190601f168015620000eb5780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200010f57600080fd5b9083019060208201858111156200012557600080fd5b82516401000000008111828201881017156200014057600080fd5b82525081516020918201929091019080838360005b838110156200016f57818101518382015260200162000155565b50505050905090810190601f1680156200019d5780820380516001836020036101000a031916815260200191505b5060405250839150829050620001ba6301ffc9a760e01b6200022d565b8151620001cf906006906020850190620002b2565b508051620001e5906007906020840190620002b2565b50620001f86380ac58cd60e01b6200022d565b6200020a635b5e139f60e01b6200022d565b6200021c63780e9d6360e01b6200022d565b5050503360601b608052506200035e565b6001600160e01b031980821614156200028d576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152602081905260409020805460ff19166001179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620002ea576000855562000335565b82601f106200030557805160ff191683800117855562000335565b8280016001018555821562000335579182015b828111156200033557825182559160200191906001019062000318565b506200034392915062000347565b5090565b5b8082111562000343576000815560010162000348565b60805160601c611f206200037c600039806107f75250611f206000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806354ba0f27116100d857806395d89b411161008c578063c87b56dd11610066578063c87b56dd14610505578063e985e9c514610522578063f77c47911461055057610177565b806395d89b4114610409578063a22cb46514610411578063b88d4fde1461043f57610177565b80636352211e116100bd5780636352211e146103be5780636c0360eb146103db57806370a08231146103e357610177565b806354ba0f271461039057806361b8ce8c146103b657610177565b806319ab453c1161012f5780632f745c59116101145780632f745c591461031157806342842e0e1461033d5780634f6ccce71461037357610177565b806319ab453c146102b557806323b872dd146102db57610177565b8063081812fc11610160578063081812fc14610234578063095ea7b31461026d57806318160ddd1461029b57610177565b806301ffc9a71461017c57806306fdde03146101b7575b600080fd5b6101a36004803603602081101561019257600080fd5b50356001600160e01b031916610558565b604080519115158252519081900360200190f35b6101bf61057b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f95781810151838201526020016101e1565b50505050905090810190601f1680156102265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102516004803603602081101561024a57600080fd5b5035610611565b604080516001600160a01b039092168252519081900360200190f35b6102996004803603604081101561028357600080fd5b506001600160a01b038135169060200135610673565b005b6102a361074e565b60408051918252519081900360200190f35b610299600480360360208110156102cb57600080fd5b50356001600160a01b031661075f565b610299600480360360608110156102f157600080fd5b506001600160a01b03813581169160208101359091169060400135610902565b6102a36004803603604081101561032757600080fd5b506001600160a01b038135169060200135610959565b6102996004803603606081101561035357600080fd5b506001600160a01b03813581169160208101359091169060400135610984565b6102a36004803603602081101561038957600080fd5b503561099f565b6102a3600480360360208110156103a657600080fd5b50356001600160a01b03166109b5565b6102a3610a2d565b610251600480360360208110156103d457600080fd5b5035610a33565b6101bf610a5b565b6102a3600480360360208110156103f957600080fd5b50356001600160a01b0316610abc565b6101bf610b24565b6102996004803603604081101561042757600080fd5b506001600160a01b0381351690602001351515610b85565b6102996004803603608081101561045557600080fd5b6001600160a01b0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561049057600080fd5b8201836020820111156104a257600080fd5b803590602001918460018302840111640100000000831117156104c457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610c8a945050505050565b6101bf6004803603602081101561051b57600080fd5b5035610ce8565b6101a36004803603604081101561053857600080fd5b506001600160a01b0381358116916020013516610f69565b610251610f97565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b820191906000526020600020905b8154815290600101906020018083116105ea57829003601f168201915b5050505050905090565b600061061c82610fa6565b6106575760405162461bcd60e51b815260040180806020018281038252602c815260200180611e15602c913960400191505060405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061067e82610a33565b9050806001600160a01b0316836001600160a01b031614156106d15760405162461bcd60e51b8152600401808060200182810382526021815260200180611e996021913960400191505060405180910390fd5b806001600160a01b03166106e3610fb3565b6001600160a01b031614806107045750610704816106ff610fb3565b610f69565b61073f5760405162461bcd60e51b8152600401808060200182810382526038815260200180611d3a6038913960400191505060405180910390fd5b6107498383610fb7565b505050565b600061075a6002611032565b905090565b600a54610100900460ff1680610778575061077861103d565b806107865750600a5460ff16155b6107c15760405162461bcd60e51b815260040180806020018281038252602e815260200180611dc5602e913960400191505060405180910390fd5b600a54610100900460ff161580156107ec57600a805460ff1961ff0019909116610100171660011790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610869576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166108c4576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600c805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905580156108fe57600a805461ff00191690555b5050565b61091361090d610fb3565b8261104e565b61094e5760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b6107498383836110f2565b6001600160a01b038216600090815260016020526040812061097b908361123e565b90505b92915050565b61074983838360405180602001604052806000815250610c8a565b6000806109ad60028461124a565b509392505050565b600c546000906001600160a01b03163314610a17576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b50600b8054600181019091556105768282611266565b600b5481565b600061097e82604051806060016040528060298152602001611d9c6029913960029190611280565b60098054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b60006001600160a01b038216610b035760405162461bcd60e51b815260040180806020018281038252602a815260200180611d72602a913960400191505060405180910390fd5b6001600160a01b038216600090815260016020526040902061097e90611032565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b610b8d610fb3565b6001600160a01b0316826001600160a01b03161415610bf3576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060056000610c00610fb3565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155610c44610fb3565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b610c9b610c95610fb3565b8361104e565b610cd65760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b610ce284848484611297565b50505050565b6060610cf382610fa6565b610d2e5760405162461bcd60e51b815260040180806020018281038252602f815260200180611e6a602f913960400191505060405180910390fd5b60008281526008602090815260408083208054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015610dc15780601f10610d9657610100808354040283529160200191610dc1565b820191906000526020600020905b815481529060010190602001808311610da457829003601f168201915b505050505090506000610dd2610a5b565b9050805160001415610de657509050610576565b815115610ea75780826040516020018083805190602001908083835b60208310610e215780518252601f199092019160209182019101610e02565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610e695780518252601f199092019160209182019101610e4a565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050610576565b80610eb1856112e9565b6040516020018083805190602001908083835b60208310610ee35780518252601f199092019160209182019101610ec4565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610f2b5780518252601f199092019160209182019101610f0c565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050919050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b600c546001600160a01b031681565b600061097e6002836113dc565b3390565b6000818152600460205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091558190610ff982610a33565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061097e826113e8565b6000611048306113ec565b15905090565b600061105982610fa6565b6110945760405162461bcd60e51b815260040180806020018281038252602c815260200180611d0e602c913960400191505060405180910390fd5b600061109f83610a33565b9050806001600160a01b0316846001600160a01b031614806110da5750836001600160a01b03166110cf84610611565b6001600160a01b0316145b806110ea57506110ea8185610f69565b949350505050565b826001600160a01b031661110582610a33565b6001600160a01b03161461114a5760405162461bcd60e51b8152600401808060200182810382526029815260200180611e416029913960400191505060405180910390fd5b6001600160a01b03821661118f5760405162461bcd60e51b8152600401808060200182810382526024815260200180611cea6024913960400191505060405180910390fd5b61119a8383836113f2565b6111a5600082610fb7565b6001600160a01b03831660009081526001602052604090206111c79082611462565b506001600160a01b03821660009081526001602052604090206111ea908261146e565b506111f76002828461147a565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061097b8383611490565b600080808061125986866114f4565b9097909650945050505050565b6108fe82826040518060200160405280600081525061156f565b600061128d8484846115c1565b90505b9392505050565b6112a28484846110f2565b6112ae8484848461168b565b610ce25760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b60608161130e57506040805180820190915260018152600360fc1b6020820152610576565b8160005b811561132657600101600a82049150611312565b60008167ffffffffffffffff8111801561133f57600080fd5b506040519080825280601f01601f19166020018201604052801561136a576020820181803683370190505b50859350905060001982015b83156113d357600a840660300160f81b8282806001900393508151811061139957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84049350611376565b50949350505050565b600061097b838361181d565b5490565b3b151590565b600c546040805163c65a391d60e01b81526004810184905260006024820181905291516001600160a01b039093169263c65a391d9260448084019391929182900301818387803b15801561144557600080fd5b505af1158015611459573d6000803e3d6000fd5b50505050505050565b600061097b8383611835565b600061097b83836118fb565b600061128d84846001600160a01b038516611945565b815460009082106114d25760405162461bcd60e51b8152600401808060200182810382526022815260200180611c966022913960400191505060405180910390fd5b8260000182815481106114e157fe5b9060005260206000200154905092915050565b8154600090819083106115385760405162461bcd60e51b8152600401808060200182810382526022815260200180611df36022913960400191505060405180910390fd5b600084600001848154811061154957fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b61157983836119dc565b611586600084848461168b565b6107495760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b6000828152600184016020526040812054828161165c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611621578181015183820152602001611609565b50505050905090810190601f16801561164e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5084600001600182038154811061166f57fe5b9060005260206000209060020201600101549150509392505050565b600061169f846001600160a01b03166113ec565b6116ab575060016110ea565b60006117e3630a85bd0160e11b6116c0610fb3565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561172757818101518382015260200161170f565b50505050905090810190601f1680156117545780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001611cb8603291396001600160a01b0388169190611b0a565b905060008180602001905160208110156117fc57600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b600081815260018301602052604081205480156118f1578354600019808301919081019060009087908390811061186857fe5b906000526020600020015490508087600001848154811061188557fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806118b557fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061097e565b600091505061097e565b6000611907838361181d565b61193d5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561097e565b50600061097e565b6000828152600184016020526040812054806119aa575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611290565b828560000160018303815481106119bd57fe5b9060005260206000209060020201600101819055506000915050611290565b6001600160a01b038216611a37576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b611a4081610fa6565b15611a92576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b611a9e600083836113f2565b6001600160a01b0382166000908152600160205260409020611ac0908261146e565b50611acd6002828461147a565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b606061128d848460008585611b1e856113ec565b611b6f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310611bad5780518252601f199092019160209182019101611b8e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611c0f576040519150601f19603f3d011682016040523d82523d6000602084013e611c14565b606091505b5091509150611c24828286611c2f565b979650505050505050565b60608315611c3e575081611290565b825115611c4e5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561162157818101518382015260200161160956fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a26469706673582212207d83bf40ecfe95bb92aa9776a7a467a49b4b6adfd61b55d757fb5da1867bafdb64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101775760003560e01c806354ba0f27116100d857806395d89b411161008c578063c87b56dd11610066578063c87b56dd14610505578063e985e9c514610522578063f77c47911461055057610177565b806395d89b4114610409578063a22cb46514610411578063b88d4fde1461043f57610177565b80636352211e116100bd5780636352211e146103be5780636c0360eb146103db57806370a08231146103e357610177565b806354ba0f271461039057806361b8ce8c146103b657610177565b806319ab453c1161012f5780632f745c59116101145780632f745c591461031157806342842e0e1461033d5780634f6ccce71461037357610177565b806319ab453c146102b557806323b872dd146102db57610177565b8063081812fc11610160578063081812fc14610234578063095ea7b31461026d57806318160ddd1461029b57610177565b806301ffc9a71461017c57806306fdde03146101b7575b600080fd5b6101a36004803603602081101561019257600080fd5b50356001600160e01b031916610558565b604080519115158252519081900360200190f35b6101bf61057b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f95781810151838201526020016101e1565b50505050905090810190601f1680156102265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102516004803603602081101561024a57600080fd5b5035610611565b604080516001600160a01b039092168252519081900360200190f35b6102996004803603604081101561028357600080fd5b506001600160a01b038135169060200135610673565b005b6102a361074e565b60408051918252519081900360200190f35b610299600480360360208110156102cb57600080fd5b50356001600160a01b031661075f565b610299600480360360608110156102f157600080fd5b506001600160a01b03813581169160208101359091169060400135610902565b6102a36004803603604081101561032757600080fd5b506001600160a01b038135169060200135610959565b6102996004803603606081101561035357600080fd5b506001600160a01b03813581169160208101359091169060400135610984565b6102a36004803603602081101561038957600080fd5b503561099f565b6102a3600480360360208110156103a657600080fd5b50356001600160a01b03166109b5565b6102a3610a2d565b610251600480360360208110156103d457600080fd5b5035610a33565b6101bf610a5b565b6102a3600480360360208110156103f957600080fd5b50356001600160a01b0316610abc565b6101bf610b24565b6102996004803603604081101561042757600080fd5b506001600160a01b0381351690602001351515610b85565b6102996004803603608081101561045557600080fd5b6001600160a01b0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561049057600080fd5b8201836020820111156104a257600080fd5b803590602001918460018302840111640100000000831117156104c457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610c8a945050505050565b6101bf6004803603602081101561051b57600080fd5b5035610ce8565b6101a36004803603604081101561053857600080fd5b506001600160a01b0381358116916020013516610f69565b610251610f97565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b820191906000526020600020905b8154815290600101906020018083116105ea57829003601f168201915b5050505050905090565b600061061c82610fa6565b6106575760405162461bcd60e51b815260040180806020018281038252602c815260200180611e15602c913960400191505060405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061067e82610a33565b9050806001600160a01b0316836001600160a01b031614156106d15760405162461bcd60e51b8152600401808060200182810382526021815260200180611e996021913960400191505060405180910390fd5b806001600160a01b03166106e3610fb3565b6001600160a01b031614806107045750610704816106ff610fb3565b610f69565b61073f5760405162461bcd60e51b8152600401808060200182810382526038815260200180611d3a6038913960400191505060405180910390fd5b6107498383610fb7565b505050565b600061075a6002611032565b905090565b600a54610100900460ff1680610778575061077861103d565b806107865750600a5460ff16155b6107c15760405162461bcd60e51b815260040180806020018281038252602e815260200180611dc5602e913960400191505060405180910390fd5b600a54610100900460ff161580156107ec57600a805460ff1961ff0019909116610100171660011790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610869576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166108c4576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600c805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905580156108fe57600a805461ff00191690555b5050565b61091361090d610fb3565b8261104e565b61094e5760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b6107498383836110f2565b6001600160a01b038216600090815260016020526040812061097b908361123e565b90505b92915050565b61074983838360405180602001604052806000815250610c8a565b6000806109ad60028461124a565b509392505050565b600c546000906001600160a01b03163314610a17576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b50600b8054600181019091556105768282611266565b600b5481565b600061097e82604051806060016040528060298152602001611d9c6029913960029190611280565b60098054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b60006001600160a01b038216610b035760405162461bcd60e51b815260040180806020018281038252602a815260200180611d72602a913960400191505060405180910390fd5b6001600160a01b038216600090815260016020526040902061097e90611032565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b610b8d610fb3565b6001600160a01b0316826001600160a01b03161415610bf3576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060056000610c00610fb3565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155610c44610fb3565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b610c9b610c95610fb3565b8361104e565b610cd65760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b610ce284848484611297565b50505050565b6060610cf382610fa6565b610d2e5760405162461bcd60e51b815260040180806020018281038252602f815260200180611e6a602f913960400191505060405180910390fd5b60008281526008602090815260408083208054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015610dc15780601f10610d9657610100808354040283529160200191610dc1565b820191906000526020600020905b815481529060010190602001808311610da457829003601f168201915b505050505090506000610dd2610a5b565b9050805160001415610de657509050610576565b815115610ea75780826040516020018083805190602001908083835b60208310610e215780518252601f199092019160209182019101610e02565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610e695780518252601f199092019160209182019101610e4a565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050610576565b80610eb1856112e9565b6040516020018083805190602001908083835b60208310610ee35780518252601f199092019160209182019101610ec4565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610f2b5780518252601f199092019160209182019101610f0c565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050919050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b600c546001600160a01b031681565b600061097e6002836113dc565b3390565b6000818152600460205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091558190610ff982610a33565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061097e826113e8565b6000611048306113ec565b15905090565b600061105982610fa6565b6110945760405162461bcd60e51b815260040180806020018281038252602c815260200180611d0e602c913960400191505060405180910390fd5b600061109f83610a33565b9050806001600160a01b0316846001600160a01b031614806110da5750836001600160a01b03166110cf84610611565b6001600160a01b0316145b806110ea57506110ea8185610f69565b949350505050565b826001600160a01b031661110582610a33565b6001600160a01b03161461114a5760405162461bcd60e51b8152600401808060200182810382526029815260200180611e416029913960400191505060405180910390fd5b6001600160a01b03821661118f5760405162461bcd60e51b8152600401808060200182810382526024815260200180611cea6024913960400191505060405180910390fd5b61119a8383836113f2565b6111a5600082610fb7565b6001600160a01b03831660009081526001602052604090206111c79082611462565b506001600160a01b03821660009081526001602052604090206111ea908261146e565b506111f76002828461147a565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061097b8383611490565b600080808061125986866114f4565b9097909650945050505050565b6108fe82826040518060200160405280600081525061156f565b600061128d8484846115c1565b90505b9392505050565b6112a28484846110f2565b6112ae8484848461168b565b610ce25760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b60608161130e57506040805180820190915260018152600360fc1b6020820152610576565b8160005b811561132657600101600a82049150611312565b60008167ffffffffffffffff8111801561133f57600080fd5b506040519080825280601f01601f19166020018201604052801561136a576020820181803683370190505b50859350905060001982015b83156113d357600a840660300160f81b8282806001900393508151811061139957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84049350611376565b50949350505050565b600061097b838361181d565b5490565b3b151590565b600c546040805163c65a391d60e01b81526004810184905260006024820181905291516001600160a01b039093169263c65a391d9260448084019391929182900301818387803b15801561144557600080fd5b505af1158015611459573d6000803e3d6000fd5b50505050505050565b600061097b8383611835565b600061097b83836118fb565b600061128d84846001600160a01b038516611945565b815460009082106114d25760405162461bcd60e51b8152600401808060200182810382526022815260200180611c966022913960400191505060405180910390fd5b8260000182815481106114e157fe5b9060005260206000200154905092915050565b8154600090819083106115385760405162461bcd60e51b8152600401808060200182810382526022815260200180611df36022913960400191505060405180910390fd5b600084600001848154811061154957fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b61157983836119dc565b611586600084848461168b565b6107495760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b6000828152600184016020526040812054828161165c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611621578181015183820152602001611609565b50505050905090810190601f16801561164e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5084600001600182038154811061166f57fe5b9060005260206000209060020201600101549150509392505050565b600061169f846001600160a01b03166113ec565b6116ab575060016110ea565b60006117e3630a85bd0160e11b6116c0610fb3565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561172757818101518382015260200161170f565b50505050905090810190601f1680156117545780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001611cb8603291396001600160a01b0388169190611b0a565b905060008180602001905160208110156117fc57600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b600081815260018301602052604081205480156118f1578354600019808301919081019060009087908390811061186857fe5b906000526020600020015490508087600001848154811061188557fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806118b557fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061097e565b600091505061097e565b6000611907838361181d565b61193d5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561097e565b50600061097e565b6000828152600184016020526040812054806119aa575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611290565b828560000160018303815481106119bd57fe5b9060005260206000209060020201600101819055506000915050611290565b6001600160a01b038216611a37576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b611a4081610fa6565b15611a92576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b611a9e600083836113f2565b6001600160a01b0382166000908152600160205260409020611ac0908261146e565b50611acd6002828461147a565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b606061128d848460008585611b1e856113ec565b611b6f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310611bad5780518252601f199092019160209182019101611b8e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611c0f576040519150601f19603f3d011682016040523d82523d6000602084013e611c14565b606091505b5091509150611c24828286611c2f565b979650505050505050565b60608315611c3e575081611290565b825115611c4e5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561162157818101518382015260200161160956fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a26469706673582212207d83bf40ecfe95bb92aa9776a7a467a49b4b6adfd61b55d757fb5da1867bafdb64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC721-approve}.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC721-balanceOf}.\"\n      },\n      \"baseURI()\": {\n        \"details\": \"Returns the base URI set via {_setBaseURI}. This will be automatically added as a prefix in {tokenURI} to each token's URI, or to the token ID if no specific URI is set for that token ID.\"\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_name\": \"token name for ERC721\",\n          \"_symbol\": \"token symbol for ERC721\"\n        }\n      },\n      \"getApproved(uint256)\": {\n        \"details\": \"See {IERC721-getApproved}.\"\n      },\n      \"init(address)\": {\n        \"params\": {\n          \"_controller\": \"controller address\"\n        }\n      },\n      \"isApprovedForAll(address,address)\": {\n        \"details\": \"See {IERC721-isApprovedForAll}.\"\n      },\n      \"mintNFT(address)\": {\n        \"details\": \"autoincrement tokenId starts at 1\",\n        \"params\": {\n          \"_recipient\": \"recipient address for NFT\"\n        }\n      },\n      \"name()\": {\n        \"details\": \"See {IERC721Metadata-name}.\"\n      },\n      \"ownerOf(uint256)\": {\n        \"details\": \"See {IERC721-ownerOf}.\"\n      },\n      \"safeTransferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC721-safeTransferFrom}.\"\n      },\n      \"safeTransferFrom(address,address,uint256,bytes)\": {\n        \"details\": \"See {IERC721-safeTransferFrom}.\"\n      },\n      \"setApprovalForAll(address,bool)\": {\n        \"details\": \"See {IERC721-setApprovalForAll}.\"\n      },\n      \"supportsInterface(bytes4)\": {\n        \"details\": \"See {IERC165-supportsInterface}. Time complexity O(1), guaranteed to always use less than 30 000 gas.\"\n      },\n      \"symbol()\": {\n        \"details\": \"See {IERC721Metadata-symbol}.\"\n      },\n      \"tokenByIndex(uint256)\": {\n        \"details\": \"See {IERC721Enumerable-tokenByIndex}.\"\n      },\n      \"tokenOfOwnerByIndex(address,uint256)\": {\n        \"details\": \"See {IERC721Enumerable-tokenOfOwnerByIndex}.\"\n      },\n      \"tokenURI(uint256)\": {\n        \"details\": \"See {IERC721Metadata-tokenURI}.\"\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC721Enumerable-totalSupply}.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC721-transferFrom}.\"\n      }\n    },\n    \"stateVariables\": {\n      \"nextId\": {\n        \"details\": \"tokenId for the next vault opened\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"constructor\": {\n        \"notice\": \"short power perpetual constructor\"\n      },\n      \"init(address)\": {\n        \"notice\": \"initialize short contract\"\n      },\n      \"mintNFT(address)\": {\n        \"notice\": \"mint new NFT\"\n      }\n    },\n    \"notice\": \"ERC721 NFT representing ownership of a vault (short position)\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 388,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_supportedInterfaces\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_bytes4,t_bool)\"\n      },\n      {\n        \"astId\": 1704,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_holderTokens\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_struct(UintSet)4070_storage)\"\n      },\n      {\n        \"astId\": 1706,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_tokenOwners\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_struct(UintToAddressMap)3447_storage\"\n      },\n      {\n        \"astId\": 1710,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_tokenApprovals\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_mapping(t_uint256,t_address)\"\n      },\n      {\n        \"astId\": 1716,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_operatorApprovals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_bool))\"\n      },\n      {\n        \"astId\": 1718,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 1720,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"7\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 1724,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_tokenURIs\",\n        \"offset\": 0,\n        \"slot\": \"8\",\n        \"type\": \"t_mapping(t_uint256,t_string_storage)\"\n      },\n      {\n        \"astId\": 1726,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_baseURI\",\n        \"offset\": 0,\n        \"slot\": \"9\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 805,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_initialized\",\n        \"offset\": 0,\n        \"slot\": \"10\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 808,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_initializing\",\n        \"offset\": 1,\n        \"slot\": \"10\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 10957,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"nextId\",\n        \"offset\": 0,\n        \"slot\": \"11\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 10959,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"controller\",\n        \"offset\": 0,\n        \"slot\": \"12\",\n        \"type\": \"t_address\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_array(t_bytes32)dyn_storage\": {\n        \"base\": \"t_bytes32\",\n        \"encoding\": \"dynamic_array\",\n        \"label\": \"bytes32[]\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_array(t_struct(MapEntry)3121_storage)dyn_storage\": {\n        \"base\": \"t_struct(MapEntry)3121_storage\",\n        \"encoding\": \"dynamic_array\",\n        \"label\": \"struct EnumerableMap.MapEntry[]\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_bytes32\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bytes32\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_bytes4\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bytes4\",\n        \"numberOfBytes\": \"4\"\n      },\n      \"t_mapping(t_address,t_bool)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => bool)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_bool\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_bool))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => bool))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_bool)\"\n      },\n      \"t_mapping(t_address,t_struct(UintSet)4070_storage)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => struct EnumerableSet.UintSet)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_struct(UintSet)4070_storage\"\n      },\n      \"t_mapping(t_bytes32,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_bytes32\",\n        \"label\": \"mapping(bytes32 => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_mapping(t_bytes4,t_bool)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_bytes4\",\n        \"label\": \"mapping(bytes4 => bool)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_bool\"\n      },\n      \"t_mapping(t_uint256,t_address)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => address)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_address\"\n      },\n      \"t_mapping(t_uint256,t_string_storage)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => string)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_string_storage\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_struct(Map)3129_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableMap.Map\",\n        \"members\": [\n          {\n            \"astId\": 3124,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_entries\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_array(t_struct(MapEntry)3121_storage)dyn_storage\"\n          },\n          {\n            \"astId\": 3128,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_indexes\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_mapping(t_bytes32,t_uint256)\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(MapEntry)3121_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableMap.MapEntry\",\n        \"members\": [\n          {\n            \"astId\": 3118,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_key\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_bytes32\"\n          },\n          {\n            \"astId\": 3120,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_value\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_bytes32\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(Set)3684_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableSet.Set\",\n        \"members\": [\n          {\n            \"astId\": 3679,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_values\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_array(t_bytes32)dyn_storage\"\n          },\n          {\n            \"astId\": 3683,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_indexes\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_mapping(t_bytes32,t_uint256)\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(UintSet)4070_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableSet.UintSet\",\n        \"members\": [\n          {\n            \"astId\": 4069,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_inner\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_struct(Set)3684_storage\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(UintToAddressMap)3447_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableMap.UintToAddressMap\",\n        \"members\": [\n          {\n            \"astId\": 3446,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_inner\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_struct(Map)3129_storage\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/SqrtPriceMathPartial.json",
    "content": "{\n  \"address\": \"0xa932Db3b9f630436aeb5a9AF8687E521dc943569\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioAX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioBX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"roundUp\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getAmount0Delta\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioAX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioBX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"roundUp\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getAmount1Delta\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0xf23dfcc0c19dd6b861f4c91fb5ef8d2bcc6c90382acc2b417d88af568b700dca\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0xa932Db3b9f630436aeb5a9AF8687E521dc943569\",\n    \"transactionIndex\": 13,\n    \"gasUsed\": \"245472\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0xefbae2f6edd1913754f1fdbfd82bdb710bdcfd97eff013eb9e99ad70170ced1d\",\n    \"transactionHash\": \"0xf23dfcc0c19dd6b861f4c91fb5ef8d2bcc6c90382acc2b417d88af568b700dca\",\n    \"logs\": [],\n    \"blockNumber\": 8007860,\n    \"cumulativeGasUsed\": \"1528277\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioAX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioBX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"roundUp\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getAmount0Delta\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioAX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioBX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"roundUp\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getAmount1Delta\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"getAmount0Delta(uint160,uint160,uint128,bool)\\\":{\\\"details\\\":\\\"Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper), i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\",\\\"params\\\":{\\\"liquidity\\\":\\\"The amount of usable liquidity\\\",\\\"roundUp\\\":\\\"Whether to round the amount up or down\\\",\\\"sqrtRatioAX96\\\":\\\"A sqrt price\\\",\\\"sqrtRatioBX96\\\":\\\"Another sqrt price\\\"},\\\"returns\\\":{\\\"amount0\\\":\\\"Amount of token0 required to cover a position of size liquidity between the two passed prices\\\"}},\\\"getAmount1Delta(uint160,uint160,uint128,bool)\\\":{\\\"details\\\":\\\"Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\",\\\"params\\\":{\\\"liquidity\\\":\\\"The amount of usable liquidity\\\",\\\"roundUp\\\":\\\"Whether to round the amount up, or down\\\",\\\"sqrtRatioAX96\\\":\\\"A sqrt price\\\",\\\"sqrtRatioBX96\\\":\\\"Another sqrt price\\\"},\\\"returns\\\":{\\\"amount1\\\":\\\"Amount of token1 required to cover a position of size liquidity between the two passed prices\\\"}}},\\\"title\\\":\\\"Functions based on Q64.96 sqrt price and liquidity\\\",\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"getAmount0Delta(uint160,uint160,uint128,bool)\\\":{\\\"notice\\\":\\\"Gets the amount0 delta between two prices\\\"},\\\"getAmount1Delta(uint160,uint160,uint128,bool)\\\":{\\\"notice\\\":\\\"Gets the amount1 delta between two prices\\\"}},\\\"notice\\\":\\\"Exposes two functions from @uniswap/v3-core SqrtPriceMath that use square root of price as a Q64.96 and liquidity to compute deltas\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":\\\"SqrtPriceMathPartial\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/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\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x61037c610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80632c32d4b61461004557806348a0c5bd146100a7575b600080fd5b6100956004803603608081101561005b57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156100f7565b60408051918252519081900360200190f35b610095600480360360808110156100bd57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156101b4565b6000836001600160a01b0316856001600160a01b03161115610117579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661015357600080fd5b8361018357866001600160a01b03166101768383896001600160a01b0316610251565b8161017d57fe5b046101a9565b6101a961019a8383896001600160a01b0316610301565b886001600160a01b031661033b565b979650505050505050565b6000836001600160a01b0316856001600160a01b031611156101d4579293925b816102135761020e836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610251565b610248565b610248836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610301565b95945050505050565b6000808060001985870986860292508281109083900303905080610287576000841161027c57600080fd5b5082900490506102fa565b80841161029357600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b600061030e848484610251565b90506000828061031a57fe5b84860911156102fa57600019811061033157600080fd5b6001019392505050565b80820491061515019056fea264697066735822122015b1d5e98e518aedb03f0724756a56b09b753efd09a45ae663413fd3cad16d6d64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80632c32d4b61461004557806348a0c5bd146100a7575b600080fd5b6100956004803603608081101561005b57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156100f7565b60408051918252519081900360200190f35b610095600480360360808110156100bd57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156101b4565b6000836001600160a01b0316856001600160a01b03161115610117579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661015357600080fd5b8361018357866001600160a01b03166101768383896001600160a01b0316610251565b8161017d57fe5b046101a9565b6101a961019a8383896001600160a01b0316610301565b886001600160a01b031661033b565b979650505050505050565b6000836001600160a01b0316856001600160a01b031611156101d4579293925b816102135761020e836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610251565b610248565b610248836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610301565b95945050505050565b6000808060001985870986860292508281109083900303905080610287576000841161027c57600080fd5b5082900490506102fa565b80841161029357600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b600061030e848484610251565b90506000828061031a57fe5b84860911156102fa57600019811061033157600080fd5b6001019392505050565b80820491061515019056fea264697066735822122015b1d5e98e518aedb03f0724756a56b09b753efd09a45ae663413fd3cad16d6d64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"getAmount0Delta(uint160,uint160,uint128,bool)\": {\n        \"details\": \"Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper), i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\",\n        \"params\": {\n          \"liquidity\": \"The amount of usable liquidity\",\n          \"roundUp\": \"Whether to round the amount up or down\",\n          \"sqrtRatioAX96\": \"A sqrt price\",\n          \"sqrtRatioBX96\": \"Another sqrt price\"\n        },\n        \"returns\": {\n          \"amount0\": \"Amount of token0 required to cover a position of size liquidity between the two passed prices\"\n        }\n      },\n      \"getAmount1Delta(uint160,uint160,uint128,bool)\": {\n        \"details\": \"Calculates liquidity * (sqrt(upper) - sqrt(lower))\",\n        \"params\": {\n          \"liquidity\": \"The amount of usable liquidity\",\n          \"roundUp\": \"Whether to round the amount up, or down\",\n          \"sqrtRatioAX96\": \"A sqrt price\",\n          \"sqrtRatioBX96\": \"Another sqrt price\"\n        },\n        \"returns\": {\n          \"amount1\": \"Amount of token1 required to cover a position of size liquidity between the two passed prices\"\n        }\n      }\n    },\n    \"title\": \"Functions based on Q64.96 sqrt price and liquidity\",\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"getAmount0Delta(uint160,uint160,uint128,bool)\": {\n        \"notice\": \"Gets the amount0 delta between two prices\"\n      },\n      \"getAmount1Delta(uint160,uint160,uint128,bool)\": {\n        \"notice\": \"Gets the amount1 delta between two prices\"\n      }\n    },\n    \"notice\": \"Exposes two functions from @uniswap/v3-core SqrtPriceMath that use square root of price as a Q64.96 and liquidity to compute deltas\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/SwapRouter.json",
    "content": "{\n  \"address\": \"0x833A158dA5ceBc44901211427E9Df936023EC0d3\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_factory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_WETH9\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"WETH9\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"bytes\",\n              \"name\": \"path\",\n              \"type\": \"bytes\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountIn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOutMinimum\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactInputParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"exactInput\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountIn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOutMinimum\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactInputSingleParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"exactInputSingle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"bytes\",\n              \"name\": \"path\",\n              \"type\": \"bytes\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOut\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountInMaximum\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactOutputParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"exactOutput\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOut\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountInMaximum\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactOutputSingleParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"exactOutputSingle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes[]\",\n          \"name\": \"data\",\n          \"type\": \"bytes[]\"\n        }\n      ],\n      \"name\": \"multicall\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes[]\",\n          \"name\": \"results\",\n          \"type\": \"bytes[]\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"refundETH\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"deadline\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"nonce\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"expiry\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitAllowed\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"nonce\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"expiry\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitAllowedIfNecessary\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"deadline\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitIfNecessary\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"sweepToken\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"feeBips\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"feeRecipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"sweepTokenWithFee\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"unwrapWETH9\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"feeBips\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"feeRecipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"unwrapWETH9WithFee\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0xae2020cd296737e2622dde9de8791e1433f7c78c4d911a9dcc9caf592cc57de2\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x833A158dA5ceBc44901211427E9Df936023EC0d3\",\n    \"transactionIndex\": 13,\n    \"gasUsed\": \"2667120\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x62364c25350db2a69a96d016abe27de739a7f4798d80fefe67f47f38e781fc52\",\n    \"transactionHash\": \"0xae2020cd296737e2622dde9de8791e1433f7c78c4d911a9dcc9caf592cc57de2\",\n    \"logs\": [],\n    \"blockNumber\": 8007328,\n    \"cumulativeGasUsed\": \"4081980\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n    \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\"\n  ],\n  \"bytecode\": \"0x60c06040526000196000553480156200001757600080fd5b506040516200302f3803806200302f8339810160408190526200003a9162000076565b6001600160601b0319606092831b8116608052911b1660a052620000ad565b80516001600160a01b03811681146200007157600080fd5b919050565b6000806040838503121562000089578182fd5b620000948362000059565b9150620000a46020840162000059565b90509250929050565b60805160601c60a05160601c612f26620001096000398061012f528061058352806106ad5280610747528061078752806108b15280611c435280611ca35280611d24525080610dc6528061140c5280611e265250612f266000f3fe6080604052600436106101125760003560e01c8063c04b8d59116100a5578063df2ab5bb11610074578063f28c049811610059578063f28c0498146102f5578063f3995c6714610308578063fa461e331461031b576101bd565b8063df2ab5bb146102cf578063e0e189a0146102e2576101bd565b8063c04b8d5914610281578063c2e3140a14610294578063c45a0155146102a7578063db3e2198146102bc576101bd565b80634aa4a4fc116100e15780634aa4a4fc146102195780639b2c0a371461023b578063a4a78f0c1461024e578063ac9650d814610261576101bd565b806312210e8a146101c2578063414bf389146101ca5780634659a494146101f357806349404b7c14610206576101bd565b366101bd573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146101bb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4e6f742057455448390000000000000000000000000000000000000000000000604482015290519081900360640190fd5b005b600080fd5b6101bb61033b565b6101dd6101d83660046129f8565b61034d565b6040516101ea9190612df1565b60405180910390f35b6101bb610201366004612776565b6104bf565b6101bb610214366004612aff565b61057f565b34801561022557600080fd5b5061022e610745565b6040516101ea9190612c37565b6101bb610249366004612b2e565b610769565b6101bb61025c366004612776565b610981565b61027461026f3660046127d6565b610a56565b6040516101ea9190612caa565b6101dd61028f36600461294d565b610bb0565b6101bb6102a2366004612776565b610d0f565b3480156102b357600080fd5b5061022e610dc4565b6101dd6102ca3660046129f8565b610de8565b6101bb6102dd3660046126d7565b610f78565b6101bb6102f0366004612718565b611095565b6101dd610303366004612a14565b6111fb565b6101bb610316366004612776565b61132f565b34801561032757600080fd5b506101bb610336366004612868565b6113c7565b471561034b5761034b334761150e565b565b600081608001358061035d61165c565b11156103ca57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b61047060a08401356103e260808601606087016126b4565b6103f3610100870160e088016126b4565b604080518082019091528061040b60208a018a6126b4565b61041b60608b0160408c01612adc565b61042b60408c0160208d016126b4565b60405160200161043d93929190612bc1565b60405160208183030381529060405281526020013373ffffffffffffffffffffffffffffffffffffffff16815250611660565b91508260c001358210156104b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b090612d72565b60405180910390fd5b50919050565b604080517f8fcbaf0c00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101879052606481018690526001608482015260ff851660a482015260c4810184905260e48101839052905173ffffffffffffffffffffffffffffffffffffffff881691638fcbaf0c9161010480830192600092919082900301818387803b15801561055f57600080fd5b505af1158015610573573d6000803e3d6000fd5b50505050505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561060857600080fd5b505afa15801561061c573d6000803e3d6000fd5b505050506040513d602081101561063257600080fd5b50519050828110156106a557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e742057455448390000000000000000000000000000604482015290519081900360640190fd5b8015610740577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561071e57600080fd5b505af1158015610732573d6000803e3d6000fd5b50505050610740828261150e565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008211801561077a575060648211155b61078357600080fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561080c57600080fd5b505afa158015610820573d6000803e3d6000fd5b505050506040513d602081101561083657600080fd5b50519050848110156108a957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e742057455448390000000000000000000000000000604482015290519081900360640190fd5b801561097a577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561092257600080fd5b505af1158015610936573d6000803e3d6000fd5b50505050600061271061095285846117e690919063ffffffff16565b8161095957fe5b049050801561096c5761096c838261150e565b6109788582840361150e565b505b5050505050565b604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815233600482015230602482015290517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9173ffffffffffffffffffffffffffffffffffffffff89169163dd62ed3e91604480820192602092909190829003018186803b158015610a1657600080fd5b505afa158015610a2a573d6000803e3d6000fd5b505050506040513d6020811015610a4057600080fd5b50511015610978576109788686868686866104bf565b60608167ffffffffffffffff81118015610a6f57600080fd5b50604051908082528060200260200182016040528015610aa357816020015b6060815260200190600190039081610a8e5790505b50905060005b82811015610ba95760008030868685818110610ac157fe5b9050602002810190610ad39190612dfa565b604051610ae1929190612c27565b600060405180830381855af49150503d8060008114610b1c576040519150601f19603f3d011682016040523d82523d6000602084013e610b21565b606091505b509150915081610b8757604481511015610b3a57600080fd5b60048101905080806020019051810190610b5491906128e3565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b09190612d28565b80848481518110610b9457fe5b60209081029190910101525050600101610aa9565b5092915050565b6000816040015180610bc061165c565b1115610c2d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b335b6000610c3e8560000151611810565b9050610c97856060015182610c57578660200151610c59565b305b60006040518060400160405280610c738b6000015161181c565b81526020018773ffffffffffffffffffffffffffffffffffffffff16815250611660565b60608601528015610cb7578451309250610cb09061182b565b8552610cc4565b8460600151935050610cca565b50610c2f565b8360800151831015610d08576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b090612d72565b5050919050565b604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523360048201523060248201529051869173ffffffffffffffffffffffffffffffffffffffff89169163dd62ed3e91604480820192602092909190829003018186803b158015610d8457600080fd5b505afa158015610d98573d6000803e3d6000fd5b505050506040513d6020811015610dae57600080fd5b505110156109785761097886868686868661132f565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000816080013580610df861165c565b1115610e6557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b610f0e60a0840135610e7d60808601606087016126b4565b610e8e610100870160e088016126b4565b6040518060400160405280886020016020810190610eac91906126b4565b610ebc60608b0160408c01612adc565b610ec960208c018c6126b4565b604051602001610edb93929190612bc1565b60405160208183030381529060405281526020013373ffffffffffffffffffffffffffffffffffffffff16815250611860565b91508260c00135821115610f4e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b090612d3b565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600055919050565b60008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610fe157600080fd5b505afa158015610ff5573d6000803e3d6000fd5b505050506040513d602081101561100b57600080fd5b505190508281101561107e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e7420746f6b656e0000000000000000000000000000604482015290519081900360640190fd5b801561108f5761108f848383611a1c565b50505050565b6000821180156110a6575060648211155b6110af57600080fd5b60008573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561111857600080fd5b505afa15801561112c573d6000803e3d6000fd5b505050506040513d602081101561114257600080fd5b50519050848110156111b557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e7420746f6b656e0000000000000000000000000000604482015290519081900360640190fd5b80156109785760006127106111ca83866117e6565b816111d157fe5b04905080156111e5576111e5878483611a1c565b6111f28786838503611a1c565b50505050505050565b600081604001358061120b61165c565b111561127857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b6112eb606084013561129060408601602087016126b4565b60408051808201909152600090806112a88980612dfa565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525033602090910152611860565b5060005491508260800135821115610f4e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b090612d3b565b604080517fd505accf000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018790526064810186905260ff8516608482015260a4810184905260c48101839052905173ffffffffffffffffffffffffffffffffffffffff88169163d505accf9160e480830192600092919082900301818387803b15801561055f57600080fd5b60008413806113d65750600083135b6113df57600080fd5b60006113ed82840184612a4c565b905060008060006114018460000151611bf1565b9250925092506114337f0000000000000000000000000000000000000000000000000000000000000000848484611c22565b5060008060008a13611474578473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610896114a5565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16108a5b9150915081156114c4576114bf8587602001513384611c41565b610573565b85516114cf90611810565b156114f45785516114df9061182b565b86526114ee8133600089611860565b50610573565b806000819055508394506105738587602001513384611c41565b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040518082805190602001908083835b6020831061158557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611548565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146115e7576040519150601f19603f3d011682016040523d82523d6000602084013e6115ec565b606091505b505090508061074057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f5354450000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b4290565b600073ffffffffffffffffffffffffffffffffffffffff8416611681573093505b60008060006116938560000151611bf1565b9194509250905073ffffffffffffffffffffffffffffffffffffffff808316908416106000806116c4868686611e1f565b73ffffffffffffffffffffffffffffffffffffffff1663128acb088b856116ea8f611e5d565b73ffffffffffffffffffffffffffffffffffffffff8e161561170c578d611732565b8761172b5773fffd8963efd1fc6a506488495d951d5263988d25611732565b6401000276a45b8d6040516020016117439190612da9565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401611772959493929190612c58565b6040805180830381600087803b15801561178b57600080fd5b505af115801561179f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c39190612845565b91509150826117d257816117d4565b805b6000039b9a5050505050505050505050565b6000821580611801575050818102818382816117fe57fe5b04145b61180a57600080fd5b92915050565b8051604211155b919050565b606061180a826000602b611e8f565b805160609061180a9083906017907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901611e8f565b600073ffffffffffffffffffffffffffffffffffffffff8416611881573093505b60008060006118938560000151611bf1565b9194509250905073ffffffffffffffffffffffffffffffffffffffff808416908316106000806118c4858786611e1f565b73ffffffffffffffffffffffffffffffffffffffff1663128acb088b856118ea8f611e5d565b60000373ffffffffffffffffffffffffffffffffffffffff8e161561190f578d611935565b8761192e5773fffd8963efd1fc6a506488495d951d5263988d25611935565b6401000276a45b8d6040516020016119469190612da9565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401611975959493929190612c58565b6040805180830381600087803b15801561198e57600080fd5b505af11580156119a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c69190612845565b915091506000836119db5781836000036119e1565b82826000035b909850905073ffffffffffffffffffffffffffffffffffffffff8a16611a0d578b8114611a0d57600080fd5b50505050505050949350505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781529251825160009485949389169392918291908083835b60208310611af157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611ab4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611b53576040519150601f19603f3d011682016040523d82523d6000602084013e611b58565b606091505b5091509150818015611b86575080511580611b865750808060200190516020811015611b8357600080fd5b50515b61097a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f5354000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60008080611bff8482612076565b9250611c0c846014612176565b9050611c19846017612076565b91509193909250565b6000611c3885611c33868686612266565b6122e3565b95945050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148015611c9c5750804710155b15611de5577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d0957600080fd5b505af1158015611d1d573d6000803e3d6000fd5b50505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611db357600080fd5b505af1158015611dc7573d6000803e3d6000fd5b505050506040513d6020811015611ddd57600080fd5b5061108f9050565b73ffffffffffffffffffffffffffffffffffffffff8316301415611e1357611e0e848383611a1c565b61108f565b61108f84848484612313565b6000611e557f0000000000000000000000000000000000000000000000000000000000000000611e50868686612266565b6124f0565b949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210611e8b57600080fd5b5090565b60608182601f011015611f0357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b828284011015611f7457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b81830184511015611fe657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015290519081900360640190fd5b606082158015612005576040519150600082526020820160405261206d565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561203e578051835260209283019201612026565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6000818260140110156120ea57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b816014018351101561215d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b6000818260030110156121ea57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b816003018351101561225d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b61226e612626565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1611156122a6579192915b506040805160608101825273ffffffffffffffffffffffffffffffffffffffff948516815292909316602083015262ffffff169181019190915290565b60006122ef83836124f0565b90503373ffffffffffffffffffffffffffffffffffffffff82161461180a57600080fd5b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000178152925182516000948594938a169392918291908083835b602083106123f057805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016123b3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612452576040519150601f19603f3d011682016040523d82523d6000602084013e612457565b606091505b5091509150818015612485575080511580612485575080806020019051602081101561248257600080fd5b50515b61097857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f5354460000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000816020015173ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff161061253257600080fd5b508051602080830151604093840151845173ffffffffffffffffffffffffffffffffffffffff94851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561181781612ef4565b600082601f830112612661578081fd5b813561267461266f82612e88565b612e64565b818152846020838601011115612688578283fd5b816020850160208301379081016020019190915292915050565b600061010082840312156104b9578081fd5b6000602082840312156126c5578081fd5b81356126d081612ef4565b9392505050565b6000806000606084860312156126eb578182fd5b83356126f681612ef4565b925060208401359150604084013561270d81612ef4565b809150509250925092565b600080600080600060a0868803121561272f578081fd5b853561273a81612ef4565b945060208601359350604086013561275181612ef4565b925060608601359150608086013561276881612ef4565b809150509295509295909350565b60008060008060008060c0878903121561278e578081fd5b863561279981612ef4565b95506020870135945060408701359350606087013560ff811681146127bc578182fd5b9598949750929560808101359460a0909101359350915050565b600080602083850312156127e8578182fd5b823567ffffffffffffffff808211156127ff578384fd5b818501915085601f830112612812578384fd5b813581811115612820578485fd5b8660208083028501011115612833578485fd5b60209290920196919550909350505050565b60008060408385031215612857578182fd5b505080516020909101519092909150565b6000806000806060858703121561287d578182fd5b8435935060208501359250604085013567ffffffffffffffff808211156128a2578384fd5b818701915087601f8301126128b5578384fd5b8135818111156128c3578485fd5b8860208285010111156128d4578485fd5b95989497505060200194505050565b6000602082840312156128f4578081fd5b815167ffffffffffffffff81111561290a578182fd5b8201601f8101841361291a578182fd5b805161292861266f82612e88565b81815285602083850101111561293c578384fd5b611c38826020830160208601612ec8565b60006020828403121561295e578081fd5b813567ffffffffffffffff80821115612975578283fd5b9083019060a08286031215612988578283fd5b60405160a08101818110838211171561299d57fe5b6040528235828111156129ae578485fd5b6129ba87828601612651565b8252506129c960208401612646565b602082015260408301356040820152606083013560608201526080830135608082015280935050505092915050565b60006101008284031215612a0a578081fd5b6126d083836126a2565b600060208284031215612a25578081fd5b813567ffffffffffffffff811115612a3b578182fd5b820160a081850312156126d0578182fd5b600060208284031215612a5d578081fd5b813567ffffffffffffffff80821115612a74578283fd5b9083019060408286031215612a87578283fd5b604051604081018181108382111715612a9c57fe5b604052823582811115612aad578485fd5b612ab987828601612651565b82525060208301359250612acc83612ef4565b6020810192909252509392505050565b600060208284031215612aed578081fd5b813562ffffff811681146126d0578182fd5b60008060408385031215612b11578182fd5b823591506020830135612b2381612ef4565b809150509250929050565b60008060008060808587031215612b43578182fd5b843593506020850135612b5581612ef4565b9250604085013591506060850135612b6c81612ef4565b939692955090935050565b60008151808452612b8f816020860160208601612ec8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b6000828483379101908152919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a06080830152612c9f60a0830184612b77565b979650505050505050565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015612d1b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452612d09858351612b77565b94509285019290850190600101612ccf565b5092979650505050505050565b6000602082526126d06020830184612b77565b60208082526012908201527f546f6f206d756368207265717565737465640000000000000000000000000000604082015260600190565b60208082526013908201527f546f6f206c6974746c6520726563656976656400000000000000000000000000604082015260600190565b600060208252825160406020840152612dc56060840182612b77565b905073ffffffffffffffffffffffffffffffffffffffff60208501511660408401528091505092915050565b90815260200190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612e2e578283fd5b83018035915067ffffffffffffffff821115612e48578283fd5b602001915036819003821315612e5d57600080fd5b9250929050565b60405181810167ffffffffffffffff81118282101715612e8057fe5b604052919050565b600067ffffffffffffffff821115612e9c57fe5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b83811015612ee3578181015183820152602001612ecb565b8381111561108f5750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114612f1657600080fd5b5056fea164736f6c6343000706000a\"\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/TickMathExternal.json",
    "content": "{\n  \"address\": \"0x569292d3d8B44F02B11ef048A3Dd361e57880E8C\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tick\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"name\": \"getSqrtRatioAtTick\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96\",\n          \"type\": \"uint160\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96\",\n          \"type\": \"uint160\"\n        }\n      ],\n      \"name\": \"getTickAtSqrtRatio\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tick\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x7fe4a088f675d25a5da8ca9fa31b59d5cdea3ade0814eabcfc4d589172a017b8\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x569292d3d8B44F02B11ef048A3Dd361e57880E8C\",\n    \"transactionIndex\": 31,\n    \"gasUsed\": \"461403\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x25eff00e9052859271cf8cabd5fc500dc6308e69d182e9b6d7cc81b97becfb3b\",\n    \"transactionHash\": \"0x7fe4a088f675d25a5da8ca9fa31b59d5cdea3ade0814eabcfc4d589172a017b8\",\n    \"logs\": [],\n    \"blockNumber\": 8007859,\n    \"cumulativeGasUsed\": \"10215601\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"tick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"name\\\":\\\"getSqrtRatioAtTick\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"name\\\":\\\"getTickAtSqrtRatio\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"tick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"getSqrtRatioAtTick(int24)\\\":{\\\"details\\\":\\\"Throws if |tick| > max tick\\\",\\\"params\\\":{\\\"tick\\\":\\\"The input tick for the above formula\\\"},\\\"returns\\\":{\\\"sqrtPriceX96\\\":\\\"A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) at the given tick\\\"}},\\\"getTickAtSqrtRatio(uint160)\\\":{\\\"details\\\":\\\"Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may ever return.\\\",\\\"params\\\":{\\\"sqrtPriceX96\\\":\\\"The sqrt ratio for which to compute the tick as a Q64.96\\\"},\\\"returns\\\":{\\\"tick\\\":\\\"The greatest tick for which the ratio is less than or equal to the input ratio\\\"}}},\\\"stateVariables\\\":{\\\"MAX_SQRT_RATIO\\\":{\\\"details\\\":\\\"The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\"},\\\"MAX_TICK\\\":{\\\"details\\\":\\\"The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\"},\\\"MIN_SQRT_RATIO\\\":{\\\"details\\\":\\\"The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\"},\\\"MIN_TICK\\\":{\\\"details\\\":\\\"The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\"}},\\\"title\\\":\\\"Math library for computing sqrt prices from ticks and vice versa\\\",\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"getSqrtRatioAtTick(int24)\\\":{\\\"notice\\\":\\\"Calculates sqrt(1.0001^tick) * 2^96\\\"},\\\"getTickAtSqrtRatio(uint160)\\\":{\\\"notice\\\":\\\"Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\"}},\\\"notice\\\":\\\"Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports prices between 2**-128 and 2**128\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/libs/TickMathExternal.sol\\\":\\\"TickMathExternal\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x610768610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80634f76c05814610045578063986cfba314610082575b600080fd5b61006b6004803603602081101561005b57600080fd5b50356001600160a01b03166100be565b6040805160029290920b8252519081900360200190f35b6100a26004803603602081101561009857600080fd5b503560020b6103f3565b604080516001600160a01b039092168252519081900360200190f35b60006401000276a36001600160a01b038316108015906100fa575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b61012f576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106101d957607f810383901c91506101e3565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146103e457886001600160a01b03166103c8826103f3565b6001600160a01b031611156103dd57816103df565b805b6103e6565b815b9998505050505050505050565b60008060008360020b1261040a578260020b610412565b8260020b6000035b9050620d89e8811115610450576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b60006001821661047157700100000000000000000000000000000000610483565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156104b7576ffff97272373d413259a46990580e213a0260801c5b60048216156104d6576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b60088216156104f5576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610514576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610533576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610552576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610571576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610591576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b6102008216156105b1576ff987a7253ac413176f2b074cf7815e540260801c5b6104008216156105d1576ff3392b0822b70005940c7a398e4b70f30260801c5b6108008216156105f1576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610611576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610631576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610651576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610671576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610692576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156106b2576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156106d1576d2216e584f5fa1ea926041bedfe980260801c5b620800008216156106ee576b048a170391f7dc42444e8fa20260801c5b60008460020b131561070957806000198161070557fe5b0490505b64010000000081061561071d576001610720565b60005b60ff16602082901c019250505091905056fea26469706673582212202e5ff2dd11e1c84c4b4e2364d3ed76b64538bfce96b28ff3a83052ea235fa8ed64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80634f76c05814610045578063986cfba314610082575b600080fd5b61006b6004803603602081101561005b57600080fd5b50356001600160a01b03166100be565b6040805160029290920b8252519081900360200190f35b6100a26004803603602081101561009857600080fd5b503560020b6103f3565b604080516001600160a01b039092168252519081900360200190f35b60006401000276a36001600160a01b038316108015906100fa575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b61012f576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106101d957607f810383901c91506101e3565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146103e457886001600160a01b03166103c8826103f3565b6001600160a01b031611156103dd57816103df565b805b6103e6565b815b9998505050505050505050565b60008060008360020b1261040a578260020b610412565b8260020b6000035b9050620d89e8811115610450576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b60006001821661047157700100000000000000000000000000000000610483565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156104b7576ffff97272373d413259a46990580e213a0260801c5b60048216156104d6576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b60088216156104f5576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610514576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610533576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610552576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610571576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610591576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b6102008216156105b1576ff987a7253ac413176f2b074cf7815e540260801c5b6104008216156105d1576ff3392b0822b70005940c7a398e4b70f30260801c5b6108008216156105f1576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610611576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610631576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610651576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610671576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610692576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156106b2576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156106d1576d2216e584f5fa1ea926041bedfe980260801c5b620800008216156106ee576b048a170391f7dc42444e8fa20260801c5b60008460020b131561070957806000198161070557fe5b0490505b64010000000081061561071d576001610720565b60005b60ff16602082901c019250505091905056fea26469706673582212202e5ff2dd11e1c84c4b4e2364d3ed76b64538bfce96b28ff3a83052ea235fa8ed64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"getSqrtRatioAtTick(int24)\": {\n        \"details\": \"Throws if |tick| > max tick\",\n        \"params\": {\n          \"tick\": \"The input tick for the above formula\"\n        },\n        \"returns\": {\n          \"sqrtPriceX96\": \"A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) at the given tick\"\n        }\n      },\n      \"getTickAtSqrtRatio(uint160)\": {\n        \"details\": \"Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may ever return.\",\n        \"params\": {\n          \"sqrtPriceX96\": \"The sqrt ratio for which to compute the tick as a Q64.96\"\n        },\n        \"returns\": {\n          \"tick\": \"The greatest tick for which the ratio is less than or equal to the input ratio\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"MAX_SQRT_RATIO\": {\n        \"details\": \"The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\"\n      },\n      \"MAX_TICK\": {\n        \"details\": \"The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\"\n      },\n      \"MIN_SQRT_RATIO\": {\n        \"details\": \"The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\"\n      },\n      \"MIN_TICK\": {\n        \"details\": \"The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\"\n      }\n    },\n    \"title\": \"Math library for computing sqrt prices from ticks and vice versa\",\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"getSqrtRatioAtTick(int24)\": {\n        \"notice\": \"Calculates sqrt(1.0001^tick) * 2^96\"\n      },\n      \"getTickAtSqrtRatio(uint160)\": {\n        \"notice\": \"Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\"\n      }\n    },\n    \"notice\": \"Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports prices between 2**-128 and 2**128\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/UniswapV3Factory.json",
    "content": "{\n  \"address\": \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n  \"abi\": [\n    {\n      \"inputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"int24\",\n          \"name\": \"tickSpacing\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"name\": \"FeeAmountEnabled\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"oldOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnerChanged\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"token0\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"token1\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"int24\",\n          \"name\": \"tickSpacing\",\n          \"type\": \"int24\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"pool\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"PoolCreated\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"tokenA\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"tokenB\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"createPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"pool\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tickSpacing\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"name\": \"enableFeeAmount\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"feeAmountTickSpacing\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"getPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"parameters\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"factory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token0\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token1\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tickSpacing\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_owner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"setOwner\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x2ffb43ab8c2f85abde9068b067c88ada3888c58f3af3665e2f2cc824a4707233\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n    \"transactionIndex\": 21,\n    \"gasUsed\": \"5439096\",\n    \"logsBloom\": \"0x10000000000000000100000000040020000020000000000000080000800000000400000000000800080000000000000000004000040000000020000000000000000000000000002800000000000000000000000000000040000000000000000000000000021000000000000000000801000080000000000000000000000800004000000000000000010000000000000000000010000000000000200000000000000000000000000000000000000100000000000000000000000000000000000000000001000000000000000000000000000000000000080000004000000020000000000000000004000000200000000000000000000000000000000000000000\",\n    \"blockHash\": \"0xa1574ad396df3f4bb0bca673ee26b4d60dff2f936762a756778def5c1740d19e\",\n    \"transactionHash\": \"0x2ffb43ab8c2f85abde9068b067c88ada3888c58f3af3665e2f2cc824a4707233\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 21,\n        \"blockNumber\": 8007327,\n        \"transactionHash\": \"0x2ffb43ab8c2f85abde9068b067c88ada3888c58f3af3665e2f2cc824a4707233\",\n        \"address\": \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n        \"topics\": [\n          \"0xb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000006326a0dfe0517ff46af3ad16bc40c26c26397f9e\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 58,\n        \"blockHash\": \"0xa1574ad396df3f4bb0bca673ee26b4d60dff2f936762a756778def5c1740d19e\"\n      },\n      {\n        \"transactionIndex\": 21,\n        \"blockNumber\": 8007327,\n        \"transactionHash\": \"0x2ffb43ab8c2f85abde9068b067c88ada3888c58f3af3665e2f2cc824a4707233\",\n        \"address\": \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n        \"topics\": [\n          \"0xc66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc\",\n          \"0x00000000000000000000000000000000000000000000000000000000000001f4\",\n          \"0x000000000000000000000000000000000000000000000000000000000000000a\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 59,\n        \"blockHash\": \"0xa1574ad396df3f4bb0bca673ee26b4d60dff2f936762a756778def5c1740d19e\"\n      },\n      {\n        \"transactionIndex\": 21,\n        \"blockNumber\": 8007327,\n        \"transactionHash\": \"0x2ffb43ab8c2f85abde9068b067c88ada3888c58f3af3665e2f2cc824a4707233\",\n        \"address\": \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n        \"topics\": [\n          \"0xc66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000bb8\",\n          \"0x000000000000000000000000000000000000000000000000000000000000003c\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 60,\n        \"blockHash\": \"0xa1574ad396df3f4bb0bca673ee26b4d60dff2f936762a756778def5c1740d19e\"\n      },\n      {\n        \"transactionIndex\": 21,\n        \"blockNumber\": 8007327,\n        \"transactionHash\": \"0x2ffb43ab8c2f85abde9068b067c88ada3888c58f3af3665e2f2cc824a4707233\",\n        \"address\": \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n        \"topics\": [\n          \"0xc66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc\",\n          \"0x0000000000000000000000000000000000000000000000000000000000002710\",\n          \"0x00000000000000000000000000000000000000000000000000000000000000c8\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 61,\n        \"blockHash\": \"0xa1574ad396df3f4bb0bca673ee26b4d60dff2f936762a756778def5c1740d19e\"\n      }\n    ],\n    \"blockNumber\": 8007327,\n    \"cumulativeGasUsed\": \"7854973\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"bytecode\": \"0x60a060405234801561001057600080fd5b503060601b608052600380546001600160a01b031916339081179091556040516000907fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c908290a36101f4600081815260046020527ffb8cf1d12598d1a039dd1d106665851a96aadf67d0d9ed76fceea282119208b7805462ffffff1916600a90811790915560405190929160008051602061614b83398151915291a3610bb8600081815260046020527f72dffa9b822156d9cf4b0090fa0b656bcb9cc2b2c60eb6acfc20a34f54b31743805462ffffff1916603c90811790915560405190929160008051602061614b83398151915291a3612710600081815260046020527f8cc740d51daa94ff54f33bd779c2d20149f524c340519b49181be5a08615f829805462ffffff191660c890811790915560405190929160008051602061614b83398151915291a360805160601c615fd7610174600039806105515250615fd76000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063890357301161005b578063890357301461013b5780638a7c195f146101855780638da5cb5b146101b0578063a1671295146101b85761007d565b806313af4035146100825780631698ee82146100aa57806322afcccb14610102575b600080fd5b6100a86004803603602081101561009857600080fd5b50356001600160a01b03166101f4565b005b6100e6600480360360608110156100c057600080fd5b5080356001600160a01b03908116916020810135909116906040013562ffffff16610267565b604080516001600160a01b039092168252519081900360200190f35b6101246004803603602081101561011857600080fd5b503562ffffff16610293565b6040805160029290920b8252519081900360200190f35b6101436102a8565b604080516001600160a01b0396871681529486166020860152929094168383015262ffffff16606083015260029290920b608082015290519081900360a00190f35b6100a86004803603604081101561019b57600080fd5b5062ffffff813516906020013560020b6102de565b6100e66103a1565b6100e6600480360360608110156101ce57600080fd5b5080356001600160a01b03908116916020810135909116906040013562ffffff166103b0565b6003546001600160a01b0316331461020b57600080fd5b6003546040516001600160a01b038084169216907fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c90600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b60056020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b60046020526000908152604090205460020b81565b600054600154600280546001600160a01b03938416939283169281169162ffffff600160a01b83041691600160b81b9004900b85565b6003546001600160a01b031633146102f557600080fd5b620f42408262ffffff161061030957600080fd5b60008160020b13801561032057506140008160020b125b61032957600080fd5b62ffffff8216600090815260046020526040902054600290810b900b1561034f57600080fd5b62ffffff828116600081815260046020526040808220805462ffffff1916600287900b958616179055517fc66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc9190a35050565b6003546001600160a01b031681565b60006103ba610546565b826001600160a01b0316846001600160a01b031614156103d957600080fd5b600080846001600160a01b0316866001600160a01b0316106103fc5784866103ff565b85855b90925090506001600160a01b03821661041757600080fd5b62ffffff8416600090815260046020526040902054600290810b9081900b61043e57600080fd5b6001600160a01b0383811660009081526005602090815260408083208685168452825280832062ffffff8a168452909152902054161561047d57600080fd5b61048a308484888561057d565b6001600160a01b03808516600081815260056020818152604080842089871680865290835281852062ffffff8e168087529084528286208054988a166001600160a01b0319998a1681179091558287529484528286208787528452828620818752845294829020805490971684179096558051600289900b815291820192909252815195995091947f783cca1c0412dd0d695e784568c96da2e9c22ff989357a2e8b1d9b2b4e6b71189281900390910190a45050509392505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461057b57600080fd5b565b6040805160a0810182526001600160a01b03878116808352878216602080850182905292881684860181905262ffffff888116606080880182905260028a810b6080998a01819052600080546001600160a01b03199081169099178155600180548a1689179055825490981686177fffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffff16600160a01b8502177fffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffff16600160b81b91830b9095160293909317909255875180870194909452838801929092528281019190915285518083039091018152930193849052825192909101919091209091610686906106f5565b8190604051809103906000f59050801580156106a6573d6000803e3d6000fd5b50600080546001600160a01b0319908116909155600180549091169055600280547fffffffffffff00000000000000000000000000000000000000000000000000001690559695505050505050565b6158c8806107038339019056fe6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000aa164736f6c6343000706000ac66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc\"\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/WPowerPerp.json",
    "content": "{\n  \"address\": \"0x9421c968D28DD789363FbD8c9aA5cF2090F0a656\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_name\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_symbol\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burn\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"controller\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"subtractedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"decreaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"addedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"increaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controller\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"init\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"mint\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x34ff09c2d59fb5e9fea7ab60b4e23e28e3634cb3b4db7208959ff554c9bb5585\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x6326A0DFe0517ff46Af3AD16BC40c26C26397F9e\",\n    \"contractAddress\": \"0x9421c968D28DD789363FbD8c9aA5cF2090F0a656\",\n    \"transactionIndex\": 22,\n    \"gasUsed\": \"1032138\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x62e9161ea8a3bb2046b5b0025284b5177b2f092edc4d5e6261ce09072332be34\",\n    \"transactionHash\": \"0x34ff09c2d59fb5e9fea7ab60b4e23e28e3634cb3b4db7208959ff554c9bb5585\",\n    \"logs\": [],\n    \"blockNumber\": 8008057,\n    \"cumulativeGasUsed\": \"4019576\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"Opyn Squeeth\",\n    \"oSQTH\"\n  ],\n  \"solcInputHash\": \"05b9c7d057ff8b2bf36168b053759720\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_name\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_symbol\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burn\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"subtractedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"decreaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"addedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"increaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controller\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"init\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mint\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"details\\\":\\\"value of power perpetual is expected to go down over time through the impact of funding\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"allowance(address,address)\\\":{\\\"details\\\":\\\"See {IERC20-allowance}.\\\"},\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC20-balanceOf}.\\\"},\\\"burn(address,uint256)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"account to burn from\\\",\\\"_amount\\\":\\\"amount to burn\\\"}},\\\"constructor\\\":{\\\"params\\\":{\\\"_name\\\":\\\"token name for ERC20\\\",\\\"_symbol\\\":\\\"token symbol for ERC20\\\"}},\\\"decimals()\\\":{\\\"details\\\":\\\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\\\"},\\\"decreaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\\\"},\\\"increaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\\\"},\\\"init(address)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\"}},\\\"mint(address,uint256)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"account to mint to\\\",\\\"_amount\\\":\\\"amount to mint\\\"}},\\\"name()\\\":{\\\"details\\\":\\\"Returns the name of the token.\\\"},\\\"symbol()\\\":{\\\"details\\\":\\\"Returns the symbol of the token, usually a shorter version of the name.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC20-totalSupply}.\\\"},\\\"transfer(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"burn(address,uint256)\\\":{\\\"notice\\\":\\\"burn wPowerPerp\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"long power perpetual constructor\\\"},\\\"init(address)\\\":{\\\"notice\\\":\\\"init wPowerPerp contract\\\"},\\\"mint(address,uint256)\\\":{\\\"notice\\\":\\\"mint wPowerPerp\\\"}},\\\"notice\\\":\\\"ERC20 Token representing wrapped long power perpetual position\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/WPowerPerp.sol\\\":\\\"WPowerPerp\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// solhint-disable-next-line compiler-version\\\\npragma solidity >=0.4.24 <0.8.0;\\\\n\\\\nimport \\\\\\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\\\nabstract contract Initializable {\\\\n\\\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\\\n    function _isConstructor() private view returns (bool) {\\\\n        return !Address.isContract(address(this));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9abeffe138f098b16557187383ba0f9e8503602fa95cd668132986ee115237ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/core/WPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\n\\\\n//contract\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\nimport {Initializable} from \\\\\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice ERC20 Token representing wrapped long power perpetual position\\\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\\\n */\\\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\\\n    address public controller;\\\\n    address private immutable deployer;\\\\n\\\\n    /**\\\\n     * @notice long power perpetual constructor\\\\n     * @param _name token name for ERC20\\\\n     * @param _symbol token symbol for ERC20\\\\n     */\\\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\\\n        deployer = msg.sender;\\\\n    }\\\\n\\\\n    modifier onlyController() {\\\\n        require(msg.sender == controller, \\\\\\\"Not controller\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice init wPowerPerp contract\\\\n     * @param _controller controller address\\\\n     */\\\\n    function init(address _controller) external initializer {\\\\n        require(msg.sender == deployer, \\\\\\\"Invalid caller of init\\\\\\\");\\\\n        require(_controller != address(0), \\\\\\\"Invalid controller address\\\\\\\");\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp\\\\n     * @param _account account to mint to\\\\n     * @param _amount amount to mint\\\\n     */\\\\n    function mint(address _account, uint256 _amount) external override onlyController {\\\\n        _mint(_account, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp\\\\n     * @param _account account to burn from\\\\n     * @param _amount amount to burn\\\\n     */\\\\n    function burn(address _account, uint256 _amount) external override onlyController {\\\\n        _burn(_account, _amount);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x46a9dd6652f902a62c5e538d99c4566bcd23cbe21247621c2f17b67250c334c5\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60a06040523480156200001157600080fd5b506040516200130238038062001302833981810160405260408110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200010a57600080fd5b9083019060208201858111156200012057600080fd5b82516401000000008111828201881017156200013b57600080fd5b82525081516020918201929091019080838360005b838110156200016a57818101518382015260200162000150565b50505050905090810190601f168015620001985780820380516001836020036101000a031916815260200191505b50604052505082518391508290620001b8906003906020850190620001ed565b508051620001ce906004906020840190620001ed565b50506005805460ff191660121790555050503360601b60805262000299565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928262000225576000855562000270565b82601f106200024057805160ff191683800117855562000270565b8280016001018555821562000270579182015b828111156200027057825182559160200191906001019062000253565b506200027e92915062000282565b5090565b5b808211156200027e576000815560010162000283565b60805160601c61104b620002b760003980610505525061104b6000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806340c10f1911610097578063a457c2d711610066578063a457c2d7146102ff578063a9059cbb1461032b578063dd62ed3e14610357578063f77c479114610385576100f5565b806340c10f191461027957806370a08231146102a557806395d89b41146102cb5780639dc29fac146102d3576100f5565b806319ab453c116100d357806319ab453c146101d157806323b872dd146101f9578063313ce5671461022f578063395093511461024d576100f5565b806306fdde03146100fa578063095ea7b31461017757806318160ddd146101b7575b600080fd5b6101026103a9565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013c578181015183820152602001610124565b50505050905090810190601f1680156101695780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101a36004803603604081101561018d57600080fd5b506001600160a01b03813516906020013561043f565b604080519115158252519081900360200190f35b6101bf61045c565b60408051918252519081900360200190f35b6101f7600480360360208110156101e757600080fd5b50356001600160a01b0316610462565b005b6101a36004803603606081101561020f57600080fd5b506001600160a01b03813581169160208101359091169060400135610622565b6102376106a9565b6040805160ff9092168252519081900360200190f35b6101a36004803603604081101561026357600080fd5b506001600160a01b0381351690602001356106b2565b6101f76004803603604081101561028f57600080fd5b506001600160a01b038135169060200135610700565b6101bf600480360360208110156102bb57600080fd5b50356001600160a01b0316610761565b61010261077c565b6101f7600480360360408110156102e957600080fd5b506001600160a01b0381351690602001356107dd565b6101a36004803603604081101561031557600080fd5b506001600160a01b03813516906020013561083e565b6101a36004803603604081101561034157600080fd5b506001600160a01b0381351690602001356108a6565b6101bf6004803603604081101561036d57600080fd5b506001600160a01b03813581169160200135166108ba565b61038d6108e5565b604080516001600160a01b039092168252519081900360200190f35b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b820191906000526020600020905b81548152906001019060200180831161041857829003601f168201915b5050505050905090565b600061045361044c6108fb565b84846108ff565b50600192915050565b60025490565b60055462010000900460ff168061047c575061047c6109eb565b8061048f5750600554610100900460ff16155b6104ca5760405162461bcd60e51b815260040180806020018281038252602e815260200180610f31602e913960400191505060405180910390fd5b60055462010000900460ff161580156104fa576005805461ff001962ff0000199091166201000017166101001790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610577576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166105d2576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600580547fffffffffffffffffff0000000000000000000000000000000000000000ffffff1663010000006001600160a01b03851602179055801561061e576005805462ff0000191690555b5050565b600061062f8484846109fc565b61069f8461063b6108fb565b61069a85604051806060016040528060288152602001610f5f602891396001600160a01b038a166000908152600160205260408120906106796108fb565b6001600160a01b031681526020810191909152604001600020549190610b57565b6108ff565b5060019392505050565b60055460ff1690565b60006104536106bf6108fb565b8461069a85600160006106d06108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610bee565b600554630100000090046001600160a01b03163314610757576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610c4f565b6001600160a01b031660009081526020819052604090205490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b600554630100000090046001600160a01b03163314610834576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610d3f565b600061045361084b6108fb565b8461069a85604051806060016040528060258152602001610ff160259139600160006108756108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610b57565b60006104536108b36108fb565b84846109fc565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600554630100000090046001600160a01b031681565b3390565b6001600160a01b0383166109445760405162461bcd60e51b8152600401808060200182810382526024815260200180610fcd6024913960400191505060405180910390fd5b6001600160a01b0382166109895760405162461bcd60e51b8152600401808060200182810382526022815260200180610ee96022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60006109f630610e3b565b15905090565b6001600160a01b038316610a415760405162461bcd60e51b8152600401808060200182810382526025815260200180610fa86025913960400191505060405180910390fd5b6001600160a01b038216610a865760405162461bcd60e51b8152600401808060200182810382526023815260200180610ea46023913960400191505060405180910390fd5b610a91838383610e41565b610ace81604051806060016040528060268152602001610f0b602691396001600160a01b0386166000908152602081905260409020549190610b57565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610afd9082610bee565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610be65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610bab578181015183820152602001610b93565b50505050905090810190601f168015610bd85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610c48576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610caa576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610cb660008383610e41565b600254610cc39082610bee565b6002556001600160a01b038216600090815260208190526040902054610ce99082610bee565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610d845760405162461bcd60e51b8152600401808060200182810382526021815260200180610f876021913960400191505060405180910390fd5b610d9082600083610e41565b610dcd81604051806060016040528060228152602001610ec7602291396001600160a01b0385166000908152602081905260409020549190610b57565b6001600160a01b038316600090815260208190526040902055600254610df39082610e46565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b3b151590565b505050565b600082821115610e9d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122003d0364b6bf84a5d35855deb85c94b3e1a9dcddab8eaf4b0d7c6c5f3d27cc4af64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806340c10f1911610097578063a457c2d711610066578063a457c2d7146102ff578063a9059cbb1461032b578063dd62ed3e14610357578063f77c479114610385576100f5565b806340c10f191461027957806370a08231146102a557806395d89b41146102cb5780639dc29fac146102d3576100f5565b806319ab453c116100d357806319ab453c146101d157806323b872dd146101f9578063313ce5671461022f578063395093511461024d576100f5565b806306fdde03146100fa578063095ea7b31461017757806318160ddd146101b7575b600080fd5b6101026103a9565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013c578181015183820152602001610124565b50505050905090810190601f1680156101695780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101a36004803603604081101561018d57600080fd5b506001600160a01b03813516906020013561043f565b604080519115158252519081900360200190f35b6101bf61045c565b60408051918252519081900360200190f35b6101f7600480360360208110156101e757600080fd5b50356001600160a01b0316610462565b005b6101a36004803603606081101561020f57600080fd5b506001600160a01b03813581169160208101359091169060400135610622565b6102376106a9565b6040805160ff9092168252519081900360200190f35b6101a36004803603604081101561026357600080fd5b506001600160a01b0381351690602001356106b2565b6101f76004803603604081101561028f57600080fd5b506001600160a01b038135169060200135610700565b6101bf600480360360208110156102bb57600080fd5b50356001600160a01b0316610761565b61010261077c565b6101f7600480360360408110156102e957600080fd5b506001600160a01b0381351690602001356107dd565b6101a36004803603604081101561031557600080fd5b506001600160a01b03813516906020013561083e565b6101a36004803603604081101561034157600080fd5b506001600160a01b0381351690602001356108a6565b6101bf6004803603604081101561036d57600080fd5b506001600160a01b03813581169160200135166108ba565b61038d6108e5565b604080516001600160a01b039092168252519081900360200190f35b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b820191906000526020600020905b81548152906001019060200180831161041857829003601f168201915b5050505050905090565b600061045361044c6108fb565b84846108ff565b50600192915050565b60025490565b60055462010000900460ff168061047c575061047c6109eb565b8061048f5750600554610100900460ff16155b6104ca5760405162461bcd60e51b815260040180806020018281038252602e815260200180610f31602e913960400191505060405180910390fd5b60055462010000900460ff161580156104fa576005805461ff001962ff0000199091166201000017166101001790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610577576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166105d2576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600580547fffffffffffffffffff0000000000000000000000000000000000000000ffffff1663010000006001600160a01b03851602179055801561061e576005805462ff0000191690555b5050565b600061062f8484846109fc565b61069f8461063b6108fb565b61069a85604051806060016040528060288152602001610f5f602891396001600160a01b038a166000908152600160205260408120906106796108fb565b6001600160a01b031681526020810191909152604001600020549190610b57565b6108ff565b5060019392505050565b60055460ff1690565b60006104536106bf6108fb565b8461069a85600160006106d06108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610bee565b600554630100000090046001600160a01b03163314610757576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610c4f565b6001600160a01b031660009081526020819052604090205490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b600554630100000090046001600160a01b03163314610834576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610d3f565b600061045361084b6108fb565b8461069a85604051806060016040528060258152602001610ff160259139600160006108756108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610b57565b60006104536108b36108fb565b84846109fc565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600554630100000090046001600160a01b031681565b3390565b6001600160a01b0383166109445760405162461bcd60e51b8152600401808060200182810382526024815260200180610fcd6024913960400191505060405180910390fd5b6001600160a01b0382166109895760405162461bcd60e51b8152600401808060200182810382526022815260200180610ee96022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60006109f630610e3b565b15905090565b6001600160a01b038316610a415760405162461bcd60e51b8152600401808060200182810382526025815260200180610fa86025913960400191505060405180910390fd5b6001600160a01b038216610a865760405162461bcd60e51b8152600401808060200182810382526023815260200180610ea46023913960400191505060405180910390fd5b610a91838383610e41565b610ace81604051806060016040528060268152602001610f0b602691396001600160a01b0386166000908152602081905260409020549190610b57565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610afd9082610bee565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610be65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610bab578181015183820152602001610b93565b50505050905090810190601f168015610bd85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610c48576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610caa576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610cb660008383610e41565b600254610cc39082610bee565b6002556001600160a01b038216600090815260208190526040902054610ce99082610bee565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610d845760405162461bcd60e51b8152600401808060200182810382526021815260200180610f876021913960400191505060405180910390fd5b610d9082600083610e41565b610dcd81604051806060016040528060228152602001610ec7602291396001600160a01b0385166000908152602081905260409020549190610b57565b6001600160a01b038316600090815260208190526040902055600254610df39082610e46565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b3b151590565b505050565b600082821115610e9d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122003d0364b6bf84a5d35855deb85c94b3e1a9dcddab8eaf4b0d7c6c5f3d27cc4af64736f6c63430007060033\",\n  \"devdoc\": {\n    \"details\": \"value of power perpetual is expected to go down over time through the impact of funding\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"allowance(address,address)\": {\n        \"details\": \"See {IERC20-allowance}.\"\n      },\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC20-balanceOf}.\"\n      },\n      \"burn(address,uint256)\": {\n        \"params\": {\n          \"_account\": \"account to burn from\",\n          \"_amount\": \"amount to burn\"\n        }\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_name\": \"token name for ERC20\",\n          \"_symbol\": \"token symbol for ERC20\"\n        }\n      },\n      \"decimals()\": {\n        \"details\": \"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"\n      },\n      \"decreaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"\n      },\n      \"increaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"init(address)\": {\n        \"params\": {\n          \"_controller\": \"controller address\"\n        }\n      },\n      \"mint(address,uint256)\": {\n        \"params\": {\n          \"_account\": \"account to mint to\",\n          \"_amount\": \"amount to mint\"\n        }\n      },\n      \"name()\": {\n        \"details\": \"Returns the name of the token.\"\n      },\n      \"symbol()\": {\n        \"details\": \"Returns the symbol of the token, usually a shorter version of the name.\"\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC20-totalSupply}.\"\n      },\n      \"transfer(address,uint256)\": {\n        \"details\": \"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"burn(address,uint256)\": {\n        \"notice\": \"burn wPowerPerp\"\n      },\n      \"constructor\": {\n        \"notice\": \"long power perpetual constructor\"\n      },\n      \"init(address)\": {\n        \"notice\": \"init wPowerPerp contract\"\n      },\n      \"mint(address,uint256)\": {\n        \"notice\": \"mint wPowerPerp\"\n      }\n    },\n    \"notice\": \"ERC20 Token representing wrapped long power perpetual position\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 881,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_balances\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 887,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_allowances\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n      },\n      {\n        \"astId\": 889,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_totalSupply\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 891,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 893,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 895,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_decimals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint8\"\n      },\n      {\n        \"astId\": 805,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_initialized\",\n        \"offset\": 1,\n        \"slot\": \"5\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 808,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_initializing\",\n        \"offset\": 2,\n        \"slot\": \"5\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 11082,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"controller\",\n        \"offset\": 3,\n        \"slot\": \"5\",\n        \"type\": \"t_address\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => uint256))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_uint256)\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint8\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint8\",\n        \"numberOfBytes\": \"1\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/solcInputs/0233939f192df1cbf8f7a345e29af693.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // Ceil A to a multiple m\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(sub(add(a, m), 1), m), m);\\n    }\\n\\n    // Floor A to a multiple m\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(a, m), m);\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {EIP712} from \\\"@openzeppelin/contracts/drafts/EIP712.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\nimport {ECDSA} from \\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * Crab V2 Error Codes:\\n * C1: Caller is not timelock\\n * C2: Contract not yet initialized\\n * C3: Invalid oracle address\\n * C4: Invalid timelock address\\n * C5: Invalid ETH:WSqueeth address\\n * C6: Invalid crabMigration address\\n * C7: Invalid hedge time threshold\\n * C8: Invalid hedge price threshold\\n * C9: Cannot receive ETH\\n * C10: Caller not Crab Migration contract\\n * C11: Crab V2 already initialized\\n * C12: Squeeth contracts not shut down\\n * C13: Crab must redeemShortShutdown\\n * C14: Twap period is too short\\n * C15: Price tolerance is too high\\n * C16: Deposit exceeds strategy cap\\n * C17: Clearing Price should be below bid price\\n * C18: Clearing Price should be above offer price\\n * C19: Invalid offer signature\\n * C20: Order has expired\\n * C21: Manager Price should be greater than 0\\n * C22: Not a valid Time or Price hedge\\n * C23: Orders must take the opposite side of the hedge\\n * C24: All orders must be either buying or selling\\n * C25: Orders are not arranged properly\\n * C26: Crab contracts shut down\\n *  C27: Nonce already used.\\n */\\n\\n/**\\n * @dev CrabStrategyV2 contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    // @dev OTC price must be within this distance of the uniswap twap price\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\n\\n    // @dev OTC price tolerance cannot exceed 20%\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\n\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n    /// @dev true if CrabV2 was initialized\\n    bool public isInitialized;\\n\\n    /// @dev typehash for signed orders\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\n        keccak256(\\n            \\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\"\\n        );\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:wSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable timelock;\\n    address public immutable crabMigration;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev wSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    /// @dev store the used flag for a nonce for each address\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct Order {\\n        uint256 bidId;\\n        address trader;\\n        uint256 quantity;\\n        uint256 price;\\n        bool isBuying;\\n        uint256 expiry;\\n        uint256 nonce;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event HedgeOTCSingle(\\n        address trader,\\n        uint256 bidId,\\n        uint256 quantity,\\n        uint256 price,\\n        bool isBuying,\\n        uint256 clearingPrice\\n    );\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\n\\n    modifier onlyTimelock() {\\n        require(msg.sender == timelock, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialization() {\\n        require(isInitialized, \\\"C2\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _timelock timelock contract address\\n     * @param _crabMigration crab migration contract address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        address _timelock,\\n        address _crabMigration,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold\\n    )\\n        StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy v2\\\", \\\"Crabv2\\\")\\n        StrategyFlashSwap(_uniswapFactory)\\n        EIP712(\\\"CrabOTC\\\", \\\"2\\\")\\n    {\\n        require(_oracle != address(0), \\\"C3\\\");\\n        require(_timelock != address(0), \\\"C4\\\");\\n        require(_ethWSqueethPool != address(0), \\\"C5\\\");\\n        require(_crabMigration != address(0), \\\"C6\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        timelock = _timelock;\\n        crabMigration = _crabMigration;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"C9\\\");\\n    }\\n\\n    /**\\n     * @notice initializes the collateral ratio after the first migration\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\n     * @param _crabSharesToMint crab shares to mint\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\n     * @param _strategyCap strategy cap for crab V2\\n     */\\n    function initialize(\\n        uint256 _wSqueethToMint,\\n        uint256 _crabSharesToMint,\\n        uint256 _timeAtLastHedge,\\n        uint256 _priceAtLastHedge,\\n        uint256 _strategyCap\\n    ) external payable {\\n        require(msg.sender == crabMigration, \\\"C10\\\");\\n        require(!isInitialized, \\\"C11\\\");\\n\\n        _setStrategyCap(_strategyCap);\\n\\n        uint256 amount = msg.value;\\n\\n        _checkStrategyCap(amount, 0);\\n\\n        // store hedge data from crab V1\\n        timeAtLastHedge = _timeAtLastHedge;\\n        priceAtLastHedge = _priceAtLastHedge;\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\n\\n        isInitialized = true;\\n    }\\n\\n    /**\\n     * @notice transfer vault NFT to new contract\\n     * @dev strategy cap is set to 0 to avoid future deposits\\n     * @param _newStrategy new strategy contract address\\n     */\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\n        _setStrategyCap(0);\\n\\n        emit VaultTransferred(_newStrategy, vaultId);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\n        _setStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice set strategy cap amount\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function _setStrategyCap(uint256 _capAmount) internal {\\n        strategyCap = _capAmount;\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external afterInitialization {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     * @param _poolFee Uniswap pool fee\\n     */\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _poolFee,\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\n     * @param _poolFee Uniswap pool fee\\n\\n     */\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _poolFee,\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"C12\\\");\\n        require(hasRedeemedInShutdown, \\\"C13\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice set nonce to true\\n     * @param _nonce the number to be set true\\n     */\\n    function setNonceTrue(uint256 _nonce) external {\\n        nonces[msg.sender][_nonce] = true;\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"C14\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\n     */\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\n        // Tolerance cannot be more than 20%\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\"C15\\\");\\n\\n        otcPriceTolerance = _otcPriceTolerance;\\n\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"C16\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            // will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            // return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\n\\n            // excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @dev set nonce flag of the trader to true\\n     * @param _trader address of the signer\\n     * @param _nonce number that is to be traded only once\\n     */\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\n        require(!nonces[_trader][_nonce], \\\"C27\\\");\\n        nonces[_trader][_nonce] = true;\\n    }\\n\\n    /**\\n     * @dev view function to get the domain seperator used in signing\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev check the signer and swap tokens in the order\\n     * @param _remainingAmount quantity the manager wants to trade\\n     * @param _clearingPrice the price at which all orders are traded\\n     * @param _order a signed order to swap tokens\\n     */\\n    function _execOrder(\\n        uint256 _remainingAmount,\\n        uint256 _clearingPrice,\\n        Order memory _order\\n    ) internal {\\n        // check that order beats clearing price\\n        if (_order.isBuying) {\\n            require(_clearingPrice <= _order.price, \\\"C17\\\");\\n        } else {\\n            require(_clearingPrice >= _order.price, \\\"C18\\\");\\n        }\\n\\n        _useNonce(_order.trader, _order.nonce);\\n        bytes32 structHash = keccak256(\\n            abi.encode(\\n                _CRAB_BALANCE_TYPEHASH,\\n                _order.bidId,\\n                _order.trader,\\n                _order.quantity,\\n                _order.price,\\n                _order.isBuying,\\n                _order.expiry,\\n                _order.nonce\\n            )\\n        );\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\n        require(offerSigner == _order.trader, \\\"C19\\\");\\n        require(_order.expiry >= block.timestamp, \\\"C20\\\");\\n\\n        // adjust quantity for partial fills\\n        if (_remainingAmount < _order.quantity) {\\n            _order.quantity = _remainingAmount;\\n        }\\n        // weth clearing price for the order\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\n\\n        if (_order.isBuying) {\\n            // trader sends weth and receives oSQTH\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\n            IWETH9(weth).withdraw(wethAmount);\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n        } else {\\n            // trader sends oSQTH and receives weth\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n            // wrap it\\n            IWETH9(weth).deposit{value: wethAmount}();\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\n        }\\n\\n        emit HedgeOTCSingle(\\n            _order.trader, // market maker\\n            _order.bidId,\\n            _order.quantity, // order oSQTH quantity\\n            _order.price, // order price\\n            _order.isBuying, // order direction\\n            _clearingPrice // executed price for order\\n        );\\n    }\\n\\n    /**\\n     * @dev hedge function to reduce delta using an array of signed orders\\n     * @param _totalQuantity quantity the manager wants to trade\\n     * @param _clearingPrice clearing price in weth\\n     * @param _isHedgeBuying direction of hedge trade\\n     * @param _orders an array of signed order to swap tokens\\n     */\\n    function hedgeOTC(\\n        uint256 _totalQuantity,\\n        uint256 _clearingPrice,\\n        bool _isHedgeBuying,\\n        Order[] memory _orders\\n    ) external onlyOwner afterInitialization {\\n        require(_clearingPrice > 0, \\\"C21\\\");\\n        require(_isTimeHedge() || _isPriceHedge(), \\\"C22\\\");\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = _clearingPrice;\\n\\n        uint256 remainingAmount = _totalQuantity;\\n        uint256 prevPrice = _orders[0].price;\\n        uint256 currentPrice = _orders[0].price;\\n        bool isOrderBuying = _orders[0].isBuying;\\n        require(_isHedgeBuying != isOrderBuying, \\\"C23\\\");\\n\\n        // iterate through order array and execute if valid\\n        for (uint256 i; i < _orders.length; ++i) {\\n            currentPrice = _orders[i].price;\\n            require(_orders[i].isBuying == isOrderBuying, \\\"C24\\\");\\n            if (_isHedgeBuying) {\\n                require(currentPrice >= prevPrice, \\\"C25\\\");\\n            } else {\\n                require(currentPrice <= prevPrice, \\\"C25\\\");\\n            }\\n            prevPrice = currentPrice;\\n\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\n\\n            if (remainingAmount > _orders[i].quantity) {\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\n            } else {\\n                break;\\n            }\\n        }\\n\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\n    }\\n\\n    /**\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\n     * @param _price clearing price provided by manager\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\n     */\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\n        // Get twap\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n\\n        if (_isHedgeBuying) {\\n            require(\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\n                \\\"Price too high relative to Uniswap twap.\\\"\\n            );\\n        } else {\\n            require(\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\n                \\\"Price too low relative to Uniswap twap.\\\"\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\n        require(!isShutdown, \\\"C26\\\");\\n\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n        );\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     */\\n    function _isTimeHedge() internal view returns (bool) {\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge() internal view returns (bool) {\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge() external view returns (bool) {\\n        return _isPriceHedge();\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkTimeHedge() external view returns (bool) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/drafts/EIP712.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = _getChainId();\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n        return keccak256(\\n            abi.encode(\\n                typeHash,\\n                name,\\n                version,\\n                _getChainId(),\\n                address(this)\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/cryptography/ECDSA.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        // Check the signature length\\n        if (signature.length != 65) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        }\\n\\n        // Divide the signature in r, s and v variables\\n        bytes32 r;\\n        bytes32 s;\\n        uint8 v;\\n\\n        // ecrecover takes the signature parameters, and the only way to get them\\n        // currently is to use assembly.\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            r := mload(add(signature, 0x20))\\n            s := mload(add(signature, 0x40))\\n            v := byte(0, mload(add(signature, 0x60)))\\n        }\\n\\n        return recover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n        require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n        return signer;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * replicates the behavior of the\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n     * JSON-RPC method.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\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) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/strategy/CrabHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {ICrabStrategyV2} from \\\"../interfaces/ICrabStrategyV2.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {StrategySwap} from \\\"./helper/StrategySwap.sol\\\";\\n\\n/**\\n * @dev CrabHelper contract\\n * @notice Contract for Crab helper functions\\n * @author Opyn team\\n */\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\n    using Address for address payable;\\n\\n    address public immutable crab;\\n    address public immutable weth;\\n\\n    event FlashDepositERC20(\\n        address indexed depositor,\\n        address depositedERC20,\\n        uint256 depositedAmount,\\n        uint256 depositedEthAmount,\\n        uint256 crabAmount,\\n        uint256 returnedEth\\n    );\\n\\n    event FlashWithdrawERC20(\\n        address indexed withdrawer,\\n        address withdrawnERC20,\\n        uint256 withdrawnAmount,\\n        uint256 withdrawnEthAmount,\\n        uint256 crabAmount\\n    );\\n\\n    /**\\n     * @notice constructor\\n     * @param _crab address of crabV2 contract\\n     * @param _swapRouter address of Uniswap swap router\\n     */\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\n        require(_crab != address(0), \\\"Invalid crab address\\\");\\n\\n        crab = _crab;\\n        weth = ICrabStrategyV2(_crab).weth();\\n    }\\n\\n    /**\\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\\n     * @param _ethToDeposit amount of ETH to deposit\\n     * @param _amountIn amount of ERC20 token to swap for weth\\n     * @param _minEthToGet min amount of ETH to receive in the swap\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     * @param _tokenIn ERC20 token to pay\\n     */\\n    function flashDepositERC20(\\n        uint256 _ethToDeposit,\\n        uint256 _amountIn,\\n        uint256 _minEthToGet,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee,\\n        address _tokenIn\\n    ) external nonReentrant {\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\\n\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\\n\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\n\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\n\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\n\\n        if (address(this).balance > 0) {\\n            payable(msg.sender).sendValue(address(this).balance);\\n        }\\n    }\\n\\n    /**\\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\\n     * @param _crabAmount amount of crab shares to withdraw\\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\\n     * @param _tokenOut ERC20 token to receive\\n     * @param _minAmountOut min amount of ERC20 to receive\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     */\\n    function flashWithdrawERC20(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        address _tokenOut,\\n        uint256 _minAmountOut,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee\\n    ) external nonReentrant {\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\n\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\\n\\n        uint256 ethBalance = address(this).balance;\\n        IWETH9(weth).deposit{value: ethBalance}();\\n        uint256 tokenReceived = _swapExactInputSingle(\\n            weth,\\n            _tokenOut,\\n            address(this),\\n            msg.sender,\\n            ethBalance,\\n            _minAmountOut,\\n            _erc20Fee\\n        );\\n\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crab, \\\"Cannot receive eth\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/ICrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\ninterface ICrabStrategyV2 {\\n    function wPowerPerp() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\\n\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/strategy/helper/StrategySwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract StrategySwap {\\n    ISwapRouter public immutable swapRouter;\\n\\n    constructor(address _swapRouter) {\\n        require(_swapRouter != address(0), \\\"invalid swap router address\\\");\\n        swapRouter = ISwapRouter(_swapRouter);\\n    }\\n\\n    /**\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _from from which user we are selling\\n     * @param _to Recipient to get the tokens\\n     * @param _amountIn Exact amount to sell\\n     * @param _minAmountOut Minimum amount to be paid\\n     * @param _fee pool fee\\n     * @return amountOut The amount of WETH9 received.\\n     */\\n    function _swapExactInputSingle(\\n        address _tokenIn,\\n        address _tokenOut,\\n        address _from,\\n        address _to,\\n        uint256 _amountIn,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) internal returns (uint256 amountOut) {\\n        // _from must approve this contract\\n\\n        // Transfer the specified amount of tokenIn to this contract.\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\n\\n        // Approve the router to spend tokenIn.\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\n\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\n            tokenIn: _tokenIn,\\n            tokenOut: _tokenOut,\\n            fee: _fee,\\n            recipient: _to,\\n            deadline: block.timestamp,\\n            amountIn: _amountIn,\\n            amountOutMinimum: _minAmountOut,\\n            sqrtPriceLimitX96: 0\\n        });\\n\\n        // The call to `exactInputSingle` executes the swap.\\n        amountOut = swapRouter.exactInputSingle(params);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabMigration.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport {IEulerExec, IDToken} from \\\"../interfaces/IEuler.sol\\\";\\nimport {WETH9} from \\\"../external/WETH9.sol\\\";\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// contract\\nimport {CrabStrategyV2} from \\\"./CrabStrategyV2.sol\\\";\\nimport {CrabStrategy} from \\\"./CrabStrategy.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * Migration Error Codes:\\n * M1: Migration already happened\\n * M2: Migration has not yet happened\\n * M3: msg.sender is not Euler Mainnet Contract\\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\\n * M5: Can't withdraw more than you own\\n * M6: Not enough ETH to repay the loan\\n * M7: Invalid crabV2 address\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\n * M10: Wrong migration function, use flashMigrateFromV1toV2\\n * M11: crabV2 address not yet set\\n */\\n\\n/**\\n * @dev CrabMigration contract\\n * @notice Contract for Migrating from Crab V1 to Crab V2\\n * @author Opyn team\\n */\\ncontract CrabMigration is Ownable {\\n    using SafeERC20 for IERC20;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    mapping(address => uint256) public sharesDeposited;\\n    bool public isMigrated;\\n\\n    address payable public crabV1;\\n    address payable public crabV2;\\n    address public immutable euler;\\n    address public immutable weth;\\n\\n    address immutable EULER_MAINNET;\\n    address immutable dToken;\\n    address immutable wPowerPerp;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    struct BatchMigrate {\\n        uint256 strategyCap;\\n    }\\n\\n    struct FlashMigrateV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFee;\\n    }\\n\\n    struct FlashMigrateAndBuyV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 withdrawMaxEthToPay;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFeeFlashDeposit;\\n    }\\n\\n    enum FLASH_SOURCE {\\n        BATCH_MIGRATE,\\n        FLASH_MIGRATE_V1_TO_V2,\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\n    }\\n\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\\n\\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\\n\\n    modifier beforeMigration() {\\n        require(!isMigrated, \\\"M1\\\");\\n        _;\\n    }\\n\\n    modifier afterMigration() {\\n        require(isMigrated, \\\"M2\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialized() {\\n        require(crabV2 != address(0), \\\"M11\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice migration constructor\\n     * @param _crabV1 address of crab V1\\n     * @param _weth address of weth\\n     * @param _eulerExec address of euler exec contract\\n     * @param _dToken address of euler liability token\\n     * @param _eulerMainnet address of euler deployment on mainnet\\n     */\\n    constructor(\\n        address payable _crabV1,\\n        address _weth,\\n        address _eulerExec,\\n        address _dToken,\\n        address _eulerMainnet\\n    ) {\\n        require(_eulerExec != address(0), \\\"invalid _eulerExec address\\\");\\n        require(_dToken != address(0), \\\"invalid _dToken address\\\");\\n        require(_eulerMainnet != address(0), \\\"invalid _eulerMainnet address\\\");\\n        require(_weth != address(0), \\\"invalid _weth address\\\");\\n        require(_crabV1 != address(0), \\\"invalid _crabv1 address\\\");\\n        require(IDToken(_dToken).underlyingAsset() == _weth, \\\"dToken underlying asset should be weth\\\");\\n\\n        crabV1 = _crabV1;\\n        euler = _eulerExec;\\n        EULER_MAINNET = _eulerMainnet;\\n        weth = _weth;\\n        dToken = _dToken;\\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\\n    }\\n\\n    /**\\n     * @notice set the crabV2 address\\n     * @param _crabV2 address of crab V2\\n     */\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\n        require(_crabV2 != address(0), \\\"M7\\\");\\n        crabV2 = _crabV2;\\n    }\\n\\n    /**\\n     * @notice deposit crab V1 shares in the pool for migration\\n     * @param _amount amount of crabV1 shares to deposit\\n     */\\n    function depositV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] += _amount;\\n\\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\\n\\n        emit DepositV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice withdraw crab V1 shares in the pool before migration\\n     * @param _amount amount of V1 shares to withdraw\\n     */\\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\\n\\n        emit WithdrawV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\\n     * the V2 contract at the same collateral ratio as the V1 contract\\n     * @param _strategyCap strategy cap in ETH\\n     */\\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\\n        // 1. update isMigrated\\n        isMigrated = true;\\n\\n        // 2. flash floan eth from euler eq to amt\\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: amountEthToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Euler callback function\\n     * @param encodedData callback data\\n     */\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\n        require(msg.sender == EULER_MAINNET, \\\"M3\\\");\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        // 1. borrow weth\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\n        WETH9(weth).withdraw(data.amountToBorrow);\\n\\n        // 2. callback\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\n\\n        // 3. repay the weth\\n        WETH9(weth).deposit{value: data.amountToBorrow}();\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     * @notice callback function for flash actions\\n     * @param _initiator address of original function caller\\n     * @param _amount  amount to pay back for flashswap\\n     * @param _callSource identifier for which function triggered callback\\n     * @param _calldata arbitrary data attached to callback\\n\\n     */\\n    function _flashCallback(\\n        address _initiator,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\\n\\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n\\n            // 2. mint osqth in crab V2\\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\\n                wSqueethToMint,\\n                crabV1Balance,\\n                timeAtLastHedge,\\n                priceAtLastHedge,\\n                data.strategyCap\\n            );\\n\\n            // 3. call withdraw from crab V1\\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\n\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n\\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\\n\\n            // flash deposit remaining ETH, otherwise refund\\n            // if CR1 = CR2 ethToFlashDeposit should be 0\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFee\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n            // send back V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\\n\\n            // find crab amount for contract's sqth balance\\n            // remaining crab can be withdrawn using flash withdraw\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\n\\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\\n\\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\n            require(address(this).balance >= _amount, \\\"M6\\\");\\n\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFeeFlashDeposit\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n\\n            // send V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back the excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares\\n     */\\n    function claimV2Shares() external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        sharesDeposited[msg.sender] = 0;\\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares and flash withdraw from crab V2\\n     * @param _amountToWithdraw V2 shares to claim\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee Uniswap pool fee for flash withdraw\\n     */\\n    function claimAndWithdraw(\\n        uint256 _amountToWithdraw,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        require(_amountToWithdraw <= amountV1Deposited, \\\"M5\\\");\\n\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\\n\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\n\\n        // send eth to user\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice view details of flash migration for specified amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function flashMigrationDetails(uint256 _v1Shares)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return _flashMigrationDetails(_v1Shares);\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\n     * @param _poolFee uniswap pool fee for flash deposit\\n     */\\n    function flashMigrateFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(isFlashOnlyMigrate, \\\"M9\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: ethNeededForV2,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateV1toV2({\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFee: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\\n     */\\n    function flashMigrateAndWithdrawFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint256 _ethToBorrow,\\n        uint256 _withdrawMaxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(!isFlashOnlyMigrate, \\\"M10\\\");\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\"M8\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: _ethToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateAndBuyV1toV2({\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFeeFlashDeposit: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice get migration details for given amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function _flashMigrationDetails(uint256 _v1Shares)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\\n\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\\n\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \\\"M4\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IEuler.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\ninterface IEulerExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IDToken {\\n    function underlyingAsset() external view returns (address);\\n\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\"\n    },\n    \"contracts/external/WETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\n\\ncontract WETH9 {\\n    string public name = \\\"Wrapped Ether\\\";\\n    string public symbol = \\\"WETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        payable(msg.sender).transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract MockErc20 is ERC20, Ownable {\\n\\n    /// @dev mapping to track whitelisted minters\\n    mapping(address => bool) internal whitelistedMinters;\\n    \\n    /// @notice emits an event when a minter is whitelisted \\n    event MinterWhitelisted(address indexed account );\\n\\n    /// @notice emits an event when a minter is blacklisted \\n    event MinterBlacklisted(address indexed account);\\n    \\n\\n    /**\\n     * @notice check if the sender is whitelistd\\n     */\\n    modifier onlyWhitelisted() {\\n        require(\\n            whitelistedMinters[msg.sender],\\n            \\\"Address not a whitelisted minter\\\"\\n        );\\n        _;\\n    }\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external onlyWhitelisted {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice check if a minter is whitelisted\\n     * @param _account address of minter\\n     * @return boolean, True if address is a whitelisted minter\\n     */\\n    function isWhitelistedMinter(address _account) external view returns (bool) {\\n        return whitelistedMinters[_account];\\n    }\\n\\n    /**\\n     * @notice allows the minter to whitelist other minters\\n     * @param _account address of minter to be whitelisted\\n     */\\n    function whitelistMinter(address _account) external onlyOwner onlyWhitelisted {\\n        whitelistedMinters[_account] = true;\\n\\n        emit MinterWhitelisted(_account);\\n    }\\n\\n    /**\\n     * @notice allow the minter to blacklist other minters\\n     * @param _account address of minter to be blacklisted\\n     */\\n    function blacklistMinter(address _account) external onlyOwner onlyWhitelisted {\\n        whitelistedMinters[_account] = false;\\n\\n        emit MinterBlacklisted(_account);\\n    }\\n\\n\\n  \\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockEulerDToken.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockEulerDToken {\\n    ERC20 weth;\\n\\n    constructor(address _weth) {\\n        weth = ERC20(_weth);\\n    }\\n\\n    function borrow(uint256, uint256 amount) external {\\n        weth.transfer(msg.sender, amount);\\n    }\\n\\n    function repay(uint256, uint256 amount) external {\\n        weth.transferFrom(msg.sender, address(this), amount);\\n    }\\n\\n    function underlyingAsset() external view returns (address) {\\n        return address(weth);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockCrab.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockCrab is ERC20 {\\n    address operator;\\n    uint256 vaultId;\\n    uint256 collateral;\\n    uint256 short;\\n    address public wPowerPerp;\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    function setVaultDetails(\\n        uint256 _vaultId,\\n        uint256 _collateral,\\n        uint256 _short\\n    ) external {\\n        vaultId = _vaultId;\\n        collateral = _collateral;\\n        short = _short;\\n    }\\n\\n    function getVaultDetails()\\n        external\\n        view\\n        returns (\\n            address,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return (operator, vaultId, collateral, short);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"C3\\\");\\n\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/solcInputs/05b9c7d057ff8b2bf36168b053759720.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // Ceil A to a multiple m\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(sub(add(a, m), 1), m), m);\\n    }\\n\\n    // Floor A to a multiple m\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(a, m), m);\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {EIP712} from \\\"@openzeppelin/contracts/drafts/EIP712.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\nimport {ECDSA} from \\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * Crab V2 Error Codes:\\n * C1: Caller is not timelock\\n * C2: Contract not yet initialized\\n * C3: Invalid oracle address\\n * C4: Invalid timelock address\\n * C5: Invalid ETH:WSqueeth address\\n * C6: Invalid crabMigration address\\n * C7: Invalid hedge time threshold\\n * C8: Invalid hedge price threshold\\n * C9: Cannot receive ETH\\n * C10: Caller not Crab Migration contract\\n * C11: Crab V2 already initialized\\n * C12: Squeeth contracts not shut down\\n * C13: Crab must redeemShortShutdown\\n * C14: Twap period is too short\\n * C15: Price tolerance is too high\\n * C16: Deposit exceeds strategy cap\\n * C17: Clearing Price should be below bid price\\n * C18: Clearing Price should be above offer price\\n * C19: Invalid offer signature\\n * C20: Order has expired\\n * C21: Manager Price should be greater than 0\\n * C22: Not a valid Time or Price hedge\\n * C23: Orders must take the opposite side of the hedge\\n * C24: All orders must be either buying or selling\\n * C25: Orders are not arranged properly\\n * C26: Crab contracts shut down\\n *  C27: Nonce already used.\\n */\\n\\n/**\\n * @dev CrabStrategyV2 contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    // @dev OTC price must be within this distance of the uniswap twap price\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\n\\n    // @dev OTC price tolerance cannot exceed 20%\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\n\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n    /// @dev true if CrabV2 was initialized\\n    bool public isInitialized;\\n\\n    /// @dev typehash for signed orders\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\n        keccak256(\\n            \\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\"\\n        );\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:wSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable timelock;\\n    address public immutable crabMigration;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev wSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    /// @dev store the used flag for a nonce for each address\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct Order {\\n        uint256 bidId;\\n        address trader;\\n        uint256 quantity;\\n        uint256 price;\\n        bool isBuying;\\n        uint256 expiry;\\n        uint256 nonce;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event HedgeOTCSingle(\\n        address trader,\\n        uint256 bidId,\\n        uint256 quantity,\\n        uint256 price,\\n        bool isBuying,\\n        uint256 clearingPrice\\n    );\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\n\\n    modifier onlyTimelock() {\\n        require(msg.sender == timelock, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialization() {\\n        require(isInitialized, \\\"C2\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _timelock timelock contract address\\n     * @param _crabMigration crab migration contract address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        address _timelock,\\n        address _crabMigration,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold\\n    )\\n        StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy v2\\\", \\\"Crabv2\\\")\\n        StrategyFlashSwap(_uniswapFactory)\\n        EIP712(\\\"CrabOTC\\\", \\\"2\\\")\\n    {\\n        require(_oracle != address(0), \\\"C3\\\");\\n        require(_timelock != address(0), \\\"C4\\\");\\n        require(_ethWSqueethPool != address(0), \\\"C5\\\");\\n        require(_crabMigration != address(0), \\\"C6\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        timelock = _timelock;\\n        crabMigration = _crabMigration;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"C9\\\");\\n    }\\n\\n    /**\\n     * @notice initializes the collateral ratio after the first migration\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\n     * @param _crabSharesToMint crab shares to mint\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\n     * @param _strategyCap strategy cap for crab V2\\n     */\\n    function initialize(\\n        uint256 _wSqueethToMint,\\n        uint256 _crabSharesToMint,\\n        uint256 _timeAtLastHedge,\\n        uint256 _priceAtLastHedge,\\n        uint256 _strategyCap\\n    ) external payable {\\n        require(msg.sender == crabMigration, \\\"C10\\\");\\n        require(!isInitialized, \\\"C11\\\");\\n\\n        _setStrategyCap(_strategyCap);\\n\\n        uint256 amount = msg.value;\\n\\n        _checkStrategyCap(amount, 0);\\n\\n        // store hedge data from crab V1\\n        timeAtLastHedge = _timeAtLastHedge;\\n        priceAtLastHedge = _priceAtLastHedge;\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\n\\n        isInitialized = true;\\n    }\\n\\n    /**\\n     * @notice transfer vault NFT to new contract\\n     * @dev strategy cap is set to 0 to avoid future deposits\\n     * @param _newStrategy new strategy contract address\\n     */\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\n        _setStrategyCap(0);\\n\\n        emit VaultTransferred(_newStrategy, vaultId);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\n        _setStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice set strategy cap amount\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function _setStrategyCap(uint256 _capAmount) internal {\\n        strategyCap = _capAmount;\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external afterInitialization {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     * @param _poolFee Uniswap pool fee\\n     */\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _poolFee,\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\n     * @param _poolFee Uniswap pool fee\\n\\n     */\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _poolFee,\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"C12\\\");\\n        require(hasRedeemedInShutdown, \\\"C13\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice set nonce to true\\n     * @param _nonce the number to be set true\\n     */\\n    function setNonceTrue(uint256 _nonce) external {\\n        nonces[msg.sender][_nonce] = true;\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"C14\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\n     */\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\n        // Tolerance cannot be more than 20%\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\"C15\\\");\\n\\n        otcPriceTolerance = _otcPriceTolerance;\\n\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"C16\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            // will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            // return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\n\\n            // excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @dev set nonce flag of the trader to true\\n     * @param _trader address of the signer\\n     * @param _nonce number that is to be traded only once\\n     */\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\n        require(!nonces[_trader][_nonce], \\\"C27\\\");\\n        nonces[_trader][_nonce] = true;\\n    }\\n\\n    /**\\n     * @dev view function to get the domain seperator used in signing\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev check the signer and swap tokens in the order\\n     * @param _remainingAmount quantity the manager wants to trade\\n     * @param _clearingPrice the price at which all orders are traded\\n     * @param _order a signed order to swap tokens\\n     */\\n    function _execOrder(\\n        uint256 _remainingAmount,\\n        uint256 _clearingPrice,\\n        Order memory _order\\n    ) internal {\\n        // check that order beats clearing price\\n        if (_order.isBuying) {\\n            require(_clearingPrice <= _order.price, \\\"C17\\\");\\n        } else {\\n            require(_clearingPrice >= _order.price, \\\"C18\\\");\\n        }\\n\\n        _useNonce(_order.trader, _order.nonce);\\n        bytes32 structHash = keccak256(\\n            abi.encode(\\n                _CRAB_BALANCE_TYPEHASH,\\n                _order.bidId,\\n                _order.trader,\\n                _order.quantity,\\n                _order.price,\\n                _order.isBuying,\\n                _order.expiry,\\n                _order.nonce\\n            )\\n        );\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\n        require(offerSigner == _order.trader, \\\"C19\\\");\\n        require(_order.expiry >= block.timestamp, \\\"C20\\\");\\n\\n        // adjust quantity for partial fills\\n        if (_remainingAmount < _order.quantity) {\\n            _order.quantity = _remainingAmount;\\n        }\\n        // weth clearing price for the order\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\n\\n        if (_order.isBuying) {\\n            // trader sends weth and receives oSQTH\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\n            IWETH9(weth).withdraw(wethAmount);\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n        } else {\\n            // trader sends oSQTH and receives weth\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n            // wrap it\\n            IWETH9(weth).deposit{value: wethAmount}();\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\n        }\\n\\n        emit HedgeOTCSingle(\\n            _order.trader, // market maker\\n            _order.bidId,\\n            _order.quantity, // order oSQTH quantity\\n            _order.price, // order price\\n            _order.isBuying, // order direction\\n            _clearingPrice // executed price for order\\n        );\\n    }\\n\\n    /**\\n     * @dev hedge function to reduce delta using an array of signed orders\\n     * @param _totalQuantity quantity the manager wants to trade\\n     * @param _clearingPrice clearing price in weth\\n     * @param _isHedgeBuying direction of hedge trade\\n     * @param _orders an array of signed order to swap tokens\\n     */\\n    function hedgeOTC(\\n        uint256 _totalQuantity,\\n        uint256 _clearingPrice,\\n        bool _isHedgeBuying,\\n        Order[] memory _orders\\n    ) external onlyOwner afterInitialization {\\n        require(_clearingPrice > 0, \\\"C21\\\");\\n        require(_isTimeHedge() || _isPriceHedge(), \\\"C22\\\");\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = _clearingPrice;\\n\\n        uint256 remainingAmount = _totalQuantity;\\n        uint256 prevPrice = _orders[0].price;\\n        uint256 currentPrice = _orders[0].price;\\n        bool isOrderBuying = _orders[0].isBuying;\\n        require(_isHedgeBuying != isOrderBuying, \\\"C23\\\");\\n\\n        // iterate through order array and execute if valid\\n        for (uint256 i; i < _orders.length; ++i) {\\n            currentPrice = _orders[i].price;\\n            require(_orders[i].isBuying == isOrderBuying, \\\"C24\\\");\\n            if (_isHedgeBuying) {\\n                require(currentPrice >= prevPrice, \\\"C25\\\");\\n            } else {\\n                require(currentPrice <= prevPrice, \\\"C25\\\");\\n            }\\n            prevPrice = currentPrice;\\n\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\n\\n            if (remainingAmount > _orders[i].quantity) {\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\n            } else {\\n                break;\\n            }\\n        }\\n\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\n    }\\n\\n    /**\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\n     * @param _price clearing price provided by manager\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\n     */\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\n        // Get twap\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n\\n        if (_isHedgeBuying) {\\n            require(\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\n                \\\"Price too high relative to Uniswap twap.\\\"\\n            );\\n        } else {\\n            require(\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\n                \\\"Price too low relative to Uniswap twap.\\\"\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\n        require(!isShutdown, \\\"C26\\\");\\n\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n        );\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     */\\n    function _isTimeHedge() internal view returns (bool) {\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge() internal view returns (bool) {\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge() external view returns (bool) {\\n        return _isPriceHedge();\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkTimeHedge() external view returns (bool) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/drafts/EIP712.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = _getChainId();\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n        return keccak256(\\n            abi.encode(\\n                typeHash,\\n                name,\\n                version,\\n                _getChainId(),\\n                address(this)\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/cryptography/ECDSA.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        // Check the signature length\\n        if (signature.length != 65) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        }\\n\\n        // Divide the signature in r, s and v variables\\n        bytes32 r;\\n        bytes32 s;\\n        uint8 v;\\n\\n        // ecrecover takes the signature parameters, and the only way to get them\\n        // currently is to use assembly.\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            r := mload(add(signature, 0x20))\\n            s := mload(add(signature, 0x40))\\n            v := byte(0, mload(add(signature, 0x60)))\\n        }\\n\\n        return recover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n        require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n        return signer;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * replicates the behavior of the\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n     * JSON-RPC method.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\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) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/strategy/CrabHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {ICrabStrategyV2} from \\\"../interfaces/ICrabStrategyV2.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {StrategySwap} from \\\"./helper/StrategySwap.sol\\\";\\n\\n/**\\n * @dev CrabHelper contract\\n * @notice Contract for Crab helper functions\\n * @author Opyn team\\n */\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\n    using Address for address payable;\\n\\n    address public immutable crab;\\n    address public immutable weth;\\n\\n    event FlashDepositERC20(\\n        address indexed depositor,\\n        address depositedERC20,\\n        uint256 depositedAmount,\\n        uint256 depositedEthAmount,\\n        uint256 crabAmount,\\n        uint256 returnedEth\\n    );\\n\\n    event FlashWithdrawERC20(\\n        address indexed withdrawer,\\n        address withdrawnERC20,\\n        uint256 withdrawnAmount,\\n        uint256 withdrawnEthAmount,\\n        uint256 crabAmount\\n    );\\n\\n    /**\\n     * @notice constructor\\n     * @param _crab address of crabV2 contract\\n     * @param _swapRouter address of Uniswap swap router\\n     */\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\n        require(_crab != address(0), \\\"Invalid crab address\\\");\\n\\n        crab = _crab;\\n        weth = ICrabStrategyV2(_crab).weth();\\n    }\\n\\n    /**\\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\\n     * @param _ethToDeposit amount of ETH to deposit\\n     * @param _amountIn amount of ERC20 token to swap for weth\\n     * @param _minEthToGet min amount of ETH to receive in the swap\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     * @param _tokenIn ERC20 token to pay\\n     */\\n    function flashDepositERC20(\\n        uint256 _ethToDeposit,\\n        uint256 _amountIn,\\n        uint256 _minEthToGet,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee,\\n        address _tokenIn\\n    ) external nonReentrant {\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\\n\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\\n\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\n\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\n\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\n\\n        if (address(this).balance > 0) {\\n            payable(msg.sender).sendValue(address(this).balance);\\n        }\\n    }\\n\\n    /**\\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\\n     * @param _crabAmount amount of crab shares to withdraw\\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\\n     * @param _tokenOut ERC20 token to receive\\n     * @param _minAmountOut min amount of ERC20 to receive\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     */\\n    function flashWithdrawERC20(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        address _tokenOut,\\n        uint256 _minAmountOut,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee\\n    ) external nonReentrant {\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\n\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\\n\\n        uint256 ethBalance = address(this).balance;\\n        IWETH9(weth).deposit{value: ethBalance}();\\n        uint256 tokenReceived = _swapExactInputSingle(\\n            weth,\\n            _tokenOut,\\n            address(this),\\n            msg.sender,\\n            ethBalance,\\n            _minAmountOut,\\n            _erc20Fee\\n        );\\n\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crab, \\\"Cannot receive eth\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/ICrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\ninterface ICrabStrategyV2 {\\n    function wPowerPerp() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\\n\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/strategy/helper/StrategySwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract StrategySwap {\\n    ISwapRouter public immutable swapRouter;\\n\\n    constructor(address _swapRouter) {\\n        require(_swapRouter != address(0), \\\"invalid swap router address\\\");\\n        swapRouter = ISwapRouter(_swapRouter);\\n    }\\n\\n    /**\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _from from which user we are selling\\n     * @param _to Recipient to get the tokens\\n     * @param _amountIn Exact amount to sell\\n     * @param _minAmountOut Minimum amount to be paid\\n     * @param _fee pool fee\\n     * @return amountOut The amount of WETH9 received.\\n     */\\n    function _swapExactInputSingle(\\n        address _tokenIn,\\n        address _tokenOut,\\n        address _from,\\n        address _to,\\n        uint256 _amountIn,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) internal returns (uint256 amountOut) {\\n        // _from must approve this contract\\n\\n        // Transfer the specified amount of tokenIn to this contract.\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\n\\n        // Approve the router to spend tokenIn.\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\n\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\n            tokenIn: _tokenIn,\\n            tokenOut: _tokenOut,\\n            fee: _fee,\\n            recipient: _to,\\n            deadline: block.timestamp,\\n            amountIn: _amountIn,\\n            amountOutMinimum: _minAmountOut,\\n            sqrtPriceLimitX96: 0\\n        });\\n\\n        // The call to `exactInputSingle` executes the swap.\\n        amountOut = swapRouter.exactInputSingle(params);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabMigration.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport {IEulerExec, IDToken} from \\\"../interfaces/IEuler.sol\\\";\\nimport {WETH9} from \\\"../external/WETH9.sol\\\";\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// contract\\nimport {CrabStrategyV2} from \\\"./CrabStrategyV2.sol\\\";\\nimport {CrabStrategy} from \\\"./CrabStrategy.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * Migration Error Codes:\\n * M1: Migration already happened\\n * M2: Migration has not yet happened\\n * M3: msg.sender is not Euler Mainnet Contract\\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\\n * M5: Can't withdraw more than you own\\n * M6: Not enough ETH to repay the loan\\n * M7: Invalid crabV2 address\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\n * M10: Wrong migration function, use flashMigrateFromV1toV2\\n * M11: crabV2 address not yet set\\n */\\n\\n/**\\n * @dev CrabMigration contract\\n * @notice Contract for Migrating from Crab V1 to Crab V2\\n * @author Opyn team\\n */\\ncontract CrabMigration is Ownable {\\n    using SafeERC20 for IERC20;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    mapping(address => uint256) public sharesDeposited;\\n    bool public isMigrated;\\n\\n    address payable public crabV1;\\n    address payable public crabV2;\\n    address public immutable euler;\\n    address public immutable weth;\\n\\n    address immutable EULER_MAINNET;\\n    address immutable dToken;\\n    address immutable wPowerPerp;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    struct BatchMigrate {\\n        uint256 strategyCap;\\n    }\\n\\n    struct FlashMigrateV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFee;\\n    }\\n\\n    struct FlashMigrateAndBuyV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 withdrawMaxEthToPay;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFeeFlashDeposit;\\n    }\\n\\n    enum FLASH_SOURCE {\\n        BATCH_MIGRATE,\\n        FLASH_MIGRATE_V1_TO_V2,\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\n    }\\n\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\\n\\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\\n\\n    modifier beforeMigration() {\\n        require(!isMigrated, \\\"M1\\\");\\n        _;\\n    }\\n\\n    modifier afterMigration() {\\n        require(isMigrated, \\\"M2\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialized() {\\n        require(crabV2 != address(0), \\\"M11\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice migration constructor\\n     * @param _crabV1 address of crab V1\\n     * @param _weth address of weth\\n     * @param _eulerExec address of euler exec contract\\n     * @param _dToken address of euler liability token\\n     * @param _eulerMainnet address of euler deployment on mainnet\\n     */\\n    constructor(\\n        address payable _crabV1,\\n        address _weth,\\n        address _eulerExec,\\n        address _dToken,\\n        address _eulerMainnet\\n    ) {\\n        require(_eulerExec != address(0), \\\"invalid _eulerExec address\\\");\\n        require(_dToken != address(0), \\\"invalid _dToken address\\\");\\n        require(_eulerMainnet != address(0), \\\"invalid _eulerMainnet address\\\");\\n        require(_weth != address(0), \\\"invalid _weth address\\\");\\n        require(_crabV1 != address(0), \\\"invalid _crabv1 address\\\");\\n        require(IDToken(_dToken).underlyingAsset() == _weth, \\\"dToken underlying asset should be weth\\\");\\n\\n        crabV1 = _crabV1;\\n        euler = _eulerExec;\\n        EULER_MAINNET = _eulerMainnet;\\n        weth = _weth;\\n        dToken = _dToken;\\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\\n    }\\n\\n    /**\\n     * @notice set the crabV2 address\\n     * @param _crabV2 address of crab V2\\n     */\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\n        require(_crabV2 != address(0), \\\"M7\\\");\\n        crabV2 = _crabV2;\\n    }\\n\\n    /**\\n     * @notice deposit crab V1 shares in the pool for migration\\n     * @param _amount amount of crabV1 shares to deposit\\n     */\\n    function depositV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] += _amount;\\n\\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\\n\\n        emit DepositV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice withdraw crab V1 shares in the pool before migration\\n     * @param _amount amount of V1 shares to withdraw\\n     */\\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\\n\\n        emit WithdrawV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\\n     * the V2 contract at the same collateral ratio as the V1 contract\\n     * @param _strategyCap strategy cap in ETH\\n     */\\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\\n        // 1. update isMigrated\\n        isMigrated = true;\\n\\n        // 2. flash floan eth from euler eq to amt\\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: amountEthToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Euler callback function\\n     * @param encodedData callback data\\n     */\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\n        require(msg.sender == EULER_MAINNET, \\\"M3\\\");\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        // 1. borrow weth\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\n        WETH9(weth).withdraw(data.amountToBorrow);\\n\\n        // 2. callback\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\n\\n        // 3. repay the weth\\n        WETH9(weth).deposit{value: data.amountToBorrow}();\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     * @notice callback function for flash actions\\n     * @param _initiator address of original function caller\\n     * @param _amount  amount to pay back for flashswap\\n     * @param _callSource identifier for which function triggered callback\\n     * @param _calldata arbitrary data attached to callback\\n\\n     */\\n    function _flashCallback(\\n        address _initiator,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\\n\\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n\\n            // 2. mint osqth in crab V2\\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\\n                wSqueethToMint,\\n                crabV1Balance,\\n                timeAtLastHedge,\\n                priceAtLastHedge,\\n                data.strategyCap\\n            );\\n\\n            // 3. call withdraw from crab V1\\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\n\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n\\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\\n\\n            // flash deposit remaining ETH, otherwise refund\\n            // if CR1 = CR2 ethToFlashDeposit should be 0\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFee\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n            // send back V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\\n\\n            // find crab amount for contract's sqth balance\\n            // remaining crab can be withdrawn using flash withdraw\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\n\\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\\n\\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\n            require(address(this).balance >= _amount, \\\"M6\\\");\\n\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFeeFlashDeposit\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n\\n            // send V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back the excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares\\n     */\\n    function claimV2Shares() external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        sharesDeposited[msg.sender] = 0;\\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares and flash withdraw from crab V2\\n     * @param _amountToWithdraw V2 shares to claim\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee Uniswap pool fee for flash withdraw\\n     */\\n    function claimAndWithdraw(\\n        uint256 _amountToWithdraw,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        require(_amountToWithdraw <= amountV1Deposited, \\\"M5\\\");\\n\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\\n\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\n\\n        // send eth to user\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice view details of flash migration for specified amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function flashMigrationDetails(uint256 _v1Shares)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return _flashMigrationDetails(_v1Shares);\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\n     * @param _poolFee uniswap pool fee for flash deposit\\n     */\\n    function flashMigrateFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(isFlashOnlyMigrate, \\\"M9\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: ethNeededForV2,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateV1toV2({\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFee: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\\n     */\\n    function flashMigrateAndWithdrawFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint256 _ethToBorrow,\\n        uint256 _withdrawMaxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(!isFlashOnlyMigrate, \\\"M10\\\");\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\"M8\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: _ethToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateAndBuyV1toV2({\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFeeFlashDeposit: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice get migration details for given amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function _flashMigrationDetails(uint256 _v1Shares)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\\n\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\\n\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \\\"M4\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IEuler.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\ninterface IEulerExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IDToken {\\n    function underlyingAsset() external view returns (address);\\n\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\"\n    },\n    \"contracts/external/WETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\n\\ncontract WETH9 {\\n    string public name = \\\"Wrapped Ether\\\";\\n    string public symbol = \\\"WETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        payable(msg.sender).transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract MockErc20 is ERC20, Ownable {\\n\\n    /// @dev mapping to track whitelisted minters\\n    mapping(address => bool) internal whitelistedMinters;\\n    \\n    /// @notice emits an event when a minter is whitelisted \\n    event MinterWhitelisted(address indexed account );\\n\\n    /// @notice emits an event when a minter is blacklisted \\n    event MinterBlacklisted(address indexed account);\\n    \\n\\n    /**\\n     * @notice check if the sender is whitelistd\\n     */\\n    modifier onlyWhitelisted() {\\n        require(\\n            whitelistedMinters[msg.sender] || msg.sender == owner(),\\n            \\\"Address not a whitelisted minter\\\"\\n        );\\n        _;\\n    }\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external onlyWhitelisted {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external onlyWhitelisted {\\n        _burn(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice check if a minter is whitelisted\\n     * @param _account address of minter\\n     * @return boolean, True if address is a whitelisted minter\\n     */\\n    function isWhitelistedMinter(address _account) external view returns (bool) {\\n        return whitelistedMinters[_account];\\n    }\\n\\n    /**\\n     * @notice allows the minter to whitelist other minters\\n     * @param _account address of minter to be whitelisted\\n     */\\n    function whitelistMinter(address _account) external onlyWhitelisted {\\n        whitelistedMinters[_account] = true;\\n\\n        emit MinterWhitelisted(_account);\\n    }\\n\\n    /**\\n     * @notice allow the minter to blacklist other minters\\n     * @param _account address of minter to be blacklisted\\n     */\\n    function blacklistMinter(address _account) external onlyWhitelisted {\\n        whitelistedMinters[_account] = false;\\n\\n        emit MinterBlacklisted(_account);\\n    }\\n\\n\\n  \\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockEulerDToken.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockEulerDToken {\\n    ERC20 weth;\\n\\n    constructor(address _weth) {\\n        weth = ERC20(_weth);\\n    }\\n\\n    function borrow(uint256, uint256 amount) external {\\n        weth.transfer(msg.sender, amount);\\n    }\\n\\n    function repay(uint256, uint256 amount) external {\\n        weth.transferFrom(msg.sender, address(this), amount);\\n    }\\n\\n    function underlyingAsset() external view returns (address) {\\n        return address(weth);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockCrab.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockCrab is ERC20 {\\n    address operator;\\n    uint256 vaultId;\\n    uint256 collateral;\\n    uint256 short;\\n    address public wPowerPerp;\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    function setVaultDetails(\\n        uint256 _vaultId,\\n        uint256 _collateral,\\n        uint256 _short\\n    ) external {\\n        vaultId = _vaultId;\\n        collateral = _collateral;\\n        short = _short;\\n    }\\n\\n    function getVaultDetails()\\n        external\\n        view\\n        returns (\\n            address,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return (operator, vaultId, collateral, short);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"C3\\\");\\n\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/solcInputs/31d85619debc3954507258d16df1741b.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/mocks/OpynWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\ncontract OpynWETH9 {\\n    address owner;\\n\\n    string public name = \\\"Wrapped Opyn Ether\\\";\\n    string public symbol = \\\"OpynWETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n    event MinterWhitelisted(address indexed account);\\n    event MinterBlacklisted(address indexed account);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n    mapping(address => bool) internal whitelistedMinters;\\n   \\n   /**\\n     * @notice check if the sender is whitelistd\\n     */\\n    modifier onlyWhitelisted() {\\n        require(\\n            whitelistedMinters[msg.sender] || msg.sender == owner,\\n            \\\"Address not a whitelisted minter\\\"\\n        );\\n        _;\\n    }\\n\\n    constructor() {\\n        owner = msg.sender;\\n    }\\n\\n    receive() external payable {\\n        deposit();\\n    }\\n\\n    function mint(address _to, uint256 _amount) public onlyWhitelisted {\\n\\n        balanceOf[_to] += _amount;\\n        emit Deposit(_to, _amount);\\n    }\\n\\n    function burn(address _from, uint256 _amount) public onlyWhitelisted {\\n\\n        balanceOf[_from] -= _amount;\\n        emit Withdrawal(_from, _amount);\\n    }\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        msg.sender.transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n\\n    /**\\n     * @notice check if a minter is whitelisted\\n     * @param _account address of minter\\n     * @return boolean, True if address is a whitelisted minter\\n     */\\n    function isWhitelistedMinter(address _account) external view returns (bool) {\\n        return whitelistedMinters[_account];\\n    }\\n\\n    /**\\n     * @notice allows the minter to whitelist other minters\\n     * @param _account address of minter to be whitelisted\\n     */\\n    function whitelistMinter(address _account) external onlyWhitelisted {\\n        whitelistedMinters[_account] = true;\\n\\n        emit MinterWhitelisted(_account);\\n    }\\n\\n    /**\\n     * @notice allow the minter to blacklist other minters\\n     * @param _account address of minter to be blacklisted\\n     */\\n    function blacklistMinter(address _account) external onlyWhitelisted {\\n        whitelistedMinters[_account] = false;\\n\\n        emit MinterBlacklisted(_account);\\n    }\\n}\\n\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/solcInputs/59fefefa6d402a64e50de797130b653c.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // Ceil A to a multiple m\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(sub(add(a, m), 1), m), m);\\n    }\\n\\n    // Floor A to a multiple m\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(a, m), m);\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {EIP712} from \\\"@openzeppelin/contracts/drafts/EIP712.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\nimport {ECDSA} from \\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * Crab V2 Error Codes:\\n * C1: Caller is not timelock\\n * C2: Contract not yet initialized\\n * C3: Invalid oracle address\\n * C4: Invalid timelock address\\n * C5: Invalid ETH:WSqueeth address\\n * C6: Invalid crabMigration address\\n * C7: Invalid hedge time threshold\\n * C8: Invalid hedge price threshold\\n * C9: Cannot receive ETH\\n * C10: Caller not Crab Migration contract\\n * C11: Crab V2 already initialized\\n * C12: Squeeth contracts not shut down\\n * C13: Crab must redeemShortShutdown\\n * C14: Twap period is too short\\n * C15: Price tolerance is too high\\n * C16: Deposit exceeds strategy cap\\n * C17: Clearing Price should be below bid price\\n * C18: Clearing Price should be above offer price\\n * C19: Invalid offer signature\\n * C20: Order has expired\\n * C21: Manager Price should be greater than 0\\n * C22: Not a valid Time or Price hedge\\n * C23: Orders must take the opposite side of the hedge\\n * C24: All orders must be either buying or selling\\n * C25: Orders are not arranged properly\\n * C26: Crab contracts shut down\\n *  C27: Nonce already used.\\n */\\n\\n/**\\n * @dev CrabStrategyV2 contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    // @dev OTC price must be within this distance of the uniswap twap price\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\n\\n    // @dev OTC price tolerance cannot exceed 20%\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\n\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n    /// @dev true if CrabV2 was initialized\\n    bool public isInitialized;\\n\\n    /// @dev typehash for signed orders\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\n        keccak256(\\n            \\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\"\\n        );\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:wSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable timelock;\\n    address public immutable crabMigration;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev wSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    /// @dev store the used flag for a nonce for each address\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct Order {\\n        uint256 bidId;\\n        address trader;\\n        uint256 quantity;\\n        uint256 price;\\n        bool isBuying;\\n        uint256 expiry;\\n        uint256 nonce;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event HedgeOTCSingle(\\n        address trader,\\n        uint256 bidId,\\n        uint256 quantity,\\n        uint256 price,\\n        bool isBuying,\\n        uint256 clearingPrice\\n    );\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\n\\n    modifier onlyTimelock() {\\n        require(msg.sender == timelock, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialization() {\\n        require(isInitialized, \\\"C2\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _timelock timelock contract address\\n     * @param _crabMigration crab migration contract address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        address _timelock,\\n        address _crabMigration,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold\\n    )\\n        StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy v2\\\", \\\"Crabv2\\\")\\n        StrategyFlashSwap(_uniswapFactory)\\n        EIP712(\\\"CrabOTC\\\", \\\"2\\\")\\n    {\\n        require(_oracle != address(0), \\\"C3\\\");\\n        require(_timelock != address(0), \\\"C4\\\");\\n        require(_ethWSqueethPool != address(0), \\\"C5\\\");\\n        require(_crabMigration != address(0), \\\"C6\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        timelock = _timelock;\\n        crabMigration = _crabMigration;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"C9\\\");\\n    }\\n\\n    /**\\n     * @notice initializes the collateral ratio after the first migration\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\n     * @param _crabSharesToMint crab shares to mint\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\n     * @param _strategyCap strategy cap for crab V2\\n     */\\n    function initialize(\\n        uint256 _wSqueethToMint,\\n        uint256 _crabSharesToMint,\\n        uint256 _timeAtLastHedge,\\n        uint256 _priceAtLastHedge,\\n        uint256 _strategyCap\\n    ) external payable {\\n        require(msg.sender == crabMigration, \\\"C10\\\");\\n        require(!isInitialized, \\\"C11\\\");\\n\\n        _setStrategyCap(_strategyCap);\\n\\n        uint256 amount = msg.value;\\n\\n        _checkStrategyCap(amount, 0);\\n\\n        // store hedge data from crab V1\\n        timeAtLastHedge = _timeAtLastHedge;\\n        priceAtLastHedge = _priceAtLastHedge;\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\n\\n        isInitialized = true;\\n    }\\n\\n    /**\\n     * @notice transfer vault NFT to new contract\\n     * @dev strategy cap is set to 0 to avoid future deposits\\n     * @param _newStrategy new strategy contract address\\n     */\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\n        _setStrategyCap(0);\\n\\n        emit VaultTransferred(_newStrategy, vaultId);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\n        _setStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice set strategy cap amount\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function _setStrategyCap(uint256 _capAmount) internal {\\n        strategyCap = _capAmount;\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external afterInitialization {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     * @param _poolFee Uniswap pool fee\\n     */\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _poolFee,\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\n     * @param _poolFee Uniswap pool fee\\n\\n     */\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _poolFee,\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"C12\\\");\\n        require(hasRedeemedInShutdown, \\\"C13\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice set nonce to true\\n     * @param _nonce the number to be set true\\n     */\\n    function setNonceTrue(uint256 _nonce) external {\\n        nonces[msg.sender][_nonce] = true;\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"C14\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\n     */\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\n        // Tolerance cannot be more than 20%\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\"C15\\\");\\n\\n        otcPriceTolerance = _otcPriceTolerance;\\n\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"C16\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            // will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            // return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\n\\n            // excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @dev set nonce flag of the trader to true\\n     * @param _trader address of the signer\\n     * @param _nonce number that is to be traded only once\\n     */\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\n        require(!nonces[_trader][_nonce], \\\"C27\\\");\\n        nonces[_trader][_nonce] = true;\\n    }\\n\\n    /**\\n     * @dev view function to get the domain seperator used in signing\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev check the signer and swap tokens in the order\\n     * @param _remainingAmount quantity the manager wants to trade\\n     * @param _clearingPrice the price at which all orders are traded\\n     * @param _order a signed order to swap tokens\\n     */\\n    function _execOrder(\\n        uint256 _remainingAmount,\\n        uint256 _clearingPrice,\\n        Order memory _order\\n    ) internal {\\n        // check that order beats clearing price\\n        if (_order.isBuying) {\\n            require(_clearingPrice <= _order.price, \\\"C17\\\");\\n        } else {\\n            require(_clearingPrice >= _order.price, \\\"C18\\\");\\n        }\\n\\n        _useNonce(_order.trader, _order.nonce);\\n        bytes32 structHash = keccak256(\\n            abi.encode(\\n                _CRAB_BALANCE_TYPEHASH,\\n                _order.bidId,\\n                _order.trader,\\n                _order.quantity,\\n                _order.price,\\n                _order.isBuying,\\n                _order.expiry,\\n                _order.nonce\\n            )\\n        );\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\n        require(offerSigner == _order.trader, \\\"C19\\\");\\n        require(_order.expiry >= block.timestamp, \\\"C20\\\");\\n\\n        // adjust quantity for partial fills\\n        if (_remainingAmount < _order.quantity) {\\n            _order.quantity = _remainingAmount;\\n        }\\n        // weth clearing price for the order\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\n\\n        if (_order.isBuying) {\\n            // trader sends weth and receives oSQTH\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\n            IWETH9(weth).withdraw(wethAmount);\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n        } else {\\n            // trader sends oSQTH and receives weth\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n            // wrap it\\n            IWETH9(weth).deposit{value: wethAmount}();\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\n        }\\n\\n        emit HedgeOTCSingle(\\n            _order.trader, // market maker\\n            _order.bidId,\\n            _order.quantity, // order oSQTH quantity\\n            _order.price, // order price\\n            _order.isBuying, // order direction\\n            _clearingPrice // executed price for order\\n        );\\n    }\\n\\n    /**\\n     * @dev hedge function to reduce delta using an array of signed orders\\n     * @param _totalQuantity quantity the manager wants to trade\\n     * @param _clearingPrice clearing price in weth\\n     * @param _isHedgeBuying direction of hedge trade\\n     * @param _orders an array of signed order to swap tokens\\n     */\\n    function hedgeOTC(\\n        uint256 _totalQuantity,\\n        uint256 _clearingPrice,\\n        bool _isHedgeBuying,\\n        Order[] memory _orders\\n    ) external onlyOwner afterInitialization {\\n        require(_clearingPrice > 0, \\\"C21\\\");\\n        require(_isTimeHedge() || _isPriceHedge(), \\\"C22\\\");\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = _clearingPrice;\\n\\n        uint256 remainingAmount = _totalQuantity;\\n        uint256 prevPrice = _orders[0].price;\\n        uint256 currentPrice = _orders[0].price;\\n        bool isOrderBuying = _orders[0].isBuying;\\n        require(_isHedgeBuying != isOrderBuying, \\\"C23\\\");\\n\\n        // iterate through order array and execute if valid\\n        for (uint256 i; i < _orders.length; ++i) {\\n            currentPrice = _orders[i].price;\\n            require(_orders[i].isBuying == isOrderBuying, \\\"C24\\\");\\n            if (_isHedgeBuying) {\\n                require(currentPrice >= prevPrice, \\\"C25\\\");\\n            } else {\\n                require(currentPrice <= prevPrice, \\\"C25\\\");\\n            }\\n            prevPrice = currentPrice;\\n\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\n\\n            if (remainingAmount > _orders[i].quantity) {\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\n            } else {\\n                break;\\n            }\\n        }\\n\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\n    }\\n\\n    /**\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\n     * @param _price clearing price provided by manager\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\n     */\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\n        // Get twap\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n\\n        if (_isHedgeBuying) {\\n            require(\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\n                \\\"Price too high relative to Uniswap twap.\\\"\\n            );\\n        } else {\\n            require(\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\n                \\\"Price too low relative to Uniswap twap.\\\"\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\n        require(!isShutdown, \\\"C26\\\");\\n\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n        );\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     */\\n    function _isTimeHedge() internal view returns (bool) {\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge() internal view returns (bool) {\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge() external view returns (bool) {\\n        return _isPriceHedge();\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkTimeHedge() external view returns (bool) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/drafts/EIP712.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = _getChainId();\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n        return keccak256(\\n            abi.encode(\\n                typeHash,\\n                name,\\n                version,\\n                _getChainId(),\\n                address(this)\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/cryptography/ECDSA.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        // Check the signature length\\n        if (signature.length != 65) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        }\\n\\n        // Divide the signature in r, s and v variables\\n        bytes32 r;\\n        bytes32 s;\\n        uint8 v;\\n\\n        // ecrecover takes the signature parameters, and the only way to get them\\n        // currently is to use assembly.\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            r := mload(add(signature, 0x20))\\n            s := mload(add(signature, 0x40))\\n            v := byte(0, mload(add(signature, 0x60)))\\n        }\\n\\n        return recover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n        require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n        return signer;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * replicates the behavior of the\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n     * JSON-RPC method.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\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) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/strategy/CrabHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {ICrabStrategyV2} from \\\"../interfaces/ICrabStrategyV2.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {StrategySwap} from \\\"./helper/StrategySwap.sol\\\";\\n\\n/**\\n * @dev CrabHelper contract\\n * @notice Contract for Crab helper functions\\n * @author Opyn team\\n */\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\n    using Address for address payable;\\n\\n    address public immutable crab;\\n    address public immutable weth;\\n\\n    event FlashDepositERC20(\\n        address indexed depositor,\\n        address depositedERC20,\\n        uint256 depositedAmount,\\n        uint256 depositedEthAmount,\\n        uint256 crabAmount,\\n        uint256 returnedEth\\n    );\\n\\n    event FlashWithdrawERC20(\\n        address indexed withdrawer,\\n        address withdrawnERC20,\\n        uint256 withdrawnAmount,\\n        uint256 withdrawnEthAmount,\\n        uint256 crabAmount\\n    );\\n\\n    /**\\n     * @notice constructor\\n     * @param _crab address of crabV2 contract\\n     * @param _swapRouter address of Uniswap swap router\\n     */\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\n        require(_crab != address(0), \\\"Invalid crab address\\\");\\n\\n        crab = _crab;\\n        weth = ICrabStrategyV2(_crab).weth();\\n    }\\n\\n    /**\\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\\n     * @param _ethToDeposit amount of ETH to deposit\\n     * @param _amountIn amount of ERC20 token to swap for weth\\n     * @param _minEthToGet min amount of ETH to receive in the swap\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     * @param _tokenIn ERC20 token to pay\\n     */\\n    function flashDepositERC20(\\n        uint256 _ethToDeposit,\\n        uint256 _amountIn,\\n        uint256 _minEthToGet,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee,\\n        address _tokenIn\\n    ) external nonReentrant {\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\\n\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\\n\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\n\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\n\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\n\\n        if (address(this).balance > 0) {\\n            payable(msg.sender).sendValue(address(this).balance);\\n        }\\n    }\\n\\n    /**\\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\\n     * @param _crabAmount amount of crab shares to withdraw\\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\\n     * @param _tokenOut ERC20 token to receive\\n     * @param _minAmountOut min amount of ERC20 to receive\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     */\\n    function flashWithdrawERC20(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        address _tokenOut,\\n        uint256 _minAmountOut,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee\\n    ) external nonReentrant {\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\n\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\\n\\n        uint256 ethBalance = address(this).balance;\\n        IWETH9(weth).deposit{value: ethBalance}();\\n        uint256 tokenReceived = _swapExactInputSingle(\\n            weth,\\n            _tokenOut,\\n            address(this),\\n            msg.sender,\\n            ethBalance,\\n            _minAmountOut,\\n            _erc20Fee\\n        );\\n\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crab, \\\"Cannot receive eth\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/ICrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\ninterface ICrabStrategyV2 {\\n    function wPowerPerp() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\\n\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/strategy/helper/StrategySwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract StrategySwap {\\n    ISwapRouter public immutable swapRouter;\\n\\n    constructor(address _swapRouter) {\\n        require(_swapRouter != address(0), \\\"invalid swap router address\\\");\\n        swapRouter = ISwapRouter(_swapRouter);\\n    }\\n\\n    /**\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _from from which user we are selling\\n     * @param _to Recipient to get the tokens\\n     * @param _amountIn Exact amount to sell\\n     * @param _minAmountOut Minimum amount to be paid\\n     * @param _fee pool fee\\n     * @return amountOut The amount of WETH9 received.\\n     */\\n    function _swapExactInputSingle(\\n        address _tokenIn,\\n        address _tokenOut,\\n        address _from,\\n        address _to,\\n        uint256 _amountIn,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) internal returns (uint256 amountOut) {\\n        // _from must approve this contract\\n\\n        // Transfer the specified amount of tokenIn to this contract.\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\n\\n        // Approve the router to spend tokenIn.\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\n\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\n            tokenIn: _tokenIn,\\n            tokenOut: _tokenOut,\\n            fee: _fee,\\n            recipient: _to,\\n            deadline: block.timestamp,\\n            amountIn: _amountIn,\\n            amountOutMinimum: _minAmountOut,\\n            sqrtPriceLimitX96: 0\\n        });\\n\\n        // The call to `exactInputSingle` executes the swap.\\n        amountOut = swapRouter.exactInputSingle(params);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabMigration.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport {IEulerExec, IDToken} from \\\"../interfaces/IEuler.sol\\\";\\nimport {WETH9} from \\\"../external/WETH9.sol\\\";\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// contract\\nimport {CrabStrategyV2} from \\\"./CrabStrategyV2.sol\\\";\\nimport {CrabStrategy} from \\\"./CrabStrategy.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * Migration Error Codes:\\n * M1: Migration already happened\\n * M2: Migration has not yet happened\\n * M3: msg.sender is not Euler Mainnet Contract\\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\\n * M5: Can't withdraw more than you own\\n * M6: Not enough ETH to repay the loan\\n * M7: Invalid crabV2 address\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\n * M10: Wrong migration function, use flashMigrateFromV1toV2\\n * M11: crabV2 address not yet set\\n */\\n\\n/**\\n * @dev CrabMigration contract\\n * @notice Contract for Migrating from Crab V1 to Crab V2\\n * @author Opyn team\\n */\\ncontract CrabMigration is Ownable {\\n    using SafeERC20 for IERC20;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    mapping(address => uint256) public sharesDeposited;\\n    bool public isMigrated;\\n\\n    address payable public crabV1;\\n    address payable public crabV2;\\n    address public immutable euler;\\n    address public immutable weth;\\n\\n    address immutable EULER_MAINNET;\\n    address immutable dToken;\\n    address immutable wPowerPerp;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    struct BatchMigrate {\\n        uint256 strategyCap;\\n    }\\n\\n    struct FlashMigrateV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFee;\\n    }\\n\\n    struct FlashMigrateAndBuyV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 withdrawMaxEthToPay;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFeeFlashDeposit;\\n    }\\n\\n    enum FLASH_SOURCE {\\n        BATCH_MIGRATE,\\n        FLASH_MIGRATE_V1_TO_V2,\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\n    }\\n\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\\n\\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\\n\\n    modifier beforeMigration() {\\n        require(!isMigrated, \\\"M1\\\");\\n        _;\\n    }\\n\\n    modifier afterMigration() {\\n        require(isMigrated, \\\"M2\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialized() {\\n        require(crabV2 != address(0), \\\"M11\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice migration constructor\\n     * @param _crabV1 address of crab V1\\n     * @param _weth address of weth\\n     * @param _eulerExec address of euler exec contract\\n     * @param _dToken address of euler liability token\\n     * @param _eulerMainnet address of euler deployment on mainnet\\n     */\\n    constructor(\\n        address payable _crabV1,\\n        address _weth,\\n        address _eulerExec,\\n        address _dToken,\\n        address _eulerMainnet\\n    ) {\\n        require(_eulerExec != address(0), \\\"invalid _eulerExec address\\\");\\n        require(_dToken != address(0), \\\"invalid _dToken address\\\");\\n        require(_eulerMainnet != address(0), \\\"invalid _eulerMainnet address\\\");\\n        require(_weth != address(0), \\\"invalid _weth address\\\");\\n        require(_crabV1 != address(0), \\\"invalid _crabv1 address\\\");\\n        require(IDToken(_dToken).underlyingAsset() == _weth, \\\"dToken underlying asset should be weth\\\");\\n\\n        crabV1 = _crabV1;\\n        euler = _eulerExec;\\n        EULER_MAINNET = _eulerMainnet;\\n        weth = _weth;\\n        dToken = _dToken;\\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\\n    }\\n\\n    /**\\n     * @notice set the crabV2 address\\n     * @param _crabV2 address of crab V2\\n     */\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\n        require(_crabV2 != address(0), \\\"M7\\\");\\n        crabV2 = _crabV2;\\n    }\\n\\n    /**\\n     * @notice deposit crab V1 shares in the pool for migration\\n     * @param _amount amount of crabV1 shares to deposit\\n     */\\n    function depositV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] += _amount;\\n\\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\\n\\n        emit DepositV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice withdraw crab V1 shares in the pool before migration\\n     * @param _amount amount of V1 shares to withdraw\\n     */\\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\\n\\n        emit WithdrawV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\\n     * the V2 contract at the same collateral ratio as the V1 contract\\n     * @param _strategyCap strategy cap in ETH\\n     */\\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\\n        // 1. update isMigrated\\n        isMigrated = true;\\n\\n        // 2. flash floan eth from euler eq to amt\\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: amountEthToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Euler callback function\\n     * @param encodedData callback data\\n     */\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\n        require(msg.sender == EULER_MAINNET, \\\"M3\\\");\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        // 1. borrow weth\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\n        WETH9(weth).withdraw(data.amountToBorrow);\\n\\n        // 2. callback\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\n\\n        // 3. repay the weth\\n        WETH9(weth).deposit{value: data.amountToBorrow}();\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     * @notice callback function for flash actions\\n     * @param _initiator address of original function caller\\n     * @param _amount  amount to pay back for flashswap\\n     * @param _callSource identifier for which function triggered callback\\n     * @param _calldata arbitrary data attached to callback\\n\\n     */\\n    function _flashCallback(\\n        address _initiator,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\\n\\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n\\n            // 2. mint osqth in crab V2\\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\\n                wSqueethToMint,\\n                crabV1Balance,\\n                timeAtLastHedge,\\n                priceAtLastHedge,\\n                data.strategyCap\\n            );\\n\\n            // 3. call withdraw from crab V1\\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\n\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n\\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\\n\\n            // flash deposit remaining ETH, otherwise refund\\n            // if CR1 = CR2 ethToFlashDeposit should be 0\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFee\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n            // send back V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\\n\\n            // find crab amount for contract's sqth balance\\n            // remaining crab can be withdrawn using flash withdraw\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\n\\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\\n\\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\n            require(address(this).balance >= _amount, \\\"M6\\\");\\n\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFeeFlashDeposit\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n\\n            // send V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back the excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares\\n     */\\n    function claimV2Shares() external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        sharesDeposited[msg.sender] = 0;\\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares and flash withdraw from crab V2\\n     * @param _amountToWithdraw V2 shares to claim\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee Uniswap pool fee for flash withdraw\\n     */\\n    function claimAndWithdraw(\\n        uint256 _amountToWithdraw,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        require(_amountToWithdraw <= amountV1Deposited, \\\"M5\\\");\\n\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\\n\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\n\\n        // send eth to user\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice view details of flash migration for specified amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function flashMigrationDetails(uint256 _v1Shares)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return _flashMigrationDetails(_v1Shares);\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\n     * @param _poolFee uniswap pool fee for flash deposit\\n     */\\n    function flashMigrateFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(isFlashOnlyMigrate, \\\"M9\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: ethNeededForV2,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateV1toV2({\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFee: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\\n     */\\n    function flashMigrateAndWithdrawFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint256 _ethToBorrow,\\n        uint256 _withdrawMaxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(!isFlashOnlyMigrate, \\\"M10\\\");\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\"M8\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: _ethToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateAndBuyV1toV2({\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFeeFlashDeposit: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice get migration details for given amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function _flashMigrationDetails(uint256 _v1Shares)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\\n\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\\n\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \\\"M4\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IEuler.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\ninterface IEulerExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IDToken {\\n    function underlyingAsset() external view returns (address);\\n\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\"\n    },\n    \"contracts/external/WETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\n\\ncontract WETH9 {\\n    string public name = \\\"Wrapped Ether\\\";\\n    string public symbol = \\\"WETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        payable(msg.sender).transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract MockErc20 is ERC20, Ownable {\\n\\n    /// @dev mapping to track whitelisted minters\\n    mapping(address => bool) internal whitelistedMinters;\\n    \\n    /// @notice emits an event when a minter is whitelisted \\n    event MinterWhitelisted(address indexed account );\\n\\n    /// @notice emits an event when a minter is blacklisted \\n    event MinterBlacklisted(address indexed account);\\n    \\n\\n    /**\\n     * @notice check if the sender is whitelistd\\n     */\\n    modifier onlyWhitelisted() {\\n        require(\\n            whitelistedMinters[msg.sender] || msg.sender == owner(),\\n            \\\"Address not a whitelisted minter\\\"\\n        );\\n        _;\\n    }\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external onlyWhitelisted {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice check if a minter is whitelisted\\n     * @param _account address of minter\\n     * @return boolean, True if address is a whitelisted minter\\n     */\\n    function isWhitelistedMinter(address _account) external view returns (bool) {\\n        return whitelistedMinters[_account];\\n    }\\n\\n    /**\\n     * @notice allows the minter to whitelist other minters\\n     * @param _account address of minter to be whitelisted\\n     */\\n    function whitelistMinter(address _account) external onlyWhitelisted {\\n        whitelistedMinters[_account] = true;\\n\\n        emit MinterWhitelisted(_account);\\n    }\\n\\n    /**\\n     * @notice allow the minter to blacklist other minters\\n     * @param _account address of minter to be blacklisted\\n     */\\n    function blacklistMinter(address _account) external onlyWhitelisted {\\n        whitelistedMinters[_account] = false;\\n\\n        emit MinterBlacklisted(_account);\\n    }\\n\\n\\n  \\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockEulerDToken.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockEulerDToken {\\n    ERC20 weth;\\n\\n    constructor(address _weth) {\\n        weth = ERC20(_weth);\\n    }\\n\\n    function borrow(uint256, uint256 amount) external {\\n        weth.transfer(msg.sender, amount);\\n    }\\n\\n    function repay(uint256, uint256 amount) external {\\n        weth.transferFrom(msg.sender, address(this), amount);\\n    }\\n\\n    function underlyingAsset() external view returns (address) {\\n        return address(weth);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockCrab.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockCrab is ERC20 {\\n    address operator;\\n    uint256 vaultId;\\n    uint256 collateral;\\n    uint256 short;\\n    address public wPowerPerp;\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    function setVaultDetails(\\n        uint256 _vaultId,\\n        uint256 _collateral,\\n        uint256 _short\\n    ) external {\\n        vaultId = _vaultId;\\n        collateral = _collateral;\\n        short = _short;\\n    }\\n\\n    function getVaultDetails()\\n        external\\n        view\\n        returns (\\n            address,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return (operator, vaultId, collateral, short);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"C3\\\");\\n\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/solcInputs/5f1800dd06bba4733ee96eb427b535c3.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // Ceil A to a multiple m\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(sub(add(a, m), 1), m), m);\\n    }\\n\\n    // Floor A to a multiple m\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(a, m), m);\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {EIP712} from \\\"@openzeppelin/contracts/drafts/EIP712.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\nimport {ECDSA} from \\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * Crab V2 Error Codes:\\n * C1: Caller is not timelock\\n * C2: Contract not yet initialized\\n * C3: Invalid oracle address\\n * C4: Invalid timelock address\\n * C5: Invalid ETH:WSqueeth address\\n * C6: Invalid crabMigration address\\n * C7: Invalid hedge time threshold\\n * C8: Invalid hedge price threshold\\n * C9: Cannot receive ETH\\n * C10: Caller not Crab Migration contract\\n * C11: Crab V2 already initialized\\n * C12: Squeeth contracts not shut down\\n * C13: Crab must redeemShortShutdown\\n * C14: Twap period is too short\\n * C15: Price tolerance is too high\\n * C16: Deposit exceeds strategy cap\\n * C17: Clearing Price should be below bid price\\n * C18: Clearing Price should be above offer price\\n * C19: Invalid offer signature\\n * C20: Order has expired\\n * C21: Manager Price should be greater than 0\\n * C22: Not a valid Time or Price hedge\\n * C23: Orders must take the opposite side of the hedge\\n * C24: All orders must be either buying or selling\\n * C25: Orders are not arranged properly\\n * C26: Crab contracts shut down\\n *  C27: Nonce already used.\\n */\\n\\n/**\\n * @dev CrabStrategyV2 contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    // @dev OTC price must be within this distance of the uniswap twap price\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\n\\n    // @dev OTC price tolerance cannot exceed 20%\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\n\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n    /// @dev true if CrabV2 was initialized\\n    bool public isInitialized;\\n\\n    /// @dev typehash for signed orders\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\n        keccak256(\\n            \\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\"\\n        );\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:wSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable timelock;\\n    address public immutable crabMigration;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev wSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    /// @dev store the used flag for a nonce for each address\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct Order {\\n        uint256 bidId;\\n        address trader;\\n        uint256 quantity;\\n        uint256 price;\\n        bool isBuying;\\n        uint256 expiry;\\n        uint256 nonce;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event HedgeOTCSingle(\\n        address trader,\\n        uint256 bidId,\\n        uint256 quantity,\\n        uint256 price,\\n        bool isBuying,\\n        uint256 clearingPrice\\n    );\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\n\\n    modifier onlyTimelock() {\\n        require(msg.sender == timelock, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialization() {\\n        require(isInitialized, \\\"C2\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _timelock timelock contract address\\n     * @param _crabMigration crab migration contract address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        address _timelock,\\n        address _crabMigration,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold\\n    )\\n        StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy v2\\\", \\\"Crabv2\\\")\\n        StrategyFlashSwap(_uniswapFactory)\\n        EIP712(\\\"CrabOTC\\\", \\\"2\\\")\\n    {\\n        require(_oracle != address(0), \\\"C3\\\");\\n        require(_timelock != address(0), \\\"C4\\\");\\n        require(_ethWSqueethPool != address(0), \\\"C5\\\");\\n        require(_crabMigration != address(0), \\\"C6\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        timelock = _timelock;\\n        crabMigration = _crabMigration;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"C9\\\");\\n    }\\n\\n    /**\\n     * @notice initializes the collateral ratio after the first migration\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\n     * @param _crabSharesToMint crab shares to mint\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\n     * @param _strategyCap strategy cap for crab V2\\n     */\\n    function initialize(\\n        uint256 _wSqueethToMint,\\n        uint256 _crabSharesToMint,\\n        uint256 _timeAtLastHedge,\\n        uint256 _priceAtLastHedge,\\n        uint256 _strategyCap\\n    ) external payable {\\n        require(msg.sender == crabMigration, \\\"C10\\\");\\n        require(!isInitialized, \\\"C11\\\");\\n\\n        _setStrategyCap(_strategyCap);\\n\\n        uint256 amount = msg.value;\\n\\n        _checkStrategyCap(amount, 0);\\n\\n        // store hedge data from crab V1\\n        timeAtLastHedge = _timeAtLastHedge;\\n        priceAtLastHedge = _priceAtLastHedge;\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\n\\n        isInitialized = true;\\n    }\\n\\n    /**\\n     * @notice transfer vault NFT to new contract\\n     * @dev strategy cap is set to 0 to avoid future deposits\\n     * @param _newStrategy new strategy contract address\\n     */\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\n        _setStrategyCap(0);\\n\\n        emit VaultTransferred(_newStrategy, vaultId);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\n        _setStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice set strategy cap amount\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function _setStrategyCap(uint256 _capAmount) internal {\\n        strategyCap = _capAmount;\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external afterInitialization {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     * @param _poolFee Uniswap pool fee\\n     */\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _poolFee,\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\n     * @param _poolFee Uniswap pool fee\\n\\n     */\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _poolFee,\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"C12\\\");\\n        require(hasRedeemedInShutdown, \\\"C13\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice set nonce to true\\n     * @param _nonce the number to be set true\\n     */\\n    function setNonceTrue(uint256 _nonce) external {\\n        nonces[msg.sender][_nonce] = true;\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"C14\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\n     */\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\n        // Tolerance cannot be more than 20%\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\"C15\\\");\\n\\n        otcPriceTolerance = _otcPriceTolerance;\\n\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"C16\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            // will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            // return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\n\\n            // excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @dev set nonce flag of the trader to true\\n     * @param _trader address of the signer\\n     * @param _nonce number that is to be traded only once\\n     */\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\n        require(!nonces[_trader][_nonce], \\\"C27\\\");\\n        nonces[_trader][_nonce] = true;\\n    }\\n\\n    /**\\n     * @dev view function to get the domain seperator used in signing\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev check the signer and swap tokens in the order\\n     * @param _remainingAmount quantity the manager wants to trade\\n     * @param _clearingPrice the price at which all orders are traded\\n     * @param _order a signed order to swap tokens\\n     */\\n    function _execOrder(\\n        uint256 _remainingAmount,\\n        uint256 _clearingPrice,\\n        Order memory _order\\n    ) internal {\\n        // check that order beats clearing price\\n        if (_order.isBuying) {\\n            require(_clearingPrice <= _order.price, \\\"C17\\\");\\n        } else {\\n            require(_clearingPrice >= _order.price, \\\"C18\\\");\\n        }\\n\\n        _useNonce(_order.trader, _order.nonce);\\n        bytes32 structHash = keccak256(\\n            abi.encode(\\n                _CRAB_BALANCE_TYPEHASH,\\n                _order.bidId,\\n                _order.trader,\\n                _order.quantity,\\n                _order.price,\\n                _order.isBuying,\\n                _order.expiry,\\n                _order.nonce\\n            )\\n        );\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\n        require(offerSigner == _order.trader, \\\"C19\\\");\\n        require(_order.expiry >= block.timestamp, \\\"C20\\\");\\n\\n        // adjust quantity for partial fills\\n        if (_remainingAmount < _order.quantity) {\\n            _order.quantity = _remainingAmount;\\n        }\\n        // weth clearing price for the order\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\n\\n        if (_order.isBuying) {\\n            // trader sends weth and receives oSQTH\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\n            IWETH9(weth).withdraw(wethAmount);\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n        } else {\\n            // trader sends oSQTH and receives weth\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n            // wrap it\\n            IWETH9(weth).deposit{value: wethAmount}();\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\n        }\\n\\n        emit HedgeOTCSingle(\\n            _order.trader, // market maker\\n            _order.bidId,\\n            _order.quantity, // order oSQTH quantity\\n            _order.price, // order price\\n            _order.isBuying, // order direction\\n            _clearingPrice // executed price for order\\n        );\\n    }\\n\\n    /**\\n     * @dev hedge function to reduce delta using an array of signed orders\\n     * @param _totalQuantity quantity the manager wants to trade\\n     * @param _clearingPrice clearing price in weth\\n     * @param _isHedgeBuying direction of hedge trade\\n     * @param _orders an array of signed order to swap tokens\\n     */\\n    function hedgeOTC(\\n        uint256 _totalQuantity,\\n        uint256 _clearingPrice,\\n        bool _isHedgeBuying,\\n        Order[] memory _orders\\n    ) external onlyOwner afterInitialization {\\n        require(_clearingPrice > 0, \\\"C21\\\");\\n        require(_isTimeHedge() || _isPriceHedge(), \\\"C22\\\");\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = _clearingPrice;\\n\\n        uint256 remainingAmount = _totalQuantity;\\n        uint256 prevPrice = _orders[0].price;\\n        uint256 currentPrice = _orders[0].price;\\n        bool isOrderBuying = _orders[0].isBuying;\\n        require(_isHedgeBuying != isOrderBuying, \\\"C23\\\");\\n\\n        // iterate through order array and execute if valid\\n        for (uint256 i; i < _orders.length; ++i) {\\n            currentPrice = _orders[i].price;\\n            require(_orders[i].isBuying == isOrderBuying, \\\"C24\\\");\\n            if (_isHedgeBuying) {\\n                require(currentPrice >= prevPrice, \\\"C25\\\");\\n            } else {\\n                require(currentPrice <= prevPrice, \\\"C25\\\");\\n            }\\n            prevPrice = currentPrice;\\n\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\n\\n            if (remainingAmount > _orders[i].quantity) {\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\n            } else {\\n                break;\\n            }\\n        }\\n\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\n    }\\n\\n    /**\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\n     * @param _price clearing price provided by manager\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\n     */\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\n        // Get twap\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n\\n        if (_isHedgeBuying) {\\n            require(\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\n                \\\"Price too high relative to Uniswap twap.\\\"\\n            );\\n        } else {\\n            require(\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\n                \\\"Price too low relative to Uniswap twap.\\\"\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\n        require(!isShutdown, \\\"C26\\\");\\n\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n        );\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     */\\n    function _isTimeHedge() internal view returns (bool) {\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge() internal view returns (bool) {\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge() external view returns (bool) {\\n        return _isPriceHedge();\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkTimeHedge() external view returns (bool) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/drafts/EIP712.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = _getChainId();\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n        return keccak256(\\n            abi.encode(\\n                typeHash,\\n                name,\\n                version,\\n                _getChainId(),\\n                address(this)\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/cryptography/ECDSA.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        // Check the signature length\\n        if (signature.length != 65) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        }\\n\\n        // Divide the signature in r, s and v variables\\n        bytes32 r;\\n        bytes32 s;\\n        uint8 v;\\n\\n        // ecrecover takes the signature parameters, and the only way to get them\\n        // currently is to use assembly.\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            r := mload(add(signature, 0x20))\\n            s := mload(add(signature, 0x40))\\n            v := byte(0, mload(add(signature, 0x60)))\\n        }\\n\\n        return recover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n        require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n        return signer;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * replicates the behavior of the\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n     * JSON-RPC method.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\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) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/strategy/CrabHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {ICrabStrategyV2} from \\\"../interfaces/ICrabStrategyV2.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {StrategySwap} from \\\"./helper/StrategySwap.sol\\\";\\n\\n/**\\n * @dev CrabHelper contract\\n * @notice Contract for Crab helper functions\\n * @author Opyn team\\n */\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\n    using Address for address payable;\\n\\n    address public immutable crab;\\n    address public immutable weth;\\n\\n    event FlashDepositERC20(\\n        address indexed depositor,\\n        address depositedERC20,\\n        uint256 depositedAmount,\\n        uint256 depositedEthAmount,\\n        uint256 crabAmount,\\n        uint256 returnedEth\\n    );\\n\\n    event FlashWithdrawERC20(\\n        address indexed withdrawer,\\n        address withdrawnERC20,\\n        uint256 withdrawnAmount,\\n        uint256 withdrawnEthAmount,\\n        uint256 crabAmount\\n    );\\n\\n    /**\\n     * @notice constructor\\n     * @param _crab address of crabV2 contract\\n     * @param _swapRouter address of Uniswap swap router\\n     */\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\n        require(_crab != address(0), \\\"Invalid crab address\\\");\\n\\n        crab = _crab;\\n        weth = ICrabStrategyV2(_crab).weth();\\n    }\\n\\n    /**\\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\\n     * @param _ethToDeposit amount of ETH to deposit\\n     * @param _amountIn amount of ERC20 token to swap for weth\\n     * @param _minEthToGet min amount of ETH to receive in the swap\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     * @param _tokenIn ERC20 token to pay\\n     */\\n    function flashDepositERC20(\\n        uint256 _ethToDeposit,\\n        uint256 _amountIn,\\n        uint256 _minEthToGet,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee,\\n        address _tokenIn\\n    ) external nonReentrant {\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\\n\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\\n\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\n\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\n\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\n\\n        if (address(this).balance > 0) {\\n            payable(msg.sender).sendValue(address(this).balance);\\n        }\\n    }\\n\\n    /**\\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\\n     * @param _crabAmount amount of crab shares to withdraw\\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\\n     * @param _tokenOut ERC20 token to receive\\n     * @param _minAmountOut min amount of ERC20 to receive\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     */\\n    function flashWithdrawERC20(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        address _tokenOut,\\n        uint256 _minAmountOut,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee\\n    ) external nonReentrant {\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\n\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\\n\\n        uint256 ethBalance = address(this).balance;\\n        IWETH9(weth).deposit{value: ethBalance}();\\n        uint256 tokenReceived = _swapExactInputSingle(\\n            weth,\\n            _tokenOut,\\n            address(this),\\n            msg.sender,\\n            ethBalance,\\n            _minAmountOut,\\n            _erc20Fee\\n        );\\n\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crab, \\\"Cannot receive eth\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/ICrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\ninterface ICrabStrategyV2 {\\n    function wPowerPerp() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\\n\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/strategy/helper/StrategySwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract StrategySwap {\\n    ISwapRouter public immutable swapRouter;\\n\\n    constructor(address _swapRouter) {\\n        require(_swapRouter != address(0), \\\"invalid swap router address\\\");\\n        swapRouter = ISwapRouter(_swapRouter);\\n    }\\n\\n    /**\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _from from which user we are selling\\n     * @param _to Recipient to get the tokens\\n     * @param _amountIn Exact amount to sell\\n     * @param _minAmountOut Minimum amount to be paid\\n     * @param _fee pool fee\\n     * @return amountOut The amount of WETH9 received.\\n     */\\n    function _swapExactInputSingle(\\n        address _tokenIn,\\n        address _tokenOut,\\n        address _from,\\n        address _to,\\n        uint256 _amountIn,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) internal returns (uint256 amountOut) {\\n        // _from must approve this contract\\n\\n        // Transfer the specified amount of tokenIn to this contract.\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\n\\n        // Approve the router to spend tokenIn.\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\n\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\n            tokenIn: _tokenIn,\\n            tokenOut: _tokenOut,\\n            fee: _fee,\\n            recipient: _to,\\n            deadline: block.timestamp,\\n            amountIn: _amountIn,\\n            amountOutMinimum: _minAmountOut,\\n            sqrtPriceLimitX96: 0\\n        });\\n\\n        // The call to `exactInputSingle` executes the swap.\\n        amountOut = swapRouter.exactInputSingle(params);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabMigration.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport {IEulerExec, IDToken} from \\\"../interfaces/IEuler.sol\\\";\\nimport {WETH9} from \\\"../external/WETH9.sol\\\";\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// contract\\nimport {CrabStrategyV2} from \\\"./CrabStrategyV2.sol\\\";\\nimport {CrabStrategy} from \\\"./CrabStrategy.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * Migration Error Codes:\\n * M1: Migration already happened\\n * M2: Migration has not yet happened\\n * M3: msg.sender is not Euler Mainnet Contract\\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\\n * M5: Can't withdraw more than you own\\n * M6: Not enough ETH to repay the loan\\n * M7: Invalid crabV2 address\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\n * M10: Wrong migration function, use flashMigrateFromV1toV2\\n * M11: crabV2 address not yet set\\n */\\n\\n/**\\n * @dev CrabMigration contract\\n * @notice Contract for Migrating from Crab V1 to Crab V2\\n * @author Opyn team\\n */\\ncontract CrabMigration is Ownable {\\n    using SafeERC20 for IERC20;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    mapping(address => uint256) public sharesDeposited;\\n    bool public isMigrated;\\n\\n    address payable public crabV1;\\n    address payable public crabV2;\\n    address public immutable euler;\\n    address public immutable weth;\\n\\n    address immutable EULER_MAINNET;\\n    address immutable dToken;\\n    address immutable wPowerPerp;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    struct BatchMigrate {\\n        uint256 strategyCap;\\n    }\\n\\n    struct FlashMigrateV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFee;\\n    }\\n\\n    struct FlashMigrateAndBuyV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 withdrawMaxEthToPay;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFeeFlashDeposit;\\n    }\\n\\n    enum FLASH_SOURCE {\\n        BATCH_MIGRATE,\\n        FLASH_MIGRATE_V1_TO_V2,\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\n    }\\n\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\\n\\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\\n\\n    modifier beforeMigration() {\\n        require(!isMigrated, \\\"M1\\\");\\n        _;\\n    }\\n\\n    modifier afterMigration() {\\n        require(isMigrated, \\\"M2\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialized() {\\n        require(crabV2 != address(0), \\\"M11\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice migration constructor\\n     * @param _crabV1 address of crab V1\\n     * @param _weth address of weth\\n     * @param _eulerExec address of euler exec contract\\n     * @param _dToken address of euler liability token\\n     * @param _eulerMainnet address of euler deployment on mainnet\\n     */\\n    constructor(\\n        address payable _crabV1,\\n        address _weth,\\n        address _eulerExec,\\n        address _dToken,\\n        address _eulerMainnet\\n    ) {\\n        require(_eulerExec != address(0), \\\"invalid _eulerExec address\\\");\\n        require(_dToken != address(0), \\\"invalid _dToken address\\\");\\n        require(_eulerMainnet != address(0), \\\"invalid _eulerMainnet address\\\");\\n        require(_weth != address(0), \\\"invalid _weth address\\\");\\n        require(_crabV1 != address(0), \\\"invalid _crabv1 address\\\");\\n        require(IDToken(_dToken).underlyingAsset() == _weth, \\\"dToken underlying asset should be weth\\\");\\n\\n        crabV1 = _crabV1;\\n        euler = _eulerExec;\\n        EULER_MAINNET = _eulerMainnet;\\n        weth = _weth;\\n        dToken = _dToken;\\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\\n    }\\n\\n    /**\\n     * @notice set the crabV2 address\\n     * @param _crabV2 address of crab V2\\n     */\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\n        require(_crabV2 != address(0), \\\"M7\\\");\\n        crabV2 = _crabV2;\\n    }\\n\\n    /**\\n     * @notice deposit crab V1 shares in the pool for migration\\n     * @param _amount amount of crabV1 shares to deposit\\n     */\\n    function depositV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] += _amount;\\n\\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\\n\\n        emit DepositV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice withdraw crab V1 shares in the pool before migration\\n     * @param _amount amount of V1 shares to withdraw\\n     */\\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\\n\\n        emit WithdrawV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\\n     * the V2 contract at the same collateral ratio as the V1 contract\\n     * @param _strategyCap strategy cap in ETH\\n     */\\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\\n        // 1. update isMigrated\\n        isMigrated = true;\\n\\n        // 2. flash floan eth from euler eq to amt\\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: amountEthToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Euler callback function\\n     * @param encodedData callback data\\n     */\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\n        require(msg.sender == EULER_MAINNET, \\\"M3\\\");\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        // 1. borrow weth\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\n        WETH9(weth).withdraw(data.amountToBorrow);\\n\\n        // 2. callback\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\n\\n        // 3. repay the weth\\n        WETH9(weth).deposit{value: data.amountToBorrow}();\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     * @notice callback function for flash actions\\n     * @param _initiator address of original function caller\\n     * @param _amount  amount to pay back for flashswap\\n     * @param _callSource identifier for which function triggered callback\\n     * @param _calldata arbitrary data attached to callback\\n\\n     */\\n    function _flashCallback(\\n        address _initiator,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\\n\\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n\\n            // 2. mint osqth in crab V2\\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\\n                wSqueethToMint,\\n                crabV1Balance,\\n                timeAtLastHedge,\\n                priceAtLastHedge,\\n                data.strategyCap\\n            );\\n\\n            // 3. call withdraw from crab V1\\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\n\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n\\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\\n\\n            // flash deposit remaining ETH, otherwise refund\\n            // if CR1 = CR2 ethToFlashDeposit should be 0\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFee\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n            // send back V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\\n\\n            // find crab amount for contract's sqth balance\\n            // remaining crab can be withdrawn using flash withdraw\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\n\\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\\n\\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\n            require(address(this).balance >= _amount, \\\"M6\\\");\\n\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFeeFlashDeposit\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n\\n            // send V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back the excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares\\n     */\\n    function claimV2Shares() external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        sharesDeposited[msg.sender] = 0;\\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares and flash withdraw from crab V2\\n     * @param _amountToWithdraw V2 shares to claim\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee Uniswap pool fee for flash withdraw\\n     */\\n    function claimAndWithdraw(\\n        uint256 _amountToWithdraw,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        require(_amountToWithdraw <= amountV1Deposited, \\\"M5\\\");\\n\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\\n\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\n\\n        // send eth to user\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice view details of flash migration for specified amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function flashMigrationDetails(uint256 _v1Shares)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return _flashMigrationDetails(_v1Shares);\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\n     * @param _poolFee uniswap pool fee for flash deposit\\n     */\\n    function flashMigrateFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(isFlashOnlyMigrate, \\\"M9\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: ethNeededForV2,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateV1toV2({\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFee: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\\n     */\\n    function flashMigrateAndWithdrawFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint256 _ethToBorrow,\\n        uint256 _withdrawMaxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(!isFlashOnlyMigrate, \\\"M10\\\");\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\"M8\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: _ethToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateAndBuyV1toV2({\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFeeFlashDeposit: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice get migration details for given amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function _flashMigrationDetails(uint256 _v1Shares)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\\n\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\\n\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \\\"M4\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IEuler.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\ninterface IEulerExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IDToken {\\n    function underlyingAsset() external view returns (address);\\n\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\"\n    },\n    \"contracts/external/WETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\n\\ncontract WETH9 {\\n    string public name = \\\"Wrapped Ether\\\";\\n    string public symbol = \\\"WETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        payable(msg.sender).transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract MockErc20 is ERC20, Ownable {\\n\\n    /// @dev mapping to track whitelisted minters\\n    mapping(address => bool) internal whitelistedMinters;\\n    \\n    /// @notice emits an event when a minter is whitelisted \\n    event MinterWhitelisted(address indexed account );\\n\\n    /// @notice emits an event when a minter is blacklisted \\n    event MinterBlacklisted(address indexed account);\\n    \\n\\n    /**\\n     * @notice check if the sender is whitelistd\\n     */\\n    modifier onlyWhitelisted() {\\n        require(\\n            whitelistedMinters[msg.sender],\\n            \\\"Address not a whitelisted minter\\\"\\n        );\\n        _;\\n    }\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external onlyWhitelisted {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice check if a minter is whitelisted\\n     * @param _account address of minter\\n     * @return boolean, True if address is a whitelisted minter\\n     */\\n    function isWhitelistedMinter(address _account) external view returns (bool) {\\n        return whitelistedMinters[_account];\\n    }\\n\\n    /**\\n     * @notice allows the minter to whitelist other minters\\n     * @param _account address of minter to be whitelisted\\n     */\\n    function whitelistMinter(address _account) external onlyWhitelisted {\\n        whitelistedMinters[_account] = true;\\n\\n        emit MinterWhitelisted(_account);\\n    }\\n\\n    /**\\n     * @notice allow the minter to blacklist other minters\\n     * @param _account address of minter to be blacklisted\\n     */\\n    function blacklistMinter(address _account) external onlyWhitelisted {\\n        whitelistedMinters[_account] = false;\\n\\n        emit MinterBlacklisted(_account);\\n    }\\n\\n\\n  \\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockEulerDToken.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockEulerDToken {\\n    ERC20 weth;\\n\\n    constructor(address _weth) {\\n        weth = ERC20(_weth);\\n    }\\n\\n    function borrow(uint256, uint256 amount) external {\\n        weth.transfer(msg.sender, amount);\\n    }\\n\\n    function repay(uint256, uint256 amount) external {\\n        weth.transferFrom(msg.sender, address(this), amount);\\n    }\\n\\n    function underlyingAsset() external view returns (address) {\\n        return address(weth);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockCrab.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockCrab is ERC20 {\\n    address operator;\\n    uint256 vaultId;\\n    uint256 collateral;\\n    uint256 short;\\n    address public wPowerPerp;\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    function setVaultDetails(\\n        uint256 _vaultId,\\n        uint256 _collateral,\\n        uint256 _short\\n    ) external {\\n        vaultId = _vaultId;\\n        collateral = _collateral;\\n        short = _short;\\n    }\\n\\n    function getVaultDetails()\\n        external\\n        view\\n        returns (\\n            address,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return (operator, vaultId, collateral, short);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"C3\\\");\\n\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/goerli/solcInputs/c53867cdbf46138ab42de1c7a1689875.json",
    "content": "{\n    \"language\": \"Solidity\",\n    \"sources\": {\n        \"contracts/core/Controller.sol\": {\n            \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n        },\n        \"contracts/interfaces/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n        },\n        \"contracts/interfaces/IWPowerPerp.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n        },\n        \"contracts/interfaces/IShortPowerPerp.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n        },\n        \"contracts/interfaces/IOracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/access/Ownable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/math/SafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Address.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/ABDKMath64x64.sol\": {\n            \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/VaultLib.sol\": {\n            \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/Uint256Casting.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/Power2Base.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Context.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/TickMathExternal.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/SqrtPriceMathPartial.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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        },\n        \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n            \"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\"\n        },\n        \"contracts/test/LiquidationHelper.sol\": {\n            \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n        },\n        \"contracts/interfaces/IController.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n            \"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\"\n        },\n        \"contracts/test/OracleTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n        },\n        \"contracts/core/Oracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n        },\n        \"contracts/interfaces/IERC20Detailed.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n        },\n        \"contracts/libs/OracleLibrary.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n        },\n        \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n            \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n        },\n        \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n            \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n        },\n        \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n        },\n        \"contracts/test/VaultTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n        },\n        \"contracts/strategy/base/StrategyBase.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n        },\n        \"contracts/strategy/base/StrategyMath.sol\": {\n            \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // Ceil A to a multiple m\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(sub(add(a, m), 1), m), m);\\n    }\\n\\n    // Floor A to a multiple m\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(a, m), m);\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n        },\n        \"contracts/strategy/CrabStrategy.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n        },\n        \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n        },\n        \"contracts/strategy/CrabStrategyV2.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {EIP712} from \\\"@openzeppelin/contracts/drafts/EIP712.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\nimport {ECDSA} from \\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * Crab V2 Error Codes:\\n * C1: Caller is not timelock\\n * C2: Contract not yet initialized\\n * C3: Invalid oracle address\\n * C4: Invalid timelock address\\n * C5: Invalid ETH:WSqueeth address\\n * C6: Invalid crabMigration address\\n * C7: Invalid hedge time threshold\\n * C8: Invalid hedge price threshold\\n * C9: Cannot receive ETH\\n * C10: Caller not Crab Migration contract\\n * C11: Crab V2 already initialized\\n * C12: Squeeth contracts not shut down\\n * C13: Crab must redeemShortShutdown\\n * C14: Twap period is too short\\n * C15: Price tolerance is too high\\n * C16: Deposit exceeds strategy cap\\n * C17: Clearing Price should be below bid price\\n * C18: Clearing Price should be above offer price\\n * C19: Invalid offer signature\\n * C20: Order has expired\\n * C21: Manager Price should be greater than 0\\n * C22: Not a valid Time or Price hedge\\n * C23: Orders must take the opposite side of the hedge\\n * C24: All orders must be either buying or selling\\n * C25: Orders are not arranged properly\\n * C26: Crab contracts shut down\\n *  C27: Nonce already used.\\n */\\n\\n/**\\n * @dev CrabStrategyV2 contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    // @dev OTC price must be within this distance of the uniswap twap price\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\n\\n    // @dev OTC price tolerance cannot exceed 20%\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\n\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n    /// @dev true if CrabV2 was initialized\\n    bool public isInitialized;\\n\\n    /// @dev typehash for signed orders\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\n        keccak256(\\n            \\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\"\\n        );\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:wSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable timelock;\\n    address public immutable crabMigration;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev wSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    /// @dev store the used flag for a nonce for each address\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct Order {\\n        uint256 bidId;\\n        address trader;\\n        uint256 quantity;\\n        uint256 price;\\n        bool isBuying;\\n        uint256 expiry;\\n        uint256 nonce;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event HedgeOTCSingle(\\n        address trader,\\n        uint256 bidId,\\n        uint256 quantity,\\n        uint256 price,\\n        bool isBuying,\\n        uint256 clearingPrice\\n    );\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\n\\n    modifier onlyTimelock() {\\n        require(msg.sender == timelock, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialization() {\\n        require(isInitialized, \\\"C2\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _timelock timelock contract address\\n     * @param _crabMigration crab migration contract address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        address _timelock,\\n        address _crabMigration,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold\\n    )\\n        StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy v2\\\", \\\"Crabv2\\\")\\n        StrategyFlashSwap(_uniswapFactory)\\n        EIP712(\\\"CrabOTC\\\", \\\"2\\\")\\n    {\\n        require(_oracle != address(0), \\\"C3\\\");\\n        require(_timelock != address(0), \\\"C4\\\");\\n        require(_ethWSqueethPool != address(0), \\\"C5\\\");\\n        require(_crabMigration != address(0), \\\"C6\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        timelock = _timelock;\\n        crabMigration = _crabMigration;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"C9\\\");\\n    }\\n\\n    /**\\n     * @notice initializes the collateral ratio after the first migration\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\n     * @param _crabSharesToMint crab shares to mint\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\n     * @param _strategyCap strategy cap for crab V2\\n     */\\n    function initialize(\\n        uint256 _wSqueethToMint,\\n        uint256 _crabSharesToMint,\\n        uint256 _timeAtLastHedge,\\n        uint256 _priceAtLastHedge,\\n        uint256 _strategyCap\\n    ) external payable {\\n        require(msg.sender == crabMigration, \\\"C10\\\");\\n        require(!isInitialized, \\\"C11\\\");\\n\\n        _setStrategyCap(_strategyCap);\\n\\n        uint256 amount = msg.value;\\n\\n        _checkStrategyCap(amount, 0);\\n\\n        // store hedge data from crab V1\\n        timeAtLastHedge = _timeAtLastHedge;\\n        priceAtLastHedge = _priceAtLastHedge;\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\n\\n        isInitialized = true;\\n    }\\n\\n    /**\\n     * @notice transfer vault NFT to new contract\\n     * @dev strategy cap is set to 0 to avoid future deposits\\n     * @param _newStrategy new strategy contract address\\n     */\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\n        _setStrategyCap(0);\\n\\n        emit VaultTransferred(_newStrategy, vaultId);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\n        _setStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice set strategy cap amount\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function _setStrategyCap(uint256 _capAmount) internal {\\n        strategyCap = _capAmount;\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external afterInitialization {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     * @param _poolFee Uniswap pool fee\\n     */\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _poolFee,\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\n     * @param _poolFee Uniswap pool fee\\n\\n     */\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _poolFee,\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"C12\\\");\\n        require(hasRedeemedInShutdown, \\\"C13\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice set nonce to true\\n     * @param _nonce the number to be set true\\n     */\\n    function setNonceTrue(uint256 _nonce) external {\\n        nonces[msg.sender][_nonce] = true;\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"C14\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\n     */\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\n        // Tolerance cannot be more than 20%\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\"C15\\\");\\n\\n        otcPriceTolerance = _otcPriceTolerance;\\n\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"C16\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            // will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            // return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\n\\n            // excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @dev set nonce flag of the trader to true\\n     * @param _trader address of the signer\\n     * @param _nonce number that is to be traded only once\\n     */\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\n        require(!nonces[_trader][_nonce], \\\"C27\\\");\\n        nonces[_trader][_nonce] = true;\\n    }\\n\\n    /**\\n     * @dev view function to get the domain seperator used in signing\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev check the signer and swap tokens in the order\\n     * @param _remainingAmount quantity the manager wants to trade\\n     * @param _clearingPrice the price at which all orders are traded\\n     * @param _order a signed order to swap tokens\\n     */\\n    function _execOrder(\\n        uint256 _remainingAmount,\\n        uint256 _clearingPrice,\\n        Order memory _order\\n    ) internal {\\n        // check that order beats clearing price\\n        if (_order.isBuying) {\\n            require(_clearingPrice <= _order.price, \\\"C17\\\");\\n        } else {\\n            require(_clearingPrice >= _order.price, \\\"C18\\\");\\n        }\\n\\n        _useNonce(_order.trader, _order.nonce);\\n        bytes32 structHash = keccak256(\\n            abi.encode(\\n                _CRAB_BALANCE_TYPEHASH,\\n                _order.bidId,\\n                _order.trader,\\n                _order.quantity,\\n                _order.price,\\n                _order.isBuying,\\n                _order.expiry,\\n                _order.nonce\\n            )\\n        );\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\n        require(offerSigner == _order.trader, \\\"C19\\\");\\n        require(_order.expiry >= block.timestamp, \\\"C20\\\");\\n\\n        // adjust quantity for partial fills\\n        if (_remainingAmount < _order.quantity) {\\n            _order.quantity = _remainingAmount;\\n        }\\n        // weth clearing price for the order\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\n\\n        if (_order.isBuying) {\\n            // trader sends weth and receives oSQTH\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\n            IWETH9(weth).withdraw(wethAmount);\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n        } else {\\n            // trader sends oSQTH and receives weth\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n            // wrap it\\n            IWETH9(weth).deposit{value: wethAmount}();\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\n        }\\n\\n        emit HedgeOTCSingle(\\n            _order.trader, // market maker\\n            _order.bidId,\\n            _order.quantity, // order oSQTH quantity\\n            _order.price, // order price\\n            _order.isBuying, // order direction\\n            _clearingPrice // executed price for order\\n        );\\n    }\\n\\n    /**\\n     * @dev hedge function to reduce delta using an array of signed orders\\n     * @param _totalQuantity quantity the manager wants to trade\\n     * @param _clearingPrice clearing price in weth\\n     * @param _isHedgeBuying direction of hedge trade\\n     * @param _orders an array of signed order to swap tokens\\n     */\\n    function hedgeOTC(\\n        uint256 _totalQuantity,\\n        uint256 _clearingPrice,\\n        bool _isHedgeBuying,\\n        Order[] memory _orders\\n    ) external onlyOwner afterInitialization {\\n        require(_clearingPrice > 0, \\\"C21\\\");\\n        require(_isTimeHedge() || _isPriceHedge(), \\\"C22\\\");\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = _clearingPrice;\\n\\n        uint256 remainingAmount = _totalQuantity;\\n        uint256 prevPrice = _orders[0].price;\\n        uint256 currentPrice = _orders[0].price;\\n        bool isOrderBuying = _orders[0].isBuying;\\n        require(_isHedgeBuying != isOrderBuying, \\\"C23\\\");\\n\\n        // iterate through order array and execute if valid\\n        for (uint256 i; i < _orders.length; ++i) {\\n            currentPrice = _orders[i].price;\\n            require(_orders[i].isBuying == isOrderBuying, \\\"C24\\\");\\n            if (_isHedgeBuying) {\\n                require(currentPrice >= prevPrice, \\\"C25\\\");\\n            } else {\\n                require(currentPrice <= prevPrice, \\\"C25\\\");\\n            }\\n            prevPrice = currentPrice;\\n\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\n\\n            if (remainingAmount > _orders[i].quantity) {\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\n            } else {\\n                break;\\n            }\\n        }\\n\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\n    }\\n\\n    /**\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\n     * @param _price clearing price provided by manager\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\n     */\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\n        // Get twap\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n\\n        if (_isHedgeBuying) {\\n            require(\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\n                \\\"Price too high relative to Uniswap twap.\\\"\\n            );\\n        } else {\\n            require(\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\n                \\\"Price too low relative to Uniswap twap.\\\"\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\n        require(!isShutdown, \\\"C26\\\");\\n\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n        );\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     */\\n    function _isTimeHedge() internal view returns (bool) {\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge() internal view returns (bool) {\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge() external view returns (bool) {\\n        return _isPriceHedge();\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkTimeHedge() external view returns (bool) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/drafts/EIP712.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = _getChainId();\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n        return keccak256(\\n            abi.encode(\\n                typeHash,\\n                name,\\n                version,\\n                _getChainId(),\\n                address(this)\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/cryptography/ECDSA.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        // Check the signature length\\n        if (signature.length != 65) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        }\\n\\n        // Divide the signature in r, s and v variables\\n        bytes32 r;\\n        bytes32 s;\\n        uint8 v;\\n\\n        // ecrecover takes the signature parameters, and the only way to get them\\n        // currently is to use assembly.\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            r := mload(add(signature, 0x20))\\n            s := mload(add(signature, 0x40))\\n            v := byte(0, mload(add(signature, 0x60)))\\n        }\\n\\n        return recover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n        require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n        return signer;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * replicates the behavior of the\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n     * JSON-RPC method.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\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) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/periphery/ShortHelper.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"contracts/strategy/CrabHelper.sol\": {\n            \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {ICrabStrategyV2} from \\\"../interfaces/ICrabStrategyV2.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {StrategySwap} from \\\"./helper/StrategySwap.sol\\\";\\n\\n/**\\n * @dev CrabHelper contract\\n * @notice Contract for Crab helper functions\\n * @author Opyn team\\n */\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\n    using Address for address payable;\\n\\n    address public immutable crab;\\n    address public immutable weth;\\n\\n    event FlashDepositERC20(\\n        address indexed depositor,\\n        address depositedERC20,\\n        uint256 depositedAmount,\\n        uint256 depositedEthAmount,\\n        uint256 crabAmount,\\n        uint256 returnedEth\\n    );\\n\\n    event FlashWithdrawERC20(\\n        address indexed withdrawer,\\n        address withdrawnERC20,\\n        uint256 withdrawnAmount,\\n        uint256 withdrawnEthAmount,\\n        uint256 crabAmount\\n    );\\n\\n    /**\\n     * @notice constructor\\n     * @param _crab address of crabV2 contract\\n     * @param _swapRouter address of Uniswap swap router\\n     */\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\n        require(_crab != address(0), \\\"Invalid crab address\\\");\\n\\n        crab = _crab;\\n        weth = ICrabStrategyV2(_crab).weth();\\n    }\\n\\n    /**\\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\\n     * @param _ethToDeposit amount of ETH to deposit\\n     * @param _amountIn amount of ERC20 token to swap for weth\\n     * @param _minEthToGet min amount of ETH to receive in the swap\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     * @param _tokenIn ERC20 token to pay\\n     */\\n    function flashDepositERC20(\\n        uint256 _ethToDeposit,\\n        uint256 _amountIn,\\n        uint256 _minEthToGet,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee,\\n        address _tokenIn\\n    ) external nonReentrant {\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\\n\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\\n\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\n\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\n\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\n\\n        if (address(this).balance > 0) {\\n            payable(msg.sender).sendValue(address(this).balance);\\n        }\\n    }\\n\\n    /**\\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\\n     * @param _crabAmount amount of crab shares to withdraw\\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\\n     * @param _tokenOut ERC20 token to receive\\n     * @param _minAmountOut min amount of ERC20 to receive\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     */\\n    function flashWithdrawERC20(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        address _tokenOut,\\n        uint256 _minAmountOut,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee\\n    ) external nonReentrant {\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\n\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\\n\\n        uint256 ethBalance = address(this).balance;\\n        IWETH9(weth).deposit{value: ethBalance}();\\n        uint256 tokenReceived = _swapExactInputSingle(\\n            weth,\\n            _tokenOut,\\n            address(this),\\n            msg.sender,\\n            ethBalance,\\n            _minAmountOut,\\n            _erc20Fee\\n        );\\n\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crab, \\\"Cannot receive eth\\\");\\n    }\\n}\\n\"\n        },\n        \"contracts/interfaces/ICrabStrategyV2.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\ninterface ICrabStrategyV2 {\\n    function wPowerPerp() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\\n\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external;\\n}\\n\"\n        },\n        \"contracts/strategy/helper/StrategySwap.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract StrategySwap {\\n    ISwapRouter public immutable swapRouter;\\n\\n    constructor(address _swapRouter) {\\n        require(_swapRouter != address(0), \\\"invalid swap router address\\\");\\n        swapRouter = ISwapRouter(_swapRouter);\\n    }\\n\\n    /**\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _from from which user we are selling\\n     * @param _to Recipient to get the tokens\\n     * @param _amountIn Exact amount to sell\\n     * @param _minAmountOut Minimum amount to be paid\\n     * @param _fee pool fee\\n     * @return amountOut The amount of WETH9 received.\\n     */\\n    function _swapExactInputSingle(\\n        address _tokenIn,\\n        address _tokenOut,\\n        address _from,\\n        address _to,\\n        uint256 _amountIn,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) internal returns (uint256 amountOut) {\\n        // _from must approve this contract\\n\\n        // Transfer the specified amount of tokenIn to this contract.\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\n\\n        // Approve the router to spend tokenIn.\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\n\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\n            tokenIn: _tokenIn,\\n            tokenOut: _tokenOut,\\n            fee: _fee,\\n            recipient: _to,\\n            deadline: block.timestamp,\\n            amountIn: _amountIn,\\n            amountOutMinimum: _minAmountOut,\\n            sqrtPriceLimitX96: 0\\n        });\\n\\n        // The call to `exactInputSingle` executes the swap.\\n        amountOut = swapRouter.exactInputSingle(params);\\n    }\\n}\\n\"\n        },\n        \"contracts/strategy/CrabMigration.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport {IEulerExec, IDToken} from \\\"../interfaces/IEuler.sol\\\";\\nimport {WETH9} from \\\"../external/WETH9.sol\\\";\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// contract\\nimport {CrabStrategyV2} from \\\"./CrabStrategyV2.sol\\\";\\nimport {CrabStrategy} from \\\"./CrabStrategy.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * Migration Error Codes:\\n * M1: Migration already happened\\n * M2: Migration has not yet happened\\n * M3: msg.sender is not Euler Mainnet Contract\\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\\n * M5: Can't withdraw more than you own\\n * M6: Not enough ETH to repay the loan\\n * M7: Invalid crabV2 address\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\n * M10: Wrong migration function, use flashMigrateFromV1toV2\\n * M11: crabV2 address not yet set\\n */\\n\\n/**\\n * @dev CrabMigration contract\\n * @notice Contract for Migrating from Crab V1 to Crab V2\\n * @author Opyn team\\n */\\ncontract CrabMigration is Ownable {\\n    using SafeERC20 for IERC20;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    mapping(address => uint256) public sharesDeposited;\\n    bool public isMigrated;\\n\\n    address payable public crabV1;\\n    address payable public crabV2;\\n    address public immutable euler;\\n    address public immutable weth;\\n\\n    address immutable EULER_MAINNET;\\n    address immutable dToken;\\n    address immutable wPowerPerp;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    struct BatchMigrate {\\n        uint256 strategyCap;\\n    }\\n\\n    struct FlashMigrateV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFee;\\n    }\\n\\n    struct FlashMigrateAndBuyV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 withdrawMaxEthToPay;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFeeFlashDeposit;\\n    }\\n\\n    enum FLASH_SOURCE {\\n        BATCH_MIGRATE,\\n        FLASH_MIGRATE_V1_TO_V2,\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\n    }\\n\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\\n\\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\\n\\n    modifier beforeMigration() {\\n        require(!isMigrated, \\\"M1\\\");\\n        _;\\n    }\\n\\n    modifier afterMigration() {\\n        require(isMigrated, \\\"M2\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialized() {\\n        require(crabV2 != address(0), \\\"M11\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice migration constructor\\n     * @param _crabV1 address of crab V1\\n     * @param _weth address of weth\\n     * @param _eulerExec address of euler exec contract\\n     * @param _dToken address of euler liability token\\n     * @param _eulerMainnet address of euler deployment on mainnet\\n     */\\n    constructor(\\n        address payable _crabV1,\\n        address _weth,\\n        address _eulerExec,\\n        address _dToken,\\n        address _eulerMainnet\\n    ) {\\n        require(_eulerExec != address(0), \\\"invalid _eulerExec address\\\");\\n        require(_dToken != address(0), \\\"invalid _dToken address\\\");\\n        require(_eulerMainnet != address(0), \\\"invalid _eulerMainnet address\\\");\\n        require(_weth != address(0), \\\"invalid _weth address\\\");\\n        require(_crabV1 != address(0), \\\"invalid _crabv1 address\\\");\\n        require(IDToken(_dToken).underlyingAsset() == _weth, \\\"dToken underlying asset should be weth\\\");\\n\\n        crabV1 = _crabV1;\\n        euler = _eulerExec;\\n        EULER_MAINNET = _eulerMainnet;\\n        weth = _weth;\\n        dToken = _dToken;\\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\\n    }\\n\\n    /**\\n     * @notice set the crabV2 address\\n     * @param _crabV2 address of crab V2\\n     */\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\n        require(_crabV2 != address(0), \\\"M7\\\");\\n        crabV2 = _crabV2;\\n    }\\n\\n    /**\\n     * @notice deposit crab V1 shares in the pool for migration\\n     * @param _amount amount of crabV1 shares to deposit\\n     */\\n    function depositV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] += _amount;\\n\\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\\n\\n        emit DepositV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice withdraw crab V1 shares in the pool before migration\\n     * @param _amount amount of V1 shares to withdraw\\n     */\\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\\n\\n        emit WithdrawV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\\n     * the V2 contract at the same collateral ratio as the V1 contract\\n     * @param _strategyCap strategy cap in ETH\\n     */\\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\\n        // 1. update isMigrated\\n        isMigrated = true;\\n\\n        // 2. flash floan eth from euler eq to amt\\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: amountEthToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Euler callback function\\n     * @param encodedData callback data\\n     */\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\n        require(msg.sender == EULER_MAINNET, \\\"M3\\\");\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        // 1. borrow weth\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\n        WETH9(weth).withdraw(data.amountToBorrow);\\n\\n        // 2. callback\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\n\\n        // 3. repay the weth\\n        WETH9(weth).deposit{value: data.amountToBorrow}();\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     * @notice callback function for flash actions\\n     * @param _initiator address of original function caller\\n     * @param _amount  amount to pay back for flashswap\\n     * @param _callSource identifier for which function triggered callback\\n     * @param _calldata arbitrary data attached to callback\\n\\n     */\\n    function _flashCallback(\\n        address _initiator,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\\n\\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n\\n            // 2. mint osqth in crab V2\\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\\n                wSqueethToMint,\\n                crabV1Balance,\\n                timeAtLastHedge,\\n                priceAtLastHedge,\\n                data.strategyCap\\n            );\\n\\n            // 3. call withdraw from crab V1\\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\n\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n\\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\\n\\n            // flash deposit remaining ETH, otherwise refund\\n            // if CR1 = CR2 ethToFlashDeposit should be 0\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFee\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n            // send back V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\\n\\n            // find crab amount for contract's sqth balance\\n            // remaining crab can be withdrawn using flash withdraw\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\n\\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\\n\\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\n            require(address(this).balance >= _amount, \\\"M6\\\");\\n\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFeeFlashDeposit\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n\\n            // send V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back the excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares\\n     */\\n    function claimV2Shares() external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        sharesDeposited[msg.sender] = 0;\\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares and flash withdraw from crab V2\\n     * @param _amountToWithdraw V2 shares to claim\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee Uniswap pool fee for flash withdraw\\n     */\\n    function claimAndWithdraw(\\n        uint256 _amountToWithdraw,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        require(_amountToWithdraw <= amountV1Deposited, \\\"M5\\\");\\n\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\\n\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\n\\n        // send eth to user\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice view details of flash migration for specified amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function flashMigrationDetails(uint256 _v1Shares)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return _flashMigrationDetails(_v1Shares);\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\n     * @param _poolFee uniswap pool fee for flash deposit\\n     */\\n    function flashMigrateFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(isFlashOnlyMigrate, \\\"M9\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: ethNeededForV2,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateV1toV2({\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFee: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\\n     */\\n    function flashMigrateAndWithdrawFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint256 _ethToBorrow,\\n        uint256 _withdrawMaxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(!isFlashOnlyMigrate, \\\"M10\\\");\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\"M8\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: _ethToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateAndBuyV1toV2({\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFeeFlashDeposit: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice get migration details for given amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function _flashMigrationDetails(uint256 _v1Shares)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\\n\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\\n\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \\\"M4\\\");\\n    }\\n}\\n\"\n        },\n        \"contracts/interfaces/IEuler.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\ninterface IEulerExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IDToken {\\n    function underlyingAsset() external view returns (address);\\n\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\"\n        },\n        \"contracts/external/WETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\n\\ncontract WETH9 {\\n    string public name = \\\"Wrapped Ether\\\";\\n    string public symbol = \\\"WETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        payable(msg.sender).transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockErc20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract MockErc20 is ERC20, Ownable {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external onlyOwner {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockWSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockUniswapV3Pool.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockEulerDToken.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockEulerDToken {\\n    ERC20 weth;\\n\\n    constructor(address _weth) {\\n        weth = ERC20(_weth);\\n    }\\n\\n    function borrow(uint256, uint256 amount) external {\\n        weth.transfer(msg.sender, amount);\\n    }\\n\\n    function repay(uint256, uint256 amount) external {\\n        weth.transferFrom(msg.sender, address(this), amount);\\n    }\\n\\n    function underlyingAsset() external view returns (address) {\\n        return address(weth);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockCrab.sol\": {\n            \"content\": \"pragma solidity =0.7.6;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockCrab is ERC20 {\\n    address operator;\\n    uint256 vaultId;\\n    uint256 collateral;\\n    uint256 short;\\n    address public wPowerPerp;\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    function setVaultDetails(\\n        uint256 _vaultId,\\n        uint256 _collateral,\\n        uint256 _short\\n    ) external {\\n        vaultId = _vaultId;\\n        collateral = _collateral;\\n        short = _short;\\n    }\\n\\n    function getVaultDetails()\\n        external\\n        view\\n        returns (\\n            address,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return (operator, vaultId, collateral, short);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Strings.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockUniPositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/test/ControllerAccessTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n        },\n        \"contracts/periphery/ControllerHelper.sol\": {\n            \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n        },\n        \"contracts/periphery/UniswapControllerHelper.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n        },\n        \"contracts/periphery/EulerControllerHelper.sol\": {\n            \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n        },\n        \"contracts/test/ControllerTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n        },\n        \"contracts/core/ShortPowerPerp.sol\": {\n            \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"contracts/core/WPowerPerp.sol\": {\n            \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockController.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"C3\\\");\\n\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n        },\n        \"contracts/import/Uni.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"contracts/test/CastingTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n        },\n        \"contracts/test/ABDKTester.sol\": {\n            \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n        }\n    },\n    \"settings\": {\n        \"optimizer\": {\n            \"enabled\": true,\n            \"runs\": 800\n        },\n        \"outputSelection\": {\n            \"*\": {\n                \"*\": [\n                    \"abi\",\n                    \"evm.bytecode\",\n                    \"evm.deployedBytecode\",\n                    \"evm.methodIdentifiers\",\n                    \"metadata\",\n                    \"devdoc\",\n                    \"userdoc\",\n                    \"storageLayout\",\n                    \"evm.gasEstimates\"\n                ],\n                \"\": [\"ast\"]\n            }\n        },\n        \"metadata\": {\n            \"useLiteralContent\": true\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/.chainId",
    "content": "1"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/ABDKMath64x64.json",
    "content": "{\n  \"address\": \"0x21A8D15322C257Abd2b22a56eDde758398be0F32\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"x\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"y\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"divu\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"x\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"name\": \"exp_2\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"x\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"name\": \"log_2\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x86f31b501dd7bb2b50f0734c402ecb3b42082a668cea1aa7d1b6cbc27b760e61\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xa3cB04d8BD927EEC8826BD77b7C71abE3d29c081\",\n    \"contractAddress\": \"0x21A8D15322C257Abd2b22a56eDde758398be0F32\",\n    \"transactionIndex\": 126,\n    \"gasUsed\": \"941465\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x738261ad46f621f353d1fd86ae62362fb4805c8599c51d1767164370e9156bef\",\n    \"transactionHash\": \"0x86f31b501dd7bb2b50f0734c402ecb3b42082a668cea1aa7d1b6cbc27b760e61\",\n    \"logs\": [],\n    \"blockNumber\": 13982526,\n    \"cumulativeGasUsed\": \"9014540\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"d97d3d4b09e0d70518330d405a7dd9ff\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"x\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"y\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"divu\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"int128\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"x\\\",\\\"type\\\":\\\"int128\\\"}],\\\"name\\\":\\\"exp_2\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"int128\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"x\\\",\\\"type\\\":\\\"int128\\\"}],\\\"name\\\":\\\"log_2\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"int128\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"divu(uint256,uint256)\\\":{\\\"params\\\":{\\\"x\\\":\\\"unsigned 256-bit integer number\\\",\\\"y\\\":\\\"unsigned 256-bit integer number\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"signed 64.64-bit fixed point number\\\"}},\\\"exp_2(int128)\\\":{\\\"params\\\":{\\\"x\\\":\\\"signed 64.64-bit fixed point number\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"signed 64.64-bit fixed point number\\\"}},\\\"log_2(int128)\\\":{\\\"params\\\":{\\\"x\\\":\\\"signed 64.64-bit fixed point number\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"signed 64.64-bit fixed point number\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"divu(uint256,uint256)\\\":{\\\"notice\\\":\\\"Calculate x / y rounding towards zero, where x and y are unsigned 256-bit integer numbers.  Revert on overflow or when y is zero.\\\"},\\\"exp_2(int128)\\\":{\\\"notice\\\":\\\"Calculate binary exponent of x.  Revert on overflow.\\\"},\\\"log_2(int128)\\\":{\\\"notice\\\":\\\"Calculate binary logarithm of x.  Revert if x <= 0.\\\"}},\\\"notice\\\":\\\"Smart contract library of mathematical functions operating with signed 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is basically a simple fraction whose numerator is signed 128-bit integer and denominator is 2^64.  As long as denominator is always the same, there is no need to store it, thus in Solidity signed 64.64-bit fixed point numbers are represented by int128 type holding only the numerator. Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4 Changes - some function visibility switched to public, solidity version set to 0.7.x Changes (cont) - revert strings added solidity version set to ^0.7.0\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/libs/ABDKMath64x64.sol\\\":\\\"ABDKMath64x64\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"contracts/libs/ABDKMath64x64.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: BSD-4-Clause\\\\n/*\\\\n * ABDK Math 64.64 Smart Contract Library.  Copyright \\\\u00a9 2019 by ABDK Consulting.\\\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\\\n * Copyright (c) 2019, ABDK Consulting\\\\n *\\\\n * All rights reserved.\\\\n *\\\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\\\n *\\\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\\\n */\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * Smart contract library of mathematical functions operating with signed\\\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\\\n * represented by int128 type holding only the numerator.\\\\n *\\\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\\\n * Changes (cont) - revert strings added\\\\n * solidity version set to ^0.7.0\\\\n */\\\\nlibrary ABDKMath64x64 {\\\\n    /*\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * -2^127\\\\n     */\\\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\\\n\\\\n    /*\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * 2^127-1\\\\n     */\\\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @param y signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\\\n        int256 result = (int256(x) * y) >> 64;\\\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\\\\\"MUL-OVUF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64 fixed point number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 256-bit integer number\\\\n     */\\\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\\\n        if (y == 0) return 0;\\\\n\\\\n        require(x >= 0, \\\\\\\"MULU-X0\\\\\\\");\\\\n\\\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\\\n        uint256 hi = uint256(x) * (y >> 128);\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"MULU-OF1\\\\\\\");\\\\n        hi <<= 64;\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\\\\\"MULU-OF2\\\\\\\");\\\\n        return hi + lo;\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\\\n        require(y != 0, \\\\\\\"DIVU-INF\\\\\\\");\\\\n        uint128 result = divuu(x, y);\\\\n        require(result <= uint128(MAX_64x64), \\\\\\\"DIVU-OF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function log_2(int128 x) public pure returns (int128) {\\\\n        require(x > 0, \\\\\\\"LOG_2-X0\\\\\\\");\\\\n\\\\n        int256 msb = 0;\\\\n        int256 xc = x;\\\\n        if (xc >= 0x10000000000000000) {\\\\n            xc >>= 64;\\\\n            msb += 64;\\\\n        }\\\\n        if (xc >= 0x100000000) {\\\\n            xc >>= 32;\\\\n            msb += 32;\\\\n        }\\\\n        if (xc >= 0x10000) {\\\\n            xc >>= 16;\\\\n            msb += 16;\\\\n        }\\\\n        if (xc >= 0x100) {\\\\n            xc >>= 8;\\\\n            msb += 8;\\\\n        }\\\\n        if (xc >= 0x10) {\\\\n            xc >>= 4;\\\\n            msb += 4;\\\\n        }\\\\n        if (xc >= 0x4) {\\\\n            xc >>= 2;\\\\n            msb += 2;\\\\n        }\\\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n        int256 result = (msb - 64) << 64;\\\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\\\n            ux *= ux;\\\\n            uint256 b = ux >> 255;\\\\n            ux >>= 127 + b;\\\\n            result += bit * int256(b);\\\\n        }\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary exponent of x.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function exp_2(int128 x) public pure returns (int128) {\\\\n        require(x < 0x400000000000000000, \\\\\\\"EXP_2-OF\\\\\\\"); // Overflow\\\\n\\\\n        if (x < -0x400000000000000000) return 0; // Underflow\\\\n\\\\n        uint256 result = 0x80000000000000000000000000000000;\\\\n\\\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\\\n\\\\n        result >>= uint256(63 - (x >> 64));\\\\n        require(result <= uint256(MAX_64x64));\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 64.64-bit fixed point number\\\\n     */\\\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\\\n        require(y != 0);\\\\n\\\\n        uint256 result;\\\\n\\\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\\\n        else {\\\\n            uint256 msb = 192;\\\\n            uint256 xc = x >> 192;\\\\n            if (xc >= 0x100000000) {\\\\n                xc >>= 32;\\\\n                msb += 32;\\\\n            }\\\\n            if (xc >= 0x10000) {\\\\n                xc >>= 16;\\\\n                msb += 16;\\\\n            }\\\\n            if (xc >= 0x100) {\\\\n                xc >>= 8;\\\\n                msb += 8;\\\\n            }\\\\n            if (xc >= 0x10) {\\\\n                xc >>= 4;\\\\n                msb += 4;\\\\n            }\\\\n            if (xc >= 0x4) {\\\\n                xc >>= 2;\\\\n                msb += 2;\\\\n            }\\\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF1\\\\\\\");\\\\n\\\\n            uint256 hi = result * (y >> 128);\\\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\\\n\\\\n            uint256 xh = x >> 192;\\\\n            uint256 xl = x << 64;\\\\n\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n            lo = hi << 128;\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n\\\\n            assert(xh == hi >> 128);\\\\n\\\\n            result += xl / y;\\\\n        }\\\\n\\\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF2\\\\\\\");\\\\n        return uint128(result);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x56efa7c16e4fffb37ad80af15bd042d9f92532a4553d6b12915e3fa21609ad66\\\",\\\"license\\\":\\\"BSD-4-Clause\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x611035610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80632cbbdee514610050578063fc193cf214610087578063fc505d37146100a7575b600080fd5b6100706004803603602081101561006657600080fd5b5035600f0b6100ca565b60408051600f9290920b8252519081900360200190f35b6100706004803603602081101561009d57600080fd5b5035600f0b6101f8565b610070600480360360408110156100bd57600080fd5b5080359060200135610d19565b60008082600f0b13610123576040805162461bcd60e51b815260206004820152600860248201527f4c4f475f322d5830000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000600f83900b680100000000000000008112610142576040918201911d5b6401000000008112610156576020918201911d5b620100008112610168576010918201911d5b6101008112610179576008918201911d5b60108112610189576004918201911d5b60048112610199576002918201911d5b600281126101a8576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b60008113156101eb5790800260ff81901c8281029390930192607f011c9060011d6101c5565b509093505050505b919050565b60006840000000000000000082600f0b1261025a576040805162461bcd60e51b815260206004820152600860248201527f4558505f322d4f46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b683fffffffffffffffff1982600f0b1215610277575060006101f3565b6f8000000000000000000000000000000060006780000000000000008416600f0b13156102b55770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b60008367400000000000000016600f0b13156102e2577001306fe0a31b7152de8d5a46305c85edec0260801c5b60008367200000000000000016600f0b131561030f577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b60008367100000000000000016600f0b131561033c5770010b5586cf9890f6298b92b71842a983630260801c5b60008367080000000000000016600f0b1315610369577001059b0d31585743ae7c548eb68ca417fd0260801c5b60008367040000000000000016600f0b131561039657700102c9a3e778060ee6f7caca4f7a29bde80260801c5b60008367020000000000000016600f0b13156103c35770010163da9fb33356d84a66ae336dcdfa3f0260801c5b60008367010000000000000016600f0b13156103f057700100b1afa5abcbed6129ab13ec11dc95430260801c5b600083668000000000000016600f0b131561041c5770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600083664000000000000016600f0b1315610448577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600083662000000000000016600f0b131561047457700100162f3904051fa128bca9c55c31e5df0260801c5b600083661000000000000016600f0b13156104a0577001000b175effdc76ba38e31671ca9397250260801c5b600083660800000000000016600f0b13156104cc57700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600083660400000000000016600f0b13156104f85770010002c5cc37da9491d0985c348c68e7b30260801c5b600083660200000000000016600f0b1315610524577001000162e525ee054754457d59952920260260801c5b600083660100000000000016600f0b13156105505770010000b17255775c040618bf4a4ade83fc0260801c5b6000836580000000000016600f0b131561057b577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6000836540000000000016600f0b13156105a657700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6000836520000000000016600f0b13156105d15770010000162e43f4f831060e02d839a9d16d0260801c5b6000836510000000000016600f0b13156105fc57700100000b1721bcfc99d9f890ea069117630260801c5b6000836508000000000016600f0b13156106275770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6000836504000000000016600f0b1315610652577001000002c5c863b73f016468f6bac5ca2b0260801c5b6000836502000000000016600f0b131561067d57700100000162e430e5a18f6119e3c02282a50260801c5b6000836501000000000016600f0b13156106a8577001000000b1721835514b86e6d96efd1bfe0260801c5b60008364800000000016600f0b13156106d257700100000058b90c0b48c6be5df846c5b2ef0260801c5b60008364400000000016600f0b13156106fc5770010000002c5c8601cc6b9e94213c72737a0260801c5b60008364200000000016600f0b1315610726577001000000162e42fff037df38aa2b219f060260801c5b60008364100000000016600f0b13156107505770010000000b17217fba9c739aa5819f44f90260801c5b60008364080000000016600f0b131561077a577001000000058b90bfcdee5acd3c1cedc8230260801c5b60008364040000000016600f0b13156107a457700100000002c5c85fe31f35a6a30da1be500260801c5b60008364020000000016600f0b13156107ce5770010000000162e42ff0999ce3541b9fffcf0260801c5b60008364010000000016600f0b13156107f857700100000000b17217f80f4ef5aadda455540260801c5b600083638000000016600f0b13156108215770010000000058b90bfbf8479bd5a81b51ad0260801c5b600083634000000016600f0b131561084a577001000000002c5c85fdf84bd62ae30a74cc0260801c5b600083632000000016600f0b131561087357700100000000162e42fefb2fed257559bdaa0260801c5b600083631000000016600f0b131561089c577001000000000b17217f7d5a7716bba4a9ae0260801c5b600083630800000016600f0b13156108c557700100000000058b90bfbe9ddbac5e109cce0260801c5b600083630400000016600f0b13156108ee5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600083630200000016600f0b1315610917577001000000000162e42fefa494f1478fde050260801c5b600083630100000016600f0b13156109405770010000000000b17217f7d20cf927c8e94c0260801c5b6000836280000016600f0b1315610968577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6000836240000016600f0b131561099057700100000000002c5c85fdf477b662b269450260801c5b6000836220000016600f0b13156109b85770010000000000162e42fefa3ae53369388c0260801c5b6000836210000016600f0b13156109e057700100000000000b17217f7d1d351a389d400260801c5b6000836208000016600f0b1315610a085770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6000836204000016600f0b1315610a30577001000000000002c5c85fdf4741bea6e77e0260801c5b6000836202000016600f0b1315610a5857700100000000000162e42fefa39fe95583c20260801c5b6000836201000016600f0b1315610a80577001000000000000b17217f7d1cfb72b45e10260801c5b60008361800016600f0b1315610aa757700100000000000058b90bfbe8e7cc35c3f00260801c5b60008361400016600f0b1315610ace5770010000000000002c5c85fdf473e242ea380260801c5b60008361200016600f0b1315610af5577001000000000000162e42fefa39f02b772c0260801c5b60008361100016600f0b1315610b1c5770010000000000000b17217f7d1cf7d83c1a0260801c5b60008361080016600f0b1315610b43577001000000000000058b90bfbe8e7bdcbe2e0260801c5b60008361040016600f0b1315610b6a57700100000000000002c5c85fdf473dea871f0260801c5b60008361020016600f0b1315610b915770010000000000000162e42fefa39ef44d910260801c5b60008361010016600f0b1315610bb857700100000000000000b17217f7d1cf79e9490260801c5b600083608016600f0b1315610bde5770010000000000000058b90bfbe8e7bce5440260801c5b600083604016600f0b1315610c04577001000000000000002c5c85fdf473de6eca0260801c5b600083602016600f0b1315610c2a57700100000000000000162e42fefa39ef366f0260801c5b600083601016600f0b1315610c50577001000000000000000b17217f7d1cf79afa0260801c5b600083600816600f0b1315610c7657700100000000000000058b90bfbe8e7bcd6d0260801c5b600083600416600f0b1315610c9c5770010000000000000002c5c85fdf473de6b20260801c5b600083600216600f0b1315610cc2577001000000000000000162e42fefa39ef3580260801c5b600083600116600f0b1315610ce85770010000000000000000b17217f7d1cf79ab0260801c5b600f83810b60401d603f03900b1c6f7fffffffffffffffffffffffffffffff811115610d1357600080fd5b92915050565b600081610d6d576040805162461bcd60e51b815260206004820152600860248201527f444956552d494e46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000610d798484610df9565b90506f7fffffffffffffffffffffffffffffff6fffffffffffffffffffffffffffffffff82161115610df2576040805162461bcd60e51b815260206004820152600760248201527f444956552d4f4600000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b9392505050565b600081610e0557600080fd5b600077ffffffffffffffffffffffffffffffffffffffffffffffff8411610e3b5782604085901b81610e3357fe5b049050610f9a565b60c084811c6401000000008110610e54576020918201911c5b620100008110610e66576010918201911c5b6101008110610e77576008918201911c5b60108110610e87576004918201911c5b60048110610e97576002918201911c5b60028110610ea6576001820191505b60bf820360018603901c6001018260ff0387901b81610ec157fe5b0492506fffffffffffffffffffffffffffffffff831115610f29576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46310000000000000000000000000000000000000000000000604482015290519081900360640190fd5b608085901c83026fffffffffffffffffffffffffffffffff8616840260c088901c604089901b82811015610f5e576001820391505b608084901b92900382811015610f75576001820391505b829003608084901c8214610f8557fe5b888181610f8e57fe5b04870196505050505050505b6fffffffffffffffffffffffffffffffff811115610df2576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46320000000000000000000000000000000000000000000000604482015290519081900360640190fdfea264697066735822122040574cb227dea1d1a5db4fb4ab0552095e5133a47a8b45993e447ebd0471743a64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80632cbbdee514610050578063fc193cf214610087578063fc505d37146100a7575b600080fd5b6100706004803603602081101561006657600080fd5b5035600f0b6100ca565b60408051600f9290920b8252519081900360200190f35b6100706004803603602081101561009d57600080fd5b5035600f0b6101f8565b610070600480360360408110156100bd57600080fd5b5080359060200135610d19565b60008082600f0b13610123576040805162461bcd60e51b815260206004820152600860248201527f4c4f475f322d5830000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000600f83900b680100000000000000008112610142576040918201911d5b6401000000008112610156576020918201911d5b620100008112610168576010918201911d5b6101008112610179576008918201911d5b60108112610189576004918201911d5b60048112610199576002918201911d5b600281126101a8576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b60008113156101eb5790800260ff81901c8281029390930192607f011c9060011d6101c5565b509093505050505b919050565b60006840000000000000000082600f0b1261025a576040805162461bcd60e51b815260206004820152600860248201527f4558505f322d4f46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b683fffffffffffffffff1982600f0b1215610277575060006101f3565b6f8000000000000000000000000000000060006780000000000000008416600f0b13156102b55770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b60008367400000000000000016600f0b13156102e2577001306fe0a31b7152de8d5a46305c85edec0260801c5b60008367200000000000000016600f0b131561030f577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b60008367100000000000000016600f0b131561033c5770010b5586cf9890f6298b92b71842a983630260801c5b60008367080000000000000016600f0b1315610369577001059b0d31585743ae7c548eb68ca417fd0260801c5b60008367040000000000000016600f0b131561039657700102c9a3e778060ee6f7caca4f7a29bde80260801c5b60008367020000000000000016600f0b13156103c35770010163da9fb33356d84a66ae336dcdfa3f0260801c5b60008367010000000000000016600f0b13156103f057700100b1afa5abcbed6129ab13ec11dc95430260801c5b600083668000000000000016600f0b131561041c5770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600083664000000000000016600f0b1315610448577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600083662000000000000016600f0b131561047457700100162f3904051fa128bca9c55c31e5df0260801c5b600083661000000000000016600f0b13156104a0577001000b175effdc76ba38e31671ca9397250260801c5b600083660800000000000016600f0b13156104cc57700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600083660400000000000016600f0b13156104f85770010002c5cc37da9491d0985c348c68e7b30260801c5b600083660200000000000016600f0b1315610524577001000162e525ee054754457d59952920260260801c5b600083660100000000000016600f0b13156105505770010000b17255775c040618bf4a4ade83fc0260801c5b6000836580000000000016600f0b131561057b577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6000836540000000000016600f0b13156105a657700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6000836520000000000016600f0b13156105d15770010000162e43f4f831060e02d839a9d16d0260801c5b6000836510000000000016600f0b13156105fc57700100000b1721bcfc99d9f890ea069117630260801c5b6000836508000000000016600f0b13156106275770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6000836504000000000016600f0b1315610652577001000002c5c863b73f016468f6bac5ca2b0260801c5b6000836502000000000016600f0b131561067d57700100000162e430e5a18f6119e3c02282a50260801c5b6000836501000000000016600f0b13156106a8577001000000b1721835514b86e6d96efd1bfe0260801c5b60008364800000000016600f0b13156106d257700100000058b90c0b48c6be5df846c5b2ef0260801c5b60008364400000000016600f0b13156106fc5770010000002c5c8601cc6b9e94213c72737a0260801c5b60008364200000000016600f0b1315610726577001000000162e42fff037df38aa2b219f060260801c5b60008364100000000016600f0b13156107505770010000000b17217fba9c739aa5819f44f90260801c5b60008364080000000016600f0b131561077a577001000000058b90bfcdee5acd3c1cedc8230260801c5b60008364040000000016600f0b13156107a457700100000002c5c85fe31f35a6a30da1be500260801c5b60008364020000000016600f0b13156107ce5770010000000162e42ff0999ce3541b9fffcf0260801c5b60008364010000000016600f0b13156107f857700100000000b17217f80f4ef5aadda455540260801c5b600083638000000016600f0b13156108215770010000000058b90bfbf8479bd5a81b51ad0260801c5b600083634000000016600f0b131561084a577001000000002c5c85fdf84bd62ae30a74cc0260801c5b600083632000000016600f0b131561087357700100000000162e42fefb2fed257559bdaa0260801c5b600083631000000016600f0b131561089c577001000000000b17217f7d5a7716bba4a9ae0260801c5b600083630800000016600f0b13156108c557700100000000058b90bfbe9ddbac5e109cce0260801c5b600083630400000016600f0b13156108ee5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600083630200000016600f0b1315610917577001000000000162e42fefa494f1478fde050260801c5b600083630100000016600f0b13156109405770010000000000b17217f7d20cf927c8e94c0260801c5b6000836280000016600f0b1315610968577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6000836240000016600f0b131561099057700100000000002c5c85fdf477b662b269450260801c5b6000836220000016600f0b13156109b85770010000000000162e42fefa3ae53369388c0260801c5b6000836210000016600f0b13156109e057700100000000000b17217f7d1d351a389d400260801c5b6000836208000016600f0b1315610a085770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6000836204000016600f0b1315610a30577001000000000002c5c85fdf4741bea6e77e0260801c5b6000836202000016600f0b1315610a5857700100000000000162e42fefa39fe95583c20260801c5b6000836201000016600f0b1315610a80577001000000000000b17217f7d1cfb72b45e10260801c5b60008361800016600f0b1315610aa757700100000000000058b90bfbe8e7cc35c3f00260801c5b60008361400016600f0b1315610ace5770010000000000002c5c85fdf473e242ea380260801c5b60008361200016600f0b1315610af5577001000000000000162e42fefa39f02b772c0260801c5b60008361100016600f0b1315610b1c5770010000000000000b17217f7d1cf7d83c1a0260801c5b60008361080016600f0b1315610b43577001000000000000058b90bfbe8e7bdcbe2e0260801c5b60008361040016600f0b1315610b6a57700100000000000002c5c85fdf473dea871f0260801c5b60008361020016600f0b1315610b915770010000000000000162e42fefa39ef44d910260801c5b60008361010016600f0b1315610bb857700100000000000000b17217f7d1cf79e9490260801c5b600083608016600f0b1315610bde5770010000000000000058b90bfbe8e7bce5440260801c5b600083604016600f0b1315610c04577001000000000000002c5c85fdf473de6eca0260801c5b600083602016600f0b1315610c2a57700100000000000000162e42fefa39ef366f0260801c5b600083601016600f0b1315610c50577001000000000000000b17217f7d1cf79afa0260801c5b600083600816600f0b1315610c7657700100000000000000058b90bfbe8e7bcd6d0260801c5b600083600416600f0b1315610c9c5770010000000000000002c5c85fdf473de6b20260801c5b600083600216600f0b1315610cc2577001000000000000000162e42fefa39ef3580260801c5b600083600116600f0b1315610ce85770010000000000000000b17217f7d1cf79ab0260801c5b600f83810b60401d603f03900b1c6f7fffffffffffffffffffffffffffffff811115610d1357600080fd5b92915050565b600081610d6d576040805162461bcd60e51b815260206004820152600860248201527f444956552d494e46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000610d798484610df9565b90506f7fffffffffffffffffffffffffffffff6fffffffffffffffffffffffffffffffff82161115610df2576040805162461bcd60e51b815260206004820152600760248201527f444956552d4f4600000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b9392505050565b600081610e0557600080fd5b600077ffffffffffffffffffffffffffffffffffffffffffffffff8411610e3b5782604085901b81610e3357fe5b049050610f9a565b60c084811c6401000000008110610e54576020918201911c5b620100008110610e66576010918201911c5b6101008110610e77576008918201911c5b60108110610e87576004918201911c5b60048110610e97576002918201911c5b60028110610ea6576001820191505b60bf820360018603901c6001018260ff0387901b81610ec157fe5b0492506fffffffffffffffffffffffffffffffff831115610f29576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46310000000000000000000000000000000000000000000000604482015290519081900360640190fd5b608085901c83026fffffffffffffffffffffffffffffffff8616840260c088901c604089901b82811015610f5e576001820391505b608084901b92900382811015610f75576001820391505b829003608084901c8214610f8557fe5b888181610f8e57fe5b04870196505050505050505b6fffffffffffffffffffffffffffffffff811115610df2576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46320000000000000000000000000000000000000000000000604482015290519081900360640190fdfea264697066735822122040574cb227dea1d1a5db4fb4ab0552095e5133a47a8b45993e447ebd0471743a64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"divu(uint256,uint256)\": {\n        \"params\": {\n          \"x\": \"unsigned 256-bit integer number\",\n          \"y\": \"unsigned 256-bit integer number\"\n        },\n        \"returns\": {\n          \"_0\": \"signed 64.64-bit fixed point number\"\n        }\n      },\n      \"exp_2(int128)\": {\n        \"params\": {\n          \"x\": \"signed 64.64-bit fixed point number\"\n        },\n        \"returns\": {\n          \"_0\": \"signed 64.64-bit fixed point number\"\n        }\n      },\n      \"log_2(int128)\": {\n        \"params\": {\n          \"x\": \"signed 64.64-bit fixed point number\"\n        },\n        \"returns\": {\n          \"_0\": \"signed 64.64-bit fixed point number\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"divu(uint256,uint256)\": {\n        \"notice\": \"Calculate x / y rounding towards zero, where x and y are unsigned 256-bit integer numbers.  Revert on overflow or when y is zero.\"\n      },\n      \"exp_2(int128)\": {\n        \"notice\": \"Calculate binary exponent of x.  Revert on overflow.\"\n      },\n      \"log_2(int128)\": {\n        \"notice\": \"Calculate binary logarithm of x.  Revert if x <= 0.\"\n      }\n    },\n    \"notice\": \"Smart contract library of mathematical functions operating with signed 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is basically a simple fraction whose numerator is signed 128-bit integer and denominator is 2^64.  As long as denominator is always the same, there is no need to store it, thus in Solidity signed 64.64-bit fixed point numbers are represented by int128 type holding only the numerator. Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4 Changes - some function visibility switched to public, solidity version set to 0.7.x Changes (cont) - revert strings added solidity version set to ^0.7.0\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/Controller.json",
    "content": "{\n  \"address\": \"0x64187ae08781B09368e6253F9E94951243A493D5\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_oracle\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_shortPowerPerp\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wPowerPerp\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_weth\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_quoteCurrency\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_ethQuoteCurrencyPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wPowerPerpPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniPositionManager\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_feeTier\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"BurnShort\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"DepositCollateral\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"DepositUniPositionToken\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"oldFee\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newFee\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FeeRateUpdated\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"oldFeeRecipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"newFeeRecipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"FeeRecipientUpdated\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"liquidator\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"debtAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"collateralPaid\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Liquidate\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"MintShort\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"oldNormFactor\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newNormFactor\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"lastModificationTimestamp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"timestamp\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"NormalizationFactorUpdated\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"OpenVault\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"pausesLeft\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Paused\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"payoutAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"RedeemLong\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vauldId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"collateralAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"RedeemShort\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethRedeemed\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpRedeemed\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpBurned\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpExcess\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"bounty\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ReduceDebt\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"indexForSettlement\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Shutdown\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"unpauser\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"UnPaused\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"UpdateOperator\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawCollateral\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawUniPositionToken\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"FUNDING_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"TWAP_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"applyFunding\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_powerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_withdrawAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burnPowerPerpAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_withdrawAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burnWPowerPerpAmount\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"deposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniTokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"depositUniPositionToken\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"donate\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"ethQuoteCurrencyPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"feeRate\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"feeRecipient\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"feeTier\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getDenormalizedMark\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getDenormalizedMarkForFunding\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getExpectedNormalizationFactor\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getUnscaledIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"indexForSettlement\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isShutDown\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isSystemPaused\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"isVaultSafe\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"lastFundingUpdateTimestamp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"\",\n          \"type\": \"uint128\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"lastPauseTime\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxDebtAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"liquidate\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_powerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniTokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"mintPowerPerpAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniTokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"mintWPowerPerpAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"normalizationFactor\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"\",\n          \"type\": \"uint128\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onERC721Received\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"oracle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"pause\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"pausesLeft\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"quoteCurrency\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPerpAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"redeemLong\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"redeemShort\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"reduceDebt\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"reduceDebtShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_newFeeRate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setFeeRate\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_newFeeRecipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"setFeeRecipient\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"shortPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"shutDown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"unPauseAnyone\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"unPauseOwner\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_operator\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"updateOperator\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"vaults\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"NftCollateralId\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint96\",\n          \"name\": \"collateralAmount\",\n          \"type\": \"uint96\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"shortAmount\",\n          \"type\": \"uint128\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerpPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdrawUniPositionToken\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0xf1cccfa9f3dd36b322876b4430d9689e796090396669357e73f45f44e5b32985\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xa3cB04d8BD927EEC8826BD77b7C71abE3d29c081\",\n    \"contractAddress\": \"0x64187ae08781B09368e6253F9E94951243A493D5\",\n    \"transactionIndex\": 24,\n    \"gasUsed\": \"5402942\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000800000000000010000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000022000000000000000000800000000000000000000000000000000400000000100000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x841ddd8a2f726f44b1c1fc82c948be33954e108c31863cacc918f150d88b43df\",\n    \"transactionHash\": \"0xf1cccfa9f3dd36b322876b4430d9689e796090396669357e73f45f44e5b32985\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 24,\n        \"blockNumber\": 13982541,\n        \"transactionHash\": \"0xf1cccfa9f3dd36b322876b4430d9689e796090396669357e73f45f44e5b32985\",\n        \"address\": \"0x64187ae08781B09368e6253F9E94951243A493D5\",\n        \"topics\": [\n          \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x000000000000000000000000a3cb04d8bd927eec8826bd77b7c71abe3d29c081\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 23,\n        \"blockHash\": \"0x841ddd8a2f726f44b1c1fc82c948be33954e108c31863cacc918f150d88b43df\"\n      }\n    ],\n    \"blockNumber\": 13982541,\n    \"cumulativeGasUsed\": \"6855366\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x65D66c76447ccB45dAf1e8044e918fA786A483A1\",\n    \"0xa653e22A963ff0026292Cc8B67941c0ba7863a38\",\n    \"0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B\",\n    \"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\",\n    \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\n    \"0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8\",\n    \"0x82c427AdFDf2d245Ec51D8046b41c4ee87F0d29C\",\n    \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n    3000\n  ],\n  \"solcInputHash\": \"d97d3d4b09e0d70518330d405a7dd9ff\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_oracle\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_shortPowerPerp\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wPowerPerp\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_weth\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_quoteCurrency\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_ethQuoteCurrencyPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniPositionManager\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_feeTier\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"BurnShort\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"DepositCollateral\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"DepositUniPositionToken\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"oldFee\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newFee\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FeeRateUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"oldFeeRecipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newFeeRecipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"FeeRecipientUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"liquidator\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"debtAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralPaid\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Liquidate\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"MintShort\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"oldNormFactor\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newNormFactor\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"lastModificationTimestamp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"timestamp\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"NormalizationFactorUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"OpenVault\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"pausesLeft\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Paused\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"payoutAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"RedeemLong\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vauldId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"RedeemShort\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethRedeemed\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpRedeemed\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpBurned\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpExcess\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bounty\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ReduceDebt\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"indexForSettlement\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Shutdown\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"unpauser\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"UnPaused\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"UpdateOperator\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawCollateral\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawUniPositionToken\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"FUNDING_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"TWAP_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"applyFunding\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burnPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burnWPowerPerpAmount\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"deposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"depositUniPositionToken\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"donate\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"ethQuoteCurrencyPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"feeRate\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"feeRecipient\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"feeTier\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getDenormalizedMark\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getDenormalizedMarkForFunding\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getExpectedNormalizationFactor\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getUnscaledIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"indexForSettlement\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isShutDown\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isSystemPaused\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"isVaultSafe\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"lastFundingUpdateTimestamp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"lastPauseTime\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxDebtAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"liquidate\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mintPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mintWPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"normalizationFactor\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onERC721Received\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"oracle\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"pause\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"pausesLeft\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"quoteCurrency\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"redeemLong\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"redeemShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"reduceDebt\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"reduceDebtShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_newFeeRate\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setFeeRate\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_newFeeRecipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"setFeeRecipient\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"shortPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"shutDown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"unPauseAnyone\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"unPauseOwner\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"updateOperator\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"vaults\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"NftCollateralId\\\",\\\"type\\\":\\\"uint32\\\"},{\\\"internalType\\\":\\\"uint96\\\",\\\"name\\\":\\\"collateralAmount\\\",\\\"type\\\":\\\"uint96\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"shortAmount\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdrawUniPositionToken\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"burnPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_powerPerpAmount\\\":\\\"amount of powerPerp to burn\\\",\\\"_vaultId\\\":\\\"id of the vault\\\",\\\"_withdrawAmount\\\":\\\"amount of eth to withdraw\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"amount of wPowerPerp burned\\\"}},\\\"burnWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to burn\\\",\\\"_withdrawAmount\\\":\\\"amount of eth to withdraw\\\"}},\\\"constructor\\\":{\\\"params\\\":{\\\"_ethQuoteCurrencyPool\\\":\\\"uniswap v3 pool for weth / quoteCurrency\\\",\\\"_oracle\\\":\\\"oracle address\\\",\\\"_quoteCurrency\\\":\\\"quoteCurrency address\\\",\\\"_shortPowerPerp\\\":\\\"ERC721 token address representing the short position\\\",\\\"_uniPositionManager\\\":\\\"uniswap v3 position manager address\\\",\\\"_wPowerPerp\\\":\\\"ERC20 token address representing the long position\\\",\\\"_wPowerPerpPool\\\":\\\"uniswap v3 pool for wPowerPerp / weth\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"deposit(uint256)\\\":{\\\"details\\\":\\\"deposit collateral into a vault\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"depositUniPositionToken(uint256,uint256)\\\":{\\\"params\\\":{\\\"_uniTokenId\\\":\\\"uniswap position token id\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"getDenormalizedMark(uint32)\\\":{\\\"params\\\":{\\\"_period\\\":\\\"period of time for the twap in seconds\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"mark price denominated in $USD, scaled by 1e18\\\"}},\\\"getDenormalizedMarkForFunding(uint32)\\\":{\\\"details\\\":\\\"this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\\",\\\"params\\\":{\\\"_period\\\":\\\"period which you want to calculate twap with\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"mark price denominated in $USD, scaled by 1e18\\\"}},\\\"getExpectedNormalizationFactor()\\\":{\\\"details\\\":\\\"can be used for on-chain and off-chain calculations\\\"},\\\"getIndex(uint32)\\\":{\\\"details\\\":\\\"the index price is scaled down by INDEX_SCALE in the associated PowerXBase librarythis is the index price used when calculating funding and for collateralization\\\",\\\"params\\\":{\\\"_period\\\":\\\"period which you want to calculate twap with\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"index price denominated in $USD, scaled by 1e18\\\"}},\\\"getUnscaledIndex(uint32)\\\":{\\\"details\\\":\\\"this is the mark that would be be used for future funding after a new normalization factor is applied\\\",\\\"params\\\":{\\\"_period\\\":\\\"period which you want to calculate twap with\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"index price denominated in $USD, scaled by 1e18\\\"}},\\\"isVaultSafe(uint256)\\\":{\\\"details\\\":\\\"return if the vault is properly collateralized\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"true if the vault is properly collateralized\\\"}},\\\"liquidate(uint256,uint256)\\\":{\\\"details\\\":\\\"liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateralnormally can only liquidate 50% of a vault's debtif a vault is under dust limit after a liquidation can fully liquidatewill attempt to reduceDebt first, and can earn a bounty if sucessful\\\",\\\"params\\\":{\\\"_maxDebtAmount\\\":\\\"max amount of wPowerPerpetual to repay\\\",\\\"_vaultId\\\":\\\"vault to liquidate\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"amount of wPowerPerp repaid\\\"}},\\\"mintPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_powerPerpAmount\\\":\\\"amount of powerPerp to mint\\\",\\\"_uniTokenId\\\":\\\"uniswap v3 position token id (additional collateral)\\\",\\\"_vaultId\\\":\\\"vault to mint wPowerPerp in\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"vaultId\\\",\\\"_1\\\":\\\"amount of wPowerPerp minted\\\"}},\\\"mintWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_uniTokenId\\\":\\\"uniswap v3 position token id (additional collateral)\\\",\\\"_vaultId\\\":\\\"vault to mint wPowerPerp in\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to mint\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"vaultId\\\"}},\\\"onERC721Received(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"accept erc721 from safeTransferFrom and safeMint after callback\\\",\\\"returns\\\":{\\\"_0\\\":\\\"returns received selector\\\"}},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"pause()\\\":{\\\"details\\\":\\\"can only be called for 365 days since the contract was launched or 4 times\\\"},\\\"redeemLong(uint256)\\\":{\\\"params\\\":{\\\"_wPerpAmount\\\":\\\"amount of wPowerPerp to burn\\\"}},\\\"redeemShort(uint256)\\\":{\\\"details\\\":\\\"short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"vault id\\\"}},\\\"reduceDebt(uint256)\\\":{\\\"details\\\":\\\"the caller won't get any bounty. this is expected to be used by vault owner\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"target vault\\\"}},\\\"reduceDebtShutdown(uint256)\\\":{\\\"details\\\":\\\"the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"vault containing uniswap v3 position to liquidate\\\"}},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"setFeeRate(uint256)\\\":{\\\"details\\\":\\\"this function cannot be called if the feeRecipient is still un-set\\\",\\\"params\\\":{\\\"_newFeeRate\\\":\\\"new fee rate in basis points. can't be higher than 1%\\\"}},\\\"setFeeRecipient(address)\\\":{\\\"details\\\":\\\"this should be a contract handling insurance\\\",\\\"params\\\":{\\\"_newFeeRecipient\\\":\\\"new fee recipient\\\"}},\\\"shutDown()\\\":{\\\"details\\\":\\\"this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\\"},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"unPauseAnyone()\\\":{\\\"details\\\":\\\"anyone can unpause the contract after 24 hours\\\"},\\\"unPauseOwner()\\\":{\\\"details\\\":\\\"owner can unpause at any time\\\"},\\\"updateOperator(uint256,address)\\\":{\\\"details\\\":\\\"can be revoke by setting address to 0\\\",\\\"params\\\":{\\\"_operator\\\":\\\"new operator address\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"withdraw(uint256,uint256)\\\":{\\\"params\\\":{\\\"_amount\\\":\\\"amount of eth to withdraw\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"withdrawUniPositionToken(uint256)\\\":{\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"}}},\\\"stateVariables\\\":{\\\"ONE\\\":{\\\"details\\\":\\\"basic unit used for calculation\\\"},\\\"PAUSE_TIME_LIMIT\\\":{\\\"details\\\":\\\"system can only be paused for 182 days from deployment\\\"},\\\"feeRate\\\":{\\\"details\\\":\\\"fee rate in basis point. feeRate of 1 = 0.01%\\\"},\\\"indexForSettlement\\\":{\\\"details\\\":\\\"the settlement price for each wPowerPerp for settlement\\\"},\\\"vaults\\\":{\\\"details\\\":\\\"vault data storage\\\"},\\\"wPowerPerpPool\\\":{\\\"details\\\":\\\"address of the powerPerp/weth pool\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"events\\\":{\\\"OpenVault(address,uint256)\\\":{\\\"notice\\\":\\\"Events\\\"}},\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"applyFunding()\\\":{\\\"notice\\\":\\\"update the normalization factor as a way to pay funding\\\"},\\\"burnPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"burn powerPerp and remove collateral from a vault\\\"},\\\"burnWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"burn wPowerPerp and remove collateral from a vault\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"constructor\\\"},\\\"depositUniPositionToken(uint256,uint256)\\\":{\\\"notice\\\":\\\"deposit uniswap position token into a vault to increase collateral ratio\\\"},\\\"donate()\\\":{\\\"notice\\\":\\\"add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\\"},\\\"getDenormalizedMark(uint32)\\\":{\\\"notice\\\":\\\"get the expected mark price of powerPerp after funding has been applied\\\"},\\\"getDenormalizedMarkForFunding(uint32)\\\":{\\\"notice\\\":\\\"get the mark price of powerPerp before funding has been applied\\\"},\\\"getExpectedNormalizationFactor()\\\":{\\\"notice\\\":\\\"returns the expected normalization factor, if the funding is paid right now\\\"},\\\"getIndex(uint32)\\\":{\\\"notice\\\":\\\"get the index price of the powerPerp, scaled down\\\"},\\\"getUnscaledIndex(uint32)\\\":{\\\"notice\\\":\\\"the unscaled index of the power perp in USD, scaled by 18 decimals\\\"},\\\"liquidate(uint256,uint256)\\\":{\\\"notice\\\":\\\"if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\\"},\\\"mintPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\\"},\\\"mintWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"deposit collateral and mint wPowerPerp\\\"},\\\"pause()\\\":{\\\"notice\\\":\\\"pause the system for up to 24 hours after which any one can unpause\\\"},\\\"redeemLong(uint256)\\\":{\\\"notice\\\":\\\"redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\\"},\\\"redeemShort(uint256)\\\":{\\\"notice\\\":\\\"redeem short position when the system is shutdown\\\"},\\\"reduceDebt(uint256)\\\":{\\\"notice\\\":\\\"withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\\"},\\\"reduceDebtShutdown(uint256)\\\":{\\\"notice\\\":\\\"after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by forceif a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\\"},\\\"setFeeRate(uint256)\\\":{\\\"notice\\\":\\\"set the fee rate when user mints\\\"},\\\"setFeeRecipient(address)\\\":{\\\"notice\\\":\\\"set the recipient who will receive the fee\\\"},\\\"shutDown()\\\":{\\\"notice\\\":\\\"shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactorshort positions can be redeemed for vault collateral minus value of debtpause (if not paused) and then immediately shutdown the system, can be called when paused already\\\"},\\\"unPauseAnyone()\\\":{\\\"notice\\\":\\\"unpause the contract\\\"},\\\"unPauseOwner()\\\":{\\\"notice\\\":\\\"unpause the contract\\\"},\\\"updateOperator(uint256,address)\\\":{\\\"notice\\\":\\\"authorize an address to modify the vault\\\"},\\\"withdraw(uint256,uint256)\\\":{\\\"notice\\\":\\\"withdraw collateral from a vault\\\"},\\\"withdrawUniPositionToken(uint256)\\\":{\\\"notice\\\":\\\"withdraw uniswap v3 position token from a vault\\\"}},\\\"notice\\\":\\\"Error C0: Paused C1: Not paused C2: Shutdown C3: Not shutdown C4: Invalid oracle address C5: Invalid shortPowerPerp address C6: Invalid wPowerPerp address C7: Invalid weth address C8: Invalid quote currency address C9: Invalid eth:quoteCurrency pool address C10: Invalid wPowerPerp:eth pool address C11: Invalid Uniswap position manager C12: Can not liquidate safe vault C13: Invalid address C14: Set fee recipient first C15: Fee too high C16: Paused too many times C17: Pause time limit exceeded C18: Not enough paused time has passed C19: Cannot receive eth C20: Not allowed C21: Need full liquidation C22: Dust vault left C23: Invalid nft C24: Invalid state C25: 0 liquidity Uniswap position token C26: Wrong fee tier for NFT deposit\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/Controller.sol\\\":\\\"Controller\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/core/Controller.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IERC721Receiver} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\\\\\";\\\\n\\\\n//contract\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\nimport {ReentrancyGuard} from \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ABDKMath64x64} from \\\\\\\"../libs/ABDKMath64x64.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"../libs/Uint256Casting.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\n\\\\n/**\\\\n *\\\\n * Error\\\\n * C0: Paused\\\\n * C1: Not paused\\\\n * C2: Shutdown\\\\n * C3: Not shutdown\\\\n * C4: Invalid oracle address\\\\n * C5: Invalid shortPowerPerp address\\\\n * C6: Invalid wPowerPerp address\\\\n * C7: Invalid weth address\\\\n * C8: Invalid quote currency address\\\\n * C9: Invalid eth:quoteCurrency pool address\\\\n * C10: Invalid wPowerPerp:eth pool address\\\\n * C11: Invalid Uniswap position manager\\\\n * C12: Can not liquidate safe vault\\\\n * C13: Invalid address\\\\n * C14: Set fee recipient first\\\\n * C15: Fee too high\\\\n * C16: Paused too many times\\\\n * C17: Pause time limit exceeded\\\\n * C18: Not enough paused time has passed\\\\n * C19: Cannot receive eth\\\\n * C20: Not allowed\\\\n * C21: Need full liquidation\\\\n * C22: Dust vault left\\\\n * C23: Invalid nft\\\\n * C24: Invalid state\\\\n * C25: 0 liquidity Uniswap position token\\\\n * C26: Wrong fee tier for NFT deposit\\\\n */\\\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n    using ABDKMath64x64 for int128;\\\\n    using VaultLib for VaultLib.Vault;\\\\n    using Address for address payable;\\\\n\\\\n    uint256 internal constant MIN_COLLATERAL = 6.9 ether;\\\\n    /// @dev system can only be paused for 182 days from deployment\\\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\\\n\\\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\\\n    uint24 public immutable feeTier;\\\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\\\n\\\\n    //80% of index\\\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\\\n    //140% of index\\\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\\\n    // 10%\\\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\\\n    // 2%\\\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\\\n\\\\n    /// @dev basic unit used for calculation\\\\n    uint256 private constant ONE = 1e18;\\\\n\\\\n    address public immutable weth;\\\\n    address public immutable quoteCurrency;\\\\n    address public immutable ethQuoteCurrencyPool;\\\\n    /// @dev address of the powerPerp/weth pool\\\\n    address public immutable wPowerPerpPool;\\\\n    address internal immutable uniswapPositionManager;\\\\n    address public immutable shortPowerPerp;\\\\n    address public immutable wPowerPerp;\\\\n    address public immutable oracle;\\\\n    address public feeRecipient;\\\\n\\\\n    uint256 internal immutable deployTimestamp;\\\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\\\n    uint256 public feeRate;\\\\n    /// @dev the settlement price for each wPowerPerp for settlement\\\\n    uint256 public indexForSettlement;\\\\n\\\\n    uint256 public pausesLeft = 4;\\\\n    uint256 public lastPauseTime;\\\\n\\\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\\\n    uint128 public normalizationFactor;\\\\n    uint128 public lastFundingUpdateTimestamp;\\\\n\\\\n    bool internal immutable isWethToken0;\\\\n    bool public isShutDown;\\\\n    bool public isSystemPaused;\\\\n\\\\n    /// @dev vault data storage\\\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\\\n\\\\n    /// Events\\\\n    event OpenVault(address sender, uint256 vaultId);\\\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\\\n    event ReduceDebt(\\\\n        address sender,\\\\n        uint256 vaultId,\\\\n        uint256 ethRedeemed,\\\\n        uint256 wPowerPerpRedeemed,\\\\n        uint256 wPowerPerpBurned,\\\\n        uint256 wPowerPerpExcess,\\\\n        uint256 bounty\\\\n    );\\\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\\\n    event NormalizationFactorUpdated(\\\\n        uint256 oldNormFactor,\\\\n        uint256 newNormFactor,\\\\n        uint256 lastModificationTimestamp,\\\\n        uint256 timestamp\\\\n    );\\\\n    event Paused(uint256 pausesLeft);\\\\n    event UnPaused(address unpauser);\\\\n    event Shutdown(uint256 indexForSettlement);\\\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\\\n\\\\n    modifier notPaused() {\\\\n        require(!isSystemPaused, \\\\\\\"C0\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier isPaused() {\\\\n        require(isSystemPaused, \\\\\\\"C1\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier notShutdown() {\\\\n        require(!isShutDown, \\\\\\\"C2\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier isShutdown() {\\\\n        require(isShutDown, \\\\\\\"C3\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice constructor\\\\n     * @param _oracle oracle address\\\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\\\n     * @param _wPowerPerp ERC20 token address representing the long position\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\\\n     * @param _uniPositionManager uniswap v3 position manager address\\\\n     */\\\\n    constructor(\\\\n        address _oracle,\\\\n        address _shortPowerPerp,\\\\n        address _wPowerPerp,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _wPowerPerpPool,\\\\n        address _uniPositionManager,\\\\n        uint24 _feeTier\\\\n    ) {\\\\n        require(_oracle != address(0), \\\\\\\"C4\\\\\\\");\\\\n        require(_shortPowerPerp != address(0), \\\\\\\"C5\\\\\\\");\\\\n        require(_wPowerPerp != address(0), \\\\\\\"C6\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"C7\\\\\\\");\\\\n        require(_quoteCurrency != address(0), \\\\\\\"C8\\\\\\\");\\\\n        require(_ethQuoteCurrencyPool != address(0), \\\\\\\"C9\\\\\\\");\\\\n        require(_wPowerPerpPool != address(0), \\\\\\\"C10\\\\\\\");\\\\n        require(_uniPositionManager != address(0), \\\\\\\"C11\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        shortPowerPerp = _shortPowerPerp;\\\\n        wPowerPerp = _wPowerPerp;\\\\n        weth = _weth;\\\\n        quoteCurrency = _quoteCurrency;\\\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\\\n        wPowerPerpPool = _wPowerPerpPool;\\\\n        uniswapPositionManager = _uniPositionManager;\\\\n        feeTier = _feeTier;\\\\n        isWethToken0 = _weth < _wPowerPerp;\\\\n\\\\n        normalizationFactor = 1e18;\\\\n        deployTimestamp = block.timestamp;\\\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * ======================\\\\n     * | External Functions |\\\\n     * ======================\\\\n     */\\\\n\\\\n    /**\\\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\\\n     * @dev can be used for on-chain and off-chain calculations\\\\n     */\\\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\\\n        return _getNewNormalizationFactor();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index price of the powerPerp, scaled down\\\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\\\n     * @dev this is the index price used when calculating funding and for collateralization\\\\n     * @param _period period which you want to calculate twap with\\\\n     * @return index price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getIndex(uint32 _period) external view returns (uint256) {\\\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\\\n     * @param _period period which you want to calculate twap with\\\\n     * @return index price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\\\n     * @param _period period of time for the twap in seconds\\\\n     * @return mark price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\\\n        return\\\\n            Power2Base._getDenormalizedMark(\\\\n                _period,\\\\n                oracle,\\\\n                wPowerPerpPool,\\\\n                ethQuoteCurrencyPool,\\\\n                weth,\\\\n                quoteCurrency,\\\\n                wPowerPerp,\\\\n                _getNewNormalizationFactor()\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the mark price of powerPerp before funding has been applied\\\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\\\n     * @param _period period which you want to calculate twap with\\\\n     * @return mark price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\\\n        return\\\\n            Power2Base._getDenormalizedMark(\\\\n                _period,\\\\n                oracle,\\\\n                wPowerPerpPool,\\\\n                ethQuoteCurrencyPool,\\\\n                weth,\\\\n                quoteCurrency,\\\\n                wPowerPerp,\\\\n                normalizationFactor\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev return if the vault is properly collateralized\\\\n     * @param _vaultId id of the vault\\\\n     * @return true if the vault is properly collateralized\\\\n     */\\\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\\\n     * @param _vaultId vault to mint wPowerPerp in\\\\n     * @param _powerPerpAmount amount of powerPerp to mint\\\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\\\n     * @return vaultId\\\\n     * @return amount of wPowerPerp minted\\\\n     */\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit collateral and mint wPowerPerp\\\\n     * @param _vaultId vault to mint wPowerPerp in\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\\\n     * @return vaultId\\\\n     */\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable notPaused nonReentrant returns (uint256) {\\\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev deposit collateral into a vault\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\\\n     * @param _vaultId id of the vault\\\\n     * @param _uniTokenId uniswap position token id\\\\n     */\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw collateral from a vault\\\\n     * @param _vaultId id of the vault\\\\n     * @param _amount amount of eth to withdraw\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n        payable(msg.sender).sendValue(_amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw uniswap v3 position token from a vault\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp and remove collateral from a vault\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\\\n     * @param _withdrawAmount amount of eth to withdraw\\\\n     */\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn powerPerp and remove collateral from a vault\\\\n     * @param _vaultId id of the vault\\\\n     * @param _powerPerpAmount amount of powerPerp to burn\\\\n     * @param _withdrawAmount amount of eth to withdraw\\\\n     * @return amount of wPowerPerp burned\\\\n     */\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external notPaused nonReentrant returns (uint256) {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\\\n     */\\\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\\\n     * @param _vaultId target vault\\\\n     */\\\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\\\n     * @dev normally can only liquidate 50% of a vault's debt\\\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\\\n     * @param _vaultId vault to liquidate\\\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\\\n     * @return amount of wPowerPerp repaid\\\\n     */\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\\\\\"C12\\\\\\\");\\\\n\\\\n        // try to save target vault before liquidation by reducing debt\\\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\\\n\\\\n        // if vault is safe after saving, pay bounty and return early\\\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\\\n            _writeVault(_vaultId, cachedVault);\\\\n            payable(msg.sender).sendValue(bounty);\\\\n            return 0;\\\\n        }\\\\n\\\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\\\n        cachedVault.addEthCollateral(bounty);\\\\n\\\\n        // if the vault is still not safe after saving, liquidate it\\\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\\\n            cachedVault,\\\\n            _maxDebtAmount,\\\\n            cachedNormFactor,\\\\n            msg.sender\\\\n        );\\\\n\\\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        // pay the liquidator\\\\n        payable(msg.sender).sendValue(collateralPaid);\\\\n\\\\n        return debtAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice authorize an address to modify the vault\\\\n     * @dev can be revoke by setting address to 0\\\\n     * @param _vaultId id of the vault\\\\n     * @param _operator new operator address\\\\n     */\\\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\\\n        require(\\\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\\\n            \\\\\\\"C20\\\\\\\"\\\\n        );\\\\n        vaults[_vaultId].operator = _operator;\\\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set the recipient who will receive the fee\\\\n     * @dev this should be a contract handling insurance\\\\n     * @param _newFeeRecipient new fee recipient\\\\n     */\\\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\\\n        require(_newFeeRecipient != address(0), \\\\\\\"C13\\\\\\\");\\\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\\\n        feeRecipient = _newFeeRecipient;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set the fee rate when user mints\\\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\\\n     */\\\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\\\n        require(feeRecipient != address(0), \\\\\\\"C14\\\\\\\");\\\\n        require(_newFeeRate <= 100, \\\\\\\"C15\\\\\\\");\\\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\\\n        feeRate = _newFeeRate;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\\\n     */\\\\n    function shutDown() external onlyOwner notShutdown {\\\\n        isSystemPaused = true;\\\\n        isShutDown = true;\\\\n        indexForSettlement = Power2Base._getScaledTwap(\\\\n            oracle,\\\\n            ethQuoteCurrencyPool,\\\\n            weth,\\\\n            quoteCurrency,\\\\n            TWAP_PERIOD,\\\\n            false\\\\n        );\\\\n        emit Shutdown(indexForSettlement);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\\\n     */\\\\n    function pause() external onlyOwner notShutdown notPaused {\\\\n        require(pausesLeft > 0, \\\\\\\"C16\\\\\\\");\\\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\\\\\"C17\\\\\\\");\\\\n        isSystemPaused = true;\\\\n        pausesLeft -= 1;\\\\n        lastPauseTime = block.timestamp;\\\\n\\\\n        emit Paused(pausesLeft);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice unpause the contract\\\\n     * @dev anyone can unpause the contract after 24 hours\\\\n     */\\\\n    function unPauseAnyone() external isPaused notShutdown {\\\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\\\\\"C18\\\\\\\");\\\\n        isSystemPaused = false;\\\\n        emit UnPaused(msg.sender);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice unpause the contract\\\\n     * @dev owner can unpause at any time\\\\n     */\\\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\\\n        isSystemPaused = false;\\\\n        emit UnPaused(msg.sender);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\\\n     */\\\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\\\n\\\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\\\n        payable(msg.sender).sendValue(longValue);\\\\n\\\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice redeem short position when the system is shutdown\\\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\\\n     * @param _vaultId vault id\\\\n     */\\\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        uint256 cachedNormFactor = normalizationFactor;\\\\n\\\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\\\n\\\\n        uint256 debt = Power2Base._getLongSettlementValue(\\\\n            cachedVault.shortAmount,\\\\n            indexForSettlement,\\\\n            cachedNormFactor\\\\n        );\\\\n        // if the debt is more than collateral, this line will revert\\\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\\\n\\\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\\\n        cachedVault.shortAmount = 0;\\\\n        cachedVault.collateralAmount = 0;\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        payable(msg.sender).sendValue(excess);\\\\n\\\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice update the normalization factor as a way to pay funding\\\\n     */\\\\n    function applyFunding() external notPaused {\\\\n        _applyFunding();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\\\n     */\\\\n    function donate() external payable isShutdown {}\\\\n\\\\n    /**\\\\n     * @notice fallback function to accept eth\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth, \\\\\\\"C19\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\\\n     * @return returns received selector\\\\n     */\\\\n    function onERC721Received(\\\\n        address,\\\\n        address,\\\\n        uint256,\\\\n        bytes memory\\\\n    ) public virtual override returns (bytes4) {\\\\n        return this.onERC721Received.selector;\\\\n    }\\\\n\\\\n    /*\\\\n     * ======================\\\\n     * | Internal Functions |\\\\n     * ======================\\\\n     */\\\\n\\\\n    /**\\\\n     * @notice check if an address can modify a vault\\\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\\\n     * @param _account the address to check if can modify the vault\\\\n     */\\\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\\\n        require(\\\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\\\n            \\\\\\\"C20\\\\\\\"\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\\\n     * @param _account account to receive wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _mintAmount amount to mint\\\\n     * @param _depositAmount amount of eth as collateral\\\\n     * @param _uniTokenId id of uniswap v3 position token\\\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\\\n     * @return the minted wPowerPerp amount\\\\n     */\\\\n    function _openDepositMint(\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _mintAmount,\\\\n        uint256 _depositAmount,\\\\n        uint256 _uniTokenId,\\\\n        bool _isWAmount\\\\n    ) internal returns (uint256, uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        uint256 depositAmountWithFee = _depositAmount;\\\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\\\n        uint256 feeAmount;\\\\n        VaultLib.Vault memory cachedVault;\\\\n\\\\n        // load vault or create new a new one\\\\n        if (_vaultId == 0) {\\\\n            (_vaultId, cachedVault) = _openVault(_account);\\\\n        } else {\\\\n            // make sure we're not accessing an unexistent vault.\\\\n            _checkCanModifyVault(_vaultId, msg.sender);\\\\n            cachedVault = vaults[_vaultId];\\\\n        }\\\\n\\\\n        if (wPowerPerpAmount > 0) {\\\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\\\n        }\\\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\\\n\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        // pay insurance fee\\\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\\\n\\\\n        return (_vaultId, wPowerPerpAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\\\n     * @param _account who should receive collateral\\\\n     * @param _vaultId id of the vault\\\\n     * @param _burnAmount amount of wPowerPerp to burn\\\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\\\n     * @return total burned wPowerPower amount\\\\n     */\\\\n    function _burnAndWithdraw(\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _burnAmount,\\\\n        uint256 _withdrawAmount,\\\\n        bool _isWAmount\\\\n    ) internal returns (uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\\\n\\\\n        return wBurnAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice open a new vault\\\\n     * @dev create a new vault and bind it with a new short vault id\\\\n     * @param _recipient owner of new vault\\\\n     * @return id of the new vault\\\\n     * @return new in-memory vault\\\\n     */\\\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\\\n\\\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\\\n            NftCollateralId: 0,\\\\n            collateralAmount: 0,\\\\n            shortAmount: 0,\\\\n            operator: address(0)\\\\n        });\\\\n        emit OpenVault(msg.sender, vaultId);\\\\n        return (vaultId, vault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit uniswap v3 position token into a vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account account to transfer the uniswap v3 position from\\\\n     * @param _vaultId id of the vault\\\\n     * @param _uniTokenId uniswap position token id\\\\n     */\\\\n    function _depositUniPositionToken(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _uniTokenId\\\\n    ) internal {\\\\n        //get tokens for uniswap NFT\\\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\\\n            uniswapPositionManager\\\\n        ).positions(_uniTokenId);\\\\n\\\\n        // require that liquidity is above 0\\\\n        require(liquidity > 0, \\\\\\\"C25\\\\\\\");\\\\n        // accept NFTs from only the wPowerPerp pool\\\\n        require(fee == feeTier, \\\\\\\"C26\\\\\\\");\\\\n        // check token0 and token1\\\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\\\\\"C23\\\\\\\");\\\\n\\\\n        _vault.addUniNftCollateral(_uniTokenId);\\\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral into a vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _vaultId id of the vault\\\\n     * @param _amount amount of eth adding to the vault\\\\n     */\\\\n    function _addEthCollateral(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _vaultId,\\\\n        uint256 _amount\\\\n    ) internal {\\\\n        _vault.addEthCollateral(_amount);\\\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap v3 position token from the vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account where to send the uni position token to\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function _withdrawUniPositionToken(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId\\\\n    ) internal {\\\\n        uint256 tokenId = _vault.NftCollateralId;\\\\n        _vault.removeUniNftCollateral();\\\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from the vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _vaultId id of the vault\\\\n     * @param _amount amount of eth to withdraw\\\\n     */\\\\n    function _withdrawCollateral(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _vaultId,\\\\n        uint256 _amount\\\\n    ) internal {\\\\n        _vault.removeEthCollateral(_amount);\\\\n\\\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp (ERC20) to an account\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account account to receive wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\\\n     */\\\\n    function _mintWPowerPerp(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount\\\\n    ) internal {\\\\n        _vault.addShort(_wPowerPerpAmount);\\\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\\\n\\\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp (ERC20) from an account\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account account burning the wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\\\n     */\\\\n    function _burnWPowerPerp(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount\\\\n    ) internal {\\\\n        _vault.removeShort(_wPowerPerpAmount);\\\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\\\n\\\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice liquidate a vault, pay the liquidator\\\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @param _liquidator liquidator address to receive eth\\\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\\\n     * @return collateralToPay amount of collateral paid to liquidator\\\\n     */\\\\n    function _liquidate(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _maxWPowerPerpAmount,\\\\n        uint256 _normalizationFactor,\\\\n        address _liquidator\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\\\n            _maxWPowerPerpAmount,\\\\n            uint256(_vault.shortAmount),\\\\n            uint256(_vault.collateralAmount)\\\\n        );\\\\n\\\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\\\\\"C21\\\\\\\");\\\\n\\\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\\\n        _vault.removeShort(liquidateAmount);\\\\n        _vault.removeEthCollateral(collateralToPay);\\\\n\\\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        require(!isDust, \\\\\\\"C22\\\\\\\");\\\\n\\\\n        return (liquidateAmount, collateralToPay);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\\\n     * @dev will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _owner account to send any excess\\\\n     * @param _vaultId id of the vault to reduce debt on\\\\n     * @param _payBounty true if paying caller 2% bounty\\\\n     * @return bounty amount of bounty paid for liquidator\\\\n     */\\\\n    function _reduceDebt(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _owner,\\\\n        uint256 _vaultId,\\\\n        bool _payBounty\\\\n    ) internal returns (uint256) {\\\\n        uint256 nftId = _vault.NftCollateralId;\\\\n        if (nftId == 0) return 0;\\\\n\\\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\\\n\\\\n        // change weth back to eth\\\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\\\n\\\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\\\n            _vault,\\\\n            withdrawnEthAmount,\\\\n            withdrawnWPowerPerpAmount,\\\\n            _payBounty\\\\n        );\\\\n\\\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\\\n\\\\n        emit ReduceDebt(\\\\n            msg.sender,\\\\n            _vaultId,\\\\n            withdrawnEthAmount,\\\\n            withdrawnWPowerPerpAmount,\\\\n            burnAmount,\\\\n            excess,\\\\n            bounty\\\\n        );\\\\n\\\\n        return bounty;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice pay fee recipient\\\\n     * @dev pay in eth from either the vault or the deposit amount\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\\\n     */\\\\n    function _getFee(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _depositAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 cachedFeeRate = feeRate;\\\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\\\n        uint256 depositAmountAfterFee;\\\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\\\n            _wPowerPerpAmount,\\\\n            oracle,\\\\n            wPowerPerpPool,\\\\n            wPowerPerp,\\\\n            weth\\\\n        );\\\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\\\n\\\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\\\n        if (_depositAmount > feeAmount) {\\\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\\\n            // if not, adjust the vault to pay from the vault collateral\\\\n        } else {\\\\n            _vault.removeEthCollateral(feeAmount);\\\\n            depositAmountAfterFee = _depositAmount;\\\\n        }\\\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\\\n        return (feeAmount, depositAmountAfterFee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice write vault to storage\\\\n     * @dev writes to vaults mapping\\\\n     */\\\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\\\n        vaults[_vaultId] = _vault;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\\\n     * @param _uniTokenId uniswap v3 position token id\\\\n     * @return wethAmount amount of weth withdrawn from uniswap\\\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\\\n     */\\\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\\\n\\\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\\\n\\\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\\\n            .DecreaseLiquidityParams({\\\\n                tokenId: _uniTokenId,\\\\n                liquidity: liquidity,\\\\n                amount0Min: 0,\\\\n                amount1Min: 0,\\\\n                deadline: block.timestamp\\\\n            });\\\\n\\\\n        positionManager.decreaseLiquidity(decreaseParams);\\\\n\\\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\\\n            tokenId: _uniTokenId,\\\\n            recipient: address(this),\\\\n            amount0Max: uint128(-1),\\\\n            amount1Max: uint128(-1)\\\\n        });\\\\n\\\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\\\n\\\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice update the normalization factor as a way to pay in-kind funding\\\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\\\n     * @return new normalization factor\\\\n     **/\\\\n    function _applyFunding() internal returns (uint256) {\\\\n        // only update the norm factor once per block\\\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\\\n\\\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\\\n\\\\n        emit NormalizationFactorUpdated(\\\\n            normalizationFactor,\\\\n            newNormalizationFactor,\\\\n            lastFundingUpdateTimestamp,\\\\n            block.timestamp\\\\n        );\\\\n\\\\n        // the following will be batch into 1 SSTORE because of type uint128\\\\n        normalizationFactor = newNormalizationFactor.toUint128();\\\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\\\n\\\\n        return newNormalizationFactor;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate new normalization factor base on the current timestamp\\\\n     * @return new normalization factor if funding happens in the current block\\\\n     */\\\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\\\n\\\\n        if (period == 0) {\\\\n            return normalizationFactor;\\\\n        }\\\\n\\\\n        // make sure we use the same period for mark and index\\\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\\\n\\\\n        // avoid reading normalizationFactor from storage multiple times\\\\n        uint256 cacheNormFactor = normalizationFactor;\\\\n\\\\n        uint256 mark = Power2Base._getDenormalizedMark(\\\\n            periodForOracle,\\\\n            oracle,\\\\n            wPowerPerpPool,\\\\n            ethQuoteCurrencyPool,\\\\n            weth,\\\\n            quoteCurrency,\\\\n            wPowerPerp,\\\\n            cacheNormFactor\\\\n        );\\\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\\\n\\\\n        //the fraction of the funding period. used to compound the funding rate\\\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\\\n\\\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\\\n        if (mark < lowerBound) {\\\\n            mark = lowerBound;\\\\n        } else {\\\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\\\n            if (mark > upperBound) mark = upperBound;\\\\n        }\\\\n\\\\n        // normFactor(new) = multiplier * normFactor(old)\\\\n        // multiplier = (index/mark)^rFunding\\\\n        // x^r = n^(log_n(x) * r)\\\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\\\n\\\\n        int128 base = ABDKMath64x64.divu(index, mark);\\\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\\\n        int128 multiplier = logTerm.exp_2();\\\\n        return multiplier.mulu(cacheNormFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if vault has enough collateral and is not a dust vault\\\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _normalizationFactor normalization factor\\\\n     */\\\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        require(isSafe, \\\\\\\"C24\\\\\\\");\\\\n        require(!isDust, \\\\\\\"C22\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check that the vault has enough collateral\\\\n     * @param _vault in-memory vault\\\\n     * @param _normalizationFactor normalization factor\\\\n     * @return true if the vault is properly collateralized\\\\n     */\\\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        return isSafe;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _normalizationFactor normalization factor\\\\n     * @return true if the vault is safe\\\\n     * @return true if the vault is a dust vault\\\\n     */\\\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\\\n        internal\\\\n        view\\\\n        returns (bool, bool)\\\\n    {\\\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\\\n            oracle,\\\\n            ethQuoteCurrencyPool,\\\\n            weth,\\\\n            quoteCurrency,\\\\n            TWAP_PERIOD,\\\\n            true // do not call more than maximum period so it does not revert\\\\n        );\\\\n        return\\\\n            VaultLib.getVaultStatus(\\\\n                _vault,\\\\n                uniswapPositionManager,\\\\n                _normalizationFactor,\\\\n                scaledEthPrice,\\\\n                MIN_COLLATERAL,\\\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\\\n                isWethToken0\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @return burnAmount amount of wPowerPerp that should be burned\\\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\\\n     * @return bounty amount of bounty should be paid out to caller\\\\n     */\\\\n    function _getReduceDebtResultInVault(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 nftEthAmount,\\\\n        uint256 nftWPowerperpAmount,\\\\n        bool _payBounty\\\\n    )\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            uint256,\\\\n            uint256,\\\\n            uint256\\\\n        )\\\\n    {\\\\n        uint256 bounty;\\\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\\\n\\\\n        uint256 burnAmount = nftWPowerperpAmount;\\\\n        uint256 wPowerPerpExcess;\\\\n\\\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\\\n            burnAmount = _vault.shortAmount;\\\\n        }\\\\n\\\\n        _vault.removeShort(burnAmount);\\\\n        _vault.removeUniNftCollateral();\\\\n        _vault.addEthCollateral(nftEthAmount);\\\\n        _vault.removeEthCollateral(bounty);\\\\n\\\\n        return (burnAmount, wPowerPerpExcess, bounty);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\\\n     * @dev bounty is 2% of the total value of the position token\\\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\\\n     */\\\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\\\n        return\\\\n            Power2Base\\\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\\\n                .add(_ethWithdrawn)\\\\n                .mul(REDUCE_DEBT_BOUNTY)\\\\n                .div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\\\\\"dust vault\\\\\\\"\\\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\\\n     * @param _vaultShortAmount the amount of short in the vault\\\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\\\n     */\\\\n    function _getLiquidationResult(\\\\n        uint256 _maxWPowerPerpAmount,\\\\n        uint256 _vaultShortAmount,\\\\n        uint256 _vaultCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        // try limiting liquidation amount to half of the vault debt\\\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\\\n            _maxWPowerPerpAmount,\\\\n            _vaultShortAmount.div(2)\\\\n        );\\\\n\\\\n        if (_vaultCollateralAmount > collateralToPay) {\\\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\\\n                // calculate the new liquidation amount and collateral again based on the new limit\\\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\\\n                    _maxWPowerPerpAmount,\\\\n                    _vaultShortAmount\\\\n                );\\\\n            }\\\\n        }\\\\n\\\\n        // check if final collateral to pay is greater than vault amount.\\\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\\\n        if (collateralToPay > _vaultCollateralAmount) {\\\\n            // force liquidator to pay full debt amount\\\\n            finalLiquidateAmount = _vaultShortAmount;\\\\n            collateralToPay = _vaultCollateralAmount;\\\\n        }\\\\n\\\\n        return (finalLiquidateAmount, collateralToPay);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\\\n     * @return collateralToPay total collateral the liquidator will get\\\\n     */\\\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\\\n        internal\\\\n        view\\\\n        returns (uint256, uint256)\\\\n    {\\\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\\\n            ? _maxLiquidatableWAmount\\\\n            : _maxInputWAmount;\\\\n\\\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\\\n            finalWAmountToLiquidate,\\\\n            oracle,\\\\n            wPowerPerpPool,\\\\n            wPowerPerp,\\\\n            weth\\\\n        );\\\\n\\\\n        // add 10% bonus for liquidators\\\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\\\n\\\\n        return (finalWAmountToLiquidate, collateralToPay);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\\\n     * @param _period max period that we intend to use\\\\n     * @return fair period not greator than _period to be used for both pools.\\\\n     */\\\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\\\n\\\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf10380c226b48c8be2aba71df6915ddfe04f2fdf6a6612643816ee351a72bc42\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8a9a4512f1fc29b14dcf97ca149f263f28de43191a3ee31336f2389e3f2f5f8e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/ABDKMath64x64.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: BSD-4-Clause\\\\n/*\\\\n * ABDK Math 64.64 Smart Contract Library.  Copyright \\\\u00a9 2019 by ABDK Consulting.\\\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\\\n * Copyright (c) 2019, ABDK Consulting\\\\n *\\\\n * All rights reserved.\\\\n *\\\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\\\n *\\\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\\\n */\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * Smart contract library of mathematical functions operating with signed\\\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\\\n * represented by int128 type holding only the numerator.\\\\n *\\\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\\\n * Changes (cont) - revert strings added\\\\n * solidity version set to ^0.7.0\\\\n */\\\\nlibrary ABDKMath64x64 {\\\\n    /*\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * -2^127\\\\n     */\\\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\\\n\\\\n    /*\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * 2^127-1\\\\n     */\\\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @param y signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\\\n        int256 result = (int256(x) * y) >> 64;\\\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\\\\\"MUL-OVUF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64 fixed point number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 256-bit integer number\\\\n     */\\\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\\\n        if (y == 0) return 0;\\\\n\\\\n        require(x >= 0, \\\\\\\"MULU-X0\\\\\\\");\\\\n\\\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\\\n        uint256 hi = uint256(x) * (y >> 128);\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"MULU-OF1\\\\\\\");\\\\n        hi <<= 64;\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\\\\\"MULU-OF2\\\\\\\");\\\\n        return hi + lo;\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\\\n        require(y != 0, \\\\\\\"DIVU-INF\\\\\\\");\\\\n        uint128 result = divuu(x, y);\\\\n        require(result <= uint128(MAX_64x64), \\\\\\\"DIVU-OF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function log_2(int128 x) public pure returns (int128) {\\\\n        require(x > 0, \\\\\\\"LOG_2-X0\\\\\\\");\\\\n\\\\n        int256 msb = 0;\\\\n        int256 xc = x;\\\\n        if (xc >= 0x10000000000000000) {\\\\n            xc >>= 64;\\\\n            msb += 64;\\\\n        }\\\\n        if (xc >= 0x100000000) {\\\\n            xc >>= 32;\\\\n            msb += 32;\\\\n        }\\\\n        if (xc >= 0x10000) {\\\\n            xc >>= 16;\\\\n            msb += 16;\\\\n        }\\\\n        if (xc >= 0x100) {\\\\n            xc >>= 8;\\\\n            msb += 8;\\\\n        }\\\\n        if (xc >= 0x10) {\\\\n            xc >>= 4;\\\\n            msb += 4;\\\\n        }\\\\n        if (xc >= 0x4) {\\\\n            xc >>= 2;\\\\n            msb += 2;\\\\n        }\\\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n        int256 result = (msb - 64) << 64;\\\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\\\n            ux *= ux;\\\\n            uint256 b = ux >> 255;\\\\n            ux >>= 127 + b;\\\\n            result += bit * int256(b);\\\\n        }\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary exponent of x.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function exp_2(int128 x) public pure returns (int128) {\\\\n        require(x < 0x400000000000000000, \\\\\\\"EXP_2-OF\\\\\\\"); // Overflow\\\\n\\\\n        if (x < -0x400000000000000000) return 0; // Underflow\\\\n\\\\n        uint256 result = 0x80000000000000000000000000000000;\\\\n\\\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\\\n\\\\n        result >>= uint256(63 - (x >> 64));\\\\n        require(result <= uint256(MAX_64x64));\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 64.64-bit fixed point number\\\\n     */\\\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\\\n        require(y != 0);\\\\n\\\\n        uint256 result;\\\\n\\\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\\\n        else {\\\\n            uint256 msb = 192;\\\\n            uint256 xc = x >> 192;\\\\n            if (xc >= 0x100000000) {\\\\n                xc >>= 32;\\\\n                msb += 32;\\\\n            }\\\\n            if (xc >= 0x10000) {\\\\n                xc >>= 16;\\\\n                msb += 16;\\\\n            }\\\\n            if (xc >= 0x100) {\\\\n                xc >>= 8;\\\\n                msb += 8;\\\\n            }\\\\n            if (xc >= 0x10) {\\\\n                xc >>= 4;\\\\n                msb += 4;\\\\n            }\\\\n            if (xc >= 0x4) {\\\\n                xc >>= 2;\\\\n                msb += 2;\\\\n            }\\\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF1\\\\\\\");\\\\n\\\\n            uint256 hi = result * (y >> 128);\\\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\\\n\\\\n            uint256 xh = x >> 192;\\\\n            uint256 xl = x << 64;\\\\n\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n            lo = hi << 128;\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n\\\\n            assert(xh == hi >> 128);\\\\n\\\\n            result += xl / y;\\\\n        }\\\\n\\\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF2\\\\\\\");\\\\n        return uint128(result);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x56efa7c16e4fffb37ad80af15bd042d9f92532a4553d6b12915e3fa21609ad66\\\",\\\"license\\\":\\\"BSD-4-Clause\\\"},\\\"contracts/libs/Power2Base.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary Power2Base {\\\\n    using SafeMath for uint256;\\\\n\\\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\\\n    uint256 private constant INDEX_SCALE = 1e4;\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    /**\\\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getUnscaledIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\\\n     */\\\\n    function _getDenormalizedMark(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _wSqueeth,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\\\n\\\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _weth weth address\\\\n     * @return returns value of debt in ETH\\\\n     */\\\\n    function _getDebtValueInEth(\\\\n        uint256 _debtAmount,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _wSqueeth,\\\\n        address _weth\\\\n    ) internal view returns (uint256) {\\\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle\\\\n     * @dev this will revert if period is > max period for the pool\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        // period reaching this point should be check, otherwise might revert\\\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\\\n     * @param _indexPriceForSettlement index price for settlement\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return amount in wei that should be paid to the token holder\\\\n     */\\\\n    function _getLongSettlementValue(\\\\n        uint256 _wsqueethAmount,\\\\n        uint256 _indexPriceForSettlement,\\\\n        uint256 _normalizationFactor\\\\n    ) internal pure returns (uint256) {\\\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1938180c41ec0ee817b841df605b199e15ffbbe94700b640d031b4e4665a89af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x939175a827c8e9d8d09ee55957e8127a6a55bf42d6a0b3e48b0b59c895aa85af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101e060405260046005553480156200001757600080fd5b5060405162006630380380620066308339810160408190526200003a916200032c565b600062000046620002c4565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600180556001600160a01b038916620000c65760405162461bcd60e51b8152600401620000bd9062000462565b60405180910390fd5b6001600160a01b038816620000ef5760405162461bcd60e51b8152600401620000bd90620004b6565b6001600160a01b038716620001185760405162461bcd60e51b8152600401620000bd90620003f0565b6001600160a01b038616620001415760405162461bcd60e51b8152600401620000bd9062000446565b6001600160a01b0385166200016a5760405162461bcd60e51b8152600401620000bd906200049a565b6001600160a01b038416620001935760405162461bcd60e51b8152600401620000bd906200047e565b6001600160a01b038316620001bc5760405162461bcd60e51b8152600401620000bd906200040c565b6001600160a01b038216620001e55760405162461bcd60e51b8152600401620000bd9062000429565b6001600160601b031960608a811b82166101805289811b82166101405288811b82166101605287811b821660a05286811b821660c05285811b821660e05284811b82166101005283901b16610120526001600160e81b031960e882901b166080526001600160a01b038781169087161060f81b6101c052600780546001600160801b031916670de0b6b3a7640000179055426101a081905262000297906200274f620002c8602090811b91909117901c565b600780546001600160801b03928316600160801b02921691909117905550620004d2975050505050505050565b3390565b806001600160801b03811681146200030f576040805162461bcd60e51b815260206004820152600560248201526409e8c6264760db1b604482015290519081900360640190fd5b919050565b80516001600160a01b03811681146200030f57600080fd5b60008060008060008060008060006101208a8c0312156200034b578485fd5b620003568a62000314565b98506200036660208b0162000314565b97506200037660408b0162000314565b96506200038660608b0162000314565b95506200039660808b0162000314565b9450620003a660a08b0162000314565b9350620003b660c08b0162000314565b9250620003c660e08b0162000314565b91506101008a015162ffffff81168114620003df578182fd5b809150509295985092959850929598565b602080825260029082015261219b60f11b604082015260600190565b60208082526003908201526204331360ec1b604082015260600190565b60208082526003908201526243313160e81b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526002908201526110cd60f21b604082015260600190565b602080825260029082015261433960f01b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b602080825260029082015261433560f01b604082015260600190565b60805160e81c60a05160601c60c05160601c60e05160601c6101005160601c6101205160601c6101405160601c6101605160601c6101805160601c6101a0516101c05160f81c615f2f620007016000398061465452806148f55250806115bc525080610af15280610bc95280610d3a52806113f9528061173c528061243c5280612ac65280612b9a5280613e765280614050528061411052806144d452806145945280614cd35280614d7e525080610ddf528061141d5280611b9952806124e15280612b6b52806135da52806136525280613897528061393f5280613b125280613eb85280613f6b52806144125280614d155280614dc0525080611a795280611d9f5280611de05280611ff352806121a6528061270f5280612f395280613d6452508061339352806134bb52806136ff52806145685280614769525080610d5b5280611d7b528061245d5280612ae75280613e97528061413f52806145c35280614cf45280614d9f525080610b125280610bea5280610d7c528061109e528061175d528061247e5280612b085280612bbb528061407f52806144f5525080610b545280610c2c5280610dbe52806114b1528061179f52806124c05280612b4a5280612bfd52806145375250806103535280610b335280610c0b5280610d9d5280610ebc528061177e528061249f5280612b295280612bdc5280613616528061368e52806137fa5280613ed952806145165280614d365280614de15250806113c152806135915250615f2f6000f3fe6080604052600436106103435760003560e01c80638456cb59116101b0578063b707ab99116100ec578063e74b981b11610095578063f2fde38b1161006f578063f2fde38b146108d0578063f90c3f27146108f0578063fbfc6bc014610905578063ff947525146109255761039b565b8063e74b981b14610888578063ed88c68e146108a8578063ee3189ff146108b05761039b565b8063d296d1f1116100c6578063d296d1f11461083e578063d52725841461085e578063de4a427a146108735761039b565b8063b707ab99146107e9578063c65a391d146107fe578063c9e77ee81461081e5761039b565b806391b8d34a116101595780639d4c9442116101335780639d4c944214610781578063a847e67414610796578063ac6cd5ef146107b6578063b6b55f25146107d65761039b565b806391b8d34a1461072c578063978bbdb91461074c57806397efa942146107615761039b565b80638cd21d7c1161018a5780638cd21d7c146106e25780638da5cb5b1461070257806391b4ded9146107175761039b565b80638456cb591461067d5780638632cb03146106925780638c64ea4a146106b25761039b565b806345596e2e1161027f57806372f5d98a116102285780637dc0d1d0116102025780637dc0d1d0146106295780637f07b1301461063e5780638146b09f1461065357806382564bca146106685761039b565b806372f5d98a146105c35780637691c4ac146105e55780637ca25184146106075761039b565b806363b38ae41161025957806363b38ae414610579578063713d517f1461058e578063715018a6146105ae5761039b565b806345596e2e1461052257806346904840146105425780634be2822c146105575761039b565b806324f5f531116102ec5780633fc8cef3116102c65780633fc8cef3146104ab5780634394318d146104cd578063441a3e70146104ed5780634468c0221461050d5761039b565b806324f5f53114610463578063377a19361461047857806339467918146104985761039b565b806315aded831161031d57806315aded83146104005780631bf7bf6c1461042d578063200f4b8d1461044e5761039b565b806307633669146103a057806310b9e583146103b5578063150b7a02146103ca5761039b565b3661039b57336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103995760405162461bcd60e51b815260040161039090615cc9565b60405180910390fd5b005b600080fd5b3480156103ac57600080fd5b5061039961093a565b3480156103c157600080fd5b50610399610a3d565b3480156103d657600080fd5b506103ea6103e5366004615662565b610bb0565b6040516103f79190615ad9565b60405180910390f35b34801561040c57600080fd5b5061042061041b36600461584f565b610bc1565b6040516103f79190615df3565b61044061043b366004615824565b610c58565b6040516103f7929190615dfc565b34801561045a57600080fd5b50610399610cef565b34801561046f57600080fd5b50610420610d22565b34801561048457600080fd5b5061042061049336600461584f565b610d32565b6104206104a6366004615824565b610e22565b3480156104b757600080fd5b506104c0610eba565b6040516103f79190615961565b3480156104d957600080fd5b506104206104e8366004615824565b610ede565b3480156104f957600080fd5b506103996105083660046157e0565b610f78565b34801561051957600080fd5b506104c061109c565b34801561052e57600080fd5b5061039961053d366004615781565b6110c0565b34801561054e57600080fd5b506104c06111bd565b34801561056357600080fd5b5061056c6111cc565b6040516103f79190615da5565b34801561058557600080fd5b506104206111e2565b34801561059a57600080fd5b506103996105a9366004615781565b6111e8565b3480156105ba57600080fd5b50610399611301565b3480156105cf57600080fd5b506105d86113bf565b6040516103f79190615de3565b3480156105f157600080fd5b506105fa6113e3565b6040516103f79190615ace565b34801561061357600080fd5b5061061c6113f1565b6040516103f79190615e0a565b34801561063557600080fd5b506104c06113f7565b34801561064a57600080fd5b506104c061141b565b34801561065f57600080fd5b5061039961143f565b34801561067457600080fd5b506104c06114af565b34801561068957600080fd5b506103996114d3565b34801561069e57600080fd5b506103996106ad366004615824565b61165c565b3480156106be57600080fd5b506106d26106cd366004615781565b6116e7565b6040516103f79493929190615a90565b3480156106ee57600080fd5b506104206106fd36600461584f565b611734565b34801561070e57600080fd5b506104c06117c3565b34801561072357600080fd5b506104206117d2565b34801561073857600080fd5b506103996107473660046157e0565b6117d8565b34801561075857600080fd5b506104206118d1565b34801561076d57600080fd5b5061039961077c366004615781565b6118d7565b34801561078d57600080fd5b506104c0611a77565b3480156107a257600080fd5b506105fa6107b1366004615781565b611a9b565b3480156107c257600080fd5b506103996107d1366004615781565b611b15565b6103996107e4366004615781565b611c6f565b3480156107f557600080fd5b506104c0611d79565b34801561080a57600080fd5b506103996108193660046157b1565b611d9d565b34801561082a57600080fd5b50610399610839366004615781565b611efb565b34801561084a57600080fd5b506104206108593660046157e0565b61208d565b34801561086a57600080fd5b5061056c6122f8565b34801561087f57600080fd5b50610420612307565b34801561089457600080fd5b506103996108a336600461562a565b61230d565b610399612410565b3480156108bc57600080fd5b506104206108cb36600461584f565b612434565b3480156108dc57600080fd5b506103996108eb36600461562a565b61250d565b3480156108fc57600080fd5b50610420612621565b34801561091157600080fd5b50610399610920366004615781565b612628565b34801561093157600080fd5b506105fa612746565b6109426127ad565b6001600160a01b03166109536117c3565b6001600160a01b0316146109ae576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600854610100900460ff166109d55760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156109f85760405162461bcd60e51b815260040161039090615b53565b6008805461ff00191690556040517fff2b959f2bcdb44c7ecb4b16dae055431019d7350607125cfc2b74a06632c90e90610a33903390615961565b60405180910390a1565b610a456127ad565b6001600160a01b0316610a566117c3565b6001600160a01b031614610ab1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff1615610ad45760405162461bcd60e51b815260040161039090615b53565b6008805460ff1961ff001990911661010017166001179055610b7d7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460006127b1565b60048190556040517f574214b195bf5273a95bb4498e35cf1fde0ce327c727a95ec2ab359f7ba4e11a91610a3391615df3565b630a85bd0160e11b5b949350505050565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006127de565b90505b919050565b6008546000908190610100900460ff1615610c855760405162461bcd60e51b815260040161039090615c39565b60026001541415610ccb576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610cdf33868634876000612819565b6001805590969095509350505050565b600854610100900460ff1615610d175760405162461bcd60e51b815260040161039090615c39565b610d1f61296a565b50565b6000610d2c612a58565b90505b90565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000600760009054906101000a90046001600160801b03166001600160801b0316612ee9565b600854600090610100900460ff1615610e4d5760405162461bcd60e51b815260040161039090615c39565b60026001541415610e93576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001819055506000610eac33868634876001612819565b506001805595945050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854600090610100900460ff1615610f095760405162461bcd60e51b815260040161039090615c39565b60026001541415610f4f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610f5e8433612f2d565b610f6c338585856000613021565b60018055949350505050565b600854610100900460ff1615610fa05760405162461bcd60e51b815260040161039090615c39565b60026001541415610fe6576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610ff58233612f2d565b6000610fff61296a565b600084815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915061107481858561310f565b61107e8183613159565b61108884826131ab565b611092338461327e565b5050600180555050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6110c86127ad565b6001600160a01b03166110d96117c3565b6001600160a01b031614611134576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6002546001600160a01b031661115c5760405162461bcd60e51b815260040161039090615afc565b606481111561117d5760405162461bcd60e51b815260040161039090615c55565b7f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957600354826040516111b0929190615dfc565b60405180910390a1600355565b6002546001600160a01b031681565b600754600160801b90046001600160801b031681565b60055481565b600854610100900460ff16156112105760405162461bcd60e51b815260040161039090615c39565b60026001541415611256576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556112658133612f2d565b600061126f61296a565b600083815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506112e4813385613368565b6112ee8183613159565b6112f883826131ab565b50506001805550565b6113096127ad565b6001600160a01b031661131a6117c3565b6001600160a01b031614611375576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff1681565b6101a481565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff166114665760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156114895760405162461bcd60e51b815260040161039090615b53565b600654620151800142116109f85760405162461bcd60e51b815260040161039090615be3565b7f000000000000000000000000000000000000000000000000000000000000000081565b6114db6127ad565b6001600160a01b03166114ec6117c3565b6001600160a01b031614611547576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff161561156a5760405162461bcd60e51b815260040161039090615b53565b600854610100900460ff16156115925760405162461bcd60e51b815260040161039090615c39565b6000600554116115b45760405162461bcd60e51b815260040161039090615b6f565b60006115e0427f000000000000000000000000000000000000000000000000000000000000000061343f565b905062eff10081106116045760405162461bcd60e51b815260040161039090615ce6565b6008805461ff001916610100179055600580546000190190819055426006556040517f32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e9161165191615df3565b60405180910390a150565b600854610100900460ff16156116845760405162461bcd60e51b815260040161039090615c39565b600260015414156116ca576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556116d98333612f2d565b611092338484846001613021565b600960205260009081526040902080546001909101546001600160a01b03821691600160a01b900463ffffffff16906001600160601b03811690600160601b90046001600160801b031684565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b6000546001600160a01b031690565b60065481565b600854610100900460ff16156118005760405162461bcd60e51b815260040161039090615c39565b60026001541415611846576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556118558233612f2d565b61185d61296a565b50600082815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201526112ee813385856134b3565b60035481565b60085460ff166118f95760405162461bcd60e51b815260040161039090615d03565b6002600154141561193f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b600260015561194e8133612f2d565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b03908116606083015260075491929116906119cc908390339086906137af565b5060006119e983606001516001600160801b0316600454846139fa565b90506000611a0d8285604001516001600160601b031661343f90919063ffffffff16565b60006060860181905260408601529050611a2785856131ab565b611a31338261327e565b7f7dff8cdaec6a8d4d1ad32d3c947ed0f0281c3d6456621ef928defae96ec6cddb338683604051611a64939291906159d5565b60405180910390a1505060018055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b0316606082015281611b09612a58565b9050610bb98282613a23565b60085460ff16611b375760405162461bcd60e51b815260040161039090615d03565b60026001541415611b7d576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90611bd09033908590600401615999565b600060405180830381600087803b158015611bea57600080fd5b505af1158015611bfe573d6000803e3d6000fd5b505060045460075460009350611c2092508491906001600160801b03166139fa565b9050611c2c338261327e565b7f2131ef4f2f82ca75fe7d2e646ebfa45b6be25e53510c829629c76b641500ec67338383604051611c5f939291906159d5565b60405180910390a1505060018055565b600854610100900460ff1615611c975760405162461bcd60e51b815260040161039090615c39565b60026001541415611cdd576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611cec8133612f2d565b611cf461296a565b50600081815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b03166060820152611d67818334613a39565b611d7182826131ab565b505060018055565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331480611e7857506040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611e1d908690600401615df3565b60206040518083038186803b158015611e3557600080fd5b505afa158015611e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6d9190615646565b6001600160a01b0316145b611e945760405162461bcd60e51b815260040161039090615b19565b6000828152600960205260409081902080546001600160a01b0319166001600160a01b038416179055517f3137fc9cd2e33c34f86e29c24d81f3c75b0bce639d3c4ed0d31eeff1160a7ff590611eef903390859085906159b2565b60405180910390a15050565b600854610100900460ff1615611f235760405162461bcd60e51b815260040161039090615c39565b60026001541415611f69576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611f788133612f2d565b600081815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093526001909101546001600160601b03811682850152600160601b90046001600160801b0316606082015291516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60206040518083038186803b15801561204257600080fd5b505afa158015612056573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207a9190615646565b8460006137af565b50611d7182826131ab565b600854600090610100900460ff16156120b85760405162461bcd60e51b815260040161039090615c39565b600260015414156120fe576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155600061210d61296a565b600085815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506121818183613a23565b1561219e5760405162461bcd60e51b815260040161039090615c72565b6000612248827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e896040518263ffffffff1660e01b81526004016121f09190615df3565b60206040518083038186803b15801561220857600080fd5b505afa15801561221c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122409190615646565b8860016137af565b90506122548284613a23565b156122795761226386836131ab565b61226d338261327e565b600093505050506122ee565b6122838282613a76565b60008061229284888733613aac565b915091507f158ba9ab7bbbd08eeffa4753bad41f4d450e24831d293427308badf3eadd8c76338984846040516122cb94939291906159f6565b60405180910390a16122dd88856131ab565b6122e7338261327e565b5093505050505b6001805592915050565b6007546001600160801b031681565b60045481565b6123156127ad565b6001600160a01b03166123266117c3565b6001600160a01b031614612381576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166123a75760405162461bcd60e51b815260040161039090615b8c565b6002546040517faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d3916123e6916001600160a01b03909116908490615a57565b60405180910390a1600280546001600160a01b0319166001600160a01b0392909216919091179055565b60085460ff166124325760405162461bcd60e51b815260040161039090615d03565b565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612508612a58565b612ee9565b6125156127ad565b6001600160a01b03166125266117c3565b6001600160a01b031614612581576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166125c65760405162461bcd60e51b8152600401808060200182810382526026815260200180615e796026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6217124081565b60085460ff1661264a5760405162461bcd60e51b815260040161039090615d03565b60026001541415612690576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001908155600082815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093529301546001600160601b03811684840152600160601b90046001600160801b0316606084015290516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60085460ff1681565b806001600160801b0381168114610c53576040805162461bcd60e51b815260206004820152600560248201527f4f46313238000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b3390565b6000806127c2888888888888613bd3565b90506127d081612710613c79565b9150505b9695505050505050565b6000806127f0868686868b6000613bd3565b905061280e670de0b6b3a76400006128088380613ce0565b90613c79565b979650505050505050565b600080600061282661296a565b90508560008561284b57612846836128088b670de0b6b3a7640000613ce0565b61284d565b885b905060006128596155bc565b8b612871576128678d613d40565b909c5090506128e4565b61287b8c33612f2d565b5060008b815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201525b8215612905576128f581848c613e53565b94509150612905818e8e86613f4a565b891561291657612916818d86613a39565b881561292857612928818e8e8c6134b3565b6129328186613159565b61293c8c826131ab565b811561295857600254612958906001600160a01b03168361327e565b50999b909a5098505050505050505050565b6007546000906001600160801b03600160801b9091041642141561299a57506007546001600160801b0316610d2f565b60006129a4612a58565b6007546040519192507f339e53729b0447795ff69e70a74fed98fc7fef6fe94b7521099b32f0f8de4822916129f3916001600160801b03808216928692600160801b9004909116904290615db9565b60405180910390a1612a048161274f565b600780546fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055612a364261274f565b600780546001600160801b03928316600160801b029216919091179055905090565b6007546000908190612a8490612a7f904290600160801b90046001600160801b031661343f565b614007565b905063ffffffff8116612aa45750506007546001600160801b0316610d2f565b6000612aaf8261404b565b6007549091506001600160801b03166000612b90837f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000089612ee9565b90506000612c21847f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b905060007321A8D15322C257Abd2b22a56eDde758398be0F3263fc505d3787621712406040518363ffffffff1660e01b8152600401612c61929190615e1b565b60206040518083038186803b158015612c7957600080fd5b505af4158015612c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb19190615746565b90506000612cd3670de0b6b3a764000061280885670b1a2bc2ec500000613ce0565b905080841015612ce557809350612d15565b6000612d05670de0b6b3a76400006128088667136dcc951d8c0000613ce0565b905080851115612d13578094505b505b60405163fc505d3760e01b81526000907321A8D15322C257Abd2b22a56eDde758398be0F329063fc505d3790612d519087908990600401615dfc565b60206040518083038186803b158015612d6957600080fd5b505af4158015612d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da19190615746565b90506000612e39847321A8D15322C257Abd2b22a56eDde758398be0F32632cbbdee5856040518263ffffffff1660e01b8152600401612de09190615aee565b60206040518083038186803b158015612df857600080fd5b505af4158015612e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e309190615746565b600f0b9061420f565b604051637e0c9e7960e11b81529091506000907321A8D15322C257Abd2b22a56eDde758398be0F329063fc193cf290612e7a90600f86900b90600401615aee565b60206040518083038186803b158015612e9257600080fd5b505af4158015612ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eca9190615746565b9050612eda600f82900b896142a0565b9a505050505050505050505090565b600080612efb898888888e60006127b1565b90506000612f0e8a8a878a8f6000613bd3565b9050612f1e846128088385613ce0565b9b9a5050505050505050505050565b806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e846040518263ffffffff1660e01b8152600401612f839190615df3565b60206040518083038186803b158015612f9b57600080fd5b505afa158015612faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd39190615646565b6001600160a01b0316148061300157506000828152600960205260409020546001600160a01b038281169116145b61301d5760405162461bcd60e51b815260040161039090615b19565b5050565b60008061302c61296a565b90506000836130505761304b8261280888670de0b6b3a7640000613ce0565b613052565b855b600088815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915081156130ce576130ce818a8a856143f1565b85156130df576130df81898861310f565b6130e98184613159565b6130f388826131ab565b851561310357613103338761327e565b50979650505050505050565b61311983826144ae565b7f627a692d5a03ab34732c0d2aa319f3ecdebdc4528f383eabcb25441dc0a70cfb33838360405161314c939291906159d5565b60405180910390a1505050565b60008061316684846144ca565b91509150816131875760405162461bcd60e51b815260040161039090615c8f565b80156131a55760405162461bcd60e51b815260040161039090615cac565b50505050565b600091825260096020908152604092839020825181549284015163ffffffff16600160a01b027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff6001600160a01b039092166001600160a01b0319909416939093171691909117815591810151600190920180546060909201516001600160801b0316600160601b027fffffffff00000000000000000000000000000000ffffffffffffffffffffffff6001600160601b039094166bffffffffffffffffffffffff199093169290921792909216179055565b804710156132d3576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d806000811461331e576040519150601f19603f3d011682016040523d82523d6000602084013e613323565b606091505b50509050806133635760405162461bcd60e51b815260040180806020018281038252603a815260200180615e9f603a913960400191505060405180910390fd5b505050565b602083015163ffffffff1661337c84614684565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906133cc90309087908690600401615975565b600060405180830381600087803b1580156133e657600080fd5b505af11580156133fa573d6000803e3d6000fd5b505050507fe59f38fa1264fc25c9f0185eee136eaf810d90b8e7293b342e4037c68720177a338383604051613431939291906159d5565b60405180910390a150505050565b600082821115613496576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000806127f0868686868b60006127b1565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166399fbab88866040518263ffffffff1660e01b81526004016135059190615df3565b6101806040518083038186803b15801561351e57600080fd5b505afa158015613532573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135569190615887565b505050509750505095509550955050506000816001600160801b03161161358f5760405162461bcd60e51b815260040161039090615bc6565b7f000000000000000000000000000000000000000000000000000000000000000062ffffff168262ffffff16146135d85760405162461bcd60e51b815260040161039090615b36565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614801561364a57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b806136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161480156136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b6136de5760405162461bcd60e51b815260040161039090615ba9565b6136e888866146cf565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613738908a9030908a90600401615975565b600060405180830381600087803b15801561375257600080fd5b505af1158015613766573d6000803e3d6000fd5b505050507f3917c2f26ce18614e3aedd1289da672ef6563c5c295f49e9b1697ae0ad31556233878760405161379d939291906159d5565b60405180910390a15050505050505050565b602084015160009063ffffffff16806137cc576000915050610bb9565b6000806137d883614764565b9092509050811561386257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061382f908590600401615df3565b600060405180830381600087803b15801561384957600080fd5b505af115801561385d573d6000803e3d6000fd5b505050505b60008060006138738b86868b614931565b9194509250905081156139225760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906138ce908d908690600401615999565b602060405180830381600087803b1580156138e857600080fd5b505af11580156138fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139209190615726565b505b82156139a957604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906139769030908790600401615999565b600060405180830381600087803b15801561399057600080fd5b505af11580156139a4573d6000803e3d6000fd5b505050505b7ffd0ae2fd36bd955810ae42615bc5ff277c0d0dfcb930f06c9f1777c0ef0752e3338a87878787876040516139e49796959493929190615a1c565b60405180910390a19a9950505050505050505050565b6000610bb96ec097ce7bc90715b34b9f100000000061280885613a1d8887613ce0565b90613ce0565b600080613a3084846144ca565b50949350505050565b613a438382613a76565b7f3ca13b7aab12bad7472691fe558faa6b25e99099824a0070a88bd5aa84be610f33838360405161314c939291906159d5565b6040820151613a9790613a92906001600160601b0316836149c7565b614a21565b6001600160601b031660409092019190915250565b600080600080613ad78789606001516001600160801b03168a604001516001600160601b0316614a68565b9150915081871015613afb5760405162461bcd60e51b815260040161039090615c00565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90613b499088908690600401615999565b600060405180830381600087803b158015613b6357600080fd5b505af1158015613b77573d6000803e3d6000fd5b50505050613b8e8289614ad090919063ffffffff16565b613b9888826144ae565b6000613ba489886144ca565b9150508015613bc55760405162461bcd60e51b815260040161039090615cac565b509097909650945050505050565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b158015613c4257600080fd5b505afa158015613c56573d6000803e3d6000fd5b505050506040513d6020811015613c6c57600080fd5b5051979650505050505050565b6000808211613ccf576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613cd857fe5b049392505050565b600082613cef5750600061349b565b82820282848281613cfc57fe5b0414613d395760405162461bcd60e51b8152600401808060200182810382526021815260200180615ed96021913960400191505060405180910390fd5b9392505050565b6000613d4a6155bc565b6040516354ba0f2760e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906354ba0f2790613d99908790600401615961565b602060405180830381600087803b158015613db357600080fd5b505af1158015613dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613deb9190615799565b6040805160808101825260008082526020820181905281830181905260608201529051919250907f25ff1e0131762176a9084e92880f880f39d6d0e62134607f37e631efe1bad87190613e419033908590615999565b60405180910390a19092509050915091565b600354600090819080613e6d576000849250925050613f42565b600080613efd877f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b90506000613f116127106128088487613ce0565b905080871115613f2c57613f25878261343f565b9250613f3a565b613f3689826144ae565b8692505b945090925050505b935093915050565b613f548482614b32565b6040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990613fa29086908590600401615999565b600060405180830381600087803b158015613fbc57600080fd5b505af1158015613fd0573d6000803e3d6000fd5b505050507fb19fa182730a088464dad0e9e0badeb470d0d8d937d854f5caf15c6ad1992c36338284604051613431939291906159d5565b8063ffffffff81168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a3199960e11b604482015290519081900360640190fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b81526004016140ba9190615961565b60206040518083038186803b1580156140d257600080fd5b505afa1580156140e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410a919061586b565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040161417a9190615961565b60206040518083038186803b15801561419257600080fd5b505afa1580156141a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141ca919061586b565b905060008163ffffffff168363ffffffff16116141e757826141e9565b815b90508063ffffffff168563ffffffff16116142045784614206565b805b95945050505050565b6000600f83810b9083900b0260401d6f7fffffffffffffffffffffffffffffff19811280159061424f57506f7fffffffffffffffffffffffffffffff8113155b613d39576040805162461bcd60e51b815260206004820152600860248201527f4d554c2d4f565546000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000816142af5750600061349b565b600083600f0b1215614308576040805162461bcd60e51b815260206004820152600760248201527f4d554c552d583000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600f83900b6001600160801b038316810260401c90608084901c0277ffffffffffffffffffffffffffffffffffffffffffffffff811115614390576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4631000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60401b81198111156143e9576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4632000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b019392505050565b6143fb8482614ad0565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906144499086908590600401615999565b600060405180830381600087803b15801561446357600080fd5b505af1158015614477573d6000803e3d6000fd5b505050507fea19ffc45b48de6d95594aacff7214dd24595fdb0c60e98c8f0b269058c2f792338284604051613431939291906159d5565b6040820151613a9790613a92906001600160601b03168361343f565b60008060006145607f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460016127b1565b9050614678857f00000000000000000000000000000000000000000000000000000000000000008684675fc1b971363200007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634a0a96eb7f00000000000000000000000000000000000000000000000000000000000000006101a46040518363ffffffff1660e01b8152600401614602929190615a71565b60206040518083038186803b15801561461a57600080fd5b505afa15801561462e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146529190615767565b7f0000000000000000000000000000000000000000000000000000000000000000614b4e565b92509250509250929050565b602081015163ffffffff166146c5576040805162461bcd60e51b81526020600482015260026024820152612b1960f11b604482015290519081900360640190fd5b6000602090910152565b602082015163ffffffff1615614711576040805162461bcd60e51b8152602060048201526002602482015261563160f01b604482015290519081900360640190fd5b80614749576040805162461bcd60e51b815260206004820152600360248201526243323360e81b604482015290519081900360640190fd5b61475281614007565b63ffffffff1660209092019190915250565b6000807f0000000000000000000000000000000000000000000000000000000000000000816147938286614bf2565b50506040805160a0810182528981526001600160801b0383166020820152600081830181905260608201524260808201529051630624e65f60e11b815291945092506001600160a01b0385169150630c49ccbe906147f5908490600401615d62565b6040805180830381600087803b15801561480e57600080fd5b505af1158015614822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148469190615801565b5050604080516080810182528781523060208201526001600160801b038183018190526060820152905163fc6f786560e01b815260009081906001600160a01b0387169063fc6f78659061489e908690600401615d1f565b6040805180830381600087803b1580156148b757600080fd5b505af11580156148cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148ef9190615801565b915091507f000000000000000000000000000000000000000000000000000000000000000061491f578082614922565b81815b97509750505050505050915091565b600080600080841561494a576149478787614cb0565b90505b606088015186906000906001600160801b03168211156149905760608a015161497d9089906001600160801b031661343f565b905089606001516001600160801b031691505b61499a8a83614ad0565b6149a38a614684565b6149ad8a8a613a76565b6149b78a846144ae565b9099909850909650945050505050565b600082820183811015613d39576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b806001600160601b0381168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a31c9b60e11b604482015290519081900360640190fd5b6000808080614a8187614a7c886002613c79565b614d60565b9150915080851115614ab657675fc1b97136320000614aa0868361343f565b1015614ab657614ab08787614d60565b90925090505b84811115614ac45750849050835b90969095509350505050565b6060820151614af190614aec906001600160801b03168361343f565b61274f565b6001600160801b031660609092019190915250565b600080614b1a868686866101a46000613bd3565b905061280e670de0b6b3a76400006128088984613ce0565b6060820151614af190614aec906001600160801b0316836149c7565b60008088606001516001600160801b031660001415614b735750600190506000614be6565b6000614bac6ec097ce7bc90715b34b9f100000000061280889613a1d8c8f606001516001600160801b0316613ce090919063ffffffff16565b90506000614bbe8b8b8b8b8a8a614e3c565b90508681106000614bd0846003613ce0565b614bdb846002613ce0565b101595509093505050505b97509795505050505050565b6000806000806000808790506000806000806000856001600160a01b03166399fbab888d6040518263ffffffff1660e01b8152600401808281526020019150506101806040518083038186803b158015614c4b57600080fd5b505afa158015614c5f573d6000803e3d6000fd5b505050506040513d610180811015614c7657600080fd5b5060a081015160c082015160e083015161014084015161016090940151929e50909c509a5090985096505050505050509295509295909350565b6000613d39670de0b6b3a764000061280866470de4df820000613a1d87614d5a887f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b906149c7565b6000806000838511614d725784614d74565b835b90506000614e05827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b9050614e2f614e28670de0b6b3a76400006128088467016345785d8a0000613ce0565b82906149c7565b9196919550909350505050565b6000866020015163ffffffff1660001415614e65575060408601516001600160601b03166127d4565b600080614e7e888a6020015163ffffffff168787614ed3565b90925090506000614ea66ec097ce7bc90715b34b9f100000000061280889613a1d868d613ce0565b60408b0151909150614ec5906001600160601b0316614d5a85846149c7565b9a9950505050505050505050565b6000806000806000806000614ee88b8b614bf2565b94509450945094509450600080614f0187878d88614f54565b9150915089614f2757826001600160801b03168101846001600160801b03168301614f40565b836001600160801b03168201836001600160801b031682015b985098505050505050505094509492505050565b6000806000734d9d7F7aE80d51628Aa56eF37720718C99E6FDfC63986cfba3866040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b158015614fab57600080fd5b505af4158015614fbf573d6000803e3d6000fd5b505050506040513d6020811015614fd557600080fd5b50519050600287810b9086900b121561519857739cf8dcbCf115B06d8f577E73Cb9EdFdb27828460632c32d4b6734d9d7F7aE80d51628Aa56eF37720718C99E6FDfC63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561505457600080fd5b505af4158015615068573d6000803e3d6000fd5b505050506040513d602081101561507e57600080fd5b50516040805163986cfba360e01b815260028b900b60048201529051734d9d7F7aE80d51628Aa56eF37720718C99E6FDfC9163986cfba3916024808301926020929190829003018186803b1580156150d557600080fd5b505af41580156150e9573d6000803e3d6000fd5b505050506040513d60208110156150ff57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561516557600080fd5b505af4158015615179573d6000803e3d6000fd5b505050506040513d602081101561518f57600080fd5b505192506155b2565b8560020b8560020b121561540657739cf8dcbCf115B06d8f577E73Cb9EdFdb27828460632c32d4b682734d9d7F7aE80d51628Aa56eF37720718C99E6FDfC63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561521357600080fd5b505af4158015615227573d6000803e3d6000fd5b505050506040513d602081101561523d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156152a357600080fd5b505af41580156152b7573d6000803e3d6000fd5b505050506040513d60208110156152cd57600080fd5b50516040805163986cfba360e01b815260028a900b60048201529051919450739cf8dcbCf115B06d8f577E73Cb9EdFdb27828460916348a0c5bd91734d9d7F7aE80d51628Aa56eF37720718C99E6FDfC9163986cfba391602480820192602092909190829003018186803b15801561534457600080fd5b505af4158015615358573d6000803e3d6000fd5b505050506040513d602081101561536e57600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b03928316600482015291851660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156153d357600080fd5b505af41580156153e7573d6000803e3d6000fd5b505050506040513d60208110156153fd57600080fd5b505191506155b2565b739cf8dcbCf115B06d8f577E73Cb9EdFdb278284606348a0c5bd734d9d7F7aE80d51628Aa56eF37720718C99E6FDfC63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561547257600080fd5b505af4158015615486573d6000803e3d6000fd5b505050506040513d602081101561549c57600080fd5b50516040805163986cfba360e01b815260028b900b60048201529051734d9d7F7aE80d51628Aa56eF37720718C99E6FDfC9163986cfba3916024808301926020929190829003018186803b1580156154f357600080fd5b505af4158015615507573d6000803e3d6000fd5b505050506040513d602081101561551d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561558357600080fd5b505af4158015615597573d6000803e3d6000fd5b505050506040513d60208110156155ad57600080fd5b505191505b5094509492505050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b8051610c5381615e31565b8051600281900b8114610c5357600080fd5b80516001600160801b0381168114610c5357600080fd5b805162ffffff81168114610c5357600080fd5b60006020828403121561563b578081fd5b8135613d3981615e31565b600060208284031215615657578081fd5b8151613d3981615e31565b60008060008060808587031215615677578283fd5b843561568281615e31565b935060208581013561569381615e31565b935060408601359250606086013567ffffffffffffffff808211156156b6578384fd5b818801915088601f8301126156c9578384fd5b8135818111156156d557fe5b604051601f8201601f19168101850183811182821017156156f257fe5b60405281815283820185018b1015615708578586fd5b81858501868301379081019093019390935250939692955090935050565b600060208284031215615737578081fd5b81518015158114613d39578182fd5b600060208284031215615757578081fd5b815180600f0b8114613d39578182fd5b600060208284031215615778578081fd5b613d39826155ee565b600060208284031215615792578081fd5b5035919050565b6000602082840312156157aa578081fd5b5051919050565b600080604083850312156157c3578182fd5b8235915060208301356157d581615e31565b809150509250929050565b600080604083850312156157f2578182fd5b50508035926020909101359150565b60008060408385031215615813578182fd5b505080516020909101519092909150565b600080600060608486031215615838578283fd5b505081359360208301359350604090920135919050565b600060208284031215615860578081fd5b8135613d3981615e46565b60006020828403121561587c578081fd5b8151613d3981615e46565b6000806000806000806000806000806000806101808d8f0312156158a957898afd5b8c516001600160601b03811681146158bf578a8bfd5b9b506158cd60208e016155e3565b9a506158db60408e016155e3565b99506158e960608e016155e3565b98506158f760808e01615617565b975061590560a08e016155ee565b965061591360c08e016155ee565b955061592160e08e01615600565b94506101008d015193506101208d015192506159406101408e01615600565b915061594f6101608e01615600565b90509295989b509295989b509295989b565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b03979097168752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0392909216825263ffffffff16602082015260400190565b6001600160a01b0394909416845263ffffffff9290921660208401526001600160601b031660408301526001600160801b0316606082015260800190565b901515815260200190565b6001600160e01b031991909116815260200190565b600f9190910b815260200190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b602080825260029082015261043360f41b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b602080825260029082015261433360f01b604082015260600190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b6001600160801b0391909116815260200190565b6001600160801b039485168152602081019390935292166040820152606081019190915260800190565b62ffffff91909116815260200190565b90815260200190565b918252602082015260400190565b63ffffffff91909116815260200190565b63ffffffff929092168252602082015260400190565b6001600160a01b0381168114610d1f57600080fd5b63ffffffff81168114610d1f57600080fdfe5265656e7472616e637947756172643a207265656e7472616e742063616c6c004f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212201ca81e10125d74fc4d8a6f7c39e0648cc26a50a8c5deec6ca4fb49cb3041e74964736f6c63430007060033\",\n  \"deployedBytecode\": \"0x6080604052600436106103435760003560e01c80638456cb59116101b0578063b707ab99116100ec578063e74b981b11610095578063f2fde38b1161006f578063f2fde38b146108d0578063f90c3f27146108f0578063fbfc6bc014610905578063ff947525146109255761039b565b8063e74b981b14610888578063ed88c68e146108a8578063ee3189ff146108b05761039b565b8063d296d1f1116100c6578063d296d1f11461083e578063d52725841461085e578063de4a427a146108735761039b565b8063b707ab99146107e9578063c65a391d146107fe578063c9e77ee81461081e5761039b565b806391b8d34a116101595780639d4c9442116101335780639d4c944214610781578063a847e67414610796578063ac6cd5ef146107b6578063b6b55f25146107d65761039b565b806391b8d34a1461072c578063978bbdb91461074c57806397efa942146107615761039b565b80638cd21d7c1161018a5780638cd21d7c146106e25780638da5cb5b1461070257806391b4ded9146107175761039b565b80638456cb591461067d5780638632cb03146106925780638c64ea4a146106b25761039b565b806345596e2e1161027f57806372f5d98a116102285780637dc0d1d0116102025780637dc0d1d0146106295780637f07b1301461063e5780638146b09f1461065357806382564bca146106685761039b565b806372f5d98a146105c35780637691c4ac146105e55780637ca25184146106075761039b565b806363b38ae41161025957806363b38ae414610579578063713d517f1461058e578063715018a6146105ae5761039b565b806345596e2e1461052257806346904840146105425780634be2822c146105575761039b565b806324f5f531116102ec5780633fc8cef3116102c65780633fc8cef3146104ab5780634394318d146104cd578063441a3e70146104ed5780634468c0221461050d5761039b565b806324f5f53114610463578063377a19361461047857806339467918146104985761039b565b806315aded831161031d57806315aded83146104005780631bf7bf6c1461042d578063200f4b8d1461044e5761039b565b806307633669146103a057806310b9e583146103b5578063150b7a02146103ca5761039b565b3661039b57336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103995760405162461bcd60e51b815260040161039090615cc9565b60405180910390fd5b005b600080fd5b3480156103ac57600080fd5b5061039961093a565b3480156103c157600080fd5b50610399610a3d565b3480156103d657600080fd5b506103ea6103e5366004615662565b610bb0565b6040516103f79190615ad9565b60405180910390f35b34801561040c57600080fd5b5061042061041b36600461584f565b610bc1565b6040516103f79190615df3565b61044061043b366004615824565b610c58565b6040516103f7929190615dfc565b34801561045a57600080fd5b50610399610cef565b34801561046f57600080fd5b50610420610d22565b34801561048457600080fd5b5061042061049336600461584f565b610d32565b6104206104a6366004615824565b610e22565b3480156104b757600080fd5b506104c0610eba565b6040516103f79190615961565b3480156104d957600080fd5b506104206104e8366004615824565b610ede565b3480156104f957600080fd5b506103996105083660046157e0565b610f78565b34801561051957600080fd5b506104c061109c565b34801561052e57600080fd5b5061039961053d366004615781565b6110c0565b34801561054e57600080fd5b506104c06111bd565b34801561056357600080fd5b5061056c6111cc565b6040516103f79190615da5565b34801561058557600080fd5b506104206111e2565b34801561059a57600080fd5b506103996105a9366004615781565b6111e8565b3480156105ba57600080fd5b50610399611301565b3480156105cf57600080fd5b506105d86113bf565b6040516103f79190615de3565b3480156105f157600080fd5b506105fa6113e3565b6040516103f79190615ace565b34801561061357600080fd5b5061061c6113f1565b6040516103f79190615e0a565b34801561063557600080fd5b506104c06113f7565b34801561064a57600080fd5b506104c061141b565b34801561065f57600080fd5b5061039961143f565b34801561067457600080fd5b506104c06114af565b34801561068957600080fd5b506103996114d3565b34801561069e57600080fd5b506103996106ad366004615824565b61165c565b3480156106be57600080fd5b506106d26106cd366004615781565b6116e7565b6040516103f79493929190615a90565b3480156106ee57600080fd5b506104206106fd36600461584f565b611734565b34801561070e57600080fd5b506104c06117c3565b34801561072357600080fd5b506104206117d2565b34801561073857600080fd5b506103996107473660046157e0565b6117d8565b34801561075857600080fd5b506104206118d1565b34801561076d57600080fd5b5061039961077c366004615781565b6118d7565b34801561078d57600080fd5b506104c0611a77565b3480156107a257600080fd5b506105fa6107b1366004615781565b611a9b565b3480156107c257600080fd5b506103996107d1366004615781565b611b15565b6103996107e4366004615781565b611c6f565b3480156107f557600080fd5b506104c0611d79565b34801561080a57600080fd5b506103996108193660046157b1565b611d9d565b34801561082a57600080fd5b50610399610839366004615781565b611efb565b34801561084a57600080fd5b506104206108593660046157e0565b61208d565b34801561086a57600080fd5b5061056c6122f8565b34801561087f57600080fd5b50610420612307565b34801561089457600080fd5b506103996108a336600461562a565b61230d565b610399612410565b3480156108bc57600080fd5b506104206108cb36600461584f565b612434565b3480156108dc57600080fd5b506103996108eb36600461562a565b61250d565b3480156108fc57600080fd5b50610420612621565b34801561091157600080fd5b50610399610920366004615781565b612628565b34801561093157600080fd5b506105fa612746565b6109426127ad565b6001600160a01b03166109536117c3565b6001600160a01b0316146109ae576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600854610100900460ff166109d55760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156109f85760405162461bcd60e51b815260040161039090615b53565b6008805461ff00191690556040517fff2b959f2bcdb44c7ecb4b16dae055431019d7350607125cfc2b74a06632c90e90610a33903390615961565b60405180910390a1565b610a456127ad565b6001600160a01b0316610a566117c3565b6001600160a01b031614610ab1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff1615610ad45760405162461bcd60e51b815260040161039090615b53565b6008805460ff1961ff001990911661010017166001179055610b7d7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460006127b1565b60048190556040517f574214b195bf5273a95bb4498e35cf1fde0ce327c727a95ec2ab359f7ba4e11a91610a3391615df3565b630a85bd0160e11b5b949350505050565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006127de565b90505b919050565b6008546000908190610100900460ff1615610c855760405162461bcd60e51b815260040161039090615c39565b60026001541415610ccb576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610cdf33868634876000612819565b6001805590969095509350505050565b600854610100900460ff1615610d175760405162461bcd60e51b815260040161039090615c39565b610d1f61296a565b50565b6000610d2c612a58565b90505b90565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000600760009054906101000a90046001600160801b03166001600160801b0316612ee9565b600854600090610100900460ff1615610e4d5760405162461bcd60e51b815260040161039090615c39565b60026001541415610e93576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001819055506000610eac33868634876001612819565b506001805595945050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854600090610100900460ff1615610f095760405162461bcd60e51b815260040161039090615c39565b60026001541415610f4f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610f5e8433612f2d565b610f6c338585856000613021565b60018055949350505050565b600854610100900460ff1615610fa05760405162461bcd60e51b815260040161039090615c39565b60026001541415610fe6576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610ff58233612f2d565b6000610fff61296a565b600084815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915061107481858561310f565b61107e8183613159565b61108884826131ab565b611092338461327e565b5050600180555050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6110c86127ad565b6001600160a01b03166110d96117c3565b6001600160a01b031614611134576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6002546001600160a01b031661115c5760405162461bcd60e51b815260040161039090615afc565b606481111561117d5760405162461bcd60e51b815260040161039090615c55565b7f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957600354826040516111b0929190615dfc565b60405180910390a1600355565b6002546001600160a01b031681565b600754600160801b90046001600160801b031681565b60055481565b600854610100900460ff16156112105760405162461bcd60e51b815260040161039090615c39565b60026001541415611256576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556112658133612f2d565b600061126f61296a565b600083815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506112e4813385613368565b6112ee8183613159565b6112f883826131ab565b50506001805550565b6113096127ad565b6001600160a01b031661131a6117c3565b6001600160a01b031614611375576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff1681565b6101a481565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff166114665760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156114895760405162461bcd60e51b815260040161039090615b53565b600654620151800142116109f85760405162461bcd60e51b815260040161039090615be3565b7f000000000000000000000000000000000000000000000000000000000000000081565b6114db6127ad565b6001600160a01b03166114ec6117c3565b6001600160a01b031614611547576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff161561156a5760405162461bcd60e51b815260040161039090615b53565b600854610100900460ff16156115925760405162461bcd60e51b815260040161039090615c39565b6000600554116115b45760405162461bcd60e51b815260040161039090615b6f565b60006115e0427f000000000000000000000000000000000000000000000000000000000000000061343f565b905062eff10081106116045760405162461bcd60e51b815260040161039090615ce6565b6008805461ff001916610100179055600580546000190190819055426006556040517f32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e9161165191615df3565b60405180910390a150565b600854610100900460ff16156116845760405162461bcd60e51b815260040161039090615c39565b600260015414156116ca576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556116d98333612f2d565b611092338484846001613021565b600960205260009081526040902080546001909101546001600160a01b03821691600160a01b900463ffffffff16906001600160601b03811690600160601b90046001600160801b031684565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b6000546001600160a01b031690565b60065481565b600854610100900460ff16156118005760405162461bcd60e51b815260040161039090615c39565b60026001541415611846576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556118558233612f2d565b61185d61296a565b50600082815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201526112ee813385856134b3565b60035481565b60085460ff166118f95760405162461bcd60e51b815260040161039090615d03565b6002600154141561193f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b600260015561194e8133612f2d565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b03908116606083015260075491929116906119cc908390339086906137af565b5060006119e983606001516001600160801b0316600454846139fa565b90506000611a0d8285604001516001600160601b031661343f90919063ffffffff16565b60006060860181905260408601529050611a2785856131ab565b611a31338261327e565b7f7dff8cdaec6a8d4d1ad32d3c947ed0f0281c3d6456621ef928defae96ec6cddb338683604051611a64939291906159d5565b60405180910390a1505060018055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b0316606082015281611b09612a58565b9050610bb98282613a23565b60085460ff16611b375760405162461bcd60e51b815260040161039090615d03565b60026001541415611b7d576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90611bd09033908590600401615999565b600060405180830381600087803b158015611bea57600080fd5b505af1158015611bfe573d6000803e3d6000fd5b505060045460075460009350611c2092508491906001600160801b03166139fa565b9050611c2c338261327e565b7f2131ef4f2f82ca75fe7d2e646ebfa45b6be25e53510c829629c76b641500ec67338383604051611c5f939291906159d5565b60405180910390a1505060018055565b600854610100900460ff1615611c975760405162461bcd60e51b815260040161039090615c39565b60026001541415611cdd576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611cec8133612f2d565b611cf461296a565b50600081815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b03166060820152611d67818334613a39565b611d7182826131ab565b505060018055565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331480611e7857506040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611e1d908690600401615df3565b60206040518083038186803b158015611e3557600080fd5b505afa158015611e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6d9190615646565b6001600160a01b0316145b611e945760405162461bcd60e51b815260040161039090615b19565b6000828152600960205260409081902080546001600160a01b0319166001600160a01b038416179055517f3137fc9cd2e33c34f86e29c24d81f3c75b0bce639d3c4ed0d31eeff1160a7ff590611eef903390859085906159b2565b60405180910390a15050565b600854610100900460ff1615611f235760405162461bcd60e51b815260040161039090615c39565b60026001541415611f69576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611f788133612f2d565b600081815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093526001909101546001600160601b03811682850152600160601b90046001600160801b0316606082015291516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60206040518083038186803b15801561204257600080fd5b505afa158015612056573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207a9190615646565b8460006137af565b50611d7182826131ab565b600854600090610100900460ff16156120b85760405162461bcd60e51b815260040161039090615c39565b600260015414156120fe576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155600061210d61296a565b600085815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506121818183613a23565b1561219e5760405162461bcd60e51b815260040161039090615c72565b6000612248827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e896040518263ffffffff1660e01b81526004016121f09190615df3565b60206040518083038186803b15801561220857600080fd5b505afa15801561221c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122409190615646565b8860016137af565b90506122548284613a23565b156122795761226386836131ab565b61226d338261327e565b600093505050506122ee565b6122838282613a76565b60008061229284888733613aac565b915091507f158ba9ab7bbbd08eeffa4753bad41f4d450e24831d293427308badf3eadd8c76338984846040516122cb94939291906159f6565b60405180910390a16122dd88856131ab565b6122e7338261327e565b5093505050505b6001805592915050565b6007546001600160801b031681565b60045481565b6123156127ad565b6001600160a01b03166123266117c3565b6001600160a01b031614612381576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166123a75760405162461bcd60e51b815260040161039090615b8c565b6002546040517faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d3916123e6916001600160a01b03909116908490615a57565b60405180910390a1600280546001600160a01b0319166001600160a01b0392909216919091179055565b60085460ff166124325760405162461bcd60e51b815260040161039090615d03565b565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612508612a58565b612ee9565b6125156127ad565b6001600160a01b03166125266117c3565b6001600160a01b031614612581576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166125c65760405162461bcd60e51b8152600401808060200182810382526026815260200180615e796026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6217124081565b60085460ff1661264a5760405162461bcd60e51b815260040161039090615d03565b60026001541415612690576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001908155600082815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093529301546001600160601b03811684840152600160601b90046001600160801b0316606084015290516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60085460ff1681565b806001600160801b0381168114610c53576040805162461bcd60e51b815260206004820152600560248201527f4f46313238000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b3390565b6000806127c2888888888888613bd3565b90506127d081612710613c79565b9150505b9695505050505050565b6000806127f0868686868b6000613bd3565b905061280e670de0b6b3a76400006128088380613ce0565b90613c79565b979650505050505050565b600080600061282661296a565b90508560008561284b57612846836128088b670de0b6b3a7640000613ce0565b61284d565b885b905060006128596155bc565b8b612871576128678d613d40565b909c5090506128e4565b61287b8c33612f2d565b5060008b815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201525b8215612905576128f581848c613e53565b94509150612905818e8e86613f4a565b891561291657612916818d86613a39565b881561292857612928818e8e8c6134b3565b6129328186613159565b61293c8c826131ab565b811561295857600254612958906001600160a01b03168361327e565b50999b909a5098505050505050505050565b6007546000906001600160801b03600160801b9091041642141561299a57506007546001600160801b0316610d2f565b60006129a4612a58565b6007546040519192507f339e53729b0447795ff69e70a74fed98fc7fef6fe94b7521099b32f0f8de4822916129f3916001600160801b03808216928692600160801b9004909116904290615db9565b60405180910390a1612a048161274f565b600780546fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055612a364261274f565b600780546001600160801b03928316600160801b029216919091179055905090565b6007546000908190612a8490612a7f904290600160801b90046001600160801b031661343f565b614007565b905063ffffffff8116612aa45750506007546001600160801b0316610d2f565b6000612aaf8261404b565b6007549091506001600160801b03166000612b90837f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000089612ee9565b90506000612c21847f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b9050600073__$f98cbc68e241c61b30349ba6b91a975736$__63fc505d3787621712406040518363ffffffff1660e01b8152600401612c61929190615e1b565b60206040518083038186803b158015612c7957600080fd5b505af4158015612c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb19190615746565b90506000612cd3670de0b6b3a764000061280885670b1a2bc2ec500000613ce0565b905080841015612ce557809350612d15565b6000612d05670de0b6b3a76400006128088667136dcc951d8c0000613ce0565b905080851115612d13578094505b505b60405163fc505d3760e01b815260009073__$f98cbc68e241c61b30349ba6b91a975736$__9063fc505d3790612d519087908990600401615dfc565b60206040518083038186803b158015612d6957600080fd5b505af4158015612d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da19190615746565b90506000612e398473__$f98cbc68e241c61b30349ba6b91a975736$__632cbbdee5856040518263ffffffff1660e01b8152600401612de09190615aee565b60206040518083038186803b158015612df857600080fd5b505af4158015612e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e309190615746565b600f0b9061420f565b604051637e0c9e7960e11b815290915060009073__$f98cbc68e241c61b30349ba6b91a975736$__9063fc193cf290612e7a90600f86900b90600401615aee565b60206040518083038186803b158015612e9257600080fd5b505af4158015612ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eca9190615746565b9050612eda600f82900b896142a0565b9a505050505050505050505090565b600080612efb898888888e60006127b1565b90506000612f0e8a8a878a8f6000613bd3565b9050612f1e846128088385613ce0565b9b9a5050505050505050505050565b806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e846040518263ffffffff1660e01b8152600401612f839190615df3565b60206040518083038186803b158015612f9b57600080fd5b505afa158015612faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd39190615646565b6001600160a01b0316148061300157506000828152600960205260409020546001600160a01b038281169116145b61301d5760405162461bcd60e51b815260040161039090615b19565b5050565b60008061302c61296a565b90506000836130505761304b8261280888670de0b6b3a7640000613ce0565b613052565b855b600088815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915081156130ce576130ce818a8a856143f1565b85156130df576130df81898861310f565b6130e98184613159565b6130f388826131ab565b851561310357613103338761327e565b50979650505050505050565b61311983826144ae565b7f627a692d5a03ab34732c0d2aa319f3ecdebdc4528f383eabcb25441dc0a70cfb33838360405161314c939291906159d5565b60405180910390a1505050565b60008061316684846144ca565b91509150816131875760405162461bcd60e51b815260040161039090615c8f565b80156131a55760405162461bcd60e51b815260040161039090615cac565b50505050565b600091825260096020908152604092839020825181549284015163ffffffff16600160a01b027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff6001600160a01b039092166001600160a01b0319909416939093171691909117815591810151600190920180546060909201516001600160801b0316600160601b027fffffffff00000000000000000000000000000000ffffffffffffffffffffffff6001600160601b039094166bffffffffffffffffffffffff199093169290921792909216179055565b804710156132d3576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d806000811461331e576040519150601f19603f3d011682016040523d82523d6000602084013e613323565b606091505b50509050806133635760405162461bcd60e51b815260040180806020018281038252603a815260200180615e9f603a913960400191505060405180910390fd5b505050565b602083015163ffffffff1661337c84614684565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906133cc90309087908690600401615975565b600060405180830381600087803b1580156133e657600080fd5b505af11580156133fa573d6000803e3d6000fd5b505050507fe59f38fa1264fc25c9f0185eee136eaf810d90b8e7293b342e4037c68720177a338383604051613431939291906159d5565b60405180910390a150505050565b600082821115613496576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000806127f0868686868b60006127b1565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166399fbab88866040518263ffffffff1660e01b81526004016135059190615df3565b6101806040518083038186803b15801561351e57600080fd5b505afa158015613532573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135569190615887565b505050509750505095509550955050506000816001600160801b03161161358f5760405162461bcd60e51b815260040161039090615bc6565b7f000000000000000000000000000000000000000000000000000000000000000062ffffff168262ffffff16146135d85760405162461bcd60e51b815260040161039090615b36565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614801561364a57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b806136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161480156136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b6136de5760405162461bcd60e51b815260040161039090615ba9565b6136e888866146cf565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613738908a9030908a90600401615975565b600060405180830381600087803b15801561375257600080fd5b505af1158015613766573d6000803e3d6000fd5b505050507f3917c2f26ce18614e3aedd1289da672ef6563c5c295f49e9b1697ae0ad31556233878760405161379d939291906159d5565b60405180910390a15050505050505050565b602084015160009063ffffffff16806137cc576000915050610bb9565b6000806137d883614764565b9092509050811561386257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061382f908590600401615df3565b600060405180830381600087803b15801561384957600080fd5b505af115801561385d573d6000803e3d6000fd5b505050505b60008060006138738b86868b614931565b9194509250905081156139225760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906138ce908d908690600401615999565b602060405180830381600087803b1580156138e857600080fd5b505af11580156138fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139209190615726565b505b82156139a957604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906139769030908790600401615999565b600060405180830381600087803b15801561399057600080fd5b505af11580156139a4573d6000803e3d6000fd5b505050505b7ffd0ae2fd36bd955810ae42615bc5ff277c0d0dfcb930f06c9f1777c0ef0752e3338a87878787876040516139e49796959493929190615a1c565b60405180910390a19a9950505050505050505050565b6000610bb96ec097ce7bc90715b34b9f100000000061280885613a1d8887613ce0565b90613ce0565b600080613a3084846144ca565b50949350505050565b613a438382613a76565b7f3ca13b7aab12bad7472691fe558faa6b25e99099824a0070a88bd5aa84be610f33838360405161314c939291906159d5565b6040820151613a9790613a92906001600160601b0316836149c7565b614a21565b6001600160601b031660409092019190915250565b600080600080613ad78789606001516001600160801b03168a604001516001600160601b0316614a68565b9150915081871015613afb5760405162461bcd60e51b815260040161039090615c00565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90613b499088908690600401615999565b600060405180830381600087803b158015613b6357600080fd5b505af1158015613b77573d6000803e3d6000fd5b50505050613b8e8289614ad090919063ffffffff16565b613b9888826144ae565b6000613ba489886144ca565b9150508015613bc55760405162461bcd60e51b815260040161039090615cac565b509097909650945050505050565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b158015613c4257600080fd5b505afa158015613c56573d6000803e3d6000fd5b505050506040513d6020811015613c6c57600080fd5b5051979650505050505050565b6000808211613ccf576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613cd857fe5b049392505050565b600082613cef5750600061349b565b82820282848281613cfc57fe5b0414613d395760405162461bcd60e51b8152600401808060200182810382526021815260200180615ed96021913960400191505060405180910390fd5b9392505050565b6000613d4a6155bc565b6040516354ba0f2760e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906354ba0f2790613d99908790600401615961565b602060405180830381600087803b158015613db357600080fd5b505af1158015613dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613deb9190615799565b6040805160808101825260008082526020820181905281830181905260608201529051919250907f25ff1e0131762176a9084e92880f880f39d6d0e62134607f37e631efe1bad87190613e419033908590615999565b60405180910390a19092509050915091565b600354600090819080613e6d576000849250925050613f42565b600080613efd877f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b90506000613f116127106128088487613ce0565b905080871115613f2c57613f25878261343f565b9250613f3a565b613f3689826144ae565b8692505b945090925050505b935093915050565b613f548482614b32565b6040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990613fa29086908590600401615999565b600060405180830381600087803b158015613fbc57600080fd5b505af1158015613fd0573d6000803e3d6000fd5b505050507fb19fa182730a088464dad0e9e0badeb470d0d8d937d854f5caf15c6ad1992c36338284604051613431939291906159d5565b8063ffffffff81168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a3199960e11b604482015290519081900360640190fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b81526004016140ba9190615961565b60206040518083038186803b1580156140d257600080fd5b505afa1580156140e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410a919061586b565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040161417a9190615961565b60206040518083038186803b15801561419257600080fd5b505afa1580156141a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141ca919061586b565b905060008163ffffffff168363ffffffff16116141e757826141e9565b815b90508063ffffffff168563ffffffff16116142045784614206565b805b95945050505050565b6000600f83810b9083900b0260401d6f7fffffffffffffffffffffffffffffff19811280159061424f57506f7fffffffffffffffffffffffffffffff8113155b613d39576040805162461bcd60e51b815260206004820152600860248201527f4d554c2d4f565546000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000816142af5750600061349b565b600083600f0b1215614308576040805162461bcd60e51b815260206004820152600760248201527f4d554c552d583000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600f83900b6001600160801b038316810260401c90608084901c0277ffffffffffffffffffffffffffffffffffffffffffffffff811115614390576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4631000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60401b81198111156143e9576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4632000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b019392505050565b6143fb8482614ad0565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906144499086908590600401615999565b600060405180830381600087803b15801561446357600080fd5b505af1158015614477573d6000803e3d6000fd5b505050507fea19ffc45b48de6d95594aacff7214dd24595fdb0c60e98c8f0b269058c2f792338284604051613431939291906159d5565b6040820151613a9790613a92906001600160601b03168361343f565b60008060006145607f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460016127b1565b9050614678857f00000000000000000000000000000000000000000000000000000000000000008684675fc1b971363200007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634a0a96eb7f00000000000000000000000000000000000000000000000000000000000000006101a46040518363ffffffff1660e01b8152600401614602929190615a71565b60206040518083038186803b15801561461a57600080fd5b505afa15801561462e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146529190615767565b7f0000000000000000000000000000000000000000000000000000000000000000614b4e565b92509250509250929050565b602081015163ffffffff166146c5576040805162461bcd60e51b81526020600482015260026024820152612b1960f11b604482015290519081900360640190fd5b6000602090910152565b602082015163ffffffff1615614711576040805162461bcd60e51b8152602060048201526002602482015261563160f01b604482015290519081900360640190fd5b80614749576040805162461bcd60e51b815260206004820152600360248201526243323360e81b604482015290519081900360640190fd5b61475281614007565b63ffffffff1660209092019190915250565b6000807f0000000000000000000000000000000000000000000000000000000000000000816147938286614bf2565b50506040805160a0810182528981526001600160801b0383166020820152600081830181905260608201524260808201529051630624e65f60e11b815291945092506001600160a01b0385169150630c49ccbe906147f5908490600401615d62565b6040805180830381600087803b15801561480e57600080fd5b505af1158015614822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148469190615801565b5050604080516080810182528781523060208201526001600160801b038183018190526060820152905163fc6f786560e01b815260009081906001600160a01b0387169063fc6f78659061489e908690600401615d1f565b6040805180830381600087803b1580156148b757600080fd5b505af11580156148cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148ef9190615801565b915091507f000000000000000000000000000000000000000000000000000000000000000061491f578082614922565b81815b97509750505050505050915091565b600080600080841561494a576149478787614cb0565b90505b606088015186906000906001600160801b03168211156149905760608a015161497d9089906001600160801b031661343f565b905089606001516001600160801b031691505b61499a8a83614ad0565b6149a38a614684565b6149ad8a8a613a76565b6149b78a846144ae565b9099909850909650945050505050565b600082820183811015613d39576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b806001600160601b0381168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a31c9b60e11b604482015290519081900360640190fd5b6000808080614a8187614a7c886002613c79565b614d60565b9150915080851115614ab657675fc1b97136320000614aa0868361343f565b1015614ab657614ab08787614d60565b90925090505b84811115614ac45750849050835b90969095509350505050565b6060820151614af190614aec906001600160801b03168361343f565b61274f565b6001600160801b031660609092019190915250565b600080614b1a868686866101a46000613bd3565b905061280e670de0b6b3a76400006128088984613ce0565b6060820151614af190614aec906001600160801b0316836149c7565b60008088606001516001600160801b031660001415614b735750600190506000614be6565b6000614bac6ec097ce7bc90715b34b9f100000000061280889613a1d8c8f606001516001600160801b0316613ce090919063ffffffff16565b90506000614bbe8b8b8b8b8a8a614e3c565b90508681106000614bd0846003613ce0565b614bdb846002613ce0565b101595509093505050505b97509795505050505050565b6000806000806000808790506000806000806000856001600160a01b03166399fbab888d6040518263ffffffff1660e01b8152600401808281526020019150506101806040518083038186803b158015614c4b57600080fd5b505afa158015614c5f573d6000803e3d6000fd5b505050506040513d610180811015614c7657600080fd5b5060a081015160c082015160e083015161014084015161016090940151929e50909c509a5090985096505050505050509295509295909350565b6000613d39670de0b6b3a764000061280866470de4df820000613a1d87614d5a887f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b906149c7565b6000806000838511614d725784614d74565b835b90506000614e05827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b9050614e2f614e28670de0b6b3a76400006128088467016345785d8a0000613ce0565b82906149c7565b9196919550909350505050565b6000866020015163ffffffff1660001415614e65575060408601516001600160601b03166127d4565b600080614e7e888a6020015163ffffffff168787614ed3565b90925090506000614ea66ec097ce7bc90715b34b9f100000000061280889613a1d868d613ce0565b60408b0151909150614ec5906001600160601b0316614d5a85846149c7565b9a9950505050505050505050565b6000806000806000806000614ee88b8b614bf2565b94509450945094509450600080614f0187878d88614f54565b9150915089614f2757826001600160801b03168101846001600160801b03168301614f40565b836001600160801b03168201836001600160801b031682015b985098505050505050505094509492505050565b600080600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba3866040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b158015614fab57600080fd5b505af4158015614fbf573d6000803e3d6000fd5b505050506040513d6020811015614fd557600080fd5b50519050600287810b9086900b12156151985773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b673__$d199f155f9376dc21890c162698c9ef049$__63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561505457600080fd5b505af4158015615068573d6000803e3d6000fd5b505050506040513d602081101561507e57600080fd5b50516040805163986cfba360e01b815260028b900b6004820152905173__$d199f155f9376dc21890c162698c9ef049$__9163986cfba3916024808301926020929190829003018186803b1580156150d557600080fd5b505af41580156150e9573d6000803e3d6000fd5b505050506040513d60208110156150ff57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561516557600080fd5b505af4158015615179573d6000803e3d6000fd5b505050506040513d602081101561518f57600080fd5b505192506155b2565b8560020b8560020b12156154065773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b68273__$d199f155f9376dc21890c162698c9ef049$__63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561521357600080fd5b505af4158015615227573d6000803e3d6000fd5b505050506040513d602081101561523d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156152a357600080fd5b505af41580156152b7573d6000803e3d6000fd5b505050506040513d60208110156152cd57600080fd5b50516040805163986cfba360e01b815260028a900b6004820152905191945073__$a98c5df505b68ab2f483703658c95acb30$__916348a0c5bd9173__$d199f155f9376dc21890c162698c9ef049$__9163986cfba391602480820192602092909190829003018186803b15801561534457600080fd5b505af4158015615358573d6000803e3d6000fd5b505050506040513d602081101561536e57600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b03928316600482015291851660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156153d357600080fd5b505af41580156153e7573d6000803e3d6000fd5b505050506040513d60208110156153fd57600080fd5b505191506155b2565b73__$a98c5df505b68ab2f483703658c95acb30$__6348a0c5bd73__$d199f155f9376dc21890c162698c9ef049$__63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561547257600080fd5b505af4158015615486573d6000803e3d6000fd5b505050506040513d602081101561549c57600080fd5b50516040805163986cfba360e01b815260028b900b6004820152905173__$d199f155f9376dc21890c162698c9ef049$__9163986cfba3916024808301926020929190829003018186803b1580156154f357600080fd5b505af4158015615507573d6000803e3d6000fd5b505050506040513d602081101561551d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561558357600080fd5b505af4158015615597573d6000803e3d6000fd5b505050506040513d60208110156155ad57600080fd5b505191505b5094509492505050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b8051610c5381615e31565b8051600281900b8114610c5357600080fd5b80516001600160801b0381168114610c5357600080fd5b805162ffffff81168114610c5357600080fd5b60006020828403121561563b578081fd5b8135613d3981615e31565b600060208284031215615657578081fd5b8151613d3981615e31565b60008060008060808587031215615677578283fd5b843561568281615e31565b935060208581013561569381615e31565b935060408601359250606086013567ffffffffffffffff808211156156b6578384fd5b818801915088601f8301126156c9578384fd5b8135818111156156d557fe5b604051601f8201601f19168101850183811182821017156156f257fe5b60405281815283820185018b1015615708578586fd5b81858501868301379081019093019390935250939692955090935050565b600060208284031215615737578081fd5b81518015158114613d39578182fd5b600060208284031215615757578081fd5b815180600f0b8114613d39578182fd5b600060208284031215615778578081fd5b613d39826155ee565b600060208284031215615792578081fd5b5035919050565b6000602082840312156157aa578081fd5b5051919050565b600080604083850312156157c3578182fd5b8235915060208301356157d581615e31565b809150509250929050565b600080604083850312156157f2578182fd5b50508035926020909101359150565b60008060408385031215615813578182fd5b505080516020909101519092909150565b600080600060608486031215615838578283fd5b505081359360208301359350604090920135919050565b600060208284031215615860578081fd5b8135613d3981615e46565b60006020828403121561587c578081fd5b8151613d3981615e46565b6000806000806000806000806000806000806101808d8f0312156158a957898afd5b8c516001600160601b03811681146158bf578a8bfd5b9b506158cd60208e016155e3565b9a506158db60408e016155e3565b99506158e960608e016155e3565b98506158f760808e01615617565b975061590560a08e016155ee565b965061591360c08e016155ee565b955061592160e08e01615600565b94506101008d015193506101208d015192506159406101408e01615600565b915061594f6101608e01615600565b90509295989b509295989b509295989b565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b03979097168752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0392909216825263ffffffff16602082015260400190565b6001600160a01b0394909416845263ffffffff9290921660208401526001600160601b031660408301526001600160801b0316606082015260800190565b901515815260200190565b6001600160e01b031991909116815260200190565b600f9190910b815260200190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b602080825260029082015261043360f41b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b602080825260029082015261433360f01b604082015260600190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b6001600160801b0391909116815260200190565b6001600160801b039485168152602081019390935292166040820152606081019190915260800190565b62ffffff91909116815260200190565b90815260200190565b918252602082015260400190565b63ffffffff91909116815260200190565b63ffffffff929092168252602082015260400190565b6001600160a01b0381168114610d1f57600080fd5b63ffffffff81168114610d1f57600080fdfe5265656e7472616e637947756172643a207265656e7472616e742063616c6c004f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212201ca81e10125d74fc4d8a6f7c39e0648cc26a50a8c5deec6ca4fb49cb3041e74964736f6c63430007060033\",\n  \"libraries\": {\n    \"ABDKMath64x64\": \"0x21A8D15322C257Abd2b22a56eDde758398be0F32\",\n    \"SqrtPriceMathPartial\": \"0x9cf8dcbCf115B06d8f577E73Cb9EdFdb27828460\",\n    \"TickMathExternal\": \"0x4d9d7F7aE80d51628Aa56eF37720718C99E6FDfC\"\n  },\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"burnPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_powerPerpAmount\": \"amount of powerPerp to burn\",\n          \"_vaultId\": \"id of the vault\",\n          \"_withdrawAmount\": \"amount of eth to withdraw\"\n        },\n        \"returns\": {\n          \"_0\": \"amount of wPowerPerp burned\"\n        }\n      },\n      \"burnWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_vaultId\": \"id of the vault\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to burn\",\n          \"_withdrawAmount\": \"amount of eth to withdraw\"\n        }\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_ethQuoteCurrencyPool\": \"uniswap v3 pool for weth / quoteCurrency\",\n          \"_oracle\": \"oracle address\",\n          \"_quoteCurrency\": \"quoteCurrency address\",\n          \"_shortPowerPerp\": \"ERC721 token address representing the short position\",\n          \"_uniPositionManager\": \"uniswap v3 position manager address\",\n          \"_wPowerPerp\": \"ERC20 token address representing the long position\",\n          \"_wPowerPerpPool\": \"uniswap v3 pool for wPowerPerp / weth\",\n          \"_weth\": \"weth address\"\n        }\n      },\n      \"deposit(uint256)\": {\n        \"details\": \"deposit collateral into a vault\",\n        \"params\": {\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"depositUniPositionToken(uint256,uint256)\": {\n        \"params\": {\n          \"_uniTokenId\": \"uniswap position token id\",\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"getDenormalizedMark(uint32)\": {\n        \"params\": {\n          \"_period\": \"period of time for the twap in seconds\"\n        },\n        \"returns\": {\n          \"_0\": \"mark price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"getDenormalizedMarkForFunding(uint32)\": {\n        \"details\": \"this is the mark that would be used to calculate a new normalization factor if funding was calculated now\",\n        \"params\": {\n          \"_period\": \"period which you want to calculate twap with\"\n        },\n        \"returns\": {\n          \"_0\": \"mark price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"getExpectedNormalizationFactor()\": {\n        \"details\": \"can be used for on-chain and off-chain calculations\"\n      },\n      \"getIndex(uint32)\": {\n        \"details\": \"the index price is scaled down by INDEX_SCALE in the associated PowerXBase librarythis is the index price used when calculating funding and for collateralization\",\n        \"params\": {\n          \"_period\": \"period which you want to calculate twap with\"\n        },\n        \"returns\": {\n          \"_0\": \"index price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"getUnscaledIndex(uint32)\": {\n        \"details\": \"this is the mark that would be be used for future funding after a new normalization factor is applied\",\n        \"params\": {\n          \"_period\": \"period which you want to calculate twap with\"\n        },\n        \"returns\": {\n          \"_0\": \"index price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"isVaultSafe(uint256)\": {\n        \"details\": \"return if the vault is properly collateralized\",\n        \"params\": {\n          \"_vaultId\": \"id of the vault\"\n        },\n        \"returns\": {\n          \"_0\": \"true if the vault is properly collateralized\"\n        }\n      },\n      \"liquidate(uint256,uint256)\": {\n        \"details\": \"liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateralnormally can only liquidate 50% of a vault's debtif a vault is under dust limit after a liquidation can fully liquidatewill attempt to reduceDebt first, and can earn a bounty if sucessful\",\n        \"params\": {\n          \"_maxDebtAmount\": \"max amount of wPowerPerpetual to repay\",\n          \"_vaultId\": \"vault to liquidate\"\n        },\n        \"returns\": {\n          \"_0\": \"amount of wPowerPerp repaid\"\n        }\n      },\n      \"mintPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_powerPerpAmount\": \"amount of powerPerp to mint\",\n          \"_uniTokenId\": \"uniswap v3 position token id (additional collateral)\",\n          \"_vaultId\": \"vault to mint wPowerPerp in\"\n        },\n        \"returns\": {\n          \"_0\": \"vaultId\",\n          \"_1\": \"amount of wPowerPerp minted\"\n        }\n      },\n      \"mintWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_uniTokenId\": \"uniswap v3 position token id (additional collateral)\",\n          \"_vaultId\": \"vault to mint wPowerPerp in\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to mint\"\n        },\n        \"returns\": {\n          \"_0\": \"vaultId\"\n        }\n      },\n      \"onERC721Received(address,address,uint256,bytes)\": {\n        \"details\": \"accept erc721 from safeTransferFrom and safeMint after callback\",\n        \"returns\": {\n          \"_0\": \"returns received selector\"\n        }\n      },\n      \"owner()\": {\n        \"details\": \"Returns the address of the current owner.\"\n      },\n      \"pause()\": {\n        \"details\": \"can only be called for 365 days since the contract was launched or 4 times\"\n      },\n      \"redeemLong(uint256)\": {\n        \"params\": {\n          \"_wPerpAmount\": \"amount of wPowerPerp to burn\"\n        }\n      },\n      \"redeemShort(uint256)\": {\n        \"details\": \"short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\",\n        \"params\": {\n          \"_vaultId\": \"vault id\"\n        }\n      },\n      \"reduceDebt(uint256)\": {\n        \"details\": \"the caller won't get any bounty. this is expected to be used by vault owner\",\n        \"params\": {\n          \"_vaultId\": \"target vault\"\n        }\n      },\n      \"reduceDebtShutdown(uint256)\": {\n        \"details\": \"the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\",\n        \"params\": {\n          \"_vaultId\": \"vault containing uniswap v3 position to liquidate\"\n        }\n      },\n      \"renounceOwnership()\": {\n        \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n      },\n      \"setFeeRate(uint256)\": {\n        \"details\": \"this function cannot be called if the feeRecipient is still un-set\",\n        \"params\": {\n          \"_newFeeRate\": \"new fee rate in basis points. can't be higher than 1%\"\n        }\n      },\n      \"setFeeRecipient(address)\": {\n        \"details\": \"this should be a contract handling insurance\",\n        \"params\": {\n          \"_newFeeRecipient\": \"new fee recipient\"\n        }\n      },\n      \"shutDown()\": {\n        \"details\": \"this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\"\n      },\n      \"transferOwnership(address)\": {\n        \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n      },\n      \"unPauseAnyone()\": {\n        \"details\": \"anyone can unpause the contract after 24 hours\"\n      },\n      \"unPauseOwner()\": {\n        \"details\": \"owner can unpause at any time\"\n      },\n      \"updateOperator(uint256,address)\": {\n        \"details\": \"can be revoke by setting address to 0\",\n        \"params\": {\n          \"_operator\": \"new operator address\",\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"withdraw(uint256,uint256)\": {\n        \"params\": {\n          \"_amount\": \"amount of eth to withdraw\",\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"withdrawUniPositionToken(uint256)\": {\n        \"params\": {\n          \"_vaultId\": \"id of the vault\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"ONE\": {\n        \"details\": \"basic unit used for calculation\"\n      },\n      \"PAUSE_TIME_LIMIT\": {\n        \"details\": \"system can only be paused for 182 days from deployment\"\n      },\n      \"feeRate\": {\n        \"details\": \"fee rate in basis point. feeRate of 1 = 0.01%\"\n      },\n      \"indexForSettlement\": {\n        \"details\": \"the settlement price for each wPowerPerp for settlement\"\n      },\n      \"vaults\": {\n        \"details\": \"vault data storage\"\n      },\n      \"wPowerPerpPool\": {\n        \"details\": \"address of the powerPerp/weth pool\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"events\": {\n      \"OpenVault(address,uint256)\": {\n        \"notice\": \"Events\"\n      }\n    },\n    \"kind\": \"user\",\n    \"methods\": {\n      \"applyFunding()\": {\n        \"notice\": \"update the normalization factor as a way to pay funding\"\n      },\n      \"burnPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"burn powerPerp and remove collateral from a vault\"\n      },\n      \"burnWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"burn wPowerPerp and remove collateral from a vault\"\n      },\n      \"constructor\": {\n        \"notice\": \"constructor\"\n      },\n      \"depositUniPositionToken(uint256,uint256)\": {\n        \"notice\": \"deposit uniswap position token into a vault to increase collateral ratio\"\n      },\n      \"donate()\": {\n        \"notice\": \"add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\"\n      },\n      \"getDenormalizedMark(uint32)\": {\n        \"notice\": \"get the expected mark price of powerPerp after funding has been applied\"\n      },\n      \"getDenormalizedMarkForFunding(uint32)\": {\n        \"notice\": \"get the mark price of powerPerp before funding has been applied\"\n      },\n      \"getExpectedNormalizationFactor()\": {\n        \"notice\": \"returns the expected normalization factor, if the funding is paid right now\"\n      },\n      \"getIndex(uint32)\": {\n        \"notice\": \"get the index price of the powerPerp, scaled down\"\n      },\n      \"getUnscaledIndex(uint32)\": {\n        \"notice\": \"the unscaled index of the power perp in USD, scaled by 18 decimals\"\n      },\n      \"liquidate(uint256,uint256)\": {\n        \"notice\": \"if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\"\n      },\n      \"mintPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\"\n      },\n      \"mintWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"deposit collateral and mint wPowerPerp\"\n      },\n      \"pause()\": {\n        \"notice\": \"pause the system for up to 24 hours after which any one can unpause\"\n      },\n      \"redeemLong(uint256)\": {\n        \"notice\": \"redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\"\n      },\n      \"redeemShort(uint256)\": {\n        \"notice\": \"redeem short position when the system is shutdown\"\n      },\n      \"reduceDebt(uint256)\": {\n        \"notice\": \"withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\"\n      },\n      \"reduceDebtShutdown(uint256)\": {\n        \"notice\": \"after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by forceif a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\"\n      },\n      \"setFeeRate(uint256)\": {\n        \"notice\": \"set the fee rate when user mints\"\n      },\n      \"setFeeRecipient(address)\": {\n        \"notice\": \"set the recipient who will receive the fee\"\n      },\n      \"shutDown()\": {\n        \"notice\": \"shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactorshort positions can be redeemed for vault collateral minus value of debtpause (if not paused) and then immediately shutdown the system, can be called when paused already\"\n      },\n      \"unPauseAnyone()\": {\n        \"notice\": \"unpause the contract\"\n      },\n      \"unPauseOwner()\": {\n        \"notice\": \"unpause the contract\"\n      },\n      \"updateOperator(uint256,address)\": {\n        \"notice\": \"authorize an address to modify the vault\"\n      },\n      \"withdraw(uint256,uint256)\": {\n        \"notice\": \"withdraw collateral from a vault\"\n      },\n      \"withdrawUniPositionToken(uint256)\": {\n        \"notice\": \"withdraw uniswap v3 position token from a vault\"\n      }\n    },\n    \"notice\": \"Error C0: Paused C1: Not paused C2: Shutdown C3: Not shutdown C4: Invalid oracle address C5: Invalid shortPowerPerp address C6: Invalid wPowerPerp address C7: Invalid weth address C8: Invalid quote currency address C9: Invalid eth:quoteCurrency pool address C10: Invalid wPowerPerp:eth pool address C11: Invalid Uniswap position manager C12: Can not liquidate safe vault C13: Invalid address C14: Set fee recipient first C15: Fee too high C16: Paused too many times C17: Pause time limit exceeded C18: Not enough paused time has passed C19: Cannot receive eth C20: Not allowed C21: Need full liquidation C22: Dust vault left C23: Invalid nft C24: Invalid state C25: 0 liquidity Uniswap position token C26: Wrong fee tier for NFT deposit\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 7,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"_owner\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 3698,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7240,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"feeRecipient\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 7245,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"feeRate\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7248,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"indexForSettlement\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7251,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"pausesLeft\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7253,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"lastPauseTime\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7255,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"normalizationFactor\",\n        \"offset\": 0,\n        \"slot\": \"7\",\n        \"type\": \"t_uint128\"\n      },\n      {\n        \"astId\": 7257,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"lastFundingUpdateTimestamp\",\n        \"offset\": 16,\n        \"slot\": \"7\",\n        \"type\": \"t_uint128\"\n      },\n      {\n        \"astId\": 7261,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"isShutDown\",\n        \"offset\": 0,\n        \"slot\": \"8\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 7263,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"isSystemPaused\",\n        \"offset\": 1,\n        \"slot\": \"8\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 7268,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"vaults\",\n        \"offset\": 0,\n        \"slot\": \"9\",\n        \"type\": \"t_mapping(t_uint256,t_struct(Vault)13791_storage)\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_mapping(t_uint256,t_struct(Vault)13791_storage)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => struct VaultLib.Vault)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_struct(Vault)13791_storage\"\n      },\n      \"t_struct(Vault)13791_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct VaultLib.Vault\",\n        \"members\": [\n          {\n            \"astId\": 13784,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"operator\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_address\"\n          },\n          {\n            \"astId\": 13786,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"NftCollateralId\",\n            \"offset\": 20,\n            \"slot\": \"0\",\n            \"type\": \"t_uint32\"\n          },\n          {\n            \"astId\": 13788,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"collateralAmount\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_uint96\"\n          },\n          {\n            \"astId\": 13790,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"shortAmount\",\n            \"offset\": 12,\n            \"slot\": \"1\",\n            \"type\": \"t_uint128\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_uint128\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint128\",\n        \"numberOfBytes\": \"16\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint32\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint32\",\n        \"numberOfBytes\": \"4\"\n      },\n      \"t_uint96\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint96\",\n        \"numberOfBytes\": \"12\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/ControllerHelper.json",
    "content": "{\n  \"address\": \"0xfa86d43b41Fa7a759c606130cc81970A955ff816\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controller\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_nonfungiblePositionManager\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniswapFactory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_exec\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_euler\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_dToken\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"burnExactRemoved\",\n              \"type\": \"bool\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.CloseShortWithUserNftParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"closeShortWithUserNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"dToken\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"euler\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"exec\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToFlashloan\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"burnExactRemoved\",\n              \"type\": \"bool\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashloanCloseVaultLpNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmount\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToFlashloan\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToLp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashloanWMintLpDepositNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToMint\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToSell\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"minToReceive\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashSellLongWMintParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashswapSellLongWMint\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBuy\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"maxToPay\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashswapWBurnBuyLongParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashswapWBurnBuyLong\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"encodedData\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onDeferredLiquidityCheck\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onERC721Received\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_collateralToFlashloan\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"enum ControllerHelperDataType.RebalanceVaultNftType\",\n              \"name\": \"rebalanceLpInVaultType\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"bytes\",\n              \"name\": \"data\",\n              \"type\": \"bytes\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.RebalanceLpInVaultParams[]\",\n          \"name\": \"_params\",\n          \"type\": \"tuple[]\"\n        }\n      ],\n      \"name\": \"rebalanceLpInVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountDesired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wethAmountDesired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0DesiredMin\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1DesiredMin\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.RebalanceLpWithoutVaultParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"rebalanceLpWithoutVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.ReduceLiquidityAndSellParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"reduceLiquidityAndSell\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"token\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmount\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToLp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.MintAndLpParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"wMintLp\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0xfa86d43b41Fa7a759c606130cc81970A955ff816\",\n    \"transactionIndex\": 166,\n    \"gasUsed\": \"5438748\",\n    \"logsBloom\": \"0x00800000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000002010000080000000000000000200000000000000000800000000000400000000000000000000000000008000000000002000000000004100001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000200000000000000000000040002000000000020000000000000000000000000000000000000000020000000010200800000000000000000000000800000000000000000000000000000000\",\n    \"blockHash\": \"0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6\",\n    \"transactionHash\": \"0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 166,\n        \"blockNumber\": 14925294,\n        \"transactionHash\": \"0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4\",\n        \"address\": \"0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x000000000000000000000000fa86d43b41fa7a759c606130cc81970a955ff816\",\n          \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 237,\n        \"blockHash\": \"0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6\"\n      },\n      {\n        \"transactionIndex\": 166,\n        \"blockNumber\": 14925294,\n        \"transactionHash\": \"0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4\",\n        \"address\": \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x000000000000000000000000fa86d43b41fa7a759c606130cc81970a955ff816\",\n          \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 238,\n        \"blockHash\": \"0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6\"\n      },\n      {\n        \"transactionIndex\": 166,\n        \"blockNumber\": 14925294,\n        \"transactionHash\": \"0xf3f25650676901174d6c66dd5cdeb91aa0e74010790e2e2d42105305d98402b4\",\n        \"address\": \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n        \"topics\": [\n          \"0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31\",\n          \"0x000000000000000000000000fa86d43b41fa7a759c606130cc81970a955ff816\",\n          \"0x00000000000000000000000064187ae08781b09368e6253f9e94951243a493d5\"\n        ],\n        \"data\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n        \"logIndex\": 239,\n        \"blockHash\": \"0xa4b3f7ead6dc88e26d9b627d643c43558fc278f6b6483c316ea35cdfcd2d38b6\"\n      }\n    ],\n    \"blockNumber\": 14925294,\n    \"cumulativeGasUsed\": \"17334095\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x64187ae08781B09368e6253F9E94951243A493D5\",\n    \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n    \"0x1F98431c8aD98523631AE4a59f267346ea31F984\",\n    \"0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80\",\n    \"0x27182842E098f60e3D576794A5bFFb0777E025d3\",\n    \"0x62e28f054efc24b26A794F5C1249B6349454352C\"\n  ],\n  \"solcInputHash\": \"fc32ed9e00a9017e491333926bef5473\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controller\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_nonfungiblePositionManager\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniswapFactory\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_exec\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_euler\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_dToken\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidityPercentage\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBurn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"burnExactRemoved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.CloseShortWithUserNftParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"closeShortWithUserNft\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"dToken\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"euler\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"exec\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"factory\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidityPercentage\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBurn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToFlashloan\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"burnExactRemoved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashloanCloseVaultLpNft\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToFlashloan\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToLp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"upperTick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashloanWMintLpDepositNft\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToMint\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToSell\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minToReceive\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashSellLongWMintParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashswapSellLongWMint\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBurn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBuy\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"maxToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashswapWBurnBuyLongParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashswapWBurnBuyLong\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"encodedData\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onDeferredLiquidityCheck\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onERC721Received\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_collateralToFlashloan\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"enum ControllerHelperDataType.RebalanceVaultNftType\\\",\\\"name\\\":\\\"rebalanceLpInVaultType\\\",\\\"type\\\":\\\"uint8\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.RebalanceLpInVaultParams[]\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple[]\\\"}],\\\"name\\\":\\\"rebalanceLpInVault\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountDesired\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wethAmountDesired\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0DesiredMin\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1DesiredMin\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"upperTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.RebalanceLpWithoutVaultParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"rebalanceLpWithoutVault\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidityPercentage\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.ReduceLiquidityAndSellParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"reduceLiquidityAndSell\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"token\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount0Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount1Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"uniswapV3SwapCallback\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToLp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"upperTick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.MintAndLpParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"wMintLp\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\\\":{\\\"details\\\":\\\"user should approve this contract for Uni NFT transfer\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.CloseShortWithUserNftParams struct\\\"}},\\\"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"details\\\":\\\"sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\\"}},\\\"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"details\\\":\\\"flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.FlashSellLongWMintParams struct\\\"}},\\\"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"details\\\":\\\"this function\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\\"}},\\\"onERC721Received(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"accept erc721 from safeTransferFrom and safeMint after callback\\\",\\\"returns\\\":{\\\"_0\\\":\\\"returns received selector\\\"}},\\\"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\\\":{\\\"params\\\":{\\\"_collateralToFlashloan\\\":\\\"collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\\",\\\"_params\\\":\\\"array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\\",\\\"_vaultId\\\":\\\"vault ID\\\"}},\\\"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\\\":{\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\\"}},\\\"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\\\":{\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\\"}},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"params\\\":{\\\"_data\\\":\\\"callback data encoded as SwapCallbackData struct\\\",\\\"amount0Delta\\\":\\\"amount of token0\\\",\\\"amount1Delta\\\":\\\"amount of token1\\\"}},\\\"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.MintAndLpParams struct\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\\\":{\\\"notice\\\":\\\"close short position with user Uniswap v3 LP NFT\\\"},\\\"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"notice\\\":\\\"FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\\"},\\\"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"notice\\\":\\\"sell long wPowerPerp and flashswap mint short position\\\"},\\\"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"notice\\\":\\\"flash close position and buy long squeeth\\\"},\\\"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\\\":{\\\"notice\\\":\\\"Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\\"},\\\"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\\\":{\\\"notice\\\":\\\"Rebalance LP nft through trading\\\"},\\\"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\\\":{\\\"notice\\\":\\\"sell all LP wPowerPerp amounts to WETH and send back to user\\\"},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"notice\\\":\\\"uniswap swap callback function for flashswap\\\"},\\\"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"notice\\\":\\\"mint WPowerPerp and LP into Uniswap v3 pool\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/periphery/ControllerHelper.sol\\\":\\\"ControllerHelper\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#flash\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\\\ninterface IUniswapV3FlashCallback {\\\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\\\n    function uniswapV3FlashCallback(\\\\n        uint256 fee0,\\\\n        uint256 fee1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x151ba1777392771025f0fca946c95fbc16ec4b5eff05e1f236115b99bd574de2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Safe casting methods\\\\n/// @notice Contains methods for safely casting between types\\\\nlibrary SafeCast {\\\\n    /// @notice Cast a uint256 to a uint160, revert on overflow\\\\n    /// @param y The uint256 to be downcasted\\\\n    /// @return z The downcasted integer, now type uint160\\\\n    function toUint160(uint256 y) internal pure returns (uint160 z) {\\\\n        require((z = uint160(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a int256 to a int128, revert on overflow or underflow\\\\n    /// @param y The int256 to be downcasted\\\\n    /// @return z The downcasted integer, now type int128\\\\n    function toInt128(int256 y) internal pure returns (int128 z) {\\\\n        require((z = int128(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a uint256 to a int256, revert on overflow\\\\n    /// @param y The uint256 to be casted\\\\n    /// @return z The casted integer, now type int256\\\\n    function toInt256(uint256 y) internal pure returns (int256 z) {\\\\n        require(y < 2**255);\\\\n        z = int256(y);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n/*\\\\n * @title Solidity Bytes Arrays Utils\\\\n * @author Gon\\\\u00e7alo S\\\\u00e1 <goncalo.sa@consensys.net>\\\\n *\\\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\\\n */\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nlibrary BytesLib {\\\\n    function slice(\\\\n        bytes memory _bytes,\\\\n        uint256 _start,\\\\n        uint256 _length\\\\n    ) internal pure returns (bytes memory) {\\\\n        require(_length + 31 >= _length, 'slice_overflow');\\\\n        require(_start + _length >= _start, 'slice_overflow');\\\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\\\n\\\\n        bytes memory tempBytes;\\\\n\\\\n        assembly {\\\\n            switch iszero(_length)\\\\n                case 0 {\\\\n                    // Get a location of some free memory and store it in tempBytes as\\\\n                    // Solidity does for memory variables.\\\\n                    tempBytes := mload(0x40)\\\\n\\\\n                    // The first word of the slice result is potentially a partial\\\\n                    // word read from the original array. To read it, we calculate\\\\n                    // the length of that partial word and start copying that many\\\\n                    // bytes into the array. The first word we copy will start with\\\\n                    // data we don't care about, but the last `lengthmod` bytes will\\\\n                    // land at the beginning of the contents of the new array. When\\\\n                    // we're done copying, we overwrite the full first word with\\\\n                    // the actual length of the slice.\\\\n                    let lengthmod := and(_length, 31)\\\\n\\\\n                    // The multiplication in the next line is necessary\\\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\\\n                    // the following copy loop was copying the origin's length\\\\n                    // and then ending prematurely not copying everything it should.\\\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\\\n                    let end := add(mc, _length)\\\\n\\\\n                    for {\\\\n                        // The multiplication in the next line has the same exact purpose\\\\n                        // as the one above.\\\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\\\n                    } lt(mc, end) {\\\\n                        mc := add(mc, 0x20)\\\\n                        cc := add(cc, 0x20)\\\\n                    } {\\\\n                        mstore(mc, mload(cc))\\\\n                    }\\\\n\\\\n                    mstore(tempBytes, _length)\\\\n\\\\n                    //update free-memory pointer\\\\n                    //allocating the array padded to 32 bytes like the compiler does now\\\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\\\n                }\\\\n                //if we want a zero-length slice let's just return a zero-length array\\\\n                default {\\\\n                    tempBytes := mload(0x40)\\\\n                    //zero out the 32 bytes slice we are about to return\\\\n                    //we need to do it because Solidity does not garbage collect\\\\n                    mstore(tempBytes, 0)\\\\n\\\\n                    mstore(0x40, add(tempBytes, 0x20))\\\\n                }\\\\n        }\\\\n\\\\n        return tempBytes;\\\\n    }\\\\n\\\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\\\n        address tempAddress;\\\\n\\\\n        assembly {\\\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\\\n        }\\\\n\\\\n        return tempAddress;\\\\n    }\\\\n\\\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\\\n        uint24 tempUint;\\\\n\\\\n        assembly {\\\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\\\n        }\\\\n\\\\n        return tempUint;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport './PoolAddress.sol';\\\\n\\\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\\\nlibrary CallbackValidation {\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param tokenA The contract address of either token0 or token1\\\\n    /// @param tokenB The contract address of the other token\\\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(\\\\n        address factory,\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool pool) {\\\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param poolKey The identifying key of the V3 pool\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\\\n        internal\\\\n        view\\\\n        returns (IUniswapV3Pool pool)\\\\n    {\\\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\\\n        require(msg.sender == address(pool));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.6.0;\\\\n\\\\nimport './BytesLib.sol';\\\\n\\\\n/// @title Functions for manipulating path data for multihop swaps\\\\nlibrary Path {\\\\n    using BytesLib for bytes;\\\\n\\\\n    /// @dev The length of the bytes encoded address\\\\n    uint256 private constant ADDR_SIZE = 20;\\\\n    /// @dev The length of the bytes encoded fee\\\\n    uint256 private constant FEE_SIZE = 3;\\\\n\\\\n    /// @dev The offset of a single token address and pool fee\\\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\\\n    /// @dev The offset of an encoded pool key\\\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\\\n\\\\n    /// @notice Returns true iff the path contains two or more pools\\\\n    /// @param path The encoded swap path\\\\n    /// @return True if path contains two or more pools, otherwise false\\\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\\\n    }\\\\n\\\\n    /// @notice Returns the number of pools in the path\\\\n    /// @param path The encoded swap path\\\\n    /// @return The number of pools in the path\\\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Decodes the first pool in path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return tokenA The first token of the given pool\\\\n    /// @return tokenB The second token of the given pool\\\\n    /// @return fee The fee level of the pool\\\\n    function decodeFirstPool(bytes memory path)\\\\n        internal\\\\n        pure\\\\n        returns (\\\\n            address tokenA,\\\\n            address tokenB,\\\\n            uint24 fee\\\\n        )\\\\n    {\\\\n        tokenA = path.toAddress(0);\\\\n        fee = path.toUint24(ADDR_SIZE);\\\\n        tokenB = path.toAddress(NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Gets the segment corresponding to the first pool in the path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return The segment containing all data necessary to target the first pool in the path\\\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(0, POP_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\\\n    /// @param path The swap path\\\\n    /// @return The remaining token + fee elements in the path\\\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IERC20Detailed.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// uniswap Library only works under 0.7.6\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IERC20Detailed is IERC20 {\\\\n    function decimals() external view returns (uint8);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcd59a0158d0711810c499904b9d37a71fdb34d1c4403f3cb67ca47de5e88bf7b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/ControllerHelper.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IERC721Receiver} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\\\\\";\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {UniswapControllerHelper} from \\\\\\\"./UniswapControllerHelper.sol\\\\\\\";\\\\nimport {EulerControllerHelper} from \\\\\\\"./EulerControllerHelper.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ControllerHelperDataType} from \\\\\\\"./lib/ControllerHelperDataType.sol\\\\\\\";\\\\nimport {ControllerHelperUtil} from \\\\\\\"./lib/ControllerHelperUtil.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    bool private immutable isWethToken0;\\\\n    address private immutable controller;\\\\n    address private immutable shortPowerPerp;\\\\n    address private immutable wPowerPerp;\\\\n    address private immutable weth;\\\\n    address private immutable nonfungiblePositionManager;\\\\n\\\\n    constructor(\\\\n        address _controller,\\\\n        address _nonfungiblePositionManager,\\\\n        address _uniswapFactory,\\\\n        address _exec,\\\\n        address _euler,\\\\n        address _dToken\\\\n    )\\\\n        UniswapControllerHelper(_uniswapFactory)\\\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\\\n    {\\\\n        controller = _controller;\\\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\\\n        wPowerPerp = IController(_controller).wPowerPerp();\\\\n        weth = IController(_controller).weth();\\\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\\\n\\\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\\\n\\\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\\\n\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\\\n     * @return returns received selector\\\\n     */\\\\n    function onERC721Received(\\\\n        address,\\\\n        address,\\\\n        uint256,\\\\n        bytes memory\\\\n    ) public virtual override returns (bytes4) {\\\\n        return this.onERC721Received.selector;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {}\\\\n\\\\n    /**\\\\n     * @notice flash close position and buy long squeeth\\\\n     * @dev this function\\\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\\\n     */\\\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        _checkAccess(_params.vaultId);\\\\n\\\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\\\n\\\\n        wrapInternal(msg.value);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            _params.poolFee,\\\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\\\n            _params.maxToPay,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\\\n            abi.encode(_params)\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sell long wPowerPerp and flashswap mint short position\\\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\\\n     */\\\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        if (_params.vaultId != 0) {\\\\n            _checkAccess(_params.vaultId);\\\\n        }\\\\n\\\\n        wrapInternal(msg.value);\\\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\\\n        // flashswap and mint short position\\\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            _params.poolFee,\\\\n            totalAmountIn,\\\\n            _params.minToReceive,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\\\n            abi.encode(_params)\\\\n        );\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice close short position with user Uniswap v3 LP NFT\\\\n     * @dev user should approve this contract for Uni NFT transfer\\\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\\\n     */\\\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        _checkAccess(_params.vaultId);\\\\n\\\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\\\n            msg.sender,\\\\n            address(this),\\\\n            _params.tokenId\\\\n        );\\\\n\\\\n        wrapInternal(msg.value);\\\\n\\\\n        // close LP position\\\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n            nonfungiblePositionManager,\\\\n            ControllerHelperDataType.CloseUniLpParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: _params.liquidity,\\\\n                liquidityPercentage: _params.liquidityPercentage,\\\\n                amount0Min: _params.amount0Min,\\\\n                amount1Min: _params.amount1Min\\\\n            }),\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\\\n        ControllerHelperUtil.checkClosedLp(\\\\n            msg.sender,\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            0,\\\\n            _params.tokenId,\\\\n            _params.liquidityPercentage\\\\n        );\\\\n        // burn vault debt using amounts withdrawn from LP position\\\\n        _closeShortWithAmountsFromLp(\\\\n            _params.vaultId,\\\\n            wPowerPerpAmountInLp,\\\\n            _params.wPowerPerpAmountToBurn,\\\\n            _params.collateralToWithdraw,\\\\n            _params.limitPriceEthPerPowerPerp,\\\\n            _params.poolFee,\\\\n            _params.burnExactRemoved\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        _checkAccess(_params.vaultId);\\\\n\\\\n        wrapInternal(msg.value);\\\\n        _flashLoan(\\\\n            weth,\\\\n            _params.collateralToFlashloan,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\\\n            abi.encode(_params)\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\\\n     */\\\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\\\n        if (_params.vaultId != 0) {\\\\n            _checkAccess(_params.vaultId);\\\\n        }\\\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\\\n\\\\n        wrapInternal(msg.value);\\\\n\\\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            _params,\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        // if openeded new vault, transfer vault NFT to user\\\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\\\n     */\\\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        if (_params.vaultId != 0) {\\\\n            _checkAccess(_params.vaultId);\\\\n        }\\\\n\\\\n        wrapInternal(msg.value);\\\\n        _flashLoan(\\\\n            weth,\\\\n            _params.collateralToFlashloan,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\\\n            abi.encode(_params)\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\\\n     */\\\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\\\n            msg.sender,\\\\n            address(this),\\\\n            _params.tokenId\\\\n        );\\\\n\\\\n        // close LP NFT and get Weth and WPowerPerp amounts\\\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n            nonfungiblePositionManager,\\\\n            ControllerHelperDataType.CloseUniLpParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: _params.liquidity,\\\\n                liquidityPercentage: _params.liquidityPercentage,\\\\n                amount0Min: uint128(_params.amount0Min),\\\\n                amount1Min: uint128(_params.amount1Min)\\\\n            }),\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        ControllerHelperUtil.checkClosedLp(\\\\n            msg.sender,\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            0,\\\\n            _params.tokenId,\\\\n            _params.liquidityPercentage\\\\n        );\\\\n\\\\n        if (wPowerPerpAmountInLp > 0) {\\\\n            _exactInFlashSwap(\\\\n                wPowerPerp,\\\\n                weth,\\\\n                _params.poolFee,\\\\n                wPowerPerpAmountInLp,\\\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\\\n                \\\\\\\"\\\\\\\"\\\\n            );\\\\n        }\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice Rebalance LP nft through trading\\\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\\\n     */\\\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        wrapInternal(msg.value);\\\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\\\n            msg.sender,\\\\n            address(this),\\\\n            _params.tokenId\\\\n        );\\\\n        // close LP NFT and get Weth and WPowerPerp amounts\\\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n            nonfungiblePositionManager,\\\\n            ControllerHelperDataType.CloseUniLpParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: _params.liquidity,\\\\n                liquidityPercentage: 1e18,\\\\n                amount0Min: uint128(_params.amount0Min),\\\\n                amount1Min: uint128(_params.amount1Min)\\\\n            }),\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        ControllerHelperUtil.checkClosedLp(\\\\n            msg.sender,\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            0,\\\\n            _params.tokenId,\\\\n            1e18\\\\n        );\\\\n\\\\n        uint256 wethAmountDesired;\\\\n        uint256 wPowerPerpAmountDesired;\\\\n\\\\n        if (isWethToken0) {\\\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\\\n                _params.wPowerPerpPool,\\\\n                _params.wethAmountDesired,\\\\n                _params.wPowerPerpAmountDesired,\\\\n                _params.lowerTick,\\\\n                _params.upperTick,\\\\n                isWethToken0\\\\n            );\\\\n        } else {\\\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\\\n                _params.wPowerPerpPool,\\\\n                _params.wethAmountDesired,\\\\n                _params.wPowerPerpAmountDesired,\\\\n                _params.lowerTick,\\\\n                _params.upperTick,\\\\n                isWethToken0\\\\n            );\\\\n        }\\\\n\\\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\\\n            _exactOutFlashSwap(\\\\n                weth,\\\\n                wPowerPerp,\\\\n                _params.poolFee,\\\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\\\n                \\\\\\\"\\\\\\\"\\\\n            );\\\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\\\n            _exactInFlashSwap(\\\\n                wPowerPerp,\\\\n                weth,\\\\n                _params.poolFee,\\\\n                wPowerPerpExcess,\\\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\\\n                \\\\\\\"\\\\\\\"\\\\n            );\\\\n        }\\\\n\\\\n        // mint new position\\\\n        ControllerHelperUtil.lpWPowerPerpPool(\\\\n            nonfungiblePositionManager,\\\\n            _params.wPowerPerpPool,\\\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\\\n                recipient: msg.sender,\\\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\\\n                amount0Min: _params.amount0DesiredMin,\\\\n                amount1Min: _params.amount1DesiredMin,\\\\n                lowerTick: _params.lowerTick,\\\\n                upperTick: _params.upperTick\\\\n            })\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\\\n     * @param _vaultId vault ID\\\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\\\n     */\\\\n    function rebalanceLpInVault(\\\\n        uint256 _vaultId,\\\\n        uint256 _collateralToFlashloan,\\\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\\\n    ) external payable {\\\\n        // check ownership\\\\n        _checkAccess(_vaultId);\\\\n\\\\n        wrapInternal(msg.value);\\\\n        _flashLoan(\\\\n            weth,\\\\n            _collateralToFlashloan,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\\\n            abi.encode(_vaultId, _params)\\\\n        );\\\\n\\\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice checks if the msg.sender is the owener of the vault\\\\n     * @param _vaultId vault ID\\\\n     */\\\\n    function _checkAccess(uint256 _vaultId) internal view {\\\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice gets the shortAmount that has been minted from a vault\\\\n     * @param _vaultId vault ID\\\\n     * @return short amount from vault\\\\n     */\\\\n\\\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\\\n\\\\n        return vault.shortAmount;\\\\n    }\\\\n\\\\n    function _flashCallback(\\\\n        address _initiator,\\\\n        address, /*_asset*/\\\\n        uint256 _amount,\\\\n        uint8 _callSource,\\\\n        bytes memory _calldata\\\\n    ) internal override {\\\\n        if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\\\n        ) {\\\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\\\n                _calldata,\\\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\\\n            );\\\\n\\\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\\\n                controller,\\\\n                nonfungiblePositionManager,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                ControllerHelperDataType.MintAndLpParams({\\\\n                    recipient: address(this),\\\\n                    wPowerPerpPool: data.wPowerPerpPool,\\\\n                    vaultId: data.vaultId,\\\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\\\n                    collateralToDeposit: data.collateralToDeposit,\\\\n                    collateralToLp: data.collateralToLp,\\\\n                    amount0Min: data.amount0Min,\\\\n                    amount1Min: data.amount1Min,\\\\n                    lowerTick: data.lowerTick,\\\\n                    upperTick: data.upperTick\\\\n                }),\\\\n                isWethToken0\\\\n            );\\\\n\\\\n            // deposit Uni NFT token in vault\\\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                vaultId,\\\\n                0,\\\\n                _amount.add(data.collateralToWithdraw)\\\\n            );\\\\n\\\\n            // if openeded new vault, transfer vault NFT to user\\\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\\\n        ) {\\\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\\\n                _calldata,\\\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\\\n            );\\\\n\\\\n            IWETH9(weth).withdraw(_amount);\\\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\\\n\\\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\\\n\\\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n                nonfungiblePositionManager,\\\\n                ControllerHelperDataType.CloseUniLpParams({\\\\n                    tokenId: data.tokenId,\\\\n                    liquidity: data.liquidity,\\\\n                    liquidityPercentage: data.liquidityPercentage,\\\\n                    amount0Min: data.amount0Min,\\\\n                    amount1Min: data.amount1Min\\\\n                }),\\\\n                isWethToken0\\\\n            );\\\\n\\\\n            ControllerHelperUtil.checkClosedLp(\\\\n                _initiator,\\\\n                controller,\\\\n                nonfungiblePositionManager,\\\\n                data.vaultId,\\\\n                data.tokenId,\\\\n                data.liquidityPercentage\\\\n            );\\\\n\\\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\\\n            _closeShortWithAmountsFromLp(\\\\n                data.vaultId,\\\\n                wPowerPerpAmountInLp,\\\\n                data.wPowerPerpAmountToBurn,\\\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\\\n                data.limitPriceEthPerPowerPerp,\\\\n                data.poolFee,\\\\n                data.burnExactRemoved\\\\n            );\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\\\n        ) {\\\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\\\n                _calldata,\\\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\\\n            );\\\\n\\\\n            // deposit collateral into vault and withdraw LP NFT\\\\n            IWETH9(weth).withdraw(_amount);\\\\n            IController(controller).deposit{value: _amount}(vaultId);\\\\n            IController(controller).withdrawUniPositionToken(vaultId);\\\\n            for (uint256 i; i < data.length; i++) {\\\\n                if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\\\n                ) {\\\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\\\n                    );\\\\n\\\\n                    ControllerHelperUtil.increaseLpLiquidity(\\\\n                        controller,\\\\n                        nonfungiblePositionManager,\\\\n                        wPowerPerp,\\\\n                        increaseLiquidityParam.wPowerPerpPool,\\\\n                        vaultId,\\\\n                        increaseLiquidityParam,\\\\n                        isWethToken0\\\\n                    );\\\\n\\\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\\\n                ) {\\\\n                    // decrease liquidity in LP\\\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\\\n                    );\\\\n\\\\n                    ControllerHelperUtil.closeUniLp(\\\\n                        nonfungiblePositionManager,\\\\n                        ControllerHelperDataType.CloseUniLpParams({\\\\n                            tokenId: decreaseLiquidityParam.tokenId,\\\\n                            liquidity: decreaseLiquidityParam.liquidity,\\\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\\\n                        }),\\\\n                        isWethToken0\\\\n                    );\\\\n\\\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\\\n                    ControllerHelperUtil.checkClosedLp(\\\\n                        _initiator,\\\\n                        controller,\\\\n                        nonfungiblePositionManager,\\\\n                        vaultId,\\\\n                        decreaseLiquidityParam.tokenId,\\\\n                        decreaseLiquidityParam.liquidityPercentage\\\\n                    );\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\\\n                ) {\\\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\\\n                    );\\\\n\\\\n                    // make sure not to fail\\\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\\\n\\\\n                    ControllerHelperUtil.mintDepositInVault(\\\\n                        controller,\\\\n                        weth,\\\\n                        vaultId,\\\\n                        depositIntoVaultParams.wPowerPerpToMint,\\\\n                        depositIntoVaultParams.collateralToDeposit\\\\n                    );\\\\n                } else if (\\\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\\\n                ) {\\\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\\\n                    );\\\\n\\\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\\\n\\\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\\\n                            controller,\\\\n                            weth,\\\\n                            vaultId,\\\\n                            currentBalance,\\\\n                            withdrawFromVaultParams.collateralToWithdraw\\\\n                        );\\\\n                    } else {\\\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\\\n                            controller,\\\\n                            weth,\\\\n                            vaultId,\\\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\\\n                            withdrawFromVaultParams.collateralToWithdraw\\\\n                        );\\\\n                    }\\\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.MintAndLpParams)\\\\n                    );\\\\n\\\\n                    uint256 tokenId;\\\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\\\n                        controller,\\\\n                        nonfungiblePositionManager,\\\\n                        wPowerPerp,\\\\n                        weth,\\\\n                        mintAndLpParams,\\\\n                        isWethToken0\\\\n                    );\\\\n                    // deposit Uni NFT token in vault\\\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\\\n                ) {\\\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.GeneralSwapParams)\\\\n                    );\\\\n\\\\n                    require(\\\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\\\n                    );\\\\n\\\\n                    _exactInFlashSwap(\\\\n                        swapParams.tokenIn,\\\\n                        swapParams.tokenOut,\\\\n                        swapParams.poolFee,\\\\n                        swapParams.amountIn,\\\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\\\n                        \\\\\\\"\\\\\\\"\\\\n                    );\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\\\n                ) {\\\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.CollectFeesParams)\\\\n                    );\\\\n\\\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\\\n                        .CollectParams({\\\\n                            tokenId: collectFeesParams.tokenId,\\\\n                            recipient: address(this),\\\\n                            amount0Max: collectFeesParams.amount0Max,\\\\n                            amount1Max: collectFeesParams.amount0Max\\\\n                        });\\\\n\\\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\\\n                ) {\\\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\\\n                    );\\\\n\\\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\\\n                }\\\\n            }\\\\n\\\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _swapCallback(\\\\n        address _caller,\\\\n        address _tokenIn,\\\\n        address _pool,\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\\\n        ) {\\\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\\\n                _callData,\\\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\\\n            );\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                data.vaultId,\\\\n                data.wPowerPerpAmountToBurn,\\\\n                data.collateralToWithdraw\\\\n            );\\\\n\\\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\\\n        ) {\\\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\\\n                _callData,\\\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\\\n            );\\\\n\\\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\\\n                    controller,\\\\n                    weth,\\\\n                    data.vaultId,\\\\n                    data.wPowerPerpAmountToMint,\\\\n                    data.collateralToDeposit\\\\n                );\\\\n\\\\n                // this is a newly open vault, transfer to the user\\\\n                if (data.vaultId == 0)\\\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\\\n            }\\\\n\\\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\\\n        ) {\\\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\\\n        ) {\\\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\\\n        ) {\\\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\\\n                _callData,\\\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\\\n            );\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                data.vaultId,\\\\n                data.wPowerPerpAmountToBurn,\\\\n                data.collateralToWithdraw\\\\n            );\\\\n\\\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\\\n        ) {\\\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice wrap ETH to WETH\\\\n     * @param _amount amount to wrap\\\\n     */\\\\n    function wrapInternal(uint256 _amount) internal {\\\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\\\n    }\\\\n\\\\n    function _closeShortWithAmountsFromLp(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _wPowerPerpAmountToBurn,\\\\n        uint256 _collateralToWithdraw,\\\\n        uint256 _limitPriceEthPerPowerPerp,\\\\n        uint24 _poolFee,\\\\n        bool burnExactRemoved\\\\n    ) private {\\\\n        if (burnExactRemoved) {\\\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                _vaultId,\\\\n                _wPowerPerpAmount,\\\\n                _collateralToWithdraw\\\\n            );\\\\n        } else {\\\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\\\n                // swap needed wPowerPerp amount to close short position\\\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\\\n\\\\n                _exactOutFlashSwap(\\\\n                    weth,\\\\n                    wPowerPerp,\\\\n                    _poolFee,\\\\n                    wPowerPerpDeficit,\\\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\\\n                );\\\\n            } else {\\\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\\\n                ControllerHelperUtil.burnWithdrawFromVault(\\\\n                    controller,\\\\n                    weth,\\\\n                    _vaultId,\\\\n                    _wPowerPerpAmountToBurn,\\\\n                    _collateralToWithdraw\\\\n                );\\\\n\\\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\\\n                if (wPowerPerpExcess > 0) {\\\\n                    _exactInFlashSwap(\\\\n                        wPowerPerp,\\\\n                        weth,\\\\n                        _poolFee,\\\\n                        wPowerPerpExcess,\\\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\\\n                        \\\\\\\"\\\\\\\"\\\\n                    );\\\\n                }\\\\n            }\\\\n        }\\\\n\\\\n        // wrap ETH to WETH\\\\n        wrapInternal(address(this).balance);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe9649979188ed6661ec0511b25ef05748ae61abd4ffc1f716ca7e89b7faf333e\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/EulerControllerHelper.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: agpl-3.0\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IERC20Detailed} from \\\\\\\"../interfaces/IERC20Detailed.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\\\ninterface IDeferredLiquidityCheck {\\\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\\\n}\\\\n\\\\ninterface IExec {\\\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\\\n}\\\\n\\\\ninterface IEulerDToken {\\\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\\\n\\\\n    function repay(uint256 subAccountId, uint256 amount) external;\\\\n}\\\\n\\\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\\\n    using SafeMath for uint256;\\\\n\\\\n    address public immutable exec;\\\\n    address public immutable euler;\\\\n    address public immutable token;\\\\n    address public immutable dToken;\\\\n\\\\n    struct FlashloanCallbackData {\\\\n        address caller;\\\\n        address assetToBorrow;\\\\n        uint256 amountToBorrow;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    constructor(\\\\n        address _exec,\\\\n        address _euler,\\\\n        address _token,\\\\n        address _dToken\\\\n    ) {\\\\n        exec = _exec;\\\\n        euler = _euler;\\\\n        token = _token;\\\\n        dToken = _dToken;\\\\n    }\\\\n\\\\n    function _flashCallback(\\\\n        address _initiator,\\\\n        address _asset,\\\\n        uint256 _amount,\\\\n        uint8 _callSource,\\\\n        bytes memory _calldata\\\\n    ) internal virtual {}\\\\n\\\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\\\n        // sanity checks\\\\n        require(msg.sender == euler);\\\\n\\\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\\\n\\\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\\\n\\\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\\\n\\\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\\\n    }\\\\n\\\\n    /**\\\\n     */\\\\n    function _flashLoan(\\\\n        address _asset,\\\\n        uint256 _amount,\\\\n        uint8 _callSource,\\\\n        bytes memory _data\\\\n    ) internal {\\\\n        // Disable the liquidity check for \\\\\\\"this\\\\\\\" and call-back into onDeferredLiquidityCheck:\\\\n        IExec(exec).deferLiquidityCheck(\\\\n            address(this),\\\\n            abi.encode(\\\\n                FlashloanCallbackData({\\\\n                    caller: msg.sender,\\\\n                    assetToBorrow: _asset,\\\\n                    amountToBorrow: _amount,\\\\n                    callSource: _callSource,\\\\n                    callData: _data\\\\n                })\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6a7f3fef2c2eca5a4851e75c632eff2e7c28b4b244ad9fb0bbe2247efe1b395c\\\",\\\"license\\\":\\\"agpl-3.0\\\"},\\\"contracts/periphery/UniswapControllerHelper.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\\\\\";\\\\n\\\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\\\n    using Path for bytes;\\\\n    using SafeCast for uint256;\\\\n    using LowGasSafeMath for uint256;\\\\n    using LowGasSafeMath for int256;\\\\n\\\\n    /// @dev Uniswap factory address\\\\n    address public immutable factory;\\\\n\\\\n    struct SwapCallbackData {\\\\n        bytes path;\\\\n        address caller;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev constructor\\\\n     * @param _factory uniswap factory address\\\\n     */\\\\n    constructor(address _factory) {\\\\n        require(_factory != address(0));\\\\n        factory = _factory;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap swap callback function for flashswap\\\\n     * @param amount0Delta amount of token0\\\\n     * @param amount1Delta amount of token1\\\\n     * @param _data callback data encoded as SwapCallbackData struct\\\\n     */\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata _data\\\\n    ) external override {\\\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\\\n\\\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //ensure that callback comes from uniswap pool\\\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\\\n\\\\n        //determine the amount that needs to be repaid as part of the flashswap\\\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\\\n\\\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountIn amount to sell\\\\n     * @param _amountOutMinimum minimum amount to receive\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call\\\\n     */\\\\n    function _exactInFlashSwap(\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        uint24 _fee,\\\\n        uint256 _amountIn,\\\\n        uint256 _amountOutMinimum,\\\\n        uint8 _callSource,\\\\n        bytes memory _data\\\\n    ) internal returns (uint256) {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountOut = _exactInputInternal(\\\\n            _amountIn,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({\\\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\\\n                caller: msg.sender,\\\\n                callSource: _callSource,\\\\n                callData: _data\\\\n            })\\\\n        );\\\\n\\\\n        //slippage limit check\\\\n        require(amountOut >= _amountOutMinimum);\\\\n\\\\n        return amountOut;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountOut exact amount to receive\\\\n     * @param _amountInMaximum maximum amount to sell\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call\\\\n     */\\\\n    function _exactOutFlashSwap(\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        uint24 _fee,\\\\n        uint256 _amountOut,\\\\n        uint256 _amountInMaximum,\\\\n        uint8 _callSource,\\\\n        bytes memory _data\\\\n    ) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountIn = _exactOutputInternal(\\\\n            _amountOut,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({\\\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\\\n                caller: msg.sender,\\\\n                callSource: _callSource,\\\\n                callData: _data\\\\n            })\\\\n        );\\\\n\\\\n        //slippage limit check\\\\n        require(amountIn <= _amountInMaximum);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice function to be called by uniswap callback.\\\\n     * @dev this function should be overridden by the child contract\\\\n     * param _caller initial strategy function caller\\\\n     * param _tokenIn token address sold\\\\n     * param _tokenOut token address bought\\\\n     * param _fee pool fee\\\\n     * param _amountToPay amount to pay for the pool second token\\\\n     * param _callData arbitrary data assigned with the flashswap call\\\\n     * param _callSource function call source\\\\n     */\\\\n    function _swapCallback(\\\\n        address _caller,\\\\n        address _tokenIn,\\\\n        address _pool,\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal virtual {}\\\\n\\\\n    /**\\\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\\\n     * @param _amountIn amount of token to pay\\\\n     * @param _recipient recipient for receive\\\\n     * @param _sqrtPriceLimitX96 price limit\\\\n     * @return amount of token bought (amountOut)\\\\n     */\\\\n    function _exactInputInternal(\\\\n        uint256 _amountIn,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\\\n            _recipient,\\\\n            zeroForOne,\\\\n            _amountIn.toInt256(),\\\\n            _sqrtPriceLimitX96 == 0\\\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                : _sqrtPriceLimitX96,\\\\n            abi.encode(data)\\\\n        );\\\\n\\\\n        //determine the amountOut based on which token has a lower address\\\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\\\n     * @param _amountOut amount of token to receive\\\\n     * @param _recipient recipient for receive\\\\n     * @param _sqrtPriceLimitX96 price limit\\\\n     * @return amount of token sold (amountIn)\\\\n     */\\\\n    function _exactOutputInternal(\\\\n        uint256 _amountOut,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\\\n            _recipient,\\\\n            zeroForOne,\\\\n            -_amountOut.toInt256(),\\\\n            _sqrtPriceLimitX96 == 0\\\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                : _sqrtPriceLimitX96,\\\\n            abi.encode(data)\\\\n        );\\\\n\\\\n        //determine the amountIn and amountOut based on which token has a lower address\\\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\\\n        // it's technically possible to not receive the full output amount,\\\\n        // so if no price limit has been specified, require this possibility away\\\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\\\n\\\\n        return amountIn;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice returns the uniswap pool for the given token pair and fee\\\\n     * @dev the pool contract may or may not exist\\\\n     * @param tokenA address of first token\\\\n     * @param tokenB address of second token\\\\n     * @param fee fee tier for pool\\\\n     */\\\\n    function _getPool(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (address) {\\\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x91b5e0a2bc1ce71c0c614f89c6304c2d9ea5052120bdc88f0cf62f694afd284e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/lib/ControllerHelperDataType.sol\\\":{\\\"content\\\":\\\"pragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperDataType {\\\\n    using SafeMath for uint256;\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum CALLBACK_SOURCE {\\\\n        FLASH_W_MINT,\\\\n        FLASH_W_BURN,\\\\n        FLASH_SELL_LONG_W_MINT,\\\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\\\n        GENERAL_SWAP\\\\n    }\\\\n\\\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\\\n    enum RebalanceVaultNftType {\\\\n        IncreaseLpLiquidity,\\\\n        DecreaseLpLiquidity,\\\\n        DepositIntoVault,\\\\n        WithdrawFromVault,\\\\n        MintNewLp,\\\\n        generalSwap,\\\\n        CollectFees, \\\\n        DepositExistingNft\\\\n    }\\\\n    \\\\n    /// @dev params for flashswapWBurnBuyLong()\\\\n    struct FlashswapWBurnBuyLongParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\\\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev params for flashswapSellLongWMint()\\\\n    struct FlashSellLongWMintParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\\\n    struct SwapExactoutEthWPowerPerpData {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\\\n    }\\\\n\\\\n    /// @dev params for CloseShortWithUserNft()\\\\n    struct CloseShortWithUserNftParams {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity;  // liquidity amount in LP \\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;      // uniswap pool fee\\\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for wMintLp()\\\\n    struct MintAndLpParams {\\\\n        address recipient;  // recipient address\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 collateralToLp; // collateral amount to LP\\\\n        uint256 amount0Min; // minimum amount to LP of asset0\\\\n        uint256 amount1Min; // minimum amount to LP of asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for flashloanWMintDepositNft()\\\\n    struct FlashloanWMintLpDepositNftParams {\\\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\\\n        uint256 vaultId; // vault ID (could be zero)\\\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\\\n        uint256 amount0Min; // minimum amount of token0 to LP\\\\n        uint256 amount1Min; // minimum amount of token1 to LP\\\\n        int24 lowerTick; // range lower tick to LP in\\\\n        int24 upperTick; // range upper tick to LP in\\\\n    }\\\\n\\\\n    /// @dev params for flashloanCloseVaultLpNft()\\\\n    struct FlashloanCloseVaultLpNftParam {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity; // amount of liquidity in LP position\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for _closeUniLp() \\\\n    struct CloseUniLpParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\\\n    }\\\\n\\\\n    /// @dev params for sellAll()\\\\n    struct ReduceLiquidityAndSellParams {\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpWithoutVault()\\\\n    struct RebalanceLpWithoutVaultParams {\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\\\n        uint256 wethAmountDesired;  // WETH amount to LP\\\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\\\n    struct LpWPowerPerpPoolParams {\\\\n        address recipient;  // recipient address\\\\n        uint256 amount0Desired; // amount desired to LP for asset0\\\\n        uint256 amount1Desired; // amount desired to LP for asset1\\\\n        uint256 amount0Min; // amount min to LP for asset0\\\\n        uint256 amount1Min; // amount min to LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpInVault()\\\\n    struct RebalanceLpInVaultParams {\\\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\\\n        bytes data;\\\\n    }\\\\n\\\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\\\n    struct IncreaseLpLiquidityParams {\\\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 wethAmountToLp; // WETH amount to LP\\\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for decrease liquidity in LP position\\\\n    struct DecreaseLpLiquidityParams {  \\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for minting into vault\\\\n    struct DepositIntoVaultParams {\\\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\\\n    }\\\\n\\\\n    /// @dev struct for withdrawing from vault\\\\n    struct withdrawFromVaultParams {  \\\\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\\\n    }\\\\n\\\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\\\n    struct GeneralSwapParams {\\\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\\\n        uint256 amountIn; // amount to swap in\\\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\\\n    struct CollectFeesParams {\\\\n        uint256 tokenId;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\\\n    struct DepositExistingNftParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x04a47d47c3e0a1ec4e834f9aa466960200084fbdee47f0f513990b2c4708b02a\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/ControllerHelperUtil.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ControllerHelperDataType} from \\\\\\\"./ControllerHelperDataType.sol\\\\\\\";\\\\nimport {LiquidityAmounts} from \\\\\\\"./LiquidityAmounts.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"../../libs/TickMathExternal.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperUtil {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /**\\\\n     * @notice fully or partially close Uni v3 LP\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return withdrawn wPowerPerp and WETH amounts\\\\n     */\\\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\\\n            .DecreaseLiquidityParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\\\n                amount0Min: _params.amount0Min,\\\\n                amount1Min: _params.amount1Min,\\\\n                deadline: block.timestamp\\\\n            });\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\\\n\\\\n        uint256 wethAmount;\\\\n        uint256 _wPowerPerpAmount;\\\\n        (_isWethToken0)\\\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n                INonfungiblePositionManager.CollectParams({\\\\n                    tokenId: _params.tokenId,\\\\n                    recipient: address(this),\\\\n                    amount0Max: type(uint128).max,\\\\n                    amount1Max: type(uint128).max\\\\n                })\\\\n            )\\\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n            INonfungiblePositionManager.CollectParams({\\\\n                tokenId: _params.tokenId,\\\\n                recipient: address(this),\\\\n                amount0Max: type(uint128).max,\\\\n                amount1Max: type(uint128).max\\\\n            })\\\\n        );\\\\n\\\\n        return (_wPowerPerpAmount, wethAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\\\n     * @param _collateralToLp amount of ETH collateral to LP\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\\\n     * @param _lowerTick LP position lower tick\\\\n     * @param _upperTick LP position upper tick\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return exact amount0 and amount1 to be LPed\\\\n     */\\\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\\\n        uint256 amount0Desired; \\\\n        uint256 amount1Desired;\\\\n\\\\n        {\\\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\\\n        }\\\\n        \\\\n        return (amount0Desired, amount1Desired);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\\\n     * @param _controller wPowerPerp controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return _vaultId and tokenId\\\\n     */\\\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\\\n\\\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\\\n                \\\\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\\\n                _mintAndLpParams.vaultId,\\\\n                amountToMint,\\\\n                0\\\\n            );\\\\n        }\\\\n        // LP amount0Desired and amount1Desired in Uni v3\\\\n        uint256 uniTokenId = lpWPowerPerpPool(\\\\n            _nonfungiblePositionManager,\\\\n            _mintAndLpParams.wPowerPerpPool,\\\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\\\n                recipient: _mintAndLpParams.recipient,\\\\n                amount0Desired: amount0Desired,\\\\n                amount1Desired: amount1Desired,\\\\n                amount0Min: _mintAndLpParams.amount0Min,\\\\n                amount1Min: _mintAndLpParams.amount1Min,\\\\n                lowerTick: _mintAndLpParams.lowerTick,\\\\n                upperTick: _mintAndLpParams.upperTick\\\\n            })\\\\n        );\\\\n        return (_vaultId, uniTokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice increase liquidityin Uni v3 position\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault Id\\\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     */\\\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\\\n            (\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                int24 tickLower,\\\\n                int24 tickUpper,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                \\\\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\\\n\\\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n\\\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\\\n                    _vaultId,\\\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\\\n                    0\\\\n                );\\\\n            }\\\\n        }\\\\n\\\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\\\n            tokenId: _increaseLiquidityParam.tokenId,\\\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\\\n            deadline: block.timestamp\\\\n        });\\\\n\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp in vault\\\\n     * @param _controller controller address\\\\n     * @param _weth WETH address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\\\n     * @param _collateralToDeposit amount of collateral to deposit\\\\n     */\\\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\\\n\\\\n        uint256 vaultId = _vaultId;\\\\n        if (_wPowerPerpToMint > 0) {\\\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\\\n                _vaultId,\\\\n                _wPowerPerpToMint,\\\\n                0\\\\n            );\\\\n        } else {\\\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\\\n        }\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\\\n     * @param _controller controller address\\\\n     * @param _weth weth address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     */\\\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\\\n        IController(_controller).burnWPowerPerpAmount(\\\\n            _vaultId,\\\\n            _wPowerPerpToBurn,\\\\n            _collateralToWithdraw\\\\n        );\\\\n\\\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice LP into Uniswap V3 pool\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\\\n     */\\\\n    function lpWPowerPerpPool(\\\\n        address _nonfungiblePositionManager,\\\\n        address _wPowerPerpPool,\\\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\\\n    ) public returns (uint256) {\\\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\\\n            tickLower: int24(_params.lowerTick),\\\\n            tickUpper: int24(_params.upperTick),\\\\n            amount0Desired: _params.amount0Desired,\\\\n            amount1Desired: _params.amount1Desired,\\\\n            amount0Min: _params.amount0Min,\\\\n            amount1Min: _params.amount1Min,\\\\n            recipient: _params.recipient,\\\\n            deadline: block.timestamp\\\\n        });\\\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\\\n            mintParams\\\\n        );\\\\n        return tokenId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\\\n     * @param _user user address\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault ID\\\\n     * @param _tokenId Uni LP NFT id\\\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\\\n     */\\\\n    function checkClosedLp(\\\\n        address _user,\\\\n        address _controller,\\\\n        address _nonfungiblePositionManager,\\\\n        uint256 _vaultId,\\\\n        uint256 _tokenId,\\\\n        uint256 _liquidityPercentage\\\\n    ) public {\\\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\\\n                address(this),\\\\n                _user,\\\\n                _tokenId\\\\n            );\\\\n        } else {\\\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice send ETH and wPowerPerp\\\\n     * @param _weth WETH address\\\\n     * @param _wPowerPerp wPowerPerp address\\\\n     */\\\\n    function sendBack(address _weth, address _wPowerPerp) public {\\\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n        if (wPowerPerpBalance > 0) {\\\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x51c6185083d747a36ee8543219c0e7a326b866c0bdc113e82956cd4e226f7ba3\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/LiquidityAmounts.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"../../libs/SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\n\\\\n\\\\n/// @title Liquidity amount functions\\\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\\\nlibrary LiquidityAmounts {\\\\n    /// @notice Downcasts uint256 to uint128\\\\n    /// @param x The uint258 to be downcasted\\\\n    /// @return y The passed value, downcasted to uint128\\\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\\\n        require((y = uint128(x)) == x);\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount0 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount0(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount1 The amount1 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount1(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount of token0 being sent in\\\\n    /// @param amount1 The amount of token1 being sent in\\\\n    /// @return liquidity The maximum amount of liquidity received\\\\n    function getLiquidityForAmounts(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\\\n\\\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\\\n        } else {\\\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\\\n        }\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    function getAmount0ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            FullMath.mulDiv(\\\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\\\n                sqrtRatioBX96 - sqrtRatioAX96,\\\\n                sqrtRatioBX96\\\\n            ) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmount1ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n\\\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmountsForLiquidity(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\\\n        } else {\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        }\\\\n    }\\\\n\\\\n    function getAmountsFromLiquidity(        \\\\n        uint160 sqrtRatioX96,\\\\n        int24 currentTick,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (currentTick < tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else if (currentTick < tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtRatioX96,\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                sqrtRatioX96,\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            }\\\\n    \\\\n    }\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb4b0f464529a43f3ca7a9d6afc5976902c0a004649bdf3239ca77469d26b7cf2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101e06040523480156200001257600080fd5b5060405162006a3e38038062006a3e833981016040819052620000359162000679565b8282876001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200007157600080fd5b505afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac919062000655565b83876001600160a01b038116620000c257600080fd5b6001600160601b0319606091821b811660805294811b851660a05292831b841660c05290821b831660e052811b82166101005287901b166101405260408051634ea64a2160e11b815290516001600160a01b03881691639d4c9442916004808301926020929190829003018186803b1580156200013e57600080fd5b505afa15801562000153573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000179919062000655565b6001600160a01b0316610160816001600160a01b031660601b81525050856001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b158015620001d057600080fd5b505afa158015620001e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200020b919062000655565b6001600160a01b0316610180816001600160a01b031660601b81525050856001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200026257600080fd5b505afa15801562000277573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029d919062000655565b6001600160601b0319606091821b81166101a0529086901b166101c052604080516307f07b1360e41b815290516001600160a01b03881691637f07b130916004808301926020929190829003018186803b158015620002fb57600080fd5b505afa15801562000310573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000336919062000655565b6001600160a01b0316866001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200037957600080fd5b505afa1580156200038e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003b4919062000655565b6001600160a01b031610151561012081151560f81b81525050856001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b1580156200040757600080fd5b505afa1580156200041c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000442919062000655565b6001600160a01b031663095ea7b3866000196040518363ffffffff1660e01b81526004016200047392919062000736565b602060405180830381600087803b1580156200048e57600080fd5b505af1158015620004a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c99190620006f9565b50856001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200050457600080fd5b505afa15801562000519573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200053f919062000655565b6001600160a01b031663095ea7b3866000196040518363ffffffff1660e01b81526004016200057092919062000736565b602060405180830381600087803b1580156200058b57600080fd5b505af1158015620005a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c69190620006f9565b5060405163a22cb46560e01b81526001600160a01b0386169063a22cb46590620005f89089906001906004016200071b565b600060405180830381600087803b1580156200061357600080fd5b505af115801562000628573d6000803e3d6000fd5b505050505050505050506200074f565b80516001600160a01b03811681146200065057600080fd5b919050565b60006020828403121562000667578081fd5b620006728262000638565b9392505050565b60008060008060008060c0878903121562000692578182fd5b6200069d8762000638565b9550620006ad6020880162000638565b9450620006bd6040880162000638565b9350620006cd6060880162000638565b9250620006dd6080880162000638565b9150620006ed60a0880162000638565b90509295509295509295565b6000602082840312156200070b578081fd5b8151801515811462000672578182fd5b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6101205160f81c6101405160601c6101605160601c6101805160601c6101a05160601c6101c05160601c615fe162000a5d600039806102f452806103dc52806104cd52806108aa5280610b315280610cca5280610efc5280610f8652806110f1528061183f52806118d55280611a4152806120bc52806125eb528061274a5280612a5f5280612bff5280612d5552806132cb528061367e52508061074952806108275280610a385280610acf5280610bef5280610d0e5280610e67528061118252806111fc528061125e52806112c4528061136652806113d3528061177a5280611c0552806120fe52806122f5528061246852806128405280612e0b5280612f13528061310852806131d0528061330d528061349b528061355b528061384d528061392552806139a45280613a6a5280613b0b5280613c405280613cad5280613df5528061404e528061411d52508061076a52806108065280610a5a5280610c115280610cec5280610e895280611161528061121e52806112e652806113f452806116ae528061175952806120dd5280612a815280612ff352806132ec52806134db528061351b52806139c55280613aea5280613f165280613f86525080610dcc5280611e7252806123a25280613e915250806104ab5280610ca852806110cf5280611a1f528061209b528061224f52806122d452806124e65280612565528061272852806128bc528061293b5280612a3d5280612b145280612d335280612ef152806130e652806131ae52806132aa52806133da5280613789528061382b52806139035280613a485280613c1e5280613dd352806140fb52806144985250806103ff528061053d52806105b852806106a852806108f252806109245280610d32528061100d528061195e52806121a4528061265b5280612aa85280612c6d528061332f5250806114b052806116195280611aea525080611bdb52508061146c52806115695280611b0e5250806117d85280611f145250806117fc5280611b7752806147505250615fe16000f3fe6080604052600436106101125760003560e01c8063a15db5c5116100a5578063d8fa26f011610074578063db661b7111610059578063db661b711461027a578063fa461e331461028f578063fc0c546a146102af57610119565b8063d8fa26f014610252578063d9d7858a1461026557610119565b8063a15db5c5146101e8578063bc638a7914610208578063c1c0e9c41461021b578063c45a01551461023d57610119565b80633ca8402b116100e15780633ca8402b1461018f5780634fc5864f146101af57806383b17e4d146101c2578063923247ae146101d557610119565b8063150b7a021461011e57806315d23b04146101545780632ef1f08214610169578063334cc3651461017c57610119565b3661011957005b600080fd5b34801561012a57600080fd5b5061013e610139366004614aaf565b6102c4565b60405161014b9190615b22565b60405180910390f35b6101676101623660046151a6565b6102d4565b005b610167610177366004615506565b610ab8565b61016761018a3660046150fe565b610c39565b34801561019b57600080fd5b506101676101aa3660046151b8565b610ee5565b6101676101bd366004614ea3565b611246565b6101676101d0366004614c3e565b611341565b6101676101e3366004614db7565b61139d565b3480156101f457600080fd5b50610167610203366004614b51565b611461565b610167610216366004614db7565b61167d565b34801561022757600080fd5b506102306117d6565b60405161014b91906156ad565b34801561024957600080fd5b506102306117fa565b610167610260366004614c3e565b61181e565b34801561027157600080fd5b50610230611ae8565b34801561028657600080fd5b50610230611b0c565b34801561029b57600080fd5b506101676102aa366004614bc3565b611b30565b3480156102bb57600080fd5b50610230611bd9565b630a85bd0160e11b949350505050565b6102dd34611bfd565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061033190339030906020870135906004016156c1565b600060405180830381600087803b15801561034b57600080fd5b505af115801561035f573d6000803e3d6000fd5b50506040805160a08101825260208086013582528583013590820152670de0b6b3a7640000818301526001600160801b0361010086013581166060830152610120860135166080820152905163760a3f2b60e11b81526000935073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE925063ec147e5691610427917f000000000000000000000000000000000000000000000000000000000000000091907f000000000000000000000000000000000000000000000000000000000000000090600401615a6c565b604080518083038186803b15801561043e57600080fd5b505af4158015610452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104769190614ba0565b50604051630725e4e160e31b815290915073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9063392f2708906105089033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a013590670de0b6b3a7640000906004016156e5565b60006040518083038186803b15801561052057600080fd5b505af4158015610534573d6000803e3d6000fd5b505050506000807f0000000000000000000000000000000000000000000000000000000000000000156106515773B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63b573fa8b6105886020870187614a77565b608087013560608801356105a46101608a016101408b01614b84565b6105b66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016105f896959493929190615ae7565b604080518083038186803b15801561060f57600080fd5b505af4158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190614ba0565b909250905061073c565b73B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63b573fa8b6106786020870187614a77565b608087013560608801356106946101608a016101408b01614b84565b6106a66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016106e896959493929190615ae7565b604080518083038186803b1580156106ff57600080fd5b505af4158015610713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107379190614ba0565b925090505b828111156107eb576107e67f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061079b6101a0880161018089016153db565b6107a58588611c61565b6107cf670de0b6b3a76400006107c96107be898c611c61565b60e08d013590611cc3565b90611d23565b600460405180602001604052806000815250611d8a565b61088e565b8281101561088e5760006107ff8483611c61565b905061088b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006108586101a089016101808a016153db565b84610873670de0b6b3a76400006107c960e08d013584611cc3565b60035b60405180602001604052806000815250611dee565b50505b73B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63aee2533b7f00000000000000000000000000000000000000000000000000000000000000006108d66020880188614a77565b6040518060e00160405280336001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000061091b578661091d565b875b81526020017f000000000000000000000000000000000000000000000000000000000000000061094d578761094f565b865b815260a08a0135602082015260c08a0135604082015260600161097a6101608b016101408c01614b84565b60020b81526020016109946101808b016101608c01614b84565b60020b8152506040518463ffffffff1660e01b81526004016109b89392919061596c565b60206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0891906153f7565b506040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610a9a57600080fd5b505af4158015610aae573d6000803e3d6000fd5b5050505050505050565b610ac184611e61565b610aca34611bfd565b610b1a7f0000000000000000000000000000000000000000000000000000000000000000846008878686604051602001610b0693929190615dc6565b604051602081830303815290604052611f12565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190610b669030906004016156ad565b60206040518083038186803b158015610b7e57600080fd5b505afa158015610b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb691906153f7565b15610bc057600080fd5b6040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b604081013515610c5057610c508160400135611e61565b610c62608082013560a0830135611fe8565b3414610c6d57600080fd5b610c7634611bfd565b6040516308e6940f60e41b815260009073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE90638e6940f090610d5a907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009089907f000000000000000000000000000000000000000000000000000000000000000090600401615738565b604080518083038186803b158015610d7157600080fd5b505af4158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190614ba0565b5090506040820135610e3857604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610e05903090339086906004016156c1565b600060405180830381600087803b158015610e1f57600080fd5b505af1158015610e33573d6000803e3d6000fd5b505050505b6040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610ec957600080fd5b505af4158015610edd573d6000803e3d6000fd5b505050505050565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610f3690339030908635906004016156c1565b600060405180830381600087803b158015610f5057600080fd5b505af1158015610f64573d6000803e3d6000fd5b50505050600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a00160405280866000013581526020018660200135815260200186604001358152602001866060016020810190610fe191906153bf565b6001600160801b03168152602001610fff60a08801608089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161104a93929190615a6c565b604080518083038186803b15801561106157600080fd5b505af4158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190614ba0565b5060408051630725e4e160e31b815291925073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9163392f2708916111239133917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000916000918a35918b0135906004016156e5565b60006040518083038186803b15801561113b57600080fd5b505af415801561114f573d6000803e3d6000fd5b505050506000811115610e38576111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006111b160e0860160c087016153db565b84610873670de0b6b3a76400006107c960a08a013584611cc3565b506040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b6112508135611e61565b61125934611bfd565b6112957f000000000000000000000000000000000000000000000000000000000000000060a0830135600784604051602001610b069190615c01565b6040516328bb252f60e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906351764a5e9061130e907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b15801561132657600080fd5b505af415801561133a573d6000803e3d6000fd5b5050505050565b602081013515611358576113588160200135611e61565b61136134611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000006080830135600684604051602001610b069190615cca565b6113a78135611e61565b6113b5606082013534611fe8565b816080013511156113c557600080fd5b6113ce34611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061142360c0850160a086016153db565b61143560208601356040870135611fe8565b608086013560018760405160200161144d9190615ba0565b604051602081830303815290604052611d8a565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461149657600080fd5b6000818060200190518101906114ac9190614ded565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ecbcdab600083604001516040518363ffffffff1660e01b8152600401611501929190615b4f565b600060405180830381600087803b15801561151b57600080fd5b505af115801561152f573d6000803e3d6000fd5b5050505061155481600001518260200151836040015184606001518560800151612042565b80602001516001600160a01b031663095ea7b37f000000000000000000000000000000000000000000000000000000000000000083604001516040518363ffffffff1660e01b81526004016115aa929190615ace565b602060405180830381600087803b1580156115c457600080fd5b505af11580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614b35565b50604080820151905163d8aed14560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163d8aed1459161164f91600091600401615b4f565b600060405180830381600087803b15801561166957600080fd5b505af1158015610edd573d6000803e3d6000fd5b80351561168e5761168e8135611e61565b61169734611bfd565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906116eb90339030906060870135906004016156c1565b602060405180830381600087803b15801561170557600080fd5b505af1158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190614b35565b50600061175260208301356060840135611fe8565b90506111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006117a960c0860160a087016153db565b8460808701356002886040516020016117c29190615ba0565b604051602081830303815290604052611dee565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6118288135611e61565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061187c90339030906020870135906004016156c1565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050506118b734611bfd565b600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200135815260200186604001358152602001866060013581526020018660e001602081019061193091906153bf565b6001600160801b03168152602001611950610120880161010089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161199b93929190615a6c565b604080518083038186803b1580156119b257600080fd5b505af41580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614ba0565b50604051630725e4e160e31b815290915073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9063392f270890611a789033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a01359060608b0135906004016156e5565b60006040518083038186803b158015611a9057600080fd5b505af4158015611aa4573d6000803e3d6000fd5b50610e389250508335905082608085013560a086013560c0870135611ad161014089016101208a016153db565b611ae36101608a016101408b01614b19565b6138b5565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000841380611b3f5750600083135b611b4857600080fd5b6000611b56828401846151c9565b90506000806000611b6a8460000151613b58565b9250925092506000611b9e7f0000000000000000000000000000000000000000000000000000000000000000858585613b89565b90506000808a13611baf5788611bb1565b895b9050611bcd86602001518684848a606001518b60400151613ba8565b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8015611c5e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166957600080fd5b50565b600082821115611cb8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600082611cd257506000611cbd565b82820282848281611cdf57fe5b0414611d1c5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f8b6021913960400191505060405180910390fd5b9392505050565b6000808211611d79576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611d8257fe5b049392505050565b6000611ddf8530600060405180608001604052808c8c8f604051602001611db393929190615644565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526141e7565b905083811115610aae57600080fd5b600080611e448630600060405180608001604052808e8d8f604051602001611e1893929190615644565b60408051601f1981840301815291815290825233602083015260ff8b1690820152606001889052614354565b905084811015611e5357600080fd5b90505b979650505050505050565b6040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611eaf908590600401615dbd565b60206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190614a93565b6001600160a01b031614611c5e57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060a00160405280336001600160a01b03168152602001886001600160a01b031681526020018781526020018660ff16815260200185815250604051602001611f8e9190615bae565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611fba929190615a4a565b600060405180830381600087803b158015611fd457600080fd5b505af1158015610aae573d6000803e3d6000fd5b600082820183811015611d1c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60068260ff16600981111561205357fe5b600981111561205e57fe5b14156124165760008180602001905181019061207a9190614f6c565b905060008073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000604051806101400160405280306001600160a01b031681526020018a600001516001600160a01b031681526020018a6020015181526020018a6040015181526020018a6060015181526020018a60a0015181526020018a60e0015181526020018a610100015181526020018a610120015160020b81526020018a610140015160020b8152507f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016121e496959493929190615818565b604080518083038186803b1580156121fb57600080fd5b505af415801561220f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122339190614ba0565b6040516348dc69a560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906122869085908590600401615b4f565b600060405180830381600087803b1580156122a057600080fd5b505af11580156122b4573d6000803e3d6000fd5b5050505073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE6363410a867f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085600061232e8960c001518d611fe890919063ffffffff16565b6040518663ffffffff1660e01b815260040161234e9594939291906159df565b60006040518083038186803b15801561236657600080fd5b505af415801561237a573d6000803e3d6000fd5b5050505082602001516000141561240e57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906123db9030908c9087906004016156c1565b600060405180830381600087803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050505b50505061133a565b60078260ff16600981111561242757fe5b600981111561243257fe5b14156127eb5760008180602001905181019061244e9190614eb5565b604051632e1a7d4d60e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061249d908790600401615dbd565b600060405180830381600087803b1580156124b757600080fd5b505af11580156124cb573d6000803e3d6000fd5b5050825160405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063b6b55f259250879161251d91600401615dbd565b6000604051808303818588803b15801561253657600080fd5b505af115801561254a573d6000803e3d6000fd5b5050835160405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016945063713d517f935061259b9250600401615dbd565b600060405180830381600087803b1580156125b557600080fd5b505af11580156125c9573d6000803e3d6000fd5b50505050600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200151815260200186604001518152602001866060015181526020018661010001516001600160801b031681526020018661012001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161269893929190615a6c565b604080518083038186803b1580156126af57600080fd5b505af41580156126c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e79190614ba0565b50825160208401516060850151604051630725e4e160e31b815293945073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9363392f270893612775938d937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000939291906004016156e5565b60006040518083038186803b15801561278d57600080fd5b505af41580156127a1573d6000803e3d6000fd5b505050506127e482600001518284608001516127ce8660a001518760c00151611fe890919063ffffffff16565b8660e001518761014001518861016001516138b5565b505061133a565b60088260ff1660098111156127fc57fe5b600981111561280757fe5b141561133a5760008082806020019051810190612824919061540f565b604051632e1a7d4d60e01b815291935091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612875908890600401615dbd565b600060405180830381600087803b15801561288f57600080fd5b505af11580156128a3573d6000803e3d6000fd5b505060405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063b6b55f25915087906128f5908690600401615dbd565b6000604051808303818588803b15801561290e57600080fd5b505af1158015612922573d6000803e3d6000fd5b505060405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063713d517f925061297391508590600401615dbd565b600060405180830381600087803b15801561298d57600080fd5b505af11580156129a1573d6000803e3d6000fd5b5050505060005b81518110156137fb5760008282815181106129bf57fe5b60200260200101516000015160078111156129d657fe5b1415612b895760008282815181106129ea57fe5b602002602001015160200151806020019051810190612a09919061507c565b8051604051637a04dbd760e01b815291925073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE91637a04dbd791612ad0917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091908b9089907f0000000000000000000000000000000000000000000000000000000000000000906004016158d4565b60006040518083038186803b158015612ae857600080fd5b505af4158015612afc573d6000803e3d6000fd5b5050505060208101516040516348dc69a560e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916391b8d34a91612b51918891600401615b4f565b600060405180830381600087803b158015612b6b57600080fd5b505af1158015612b7f573d6000803e3d6000fd5b50505050506137f3565b6001828281518110612b9757fe5b6020026020010151600001516007811115612bae57fe5b1415612dad576000828281518110612bc257fe5b602002602001015160200151806020019051810190612be19190614cbc565b905073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a0016040528085600001518152602001856020015181526020018560400151815260200185606001516001600160801b0316815260200185608001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401612caa93929190615a6c565b604080518083038186803b158015612cc157600080fd5b505af4158015612cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf99190614ba0565b505080516040808301519051630725e4e160e31b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE9263392f270892612d81928e927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c9291906004016156e5565b60006040518083038186803b158015612d9957600080fd5b505af4158015612b7f573d6000803e3d6000fd5b6002828281518110612dbb57fe5b6020026020010151600001516007811115612dd257fe5b1415612f95576000828281518110612de657fe5b602002602001015160200151806020019051810190612e059190614d6f565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612e5591906156ad565b60206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906153f7565b90508160200151811015612ebb57602082018190525b81516020830151604051639f70f9e560e01b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE92639f70f9e592612f3d927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60206040518083038186803b158015612f5557600080fd5b505af4158015612f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8d91906153f7565b5050506137f3565b6003828281518110612fa357fe5b6020026020010151600001516007811115612fba57fe5b1415613232576000828281518110612fce57fe5b602002602001015160200151806020019051810190612fed9190615370565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161303d91906156ad565b60206040518083038186803b15801561305557600080fd5b505afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d91906153f7565b905081604001511561316b5760006130a486614493565b9050818110156130b2578091505b60208301516040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE916363410a8691613135917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918c918991906004016159df565b60006040518083038186803b15801561314d57600080fd5b505af4158015613161573d6000803e3d6000fd5b505050505061322b565b8151811015613178578082525b815160208301516040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE926363410a86926131fa927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60006040518083038186803b15801561321257600080fd5b505af4158015613226573d6000803e3d6000fd5b505050505b50506137f3565b600482828151811061324057fe5b602002602001015160000151600781111561325757fe5b141561343f57600082828151811061326b57fe5b60200260200101516020015180602001905181019061328a9190615110565b9050600073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000877f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b815260040161336f96959493929190615818565b604080518083038186803b15801561338657600080fd5b505af415801561339a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133be9190614ba0565b6040516348dc69a560e11b815291965091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906134119088908590600401615b4f565b600060405180830381600087803b15801561342b57600080fd5b505af1158015613226573d6000803e3d6000fd5b600582828151811061344d57fe5b602002602001015160000151600781111561346457fe5b14156135e157600082828151811061347857fe5b6020026020010151602001518060200190518101906134979190615007565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561351357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b8061359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b61359c57600080fd5b61322b81600001518260200151836080015184604001516135da670de0b6b3a76400006107c988604001518960600151611cc390919063ffffffff16565b6009610876565b60068282815181106135ef57fe5b602002602001015160000151600781111561360657fe5b141561371557600082828151811061361a57fe5b6020026020010151602001518060200190518101906136399190614c5a565b604080516080810182528251815230602080830191909152830180516001600160801b03908116838501529051166060820152905163fc6f786560e01b8152919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fc6f7865906136bb908490600401615b5d565b6040805180830381600087803b1580156136d457600080fd5b505af11580156136e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370c9190614ba0565b505050506137f3565b600782828151811061372357fe5b602002602001015160000151600781111561373a57fe5b14156137f357600082828151811061374e57fe5b60200260200101516020015180602001905181019061376d9190614d34565b80516040516348dc69a560e11b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916391b8d34a916137bf91889190600401615b4f565b600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b50505050505b6001016129a8565b506040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906363410a869061387c907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009087906000908c906004016159df565b60006040518083038186803b15801561389457600080fd5b505af41580156138a8573d6000803e3d6000fd5b5050505050505050505050565b80156139895760006138c688614493565b9050868110156138d4578096505b6040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906363410a8690613953907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908d908d908c906004016159df565b60006040518083038186803b15801561396b57600080fd5b505af415801561397f573d6000803e3d6000fd5b5050505050613b46565b84861015613a1957600061399d8688611c61565b9050613a137f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085846139fc670de0b6b3a76400006107c98b84611cc3565b60058e8d8d60405160200161144d93929190615697565b50613b46565b6040516331a0854360e11b815273B53c2eE92A24B08521912e1687Bc8142a7E6a9EE906363410a8690613a98907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c908b908b906004016159df565b60006040518083038186803b158015613ab057600080fd5b505af4158015613ac4573d6000803e3d6000fd5b505050506000613add8688611c6190919063ffffffff16565b90508015613b4457613b427f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008584610873670de0b6b3a76400006107c98b84611cc3565b505b505b613b4f47611bfd565b50505050505050565b60008080613b668482614548565b9250613b73846014614614565b9050613b80846017614548565b91509193909250565b6000613b9f85613b9a8686866146d0565b614726565b95945050505050565b60018160ff166009811115613bb957fe5b6009811115613bc457fe5b1415613d3f57600082806020019051810190613be09190614dd2565b8051602082015160608301516040516331a0854360e11b815293945073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60006040518083038186803b158015613c8057600080fd5b505af4158015613c94573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb9150613ce69088908890600401615ace565b602060405180830381600087803b158015613d0057600080fd5b505af1158015613d14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d389190614b35565b5050610edd565b60028160ff166009811115613d5057fe5b6009811115613d5b57fe5b1415613f4d57600082806020019051810190613d779190614dd2565b9050600081602001511180613d90575060008160400151115b15613eff57805160208201516040808401519051639f70f9e560e01b815260009373B53c2eE92A24B08521912e1687Bc8142a7E6a9EE93639f70f9e593613e21937f0000000000000000000000000000000000000000000000000000000000000000937f000000000000000000000000000000000000000000000000000000000000000093909290916004016159df565b60206040518083038186803b158015613e3957600080fd5b505af4158015613e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7191906153f7565b8251909150613efd57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613eca9030908c9086906004016156c1565b600060405180830381600087803b158015613ee457600080fd5b505af1158015613ef8573d6000803e3d6000fd5b505050505b505b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ce69088908890600401615ace565b60038160ff166009811115613f5e57fe5b6009811115613f6957fe5b14156140155760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b602060405180830381600087803b158015613fd757600080fd5b505af1158015613feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400f9190614b35565b50610edd565b60048160ff16600981111561402657fe5b600981111561403157fe5b14156140855760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b60058160ff16600981111561409657fe5b60098111156140a157fe5b1415614145576000828060200190518101906140bd9190615287565b8051602082015160408084015190516331a0854360e11b815293945073B53c2eE92A24B08521912e1687Bc8142a7E6a9EE936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60098160ff16600981111561415657fe5b600981111561416157fe5b1415610edd5760405163a9059cbb60e01b81526001600160a01b0386169063a9059cbb906141959087908790600401615ace565b602060405180830381600087803b1580156141af57600080fd5b505af11580156141c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4f9190614b35565b6000806000806141fa8560000151613b58565b919450925090506001600160a01b038084169083161060008061421e858786614749565b6001600160a01b031663128acb088b856142378f614787565b6000036001600160a01b038e161561424f578d614275565b8761426e5773fffd8963efd1fc6a506488495d951d5263988d25614275565b6401000276a45b8d6040516020016142869190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142b5959493929190615a10565b6040805180830381600087803b1580156142ce57600080fd5b505af11580156142e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143069190614ba0565b915091506000808461431c578284600003614322565b83836000035b915091508a6001600160a01b031660001415614344578c811461434457600080fd5b509b9a5050505050505050505050565b6000806000806143678560000151613b58565b919450925090506001600160a01b038083169084161060008061438b868686614749565b6001600160a01b031663128acb088b856143a48f614787565b6001600160a01b038e16156143b9578d6143df565b876143d85773fffd8963efd1fc6a506488495d951d5263988d256143df565b6401000276a45b8d6040516020016143f09190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161441f959493929190615a10565b6040805180830381600087803b15801561443857600080fd5b505af115801561444c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144709190614ba0565b915091508261447f5781614481565b805b6000039b9a5050505050505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c64ea4a846040518263ffffffff1660e01b81526004016144e29190615dbd565b60806040518083038186803b1580156144fa57600080fd5b505afa15801561450e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453291906152dc565b606001516001600160801b03169150505b919050565b6000818260140110156145a2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b81601401835110156145fb576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b60008182600301101561466e576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156146c7576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6146d8614899565b826001600160a01b0316846001600160a01b031611156146f6579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614732838361479d565b9050336001600160a01b03821614611cbd57600080fd5b600061477f7f000000000000000000000000000000000000000000000000000000000000000061477a8686866146d0565b61479d565b949350505050565b6000600160ff1b821061479957600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b0316106147c557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561454381615f16565b805161454381615f16565b803561454381615f2b565b805161454381615f2b565b600082601f8301126148f5578081fd5b813561490861490382615ec4565b615ea0565b81815284602083860101111561491c578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614946578081fd5b815161495461490382615ec4565b818152846020838601011115614968578283fd5b61477f826020830160208701615ee6565b803561454381615f46565b805161454381615f46565b600061016082840312156149a1578081fd5b50919050565b600060c082840312156149a1578081fd5b600060c082840312156149c9578081fd5b60405160c0810181811067ffffffffffffffff821117156149e657fe5b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151614a2881615f6a565b60a0919091015292915050565b803561454381615f55565b805161454381615f55565b803561454381615f6a565b805161454381615f6a565b803561454381615f7b565b805161454381615f7b565b600060208284031215614a88578081fd5b8135611d1c81615f16565b600060208284031215614aa4578081fd5b8151611d1c81615f16565b60008060008060808587031215614ac4578283fd5b8435614acf81615f16565b93506020850135614adf81615f16565b925060408501359150606085013567ffffffffffffffff811115614b01578182fd5b614b0d878288016148e5565b91505092959194509250565b600060208284031215614b2a578081fd5b8135611d1c81615f2b565b600060208284031215614b46578081fd5b8151611d1c81615f2b565b600060208284031215614b62578081fd5b813567ffffffffffffffff811115614b78578182fd5b61477f848285016148e5565b600060208284031215614b95578081fd5b8135611d1c81615f46565b60008060408385031215614bb2578182fd5b505080516020909101519092909150565b60008060008060608587031215614bd8578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614bfd578384fd5b818701915087601f830112614c10578384fd5b813581811115614c1e578485fd5b886020828501011115614c2f578485fd5b95989497505060200194505050565b60006101608284031215614c50578081fd5b611d1c838361498f565b600060608284031215614c6b578081fd5b6040516060810181811067ffffffffffffffff82111715614c8857fe5b604052825181526020830151614c9d81615f55565b60208201526040830151614cb081615f55565b60408201529392505050565b600060a08284031215614ccd578081fd5b60405160a0810181811067ffffffffffffffff82111715614cea57fe5b80604052508251815260208301516020820152604083015160408201526060830151614d1581615f55565b60608201526080830151614d2881615f55565b60808201529392505050565b600060208284031215614d45578081fd5b6040516020810181811067ffffffffffffffff82111715614d6257fe5b6040529151825250919050565b600060408284031215614d80578081fd5b6040516040810181811067ffffffffffffffff82111715614d9d57fe5b604052825181526020928301519281019290925250919050565b600060c08284031215614dc8578081fd5b611d1c83836149a7565b600060c08284031215614de3578081fd5b611d1c83836149b8565b600060208284031215614dfe578081fd5b815167ffffffffffffffff80821115614e15578283fd5b9083019060a08286031215614e28578283fd5b60405160a081018181108382111715614e3d57fe5b604052614e49836148c4565b8152614e57602084016148c4565b602082015260408301516040820152614e7260608401614a6c565b6060820152608083015182811115614e88578485fd5b614e9487828601614936565b60808301525095945050505050565b600061018082840312156149a1578081fd5b6000610180808385031215614ec8578182fd5b614ed181615ea0565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100614f2b818501614a40565b90820152610120614f3d848201614a40565b90820152610140614f4f848201614a56565b90820152610160614f618482016148da565b908201529392505050565b6000610160808385031215614f7f578182fd5b614f8881615ea0565b9050614f93836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120614ff5818501614984565b90820152610140614f61848201614984565b600060a08284031215615018578081fd5b60405160a0810181811067ffffffffffffffff8211171561503557fe5b604052825161504381615f16565b8152602083015161505381615f16565b8060208301525060408301516040820152606083015160608201526080830151614d2881615f6a565b600060e0828403121561508d578081fd5b60405160e0810181811067ffffffffffffffff821117156150aa57fe5b6040526150b6836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600061014082840312156149a1578081fd5b6000610140808385031215615123578182fd5b61512c81615ea0565b9050615137836148c4565b8152615145602084016148c4565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100615194818501614984565b90820152610120614f61848201614984565b60006101a082840312156149a1578081fd5b600060e082840312156149a1578081fd5b6000602082840312156151da578081fd5b813567ffffffffffffffff808211156151f1578283fd5b9083019060808286031215615204578283fd5b60405160808101818110838211171561521957fe5b60405282358281111561522a578485fd5b615236878286016148e5565b825250615245602084016148b9565b602082015261525660408401614a61565b604082015260608301358281111561526c578485fd5b615278878286016148e5565b60608301525095945050505050565b600060608284031215615298578081fd5b6040516060810181811067ffffffffffffffff821117156152b557fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000608082840312156152ed578081fd5b6040516080810181811067ffffffffffffffff8211171561530a57fe5b604052825161531881615f16565b8152602083015163ffffffff81168114615330578283fd5b602082015260408301516bffffffffffffffffffffffff81168114615353578283fd5b604082015261536460608401614a40565b60608201529392505050565b600060608284031215615381578081fd5b6040516060810181811067ffffffffffffffff8211171561539e57fe5b806040525082518152602083015160208201526040830151614cb081615f2b565b6000602082840312156153d0578081fd5b8135611d1c81615f55565b6000602082840312156153ec578081fd5b8135611d1c81615f6a565b600060208284031215615408578081fd5b5051919050565b60008060408385031215615421578182fd5b8251915060208084015167ffffffffffffffff80821115615440578384fd5b818601915086601f830112615453578384fd5b81518181111561545f57fe5b61546c8485830201615ea0565b81815284810190848601875b848110156154f557815187016040818e03601f1901121561549757898afd5b6040516040810181811089821117156154ac57fe5b604052818a01516154bc81615f39565b81526040820151888111156154cf578b8cfd5b6154dd8f8c83860101614936565b828c0152508552509287019290870190600101615478565b50979a909950975050505050505050565b6000806000806060858703121561551b578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615540578384fd5b818701915087601f830112615553578384fd5b813581811115615561578485fd5b8860208083028501011115614c2f578485fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526155c9816020860160208601615ee6565b601f01601f19169290920160200192915050565b60020b9052565b803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a081013561561e81615f6a565b62ffffff811660a0840152505050565b6001600160801b03169052565b62ffffff169052565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286811660208301528581166040830152841660608201526101e0810161577660808301615771866148b9565b615574565b615782602085016148b9565b61578f60a0840182615574565b50604084013560c0830152606084013560e083015261010060808501358184015261012060a08601358185015260c086013561014085015260e08601356101608501526157dd828701614979565b91506157ed6101808501836155dd565b6157f8818701614979565b9150506158096101a08401826155dd565b50611e566101c0830184615581565b6001600160a01b038781168252868116602083015285811660408301528416606082015282516101e0820190615852906080840190615574565b602084015161586460a0840182615574565b50604084015160c0830152606084015160e08301526080840151610100818185015260a08601519150610120828186015260c087015161014086015260e08701516101608601528187015192506158bf6101808601846155dd565b860151915061580990506101a08401826155dd565b60006101a0820190506001600160a01b03808a1683528089166020840152808816604084015280871660608401528560808401528085511660a084015250602084015160c0830152604084015160e08301526060840151610100830152608084015161012083015260a084015161014083015260c0840151610160830152615960610180830184615581565b98975050505050505050565b6000610120820190506001600160a01b0380861683528085166020840152808451166040840152506020830151606083015260408301516080830152606083015160a0830152608083015160c083015260a083015160020b60e083015260c083015160020b610100830152949350505050565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152611e5660a08301846155b1565b60006001600160a01b03841682526040602083015261477f60408301846155b1565b600060e0820190506001600160a01b038516825283516020830152602084015160408301526040840151606083015260608401516001600160801b0380821660808501528060808701511660a0850152505082151560c0830152949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396909616865260208601949094526040850192909252600290810b60608501520b6080830152151560a082015260c00190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b918252602082015260400190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b60c08101611cbd82846155e4565b6000602082526001600160a01b03808451166020840152806020850151166040840152506040830151606083015260ff6060840151166080830152608083015160a08084015261477f60c08401826155b1565b600061018082019050823582526020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100615c62818501614a35565b615c6e8285018261562e565b5050610120615c7e818501614a35565b615c8a8285018261562e565b5050610140615c9a818501614a4b565b615ca68285018261563b565b5050610160615cb68185016148cf565b615cc282850182615581565b505092915050565b6101608101615cdc82615771856148b9565b6020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100808401358184015250610120615d3c818501614979565b615d48828501826155dd565b5050610140615d58818501614979565b615cc2828501826155dd565b600060208252825160806020840152615d8060a08401826155b1565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f19848303016080850152613b9f82826155b1565b90815260200190565b6000604080830186845260208281860152818683526060860190506060828802870101925087855b88811015615e9157878503605f190183528135368b9003603e19018112615e13578788fd5b8a018035615e2081615f39565b60088110615e2a57fe5b86528085013536829003601e19018112615e42578889fd5b8101803567ffffffffffffffff811115615e5a57898afd5b803603831315615e6857898afd5b8887890152615e7c89890182898501615587565b97505050928401925090830190600101615dee565b50929998505050505050505050565b60405181810167ffffffffffffffff81118282101715615ebc57fe5b604052919050565b600067ffffffffffffffff821115615ed857fe5b50601f01601f191660200190565b60005b83811015615f01578181015183820152602001615ee9565b83811115615f10576000848401525b50505050565b6001600160a01b0381168114611c5e57600080fd5b8015158114611c5e57600080fd5b60088110611c5e57600080fd5b8060020b8114611c5e57600080fd5b6001600160801b0381168114611c5e57600080fd5b62ffffff81168114611c5e57600080fd5b60ff81168114611c5e57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220564c27264bc33c078d9c75afb2f26fb0c092712e686cacc101aaeee9df569b6e64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x6080604052600436106101125760003560e01c8063a15db5c5116100a5578063d8fa26f011610074578063db661b7111610059578063db661b711461027a578063fa461e331461028f578063fc0c546a146102af57610119565b8063d8fa26f014610252578063d9d7858a1461026557610119565b8063a15db5c5146101e8578063bc638a7914610208578063c1c0e9c41461021b578063c45a01551461023d57610119565b80633ca8402b116100e15780633ca8402b1461018f5780634fc5864f146101af57806383b17e4d146101c2578063923247ae146101d557610119565b8063150b7a021461011e57806315d23b04146101545780632ef1f08214610169578063334cc3651461017c57610119565b3661011957005b600080fd5b34801561012a57600080fd5b5061013e610139366004614aaf565b6102c4565b60405161014b9190615b22565b60405180910390f35b6101676101623660046151a6565b6102d4565b005b610167610177366004615506565b610ab8565b61016761018a3660046150fe565b610c39565b34801561019b57600080fd5b506101676101aa3660046151b8565b610ee5565b6101676101bd366004614ea3565b611246565b6101676101d0366004614c3e565b611341565b6101676101e3366004614db7565b61139d565b3480156101f457600080fd5b50610167610203366004614b51565b611461565b610167610216366004614db7565b61167d565b34801561022757600080fd5b506102306117d6565b60405161014b91906156ad565b34801561024957600080fd5b506102306117fa565b610167610260366004614c3e565b61181e565b34801561027157600080fd5b50610230611ae8565b34801561028657600080fd5b50610230611b0c565b34801561029b57600080fd5b506101676102aa366004614bc3565b611b30565b3480156102bb57600080fd5b50610230611bd9565b630a85bd0160e11b949350505050565b6102dd34611bfd565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061033190339030906020870135906004016156c1565b600060405180830381600087803b15801561034b57600080fd5b505af115801561035f573d6000803e3d6000fd5b50506040805160a08101825260208086013582528583013590820152670de0b6b3a7640000818301526001600160801b0361010086013581166060830152610120860135166080820152905163760a3f2b60e11b81526000935073__$561e80098325da493156966792c25e3551$__925063ec147e5691610427917f000000000000000000000000000000000000000000000000000000000000000091907f000000000000000000000000000000000000000000000000000000000000000090600401615a6c565b604080518083038186803b15801561043e57600080fd5b505af4158015610452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104769190614ba0565b50604051630725e4e160e31b815290915073__$561e80098325da493156966792c25e3551$__9063392f2708906105089033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a013590670de0b6b3a7640000906004016156e5565b60006040518083038186803b15801561052057600080fd5b505af4158015610534573d6000803e3d6000fd5b505050506000807f0000000000000000000000000000000000000000000000000000000000000000156106515773__$561e80098325da493156966792c25e3551$__63b573fa8b6105886020870187614a77565b608087013560608801356105a46101608a016101408b01614b84565b6105b66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016105f896959493929190615ae7565b604080518083038186803b15801561060f57600080fd5b505af4158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190614ba0565b909250905061073c565b73__$561e80098325da493156966792c25e3551$__63b573fa8b6106786020870187614a77565b608087013560608801356106946101608a016101408b01614b84565b6106a66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016106e896959493929190615ae7565b604080518083038186803b1580156106ff57600080fd5b505af4158015610713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107379190614ba0565b925090505b828111156107eb576107e67f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061079b6101a0880161018089016153db565b6107a58588611c61565b6107cf670de0b6b3a76400006107c96107be898c611c61565b60e08d013590611cc3565b90611d23565b600460405180602001604052806000815250611d8a565b61088e565b8281101561088e5760006107ff8483611c61565b905061088b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006108586101a089016101808a016153db565b84610873670de0b6b3a76400006107c960e08d013584611cc3565b60035b60405180602001604052806000815250611dee565b50505b73__$561e80098325da493156966792c25e3551$__63aee2533b7f00000000000000000000000000000000000000000000000000000000000000006108d66020880188614a77565b6040518060e00160405280336001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000061091b578661091d565b875b81526020017f000000000000000000000000000000000000000000000000000000000000000061094d578761094f565b865b815260a08a0135602082015260c08a0135604082015260600161097a6101608b016101408c01614b84565b60020b81526020016109946101808b016101608c01614b84565b60020b8152506040518463ffffffff1660e01b81526004016109b89392919061596c565b60206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0891906153f7565b506040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610a9a57600080fd5b505af4158015610aae573d6000803e3d6000fd5b5050505050505050565b610ac184611e61565b610aca34611bfd565b610b1a7f0000000000000000000000000000000000000000000000000000000000000000846008878686604051602001610b0693929190615dc6565b604051602081830303815290604052611f12565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190610b669030906004016156ad565b60206040518083038186803b158015610b7e57600080fd5b505afa158015610b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb691906153f7565b15610bc057600080fd5b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b604081013515610c5057610c508160400135611e61565b610c62608082013560a0830135611fe8565b3414610c6d57600080fd5b610c7634611bfd565b6040516308e6940f60e41b815260009073__$561e80098325da493156966792c25e3551$__90638e6940f090610d5a907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009089907f000000000000000000000000000000000000000000000000000000000000000090600401615738565b604080518083038186803b158015610d7157600080fd5b505af4158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190614ba0565b5090506040820135610e3857604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610e05903090339086906004016156c1565b600060405180830381600087803b158015610e1f57600080fd5b505af1158015610e33573d6000803e3d6000fd5b505050505b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610ec957600080fd5b505af4158015610edd573d6000803e3d6000fd5b505050505050565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610f3690339030908635906004016156c1565b600060405180830381600087803b158015610f5057600080fd5b505af1158015610f64573d6000803e3d6000fd5b50505050600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a00160405280866000013581526020018660200135815260200186604001358152602001866060016020810190610fe191906153bf565b6001600160801b03168152602001610fff60a08801608089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161104a93929190615a6c565b604080518083038186803b15801561106157600080fd5b505af4158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190614ba0565b5060408051630725e4e160e31b815291925073__$561e80098325da493156966792c25e3551$__9163392f2708916111239133917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000916000918a35918b0135906004016156e5565b60006040518083038186803b15801561113b57600080fd5b505af415801561114f573d6000803e3d6000fd5b505050506000811115610e38576111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006111b160e0860160c087016153db565b84610873670de0b6b3a76400006107c960a08a013584611cc3565b506040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b6112508135611e61565b61125934611bfd565b6112957f000000000000000000000000000000000000000000000000000000000000000060a0830135600784604051602001610b069190615c01565b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e9061130e907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b15801561132657600080fd5b505af415801561133a573d6000803e3d6000fd5b5050505050565b602081013515611358576113588160200135611e61565b61136134611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000006080830135600684604051602001610b069190615cca565b6113a78135611e61565b6113b5606082013534611fe8565b816080013511156113c557600080fd5b6113ce34611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061142360c0850160a086016153db565b61143560208601356040870135611fe8565b608086013560018760405160200161144d9190615ba0565b604051602081830303815290604052611d8a565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461149657600080fd5b6000818060200190518101906114ac9190614ded565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ecbcdab600083604001516040518363ffffffff1660e01b8152600401611501929190615b4f565b600060405180830381600087803b15801561151b57600080fd5b505af115801561152f573d6000803e3d6000fd5b5050505061155481600001518260200151836040015184606001518560800151612042565b80602001516001600160a01b031663095ea7b37f000000000000000000000000000000000000000000000000000000000000000083604001516040518363ffffffff1660e01b81526004016115aa929190615ace565b602060405180830381600087803b1580156115c457600080fd5b505af11580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614b35565b50604080820151905163d8aed14560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163d8aed1459161164f91600091600401615b4f565b600060405180830381600087803b15801561166957600080fd5b505af1158015610edd573d6000803e3d6000fd5b80351561168e5761168e8135611e61565b61169734611bfd565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906116eb90339030906060870135906004016156c1565b602060405180830381600087803b15801561170557600080fd5b505af1158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190614b35565b50600061175260208301356060840135611fe8565b90506111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006117a960c0860160a087016153db565b8460808701356002886040516020016117c29190615ba0565b604051602081830303815290604052611dee565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6118288135611e61565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061187c90339030906020870135906004016156c1565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050506118b734611bfd565b600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200135815260200186604001358152602001866060013581526020018660e001602081019061193091906153bf565b6001600160801b03168152602001611950610120880161010089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161199b93929190615a6c565b604080518083038186803b1580156119b257600080fd5b505af41580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614ba0565b50604051630725e4e160e31b815290915073__$561e80098325da493156966792c25e3551$__9063392f270890611a789033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a01359060608b0135906004016156e5565b60006040518083038186803b158015611a9057600080fd5b505af4158015611aa4573d6000803e3d6000fd5b50610e389250508335905082608085013560a086013560c0870135611ad161014089016101208a016153db565b611ae36101608a016101408b01614b19565b6138b5565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000841380611b3f5750600083135b611b4857600080fd5b6000611b56828401846151c9565b90506000806000611b6a8460000151613b58565b9250925092506000611b9e7f0000000000000000000000000000000000000000000000000000000000000000858585613b89565b90506000808a13611baf5788611bb1565b895b9050611bcd86602001518684848a606001518b60400151613ba8565b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8015611c5e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166957600080fd5b50565b600082821115611cb8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600082611cd257506000611cbd565b82820282848281611cdf57fe5b0414611d1c5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f8b6021913960400191505060405180910390fd5b9392505050565b6000808211611d79576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611d8257fe5b049392505050565b6000611ddf8530600060405180608001604052808c8c8f604051602001611db393929190615644565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526141e7565b905083811115610aae57600080fd5b600080611e448630600060405180608001604052808e8d8f604051602001611e1893929190615644565b60408051601f1981840301815291815290825233602083015260ff8b1690820152606001889052614354565b905084811015611e5357600080fd5b90505b979650505050505050565b6040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611eaf908590600401615dbd565b60206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190614a93565b6001600160a01b031614611c5e57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060a00160405280336001600160a01b03168152602001886001600160a01b031681526020018781526020018660ff16815260200185815250604051602001611f8e9190615bae565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611fba929190615a4a565b600060405180830381600087803b158015611fd457600080fd5b505af1158015610aae573d6000803e3d6000fd5b600082820183811015611d1c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60068260ff16600981111561205357fe5b600981111561205e57fe5b14156124165760008180602001905181019061207a9190614f6c565b905060008073__$561e80098325da493156966792c25e3551$__638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000604051806101400160405280306001600160a01b031681526020018a600001516001600160a01b031681526020018a6020015181526020018a6040015181526020018a6060015181526020018a60a0015181526020018a60e0015181526020018a610100015181526020018a610120015160020b81526020018a610140015160020b8152507f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016121e496959493929190615818565b604080518083038186803b1580156121fb57600080fd5b505af415801561220f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122339190614ba0565b6040516348dc69a560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906122869085908590600401615b4f565b600060405180830381600087803b1580156122a057600080fd5b505af11580156122b4573d6000803e3d6000fd5b5050505073__$561e80098325da493156966792c25e3551$__6363410a867f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085600061232e8960c001518d611fe890919063ffffffff16565b6040518663ffffffff1660e01b815260040161234e9594939291906159df565b60006040518083038186803b15801561236657600080fd5b505af415801561237a573d6000803e3d6000fd5b5050505082602001516000141561240e57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906123db9030908c9087906004016156c1565b600060405180830381600087803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050505b50505061133a565b60078260ff16600981111561242757fe5b600981111561243257fe5b14156127eb5760008180602001905181019061244e9190614eb5565b604051632e1a7d4d60e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061249d908790600401615dbd565b600060405180830381600087803b1580156124b757600080fd5b505af11580156124cb573d6000803e3d6000fd5b5050825160405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063b6b55f259250879161251d91600401615dbd565b6000604051808303818588803b15801561253657600080fd5b505af115801561254a573d6000803e3d6000fd5b5050835160405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016945063713d517f935061259b9250600401615dbd565b600060405180830381600087803b1580156125b557600080fd5b505af11580156125c9573d6000803e3d6000fd5b50505050600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200151815260200186604001518152602001866060015181526020018661010001516001600160801b031681526020018661012001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161269893929190615a6c565b604080518083038186803b1580156126af57600080fd5b505af41580156126c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e79190614ba0565b50825160208401516060850151604051630725e4e160e31b815293945073__$561e80098325da493156966792c25e3551$__9363392f270893612775938d937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000939291906004016156e5565b60006040518083038186803b15801561278d57600080fd5b505af41580156127a1573d6000803e3d6000fd5b505050506127e482600001518284608001516127ce8660a001518760c00151611fe890919063ffffffff16565b8660e001518761014001518861016001516138b5565b505061133a565b60088260ff1660098111156127fc57fe5b600981111561280757fe5b141561133a5760008082806020019051810190612824919061540f565b604051632e1a7d4d60e01b815291935091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612875908890600401615dbd565b600060405180830381600087803b15801561288f57600080fd5b505af11580156128a3573d6000803e3d6000fd5b505060405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063b6b55f25915087906128f5908690600401615dbd565b6000604051808303818588803b15801561290e57600080fd5b505af1158015612922573d6000803e3d6000fd5b505060405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063713d517f925061297391508590600401615dbd565b600060405180830381600087803b15801561298d57600080fd5b505af11580156129a1573d6000803e3d6000fd5b5050505060005b81518110156137fb5760008282815181106129bf57fe5b60200260200101516000015160078111156129d657fe5b1415612b895760008282815181106129ea57fe5b602002602001015160200151806020019051810190612a09919061507c565b8051604051637a04dbd760e01b815291925073__$561e80098325da493156966792c25e3551$__91637a04dbd791612ad0917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091908b9089907f0000000000000000000000000000000000000000000000000000000000000000906004016158d4565b60006040518083038186803b158015612ae857600080fd5b505af4158015612afc573d6000803e3d6000fd5b5050505060208101516040516348dc69a560e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916391b8d34a91612b51918891600401615b4f565b600060405180830381600087803b158015612b6b57600080fd5b505af1158015612b7f573d6000803e3d6000fd5b50505050506137f3565b6001828281518110612b9757fe5b6020026020010151600001516007811115612bae57fe5b1415612dad576000828281518110612bc257fe5b602002602001015160200151806020019051810190612be19190614cbc565b905073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a0016040528085600001518152602001856020015181526020018560400151815260200185606001516001600160801b0316815260200185608001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401612caa93929190615a6c565b604080518083038186803b158015612cc157600080fd5b505af4158015612cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf99190614ba0565b505080516040808301519051630725e4e160e31b815273__$561e80098325da493156966792c25e3551$__9263392f270892612d81928e927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c9291906004016156e5565b60006040518083038186803b158015612d9957600080fd5b505af4158015612b7f573d6000803e3d6000fd5b6002828281518110612dbb57fe5b6020026020010151600001516007811115612dd257fe5b1415612f95576000828281518110612de657fe5b602002602001015160200151806020019051810190612e059190614d6f565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612e5591906156ad565b60206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906153f7565b90508160200151811015612ebb57602082018190525b81516020830151604051639f70f9e560e01b815273__$561e80098325da493156966792c25e3551$__92639f70f9e592612f3d927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60206040518083038186803b158015612f5557600080fd5b505af4158015612f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8d91906153f7565b5050506137f3565b6003828281518110612fa357fe5b6020026020010151600001516007811115612fba57fe5b1415613232576000828281518110612fce57fe5b602002602001015160200151806020019051810190612fed9190615370565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161303d91906156ad565b60206040518083038186803b15801561305557600080fd5b505afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d91906153f7565b905081604001511561316b5760006130a486614493565b9050818110156130b2578091505b60208301516040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__916363410a8691613135917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918c918991906004016159df565b60006040518083038186803b15801561314d57600080fd5b505af4158015613161573d6000803e3d6000fd5b505050505061322b565b8151811015613178578082525b815160208301516040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__926363410a86926131fa927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60006040518083038186803b15801561321257600080fd5b505af4158015613226573d6000803e3d6000fd5b505050505b50506137f3565b600482828151811061324057fe5b602002602001015160000151600781111561325757fe5b141561343f57600082828151811061326b57fe5b60200260200101516020015180602001905181019061328a9190615110565b9050600073__$561e80098325da493156966792c25e3551$__638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000877f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b815260040161336f96959493929190615818565b604080518083038186803b15801561338657600080fd5b505af415801561339a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133be9190614ba0565b6040516348dc69a560e11b815291965091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906134119088908590600401615b4f565b600060405180830381600087803b15801561342b57600080fd5b505af1158015613226573d6000803e3d6000fd5b600582828151811061344d57fe5b602002602001015160000151600781111561346457fe5b14156135e157600082828151811061347857fe5b6020026020010151602001518060200190518101906134979190615007565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561351357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b8061359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b61359c57600080fd5b61322b81600001518260200151836080015184604001516135da670de0b6b3a76400006107c988604001518960600151611cc390919063ffffffff16565b6009610876565b60068282815181106135ef57fe5b602002602001015160000151600781111561360657fe5b141561371557600082828151811061361a57fe5b6020026020010151602001518060200190518101906136399190614c5a565b604080516080810182528251815230602080830191909152830180516001600160801b03908116838501529051166060820152905163fc6f786560e01b8152919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fc6f7865906136bb908490600401615b5d565b6040805180830381600087803b1580156136d457600080fd5b505af11580156136e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370c9190614ba0565b505050506137f3565b600782828151811061372357fe5b602002602001015160000151600781111561373a57fe5b14156137f357600082828151811061374e57fe5b60200260200101516020015180602001905181019061376d9190614d34565b80516040516348dc69a560e11b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916391b8d34a916137bf91889190600401615b4f565b600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b50505050505b6001016129a8565b506040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a869061387c907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009087906000908c906004016159df565b60006040518083038186803b15801561389457600080fd5b505af41580156138a8573d6000803e3d6000fd5b5050505050505050505050565b80156139895760006138c688614493565b9050868110156138d4578096505b6040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a8690613953907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908d908d908c906004016159df565b60006040518083038186803b15801561396b57600080fd5b505af415801561397f573d6000803e3d6000fd5b5050505050613b46565b84861015613a1957600061399d8688611c61565b9050613a137f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085846139fc670de0b6b3a76400006107c98b84611cc3565b60058e8d8d60405160200161144d93929190615697565b50613b46565b6040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a8690613a98907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c908b908b906004016159df565b60006040518083038186803b158015613ab057600080fd5b505af4158015613ac4573d6000803e3d6000fd5b505050506000613add8688611c6190919063ffffffff16565b90508015613b4457613b427f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008584610873670de0b6b3a76400006107c98b84611cc3565b505b505b613b4f47611bfd565b50505050505050565b60008080613b668482614548565b9250613b73846014614614565b9050613b80846017614548565b91509193909250565b6000613b9f85613b9a8686866146d0565b614726565b95945050505050565b60018160ff166009811115613bb957fe5b6009811115613bc457fe5b1415613d3f57600082806020019051810190613be09190614dd2565b8051602082015160608301516040516331a0854360e11b815293945073__$561e80098325da493156966792c25e3551$__936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60006040518083038186803b158015613c8057600080fd5b505af4158015613c94573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb9150613ce69088908890600401615ace565b602060405180830381600087803b158015613d0057600080fd5b505af1158015613d14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d389190614b35565b5050610edd565b60028160ff166009811115613d5057fe5b6009811115613d5b57fe5b1415613f4d57600082806020019051810190613d779190614dd2565b9050600081602001511180613d90575060008160400151115b15613eff57805160208201516040808401519051639f70f9e560e01b815260009373__$561e80098325da493156966792c25e3551$__93639f70f9e593613e21937f0000000000000000000000000000000000000000000000000000000000000000937f000000000000000000000000000000000000000000000000000000000000000093909290916004016159df565b60206040518083038186803b158015613e3957600080fd5b505af4158015613e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7191906153f7565b8251909150613efd57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613eca9030908c9086906004016156c1565b600060405180830381600087803b158015613ee457600080fd5b505af1158015613ef8573d6000803e3d6000fd5b505050505b505b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ce69088908890600401615ace565b60038160ff166009811115613f5e57fe5b6009811115613f6957fe5b14156140155760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b602060405180830381600087803b158015613fd757600080fd5b505af1158015613feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400f9190614b35565b50610edd565b60048160ff16600981111561402657fe5b600981111561403157fe5b14156140855760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b60058160ff16600981111561409657fe5b60098111156140a157fe5b1415614145576000828060200190518101906140bd9190615287565b8051602082015160408084015190516331a0854360e11b815293945073__$561e80098325da493156966792c25e3551$__936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60098160ff16600981111561415657fe5b600981111561416157fe5b1415610edd5760405163a9059cbb60e01b81526001600160a01b0386169063a9059cbb906141959087908790600401615ace565b602060405180830381600087803b1580156141af57600080fd5b505af11580156141c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4f9190614b35565b6000806000806141fa8560000151613b58565b919450925090506001600160a01b038084169083161060008061421e858786614749565b6001600160a01b031663128acb088b856142378f614787565b6000036001600160a01b038e161561424f578d614275565b8761426e5773fffd8963efd1fc6a506488495d951d5263988d25614275565b6401000276a45b8d6040516020016142869190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142b5959493929190615a10565b6040805180830381600087803b1580156142ce57600080fd5b505af11580156142e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143069190614ba0565b915091506000808461431c578284600003614322565b83836000035b915091508a6001600160a01b031660001415614344578c811461434457600080fd5b509b9a5050505050505050505050565b6000806000806143678560000151613b58565b919450925090506001600160a01b038083169084161060008061438b868686614749565b6001600160a01b031663128acb088b856143a48f614787565b6001600160a01b038e16156143b9578d6143df565b876143d85773fffd8963efd1fc6a506488495d951d5263988d256143df565b6401000276a45b8d6040516020016143f09190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161441f959493929190615a10565b6040805180830381600087803b15801561443857600080fd5b505af115801561444c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144709190614ba0565b915091508261447f5781614481565b805b6000039b9a5050505050505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c64ea4a846040518263ffffffff1660e01b81526004016144e29190615dbd565b60806040518083038186803b1580156144fa57600080fd5b505afa15801561450e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453291906152dc565b606001516001600160801b03169150505b919050565b6000818260140110156145a2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b81601401835110156145fb576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b60008182600301101561466e576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156146c7576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6146d8614899565b826001600160a01b0316846001600160a01b031611156146f6579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614732838361479d565b9050336001600160a01b03821614611cbd57600080fd5b600061477f7f000000000000000000000000000000000000000000000000000000000000000061477a8686866146d0565b61479d565b949350505050565b6000600160ff1b821061479957600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b0316106147c557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561454381615f16565b805161454381615f16565b803561454381615f2b565b805161454381615f2b565b600082601f8301126148f5578081fd5b813561490861490382615ec4565b615ea0565b81815284602083860101111561491c578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614946578081fd5b815161495461490382615ec4565b818152846020838601011115614968578283fd5b61477f826020830160208701615ee6565b803561454381615f46565b805161454381615f46565b600061016082840312156149a1578081fd5b50919050565b600060c082840312156149a1578081fd5b600060c082840312156149c9578081fd5b60405160c0810181811067ffffffffffffffff821117156149e657fe5b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151614a2881615f6a565b60a0919091015292915050565b803561454381615f55565b805161454381615f55565b803561454381615f6a565b805161454381615f6a565b803561454381615f7b565b805161454381615f7b565b600060208284031215614a88578081fd5b8135611d1c81615f16565b600060208284031215614aa4578081fd5b8151611d1c81615f16565b60008060008060808587031215614ac4578283fd5b8435614acf81615f16565b93506020850135614adf81615f16565b925060408501359150606085013567ffffffffffffffff811115614b01578182fd5b614b0d878288016148e5565b91505092959194509250565b600060208284031215614b2a578081fd5b8135611d1c81615f2b565b600060208284031215614b46578081fd5b8151611d1c81615f2b565b600060208284031215614b62578081fd5b813567ffffffffffffffff811115614b78578182fd5b61477f848285016148e5565b600060208284031215614b95578081fd5b8135611d1c81615f46565b60008060408385031215614bb2578182fd5b505080516020909101519092909150565b60008060008060608587031215614bd8578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614bfd578384fd5b818701915087601f830112614c10578384fd5b813581811115614c1e578485fd5b886020828501011115614c2f578485fd5b95989497505060200194505050565b60006101608284031215614c50578081fd5b611d1c838361498f565b600060608284031215614c6b578081fd5b6040516060810181811067ffffffffffffffff82111715614c8857fe5b604052825181526020830151614c9d81615f55565b60208201526040830151614cb081615f55565b60408201529392505050565b600060a08284031215614ccd578081fd5b60405160a0810181811067ffffffffffffffff82111715614cea57fe5b80604052508251815260208301516020820152604083015160408201526060830151614d1581615f55565b60608201526080830151614d2881615f55565b60808201529392505050565b600060208284031215614d45578081fd5b6040516020810181811067ffffffffffffffff82111715614d6257fe5b6040529151825250919050565b600060408284031215614d80578081fd5b6040516040810181811067ffffffffffffffff82111715614d9d57fe5b604052825181526020928301519281019290925250919050565b600060c08284031215614dc8578081fd5b611d1c83836149a7565b600060c08284031215614de3578081fd5b611d1c83836149b8565b600060208284031215614dfe578081fd5b815167ffffffffffffffff80821115614e15578283fd5b9083019060a08286031215614e28578283fd5b60405160a081018181108382111715614e3d57fe5b604052614e49836148c4565b8152614e57602084016148c4565b602082015260408301516040820152614e7260608401614a6c565b6060820152608083015182811115614e88578485fd5b614e9487828601614936565b60808301525095945050505050565b600061018082840312156149a1578081fd5b6000610180808385031215614ec8578182fd5b614ed181615ea0565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100614f2b818501614a40565b90820152610120614f3d848201614a40565b90820152610140614f4f848201614a56565b90820152610160614f618482016148da565b908201529392505050565b6000610160808385031215614f7f578182fd5b614f8881615ea0565b9050614f93836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120614ff5818501614984565b90820152610140614f61848201614984565b600060a08284031215615018578081fd5b60405160a0810181811067ffffffffffffffff8211171561503557fe5b604052825161504381615f16565b8152602083015161505381615f16565b8060208301525060408301516040820152606083015160608201526080830151614d2881615f6a565b600060e0828403121561508d578081fd5b60405160e0810181811067ffffffffffffffff821117156150aa57fe5b6040526150b6836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600061014082840312156149a1578081fd5b6000610140808385031215615123578182fd5b61512c81615ea0565b9050615137836148c4565b8152615145602084016148c4565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100615194818501614984565b90820152610120614f61848201614984565b60006101a082840312156149a1578081fd5b600060e082840312156149a1578081fd5b6000602082840312156151da578081fd5b813567ffffffffffffffff808211156151f1578283fd5b9083019060808286031215615204578283fd5b60405160808101818110838211171561521957fe5b60405282358281111561522a578485fd5b615236878286016148e5565b825250615245602084016148b9565b602082015261525660408401614a61565b604082015260608301358281111561526c578485fd5b615278878286016148e5565b60608301525095945050505050565b600060608284031215615298578081fd5b6040516060810181811067ffffffffffffffff821117156152b557fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000608082840312156152ed578081fd5b6040516080810181811067ffffffffffffffff8211171561530a57fe5b604052825161531881615f16565b8152602083015163ffffffff81168114615330578283fd5b602082015260408301516bffffffffffffffffffffffff81168114615353578283fd5b604082015261536460608401614a40565b60608201529392505050565b600060608284031215615381578081fd5b6040516060810181811067ffffffffffffffff8211171561539e57fe5b806040525082518152602083015160208201526040830151614cb081615f2b565b6000602082840312156153d0578081fd5b8135611d1c81615f55565b6000602082840312156153ec578081fd5b8135611d1c81615f6a565b600060208284031215615408578081fd5b5051919050565b60008060408385031215615421578182fd5b8251915060208084015167ffffffffffffffff80821115615440578384fd5b818601915086601f830112615453578384fd5b81518181111561545f57fe5b61546c8485830201615ea0565b81815284810190848601875b848110156154f557815187016040818e03601f1901121561549757898afd5b6040516040810181811089821117156154ac57fe5b604052818a01516154bc81615f39565b81526040820151888111156154cf578b8cfd5b6154dd8f8c83860101614936565b828c0152508552509287019290870190600101615478565b50979a909950975050505050505050565b6000806000806060858703121561551b578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615540578384fd5b818701915087601f830112615553578384fd5b813581811115615561578485fd5b8860208083028501011115614c2f578485fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526155c9816020860160208601615ee6565b601f01601f19169290920160200192915050565b60020b9052565b803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a081013561561e81615f6a565b62ffffff811660a0840152505050565b6001600160801b03169052565b62ffffff169052565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286811660208301528581166040830152841660608201526101e0810161577660808301615771866148b9565b615574565b615782602085016148b9565b61578f60a0840182615574565b50604084013560c0830152606084013560e083015261010060808501358184015261012060a08601358185015260c086013561014085015260e08601356101608501526157dd828701614979565b91506157ed6101808501836155dd565b6157f8818701614979565b9150506158096101a08401826155dd565b50611e566101c0830184615581565b6001600160a01b038781168252868116602083015285811660408301528416606082015282516101e0820190615852906080840190615574565b602084015161586460a0840182615574565b50604084015160c0830152606084015160e08301526080840151610100818185015260a08601519150610120828186015260c087015161014086015260e08701516101608601528187015192506158bf6101808601846155dd565b860151915061580990506101a08401826155dd565b60006101a0820190506001600160a01b03808a1683528089166020840152808816604084015280871660608401528560808401528085511660a084015250602084015160c0830152604084015160e08301526060840151610100830152608084015161012083015260a084015161014083015260c0840151610160830152615960610180830184615581565b98975050505050505050565b6000610120820190506001600160a01b0380861683528085166020840152808451166040840152506020830151606083015260408301516080830152606083015160a0830152608083015160c083015260a083015160020b60e083015260c083015160020b610100830152949350505050565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152611e5660a08301846155b1565b60006001600160a01b03841682526040602083015261477f60408301846155b1565b600060e0820190506001600160a01b038516825283516020830152602084015160408301526040840151606083015260608401516001600160801b0380821660808501528060808701511660a0850152505082151560c0830152949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396909616865260208601949094526040850192909252600290810b60608501520b6080830152151560a082015260c00190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b918252602082015260400190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b60c08101611cbd82846155e4565b6000602082526001600160a01b03808451166020840152806020850151166040840152506040830151606083015260ff6060840151166080830152608083015160a08084015261477f60c08401826155b1565b600061018082019050823582526020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100615c62818501614a35565b615c6e8285018261562e565b5050610120615c7e818501614a35565b615c8a8285018261562e565b5050610140615c9a818501614a4b565b615ca68285018261563b565b5050610160615cb68185016148cf565b615cc282850182615581565b505092915050565b6101608101615cdc82615771856148b9565b6020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100808401358184015250610120615d3c818501614979565b615d48828501826155dd565b5050610140615d58818501614979565b615cc2828501826155dd565b600060208252825160806020840152615d8060a08401826155b1565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f19848303016080850152613b9f82826155b1565b90815260200190565b6000604080830186845260208281860152818683526060860190506060828802870101925087855b88811015615e9157878503605f190183528135368b9003603e19018112615e13578788fd5b8a018035615e2081615f39565b60088110615e2a57fe5b86528085013536829003601e19018112615e42578889fd5b8101803567ffffffffffffffff811115615e5a57898afd5b803603831315615e6857898afd5b8887890152615e7c89890182898501615587565b97505050928401925090830190600101615dee565b50929998505050505050505050565b60405181810167ffffffffffffffff81118282101715615ebc57fe5b604052919050565b600067ffffffffffffffff821115615ed857fe5b50601f01601f191660200190565b60005b83811015615f01578181015183820152602001615ee9565b83811115615f10576000848401525b50505050565b6001600160a01b0381168114611c5e57600080fd5b8015158114611c5e57600080fd5b60088110611c5e57600080fd5b8060020b8114611c5e57600080fd5b6001600160801b0381168114611c5e57600080fd5b62ffffff81168114611c5e57600080fd5b60ff81168114611c5e57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220564c27264bc33c078d9c75afb2f26fb0c092712e686cacc101aaeee9df569b6e64736f6c63430007060033\",\n  \"libraries\": {\n    \"ControllerHelperUtil\": \"0xB53c2eE92A24B08521912e1687Bc8142a7E6a9EE\"\n  },\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\": {\n        \"details\": \"user should approve this contract for Uni NFT transfer\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.CloseShortWithUserNftParams struct\"\n        }\n      },\n      \"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"details\": \"sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\"\n        }\n      },\n      \"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"details\": \"flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.FlashSellLongWMintParams struct\"\n        }\n      },\n      \"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"details\": \"this function\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\"\n        }\n      },\n      \"onERC721Received(address,address,uint256,bytes)\": {\n        \"details\": \"accept erc721 from safeTransferFrom and safeMint after callback\",\n        \"returns\": {\n          \"_0\": \"returns received selector\"\n        }\n      },\n      \"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\": {\n        \"params\": {\n          \"_collateralToFlashloan\": \"collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\",\n          \"_params\": \"array of ControllerHelperDataType.RebalanceLpInVaultParams structs\",\n          \"_vaultId\": \"vault ID\"\n        }\n      },\n      \"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\": {\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\"\n        }\n      },\n      \"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\": {\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.ReduceLiquidityAndSellParams struct\"\n        }\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"params\": {\n          \"_data\": \"callback data encoded as SwapCallbackData struct\",\n          \"amount0Delta\": \"amount of token0\",\n          \"amount1Delta\": \"amount of token1\"\n        }\n      },\n      \"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.MintAndLpParams struct\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\": {\n        \"notice\": \"close short position with user Uniswap v3 LP NFT\"\n      },\n      \"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"notice\": \"FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\"\n      },\n      \"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"notice\": \"sell long wPowerPerp and flashswap mint short position\"\n      },\n      \"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"notice\": \"flash close position and buy long squeeth\"\n      },\n      \"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\": {\n        \"notice\": \"Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\"\n      },\n      \"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\": {\n        \"notice\": \"Rebalance LP nft through trading\"\n      },\n      \"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\": {\n        \"notice\": \"sell all LP wPowerPerp amounts to WETH and send back to user\"\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"notice\": \"uniswap swap callback function for flashswap\"\n      },\n      \"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"notice\": \"mint WPowerPerp and LP into Uniswap v3 pool\"\n      }\n    },\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/ControllerHelperUtil.json",
    "content": "{\n  \"address\": \"0xB53c2eE92A24B08521912e1687Bc8142a7E6a9EE\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wPowerPerpPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_collateralToLp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"_lowerTick\",\n          \"type\": \"int24\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"_upperTick\",\n          \"type\": \"int24\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_isWethToken0\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getAmountsToLp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x5c1260bffa8cb4db9aee68e84371f4a87b986d71e4461a00b90cf44d976aebd1\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0xB53c2eE92A24B08521912e1687Bc8142a7E6a9EE\",\n    \"transactionIndex\": 189,\n    \"gasUsed\": \"2335067\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x0d3472fb167969637c53bd133377a3a68d708da5443898cab05e9c4cc97c9c7b\",\n    \"transactionHash\": \"0x5c1260bffa8cb4db9aee68e84371f4a87b986d71e4461a00b90cf44d976aebd1\",\n    \"logs\": [],\n    \"blockNumber\": 14922913,\n    \"cumulativeGasUsed\": \"14575374\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"fc32ed9e00a9017e491333926bef5473\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_collateralToLp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"_lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"_upperTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_isWethToken0\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getAmountsToLp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_collateralToWithdraw\\\":\\\"amount of collateral to withdraw\\\",\\\"_controller\\\":\\\"controller address\\\",\\\"_vaultId\\\":\\\"vault Id\\\",\\\"_wPowerPerpToBurn\\\":\\\"amount of wPowerPerp to burn\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"checkClosedLp(address,address,address,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\",\\\"_liquidityPercentage\\\":\\\"percentage of liquidity that was closed from total amount\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_tokenId\\\":\\\"Uni LP NFT id\\\",\\\"_user\\\":\\\"user address\\\",\\\"_vaultId\\\":\\\"vault ID\\\"}},\\\"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\\\":{\\\"params\\\":{\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_params\\\":\\\"ControllerHelperDataType.CloseUniLpParams struct \\\"},\\\"returns\\\":{\\\"_0\\\":\\\"withdrawn wPowerPerp and WETH amounts\\\"}},\\\"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\\\":{\\\"params\\\":{\\\"_collateralToLp\\\":\\\"amount of ETH collateral to LP\\\",\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_lowerTick\\\":\\\"LP position lower tick\\\",\\\"_upperTick\\\":\\\"LP position upper tick\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to LP\\\",\\\"_wPowerPerpPool\\\":\\\"wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"exact amount0 and amount1 to be LPed\\\"}},\\\"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\",\\\"_increaseLiquidityParam\\\":\\\"ControllerHelperDataType.IncreaseLpLiquidityParams struct\\\",\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_vaultId\\\":\\\"vault Id\\\"}},\\\"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\\\":{\\\"params\\\":{\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_params\\\":\\\"ControllerHelperDataType.LpWPowerPerpPoolParams struct\\\",\\\"_wPowerPerpPool\\\":\\\"wPowerpPerp pool address in Uni v3\\\"}},\\\"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"wPowerPerp controller address\\\",\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_mintAndLpParams\\\":\\\"ControllerHelperDataType.MintAndLpParams struct\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"_vaultId and tokenId\\\"}},\\\"mintDepositInVault(address,address,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_collateralToDeposit\\\":\\\"amount of collateral to deposit\\\",\\\"_controller\\\":\\\"controller address\\\",\\\"_vaultId\\\":\\\"vault Id\\\",\\\"_wPowerPerpToMint\\\":\\\"amount of wPowerPerp to mint\\\",\\\"_weth\\\":\\\"WETH address\\\"}},\\\"sendBack(address,address)\\\":{\\\"params\\\":{\\\"_wPowerPerp\\\":\\\"wPowerPerp address\\\",\\\"_weth\\\":\\\"WETH address\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"burn wPowerPerp or just withdraw collateral from vault (or both)\\\"},\\\"checkClosedLp(address,address,address,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\\"},\\\"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\\\":{\\\"notice\\\":\\\"fully or partially close Uni v3 LP\\\"},\\\"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\\\":{\\\"notice\\\":\\\"get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\\"},\\\"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\\\":{\\\"notice\\\":\\\"increase liquidityin Uni v3 position\\\"},\\\"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\\\":{\\\"notice\\\":\\\"LP into Uniswap V3 pool\\\"},\\\"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\\\":{\\\"notice\\\":\\\"minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\\"},\\\"mintDepositInVault(address,address,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"mint wPowerPerp in vault\\\"},\\\"sendBack(address,address)\\\":{\\\"notice\\\":\\\"send ETH and wPowerPerp\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/periphery/lib/ControllerHelperUtil.sol\\\":\\\"ControllerHelperUtil\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/lib/ControllerHelperDataType.sol\\\":{\\\"content\\\":\\\"pragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperDataType {\\\\n    using SafeMath for uint256;\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum CALLBACK_SOURCE {\\\\n        FLASH_W_MINT,\\\\n        FLASH_W_BURN,\\\\n        FLASH_SELL_LONG_W_MINT,\\\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\\\n        GENERAL_SWAP\\\\n    }\\\\n\\\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\\\n    enum RebalanceVaultNftType {\\\\n        IncreaseLpLiquidity,\\\\n        DecreaseLpLiquidity,\\\\n        DepositIntoVault,\\\\n        WithdrawFromVault,\\\\n        MintNewLp,\\\\n        generalSwap,\\\\n        CollectFees, \\\\n        DepositExistingNft\\\\n    }\\\\n    \\\\n    /// @dev params for flashswapWBurnBuyLong()\\\\n    struct FlashswapWBurnBuyLongParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\\\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev params for flashswapSellLongWMint()\\\\n    struct FlashSellLongWMintParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\\\n    struct SwapExactoutEthWPowerPerpData {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\\\n    }\\\\n\\\\n    /// @dev params for CloseShortWithUserNft()\\\\n    struct CloseShortWithUserNftParams {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity;  // liquidity amount in LP \\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;      // uniswap pool fee\\\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for wMintLp()\\\\n    struct MintAndLpParams {\\\\n        address recipient;  // recipient address\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 collateralToLp; // collateral amount to LP\\\\n        uint256 amount0Min; // minimum amount to LP of asset0\\\\n        uint256 amount1Min; // minimum amount to LP of asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for flashloanWMintDepositNft()\\\\n    struct FlashloanWMintLpDepositNftParams {\\\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\\\n        uint256 vaultId; // vault ID (could be zero)\\\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\\\n        uint256 amount0Min; // minimum amount of token0 to LP\\\\n        uint256 amount1Min; // minimum amount of token1 to LP\\\\n        int24 lowerTick; // range lower tick to LP in\\\\n        int24 upperTick; // range upper tick to LP in\\\\n    }\\\\n\\\\n    /// @dev params for flashloanCloseVaultLpNft()\\\\n    struct FlashloanCloseVaultLpNftParam {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity; // amount of liquidity in LP position\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for _closeUniLp() \\\\n    struct CloseUniLpParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\\\n    }\\\\n\\\\n    /// @dev params for sellAll()\\\\n    struct ReduceLiquidityAndSellParams {\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpWithoutVault()\\\\n    struct RebalanceLpWithoutVaultParams {\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\\\n        uint256 wethAmountDesired;  // WETH amount to LP\\\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\\\n    struct LpWPowerPerpPoolParams {\\\\n        address recipient;  // recipient address\\\\n        uint256 amount0Desired; // amount desired to LP for asset0\\\\n        uint256 amount1Desired; // amount desired to LP for asset1\\\\n        uint256 amount0Min; // amount min to LP for asset0\\\\n        uint256 amount1Min; // amount min to LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpInVault()\\\\n    struct RebalanceLpInVaultParams {\\\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\\\n        bytes data;\\\\n    }\\\\n\\\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\\\n    struct IncreaseLpLiquidityParams {\\\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 wethAmountToLp; // WETH amount to LP\\\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for decrease liquidity in LP position\\\\n    struct DecreaseLpLiquidityParams {  \\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for minting into vault\\\\n    struct DepositIntoVaultParams {\\\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\\\n    }\\\\n\\\\n    /// @dev struct for withdrawing from vault\\\\n    struct withdrawFromVaultParams {  \\\\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\\\n    }\\\\n\\\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\\\n    struct GeneralSwapParams {\\\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\\\n        uint256 amountIn; // amount to swap in\\\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\\\n    struct CollectFeesParams {\\\\n        uint256 tokenId;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\\\n    struct DepositExistingNftParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x04a47d47c3e0a1ec4e834f9aa466960200084fbdee47f0f513990b2c4708b02a\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/ControllerHelperUtil.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ControllerHelperDataType} from \\\\\\\"./ControllerHelperDataType.sol\\\\\\\";\\\\nimport {LiquidityAmounts} from \\\\\\\"./LiquidityAmounts.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"../../libs/TickMathExternal.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperUtil {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /**\\\\n     * @notice fully or partially close Uni v3 LP\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return withdrawn wPowerPerp and WETH amounts\\\\n     */\\\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\\\n            .DecreaseLiquidityParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\\\n                amount0Min: _params.amount0Min,\\\\n                amount1Min: _params.amount1Min,\\\\n                deadline: block.timestamp\\\\n            });\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\\\n\\\\n        uint256 wethAmount;\\\\n        uint256 _wPowerPerpAmount;\\\\n        (_isWethToken0)\\\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n                INonfungiblePositionManager.CollectParams({\\\\n                    tokenId: _params.tokenId,\\\\n                    recipient: address(this),\\\\n                    amount0Max: type(uint128).max,\\\\n                    amount1Max: type(uint128).max\\\\n                })\\\\n            )\\\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n            INonfungiblePositionManager.CollectParams({\\\\n                tokenId: _params.tokenId,\\\\n                recipient: address(this),\\\\n                amount0Max: type(uint128).max,\\\\n                amount1Max: type(uint128).max\\\\n            })\\\\n        );\\\\n\\\\n        return (_wPowerPerpAmount, wethAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\\\n     * @param _collateralToLp amount of ETH collateral to LP\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\\\n     * @param _lowerTick LP position lower tick\\\\n     * @param _upperTick LP position upper tick\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return exact amount0 and amount1 to be LPed\\\\n     */\\\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\\\n        uint256 amount0Desired; \\\\n        uint256 amount1Desired;\\\\n\\\\n        {\\\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\\\n        }\\\\n        \\\\n        return (amount0Desired, amount1Desired);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\\\n     * @param _controller wPowerPerp controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return _vaultId and tokenId\\\\n     */\\\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\\\n\\\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\\\n                \\\\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\\\n                _mintAndLpParams.vaultId,\\\\n                amountToMint,\\\\n                0\\\\n            );\\\\n        }\\\\n        // LP amount0Desired and amount1Desired in Uni v3\\\\n        uint256 uniTokenId = lpWPowerPerpPool(\\\\n            _nonfungiblePositionManager,\\\\n            _mintAndLpParams.wPowerPerpPool,\\\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\\\n                recipient: _mintAndLpParams.recipient,\\\\n                amount0Desired: amount0Desired,\\\\n                amount1Desired: amount1Desired,\\\\n                amount0Min: _mintAndLpParams.amount0Min,\\\\n                amount1Min: _mintAndLpParams.amount1Min,\\\\n                lowerTick: _mintAndLpParams.lowerTick,\\\\n                upperTick: _mintAndLpParams.upperTick\\\\n            })\\\\n        );\\\\n        return (_vaultId, uniTokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice increase liquidityin Uni v3 position\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault Id\\\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     */\\\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\\\n            (\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                int24 tickLower,\\\\n                int24 tickUpper,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                \\\\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\\\n\\\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n\\\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\\\n                    _vaultId,\\\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\\\n                    0\\\\n                );\\\\n            }\\\\n        }\\\\n\\\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\\\n            tokenId: _increaseLiquidityParam.tokenId,\\\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\\\n            deadline: block.timestamp\\\\n        });\\\\n\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp in vault\\\\n     * @param _controller controller address\\\\n     * @param _weth WETH address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\\\n     * @param _collateralToDeposit amount of collateral to deposit\\\\n     */\\\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\\\n\\\\n        uint256 vaultId = _vaultId;\\\\n        if (_wPowerPerpToMint > 0) {\\\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\\\n                _vaultId,\\\\n                _wPowerPerpToMint,\\\\n                0\\\\n            );\\\\n        } else {\\\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\\\n        }\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\\\n     * @param _controller controller address\\\\n     * @param _weth weth address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     */\\\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\\\n        IController(_controller).burnWPowerPerpAmount(\\\\n            _vaultId,\\\\n            _wPowerPerpToBurn,\\\\n            _collateralToWithdraw\\\\n        );\\\\n\\\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice LP into Uniswap V3 pool\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\\\n     */\\\\n    function lpWPowerPerpPool(\\\\n        address _nonfungiblePositionManager,\\\\n        address _wPowerPerpPool,\\\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\\\n    ) public returns (uint256) {\\\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\\\n            tickLower: int24(_params.lowerTick),\\\\n            tickUpper: int24(_params.upperTick),\\\\n            amount0Desired: _params.amount0Desired,\\\\n            amount1Desired: _params.amount1Desired,\\\\n            amount0Min: _params.amount0Min,\\\\n            amount1Min: _params.amount1Min,\\\\n            recipient: _params.recipient,\\\\n            deadline: block.timestamp\\\\n        });\\\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\\\n            mintParams\\\\n        );\\\\n        return tokenId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\\\n     * @param _user user address\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault ID\\\\n     * @param _tokenId Uni LP NFT id\\\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\\\n     */\\\\n    function checkClosedLp(\\\\n        address _user,\\\\n        address _controller,\\\\n        address _nonfungiblePositionManager,\\\\n        uint256 _vaultId,\\\\n        uint256 _tokenId,\\\\n        uint256 _liquidityPercentage\\\\n    ) public {\\\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\\\n                address(this),\\\\n                _user,\\\\n                _tokenId\\\\n            );\\\\n        } else {\\\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice send ETH and wPowerPerp\\\\n     * @param _weth WETH address\\\\n     * @param _wPowerPerp wPowerPerp address\\\\n     */\\\\n    function sendBack(address _weth, address _wPowerPerp) public {\\\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n        if (wPowerPerpBalance > 0) {\\\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x51c6185083d747a36ee8543219c0e7a326b866c0bdc113e82956cd4e226f7ba3\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/LiquidityAmounts.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"../../libs/SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\n\\\\n\\\\n/// @title Liquidity amount functions\\\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\\\nlibrary LiquidityAmounts {\\\\n    /// @notice Downcasts uint256 to uint128\\\\n    /// @param x The uint258 to be downcasted\\\\n    /// @return y The passed value, downcasted to uint128\\\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\\\n        require((y = uint128(x)) == x);\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount0 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount0(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount1 The amount1 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount1(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount of token0 being sent in\\\\n    /// @param amount1 The amount of token1 being sent in\\\\n    /// @return liquidity The maximum amount of liquidity received\\\\n    function getLiquidityForAmounts(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\\\n\\\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\\\n        } else {\\\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\\\n        }\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    function getAmount0ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            FullMath.mulDiv(\\\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\\\n                sqrtRatioBX96 - sqrtRatioAX96,\\\\n                sqrtRatioBX96\\\\n            ) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmount1ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n\\\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmountsForLiquidity(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\\\n        } else {\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        }\\\\n    }\\\\n\\\\n    function getAmountsFromLiquidity(        \\\\n        uint160 sqrtRatioX96,\\\\n        int24 currentTick,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (currentTick < tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else if (currentTick < tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtRatioX96,\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                sqrtRatioX96,\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            }\\\\n    \\\\n    }\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb4b0f464529a43f3ca7a9d6afc5976902c0a004649bdf3239ca77469d26b7cf2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x61294e610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100ad5760003560e01c80638e6940f011610080578063aee2533b11610065578063aee2533b14610198578063b573fa8b146101b8578063ec147e56146101cb576100ad565b80638e6940f0146101345780639f70f9e51461016b576100ad565b8063392f2708146100b257806351764a5e146100d457806363410a86146100f45780637a04dbd714610114575b600080fd5b8180156100be57600080fd5b506100d26100cd366004612153565b6101eb565b005b8180156100e057600080fd5b506100d26100ef366004611f91565b6102d4565b81801561010057600080fd5b506100d261010f366004612282565b6104c1565b81801561012057600080fd5b506100d261012f366004612056565b61056e565b81801561014057600080fd5b5061015461014f366004611fc9565b610865565b60405161016292919061284f565b60405180910390f35b81801561017757600080fd5b5061018b610186366004612282565b610b78565b6040516101629190612846565b8180156101a457600080fd5b5061018b6101b33660046121b7565b610cdf565b6101546101c636600461237c565b610f52565b8180156101d757600080fd5b506101546101e63660046122d2565b6111bd565b8215806101ff575080670de0b6b3a7640000145b1561026b57604051632142170760e11b81526001600160a01b038516906342842e0e906102349030908a90879060040161269c565b600060405180830381600087803b15801561024e57600080fd5b505af1158015610262573d6000803e3d6000fd5b505050506102cc565b6040516348dc69a560e11b81526001600160a01b038616906391b8d34a90610299908690869060040161284f565b600060405180830381600087803b1580156102b357600080fd5b505af11580156102c7573d6000803e3d6000fd5b505050505b505050505050565b6040516370a0823160e01b81526001600160a01b03831690632e1a7d4d9082906370a082319061030890309060040161266f565b60206040518083038186803b15801561032057600080fd5b505afa158015610334573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035891906124fb565b6040518263ffffffff1660e01b81526004016103749190612846565b600060405180830381600087803b15801561038e57600080fd5b505af11580156103a2573d6000803e3d6000fd5b506103b39250339150479050611424565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906103e290309060040161266f565b60206040518083038186803b1580156103fa57600080fd5b505afa15801561040e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043291906124fb565b905080156104bc5760405163a9059cbb60e01b81526001600160a01b0383169063a9059cbb906104689033908590600401612683565b602060405180830381600087803b15801561048257600080fd5b505af1158015610496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ba91906123dd565b505b505050565b604051638632cb0360e01b81526001600160a01b03861690638632cb03906104f19086908690869060040161285d565b600060405180830381600087803b15801561050b57600080fd5b505af115801561051f573d6000803e3d6000fd5b50505050600081111561056757836001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156102b357600080fd5b5050505050565b60408201511561077557600080876001600160a01b03166399fbab8885602001516040518263ffffffff1660e01b81526004016105ab9190612846565b6101806040518083038186803b1580156105c457600080fd5b505afa1580156105d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fc9190612573565b5050505050965096505050505050600080610623888760800151886040015187878a610f52565b9150915084610633578181610636565b80825b6080880152604080880191909152516370a0823160e01b81526000906001600160a01b038b16906370a082319061067190309060040161266f565b60206040518083038186803b15801561068957600080fd5b505afa15801561069d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c191906124fb565b9050866040015181101561076f578b6001600160a01b0316633946791888606001518a6106fb858c6040015161150990919063ffffffff16565b60006040518563ffffffff1660e01b815260040161071b9392919061285d565b6020604051808303818588803b15801561073457600080fd5b505af1158015610748573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061076d91906124fb565b505b50505050505b60006040518060c00160405280846020015181526020018361079b5784604001516107a1565b84608001515b8152602001836107b55784608001516107bb565b84604001515b81526020018460a0015181526020018460c001518152602001428152509050866001600160a01b031663219f5d17826040518263ffffffff1660e01b81526004016108069190612754565b606060405180830381600087803b15801561082057600080fd5b505af1158015610834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108589190612415565b5050505050505050505050565b600080846001600160a01b0316632e1a7d4d85608001356040518263ffffffff1660e01b81526004016108989190612846565b600060405180830381600087803b1580156108b257600080fd5b505af11580156108c6573d6000803e3d6000fd5b505050506000806109178660200160208101906108e39190611f59565b60a088013560608901356108ff6101208b016101008c016123f9565b6109116101408c016101208d016123f9565b8a610f52565b9092509050604086013560008661092e5783610930565b825b9050808a6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161095f919061266f565b60206040518083038186803b15801561097757600080fd5b505afa15801561098b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109af91906124fb565b1015610acd576040516370a0823160e01b8152610a3c906001600160a01b038c16906370a08231906109e590309060040161266f565b60206040518083038186803b1580156109fd57600080fd5b505afa158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3591906124fb565b8290611509565b90508b6001600160a01b0316633946791889608001358a604001358460006040518563ffffffff1660e01b8152600401610a789392919061285d565b6020604051808303818588803b158015610a9157600080fd5b505af1158015610aa5573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610aca91906124fb565b91505b6000610b648c610ae360408c0160208d01611f59565b6040805160e0810190915280610afc60208f018f611f59565b6001600160a01b031681526020018981526020018881526020018d60c0013581526020018d60e0013581526020018d610100016020810190610b3e91906123f9565b60020b81526020018d610120016020810190610b5a91906123f9565b60020b9052610cdf565b929d929c50919a5050505050505050505050565b60008115610bdf57604051632e1a7d4d60e01b81526001600160a01b03861690632e1a7d4d90610bac908590600401612846565b600060405180830381600087803b158015610bc657600080fd5b505af1158015610bda573d6000803e3d6000fd5b505050505b838315610c7257604051630728cf2360e31b81526001600160a01b038816906339467918908590610c19908990899060009060040161285d565b6020604051808303818588803b158015610c3257600080fd5b505af1158015610c46573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610c6b91906124fb565b9050610cd3565b60405163b6b55f2560e01b81526001600160a01b0388169063b6b55f25908590610ca0908990600401612846565b6000604051808303818588803b158015610cb957600080fd5b505af1158015610ccd573d6000803e3d6000fd5b50505050505b90505b95945050505050565b600080604051806101600160405280856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d2757600080fd5b505afa158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f9190611f75565b6001600160a01b03168152602001856001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610da657600080fd5b505afa158015610dba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dde9190611f75565b6001600160a01b03168152602001856001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610e2557600080fd5b505afa158015610e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5d91906124e1565b62ffffff1681526020018460a0015160020b81526020018460c0015160020b81526020018460200151815260200184604001518152602001846060015181526020018460800151815260200184600001516001600160a01b031681526020014281525090506000856001600160a01b03166388316456836040518263ffffffff1660e01b8152600401610ef09190612798565b608060405180830381600087803b158015610f0a57600080fd5b505af1158015610f1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f429190612513565b50919450505050505b9392505050565b60008060008060008a6001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610f9357600080fd5b505afa158015610fa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcb919061244b565b50505050509150506000738f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D63986cfba3836040518263ffffffff1660e01b815260040161100c91906126c0565b60206040518083038186803b15801561102457600080fd5b505af4158015611038573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105c9190611f75565b90506000738f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D63986cfba38b6040518263ffffffff1660e01b815260040161109791906126c0565b60206040518083038186803b1580156110af57600080fd5b505af41580156110c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e79190611f75565b90506000738f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D63986cfba38b6040518263ffffffff1660e01b815260040161112291906126c0565b60206040518083038186803b15801561113a57600080fd5b505af415801561114e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111729190611f75565b905088611180578b8d611183565b8c8c5b909650945060006111978484848a8a61156b565b90506111a684868e8e85611623565b909950975050505050505050965096945050505050565b60008060006040518060a0016040528086600001518152602001611204670de0b6b3a76400006111fe89604001518a6020015161196490919063ffffffff16565b906119bd565b6001600160801b0316815260200186606001516001600160801b0316815260200186608001516001600160801b03168152602001428152509050856001600160a01b0316630c49ccbe826040518263ffffffff1660e01b815260040161126a9190612711565b6040805180830381600087803b15801561128357600080fd5b505af1158015611297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bb9190612550565b5050600080856113705760408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f78659161131691906004016126ce565b6040805180830381600087803b15801561132f57600080fd5b505af1158015611343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113679190612550565b92509050611418565b60408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f7865916113c191906004016126ce565b6040805180830381600087803b1580156113da57600080fd5b505af11580156113ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114129190612550565b90925090505b97909650945050505050565b80471015611479576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146114c4576040519150601f19603f3d011682016040523d82523d6000602084013e6114c9565b606091505b50509050806104bc5760405162461bcd60e51b815260040180806020018281038252603a8152602001806128be603a913960400191505060405180910390fd5b600082821115611560576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000836001600160a01b0316856001600160a01b0316111561158b579293925b846001600160a01b0316866001600160a01b0316116115b6576115af858585611a24565b9050610cd6565b836001600160a01b0316866001600160a01b031610156116185760006115dd878686611a24565b905060006115ec878986611a90565b9050806001600160801b0316826001600160801b03161061160d578061160f565b815b92505050610cd6565b610cd3858584611a90565b6000808460020b8660020b12156116fc5773b9127F2e97F6816DCd7b85d8617B7AcFe5E15419632c32d4b661165787611ade565b61166087611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b1580156116c957600080fd5b505af41580156116dd573d6000803e3d6000fd5b505050506040513d60208110156116f357600080fd5b5051915061195a565b8360020b8660020b12156118965773b9127F2e97F6816DCd7b85d8617B7AcFe5E15419632c32d4b68861172e87611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561179757600080fd5b505af41580156117ab573d6000803e3d6000fd5b505050506040513d60208110156117c157600080fd5b5051915073b9127F2e97F6816DCd7b85d8617B7AcFe5E154196348a0c5bd6117e887611ade565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039283166004820152918b1660248301526001600160801b038716604483015260006064830152516084808301926020929190829003018186803b15801561186357600080fd5b505af4158015611877573d6000803e3d6000fd5b505050506040513d602081101561188d57600080fd5b5051905061195a565b73b9127F2e97F6816DCd7b85d8617B7AcFe5E154196348a0c5bd6118b987611ade565b6118c287611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561192b57600080fd5b505af415801561193f573d6000803e3d6000fd5b505050506040513d602081101561195557600080fd5b505190505b9550959350505050565b60008261197357506000611565565b8282028284828161198057fe5b0414610f4b5760405162461bcd60e51b81526004018080602001828103825260218152602001806128f86021913960400191505060405180910390fd5b6000808211611a13576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611a1c57fe5b049392505050565b6000826001600160a01b0316846001600160a01b03161115611a44579192915b6000611a70856001600160a01b0316856001600160a01b03166c01000000000000000000000000611e1d565b9050610cd6611a8b84838888036001600160a01b0316611e1d565b611ecc565b6000826001600160a01b0316846001600160a01b03161115611ab0579192915b611ad6611a8b836c010000000000000000000000008787036001600160a01b0316611e1d565b949350505050565b60008060008360020b12611af5578260020b611afd565b8260020b6000035b9050620d89e8811115611b3b576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216611b5c57700100000000000000000000000000000000611b6e565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615611ba2576ffff97272373d413259a46990580e213a0260801c5b6004821615611bc1576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615611be0576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615611bff576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615611c1e576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615611c3d576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615611c5c576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615611c7c576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615611c9c576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615611cbc576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615611cdc576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615611cfc576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615611d1c576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615611d3c576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615611d5c576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615611d7d576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615611d9d576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615611dbc576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615611dd9576b048a170391f7dc42444e8fa20260801c5b60008460020b1315611df4578060001981611df057fe5b0490505b640100000000810615611e08576001611e0b565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080611e535760008411611e4857600080fd5b508290049050610f4b565b808411611e5f57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b806001600160801b0381168114611ee257600080fd5b919050565b8035611ee281612873565b8051611ee281612873565b8035611ee28161288b565b8035611ee281612899565b8051611ee281612899565b8035611ee2816128a8565b8051611ee2816128a8565b805161ffff81168114611ee257600080fd5b805162ffffff81168114611ee257600080fd5b600060208284031215611f6a578081fd5b8135610f4b81612873565b600060208284031215611f86578081fd5b8151610f4b81612873565b60008060408385031215611fa3578081fd5b8235611fae81612873565b91506020830135611fbe81612873565b809150509250929050565b6000806000806000808688036101e0811215611fe3578283fd5b8735611fee81612873565b96506020880135611ffe81612873565b9550604088013561200e81612873565b9450606088013561201e81612873565b9350610140607f1982011215612032578283fd5b506080870191506101c08701356120488161288b565b809150509295509295509295565b60008060008060008060008789036101a0811215612072578182fd5b883561207d81612873565b9750602089013561208d81612873565b9650604089013561209d81612873565b955060608901356120ad81612873565b94506080890135935060e0609f19820112156120c7578182fd5b5060405160e0810181811067ffffffffffffffff821117156120e557fe5b6040526120f460a08a01611ee7565b815260c089810135602083015260e08a013560408301526101008a013560608301526101208a013560808301526101408a013560a08301526101608a01359082015291506121456101808901611efd565b905092959891949750929550565b60008060008060008060c0878903121561216b578384fd5b863561217681612873565b9550602087013561218681612873565b9450604087013561219681612873565b959894975094956060810135955060808101359460a0909101359350915050565b60008060008385036101208112156121cd578182fd5b84356121d881612873565b935060208501356121e881612873565b925060e0603f19820112156121fb578182fd5b5060405160e0810181811067ffffffffffffffff8211171561221957fe5b806040525061222a60408601611ee7565b8152606085013560208201526080850135604082015260a0850135606082015260c0850135608082015261226060e08601611f08565b60a08201526122726101008601611f08565b60c0820152809150509250925092565b600080600080600060a08688031215612299578283fd5b85356122a481612873565b945060208601356122b481612873565b94979496505050506040830135926060810135926080909101359150565b600080600083850360e08112156122e7578182fd5b84356122f281612873565b935060a0601f1982011215612305578182fd5b5060405160a0810181811067ffffffffffffffff8211171561232357fe5b806040525060208501358152604085013560208201526060850135604082015261234f60808601611f1e565b606082015261236060a08601611f1e565b6080820152915061237360c08501611efd565b90509250925092565b60008060008060008060c08789031215612394578384fd5b863561239f81612873565b9550602087013594506040870135935060608701356123bd81612899565b925060808701356123cd81612899565b915060a08701356120488161288b565b6000602082840312156123ee578081fd5b8151610f4b8161288b565b60006020828403121561240a578081fd5b8135610f4b81612899565b600080600060608486031215612429578081fd5b8351612434816128a8565b602085015160409095015190969495509392505050565b600080600080600080600060e0888a031215612465578081fd5b875161247081612873565b602089015190975061248181612899565b955061248f60408901611f34565b945061249d60608901611f34565b93506124ab60808901611f34565b925060a088015160ff811681146124c0578182fd5b60c08901519092506124d18161288b565b8091505092959891949750929550565b6000602082840312156124f2578081fd5b610f4b82611f46565b60006020828403121561250c578081fd5b5051919050565b60008060008060808587031215612528578182fd5b84519350602085015161253a816128a8565b6040860151606090960151949790965092505050565b60008060408385031215612562578182fd5b505080516020909101519092909150565b6000806000806000806000806000806000806101808d8f031215612595578586fd5b8c516bffffffffffffffffffffffff811681146125b0578687fd5b9b506125be60208e01611ef2565b9a506125cc60408e01611ef2565b99506125da60608e01611ef2565b98506125e860808e01611f46565b97506125f660a08e01611f13565b965061260460c08e01611f13565b955061261260e08e01611f29565b94506101008d015193506101208d015192506126316101408e01611f29565b91506126406101608e01611f29565b90509295989b509295989b509295989b565b6001600160a01b03169052565b60020b9052565b62ffffff169052565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60029190910b815260200190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6000610160820190506127ac828451612652565b60208301516127be6020840182612652565b5060408301516127d16040840182612666565b5060608301516127e4606084018261265f565b5060808301516127f7608084018261265f565b5060a083015160a083015260c083015160c083015260e083015160e08301526101008084015181840152506101208084015161283582850182612652565b505061014092830151919092015290565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b6001600160a01b038116811461288857600080fd5b50565b801515811461288857600080fd5b8060020b811461288857600080fd5b6001600160801b038116811461288857600080fdfe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220cfb89b72f5833964391283454a5a095d88e171c58035cad9299687278c762ec164736f6c63430007060033\",\n  \"deployedBytecode\": \"0x73000000000000000000000000000000000000000030146080604052600436106100ad5760003560e01c80638e6940f011610080578063aee2533b11610065578063aee2533b14610198578063b573fa8b146101b8578063ec147e56146101cb576100ad565b80638e6940f0146101345780639f70f9e51461016b576100ad565b8063392f2708146100b257806351764a5e146100d457806363410a86146100f45780637a04dbd714610114575b600080fd5b8180156100be57600080fd5b506100d26100cd366004612153565b6101eb565b005b8180156100e057600080fd5b506100d26100ef366004611f91565b6102d4565b81801561010057600080fd5b506100d261010f366004612282565b6104c1565b81801561012057600080fd5b506100d261012f366004612056565b61056e565b81801561014057600080fd5b5061015461014f366004611fc9565b610865565b60405161016292919061284f565b60405180910390f35b81801561017757600080fd5b5061018b610186366004612282565b610b78565b6040516101629190612846565b8180156101a457600080fd5b5061018b6101b33660046121b7565b610cdf565b6101546101c636600461237c565b610f52565b8180156101d757600080fd5b506101546101e63660046122d2565b6111bd565b8215806101ff575080670de0b6b3a7640000145b1561026b57604051632142170760e11b81526001600160a01b038516906342842e0e906102349030908a90879060040161269c565b600060405180830381600087803b15801561024e57600080fd5b505af1158015610262573d6000803e3d6000fd5b505050506102cc565b6040516348dc69a560e11b81526001600160a01b038616906391b8d34a90610299908690869060040161284f565b600060405180830381600087803b1580156102b357600080fd5b505af11580156102c7573d6000803e3d6000fd5b505050505b505050505050565b6040516370a0823160e01b81526001600160a01b03831690632e1a7d4d9082906370a082319061030890309060040161266f565b60206040518083038186803b15801561032057600080fd5b505afa158015610334573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035891906124fb565b6040518263ffffffff1660e01b81526004016103749190612846565b600060405180830381600087803b15801561038e57600080fd5b505af11580156103a2573d6000803e3d6000fd5b506103b39250339150479050611424565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906103e290309060040161266f565b60206040518083038186803b1580156103fa57600080fd5b505afa15801561040e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043291906124fb565b905080156104bc5760405163a9059cbb60e01b81526001600160a01b0383169063a9059cbb906104689033908590600401612683565b602060405180830381600087803b15801561048257600080fd5b505af1158015610496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ba91906123dd565b505b505050565b604051638632cb0360e01b81526001600160a01b03861690638632cb03906104f19086908690869060040161285d565b600060405180830381600087803b15801561050b57600080fd5b505af115801561051f573d6000803e3d6000fd5b50505050600081111561056757836001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156102b357600080fd5b5050505050565b60408201511561077557600080876001600160a01b03166399fbab8885602001516040518263ffffffff1660e01b81526004016105ab9190612846565b6101806040518083038186803b1580156105c457600080fd5b505afa1580156105d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fc9190612573565b5050505050965096505050505050600080610623888760800151886040015187878a610f52565b9150915084610633578181610636565b80825b6080880152604080880191909152516370a0823160e01b81526000906001600160a01b038b16906370a082319061067190309060040161266f565b60206040518083038186803b15801561068957600080fd5b505afa15801561069d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c191906124fb565b9050866040015181101561076f578b6001600160a01b0316633946791888606001518a6106fb858c6040015161150990919063ffffffff16565b60006040518563ffffffff1660e01b815260040161071b9392919061285d565b6020604051808303818588803b15801561073457600080fd5b505af1158015610748573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061076d91906124fb565b505b50505050505b60006040518060c00160405280846020015181526020018361079b5784604001516107a1565b84608001515b8152602001836107b55784608001516107bb565b84604001515b81526020018460a0015181526020018460c001518152602001428152509050866001600160a01b031663219f5d17826040518263ffffffff1660e01b81526004016108069190612754565b606060405180830381600087803b15801561082057600080fd5b505af1158015610834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108589190612415565b5050505050505050505050565b600080846001600160a01b0316632e1a7d4d85608001356040518263ffffffff1660e01b81526004016108989190612846565b600060405180830381600087803b1580156108b257600080fd5b505af11580156108c6573d6000803e3d6000fd5b505050506000806109178660200160208101906108e39190611f59565b60a088013560608901356108ff6101208b016101008c016123f9565b6109116101408c016101208d016123f9565b8a610f52565b9092509050604086013560008661092e5783610930565b825b9050808a6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161095f919061266f565b60206040518083038186803b15801561097757600080fd5b505afa15801561098b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109af91906124fb565b1015610acd576040516370a0823160e01b8152610a3c906001600160a01b038c16906370a08231906109e590309060040161266f565b60206040518083038186803b1580156109fd57600080fd5b505afa158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3591906124fb565b8290611509565b90508b6001600160a01b0316633946791889608001358a604001358460006040518563ffffffff1660e01b8152600401610a789392919061285d565b6020604051808303818588803b158015610a9157600080fd5b505af1158015610aa5573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610aca91906124fb565b91505b6000610b648c610ae360408c0160208d01611f59565b6040805160e0810190915280610afc60208f018f611f59565b6001600160a01b031681526020018981526020018881526020018d60c0013581526020018d60e0013581526020018d610100016020810190610b3e91906123f9565b60020b81526020018d610120016020810190610b5a91906123f9565b60020b9052610cdf565b929d929c50919a5050505050505050505050565b60008115610bdf57604051632e1a7d4d60e01b81526001600160a01b03861690632e1a7d4d90610bac908590600401612846565b600060405180830381600087803b158015610bc657600080fd5b505af1158015610bda573d6000803e3d6000fd5b505050505b838315610c7257604051630728cf2360e31b81526001600160a01b038816906339467918908590610c19908990899060009060040161285d565b6020604051808303818588803b158015610c3257600080fd5b505af1158015610c46573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610c6b91906124fb565b9050610cd3565b60405163b6b55f2560e01b81526001600160a01b0388169063b6b55f25908590610ca0908990600401612846565b6000604051808303818588803b158015610cb957600080fd5b505af1158015610ccd573d6000803e3d6000fd5b50505050505b90505b95945050505050565b600080604051806101600160405280856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d2757600080fd5b505afa158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f9190611f75565b6001600160a01b03168152602001856001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610da657600080fd5b505afa158015610dba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dde9190611f75565b6001600160a01b03168152602001856001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610e2557600080fd5b505afa158015610e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5d91906124e1565b62ffffff1681526020018460a0015160020b81526020018460c0015160020b81526020018460200151815260200184604001518152602001846060015181526020018460800151815260200184600001516001600160a01b031681526020014281525090506000856001600160a01b03166388316456836040518263ffffffff1660e01b8152600401610ef09190612798565b608060405180830381600087803b158015610f0a57600080fd5b505af1158015610f1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f429190612513565b50919450505050505b9392505050565b60008060008060008a6001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610f9357600080fd5b505afa158015610fa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcb919061244b565b5050505050915050600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba3836040518263ffffffff1660e01b815260040161100c91906126c0565b60206040518083038186803b15801561102457600080fd5b505af4158015611038573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105c9190611f75565b9050600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba38b6040518263ffffffff1660e01b815260040161109791906126c0565b60206040518083038186803b1580156110af57600080fd5b505af41580156110c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e79190611f75565b9050600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba38b6040518263ffffffff1660e01b815260040161112291906126c0565b60206040518083038186803b15801561113a57600080fd5b505af415801561114e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111729190611f75565b905088611180578b8d611183565b8c8c5b909650945060006111978484848a8a61156b565b90506111a684868e8e85611623565b909950975050505050505050965096945050505050565b60008060006040518060a0016040528086600001518152602001611204670de0b6b3a76400006111fe89604001518a6020015161196490919063ffffffff16565b906119bd565b6001600160801b0316815260200186606001516001600160801b0316815260200186608001516001600160801b03168152602001428152509050856001600160a01b0316630c49ccbe826040518263ffffffff1660e01b815260040161126a9190612711565b6040805180830381600087803b15801561128357600080fd5b505af1158015611297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bb9190612550565b5050600080856113705760408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f78659161131691906004016126ce565b6040805180830381600087803b15801561132f57600080fd5b505af1158015611343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113679190612550565b92509050611418565b60408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f7865916113c191906004016126ce565b6040805180830381600087803b1580156113da57600080fd5b505af11580156113ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114129190612550565b90925090505b97909650945050505050565b80471015611479576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146114c4576040519150601f19603f3d011682016040523d82523d6000602084013e6114c9565b606091505b50509050806104bc5760405162461bcd60e51b815260040180806020018281038252603a8152602001806128be603a913960400191505060405180910390fd5b600082821115611560576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000836001600160a01b0316856001600160a01b0316111561158b579293925b846001600160a01b0316866001600160a01b0316116115b6576115af858585611a24565b9050610cd6565b836001600160a01b0316866001600160a01b031610156116185760006115dd878686611a24565b905060006115ec878986611a90565b9050806001600160801b0316826001600160801b03161061160d578061160f565b815b92505050610cd6565b610cd3858584611a90565b6000808460020b8660020b12156116fc5773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b661165787611ade565b61166087611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b1580156116c957600080fd5b505af41580156116dd573d6000803e3d6000fd5b505050506040513d60208110156116f357600080fd5b5051915061195a565b8360020b8660020b12156118965773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b68861172e87611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561179757600080fd5b505af41580156117ab573d6000803e3d6000fd5b505050506040513d60208110156117c157600080fd5b5051915073__$a98c5df505b68ab2f483703658c95acb30$__6348a0c5bd6117e887611ade565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039283166004820152918b1660248301526001600160801b038716604483015260006064830152516084808301926020929190829003018186803b15801561186357600080fd5b505af4158015611877573d6000803e3d6000fd5b505050506040513d602081101561188d57600080fd5b5051905061195a565b73__$a98c5df505b68ab2f483703658c95acb30$__6348a0c5bd6118b987611ade565b6118c287611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561192b57600080fd5b505af415801561193f573d6000803e3d6000fd5b505050506040513d602081101561195557600080fd5b505190505b9550959350505050565b60008261197357506000611565565b8282028284828161198057fe5b0414610f4b5760405162461bcd60e51b81526004018080602001828103825260218152602001806128f86021913960400191505060405180910390fd5b6000808211611a13576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611a1c57fe5b049392505050565b6000826001600160a01b0316846001600160a01b03161115611a44579192915b6000611a70856001600160a01b0316856001600160a01b03166c01000000000000000000000000611e1d565b9050610cd6611a8b84838888036001600160a01b0316611e1d565b611ecc565b6000826001600160a01b0316846001600160a01b03161115611ab0579192915b611ad6611a8b836c010000000000000000000000008787036001600160a01b0316611e1d565b949350505050565b60008060008360020b12611af5578260020b611afd565b8260020b6000035b9050620d89e8811115611b3b576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216611b5c57700100000000000000000000000000000000611b6e565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615611ba2576ffff97272373d413259a46990580e213a0260801c5b6004821615611bc1576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615611be0576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615611bff576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615611c1e576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615611c3d576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615611c5c576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615611c7c576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615611c9c576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615611cbc576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615611cdc576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615611cfc576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615611d1c576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615611d3c576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615611d5c576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615611d7d576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615611d9d576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615611dbc576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615611dd9576b048a170391f7dc42444e8fa20260801c5b60008460020b1315611df4578060001981611df057fe5b0490505b640100000000810615611e08576001611e0b565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080611e535760008411611e4857600080fd5b508290049050610f4b565b808411611e5f57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b806001600160801b0381168114611ee257600080fd5b919050565b8035611ee281612873565b8051611ee281612873565b8035611ee28161288b565b8035611ee281612899565b8051611ee281612899565b8035611ee2816128a8565b8051611ee2816128a8565b805161ffff81168114611ee257600080fd5b805162ffffff81168114611ee257600080fd5b600060208284031215611f6a578081fd5b8135610f4b81612873565b600060208284031215611f86578081fd5b8151610f4b81612873565b60008060408385031215611fa3578081fd5b8235611fae81612873565b91506020830135611fbe81612873565b809150509250929050565b6000806000806000808688036101e0811215611fe3578283fd5b8735611fee81612873565b96506020880135611ffe81612873565b9550604088013561200e81612873565b9450606088013561201e81612873565b9350610140607f1982011215612032578283fd5b506080870191506101c08701356120488161288b565b809150509295509295509295565b60008060008060008060008789036101a0811215612072578182fd5b883561207d81612873565b9750602089013561208d81612873565b9650604089013561209d81612873565b955060608901356120ad81612873565b94506080890135935060e0609f19820112156120c7578182fd5b5060405160e0810181811067ffffffffffffffff821117156120e557fe5b6040526120f460a08a01611ee7565b815260c089810135602083015260e08a013560408301526101008a013560608301526101208a013560808301526101408a013560a08301526101608a01359082015291506121456101808901611efd565b905092959891949750929550565b60008060008060008060c0878903121561216b578384fd5b863561217681612873565b9550602087013561218681612873565b9450604087013561219681612873565b959894975094956060810135955060808101359460a0909101359350915050565b60008060008385036101208112156121cd578182fd5b84356121d881612873565b935060208501356121e881612873565b925060e0603f19820112156121fb578182fd5b5060405160e0810181811067ffffffffffffffff8211171561221957fe5b806040525061222a60408601611ee7565b8152606085013560208201526080850135604082015260a0850135606082015260c0850135608082015261226060e08601611f08565b60a08201526122726101008601611f08565b60c0820152809150509250925092565b600080600080600060a08688031215612299578283fd5b85356122a481612873565b945060208601356122b481612873565b94979496505050506040830135926060810135926080909101359150565b600080600083850360e08112156122e7578182fd5b84356122f281612873565b935060a0601f1982011215612305578182fd5b5060405160a0810181811067ffffffffffffffff8211171561232357fe5b806040525060208501358152604085013560208201526060850135604082015261234f60808601611f1e565b606082015261236060a08601611f1e565b6080820152915061237360c08501611efd565b90509250925092565b60008060008060008060c08789031215612394578384fd5b863561239f81612873565b9550602087013594506040870135935060608701356123bd81612899565b925060808701356123cd81612899565b915060a08701356120488161288b565b6000602082840312156123ee578081fd5b8151610f4b8161288b565b60006020828403121561240a578081fd5b8135610f4b81612899565b600080600060608486031215612429578081fd5b8351612434816128a8565b602085015160409095015190969495509392505050565b600080600080600080600060e0888a031215612465578081fd5b875161247081612873565b602089015190975061248181612899565b955061248f60408901611f34565b945061249d60608901611f34565b93506124ab60808901611f34565b925060a088015160ff811681146124c0578182fd5b60c08901519092506124d18161288b565b8091505092959891949750929550565b6000602082840312156124f2578081fd5b610f4b82611f46565b60006020828403121561250c578081fd5b5051919050565b60008060008060808587031215612528578182fd5b84519350602085015161253a816128a8565b6040860151606090960151949790965092505050565b60008060408385031215612562578182fd5b505080516020909101519092909150565b6000806000806000806000806000806000806101808d8f031215612595578586fd5b8c516bffffffffffffffffffffffff811681146125b0578687fd5b9b506125be60208e01611ef2565b9a506125cc60408e01611ef2565b99506125da60608e01611ef2565b98506125e860808e01611f46565b97506125f660a08e01611f13565b965061260460c08e01611f13565b955061261260e08e01611f29565b94506101008d015193506101208d015192506126316101408e01611f29565b91506126406101608e01611f29565b90509295989b509295989b509295989b565b6001600160a01b03169052565b60020b9052565b62ffffff169052565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60029190910b815260200190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6000610160820190506127ac828451612652565b60208301516127be6020840182612652565b5060408301516127d16040840182612666565b5060608301516127e4606084018261265f565b5060808301516127f7608084018261265f565b5060a083015160a083015260c083015160c083015260e083015160e08301526101008084015181840152506101208084015161283582850182612652565b505061014092830151919092015290565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b6001600160a01b038116811461288857600080fd5b50565b801515811461288857600080fd5b8060020b811461288857600080fd5b6001600160801b038116811461288857600080fdfe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220cfb89b72f5833964391283454a5a095d88e171c58035cad9299687278c762ec164736f6c63430007060033\",\n  \"libraries\": {\n    \"TickMathExternal\": \"0x8f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D\",\n    \"SqrtPriceMathPartial\": \"0xb9127F2e97F6816DCd7b85d8617B7AcFe5E15419\"\n  },\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_collateralToWithdraw\": \"amount of collateral to withdraw\",\n          \"_controller\": \"controller address\",\n          \"_vaultId\": \"vault Id\",\n          \"_wPowerPerpToBurn\": \"amount of wPowerPerp to burn\",\n          \"_weth\": \"weth address\"\n        }\n      },\n      \"checkClosedLp(address,address,address,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_controller\": \"controller address\",\n          \"_liquidityPercentage\": \"percentage of liquidity that was closed from total amount\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_tokenId\": \"Uni LP NFT id\",\n          \"_user\": \"user address\",\n          \"_vaultId\": \"vault ID\"\n        }\n      },\n      \"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\": {\n        \"params\": {\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_params\": \"ControllerHelperDataType.CloseUniLpParams struct \"\n        },\n        \"returns\": {\n          \"_0\": \"withdrawn wPowerPerp and WETH amounts\"\n        }\n      },\n      \"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\": {\n        \"params\": {\n          \"_collateralToLp\": \"amount of ETH collateral to LP\",\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_lowerTick\": \"LP position lower tick\",\n          \"_upperTick\": \"LP position upper tick\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to LP\",\n          \"_wPowerPerpPool\": \"wPowerPerp Uni v3 pool (oSQTH/ETH pool)\"\n        },\n        \"returns\": {\n          \"_0\": \"exact amount0 and amount1 to be LPed\"\n        }\n      },\n      \"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\": {\n        \"params\": {\n          \"_controller\": \"controller address\",\n          \"_increaseLiquidityParam\": \"ControllerHelperDataType.IncreaseLpLiquidityParams struct\",\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_vaultId\": \"vault Id\"\n        }\n      },\n      \"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\": {\n        \"params\": {\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_params\": \"ControllerHelperDataType.LpWPowerPerpPoolParams struct\",\n          \"_wPowerPerpPool\": \"wPowerpPerp pool address in Uni v3\"\n        }\n      },\n      \"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\": {\n        \"params\": {\n          \"_controller\": \"wPowerPerp controller address\",\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_mintAndLpParams\": \"ControllerHelperDataType.MintAndLpParams struct\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\"\n        },\n        \"returns\": {\n          \"_0\": \"_vaultId and tokenId\"\n        }\n      },\n      \"mintDepositInVault(address,address,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_collateralToDeposit\": \"amount of collateral to deposit\",\n          \"_controller\": \"controller address\",\n          \"_vaultId\": \"vault Id\",\n          \"_wPowerPerpToMint\": \"amount of wPowerPerp to mint\",\n          \"_weth\": \"WETH address\"\n        }\n      },\n      \"sendBack(address,address)\": {\n        \"params\": {\n          \"_wPowerPerp\": \"wPowerPerp address\",\n          \"_weth\": \"WETH address\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\": {\n        \"notice\": \"burn wPowerPerp or just withdraw collateral from vault (or both)\"\n      },\n      \"checkClosedLp(address,address,address,uint256,uint256,uint256)\": {\n        \"notice\": \"transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\"\n      },\n      \"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\": {\n        \"notice\": \"fully or partially close Uni v3 LP\"\n      },\n      \"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\": {\n        \"notice\": \"get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\"\n      },\n      \"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\": {\n        \"notice\": \"increase liquidityin Uni v3 position\"\n      },\n      \"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\": {\n        \"notice\": \"LP into Uniswap V3 pool\"\n      },\n      \"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\": {\n        \"notice\": \"minth amount of wPowerPerp and LP in weth/wPowerPerp pool\"\n      },\n      \"mintDepositInVault(address,address,uint256,uint256,uint256)\": {\n        \"notice\": \"mint wPowerPerp in vault\"\n      },\n      \"sendBack(address,address)\": {\n        \"notice\": \"send ETH and wPowerPerp\"\n      }\n    },\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/CrabHelper.json",
    "content": "{\n  \"address\": \"0x2F55e27E669F070dEf7B5771dB72f6B31A6d4df8\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_crab\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_swapRouter\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"depositedERC20\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"depositedAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"depositedEthAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"returnedEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDepositERC20\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawnERC20\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"withdrawnAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"withdrawnEthAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdrawERC20\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"crab\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToDeposit\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amountIn\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minEthToGet\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_erc20Fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_wPowerPerpFee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_tokenIn\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"flashDepositERC20\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxEthToPay\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_tokenOut\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minAmountOut\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_erc20Fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_wPowerPerpFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashWithdrawERC20\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"swapRouter\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract ISwapRouter\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x582ac5cda021ecbb192d220bb58e57eef87fc2b95cc69d10cf8887bd2d4e8a90\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xf60eb02594AbB75b2e0FA4b2aA28b0691D8db775\",\n    \"contractAddress\": \"0x2F55e27E669F070dEf7B5771dB72f6B31A6d4df8\",\n    \"transactionIndex\": 84,\n    \"gasUsed\": \"821234\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x4956b136e7f28c2736a3ea6f258165ede70c20ce6e0dd367ba583f2cbb77956a\",\n    \"transactionHash\": \"0x582ac5cda021ecbb192d220bb58e57eef87fc2b95cc69d10cf8887bd2d4e8a90\",\n    \"logs\": [],\n    \"blockNumber\": 15765940,\n    \"cumulativeGasUsed\": \"9883060\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x3B960E47784150F5a63777201ee2B15253D713e8\",\n    \"0xE592427A0AEce92De3Edee1F18E0157C05861564\"\n  ],\n  \"solcInputHash\": \"c53867cdbf46138ab42de1c7a1689875\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_crab\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_swapRouter\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositedERC20\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"depositedAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"depositedEthAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"returnedEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDepositERC20\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawnERC20\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"withdrawnAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"withdrawnEthAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdrawERC20\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"crab\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amountIn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minEthToGet\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_erc20Fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_wPowerPerpFee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_tokenIn\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"flashDepositERC20\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxEthToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minAmountOut\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_erc20Fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_wPowerPerpFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashWithdrawERC20\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"swapRouter\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract ISwapRouter\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"author\\\":\\\"Opyn team\\\",\\\"details\\\":\\\"CrabHelper contract\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"constructor\\\":{\\\"params\\\":{\\\"_crab\\\":\\\"address of crabV2 contract\\\",\\\"_swapRouter\\\":\\\"address of Uniswap swap router\\\"}},\\\"flashDepositERC20(uint256,uint256,uint256,uint24,uint24,address)\\\":{\\\"params\\\":{\\\"_amountIn\\\":\\\"amount of ERC20 token to swap for weth\\\",\\\"_erc20Fee\\\":\\\"pool fee for transfer ERC20/eth pool (3000 = 30bps)\\\",\\\"_ethToDeposit\\\":\\\"amount of ETH to deposit\\\",\\\"_minEthToGet\\\":\\\"min amount of ETH to receive in the swap\\\",\\\"_tokenIn\\\":\\\"ERC20 token to pay\\\",\\\"_wPowerPerpFee\\\":\\\"pool fee for wPowerPerp/eth pool (3000 = 30bps)\\\"}},\\\"flashWithdrawERC20(uint256,uint256,address,uint256,uint24,uint24)\\\":{\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of crab shares to withdraw\\\",\\\"_erc20Fee\\\":\\\"pool fee for transfer ERC20/eth pool (3000 = 30bps)\\\",\\\"_maxEthToPay\\\":\\\"max eth to pay in swap for wPowerPerp\\\",\\\"_minAmountOut\\\":\\\"min amount of ERC20 to receive\\\",\\\"_tokenOut\\\":\\\"ERC20 token to receive\\\",\\\"_wPowerPerpFee\\\":\\\"pool fee for wPowerPerp/eth pool (3000 = 30bps)\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"constructor\\\":{\\\"notice\\\":\\\"constructor\\\"},\\\"flashDepositERC20(uint256,uint256,uint256,uint24,uint24,address)\\\":{\\\"notice\\\":\\\"allows user to flash deposit into crab from an aribtrary ERC20\\\"},\\\"flashWithdrawERC20(uint256,uint256,address,uint256,uint24,uint24)\\\":{\\\"notice\\\":\\\"allows user to flash withdraw from crab to an aribtrary ERC20\\\"}},\\\"notice\\\":\\\"Contract for Crab helper functions\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/strategy/CrabHelper.sol\\\":\\\"CrabHelper\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\\\n\\\\n/// @title Router token swapping functionality\\\\n/// @notice Functions for swapping tokens via Uniswap V3\\\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\\\n    struct ExactInputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactInputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactOutputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\\\n\\\\n    struct ExactOutputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9bfaf1feb32814623e627ab70f2409760b15d95f1f9b058e2b3399a8bb732975\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/ICrabStrategyV2.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\ninterface ICrabStrategyV2 {\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\\\\n\\\\n    function flashWithdraw(\\\\n        uint256 _crabAmount,\\\\n        uint256 _maxEthToPay,\\\\n        uint24 _poolFee\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xabf84430d693a3a3ef9c04147da7c26f9698fdbb14abeab60a6ec1c8f24cbeab\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/strategy/CrabHelper.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {ICrabStrategyV2} from \\\\\\\"../interfaces/ICrabStrategyV2.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\nimport \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n\\\\nimport {StrategySwap} from \\\\\\\"./helper/StrategySwap.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev CrabHelper contract\\\\n * @notice Contract for Crab helper functions\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\\\n    using Address for address payable;\\\\n\\\\n    address public immutable crab;\\\\n    address public immutable weth;\\\\n\\\\n    event FlashDepositERC20(\\\\n        address indexed depositor,\\\\n        address depositedERC20,\\\\n        uint256 depositedAmount,\\\\n        uint256 depositedEthAmount,\\\\n        uint256 crabAmount,\\\\n        uint256 returnedEth\\\\n    );\\\\n\\\\n    event FlashWithdrawERC20(\\\\n        address indexed withdrawer,\\\\n        address withdrawnERC20,\\\\n        uint256 withdrawnAmount,\\\\n        uint256 withdrawnEthAmount,\\\\n        uint256 crabAmount\\\\n    );\\\\n\\\\n    /**\\\\n     * @notice constructor\\\\n     * @param _crab address of crabV2 contract\\\\n     * @param _swapRouter address of Uniswap swap router\\\\n     */\\\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\\\n        require(_crab != address(0), \\\\\\\"Invalid crab address\\\\\\\");\\\\n\\\\n        crab = _crab;\\\\n        weth = ICrabStrategyV2(_crab).weth();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\\\\n     * @param _ethToDeposit amount of ETH to deposit\\\\n     * @param _amountIn amount of ERC20 token to swap for weth\\\\n     * @param _minEthToGet min amount of ETH to receive in the swap\\\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\\\n     * @param _tokenIn ERC20 token to pay\\\\n     */\\\\n    function flashDepositERC20(\\\\n        uint256 _ethToDeposit,\\\\n        uint256 _amountIn,\\\\n        uint256 _minEthToGet,\\\\n        uint24 _erc20Fee,\\\\n        uint24 _wPowerPerpFee,\\\\n        address _tokenIn\\\\n    ) external nonReentrant {\\\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\\\\n\\\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\\\\n\\\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\\\n\\\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\\\n\\\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\\\n\\\\n        if (address(this).balance > 0) {\\\\n            payable(msg.sender).sendValue(address(this).balance);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\\\\n     * @param _crabAmount amount of crab shares to withdraw\\\\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\\\\n     * @param _tokenOut ERC20 token to receive\\\\n     * @param _minAmountOut min amount of ERC20 to receive\\\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\\\n     */\\\\n    function flashWithdrawERC20(\\\\n        uint256 _crabAmount,\\\\n        uint256 _maxEthToPay,\\\\n        address _tokenOut,\\\\n        uint256 _minAmountOut,\\\\n        uint24 _erc20Fee,\\\\n        uint24 _wPowerPerpFee\\\\n    ) external nonReentrant {\\\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\\\n\\\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\\\\n\\\\n        uint256 ethBalance = address(this).balance;\\\\n        IWETH9(weth).deposit{value: ethBalance}();\\\\n        uint256 tokenReceived = _swapExactInputSingle(\\\\n            weth,\\\\n            _tokenOut,\\\\n            address(this),\\\\n            msg.sender,\\\\n            ethBalance,\\\\n            _minAmountOut,\\\\n            _erc20Fee\\\\n        );\\\\n\\\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == crab, \\\\\\\"Cannot receive eth\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4775406a9d21e895ccc6b03f91263810aa4a000cf573cb8883f3500d826e911e\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/strategy/helper/StrategySwap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\\\\\";\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ncontract StrategySwap {\\\\n    ISwapRouter public immutable swapRouter;\\\\n\\\\n    constructor(address _swapRouter) {\\\\n        require(_swapRouter != address(0), \\\\\\\"invalid swap router address\\\\\\\");\\\\n        swapRouter = ISwapRouter(_swapRouter);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _from from which user we are selling\\\\n     * @param _to Recipient to get the tokens\\\\n     * @param _amountIn Exact amount to sell\\\\n     * @param _minAmountOut Minimum amount to be paid\\\\n     * @param _fee pool fee\\\\n     * @return amountOut The amount of WETH9 received.\\\\n     */\\\\n    function _swapExactInputSingle(\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        address _from,\\\\n        address _to,\\\\n        uint256 _amountIn,\\\\n        uint256 _minAmountOut,\\\\n        uint24 _fee\\\\n    ) internal returns (uint256 amountOut) {\\\\n        // _from must approve this contract\\\\n\\\\n        // Transfer the specified amount of tokenIn to this contract.\\\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\\\n\\\\n        // Approve the router to spend tokenIn.\\\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\\\n\\\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\\\n            tokenIn: _tokenIn,\\\\n            tokenOut: _tokenOut,\\\\n            fee: _fee,\\\\n            recipient: _to,\\\\n            deadline: block.timestamp,\\\\n            amountIn: _amountIn,\\\\n            amountOutMinimum: _minAmountOut,\\\\n            sqrtPriceLimitX96: 0\\\\n        });\\\\n\\\\n        // The call to `exactInputSingle` executes the swap.\\\\n        amountOut = swapRouter.exactInputSingle(params);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x06b92720043fa9d2999d0d895ee3d058999a297e97b592a5d61ad00d09051e24\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60e060405234801561001057600080fd5b50604051610f84380380610f848339818101604052604081101561003357600080fd5b508051602090910151806001600160a01b03811661006c5760405162461bcd60e51b815260040161006390610176565b60405180910390fd5b60601b6001600160601b03191660805260016000556001600160a01b0382166100dc576040805162461bcd60e51b815260206004820152601460248201527f496e76616c696420637261622061646472657373000000000000000000000000604482015290519081900360640190fd5b816001600160a01b031660a0816001600160a01b031660601b81525050816001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b15801561013257600080fd5b505afa158015610146573d6000803e3d6000fd5b505050506040513d602081101561015c57600080fd5b505160601b6001600160601b03191660c052506101ad9050565b6020808252601b908201527f696e76616c6964207377617020726f7574657220616464726573730000000000604082015260600190565b60805160601c60a05160601c60c05160601c610d6361022160003980606e52806103c3528061043c52806104cc528061057552806105bf52508060a052806102b4528061035d52806104f052806106a9528061073752806108505250806108e452806109b05280610a8a5250610d636000f3fe60806040526004361061005e5760003560e01c80634285512d116100435780634285512d146101a3578063bca4f628146101b8578063c31c9c071461021357610115565b806302c6600c1461011a5780633fc8cef31461017257610115565b3661011557336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100c25750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610113576040805162461bcd60e51b815260206004820152601260248201527f43616e6e6f742072656365697665206574680000000000000000000000000000604482015290519081900360640190fd5b005b600080fd5b34801561012657600080fd5b50610113600480360360c081101561013d57600080fd5b508035906020810135906001600160a01b036040820135169060608101359062ffffff608082013581169160a0013516610228565b34801561017e57600080fd5b506101876104ca565b604080516001600160a01b039092168252519081900360200190f35b3480156101af57600080fd5b506101876104ee565b3480156101c457600080fd5b50610113600480360360c08110156101db57600080fd5b50803590602081013590604081013590606081013562ffffff9081169160808101359091169060a001356001600160a01b0316610512565b34801561021f57600080fd5b506101876108e2565b60026000541415610280576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000908155604080516323b872dd60e01b81523360048201523060248201526044810189905290516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926323b872dd92606480820193602093909283900390910190829087803b1580156102fe57600080fd5b505af1158015610312573d6000803e3d6000fd5b505050506040513d602081101561032857600080fd5b505060408051630b52b7ff60e41b8152600481018890526024810187905262ffffff8316604482015290516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163b52b7ff091606480830192600092919082900301818387803b1580156103a457600080fd5b505af11580156103b8573d6000803e3d6000fd5b5050505060004790507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561041c57600080fd5b505af1158015610430573d6000803e3d6000fd5b505050505060006104667f0000000000000000000000000000000000000000000000000000000000000000873033868a8a610906565b604080516001600160a01b038916815260208101839052808201859052606081018b9052905191925033917f614f663be393aac8fd2c2993040a634f5b013b3d5f418cc59ad013e96eef53f99181900360800190a250506001600055505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6002600054141561056a576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260005561059e817f00000000000000000000000000000000000000000000000000000000000000003330898989610906565b50604080516370a0823160e01b815230600482015290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691632e1a7d4d9183916370a08231916024808301926020929190829003018186803b15801561060d57600080fd5b505afa158015610621573d6000803e3d6000fd5b505050506040513d602081101561063757600080fd5b5051604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925251602480830192600092919082900301818387803b15801561068f57600080fd5b505af11580156106a3573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fc5b73ff4788856040518463ffffffff1660e01b8152600401808381526020018262ffffff168152602001925050506000604051808303818588803b15801561071a57600080fd5b505af115801561072e573d6000803e3d6000fd5b505050505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156107a257600080fd5b505afa1580156107b6573d6000803e3d6000fd5b505050506040513d60208110156107cc57600080fd5b5051604080516001600160a01b0385168152602081018990528082018a905260608101839052476080820152905191925033917fc723e34ef5da33ff97116afe67fb4330d3189467330363a49eb6c9d2fd762a8c9181900360a00190a26040805163a9059cbb60e01b81523360048201526024810183905290516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb9160448083019260209291908290030181600087803b15801561089857600080fd5b505af11580156108ac573d6000803e3d6000fd5b505050506040513d60208110156108c257600080fd5b505047156108d4576108d43347610b1e565b505060016000555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516323b872dd60e01b81526000906001600160a01b038916906323b872dd9061093990899030908990600401610c47565b602060405180830381600087803b15801561095357600080fd5b505af1158015610967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098b9190610c08565b5060405163095ea7b360e01b81526001600160a01b0389169063095ea7b3906109da907f0000000000000000000000000000000000000000000000000000000000000000908890600401610c6b565b602060405180830381600087803b1580156109f457600080fd5b505af1158015610a08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2c9190610c08565b5060408051610100810182526001600160a01b03808b168252898116602083015262ffffff851682840152878116606083015242608083015260a0820187905260c08201869052600060e0830152915163414bf38960e01b815290917f0000000000000000000000000000000000000000000000000000000000000000169063414bf38990610abf908490600401610c84565b602060405180830381600087803b158015610ad957600080fd5b505af1158015610aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b119190610c2f565b9998505050505050505050565b80471015610b73576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610bbe576040519150601f19603f3d011682016040523d82523d6000602084013e610bc3565b606091505b5050905080610c035760405162461bcd60e51b815260040180806020018281038252603a815260200180610cf4603a913960400191505060405180910390fd5b505050565b600060208284031215610c19578081fd5b81518015158114610c28578182fd5b9392505050565b600060208284031215610c40578081fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6000610100820190506001600160a01b0380845116835280602085015116602084015262ffffff60408501511660408401528060608501511660608401526080840151608084015260a084015160a084015260c084015160c08401528060e08501511660e0840152509291505056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a2646970667358221220fcd43e471a4f1be2f1f1ccf4169e3d06484dd0cc15e022ffbfc5207a7fbbdf4664736f6c63430007060033\",\n  \"deployedBytecode\": \"0x60806040526004361061005e5760003560e01c80634285512d116100435780634285512d146101a3578063bca4f628146101b8578063c31c9c071461021357610115565b806302c6600c1461011a5780633fc8cef31461017257610115565b3661011557336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100c25750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b610113576040805162461bcd60e51b815260206004820152601260248201527f43616e6e6f742072656365697665206574680000000000000000000000000000604482015290519081900360640190fd5b005b600080fd5b34801561012657600080fd5b50610113600480360360c081101561013d57600080fd5b508035906020810135906001600160a01b036040820135169060608101359062ffffff608082013581169160a0013516610228565b34801561017e57600080fd5b506101876104ca565b604080516001600160a01b039092168252519081900360200190f35b3480156101af57600080fd5b506101876104ee565b3480156101c457600080fd5b50610113600480360360c08110156101db57600080fd5b50803590602081013590604081013590606081013562ffffff9081169160808101359091169060a001356001600160a01b0316610512565b34801561021f57600080fd5b506101876108e2565b60026000541415610280576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000908155604080516323b872dd60e01b81523360048201523060248201526044810189905290516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926323b872dd92606480820193602093909283900390910190829087803b1580156102fe57600080fd5b505af1158015610312573d6000803e3d6000fd5b505050506040513d602081101561032857600080fd5b505060408051630b52b7ff60e41b8152600481018890526024810187905262ffffff8316604482015290516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163b52b7ff091606480830192600092919082900301818387803b1580156103a457600080fd5b505af11580156103b8573d6000803e3d6000fd5b5050505060004790507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561041c57600080fd5b505af1158015610430573d6000803e3d6000fd5b505050505060006104667f0000000000000000000000000000000000000000000000000000000000000000873033868a8a610906565b604080516001600160a01b038916815260208101839052808201859052606081018b9052905191925033917f614f663be393aac8fd2c2993040a634f5b013b3d5f418cc59ad013e96eef53f99181900360800190a250506001600055505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6002600054141561056a576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260005561059e817f00000000000000000000000000000000000000000000000000000000000000003330898989610906565b50604080516370a0823160e01b815230600482015290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691632e1a7d4d9183916370a08231916024808301926020929190829003018186803b15801561060d57600080fd5b505afa158015610621573d6000803e3d6000fd5b505050506040513d602081101561063757600080fd5b5051604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925251602480830192600092919082900301818387803b15801561068f57600080fd5b505af11580156106a3573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fc5b73ff4788856040518463ffffffff1660e01b8152600401808381526020018262ffffff168152602001925050506000604051808303818588803b15801561071a57600080fd5b505af115801561072e573d6000803e3d6000fd5b505050505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156107a257600080fd5b505afa1580156107b6573d6000803e3d6000fd5b505050506040513d60208110156107cc57600080fd5b5051604080516001600160a01b0385168152602081018990528082018a905260608101839052476080820152905191925033917fc723e34ef5da33ff97116afe67fb4330d3189467330363a49eb6c9d2fd762a8c9181900360a00190a26040805163a9059cbb60e01b81523360048201526024810183905290516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb9160448083019260209291908290030181600087803b15801561089857600080fd5b505af11580156108ac573d6000803e3d6000fd5b505050506040513d60208110156108c257600080fd5b505047156108d4576108d43347610b1e565b505060016000555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516323b872dd60e01b81526000906001600160a01b038916906323b872dd9061093990899030908990600401610c47565b602060405180830381600087803b15801561095357600080fd5b505af1158015610967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098b9190610c08565b5060405163095ea7b360e01b81526001600160a01b0389169063095ea7b3906109da907f0000000000000000000000000000000000000000000000000000000000000000908890600401610c6b565b602060405180830381600087803b1580156109f457600080fd5b505af1158015610a08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2c9190610c08565b5060408051610100810182526001600160a01b03808b168252898116602083015262ffffff851682840152878116606083015242608083015260a0820187905260c08201869052600060e0830152915163414bf38960e01b815290917f0000000000000000000000000000000000000000000000000000000000000000169063414bf38990610abf908490600401610c84565b602060405180830381600087803b158015610ad957600080fd5b505af1158015610aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b119190610c2f565b9998505050505050505050565b80471015610b73576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610bbe576040519150601f19603f3d011682016040523d82523d6000602084013e610bc3565b606091505b5050905080610c035760405162461bcd60e51b815260040180806020018281038252603a815260200180610cf4603a913960400191505060405180910390fd5b505050565b600060208284031215610c19578081fd5b81518015158114610c28578182fd5b9392505050565b600060208284031215610c40578081fd5b5051919050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6000610100820190506001600160a01b0380845116835280602085015116602084015262ffffff60408501511660408401528060608501511660608401526080840151608084015260a084015160a084015260c084015160c08401528060e08501511660e0840152509291505056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a2646970667358221220fcd43e471a4f1be2f1f1ccf4169e3d06484dd0cc15e022ffbfc5207a7fbbdf4664736f6c63430007060033\",\n  \"devdoc\": {\n    \"author\": \"Opyn team\",\n    \"details\": \"CrabHelper contract\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"constructor\": {\n        \"params\": {\n          \"_crab\": \"address of crabV2 contract\",\n          \"_swapRouter\": \"address of Uniswap swap router\"\n        }\n      },\n      \"flashDepositERC20(uint256,uint256,uint256,uint24,uint24,address)\": {\n        \"params\": {\n          \"_amountIn\": \"amount of ERC20 token to swap for weth\",\n          \"_erc20Fee\": \"pool fee for transfer ERC20/eth pool (3000 = 30bps)\",\n          \"_ethToDeposit\": \"amount of ETH to deposit\",\n          \"_minEthToGet\": \"min amount of ETH to receive in the swap\",\n          \"_tokenIn\": \"ERC20 token to pay\",\n          \"_wPowerPerpFee\": \"pool fee for wPowerPerp/eth pool (3000 = 30bps)\"\n        }\n      },\n      \"flashWithdrawERC20(uint256,uint256,address,uint256,uint24,uint24)\": {\n        \"params\": {\n          \"_crabAmount\": \"amount of crab shares to withdraw\",\n          \"_erc20Fee\": \"pool fee for transfer ERC20/eth pool (3000 = 30bps)\",\n          \"_maxEthToPay\": \"max eth to pay in swap for wPowerPerp\",\n          \"_minAmountOut\": \"min amount of ERC20 to receive\",\n          \"_tokenOut\": \"ERC20 token to receive\",\n          \"_wPowerPerpFee\": \"pool fee for wPowerPerp/eth pool (3000 = 30bps)\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"constructor\": {\n        \"notice\": \"constructor\"\n      },\n      \"flashDepositERC20(uint256,uint256,uint256,uint24,uint24,address)\": {\n        \"notice\": \"allows user to flash deposit into crab from an aribtrary ERC20\"\n      },\n      \"flashWithdrawERC20(uint256,uint256,address,uint256,uint24,uint24)\": {\n        \"notice\": \"allows user to flash withdraw from crab to an aribtrary ERC20\"\n      }\n    },\n    \"notice\": \"Contract for Crab helper functions\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 4176,\n        \"contract\": \"contracts/strategy/CrabHelper.sol:CrabHelper\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_uint256\"\n      }\n    ],\n    \"types\": {\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/CrabMigration.json",
    "content": "{\n  \"address\": \"0xa1CAB67a4383312718a5799Eaa127906e9d4B19E\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address payable\",\n          \"name\": \"_crabV1\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_weth\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_eulerExec\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_dToken\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_eulerMainnet\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"user\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ClaimAndWithdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"user\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ClaimV2Shares\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"user\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabV1Amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"DepositV1Shares\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"user\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabV1Amount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabV2Amount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excessEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashMigrate\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"user\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabV1Amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawV1Shares\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_strategyCap\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"batchMigrate\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amountToWithdraw\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxEthToPay\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"claimAndWithdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"claimV2Shares\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"crabV1\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address payable\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"crabV2\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address payable\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"depositV1Shares\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"euler\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_v1Shares\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToFlashDeposit\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToBorrow\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_withdrawMaxEthToPay\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashMigrateAndWithdrawFromV1toV2\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_v1Shares\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToFlashDeposit\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashMigrateFromV1toV2\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_v1Shares\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"flashMigrationDetails\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isMigrated\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"encodedData\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onDeferredLiquidityCheck\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address payable\",\n          \"name\": \"_crabV2\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"setCrabV2\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"sharesDeposited\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdrawV1Shares\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x44e46c7181360ee9395a0650d5af7f27285ff35439f310ab742783c974cc934a\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0xa1CAB67a4383312718a5799Eaa127906e9d4B19E\",\n    \"transactionIndex\": 174,\n    \"gasUsed\": \"3091563\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000001000800000000000000000000000200000000000000000000002080000080000000000000000200000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000002400001000000000000000000004000000000000000000000000000020000000000000000000000800000000000000000000000000000000000000000000800000000000000000000000000040000000000000000000000000021000010200000000000400000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x5f61ce29f278ff5fb483088b873192af7e920ac557c097787f2f7bb3b0af325a\",\n    \"transactionHash\": \"0x44e46c7181360ee9395a0650d5af7f27285ff35439f310ab742783c974cc934a\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 174,\n        \"blockNumber\": 15134561,\n        \"transactionHash\": \"0x44e46c7181360ee9395a0650d5af7f27285ff35439f310ab742783c974cc934a\",\n        \"address\": \"0xa1CAB67a4383312718a5799Eaa127906e9d4B19E\",\n        \"topics\": [\n          \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000005599b4eaddd319e2f462b27fc8378b0bfad309ca\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 285,\n        \"blockHash\": \"0x5f61ce29f278ff5fb483088b873192af7e920ac557c097787f2f7bb3b0af325a\"\n      },\n      {\n        \"transactionIndex\": 174,\n        \"blockNumber\": 15134561,\n        \"transactionHash\": \"0x44e46c7181360ee9395a0650d5af7f27285ff35439f310ab742783c974cc934a\",\n        \"address\": \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x000000000000000000000000a1cab67a4383312718a5799eaa127906e9d4b19e\",\n          \"0x00000000000000000000000027182842e098f60e3d576794a5bffb0777e025d3\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 286,\n        \"blockHash\": \"0x5f61ce29f278ff5fb483088b873192af7e920ac557c097787f2f7bb3b0af325a\"\n      }\n    ],\n    \"blockNumber\": 15134561,\n    \"cumulativeGasUsed\": \"19161768\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0xf205ad80BB86ac92247638914265887A8BAa437D\",\n    \"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\",\n    \"0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80\",\n    \"0x62e28f054efc24b26A794F5C1249B6349454352C\",\n    \"0x27182842E098f60e3D576794A5bFFb0777E025d3\"\n  ],\n  \"solcInputHash\": \"30afee76cfee2d4cc1c12451e0258499\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address payable\\\",\\\"name\\\":\\\"_crabV1\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_weth\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_eulerExec\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_dToken\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_eulerMainnet\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"user\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ClaimAndWithdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"user\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ClaimV2Shares\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"user\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabV1Amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"DepositV1Shares\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"user\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabV1Amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabV2Amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excessEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashMigrate\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"user\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabV1Amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawV1Shares\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_strategyCap\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"batchMigrate\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amountToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxEthToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"claimAndWithdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"claimV2Shares\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"crabV1\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address payable\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"crabV2\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address payable\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"depositV1Shares\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"euler\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_v1Shares\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToFlashDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToBorrow\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawMaxEthToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashMigrateAndWithdrawFromV1toV2\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_v1Shares\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToFlashDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashMigrateFromV1toV2\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_v1Shares\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"flashMigrationDetails\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isMigrated\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"encodedData\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onDeferredLiquidityCheck\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address payable\\\",\\\"name\\\":\\\"_crabV2\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"setCrabV2\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"sharesDeposited\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdrawV1Shares\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"author\\\":\\\"Opyn team\\\",\\\"details\\\":\\\"CrabMigration contract\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"batchMigrate(uint256)\\\":{\\\"params\\\":{\\\"_strategyCap\\\":\\\"strategy cap in ETH\\\"}},\\\"claimAndWithdraw(uint256,uint256,uint24)\\\":{\\\"params\\\":{\\\"_amountToWithdraw\\\":\\\"V2 shares to claim\\\",\\\"_maxEthToPay\\\":\\\"maximum ETH to pay to buy back the owed wSqueeth debt\\\",\\\"_poolFee\\\":\\\"Uniswap pool fee for flash withdraw\\\"}},\\\"constructor\\\":{\\\"params\\\":{\\\"_crabV1\\\":\\\"address of crab V1\\\",\\\"_dToken\\\":\\\"address of euler liability token\\\",\\\"_eulerExec\\\":\\\"address of euler exec contract\\\",\\\"_eulerMainnet\\\":\\\"address of euler deployment on mainnet\\\",\\\"_weth\\\":\\\"address of weth\\\"}},\\\"depositV1Shares(uint256)\\\":{\\\"params\\\":{\\\"_amount\\\":\\\"amount of crabV1 shares to deposit\\\"}},\\\"flashMigrateAndWithdrawFromV1toV2(uint256,uint256,uint256,uint256,uint24)\\\":{\\\"params\\\":{\\\"_ethToBorrow\\\":\\\"amount to flash loan to deposit in crab v2\\\",\\\"_ethToFlashDeposit\\\":\\\"flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\\",\\\"_poolFee\\\":\\\"uniswap pool fee for the optional flash deposit into crab v2\\\",\\\"_v1Shares\\\":\\\"V1 shares to migrate\\\",\\\"_withdrawMaxEthToPay\\\":\\\"maximum ETH to pay to buy back the owed wSqueeth debt\\\"}},\\\"flashMigrateFromV1toV2(uint256,uint256,uint24)\\\":{\\\"params\\\":{\\\"_ethToFlashDeposit\\\":\\\"flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\\",\\\"_poolFee\\\":\\\"uniswap pool fee for flash deposit\\\",\\\"_v1Shares\\\":\\\"V1 shares to migrate\\\"}},\\\"flashMigrationDetails(uint256)\\\":{\\\"params\\\":{\\\"_v1Shares\\\":\\\"amount of crab V1 shares\\\"}},\\\"onDeferredLiquidityCheck(bytes)\\\":{\\\"params\\\":{\\\"encodedData\\\":\\\"callback data\\\"}},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"setCrabV2(address)\\\":{\\\"params\\\":{\\\"_crabV2\\\":\\\"address of crab V2\\\"}},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"withdrawV1Shares(uint256)\\\":{\\\"params\\\":{\\\"_amount\\\":\\\"amount of V1 shares to withdraw\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"batchMigrate(uint256)\\\":{\\\"notice\\\":\\\"the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes the V2 contract at the same collateral ratio as the V1 contract\\\"},\\\"claimAndWithdraw(uint256,uint256,uint24)\\\":{\\\"notice\\\":\\\"claim crab V2 shares and flash withdraw from crab V2\\\"},\\\"claimV2Shares()\\\":{\\\"notice\\\":\\\"claim crab V2 shares\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"migration constructor\\\"},\\\"depositV1Shares(uint256)\\\":{\\\"notice\\\":\\\"deposit crab V1 shares in the pool for migration\\\"},\\\"flashMigrateAndWithdrawFromV1toV2(uint256,uint256,uint256,uint256,uint24)\\\":{\\\"notice\\\":\\\"used to migrate from crab V1 to crab V2 when CR1 < CR2\\\"},\\\"flashMigrateFromV1toV2(uint256,uint256,uint24)\\\":{\\\"notice\\\":\\\"used to migrate from crab V1 to crab V2 when CR1 >= CR2\\\"},\\\"flashMigrationDetails(uint256)\\\":{\\\"notice\\\":\\\"view details of flash migration for specified amount of V1 shares\\\"},\\\"onDeferredLiquidityCheck(bytes)\\\":{\\\"notice\\\":\\\"Euler callback function\\\"},\\\"setCrabV2(address)\\\":{\\\"notice\\\":\\\"set the crabV2 address\\\"},\\\"withdrawV1Shares(uint256)\\\":{\\\"notice\\\":\\\"withdraw crab V1 shares in the pool before migration\\\"}},\\\"notice\\\":\\\"Contract for Migrating from Crab V1 to Crab V2\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/strategy/CrabMigration.sol\\\":\\\"CrabMigration\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\\\n *\\\\n * These functions can be used to verify that a message was signed by the holder\\\\n * of the private keys of a given address.\\\\n */\\\\nlibrary ECDSA {\\\\n    /**\\\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\\\n     * `signature`. This address can then be used for verification purposes.\\\\n     *\\\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\\\n     * this function rejects them by requiring the `s` value to be in the lower\\\\n     * half order, and the `v` value to be either 27 or 28.\\\\n     *\\\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\\\n     * verification to be secure: it is possible to craft signatures that\\\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\\\n     * this is by receiving a hash of the original message (which may otherwise\\\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\\\n     */\\\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\\\n        // Check the signature length\\\\n        if (signature.length != 65) {\\\\n            revert(\\\\\\\"ECDSA: invalid signature length\\\\\\\");\\\\n        }\\\\n\\\\n        // Divide the signature in r, s and v variables\\\\n        bytes32 r;\\\\n        bytes32 s;\\\\n        uint8 v;\\\\n\\\\n        // ecrecover takes the signature parameters, and the only way to get them\\\\n        // currently is to use assembly.\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly {\\\\n            r := mload(add(signature, 0x20))\\\\n            s := mload(add(signature, 0x40))\\\\n            v := byte(0, mload(add(signature, 0x60)))\\\\n        }\\\\n\\\\n        return recover(hash, v, r, s);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\\\n     * `r` and `s` signature fields separately.\\\\n     */\\\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\\\n        // the valid range for s in (281): 0 < s < secp256k1n \\\\u00f7 2 + 1, and for v in (282): v \\\\u2208 {27, 28}. Most\\\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\\\n        //\\\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\\\n        // these malleable signatures as well.\\\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\\\\\"ECDSA: invalid signature 's' value\\\\\\\");\\\\n        require(v == 27 || v == 28, \\\\\\\"ECDSA: invalid signature 'v' value\\\\\\\");\\\\n\\\\n        // If the signature is valid (and not malleable), return the signer address\\\\n        address signer = ecrecover(hash, v, r, s);\\\\n        require(signer != address(0), \\\\\\\"ECDSA: invalid signature\\\\\\\");\\\\n\\\\n        return signer;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\\\n     * replicates the behavior of the\\\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\\\n     * JSON-RPC method.\\\\n     *\\\\n     * See {recover}.\\\\n     */\\\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\\\n        // 32 is the length in bytes of hash,\\\\n        // enforced by the type signature above\\\\n        return keccak256(abi.encodePacked(\\\\\\\"\\\\\\\\x19Ethereum Signed Message:\\\\\\\\n32\\\\\\\", hash));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc80ce3fcc5e444a2c5bdb902fe4d4f4ecba04e9b416425697d00ae95c1955f82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/drafts/EIP712.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <0.8.0;\\\\n\\\\n/**\\\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\\\n *\\\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\\\n *\\\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\\\n * ({_hashTypedDataV4}).\\\\n *\\\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\\\n *\\\\n * NOTE: This contract implements the version of the encoding known as \\\\\\\"v4\\\\\\\", as implemented by the JSON RPC method\\\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\\\n *\\\\n * _Available since v3.4._\\\\n */\\\\nabstract contract EIP712 {\\\\n    /* solhint-disable var-name-mixedcase */\\\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\\\n    // invalidate the cached domain separator if the chain id changes.\\\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\\\n    uint256 private immutable _CACHED_CHAIN_ID;\\\\n\\\\n    bytes32 private immutable _HASHED_NAME;\\\\n    bytes32 private immutable _HASHED_VERSION;\\\\n    bytes32 private immutable _TYPE_HASH;\\\\n    /* solhint-enable var-name-mixedcase */\\\\n\\\\n    /**\\\\n     * @dev Initializes the domain separator and parameter caches.\\\\n     *\\\\n     * The meaning of `name` and `version` is specified in\\\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\\\n     *\\\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\\\n     * - `version`: the current major version of the signing domain.\\\\n     *\\\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\\\n     * contract upgrade].\\\\n     */\\\\n    constructor(string memory name, string memory version) {\\\\n        bytes32 hashedName = keccak256(bytes(name));\\\\n        bytes32 hashedVersion = keccak256(bytes(version));\\\\n        bytes32 typeHash = keccak256(\\\\\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\\\\\");\\\\n        _HASHED_NAME = hashedName;\\\\n        _HASHED_VERSION = hashedVersion;\\\\n        _CACHED_CHAIN_ID = _getChainId();\\\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\\\n        _TYPE_HASH = typeHash;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the domain separator for the current chain.\\\\n     */\\\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\\\n            return _CACHED_DOMAIN_SEPARATOR;\\\\n        } else {\\\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\\\n        }\\\\n    }\\\\n\\\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\\\n        return keccak256(\\\\n            abi.encode(\\\\n                typeHash,\\\\n                name,\\\\n                version,\\\\n                _getChainId(),\\\\n                address(this)\\\\n            )\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\\\n     *\\\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\\\n     *\\\\n     * ```solidity\\\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\\\n     *     keccak256(\\\\\\\"Mail(address to,string contents)\\\\\\\"),\\\\n     *     mailTo,\\\\n     *     keccak256(bytes(mailContents))\\\\n     * )));\\\\n     * address signer = ECDSA.recover(digest, signature);\\\\n     * ```\\\\n     */\\\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\\\n        return keccak256(abi.encodePacked(\\\\\\\"\\\\\\\\x19\\\\\\\\x01\\\\\\\", _domainSeparatorV4(), structHash));\\\\n    }\\\\n\\\\n    function _getChainId() private view returns (uint256 chainId) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly {\\\\n            chainId := chainid()\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4bc5cda2bfee483ff10334881c9ea5cc4df7faa7b18a5a4b8f02fc51cf8adca\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 SafeMath for uint256;\\\\n    using Address for address;\\\\n\\\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\\\n    }\\\\n\\\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\\\n    }\\\\n\\\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\\\\\"SafeERC20: decreased allowance below zero\\\\\\\");\\\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\\\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) { // Return data is optional\\\\n            // solhint-disable-next-line max-line-length\\\\n            require(abi.decode(returndata, (bool)), \\\\\\\"SafeERC20: ERC20 operation did not succeed\\\\\\\");\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc77dd6233a82c7c6e3dc49da8f3456baa00ecd3ea4dfa9222002a9aebf155dcd\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Safe casting methods\\\\n/// @notice Contains methods for safely casting between types\\\\nlibrary SafeCast {\\\\n    /// @notice Cast a uint256 to a uint160, revert on overflow\\\\n    /// @param y The uint256 to be downcasted\\\\n    /// @return z The downcasted integer, now type uint160\\\\n    function toUint160(uint256 y) internal pure returns (uint160 z) {\\\\n        require((z = uint160(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a int256 to a int128, revert on overflow or underflow\\\\n    /// @param y The int256 to be downcasted\\\\n    /// @return z The downcasted integer, now type int128\\\\n    function toInt128(int256 y) internal pure returns (int128 z) {\\\\n        require((z = int128(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a uint256 to a int256, revert on overflow\\\\n    /// @param y The uint256 to be casted\\\\n    /// @return z The casted integer, now type int256\\\\n    function toInt256(uint256 y) internal pure returns (int256 z) {\\\\n        require(y < 2**255);\\\\n        z = int256(y);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n/*\\\\n * @title Solidity Bytes Arrays Utils\\\\n * @author Gon\\\\u00e7alo S\\\\u00e1 <goncalo.sa@consensys.net>\\\\n *\\\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\\\n */\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nlibrary BytesLib {\\\\n    function slice(\\\\n        bytes memory _bytes,\\\\n        uint256 _start,\\\\n        uint256 _length\\\\n    ) internal pure returns (bytes memory) {\\\\n        require(_length + 31 >= _length, 'slice_overflow');\\\\n        require(_start + _length >= _start, 'slice_overflow');\\\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\\\n\\\\n        bytes memory tempBytes;\\\\n\\\\n        assembly {\\\\n            switch iszero(_length)\\\\n                case 0 {\\\\n                    // Get a location of some free memory and store it in tempBytes as\\\\n                    // Solidity does for memory variables.\\\\n                    tempBytes := mload(0x40)\\\\n\\\\n                    // The first word of the slice result is potentially a partial\\\\n                    // word read from the original array. To read it, we calculate\\\\n                    // the length of that partial word and start copying that many\\\\n                    // bytes into the array. The first word we copy will start with\\\\n                    // data we don't care about, but the last `lengthmod` bytes will\\\\n                    // land at the beginning of the contents of the new array. When\\\\n                    // we're done copying, we overwrite the full first word with\\\\n                    // the actual length of the slice.\\\\n                    let lengthmod := and(_length, 31)\\\\n\\\\n                    // The multiplication in the next line is necessary\\\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\\\n                    // the following copy loop was copying the origin's length\\\\n                    // and then ending prematurely not copying everything it should.\\\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\\\n                    let end := add(mc, _length)\\\\n\\\\n                    for {\\\\n                        // The multiplication in the next line has the same exact purpose\\\\n                        // as the one above.\\\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\\\n                    } lt(mc, end) {\\\\n                        mc := add(mc, 0x20)\\\\n                        cc := add(cc, 0x20)\\\\n                    } {\\\\n                        mstore(mc, mload(cc))\\\\n                    }\\\\n\\\\n                    mstore(tempBytes, _length)\\\\n\\\\n                    //update free-memory pointer\\\\n                    //allocating the array padded to 32 bytes like the compiler does now\\\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\\\n                }\\\\n                //if we want a zero-length slice let's just return a zero-length array\\\\n                default {\\\\n                    tempBytes := mload(0x40)\\\\n                    //zero out the 32 bytes slice we are about to return\\\\n                    //we need to do it because Solidity does not garbage collect\\\\n                    mstore(tempBytes, 0)\\\\n\\\\n                    mstore(0x40, add(tempBytes, 0x20))\\\\n                }\\\\n        }\\\\n\\\\n        return tempBytes;\\\\n    }\\\\n\\\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\\\n        address tempAddress;\\\\n\\\\n        assembly {\\\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\\\n        }\\\\n\\\\n        return tempAddress;\\\\n    }\\\\n\\\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\\\n        uint24 tempUint;\\\\n\\\\n        assembly {\\\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\\\n        }\\\\n\\\\n        return tempUint;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport './PoolAddress.sol';\\\\n\\\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\\\nlibrary CallbackValidation {\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param tokenA The contract address of either token0 or token1\\\\n    /// @param tokenB The contract address of the other token\\\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(\\\\n        address factory,\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool pool) {\\\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param poolKey The identifying key of the V3 pool\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\\\n        internal\\\\n        view\\\\n        returns (IUniswapV3Pool pool)\\\\n    {\\\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\\\n        require(msg.sender == address(pool));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.6.0;\\\\n\\\\nimport './BytesLib.sol';\\\\n\\\\n/// @title Functions for manipulating path data for multihop swaps\\\\nlibrary Path {\\\\n    using BytesLib for bytes;\\\\n\\\\n    /// @dev The length of the bytes encoded address\\\\n    uint256 private constant ADDR_SIZE = 20;\\\\n    /// @dev The length of the bytes encoded fee\\\\n    uint256 private constant FEE_SIZE = 3;\\\\n\\\\n    /// @dev The offset of a single token address and pool fee\\\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\\\n    /// @dev The offset of an encoded pool key\\\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\\\n\\\\n    /// @notice Returns true iff the path contains two or more pools\\\\n    /// @param path The encoded swap path\\\\n    /// @return True if path contains two or more pools, otherwise false\\\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\\\n    }\\\\n\\\\n    /// @notice Returns the number of pools in the path\\\\n    /// @param path The encoded swap path\\\\n    /// @return The number of pools in the path\\\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Decodes the first pool in path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return tokenA The first token of the given pool\\\\n    /// @return tokenB The second token of the given pool\\\\n    /// @return fee The fee level of the pool\\\\n    function decodeFirstPool(bytes memory path)\\\\n        internal\\\\n        pure\\\\n        returns (\\\\n            address tokenA,\\\\n            address tokenB,\\\\n            uint24 fee\\\\n        )\\\\n    {\\\\n        tokenA = path.toAddress(0);\\\\n        fee = path.toUint24(ADDR_SIZE);\\\\n        tokenB = path.toAddress(NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Gets the segment corresponding to the first pool in the path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return The segment containing all data necessary to target the first pool in the path\\\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(0, POP_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\\\n    /// @param path The swap path\\\\n    /// @return The remaining token + fee elements in the path\\\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/external/WETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\\\n\\\\ncontract WETH9 {\\\\n    string public name = \\\\\\\"Wrapped Ether\\\\\\\";\\\\n    string public symbol = \\\\\\\"WETH\\\\\\\";\\\\n    uint8 public decimals = 18;\\\\n\\\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\\\n    event Deposit(address indexed dst, uint256 wad);\\\\n    event Withdrawal(address indexed src, uint256 wad);\\\\n\\\\n    mapping(address => uint256) public balanceOf;\\\\n    mapping(address => mapping(address => uint256)) public allowance;\\\\n\\\\n    function deposit() public payable {\\\\n        balanceOf[msg.sender] += msg.value;\\\\n        emit Deposit(msg.sender, msg.value);\\\\n    }\\\\n\\\\n    function withdraw(uint256 wad) public {\\\\n        require(balanceOf[msg.sender] >= wad);\\\\n        balanceOf[msg.sender] -= wad;\\\\n        payable(msg.sender).transfer(wad);\\\\n        emit Withdrawal(msg.sender, wad);\\\\n    }\\\\n\\\\n    function totalSupply() public view returns (uint256) {\\\\n        return address(this).balance;\\\\n    }\\\\n\\\\n    function approve(address guy, uint256 wad) public returns (bool) {\\\\n        allowance[msg.sender][guy] = wad;\\\\n        emit Approval(msg.sender, guy, wad);\\\\n        return true;\\\\n    }\\\\n\\\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\\\n        return transferFrom(msg.sender, dst, wad);\\\\n    }\\\\n\\\\n    function transferFrom(\\\\n        address src,\\\\n        address dst,\\\\n        uint256 wad\\\\n    ) public returns (bool) {\\\\n        require(balanceOf[src] >= wad);\\\\n\\\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\\\n            require(allowance[src][msg.sender] >= wad);\\\\n            allowance[src][msg.sender] -= wad;\\\\n        }\\\\n\\\\n        balanceOf[src] -= wad;\\\\n        balanceOf[dst] += wad;\\\\n\\\\n        emit Transfer(src, dst, wad);\\\\n\\\\n        return true;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1624ad07a54d1a85df74a1ec4dc0e5d47d42165bfd71cf1dbc9fc51de3e6d8de\\\",\\\"license\\\":\\\"GPL-3.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IEuler.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\ninterface IEulerExec {\\\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\\\n}\\\\n\\\\ninterface IDToken {\\\\n    function underlyingAsset() external view returns (address);\\\\n\\\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\\\n\\\\n    function repay(uint256 subAccountId, uint256 amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x81fd5d15724c747dad6b8f2a01b893a59b4db6c02ce2ecb92b50dfd96c4046c8\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/Power2Base.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary Power2Base {\\\\n    using SafeMath for uint256;\\\\n\\\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\\\n    uint256 private constant INDEX_SCALE = 1e4;\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    /**\\\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getUnscaledIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\\\n     */\\\\n    function _getDenormalizedMark(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _wSqueeth,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\\\n\\\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _weth weth address\\\\n     * @return returns value of debt in ETH\\\\n     */\\\\n    function _getDebtValueInEth(\\\\n        uint256 _debtAmount,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _wSqueeth,\\\\n        address _weth\\\\n    ) internal view returns (uint256) {\\\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle\\\\n     * @dev this will revert if period is > max period for the pool\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        // period reaching this point should be check, otherwise might revert\\\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\\\n     * @param _indexPriceForSettlement index price for settlement\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return amount in wei that should be paid to the token holder\\\\n     */\\\\n    function _getLongSettlementValue(\\\\n        uint256 _wsqueethAmount,\\\\n        uint256 _indexPriceForSettlement,\\\\n        uint256 _normalizationFactor\\\\n    ) internal pure returns (uint256) {\\\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1938180c41ec0ee817b841df605b199e15ffbbe94700b640d031b4e4665a89af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/CrabMigration.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\nimport {SafeERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\\\\\";\\\\nimport {IEulerExec, IDToken} from \\\\\\\"../interfaces/IEuler.sol\\\\\\\";\\\\nimport {WETH9} from \\\\\\\"../external/WETH9.sol\\\\\\\";\\\\n\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {CrabStrategyV2} from \\\\\\\"./CrabStrategyV2.sol\\\\\\\";\\\\nimport {CrabStrategy} from \\\\\\\"./CrabStrategy.sol\\\\\\\";\\\\nimport {StrategyMath} from \\\\\\\"./base/StrategyMath.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Migration Error Codes:\\\\n * M1: Migration already happened\\\\n * M2: Migration has not yet happened\\\\n * M3: msg.sender is not Euler Mainnet Contract\\\\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\\\\n * M5: Can't withdraw more than you own\\\\n * M6: Not enough ETH to repay the loan\\\\n * M7: Invalid crabV2 address\\\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\\\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\\\n * M10: Wrong migration function, use flashMigrateFromV1toV2\\\\n * M11: crabV2 address not yet set\\\\n */\\\\n\\\\n/**\\\\n * @dev CrabMigration contract\\\\n * @notice Contract for Migrating from Crab V1 to Crab V2\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabMigration is Ownable {\\\\n    using SafeERC20 for IERC20;\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    mapping(address => uint256) public sharesDeposited;\\\\n    bool public isMigrated;\\\\n\\\\n    address payable public crabV1;\\\\n    address payable public crabV2;\\\\n    address public immutable euler;\\\\n    address public immutable weth;\\\\n\\\\n    address immutable EULER_MAINNET;\\\\n    address immutable dToken;\\\\n    address immutable wPowerPerp;\\\\n\\\\n    struct FlashloanCallbackData {\\\\n        address caller;\\\\n        uint256 amountToBorrow;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    struct BatchMigrate {\\\\n        uint256 strategyCap;\\\\n    }\\\\n\\\\n    struct FlashMigrateV1toV2 {\\\\n        uint256 v1oSqthToPay;\\\\n        uint256 ethToFlashDeposit;\\\\n        uint256 crabV1ToWithdraw;\\\\n        uint24 poolFee;\\\\n    }\\\\n\\\\n    struct FlashMigrateAndBuyV1toV2 {\\\\n        uint256 v1oSqthToPay;\\\\n        uint256 ethToFlashDeposit;\\\\n        uint256 withdrawMaxEthToPay;\\\\n        uint256 crabV1ToWithdraw;\\\\n        uint24 poolFeeFlashDeposit;\\\\n    }\\\\n\\\\n    enum FLASH_SOURCE {\\\\n        BATCH_MIGRATE,\\\\n        FLASH_MIGRATE_V1_TO_V2,\\\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\\\n    }\\\\n\\\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\\\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\\\\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\\\\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\\\\n\\\\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\\\\n\\\\n    modifier beforeMigration() {\\\\n        require(!isMigrated, \\\\\\\"M1\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier afterMigration() {\\\\n        require(isMigrated, \\\\\\\"M2\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier afterInitialized() {\\\\n        require(crabV2 != address(0), \\\\\\\"M11\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice migration constructor\\\\n     * @param _crabV1 address of crab V1\\\\n     * @param _weth address of weth\\\\n     * @param _eulerExec address of euler exec contract\\\\n     * @param _dToken address of euler liability token\\\\n     * @param _eulerMainnet address of euler deployment on mainnet\\\\n     */\\\\n    constructor(\\\\n        address payable _crabV1,\\\\n        address _weth,\\\\n        address _eulerExec,\\\\n        address _dToken,\\\\n        address _eulerMainnet\\\\n    ) {\\\\n        require(_eulerExec != address(0), \\\\\\\"invalid _eulerExec address\\\\\\\");\\\\n        require(_dToken != address(0), \\\\\\\"invalid _dToken address\\\\\\\");\\\\n        require(_eulerMainnet != address(0), \\\\\\\"invalid _eulerMainnet address\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"invalid _weth address\\\\\\\");\\\\n        require(_crabV1 != address(0), \\\\\\\"invalid _crabv1 address\\\\\\\");\\\\n        require(IDToken(_dToken).underlyingAsset() == _weth, \\\\\\\"dToken underlying asset should be weth\\\\\\\");\\\\n\\\\n        crabV1 = _crabV1;\\\\n        euler = _eulerExec;\\\\n        EULER_MAINNET = _eulerMainnet;\\\\n        weth = _weth;\\\\n        dToken = _dToken;\\\\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\\\\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set the crabV2 address\\\\n     * @param _crabV2 address of crab V2\\\\n     */\\\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\\\n        require(_crabV2 != address(0), \\\\\\\"M7\\\\\\\");\\\\n        crabV2 = _crabV2;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit crab V1 shares in the pool for migration\\\\n     * @param _amount amount of crabV1 shares to deposit\\\\n     */\\\\n    function depositV1Shares(uint256 _amount) external beforeMigration {\\\\n        sharesDeposited[msg.sender] += _amount;\\\\n\\\\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\\\\n\\\\n        emit DepositV1Shares(msg.sender, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw crab V1 shares in the pool before migration\\\\n     * @param _amount amount of V1 shares to withdraw\\\\n     */\\\\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\\\\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\\\\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\\\\n\\\\n        emit WithdrawV1Shares(msg.sender, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\\\\n     * the V2 contract at the same collateral ratio as the V1 contract\\\\n     * @param _strategyCap strategy cap in ETH\\\\n     */\\\\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\\\\n        // 1. update isMigrated\\\\n        isMigrated = true;\\\\n\\\\n        // 2. flash floan eth from euler eq to amt\\\\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\\\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\\\\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\\\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\\\n        IEulerExec(euler).deferLiquidityCheck(\\\\n            address(this),\\\\n            abi.encode(\\\\n                FlashloanCallbackData({\\\\n                    caller: msg.sender,\\\\n                    amountToBorrow: amountEthToBorrow,\\\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\\\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\\\\n                })\\\\n            )\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice Euler callback function\\\\n     * @param encodedData callback data\\\\n     */\\\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\\\n        require(msg.sender == EULER_MAINNET, \\\\\\\"M3\\\\\\\");\\\\n\\\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\\\n\\\\n        // 1. borrow weth\\\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\\\n        WETH9(weth).withdraw(data.amountToBorrow);\\\\n\\\\n        // 2. callback\\\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\\\n\\\\n        // 3. repay the weth\\\\n        WETH9(weth).deposit{value: data.amountToBorrow}();\\\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice callback function for flash actions\\\\n     * @param _initiator address of original function caller\\\\n     * @param _amount  amount to pay back for flashswap\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     * @param _calldata arbitrary data attached to callback\\\\n\\\\n     */\\\\n    function _flashCallback(\\\\n        address _initiator,\\\\n        uint256 _amount,\\\\n        uint8 _callSource,\\\\n        bytes memory _calldata\\\\n    ) internal {\\\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\\\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\\\\n\\\\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\\\n\\\\n            // 2. mint osqth in crab V2\\\\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\\\\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\\\\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\\\\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\\\\n                wSqueethToMint,\\\\n                crabV1Balance,\\\\n                timeAtLastHedge,\\\\n                priceAtLastHedge,\\\\n                data.strategyCap\\\\n            );\\\\n\\\\n            // 3. call withdraw from crab V1\\\\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\\\\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\\\n\\\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\\\n\\\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\\\n\\\\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\\\\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\\\\n\\\\n            // flash deposit remaining ETH, otherwise refund\\\\n            // if CR1 = CR2 ethToFlashDeposit should be 0\\\\n            if (data.ethToFlashDeposit > 0) {\\\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\\\n                    data.ethToFlashDeposit,\\\\n                    data.poolFee\\\\n                );\\\\n            }\\\\n\\\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\\\n            // send back V2 tokens to the user\\\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\\\n\\\\n            uint256 excessEth = address(this).balance;\\\\n\\\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\\\n\\\\n            // send back excess ETH\\\\n            if (excessEth > _amount) {\\\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\\\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\\\\n\\\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\\\n\\\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\\\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\\\\n\\\\n            // find crab amount for contract's sqth balance\\\\n            // remaining crab can be withdrawn using flash withdraw\\\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\\\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\\\n\\\\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\\\\n\\\\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\\\n            require(address(this).balance >= _amount, \\\\\\\"M6\\\\\\\");\\\\n\\\\n            if (data.ethToFlashDeposit > 0) {\\\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\\\n                    data.ethToFlashDeposit,\\\\n                    data.poolFeeFlashDeposit\\\\n                );\\\\n            }\\\\n\\\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\\\n\\\\n            // send V2 tokens to the user\\\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\\\n\\\\n            uint256 excessEth = address(this).balance;\\\\n\\\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\\\n\\\\n            // send back the excess ETH\\\\n            if (excessEth > _amount) {\\\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\\\n            }\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice claim crab V2 shares\\\\n     */\\\\n    function claimV2Shares() external afterMigration {\\\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\\\n        sharesDeposited[msg.sender] = 0;\\\\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\\\\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice claim crab V2 shares and flash withdraw from crab V2\\\\n     * @param _amountToWithdraw V2 shares to claim\\\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\\\n     * @param _poolFee Uniswap pool fee for flash withdraw\\\\n     */\\\\n    function claimAndWithdraw(\\\\n        uint256 _amountToWithdraw,\\\\n        uint256 _maxEthToPay,\\\\n        uint24 _poolFee\\\\n    ) external afterMigration {\\\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\\\n        require(_amountToWithdraw <= amountV1Deposited, \\\\\\\"M5\\\\\\\");\\\\n\\\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\\\\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\\\\n\\\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\\\n\\\\n        // send eth to user\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice view details of flash migration for specified amount of V1 shares\\\\n     * @param _v1Shares amount of crab V1 shares\\\\n     */\\\\n    function flashMigrationDetails(uint256 _v1Shares)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            bool,\\\\n            uint256,\\\\n            uint256,\\\\n            uint256\\\\n        )\\\\n    {\\\\n        return _flashMigrationDetails(_v1Shares);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\\\\n     * @param _v1Shares V1 shares to migrate\\\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\\\n     * @param _poolFee uniswap pool fee for flash deposit\\\\n     */\\\\n    function flashMigrateFromV1toV2(\\\\n        uint256 _v1Shares,\\\\n        uint256 _ethToFlashDeposit,\\\\n        uint24 _poolFee\\\\n    ) external afterMigration {\\\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\\\n\\\\n        require(isFlashOnlyMigrate, \\\\\\\"M9\\\\\\\");\\\\n\\\\n        IEulerExec(euler).deferLiquidityCheck(\\\\n            address(this),\\\\n            abi.encode(\\\\n                FlashloanCallbackData({\\\\n                    caller: msg.sender,\\\\n                    amountToBorrow: ethNeededForV2,\\\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\\\n                    callData: abi.encode(\\\\n                        FlashMigrateV1toV2({\\\\n                            v1oSqthToPay: v1oSqthToPay,\\\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\\\n                            crabV1ToWithdraw: _v1Shares,\\\\n                            poolFee: _poolFee\\\\n                        })\\\\n                    )\\\\n                })\\\\n            )\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\\\\n     * @param _v1Shares V1 shares to migrate\\\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\\\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\\\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\\\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\\\\n     */\\\\n    function flashMigrateAndWithdrawFromV1toV2(\\\\n        uint256 _v1Shares,\\\\n        uint256 _ethToFlashDeposit,\\\\n        uint256 _ethToBorrow,\\\\n        uint256 _withdrawMaxEthToPay,\\\\n        uint24 _poolFee\\\\n    ) external afterMigration {\\\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\\\n\\\\n        require(!isFlashOnlyMigrate, \\\\\\\"M10\\\\\\\");\\\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\\\\\"M8\\\\\\\");\\\\n\\\\n        IEulerExec(euler).deferLiquidityCheck(\\\\n            address(this),\\\\n            abi.encode(\\\\n                FlashloanCallbackData({\\\\n                    caller: msg.sender,\\\\n                    amountToBorrow: _ethToBorrow,\\\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\\\n                    callData: abi.encode(\\\\n                        FlashMigrateAndBuyV1toV2({\\\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\\\n                            v1oSqthToPay: v1oSqthToPay,\\\\n                            crabV1ToWithdraw: _v1Shares,\\\\n                            poolFeeFlashDeposit: _poolFee\\\\n                        })\\\\n                    )\\\\n                })\\\\n            )\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get migration details for given amount of V1 shares\\\\n     * @param _v1Shares amount of crab V1 shares\\\\n     */\\\\n    function _flashMigrationDetails(uint256 _v1Shares)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            bool,\\\\n            uint256,\\\\n            uint256,\\\\n            uint256\\\\n        )\\\\n    {\\\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\\\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\\\\n\\\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\\\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\\\\n\\\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \\\\\\\"M4\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x276e3812b302205f2e657a443f808d978eeb593a0b52cf2b326eda3df2210bd3\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/CrabStrategy.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {StrategyBase} from \\\\\\\"./base/StrategyBase.sol\\\\\\\";\\\\nimport {StrategyFlashSwap} from \\\\\\\"./base/StrategyFlashSwap.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./base/StrategyMath.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev CrabStrategy contract\\\\n * @notice Contract for Crab strategy\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\\\n    uint256 public strategyCap;\\\\n\\\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\\\n    /// @dev twap period to use for hedge calculations\\\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum FLASH_SOURCE {\\\\n        FLASH_DEPOSIT,\\\\n        FLASH_WITHDRAW,\\\\n        FLASH_HEDGE_SELL,\\\\n        FLASH_HEDGE_BUY\\\\n    }\\\\n\\\\n    /// @dev ETH:WSqueeth uniswap pool\\\\n    address public immutable ethWSqueethPool;\\\\n    /// @dev strategy uniswap oracle\\\\n    address public immutable oracle;\\\\n    address public immutable ethQuoteCurrencyPool;\\\\n    address public immutable quoteCurrency;\\\\n\\\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\\\n    uint256 public deltaHedgeThreshold = 1e15;\\\\n    /// @dev time difference to trigger a hedge (seconds)\\\\n    uint256 public hedgeTimeThreshold;\\\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\\\n    uint256 public hedgePriceThreshold;\\\\n    /// @dev hedge auction duration (seconds)\\\\n    uint256 public auctionTime;\\\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\\\n    uint256 public minPriceMultiplier;\\\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\\\n    uint256 public maxPriceMultiplier;\\\\n\\\\n    /// @dev timestamp when last hedge executed\\\\n    uint256 public timeAtLastHedge;\\\\n    /// @dev WSqueeth/Eth price when last hedge executed\\\\n    uint256 public priceAtLastHedge;\\\\n\\\\n    /// @dev set to true when redeemShortShutdown has been called\\\\n    bool private hasRedeemedInShutdown;\\\\n\\\\n    struct FlashDepositData {\\\\n        uint256 totalDeposit;\\\\n    }\\\\n\\\\n    struct FlashWithdrawData {\\\\n        uint256 crabAmount;\\\\n    }\\\\n\\\\n    struct FlashHedgeData {\\\\n        uint256 wSqueethAmount;\\\\n        uint256 ethProceeds;\\\\n        uint256 minWSqueeth;\\\\n        uint256 minEth;\\\\n    }\\\\n\\\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\\\n    event TimeHedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        uint256 hedgeTimestamp,\\\\n        uint256 auctionTriggerTimestamp,\\\\n        uint256 minWSqueeth,\\\\n        uint256 minEth\\\\n    );\\\\n    event PriceHedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        uint256 hedgeTimestamp,\\\\n        uint256 auctionTriggerTimestamp,\\\\n        uint256 minWSqueeth,\\\\n        uint256 minEth\\\\n    );\\\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\\\n    event Hedge(\\\\n        address indexed hedger,\\\\n        bool auctionType,\\\\n        uint256 hedgerPrice,\\\\n        uint256 auctionPrice,\\\\n        uint256 wSqueethHedgeTargetAmount,\\\\n        uint256 ethHedgetargetAmount\\\\n    );\\\\n    event HedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        bool auctionType,\\\\n        uint256 auctionPrice,\\\\n        uint256 wSqueethHedgeTargetAmount,\\\\n        uint256 ethHedgetargetAmount\\\\n    );\\\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\\\n    event SetStrategyCap(uint256 newCapAmount);\\\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\\\n    event SetAuctionTime(uint256 newAuctionTime);\\\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\\\n\\\\n    /**\\\\n     * @notice strategy constructor\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _wSqueethController power token controller address\\\\n     * @param _oracle oracle address\\\\n     * @param _weth weth address\\\\n     * @param _uniswapFactory uniswap factory address\\\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\\\n     * @param _auctionTime auction duration (seconds)\\\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\\\n     */\\\\n    constructor(\\\\n        address _wSqueethController,\\\\n        address _oracle,\\\\n        address _weth,\\\\n        address _uniswapFactory,\\\\n        address _ethWSqueethPool,\\\\n        uint256 _hedgeTimeThreshold,\\\\n        uint256 _hedgePriceThreshold,\\\\n        uint256 _auctionTime,\\\\n        uint256 _minPriceMultiplier,\\\\n        uint256 _maxPriceMultiplier\\\\n    ) StrategyBase(_wSqueethController, _weth, \\\\\\\"Crab Strategy\\\\\\\", \\\\\\\"Crab\\\\\\\") StrategyFlashSwap(_uniswapFactory) {\\\\n        require(_oracle != address(0), \\\\\\\"invalid oracle address\\\\\\\");\\\\n        require(_ethWSqueethPool != address(0), \\\\\\\"invalid ETH:WSqueeth address\\\\\\\");\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"invalid hedge time threshold\\\\\\\");\\\\n        require(_hedgePriceThreshold > 0, \\\\\\\"invalid hedge price threshold\\\\\\\");\\\\n        require(_auctionTime > 0, \\\\\\\"invalid auction time\\\\\\\");\\\\n        require(_minPriceMultiplier < 1e18, \\\\\\\"min price multiplier too high\\\\\\\");\\\\n        require(_minPriceMultiplier > 0, \\\\\\\"invalid min price multiplier\\\\\\\");\\\\n        require(_maxPriceMultiplier > 1e18, \\\\\\\"max price multiplier too low\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        ethWSqueethPool = _ethWSqueethPool;\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n        auctionTime = _auctionTime;\\\\n        minPriceMultiplier = _minPriceMultiplier;\\\\n        maxPriceMultiplier = _maxPriceMultiplier;\\\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\\\\\"Cannot receive eth\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the strategy cap in ETH collateral terms\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\\\n        strategyCap = _capAmount;\\\\n\\\\n        emit SetStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to redeem the net value of a vault post shutdown\\\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\\\n     */\\\\n    function redeemShortShutdown() external {\\\\n        hasRedeemedInShutdown = true;\\\\n        powerTokenController.redeemShort(vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\\n     */\\\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\\\n            _ethToDeposit,\\\\n            cachedStrategyDebt,\\\\n            cachedStrategyCollateral\\\\n        );\\\\n\\\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\\\n            // store hedge data as strategy is delta neutral at this point\\\\n            // only execute this upon first deposit\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\\\n                ethWSqueethPool,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                hedgingTwapPeriod,\\\\n                true\\\\n            );\\\\n            timeAtLastHedge = block.timestamp;\\\\n            priceAtLastHedge = wSqueethEthPrice;\\\\n        }\\\\n\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n            wSqueethToMint,\\\\n            _ethToDeposit.sub(msg.value),\\\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\\\n            abi.encodePacked(_ethToDeposit)\\\\n        );\\\\n\\\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\\n     * @param _crabAmount strategy token amount to burn\\\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\\\n     */\\\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n            exactWSqueethNeeded,\\\\n            _maxEthToPay,\\\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\\\n            abi.encodePacked(_crabAmount)\\\\n        );\\\\n\\\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit ETH into strategy\\\\n     * @dev provide ETH, return wSqueeth and strategy token\\\\n     */\\\\n    function deposit() external payable nonReentrant {\\\\n        uint256 amount = msg.value;\\\\n\\\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\\\n\\\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\\\n\\\\n        // send back ETH collateral\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n\\\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\\\n        require(powerTokenController.isShutDown(), \\\\\\\"Squeeth contracts not shut down\\\\\\\");\\\\n        require(hasRedeemedInShutdown, \\\\\\\"Crab must redeemShortShutdown\\\\\\\");\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\\\n        _burn(msg.sender, _crabAmount);\\\\n\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\\\n     * @dev between uniswap execution price and the price of the hedging auction\\\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\\\n     */\\\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\\\n\\\\n        require(isTimeHedgeAllowed, \\\\\\\"Time hedging is not allowed\\\\\\\");\\\\n\\\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\\\n\\\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\\\n     * @dev between uniswap execution price and the price of the hedging auction\\\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\\\n     */\\\\n    function priceHedgeOnUniswap(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _minWSqueeth,\\\\n        uint256 _minEth\\\\n    ) external payable {\\\\n        require(_isPriceHedge(_auctionTriggerTime), \\\\\\\"Price hedging not allowed\\\\\\\");\\\\n\\\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\\\n\\\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy hedging based on time threshold\\\\n     * @dev need to attach msg.value if buying WSqueeth\\\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\\\n     */\\\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\\\n\\\\n        require(isTimeHedgeAllowed, \\\\\\\"Time hedging is not allowed\\\\\\\");\\\\n\\\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\\\n\\\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy hedging based on price threshold\\\\n     * @dev need to attach msg.value if buying WSqueeth\\\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\\\n     */\\\\n    function priceHedge(\\\\n        uint256 _auctionTriggerTime,\\\\n        bool _isStrategySellingWSqueeth,\\\\n        uint256 _limitPrice\\\\n    ) external payable nonReentrant {\\\\n        require(_isPriceHedge(_auctionTriggerTime), \\\\\\\"Price hedging not allowed\\\\\\\");\\\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\\\n\\\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\\\n        return _isPriceHedge(_auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\\\n     * @return auctionTriggertime auction trigger timestamp\\\\n     */\\\\n    function checkTimeHedge() external view returns (bool, uint256) {\\\\n        return _isTimeHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\\\n     * @param _crabAmount strategy token amount\\\\n     * @return wSqueeth amount\\\\n     */\\\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\\\n        return _getDebtFromStrategyAmount(_crabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\\\n     */\\\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\\\n\\\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\\\n     */\\\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\\\n        require(_hedgingTwapPeriod >= 180, \\\\\\\"twap period is too short\\\\\\\");\\\\n\\\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\\\n\\\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\\\n     */\\\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"invalid hedge time threshold\\\\\\\");\\\\n\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n\\\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\\\n     */\\\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\\\n        require(_hedgePriceThreshold > 0, \\\\\\\"invalid hedge price threshold\\\\\\\");\\\\n\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n\\\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\\\n     * @param _auctionTime the length of the hedge auction in seconds\\\\n     */\\\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\\\n        require(_auctionTime > 0, \\\\\\\"invalid auction time\\\\\\\");\\\\n\\\\n        auctionTime = _auctionTime;\\\\n\\\\n        emit SetAuctionTime(_auctionTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\\\n     */\\\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\\\n        require(_minPriceMultiplier < 1e18, \\\\\\\"min price multiplier too high\\\\\\\");\\\\n\\\\n        minPriceMultiplier = _minPriceMultiplier;\\\\n\\\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\\\n     */\\\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\\\n        require(_maxPriceMultiplier > 1e18, \\\\\\\"max price multiplier too low\\\\\\\");\\\\n\\\\n        maxPriceMultiplier = _maxPriceMultiplier;\\\\n\\\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get current auction details\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\\\n     */\\\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            bool,\\\\n            uint256,\\\\n            uint256,\\\\n            uint256,\\\\n            bool\\\\n        )\\\\n    {\\\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            hedgingTwapPeriod,\\\\n            true\\\\n        );\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\\\n            strategyDebt,\\\\n            ethDelta,\\\\n            auctionWSqueethEthPrice,\\\\n            feeAdjustment\\\\n        );\\\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\\\n\\\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a user deposit puts the strategy above the cap\\\\n     * @dev reverts if a deposit amount puts strategy over the cap\\\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\\\n     * @param _depositAmount the user deposit amount in ETH\\\\n     * @param _strategyCollateral the updated strategy collateral\\\\n     */\\\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\\\\\"Deposit exceeds strategy cap\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _strategyFlash(\\\\n        address _caller,\\\\n        address, /*_tokenIn*/\\\\n        address, /*_tokenOut*/\\\\n        uint24, /*_fee*/\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n\\\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\\\n            //will revert if data.totalDeposit is > eth balance in contract\\\\n            _deposit(_caller, data.totalDeposit, true);\\\\n\\\\n            //repay the flash swap\\\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\\\n\\\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\\\n\\\\n            //return excess eth to the user that was not needed for slippage\\\\n            if (address(this).balance > 0) {\\\\n                payable(_caller).sendValue(address(this).balance);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\\\n\\\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\\\n            uint256 ethToWithdraw = _withdraw(\\\\n                _caller,\\\\n                data.crabAmount,\\\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\\\n                true\\\\n            );\\\\n\\\\n            //use some amount of withdrawn ETH to repay flash swap\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\\\n\\\\n            //excess ETH not used to repay flash swap is transferred to the user\\\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\\\n\\\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\\\n\\\\n            if (proceeds > 0) {\\\\n                payable(_caller).sendValue(proceeds);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\\\n            //strategy is selling wSqueeth for ETH\\\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\\\n\\\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\\\n\\\\n            //minimum profit check for hedger\\\\n            require(wSqueethProfit >= data.minWSqueeth, \\\\\\\"profit is less than min wSqueeth\\\\\\\");\\\\n\\\\n            //repay flash swap and transfer profit to hedger\\\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\\\n            //strategy is buying wSqueeth for ETH\\\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\\\n\\\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\\\n\\\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\\\n\\\\n            //minimum profit check for hedger\\\\n            require(ethProfit >= data.minEth, \\\\\\\"profit is less than min ETH\\\\\\\");\\\\n\\\\n            //repay flash swap and transfer profit to hedger\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\\\n            payable(_caller).sendValue(ethProfit);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit into strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _depositor depositor address\\\\n     * @param _amount amount of ETH collateral to deposit\\\\n     * @param _isFlashDeposit true if called by flashDeposit\\\\n     * @return wSqueethToMint minted amount of WSqueeth\\\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\\\n     */\\\\n    function _deposit(\\\\n        address _depositor,\\\\n        uint256 _amount,\\\\n        bool _isFlashDeposit\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_amount, strategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\\\n\\\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\\\n\\\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\\\n            // store hedge data as strategy is delta neutral at this point\\\\n            // only execute this upon first deposit\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\\\n                ethWSqueethPool,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                hedgingTwapPeriod,\\\\n                true\\\\n            );\\\\n            timeAtLastHedge = block.timestamp;\\\\n            priceAtLastHedge = wSqueethEthPrice;\\\\n        }\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\\\n\\\\n        return (wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\\\n     * @return ETH amount to withdraw\\\\n     */\\\\n    function _withdraw(\\\\n        address _from,\\\\n        uint256 _crabAmount,\\\\n        uint256 _wSqueethAmount,\\\\n        bool _isFlashWithdraw\\\\n    ) internal returns (uint256) {\\\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\\\n\\\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\\\n        _burn(_from, _crabAmount);\\\\n\\\\n        return ethToWithdraw;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\\\n     */\\\\n    function _hedge(\\\\n        uint256 _auctionTriggerTime,\\\\n        bool _isStrategySellingWSqueeth,\\\\n        uint256 _limitPrice\\\\n    ) internal {\\\\n        (\\\\n            bool isSellingAuction,\\\\n            uint256 wSqueethToAuction,\\\\n            uint256 ethProceeds,\\\\n            uint256 auctionWSqueethEthPrice\\\\n        ) = _startAuction(_auctionTriggerTime);\\\\n\\\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\\\\\"wrong auction type\\\\\\\");\\\\n\\\\n        if (isSellingAuction) {\\\\n            // Receiving ETH and paying wSqueeth\\\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\\\\\"Auction price > max price\\\\\\\");\\\\n            require(msg.value >= ethProceeds, \\\\\\\"Low ETH amount received\\\\\\\");\\\\n\\\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\\\n        } else {\\\\n            require(msg.value == 0, \\\\\\\"ETH attached for buy auction\\\\\\\");\\\\n            // Receiving wSqueeth and paying ETH\\\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\\\\\"Auction price < min price\\\\\\\");\\\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\\\n        }\\\\n\\\\n        emit Hedge(\\\\n            msg.sender,\\\\n            _isStrategySellingWSqueeth,\\\\n            _limitPrice,\\\\n            auctionWSqueethEthPrice,\\\\n            wSqueethToAuction,\\\\n            ethProceeds\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute arb between auction price and uniswap price\\\\n     * @param _auctionTriggerTime auction starting time\\\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\\\n     */\\\\n    function _hedgeOnUniswap(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _minWSqueeth,\\\\n        uint256 _minEth\\\\n    ) internal {\\\\n        (\\\\n            bool isSellingAuction,\\\\n            uint256 wSqueethToAuction,\\\\n            uint256 ethProceeds,\\\\n            uint256 auctionWSqueethEthPrice\\\\n        ) = _startAuction(_auctionTriggerTime);\\\\n\\\\n        if (isSellingAuction) {\\\\n            _exactOutFlashSwap(\\\\n                wPowerPerp,\\\\n                weth,\\\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n                ethProceeds,\\\\n                wSqueethToAuction,\\\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\\\n            );\\\\n        } else {\\\\n            _exactOutFlashSwap(\\\\n                weth,\\\\n                wPowerPerp,\\\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n                wSqueethToAuction,\\\\n                ethProceeds,\\\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\\\n            );\\\\n        }\\\\n\\\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute sell auction based on the parameters calculated\\\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\\\n     * @param _buyer buyer address\\\\n     * @param _buyerAmount buyer ETH amount sent\\\\n     * @param _wSqueethToSell wSqueeth amount to sell\\\\n     * @param _ethToBuy ETH amount to buy\\\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\\\n     */\\\\n    function _executeSellAuction(\\\\n        address _buyer,\\\\n        uint256 _buyerAmount,\\\\n        uint256 _wSqueethToSell,\\\\n        uint256 _ethToBuy,\\\\n        bool _isHedgingOnUniswap\\\\n    ) internal {\\\\n        if (_isHedgingOnUniswap) {\\\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\\\n        } else {\\\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\\\n\\\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\\\n\\\\n            if (remainingEth > 0) {\\\\n                payable(_buyer).sendValue(remainingEth);\\\\n            }\\\\n        }\\\\n\\\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute buy auction based on the parameters calculated\\\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\\\n     * @param _seller seller address\\\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\\\n     * @param _ethToSell ETH amount to sell\\\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\\\n     */\\\\n    function _executeBuyAuction(\\\\n        address _seller,\\\\n        uint256 _wSqueethToBuy,\\\\n        uint256 _ethToSell,\\\\n        bool _isHedgingOnUniswap\\\\n    ) internal {\\\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\\\n\\\\n        if (!_isHedgingOnUniswap) {\\\\n            payable(_seller).sendValue(_ethToSell);\\\\n        }\\\\n\\\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\\\n     * @param _auctionTriggerTime auction starting time\\\\n     * @return auction type\\\\n     * @return WSqueeth amount to sell or buy\\\\n     * @return ETH to sell/buy\\\\n     * @return auction WSqueeth/ETH price\\\\n     */\\\\n    function _startAuction(uint256 _auctionTriggerTime)\\\\n        internal\\\\n        returns (\\\\n            bool,\\\\n            uint256,\\\\n            uint256,\\\\n            uint256\\\\n        )\\\\n    {\\\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            hedgingTwapPeriod,\\\\n            true\\\\n        );\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\\\n            strategyDebt,\\\\n            ethDelta,\\\\n            auctionWSqueethEthPrice,\\\\n            feeAdjustment\\\\n        );\\\\n\\\\n        require(isSellingAuction == isStillSellingAuction, \\\\\\\"auction direction changed\\\\\\\");\\\\n\\\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\\\n\\\\n        timeAtLastHedge = block.timestamp;\\\\n        priceAtLastHedge = currentWSqueethPrice;\\\\n\\\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sync strategy debt and collateral amount from vault\\\\n     * @return synced debt amount\\\\n     * @return synced collateral amount\\\\n     */\\\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\\\n\\\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\\\n     * @return the fee adjustment factor\\\\n     */\\\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\\\n            oracle,\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            POWER_PERP_PERIOD,\\\\n            false\\\\n        );\\\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\\\n     * @param _depositedAmount amount of deposited WETH\\\\n     * @param _strategyDebtAmount amount of strategy debt\\\\n     * @param _strategyCollateralAmount collateral amount in strategy\\\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\\\n     */\\\\n    function _calcWsqueethToMintAndFee(\\\\n        uint256 _depositedAmount,\\\\n        uint256 _strategyDebtAmount,\\\\n        uint256 _strategyCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 wSqueethToMint;\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n\\\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\\\n            require(totalSupply() == 0, \\\\\\\"Crab contracts shut down\\\\\\\");\\\\n\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\\\n                ethWSqueethPool,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                hedgingTwapPeriod,\\\\n                true\\\\n            );\\\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\\\n        } else {\\\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\\\n            );\\\\n        }\\\\n\\\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\\\n\\\\n        return (wSqueethToMint, fee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if time hedging is allowed\\\\n     * @return auction trigger timestamp\\\\n     */\\\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\\\n\\\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\\\n            secondsToPriceHedgeTrigger\\\\n        );\\\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\\\n\\\\n        return priceThreshold >= hedgePriceThreshold;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\\\n     * @return auction price\\\\n     */\\\\n    function _getAuctionPrice(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _wSqueethEthPrice,\\\\n        bool _isSellingAuction\\\\n    ) internal view returns (uint256) {\\\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\\\n            ? 1e18\\\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\\\n\\\\n        uint256 priceMultiplier;\\\\n        if (_isSellingAuction) {\\\\n            priceMultiplier = maxPriceMultiplier.sub(\\\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\\\n            );\\\\n        } else {\\\\n            priceMultiplier = minPriceMultiplier.add(\\\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\\\n            );\\\\n        }\\\\n\\\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\\\n     * @param _debt strategy debt\\\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\\\n     */\\\\n    function _checkAuctionType(\\\\n        uint256 _debt,\\\\n        uint256 _ethDelta,\\\\n        uint256 _wSqueethEthPrice,\\\\n        uint256 _feeAdjustment\\\\n    ) internal view returns (bool, uint256) {\\\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\\\n\\\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\\\n            wSqueethDelta,\\\\n            _ethDelta,\\\\n            _wSqueethEthPrice,\\\\n            _feeAdjustment\\\\n        );\\\\n\\\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\\\\\"strategy is delta neutral\\\\\\\");\\\\n\\\\n        return (isSellingAuction, targetHedge);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate amount of strategy token to mint for depositor\\\\n     * @param _amount amount of ETH deposited\\\\n     * @param _strategyCollateralAmount amount of strategy collateral\\\\n     * @param _crabTotalSupply total supply of strategy token\\\\n     * @return amount of strategy token to mint\\\\n     */\\\\n    function _calcSharesToMint(\\\\n        uint256 _amount,\\\\n        uint256 _strategyCollateralAmount,\\\\n        uint256 _crabTotalSupply\\\\n    ) internal pure returns (uint256) {\\\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\\\n\\\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\\\n\\\\n        return _amount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\\\n     * @param _crabAmount strategy token amount\\\\n     * @param _totalSupply strategy total supply\\\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\\\n     */\\\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\\\n        return _crabAmount.wdiv(_totalSupply);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\\\n     * @param _crabRatio crab ratio\\\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\\\n     * @return amount of ETH allowed to withdraw\\\\n     */\\\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine target hedge and auction type (selling/buying auction)\\\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\\\n     * @param _wSqueethDelta WSqueeth delta\\\\n     * @param _ethDelta ETH delta\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\\\n     * @return target hedge in wSqueeth\\\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\\\n     */\\\\n    function _getTargetHedgeAndAuctionType(\\\\n        uint256 _wSqueethDelta,\\\\n        uint256 _ethDelta,\\\\n        uint256 _wSqueethEthPrice,\\\\n        uint256 _feeAdjustment\\\\n    ) internal pure returns (uint256, bool) {\\\\n        return\\\\n            (_wSqueethDelta > _ethDelta)\\\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86a9d034ce1d510b05c23a0e2d42865823c676e17685494bde6c954504062366\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/CrabStrategyV2.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {StrategyBase} from \\\\\\\"./base/StrategyBase.sol\\\\\\\";\\\\nimport {StrategyFlashSwap} from \\\\\\\"./base/StrategyFlashSwap.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\nimport {EIP712} from \\\\\\\"@openzeppelin/contracts/drafts/EIP712.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./base/StrategyMath.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\nimport {ECDSA} from \\\\\\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Crab V2 Error Codes:\\\\n * C1: Caller is not timelock\\\\n * C2: Contract not yet initialized\\\\n * C3: Invalid oracle address\\\\n * C4: Invalid timelock address\\\\n * C5: Invalid ETH:WSqueeth address\\\\n * C6: Invalid crabMigration address\\\\n * C7: Invalid hedge time threshold\\\\n * C8: Invalid hedge price threshold\\\\n * C9: Cannot receive ETH\\\\n * C10: Caller not Crab Migration contract\\\\n * C11: Crab V2 already initialized\\\\n * C12: Squeeth contracts not shut down\\\\n * C13: Crab must redeemShortShutdown\\\\n * C14: Twap period is too short\\\\n * C15: Price tolerance is too high\\\\n * C16: Deposit exceeds strategy cap\\\\n * C17: Clearing Price should be below bid price\\\\n * C18: Clearing Price should be above offer price\\\\n * C19: Invalid offer signature\\\\n * C20: Order has expired\\\\n * C21: Manager Price should be greater than 0\\\\n * C22: Not a valid Time or Price hedge\\\\n * C23: Orders must take the opposite side of the hedge\\\\n * C24: All orders must be either buying or selling\\\\n * C25: Orders are not arranged properly\\\\n * C26: Crab contracts shut down\\\\n *  C27: Nonce already used.\\\\n */\\\\n\\\\n/**\\\\n * @dev CrabStrategyV2 contract\\\\n * @notice Contract for Crab strategy\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\\\n    uint256 public strategyCap;\\\\n\\\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\\\n\\\\n    /// @dev basic unit used for calculation\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    // @dev OTC price must be within this distance of the uniswap twap price\\\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\\\n\\\\n    // @dev OTC price tolerance cannot exceed 20%\\\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\\\n\\\\n    /// @dev twap period to use for hedge calculations\\\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\\\n    /// @dev true if CrabV2 was initialized\\\\n    bool public isInitialized;\\\\n\\\\n    /// @dev typehash for signed orders\\\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\\\n        keccak256(\\\\n            \\\\\\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\\\\\"\\\\n        );\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum FLASH_SOURCE {\\\\n        FLASH_DEPOSIT,\\\\n        FLASH_WITHDRAW\\\\n    }\\\\n\\\\n    /// @dev ETH:wSqueeth uniswap pool\\\\n    address public immutable ethWSqueethPool;\\\\n    /// @dev strategy uniswap oracle\\\\n    address public immutable oracle;\\\\n    address public immutable timelock;\\\\n    address public immutable crabMigration;\\\\n\\\\n    /// @dev time difference to trigger a hedge (seconds)\\\\n    uint256 public hedgeTimeThreshold;\\\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\\\n    uint256 public hedgePriceThreshold;\\\\n\\\\n    /// @dev timestamp when last hedge executed\\\\n    uint256 public timeAtLastHedge;\\\\n    /// @dev wSqueeth/Eth price when last hedge executed\\\\n    uint256 public priceAtLastHedge;\\\\n\\\\n    /// @dev set to true when redeemShortShutdown has been called\\\\n    bool private hasRedeemedInShutdown;\\\\n\\\\n    /// @dev store the used flag for a nonce for each address\\\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\\\n\\\\n    struct FlashDepositData {\\\\n        uint256 totalDeposit;\\\\n    }\\\\n\\\\n    struct FlashWithdrawData {\\\\n        uint256 crabAmount;\\\\n    }\\\\n\\\\n    struct Order {\\\\n        uint256 bidId;\\\\n        address trader;\\\\n        uint256 quantity;\\\\n        uint256 price;\\\\n        bool isBuying;\\\\n        uint256 expiry;\\\\n        uint256 nonce;\\\\n        uint8 v;\\\\n        bytes32 r;\\\\n        bytes32 s;\\\\n    }\\\\n\\\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\\\n    event HedgeOTCSingle(\\\\n        address trader,\\\\n        uint256 bidId,\\\\n        uint256 quantity,\\\\n        uint256 price,\\\\n        bool isBuying,\\\\n        uint256 clearingPrice\\\\n    );\\\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\\\n    event SetStrategyCap(uint256 newCapAmount);\\\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\\\n\\\\n    modifier onlyTimelock() {\\\\n        require(msg.sender == timelock, \\\\\\\"C1\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier afterInitialization() {\\\\n        require(isInitialized, \\\\\\\"C2\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy constructor\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _wSqueethController power token controller address\\\\n     * @param _oracle oracle address\\\\n     * @param _weth weth address\\\\n     * @param _uniswapFactory uniswap factory address\\\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\\\n     * @param _timelock timelock contract address\\\\n     * @param _crabMigration crab migration contract address\\\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\\\n     */\\\\n    constructor(\\\\n        address _wSqueethController,\\\\n        address _oracle,\\\\n        address _weth,\\\\n        address _uniswapFactory,\\\\n        address _ethWSqueethPool,\\\\n        address _timelock,\\\\n        address _crabMigration,\\\\n        uint256 _hedgeTimeThreshold,\\\\n        uint256 _hedgePriceThreshold\\\\n    )\\\\n        StrategyBase(_wSqueethController, _weth, \\\\\\\"Crab Strategy v2\\\\\\\", \\\\\\\"Crabv2\\\\\\\")\\\\n        StrategyFlashSwap(_uniswapFactory)\\\\n        EIP712(\\\\\\\"CrabOTC\\\\\\\", \\\\\\\"2\\\\\\\")\\\\n    {\\\\n        require(_oracle != address(0), \\\\\\\"C3\\\\\\\");\\\\n        require(_timelock != address(0), \\\\\\\"C4\\\\\\\");\\\\n        require(_ethWSqueethPool != address(0), \\\\\\\"C5\\\\\\\");\\\\n        require(_crabMigration != address(0), \\\\\\\"C6\\\\\\\");\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"C7\\\\\\\");\\\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\\\\\"C8\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        ethWSqueethPool = _ethWSqueethPool;\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n        timelock = _timelock;\\\\n        crabMigration = _crabMigration;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\\\\\"C9\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice initializes the collateral ratio after the first migration\\\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\\\n     * @param _crabSharesToMint crab shares to mint\\\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\\\n     * @param _strategyCap strategy cap for crab V2\\\\n     */\\\\n    function initialize(\\\\n        uint256 _wSqueethToMint,\\\\n        uint256 _crabSharesToMint,\\\\n        uint256 _timeAtLastHedge,\\\\n        uint256 _priceAtLastHedge,\\\\n        uint256 _strategyCap\\\\n    ) external payable {\\\\n        require(msg.sender == crabMigration, \\\\\\\"C10\\\\\\\");\\\\n        require(!isInitialized, \\\\\\\"C11\\\\\\\");\\\\n\\\\n        _setStrategyCap(_strategyCap);\\\\n\\\\n        uint256 amount = msg.value;\\\\n\\\\n        _checkStrategyCap(amount, 0);\\\\n\\\\n        // store hedge data from crab V1\\\\n        timeAtLastHedge = _timeAtLastHedge;\\\\n        priceAtLastHedge = _priceAtLastHedge;\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\\\n\\\\n        isInitialized = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice transfer vault NFT to new contract\\\\n     * @dev strategy cap is set to 0 to avoid future deposits\\\\n     * @param _newStrategy new strategy contract address\\\\n     */\\\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\\\n        _setStrategyCap(0);\\\\n\\\\n        emit VaultTransferred(_newStrategy, vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the strategy cap in ETH collateral terms\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\\\n        _setStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set strategy cap amount\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function _setStrategyCap(uint256 _capAmount) internal {\\\\n        strategyCap = _capAmount;\\\\n        emit SetStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to redeem the net value of a vault post shutdown\\\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\\\n     */\\\\n    function redeemShortShutdown() external afterInitialization {\\\\n        hasRedeemedInShutdown = true;\\\\n        powerTokenController.redeemShort(vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\\n     * @param _poolFee Uniswap pool fee\\\\n     */\\\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\\\n            _ethToDeposit,\\\\n            cachedStrategyDebt,\\\\n            cachedStrategyCollateral\\\\n        );\\\\n\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            _poolFee,\\\\n            wSqueethToMint,\\\\n            _ethToDeposit.sub(msg.value),\\\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\\\n            abi.encodePacked(_ethToDeposit)\\\\n        );\\\\n\\\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\\n     * @param _crabAmount strategy token amount to burn\\\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\\\n     * @param _poolFee Uniswap pool fee\\\\n\\\\n     */\\\\n    function flashWithdraw(\\\\n        uint256 _crabAmount,\\\\n        uint256 _maxEthToPay,\\\\n        uint24 _poolFee\\\\n    ) external nonReentrant {\\\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            _poolFee,\\\\n            exactWSqueethNeeded,\\\\n            _maxEthToPay,\\\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\\\n            abi.encodePacked(_crabAmount)\\\\n        );\\\\n\\\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit ETH into strategy\\\\n     * @dev provide ETH, return wSqueeth and strategy token\\\\n     */\\\\n    function deposit() external payable nonReentrant {\\\\n        uint256 amount = msg.value;\\\\n\\\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\\\n\\\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\\\n\\\\n        // send back ETH collateral\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n\\\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\\\n        require(powerTokenController.isShutDown(), \\\\\\\"C12\\\\\\\");\\\\n        require(hasRedeemedInShutdown, \\\\\\\"C13\\\\\\\");\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\\\n        _burn(msg.sender, _crabAmount);\\\\n\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set nonce to true\\\\n     * @param _nonce the number to be set true\\\\n     */\\\\n    function setNonceTrue(uint256 _nonce) external {\\\\n        nonces[msg.sender][_nonce] = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\\\n     * @param _crabAmount strategy token amount\\\\n     * @return wSqueeth amount\\\\n     */\\\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\\\n        return _getDebtFromStrategyAmount(_crabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\\\n     */\\\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\\\n        require(_hedgingTwapPeriod >= 180, \\\\\\\"C14\\\\\\\");\\\\n\\\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\\\n\\\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\\\n     */\\\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"C7\\\\\\\");\\\\n\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n\\\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\\\n     */\\\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\\\\\"C8\\\\\\\");\\\\n\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n\\\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\\\n     */\\\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\\\n        // Tolerance cannot be more than 20%\\\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\\\\\"C15\\\\\\\");\\\\n\\\\n        otcPriceTolerance = _otcPriceTolerance;\\\\n\\\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a user deposit puts the strategy above the cap\\\\n     * @dev reverts if a deposit amount puts strategy over the cap\\\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\\\n     * @param _depositAmount the user deposit amount in ETH\\\\n     * @param _strategyCollateral the updated strategy collateral\\\\n     */\\\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\\\\\"C16\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _strategyFlash(\\\\n        address _caller,\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        uint24 _fee,\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n\\\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\\\n            // will revert if data.totalDeposit is > eth balance in contract\\\\n            _deposit(_caller, data.totalDeposit, true);\\\\n\\\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\\\n\\\\n            // repay the flash swap\\\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\\\n\\\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\\\n\\\\n            // return excess eth to the user that was not needed for slippage\\\\n            if (address(this).balance > 0) {\\\\n                payable(_caller).sendValue(address(this).balance);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\\\n\\\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\\\n            uint256 ethToWithdraw = _withdraw(\\\\n                _caller,\\\\n                data.crabAmount,\\\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\\\n                true\\\\n            );\\\\n\\\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\\\n\\\\n            // use some amount of withdrawn ETH to repay flash swap\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\\\n\\\\n            // excess ETH not used to repay flash swap is transferred to the user\\\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\\\n\\\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\\\n\\\\n            if (proceeds > 0) {\\\\n                payable(_caller).sendValue(proceeds);\\\\n            }\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit into strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _depositor depositor address\\\\n     * @param _amount amount of ETH collateral to deposit\\\\n     * @param _isFlashDeposit true if called by flashDeposit\\\\n     * @return wSqueethToMint minted amount of WSqueeth\\\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\\\n     */\\\\n    function _deposit(\\\\n        address _depositor,\\\\n        uint256 _amount,\\\\n        bool _isFlashDeposit\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_amount, strategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\\\n\\\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\\\n\\\\n        return (wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\\\n     * @return ETH amount to withdraw\\\\n     */\\\\n    function _withdraw(\\\\n        address _from,\\\\n        uint256 _crabAmount,\\\\n        uint256 _wSqueethAmount,\\\\n        bool _isFlashWithdraw\\\\n    ) internal returns (uint256) {\\\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\\\n\\\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\\\n        _burn(_from, _crabAmount);\\\\n\\\\n        return ethToWithdraw;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev set nonce flag of the trader to true\\\\n     * @param _trader address of the signer\\\\n     * @param _nonce number that is to be traded only once\\\\n     */\\\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\\\n        require(!nonces[_trader][_nonce], \\\\\\\"C27\\\\\\\");\\\\n        nonces[_trader][_nonce] = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev view function to get the domain seperator used in signing\\\\n     */\\\\n    // solhint-disable-next-line func-name-mixedcase\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\\\n        return _domainSeparatorV4();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev check the signer and swap tokens in the order\\\\n     * @param _remainingAmount quantity the manager wants to trade\\\\n     * @param _clearingPrice the price at which all orders are traded\\\\n     * @param _order a signed order to swap tokens\\\\n     */\\\\n    function _execOrder(\\\\n        uint256 _remainingAmount,\\\\n        uint256 _clearingPrice,\\\\n        Order memory _order\\\\n    ) internal {\\\\n        // check that order beats clearing price\\\\n        if (_order.isBuying) {\\\\n            require(_clearingPrice <= _order.price, \\\\\\\"C17\\\\\\\");\\\\n        } else {\\\\n            require(_clearingPrice >= _order.price, \\\\\\\"C18\\\\\\\");\\\\n        }\\\\n\\\\n        _useNonce(_order.trader, _order.nonce);\\\\n        bytes32 structHash = keccak256(\\\\n            abi.encode(\\\\n                _CRAB_BALANCE_TYPEHASH,\\\\n                _order.bidId,\\\\n                _order.trader,\\\\n                _order.quantity,\\\\n                _order.price,\\\\n                _order.isBuying,\\\\n                _order.expiry,\\\\n                _order.nonce\\\\n            )\\\\n        );\\\\n\\\\n        bytes32 hash = _hashTypedDataV4(structHash);\\\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\\\n        require(offerSigner == _order.trader, \\\\\\\"C19\\\\\\\");\\\\n        require(_order.expiry >= block.timestamp, \\\\\\\"C20\\\\\\\");\\\\n\\\\n        // adjust quantity for partial fills\\\\n        if (_remainingAmount < _order.quantity) {\\\\n            _order.quantity = _remainingAmount;\\\\n        }\\\\n        // weth clearing price for the order\\\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\\\n\\\\n        if (_order.isBuying) {\\\\n            // trader sends weth and receives oSQTH\\\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\\\n            IWETH9(weth).withdraw(wethAmount);\\\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\\\n        } else {\\\\n            // trader sends oSQTH and receives weth\\\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\\\n            // wrap it\\\\n            IWETH9(weth).deposit{value: wethAmount}();\\\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\\\n        }\\\\n\\\\n        emit HedgeOTCSingle(\\\\n            _order.trader, // market maker\\\\n            _order.bidId,\\\\n            _order.quantity, // order oSQTH quantity\\\\n            _order.price, // order price\\\\n            _order.isBuying, // order direction\\\\n            _clearingPrice // executed price for order\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev hedge function to reduce delta using an array of signed orders\\\\n     * @param _totalQuantity quantity the manager wants to trade\\\\n     * @param _clearingPrice clearing price in weth\\\\n     * @param _isHedgeBuying direction of hedge trade\\\\n     * @param _orders an array of signed order to swap tokens\\\\n     */\\\\n    function hedgeOTC(\\\\n        uint256 _totalQuantity,\\\\n        uint256 _clearingPrice,\\\\n        bool _isHedgeBuying,\\\\n        Order[] memory _orders\\\\n    ) external onlyOwner afterInitialization {\\\\n        require(_clearingPrice > 0, \\\\\\\"C21\\\\\\\");\\\\n        require(_isTimeHedge() || _isPriceHedge(), \\\\\\\"C22\\\\\\\");\\\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\\\n\\\\n        timeAtLastHedge = block.timestamp;\\\\n        priceAtLastHedge = _clearingPrice;\\\\n\\\\n        uint256 remainingAmount = _totalQuantity;\\\\n        uint256 prevPrice = _orders[0].price;\\\\n        uint256 currentPrice = _orders[0].price;\\\\n        bool isOrderBuying = _orders[0].isBuying;\\\\n        require(_isHedgeBuying != isOrderBuying, \\\\\\\"C23\\\\\\\");\\\\n\\\\n        // iterate through order array and execute if valid\\\\n        for (uint256 i; i < _orders.length; ++i) {\\\\n            currentPrice = _orders[i].price;\\\\n            require(_orders[i].isBuying == isOrderBuying, \\\\\\\"C24\\\\\\\");\\\\n            if (_isHedgeBuying) {\\\\n                require(currentPrice >= prevPrice, \\\\\\\"C25\\\\\\\");\\\\n            } else {\\\\n                require(currentPrice <= prevPrice, \\\\\\\"C25\\\\\\\");\\\\n            }\\\\n            prevPrice = currentPrice;\\\\n\\\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\\\n\\\\n            if (remainingAmount > _orders[i].quantity) {\\\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\\\n            } else {\\\\n                break;\\\\n            }\\\\n        }\\\\n\\\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\\\n     * @param _price clearing price provided by manager\\\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\\\n     */\\\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\\\n        // Get twap\\\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\\\n\\\\n        if (_isHedgeBuying) {\\\\n            require(\\\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\\\n                \\\\\\\"Price too high relative to Uniswap twap.\\\\\\\"\\\\n            );\\\\n        } else {\\\\n            require(\\\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\\\n                \\\\\\\"Price too low relative to Uniswap twap.\\\\\\\"\\\\n            );\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sync strategy debt and collateral amount from vault\\\\n     * @return synced debt amount\\\\n     * @return synced collateral amount\\\\n     */\\\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\\\n\\\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\\\n     * @return the fee adjustment factor\\\\n     */\\\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\\\n            oracle,\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            POWER_PERP_PERIOD,\\\\n            false\\\\n        );\\\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\\\n     * @param _depositedAmount amount of deposited WETH\\\\n     * @param _strategyDebtAmount amount of strategy debt\\\\n     * @param _strategyCollateralAmount collateral amount in strategy\\\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\\\n     */\\\\n    function _calcWsqueethToMintAndFee(\\\\n        uint256 _depositedAmount,\\\\n        uint256 _strategyDebtAmount,\\\\n        uint256 _strategyCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 wSqueethToMint;\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\\\n        require(!isShutdown, \\\\\\\"C26\\\\\\\");\\\\n\\\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\\\n        );\\\\n\\\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\\\n\\\\n        return (wSqueethToMint, fee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if time hedging is allowed\\\\n     */\\\\n    function _isTimeHedge() internal view returns (bool) {\\\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function _isPriceHedge() internal view returns (bool) {\\\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\\\n\\\\n        return priceThreshold >= hedgePriceThreshold;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkPriceHedge() external view returns (bool) {\\\\n        return _isPriceHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkTimeHedge() external view returns (bool) {\\\\n        return _isTimeHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate amount of strategy token to mint for depositor\\\\n     * @param _amount amount of ETH deposited\\\\n     * @param _strategyCollateralAmount amount of strategy collateral\\\\n     * @param _crabTotalSupply total supply of strategy token\\\\n     * @return amount of strategy token to mint\\\\n     */\\\\n    function _calcSharesToMint(\\\\n        uint256 _amount,\\\\n        uint256 _strategyCollateralAmount,\\\\n        uint256 _crabTotalSupply\\\\n    ) internal pure returns (uint256) {\\\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\\\n\\\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\\\n\\\\n        return _amount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\\\n     * @param _crabAmount strategy token amount\\\\n     * @param _totalSupply strategy total supply\\\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\\\n     */\\\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\\\n        return _crabAmount.wdiv(_totalSupply);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\\\n     * @param _crabRatio crab ratio\\\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\\\n     * @return amount of ETH allowed to withdraw\\\\n     */\\\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8b1900ce7c5c79e38af489819462339a27d677e2bb8626f7aa6f784409cbf3fa\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyBase.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./StrategyMath.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../../libs/VaultLib.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev StrategyBase contract\\\\n * @notice base contract for PowerToken strategy\\\\n * @author opyn team\\\\n */\\\\ncontract StrategyBase is ERC20 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev power token controller\\\\n    IController public powerTokenController;\\\\n\\\\n    /// @dev WETH token\\\\n    address public immutable weth;\\\\n    address public immutable wPowerPerp;\\\\n\\\\n    /// @dev power token strategy vault ID\\\\n    uint256 public immutable vaultId;\\\\n\\\\n    /**\\\\n     * @notice constructor for StrategyBase\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _powerTokenController power token controller address\\\\n     * @param _weth weth token address\\\\n     * @param _name token name for strategy ERC20 token\\\\n     * @param _symbol token symbol for strategy ERC20 token\\\\n     */\\\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\\\n        require(_powerTokenController != address(0), \\\\\\\"invalid controller address\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"invalid weth address\\\\\\\");\\\\n\\\\n        weth = _weth;\\\\n        powerTokenController = IController(_powerTokenController);\\\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\\\n    }\\\\n    /**\\\\n     * @notice get power token strategy vault ID \\\\n     * @return vault ID\\\\n     */\\\\n    function getStrategyVaultId() external view returns (uint256) {\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n    */\\\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\\\n        return _getVaultDetails();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint WPowerPerp and deposit collateral\\\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\\\n     * @param _to receiver address\\\\n     * @param _wAmount amount of WPowerPerp to mint\\\\n     * @param _collateral amount of collateral to deposit\\\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\\\n     */\\\\n    function _mintWPowerPerp(\\\\n        address _to,\\\\n        uint256 _wAmount,\\\\n        uint256 _collateral,\\\\n        bool _keepWsqueeth\\\\n    ) internal {\\\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\\\n\\\\n        if (!_keepWsqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn WPowerPerp and withdraw collateral\\\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\\\n     * @param _from WPowerPerp holder address\\\\n     * @param _amount amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\\\n     */\\\\n    function _burnWPowerPerp(\\\\n        address _from,\\\\n        uint256 _amount,\\\\n        uint256 _collateralToWithdraw,\\\\n        bool _isOwnedWSqueeth\\\\n    ) internal {\\\\n        if (!_isOwnedWSqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\\\n        }\\\\n\\\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint strategy token\\\\n     * @param _to recepient address\\\\n     * @param _amount token amount\\\\n     */\\\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\\\n        _mint(_to, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get strategy debt amount for a specific strategy token amount\\\\n     * @param _strategyAmount strategy amount\\\\n     * @return debt amount\\\\n     */\\\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n     */\\\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\\\n\\\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\\\n    }\\\\n}\\\\n\\\\n\\\",\\\"keccak256\\\":\\\"0xa18ad4c34899e27bdf048a866834e05dda91ee8ff904fac23587dddf69a5d675\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyFlashSwap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\\\n\\\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\\\n    using Path for bytes;\\\\n    using SafeCast for uint256;\\\\n    using LowGasSafeMath for uint256;\\\\n    using LowGasSafeMath for int256;\\\\n\\\\n    /// @dev Uniswap factory address\\\\n    address public immutable factory;\\\\n\\\\n    struct SwapCallbackData {\\\\n        bytes path;\\\\n        address caller;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev constructor\\\\n     * @param _factory uniswap factory address\\\\n     */\\\\n    constructor(\\\\n        address _factory\\\\n    ) {\\\\n        require(_factory != address(0), \\\\\\\"invalid factory address\\\\\\\");\\\\n        factory = _factory;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap swap callback function for flashes\\\\n     * @param amount0Delta amount of token0\\\\n     * @param amount1Delta amount of token1\\\\n     * @param _data callback data encoded as SwapCallbackData struct\\\\n     */\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata _data\\\\n    ) external override {\\\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\\\n\\\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //ensure that callback comes from uniswap pool\\\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\\\n\\\\n        //determine the amount that needs to be repaid as part of the flashswap\\\\n        uint256 amountToPay =\\\\n            amount0Delta > 0\\\\n                ?  uint256(amount0Delta)\\\\n                :  uint256(amount1Delta);\\\\n        \\\\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountIn amount to sell\\\\n     * @param _amountOutMinimum minimum amount to receive\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountOut = _exactInputInternal(\\\\n            _amountIn,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n       \\\\n        //slippage limit check\\\\n        require(amountOut >= _amountOutMinimum, \\\\\\\"amount out less than min\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountOut exact amount to receive\\\\n     * @param _amountInMaximum maximum amount to sell\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountIn = _exactOutputInternal(\\\\n            _amountOut,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n        \\\\n        //slippage limit check\\\\n        require(amountIn <= _amountInMaximum, \\\\\\\"amount in greater than max\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice function to be called by uniswap callback. \\\\n     * @dev this function should be overridden by the child contract\\\\n     * param _caller initial strategy function caller\\\\n     * param _tokenIn token address sold\\\\n     * param _tokenOut token address bought\\\\n     * param _fee pool fee\\\\n     * param _amountToPay amount to pay for the pool second token\\\\n     * param _callData arbitrary data assigned with the flashswap call \\\\n     * param _callSource function call source\\\\n     */\\\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\\\n    \\\\n    /** \\\\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\\\n    * @param _amountIn amount of token to pay\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token bought (amountOut)\\\\n    */\\\\n    function _exactInputInternal(\\\\n        uint256 _amountIn,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n       \\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0, int256 amount1) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                _amountIn.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n        \\\\n        //determine the amountOut based on which token has a lower address\\\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\\\n    * @param _amountOut amount of token to receive\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token sold (amountIn)\\\\n    */\\\\n    function _exactOutputInternal(\\\\n        uint256 _amountOut,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n        \\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0Delta, int256 amount1Delta) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                -_amountOut.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n\\\\n        //determine the amountIn and amountOut based on which token has a lower address\\\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\\\n        // it's technically possible to not receive the full output amount,\\\\n        // so if no price limit has been specified, require this possibility away\\\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\\\n\\\\n        return amountIn;\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice returns the uniswap pool for the given token pair and fee\\\\n    * @dev the pool contract may or may not exist\\\\n    * @param tokenA address of first token \\\\n    * @param tokenB address of second token \\\\n    * @param fee fee tier for pool\\\\n    */\\\\n    function _getPool(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool) {\\\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x91b49caf229fd114fbb589e73056772cf15a0adaba0a6f5eca4dff9cd12b9575\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/base/StrategyMath.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: AGPL-3.0-only\\\\n\\\\n/// math.sol -- mixin for inline numerical wizardry\\\\n\\\\n// This program is free software: you can redistribute it and/or modify\\\\n// it under the terms of the GNU General Public License as published by\\\\n// the Free Software Foundation, either version 3 of the License, or\\\\n// (at your option) any later version.\\\\n\\\\n// This program is distributed in the hope that it will be useful,\\\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\\\n// GNU General Public License for more details.\\\\n\\\\n// You should have received a copy of the GNU General Public License\\\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\\\n\\\\npragma solidity >0.4.13;\\\\n\\\\n\\\\n/**\\\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\\\n * @dev change contract to library, added div() function\\\\n */\\\\nlibrary StrategyMath {\\\\n    function add(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x + y) >= x, \\\\\\\"ds-math-add-overflow\\\\\\\");\\\\n    }\\\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x - y) <= x, \\\\\\\"ds-math-sub-underflow\\\\\\\");\\\\n    }\\\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\\\n        require(y == 0 || (z = x * y) / y == x, \\\\\\\"ds-math-mul-overflow\\\\\\\");\\\\n    }\\\\n\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    function min(uint x, uint y) internal pure returns (uint z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function max(uint x, uint y) internal pure returns (uint z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n    function imin(int x, int y) internal pure returns (int z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function imax(int x, int y) internal pure returns (int z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n\\\\n    uint constant WAD = 10 ** 18;\\\\n    uint constant RAY = 10 ** 27;\\\\n\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), WAD / 2) / WAD;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), RAY / 2) / RAY;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, WAD), y / 2) / y;\\\\n    }\\\\n    //rounds to zero if x*y < RAY / 2\\\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, RAY), y / 2) / y;\\\\n    }\\\\n\\\\n    // Ceil A to a multiple m\\\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(sub(add(a, m), 1), m), m);\\\\n    }\\\\n\\\\n    // Floor A to a multiple m\\\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(a, m), m);\\\\n    }\\\\n\\\\n    // This famous algorithm is called \\\\\\\"exponentiation by squaring\\\\\\\"\\\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\\\n    //\\\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\\\n    //\\\\n    // These facts are why it works:\\\\n    //\\\\n    //  If n is even, then x^n = (x^2)^(n/2).\\\\n    //  If n is odd,  then x^n = x * x^(n-1),\\\\n    //   and applying the equation for even x gives\\\\n    //    x^n = x * (x^2)^((n-1) / 2).\\\\n    //\\\\n    //  Also, EVM division is flooring and\\\\n    //    floor[(n-1) / 2] = floor[n / 2].\\\\n    //\\\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\\\n        z = n % 2 != 0 ? x : RAY;\\\\n\\\\n        for (n /= 2; n != 0; n /= 2) {\\\\n            x = rmul(x, x);\\\\n\\\\n            if (n % 2 != 0) {\\\\n                z = rmul(z, x);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0xfec6fa07fbbb639f94321d6503f5363286776cf831215017ce28aae67295613b\\\",\\\"license\\\":\\\"AGPL-3.0-only\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101206040523480156200001257600080fd5b5060405162003b3e38038062003b3e8339810160408190526200003591620003a3565b60006200004162000379565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b038316620000bd5760405162461bcd60e51b8152600401620000b49062000511565b60405180910390fd5b6001600160a01b038216620000e65760405162461bcd60e51b8152600401620000b49062000494565b6001600160a01b0381166200010f5760405162461bcd60e51b8152600401620000b4906200045d565b6001600160a01b038416620001385760405162461bcd60e51b8152600401620000b4906200057f565b6001600160a01b038516620001615760405162461bcd60e51b8152600401620000b49062000548565b836001600160a01b0316826001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b158015620001a557600080fd5b505afa158015620001ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001e091906200037d565b6001600160a01b031614620002095760405162461bcd60e51b8152600401620000b490620004cb565b600280546001600160a01b03808816610100908102610100600160a81b031990931692909217928390556001600160601b0319606087811b821660805285811b821660c05288811b821660a05286901b1660e052604080516307f07b1360e41b81529051929093041691637f07b130916004808301926020929190829003018186803b1580156200029957600080fd5b505afa158015620002ae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002d491906200037d565b60601b6001600160601b0319166101005260405163095ea7b360e01b81526001600160a01b0385169063095ea7b390620003179084906000199060040162000444565b602060405180830381600087803b1580156200033257600080fd5b505af115801562000347573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200036d919062000422565b505050505050620005cf565b3390565b6000602082840312156200038f578081fd5b81516200039c81620005b6565b9392505050565b600080600080600060a08688031215620003bb578081fd5b8551620003c881620005b6565b6020870151909550620003db81620005b6565b6040870151909450620003ee81620005b6565b60608701519093506200040181620005b6565b60808701519092506200041481620005b6565b809150509295509295909350565b60006020828403121562000434578081fd5b815180151581146200039c578182fd5b6001600160a01b03929092168252602082015260400190565b6020808252601d908201527f696e76616c6964205f65756c65724d61696e6e65742061646472657373000000604082015260600190565b60208082526017908201527f696e76616c6964205f64546f6b656e2061646472657373000000000000000000604082015260600190565b60208082526026908201527f64546f6b656e20756e6465726c79696e672061737365742073686f756c6420626040820152650ca40eecae8d60d31b606082015260800190565b6020808252601a908201527f696e76616c6964205f65756c6572457865632061646472657373000000000000604082015260600190565b60208082526017908201527f696e76616c6964205f6372616276312061646472657373000000000000000000604082015260600190565b60208082526015908201527f696e76616c6964205f7765746820616464726573730000000000000000000000604082015260600190565b6001600160a01b0381168114620005cc57600080fd5b50565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6134e46200065a60003980611c175280611ef052806121945280612572528061261652806129b1525080610d915280610f29525080610d1f52508061015852806105575280610e155280610e995250806105eb52806108665280610be5528061139552506134e46000f3fe6080604052600436106101485760003560e01c8063a15db5c5116100c0578063cb9d1ab811610074578063db661b7111610059578063db661b71146103d2578063f2fde38b146103e7578063fe7dd6e414610407576101cf565b8063cb9d1ab814610392578063d2cebf9b146103b2576101cf565b8063bab89ea3116100a5578063bab89ea31461032d578063bbac0aca14610342578063bbca7f1e14610362576101cf565b8063a15db5c5146102eb578063b06faf621461030b576101cf565b8063715018a6116101175780638da5cb5b116100fc5780638da5cb5b146102965780638e953732146102ab578063a13d7b33146102cb576101cf565b8063715018a61461026c5780637fa8c37014610281576101cf565b8063139d3799146101d45780631d4dab2c146101f45780633fc8cef31461022a578063581e74781461024c576101cf565b366101cf57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610193575060025461010090046001600160a01b031633145b806101a857506003546001600160a01b031633145b6101cd5760405162461bcd60e51b81526004016101c490613230565b60405180910390fd5b005b600080fd5b3480156101e057600080fd5b506101cd6101ef366004612ff6565b61041c565b34801561020057600080fd5b5061021461020f366004612d22565b610543565b6040516102219190613343565b60405180910390f35b34801561023657600080fd5b5061023f610555565b60405161022191906130a6565b34801561025857600080fd5b506101cd610267366004612ff6565b610579565b34801561027857600080fd5b506101cd6106dc565b34801561028d57600080fd5b5061023f6107a7565b3480156102a257600080fd5b5061023f6107bb565b3480156102b757600080fd5b506101cd6102c636600461302e565b6107ca565b3480156102d757600080fd5b506101cd6102e6366004612fc6565b61095e565b3480156102f757600080fd5b506101cd610306366004612d9c565b610cec565b34801561031757600080fd5b50610320610f97565b6040516102219190613119565b34801561033957600080fd5b506101cd610fa0565b34801561034e57600080fd5b506101cd61035d366004612d22565b61109f565b34801561036e57600080fd5b5061038261037d366004612fc6565b611168565b6040516102219493929190613124565b34801561039e57600080fd5b506101cd6103ad366004612fc6565b611186565b3480156103be57600080fd5b506101cd6103cd366004612fc6565b611282565b3480156103de57600080fd5b5061023f611393565b3480156103f357600080fd5b506101cd610402366004612d22565b6113b7565b34801561041357600080fd5b5061023f6114d8565b60025460ff1661043e5760405162461bcd60e51b81526004016101c49061324c565b336000908152600160205260409020548084111561046e5760405162461bcd60e51b81526004016101c49061316b565b61047881856114e7565b3360009081526001602052604090819020919091556003549051630b52b7ff60e41b81526001600160a01b039091169063b52b7ff0906104c09087908790879060040161335f565b600060405180830381600087803b1580156104da57600080fd5b505af11580156104ee573d6000803e3d6000fd5b50505050336001600160a01b03167f38d6d922c6452f3aaf90ad851ed15eb4c5c613c745d0531cf4337c07de651bab8560405161052b9190613343565b60405180910390a261053d3347611545565b50505050565b60016020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60025460ff1661059b5760405162461bcd60e51b81526004016101c49061324c565b60008060006105a98661162f565b50925092509250826105cd5760405162461bcd60e51b81526004016101c4906131bf565b60408051608081018252338152602081018490526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916389b7b7a69130918101600160ff16815260200160405180608001604052808781526020018b81526020018c81526020018a62ffffff1681525060405160200161065691906132ce565b60408051601f1981840301815291815291525161067691906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016106a29291906130de565b600060405180830381600087803b1580156106bc57600080fd5b505af11580156106d0573d6000803e3d6000fd5b50505050505050505050565b6106e46118d3565b6001600160a01b03166106f56107bb565b6001600160a01b031614610750576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b60025461010090046001600160a01b031681565b6000546001600160a01b031690565b60025460ff166107ec5760405162461bcd60e51b81526004016101c49061324c565b6000806107f88761162f565b509250509150811561081c5760405162461bcd60e51b81526004016101c4906131f7565b60008511801561082c5750600084115b6108485760405162461bcd60e51b81526004016101c490613187565b60408051608081018252338152602081018790526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916389b7b7a69130918101600260ff1681526020016040518060a001604052808781526020018c81526020018a81526020018d81526020018962ffffff168152506040516020016108d7919061328f565b60408051601f198184030181529181529152516108f791906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016109239291906130de565b600060405180830381600087803b15801561093d57600080fd5b505af1158015610951573d6000803e3d6000fd5b5050505050505050505050565b6109666118d3565b6001600160a01b03166109776107bb565b6001600160a01b0316146109d2576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6003546001600160a01b03166109fa5760405162461bcd60e51b81526004016101c490613268565b60025460ff1615610a1d5760405162461bcd60e51b81526004016101c490613214565b6002805460ff1916600117908190556040516370a0823160e01b81526000916001600160a01b0361010090910416906370a0823190610a609030906004016130a6565b60206040518083038186803b158015610a7857600080fd5b505afa158015610a8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab09190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b0257600080fd5b505afa158015610b16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3a9190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b158015610b8c57600080fd5b505afa158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc49190612d3e565b50925060009150610be19050610bda85856118d7565b8390611908565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060800160405280336001600160a01b0316815260200185815260200160006002811115610c4057fe5b60ff16815260200160405180602001604052808b815250604051602001610c679190613285565b60408051601f19818403018152918152915251610c8791906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610cb39291906130de565b600060405180830381600087803b158015610ccd57600080fd5b505af1158015610ce1573d6000803e3d6000fd5b505050505050505050565b6003546001600160a01b0316610d145760405162461bcd60e51b81526004016101c490613268565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d5c5760405162461bcd60e51b81526004016101c4906131a3565b600081806020019051810190610d729190612f1f565b6020810151604051630ecbcdab60e01b81529192506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691630ecbcdab91610dc89160009190600401613141565b600060405180830381600087803b158015610de257600080fd5b505af1158015610df6573d6000803e3d6000fd5b5050506020820151604051632e1a7d4d60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250632e1a7d4d91610e4991600401613343565b600060405180830381600087803b158015610e6357600080fd5b505af1158015610e77573d6000803e3d6000fd5b50505050610e978160000151826020015183604001518460600151611930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db082602001516040518263ffffffff1660e01b81526004016000604051808303818588803b158015610ef657600080fd5b505af1158015610f0a573d6000803e3d6000fd5b505050602083015160405163d8aed14560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063d8aed1459250610f6191600091600401613141565b600060405180830381600087803b158015610f7b57600080fd5b505af1158015610f8f573d6000803e3d6000fd5b505050505050565b60025460ff1681565b60025460ff16610fc25760405162461bcd60e51b81526004016101c49061324c565b336000818152600160205260408082208054929055600354905163a9059cbb60e01b815291926001600160a01b039091169163a9059cbb91611008918590600401613100565b602060405180830381600087803b15801561102257600080fd5b505af1158015611036573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105a9190612d7c565b50336001600160a01b03167f0adef25f8a7a2d6f3fb9761ba0c96c9752b6d985abd47e23b7fa3095ba8e4701826040516110949190613343565b60405180910390a250565b6110a76118d3565b6001600160a01b03166110b86107bb565b6001600160a01b031614611113576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166111395760405162461bcd60e51b81526004016101c4906131db565b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000806000806111778561162f565b93509350935093509193509193565b60025460ff16156111a95760405162461bcd60e51b81526004016101c490613214565b336000818152600160205260409081902080548401905560025490516323b872dd60e01b81526101009091046001600160a01b0316916323b872dd916111f69190309086906004016130ba565b602060405180830381600087803b15801561121057600080fd5b505af1158015611224573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112489190612d7c565b50336001600160a01b03167fcbfc37edaa5ac30951b21b47b70bbb70dd1e015fa918da25d516798c6a2622e8826040516110949190613343565b60025460ff16156112a55760405162461bcd60e51b81526004016101c490613214565b336000908152600160205260409020546112bf90826114e7565b336000818152600160205260409081902092909255600254915163a9059cbb60e01b81526101009092046001600160a01b03169163a9059cbb91611307918590600401613100565b602060405180830381600087803b15801561132157600080fd5b505af1158015611335573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113599190612d7c565b50336001600160a01b03167ffdef8f0daac171c9b3f7896ae8991c11b88b64b1b76b574d8189dcd0357e5f6e826040516110949190613343565b7f000000000000000000000000000000000000000000000000000000000000000081565b6113bf6118d3565b6001600160a01b03166113d06107bb565b6001600160a01b03161461142b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166114705760405162461bcd60e51b815260040180806020018281038252602681526020018061344f6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6003546001600160a01b031681565b8082038281111561153f576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b92915050565b8047101561159a576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146115e5576040519150601f19603f3d011682016040523d82523d6000602084013e6115ea565b606091505b505090508061162a5760405162461bcd60e51b815260040180806020018281038252603a815260200180613475603a913960400191505060405180910390fd5b505050565b600080600080600080600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561168657600080fd5b505afa15801561169a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116be9190612d3e565b935093505050600080600360009054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561171557600080fd5b505afa158015611729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174d9190612d3e565b93509350505060006117ee600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156117a657600080fd5b505afa1580156117ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117de9190612fde565b6117e8868d611908565b906118d7565b90506000633b9aca006118158161180f86611809878a611908565b90612b43565b90612b5f565b8161181c57fe5b04905060006118bb876118b5600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561187657600080fd5b505afa15801561188a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ae9190612fde565b8f906118d7565b90611908565b808311159d929c50929a509198509650505050505050565b3390565b6000816118f96118ef85670de0b6b3a7640000612b8e565b6002855b04612bfa565b8161190057fe5b049392505050565b6000670de0b6b3a76400006118f96119208585612b8e565b6002670de0b6b3a76400006118f3565b60008260ff16600281111561194157fe5b600281111561194c57fe5b1415611d1f576000818060200190518101906119689190612e10565b6002546040516370a0823160e01b81529192506000916101009091046001600160a01b0316906370a08231906119a29030906004016130a6565b60206040518083038186803b1580156119ba57600080fd5b505afa1580156119ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f29190612fde565b60025460405163f73e19c360e01b81529192506000916101009091046001600160a01b03169063f73e19c390611a2c908590600401613343565b60206040518083038186803b158015611a4457600080fd5b505afa158015611a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7c9190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166367b8c3456040518163ffffffff1660e01b815260040160206040518083038186803b158015611ace57600080fd5b505afa158015611ae2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b069190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166363bbc4b66040518163ffffffff1660e01b815260040160206040518083038186803b158015611b5857600080fd5b505afa158015611b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b909190612fde565b6003548651604051631b9756c160e31b81529293506001600160a01b039091169163dcbab608918b91611bce9188918a918991899190600401613390565b6000604051808303818588803b158015611be757600080fd5b505af1158015611bfb573d6000803e3d6000fd5b505060025460405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116955063095ea7b39450611c5c93506101009092049091169060001990600401613100565b602060405180830381600087803b158015611c7657600080fd5b505af1158015611c8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cae9190612d7c565b50600254604051632e1a7d4d60e01b81526101009091046001600160a01b031690632e1a7d4d90611ce3908790600401613343565b600060405180830381600087803b158015611cfd57600080fd5b505af1158015611d11573d6000803e3d6000fd5b50505050505050505061053d565b60018260ff166002811115611d3057fe5b6002811115611d3b57fe5b1415612317576003546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611d729030906004016130a6565b60206040518083038186803b158015611d8a57600080fd5b505afa158015611d9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc29190612fde565b9050600082806020019051810190611dda9190612eba565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e2c57600080fd5b505af1158015611e40573d6000803e3d6000fd5b505060025460408581015190516323b872dd60e01b81526101009092046001600160a01b031694506323b872dd9350611e8192508a913091906004016130ba565b602060405180830381600087803b158015611e9b57600080fd5b505af1158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190612d7c565b50600254815160405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169363095ea7b393611f2f936101009092049092169190600401613100565b602060405180830381600087803b158015611f4957600080fd5b505af1158015611f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f819190612d7c565b506002546040828101519051632e1a7d4d60e01b81526101009092046001600160a01b031691632e1a7d4d91611fb991600401613343565b600060405180830381600087803b158015611fd357600080fd5b505af1158015611fe7573d6000803e3d6000fd5b5050505060208101511561206a576003546001600160a01b031663fc5b73ff61201047886114e7565b836020015184606001516040518463ffffffff1660e01b815260040161203792919061334c565b6000604051808303818588803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b50505050505b6003546040516370a0823160e01b81526000916120f79185916001600160a01b0316906370a08231906120a19030906004016130a6565b60206040518083038186803b1580156120b957600080fd5b505afa1580156120cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f19190612fde565b906114e7565b60035460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb9061212a908a908590600401613100565b602060405180830381600087803b15801561214457600080fd5b505af1158015612158573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217c9190612d7c565b506040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90899083906370a08231906121d39030906004016130a6565b60206040518083038186803b1580156121eb57600080fd5b505afa1580156121ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122239190612fde565b6040518363ffffffff1660e01b8152600401612240929190613100565b602060405180830381600087803b15801561225a57600080fd5b505af115801561226e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122929190612d7c565b50604082015147906001600160a01b038916907fa1b94934d9119aa101df2e94f736d2cff64c4d7db8706c9b5bb1ffa265842f8990846122d2858c6114e7565b6040516122e19392919061337a565b60405180910390a28681111561230e5761230e6122fe82896114e7565b6001600160a01b038a1690611545565b5050505061053d565b60028260ff16600281111561232857fe5b600281111561233357fe5b141561053d576003546040516370a0823160e01b81526000916001600160a01b0316906370a082319061236a9030906004016130a6565b60206040518083038186803b15801561238257600080fd5b505afa158015612396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ba9190612fde565b90506000828060200190518101906123d29190612e4b565b90506000600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561242457600080fd5b505afa158015612438573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245c9190612d3e565b60025460608701516040516323b872dd60e01b81529296506101009091046001600160a01b031694506323b872dd935061249e92508b913091906004016130ba565b602060405180830381600087803b1580156124b857600080fd5b505af11580156124cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f09190612d7c565b50600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b15801561254157600080fd5b505af1158015612555573d6000803e3d6000fd5b50506040516370a0823160e01b8152600093506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692506370a0823191506125a99030906004016130a6565b60206040518083038186803b1580156125c157600080fd5b505afa1580156125d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f99190612fde565b60025460405163095ea7b360e01b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263095ea7b3926126549261010090910416908590600401613100565b602060405180830381600087803b15801561266e57600080fd5b505af1158015612682573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126a69190612d7c565b50600061273d83611809600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126fe57600080fd5b505afa158015612712573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127369190612fde565b8590611908565b90506000633b9aca006127508382612c52565b8161275757fe5b600254604051632e1a7d4d60e01b815292909104925061010090046001600160a01b031690632e1a7d4d90612790908490600401613343565b600060405180830381600087803b1580156127aa57600080fd5b505af11580156127be573d6000803e3d6000fd5b505060025460608801516101009091046001600160a01b031692506323ccafd991506127ea90846114e7565b87604001516040518363ffffffff1660e01b815260040161280c929190613141565b600060405180830381600087803b15801561282657600080fd5b505af115801561283a573d6000803e3d6000fd5b505050508847101561285e5760405162461bcd60e51b81526004016101c49061314f565b6020850151156128dd576003546001600160a01b031663fc5b73ff612883478c6114e7565b876020015188608001516040518463ffffffff1660e01b81526004016128aa92919061334c565b6000604051808303818588803b1580156128c357600080fd5b505af11580156128d7573d6000803e3d6000fd5b50505050505b6003546040516370a0823160e01b81526000916129149189916001600160a01b0316906370a08231906120a19030906004016130a6565b60035460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb90612947908e908590600401613100565b602060405180830381600087803b15801561296157600080fd5b505af1158015612975573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129999190612d7c565b506040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb908d9083906370a08231906129f09030906004016130a6565b60206040518083038186803b158015612a0857600080fd5b505afa158015612a1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a409190612fde565b6040518363ffffffff1660e01b8152600401612a5d929190613100565b602060405180830381600087803b158015612a7757600080fd5b505af1158015612a8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aaf9190612d7c565b5060004790508b6001600160a01b03167fa1b94934d9119aa101df2e94f736d2cff64c4d7db8706c9b5bb1ffa265842f89886060015184612af98f866114e790919063ffffffff16565b604051612b089392919061337a565b60405180910390a28a811115612b3557612b35612b25828d6114e7565b6001600160a01b038e1690611545565b505050505050505050505050565b6000816118f96118ef856b033b2e3c9fd0803ce8000000612b8e565b6000612b87612b81612b7b612b748686612bfa565b60016114e7565b84612c5d565b83612b8e565b9392505050565b6000811580612ba957505080820282828281612ba657fe5b04145b61153f576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b8082018281101561153f576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000612b87612b8184845b6000808211612cb3576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161190057fe5b600082601f830112612ccc578081fd5b8151612cdf612cda826133d7565b6133b3565b818152846020838601011115612cf3578283fd5b612d048260208301602087016133f9565b949350505050565b805160ff81168114612d1d57600080fd5b919050565b600060208284031215612d33578081fd5b8135612b8781613425565b60008060008060808587031215612d53578283fd5b8451612d5e81613425565b60208601516040870151606090970151919890975090945092505050565b600060208284031215612d8d578081fd5b81518015158114612b87578182fd5b600060208284031215612dad578081fd5b813567ffffffffffffffff811115612dc3578182fd5b8201601f81018413612dd3578182fd5b8035612de1612cda826133d7565b818152856020838501011115612df5578384fd5b81602084016020830137908101602001929092525092915050565b600060208284031215612e21578081fd5b6040516020810181811067ffffffffffffffff82111715612e3e57fe5b6040529151825250919050565b600060a08284031215612e5c578081fd5b60405160a0810181811067ffffffffffffffff82111715612e7957fe5b8060405250825181526020830151602082015260408301516040820152606083015160608201526080830151612eae8161343d565b60808201529392505050565b600060808284031215612ecb578081fd5b6040516080810181811067ffffffffffffffff82111715612ee857fe5b80604052508251815260208301516020820152604083015160408201526060830151612f138161343d565b60608201529392505050565b600060208284031215612f30578081fd5b815167ffffffffffffffff80821115612f47578283fd5b9083019060808286031215612f5a578283fd5b604051608081018181108382111715612f6f57fe5b6040528251612f7d81613425565b815260208381015190820152612f9560408401612d0c565b6040820152606083015182811115612fab578485fd5b612fb787828601612cbc565b60608301525095945050505050565b600060208284031215612fd7578081fd5b5035919050565b600060208284031215612fef578081fd5b5051919050565b60008060006060848603121561300a578081fd5b833592506020840135915060408401356130238161343d565b809150509250925092565b600080600080600060a08688031215613045578283fd5b85359450602086013593506040860135925060608601359150608086013561306c8161343d565b809150509295509295909350565b600081518084526130928160208601602086016133f9565b601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b038416825260406020830152612d04604083018461307a565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b931515845260208401929092526040830152606082015260800190565b918252602082015260400190565b602080825260029082015261269b60f11b604082015260600190565b6020808252600290820152614d3560f01b604082015260600190565b60208082526002908201526109a760f31b604082015260600190565b6020808252600290820152614d3360f01b604082015260600190565b6020808252600290820152614d3960f01b604082015260600190565b6020808252600290820152614d3760f01b604082015260600190565b60208082526003908201526204d31360ec1b604082015260600190565b6020808252600290820152614d3160f01b604082015260600190565b602080825260029082015261134d60f21b604082015260600190565b602080825260029082015261269960f11b604082015260600190565b6020808252600390820152624d313160e81b604082015260600190565b9051815260200190565b600060a0820190508251825260208301516020830152604083015160408301526060830151606083015262ffffff608084015116608083015292915050565b81518152602080830151908201526040808301519082015260609182015162ffffff169181019190915260800190565b6000602082526001600160a01b0383511660208301526020830151604083015260ff60408401511660608301526060830151608080840152612d0460a084018261307a565b90815260200190565b91825262ffffff16602082015260400190565b928352602083019190915262ffffff16604082015260600190565b9283526020830191909152604082015260600190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff811182821017156133cf57fe5b604052919050565b600067ffffffffffffffff8211156133eb57fe5b50601f01601f191660200190565b60005b838110156134145781810151838201526020016133fc565b8381111561053d5750506000910152565b6001600160a01b038116811461343a57600080fd5b50565b62ffffff8116811461343a57600080fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a26469706673582212207966a8d1a64f3eebd4cdd5a263bc2934c3f304d935a1b2eaf5f4667b66aa9f7a64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x6080604052600436106101485760003560e01c8063a15db5c5116100c0578063cb9d1ab811610074578063db661b7111610059578063db661b71146103d2578063f2fde38b146103e7578063fe7dd6e414610407576101cf565b8063cb9d1ab814610392578063d2cebf9b146103b2576101cf565b8063bab89ea3116100a5578063bab89ea31461032d578063bbac0aca14610342578063bbca7f1e14610362576101cf565b8063a15db5c5146102eb578063b06faf621461030b576101cf565b8063715018a6116101175780638da5cb5b116100fc5780638da5cb5b146102965780638e953732146102ab578063a13d7b33146102cb576101cf565b8063715018a61461026c5780637fa8c37014610281576101cf565b8063139d3799146101d45780631d4dab2c146101f45780633fc8cef31461022a578063581e74781461024c576101cf565b366101cf57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610193575060025461010090046001600160a01b031633145b806101a857506003546001600160a01b031633145b6101cd5760405162461bcd60e51b81526004016101c490613230565b60405180910390fd5b005b600080fd5b3480156101e057600080fd5b506101cd6101ef366004612ff6565b61041c565b34801561020057600080fd5b5061021461020f366004612d22565b610543565b6040516102219190613343565b60405180910390f35b34801561023657600080fd5b5061023f610555565b60405161022191906130a6565b34801561025857600080fd5b506101cd610267366004612ff6565b610579565b34801561027857600080fd5b506101cd6106dc565b34801561028d57600080fd5b5061023f6107a7565b3480156102a257600080fd5b5061023f6107bb565b3480156102b757600080fd5b506101cd6102c636600461302e565b6107ca565b3480156102d757600080fd5b506101cd6102e6366004612fc6565b61095e565b3480156102f757600080fd5b506101cd610306366004612d9c565b610cec565b34801561031757600080fd5b50610320610f97565b6040516102219190613119565b34801561033957600080fd5b506101cd610fa0565b34801561034e57600080fd5b506101cd61035d366004612d22565b61109f565b34801561036e57600080fd5b5061038261037d366004612fc6565b611168565b6040516102219493929190613124565b34801561039e57600080fd5b506101cd6103ad366004612fc6565b611186565b3480156103be57600080fd5b506101cd6103cd366004612fc6565b611282565b3480156103de57600080fd5b5061023f611393565b3480156103f357600080fd5b506101cd610402366004612d22565b6113b7565b34801561041357600080fd5b5061023f6114d8565b60025460ff1661043e5760405162461bcd60e51b81526004016101c49061324c565b336000908152600160205260409020548084111561046e5760405162461bcd60e51b81526004016101c49061316b565b61047881856114e7565b3360009081526001602052604090819020919091556003549051630b52b7ff60e41b81526001600160a01b039091169063b52b7ff0906104c09087908790879060040161335f565b600060405180830381600087803b1580156104da57600080fd5b505af11580156104ee573d6000803e3d6000fd5b50505050336001600160a01b03167f38d6d922c6452f3aaf90ad851ed15eb4c5c613c745d0531cf4337c07de651bab8560405161052b9190613343565b60405180910390a261053d3347611545565b50505050565b60016020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60025460ff1661059b5760405162461bcd60e51b81526004016101c49061324c565b60008060006105a98661162f565b50925092509250826105cd5760405162461bcd60e51b81526004016101c4906131bf565b60408051608081018252338152602081018490526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916389b7b7a69130918101600160ff16815260200160405180608001604052808781526020018b81526020018c81526020018a62ffffff1681525060405160200161065691906132ce565b60408051601f1981840301815291815291525161067691906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016106a29291906130de565b600060405180830381600087803b1580156106bc57600080fd5b505af11580156106d0573d6000803e3d6000fd5b50505050505050505050565b6106e46118d3565b6001600160a01b03166106f56107bb565b6001600160a01b031614610750576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b60025461010090046001600160a01b031681565b6000546001600160a01b031690565b60025460ff166107ec5760405162461bcd60e51b81526004016101c49061324c565b6000806107f88761162f565b509250509150811561081c5760405162461bcd60e51b81526004016101c4906131f7565b60008511801561082c5750600084115b6108485760405162461bcd60e51b81526004016101c490613187565b60408051608081018252338152602081018790526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916389b7b7a69130918101600260ff1681526020016040518060a001604052808781526020018c81526020018a81526020018d81526020018962ffffff168152506040516020016108d7919061328f565b60408051601f198184030181529181529152516108f791906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016109239291906130de565b600060405180830381600087803b15801561093d57600080fd5b505af1158015610951573d6000803e3d6000fd5b5050505050505050505050565b6109666118d3565b6001600160a01b03166109776107bb565b6001600160a01b0316146109d2576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6003546001600160a01b03166109fa5760405162461bcd60e51b81526004016101c490613268565b60025460ff1615610a1d5760405162461bcd60e51b81526004016101c490613214565b6002805460ff1916600117908190556040516370a0823160e01b81526000916001600160a01b0361010090910416906370a0823190610a609030906004016130a6565b60206040518083038186803b158015610a7857600080fd5b505afa158015610a8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab09190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b0257600080fd5b505afa158015610b16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3a9190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b158015610b8c57600080fd5b505afa158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc49190612d3e565b50925060009150610be19050610bda85856118d7565b8390611908565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060800160405280336001600160a01b0316815260200185815260200160006002811115610c4057fe5b60ff16815260200160405180602001604052808b815250604051602001610c679190613285565b60408051601f19818403018152918152915251610c8791906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610cb39291906130de565b600060405180830381600087803b158015610ccd57600080fd5b505af1158015610ce1573d6000803e3d6000fd5b505050505050505050565b6003546001600160a01b0316610d145760405162461bcd60e51b81526004016101c490613268565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d5c5760405162461bcd60e51b81526004016101c4906131a3565b600081806020019051810190610d729190612f1f565b6020810151604051630ecbcdab60e01b81529192506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691630ecbcdab91610dc89160009190600401613141565b600060405180830381600087803b158015610de257600080fd5b505af1158015610df6573d6000803e3d6000fd5b5050506020820151604051632e1a7d4d60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250632e1a7d4d91610e4991600401613343565b600060405180830381600087803b158015610e6357600080fd5b505af1158015610e77573d6000803e3d6000fd5b50505050610e978160000151826020015183604001518460600151611930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db082602001516040518263ffffffff1660e01b81526004016000604051808303818588803b158015610ef657600080fd5b505af1158015610f0a573d6000803e3d6000fd5b505050602083015160405163d8aed14560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063d8aed1459250610f6191600091600401613141565b600060405180830381600087803b158015610f7b57600080fd5b505af1158015610f8f573d6000803e3d6000fd5b505050505050565b60025460ff1681565b60025460ff16610fc25760405162461bcd60e51b81526004016101c49061324c565b336000818152600160205260408082208054929055600354905163a9059cbb60e01b815291926001600160a01b039091169163a9059cbb91611008918590600401613100565b602060405180830381600087803b15801561102257600080fd5b505af1158015611036573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105a9190612d7c565b50336001600160a01b03167f0adef25f8a7a2d6f3fb9761ba0c96c9752b6d985abd47e23b7fa3095ba8e4701826040516110949190613343565b60405180910390a250565b6110a76118d3565b6001600160a01b03166110b86107bb565b6001600160a01b031614611113576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166111395760405162461bcd60e51b81526004016101c4906131db565b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000806000806111778561162f565b93509350935093509193509193565b60025460ff16156111a95760405162461bcd60e51b81526004016101c490613214565b336000818152600160205260409081902080548401905560025490516323b872dd60e01b81526101009091046001600160a01b0316916323b872dd916111f69190309086906004016130ba565b602060405180830381600087803b15801561121057600080fd5b505af1158015611224573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112489190612d7c565b50336001600160a01b03167fcbfc37edaa5ac30951b21b47b70bbb70dd1e015fa918da25d516798c6a2622e8826040516110949190613343565b60025460ff16156112a55760405162461bcd60e51b81526004016101c490613214565b336000908152600160205260409020546112bf90826114e7565b336000818152600160205260409081902092909255600254915163a9059cbb60e01b81526101009092046001600160a01b03169163a9059cbb91611307918590600401613100565b602060405180830381600087803b15801561132157600080fd5b505af1158015611335573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113599190612d7c565b50336001600160a01b03167ffdef8f0daac171c9b3f7896ae8991c11b88b64b1b76b574d8189dcd0357e5f6e826040516110949190613343565b7f000000000000000000000000000000000000000000000000000000000000000081565b6113bf6118d3565b6001600160a01b03166113d06107bb565b6001600160a01b03161461142b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166114705760405162461bcd60e51b815260040180806020018281038252602681526020018061344f6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6003546001600160a01b031681565b8082038281111561153f576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b92915050565b8047101561159a576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146115e5576040519150601f19603f3d011682016040523d82523d6000602084013e6115ea565b606091505b505090508061162a5760405162461bcd60e51b815260040180806020018281038252603a815260200180613475603a913960400191505060405180910390fd5b505050565b600080600080600080600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561168657600080fd5b505afa15801561169a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116be9190612d3e565b935093505050600080600360009054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561171557600080fd5b505afa158015611729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174d9190612d3e565b93509350505060006117ee600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156117a657600080fd5b505afa1580156117ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117de9190612fde565b6117e8868d611908565b906118d7565b90506000633b9aca006118158161180f86611809878a611908565b90612b43565b90612b5f565b8161181c57fe5b04905060006118bb876118b5600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561187657600080fd5b505afa15801561188a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ae9190612fde565b8f906118d7565b90611908565b808311159d929c50929a509198509650505050505050565b3390565b6000816118f96118ef85670de0b6b3a7640000612b8e565b6002855b04612bfa565b8161190057fe5b049392505050565b6000670de0b6b3a76400006118f96119208585612b8e565b6002670de0b6b3a76400006118f3565b60008260ff16600281111561194157fe5b600281111561194c57fe5b1415611d1f576000818060200190518101906119689190612e10565b6002546040516370a0823160e01b81529192506000916101009091046001600160a01b0316906370a08231906119a29030906004016130a6565b60206040518083038186803b1580156119ba57600080fd5b505afa1580156119ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f29190612fde565b60025460405163f73e19c360e01b81529192506000916101009091046001600160a01b03169063f73e19c390611a2c908590600401613343565b60206040518083038186803b158015611a4457600080fd5b505afa158015611a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7c9190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166367b8c3456040518163ffffffff1660e01b815260040160206040518083038186803b158015611ace57600080fd5b505afa158015611ae2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b069190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166363bbc4b66040518163ffffffff1660e01b815260040160206040518083038186803b158015611b5857600080fd5b505afa158015611b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b909190612fde565b6003548651604051631b9756c160e31b81529293506001600160a01b039091169163dcbab608918b91611bce9188918a918991899190600401613390565b6000604051808303818588803b158015611be757600080fd5b505af1158015611bfb573d6000803e3d6000fd5b505060025460405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116955063095ea7b39450611c5c93506101009092049091169060001990600401613100565b602060405180830381600087803b158015611c7657600080fd5b505af1158015611c8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cae9190612d7c565b50600254604051632e1a7d4d60e01b81526101009091046001600160a01b031690632e1a7d4d90611ce3908790600401613343565b600060405180830381600087803b158015611cfd57600080fd5b505af1158015611d11573d6000803e3d6000fd5b50505050505050505061053d565b60018260ff166002811115611d3057fe5b6002811115611d3b57fe5b1415612317576003546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611d729030906004016130a6565b60206040518083038186803b158015611d8a57600080fd5b505afa158015611d9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc29190612fde565b9050600082806020019051810190611dda9190612eba565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e2c57600080fd5b505af1158015611e40573d6000803e3d6000fd5b505060025460408581015190516323b872dd60e01b81526101009092046001600160a01b031694506323b872dd9350611e8192508a913091906004016130ba565b602060405180830381600087803b158015611e9b57600080fd5b505af1158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190612d7c565b50600254815160405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169363095ea7b393611f2f936101009092049092169190600401613100565b602060405180830381600087803b158015611f4957600080fd5b505af1158015611f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f819190612d7c565b506002546040828101519051632e1a7d4d60e01b81526101009092046001600160a01b031691632e1a7d4d91611fb991600401613343565b600060405180830381600087803b158015611fd357600080fd5b505af1158015611fe7573d6000803e3d6000fd5b5050505060208101511561206a576003546001600160a01b031663fc5b73ff61201047886114e7565b836020015184606001516040518463ffffffff1660e01b815260040161203792919061334c565b6000604051808303818588803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b50505050505b6003546040516370a0823160e01b81526000916120f79185916001600160a01b0316906370a08231906120a19030906004016130a6565b60206040518083038186803b1580156120b957600080fd5b505afa1580156120cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f19190612fde565b906114e7565b60035460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb9061212a908a908590600401613100565b602060405180830381600087803b15801561214457600080fd5b505af1158015612158573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217c9190612d7c565b506040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90899083906370a08231906121d39030906004016130a6565b60206040518083038186803b1580156121eb57600080fd5b505afa1580156121ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122239190612fde565b6040518363ffffffff1660e01b8152600401612240929190613100565b602060405180830381600087803b15801561225a57600080fd5b505af115801561226e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122929190612d7c565b50604082015147906001600160a01b038916907fa1b94934d9119aa101df2e94f736d2cff64c4d7db8706c9b5bb1ffa265842f8990846122d2858c6114e7565b6040516122e19392919061337a565b60405180910390a28681111561230e5761230e6122fe82896114e7565b6001600160a01b038a1690611545565b5050505061053d565b60028260ff16600281111561232857fe5b600281111561233357fe5b141561053d576003546040516370a0823160e01b81526000916001600160a01b0316906370a082319061236a9030906004016130a6565b60206040518083038186803b15801561238257600080fd5b505afa158015612396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ba9190612fde565b90506000828060200190518101906123d29190612e4b565b90506000600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561242457600080fd5b505afa158015612438573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245c9190612d3e565b60025460608701516040516323b872dd60e01b81529296506101009091046001600160a01b031694506323b872dd935061249e92508b913091906004016130ba565b602060405180830381600087803b1580156124b857600080fd5b505af11580156124cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f09190612d7c565b50600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b15801561254157600080fd5b505af1158015612555573d6000803e3d6000fd5b50506040516370a0823160e01b8152600093506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692506370a0823191506125a99030906004016130a6565b60206040518083038186803b1580156125c157600080fd5b505afa1580156125d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f99190612fde565b60025460405163095ea7b360e01b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263095ea7b3926126549261010090910416908590600401613100565b602060405180830381600087803b15801561266e57600080fd5b505af1158015612682573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126a69190612d7c565b50600061273d83611809600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126fe57600080fd5b505afa158015612712573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127369190612fde565b8590611908565b90506000633b9aca006127508382612c52565b8161275757fe5b600254604051632e1a7d4d60e01b815292909104925061010090046001600160a01b031690632e1a7d4d90612790908490600401613343565b600060405180830381600087803b1580156127aa57600080fd5b505af11580156127be573d6000803e3d6000fd5b505060025460608801516101009091046001600160a01b031692506323ccafd991506127ea90846114e7565b87604001516040518363ffffffff1660e01b815260040161280c929190613141565b600060405180830381600087803b15801561282657600080fd5b505af115801561283a573d6000803e3d6000fd5b505050508847101561285e5760405162461bcd60e51b81526004016101c49061314f565b6020850151156128dd576003546001600160a01b031663fc5b73ff612883478c6114e7565b876020015188608001516040518463ffffffff1660e01b81526004016128aa92919061334c565b6000604051808303818588803b1580156128c357600080fd5b505af11580156128d7573d6000803e3d6000fd5b50505050505b6003546040516370a0823160e01b81526000916129149189916001600160a01b0316906370a08231906120a19030906004016130a6565b60035460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb90612947908e908590600401613100565b602060405180830381600087803b15801561296157600080fd5b505af1158015612975573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129999190612d7c565b506040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb908d9083906370a08231906129f09030906004016130a6565b60206040518083038186803b158015612a0857600080fd5b505afa158015612a1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a409190612fde565b6040518363ffffffff1660e01b8152600401612a5d929190613100565b602060405180830381600087803b158015612a7757600080fd5b505af1158015612a8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aaf9190612d7c565b5060004790508b6001600160a01b03167fa1b94934d9119aa101df2e94f736d2cff64c4d7db8706c9b5bb1ffa265842f89886060015184612af98f866114e790919063ffffffff16565b604051612b089392919061337a565b60405180910390a28a811115612b3557612b35612b25828d6114e7565b6001600160a01b038e1690611545565b505050505050505050505050565b6000816118f96118ef856b033b2e3c9fd0803ce8000000612b8e565b6000612b87612b81612b7b612b748686612bfa565b60016114e7565b84612c5d565b83612b8e565b9392505050565b6000811580612ba957505080820282828281612ba657fe5b04145b61153f576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b8082018281101561153f576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000612b87612b8184845b6000808211612cb3576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161190057fe5b600082601f830112612ccc578081fd5b8151612cdf612cda826133d7565b6133b3565b818152846020838601011115612cf3578283fd5b612d048260208301602087016133f9565b949350505050565b805160ff81168114612d1d57600080fd5b919050565b600060208284031215612d33578081fd5b8135612b8781613425565b60008060008060808587031215612d53578283fd5b8451612d5e81613425565b60208601516040870151606090970151919890975090945092505050565b600060208284031215612d8d578081fd5b81518015158114612b87578182fd5b600060208284031215612dad578081fd5b813567ffffffffffffffff811115612dc3578182fd5b8201601f81018413612dd3578182fd5b8035612de1612cda826133d7565b818152856020838501011115612df5578384fd5b81602084016020830137908101602001929092525092915050565b600060208284031215612e21578081fd5b6040516020810181811067ffffffffffffffff82111715612e3e57fe5b6040529151825250919050565b600060a08284031215612e5c578081fd5b60405160a0810181811067ffffffffffffffff82111715612e7957fe5b8060405250825181526020830151602082015260408301516040820152606083015160608201526080830151612eae8161343d565b60808201529392505050565b600060808284031215612ecb578081fd5b6040516080810181811067ffffffffffffffff82111715612ee857fe5b80604052508251815260208301516020820152604083015160408201526060830151612f138161343d565b60608201529392505050565b600060208284031215612f30578081fd5b815167ffffffffffffffff80821115612f47578283fd5b9083019060808286031215612f5a578283fd5b604051608081018181108382111715612f6f57fe5b6040528251612f7d81613425565b815260208381015190820152612f9560408401612d0c565b6040820152606083015182811115612fab578485fd5b612fb787828601612cbc565b60608301525095945050505050565b600060208284031215612fd7578081fd5b5035919050565b600060208284031215612fef578081fd5b5051919050565b60008060006060848603121561300a578081fd5b833592506020840135915060408401356130238161343d565b809150509250925092565b600080600080600060a08688031215613045578283fd5b85359450602086013593506040860135925060608601359150608086013561306c8161343d565b809150509295509295909350565b600081518084526130928160208601602086016133f9565b601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b038416825260406020830152612d04604083018461307a565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b931515845260208401929092526040830152606082015260800190565b918252602082015260400190565b602080825260029082015261269b60f11b604082015260600190565b6020808252600290820152614d3560f01b604082015260600190565b60208082526002908201526109a760f31b604082015260600190565b6020808252600290820152614d3360f01b604082015260600190565b6020808252600290820152614d3960f01b604082015260600190565b6020808252600290820152614d3760f01b604082015260600190565b60208082526003908201526204d31360ec1b604082015260600190565b6020808252600290820152614d3160f01b604082015260600190565b602080825260029082015261134d60f21b604082015260600190565b602080825260029082015261269960f11b604082015260600190565b6020808252600390820152624d313160e81b604082015260600190565b9051815260200190565b600060a0820190508251825260208301516020830152604083015160408301526060830151606083015262ffffff608084015116608083015292915050565b81518152602080830151908201526040808301519082015260609182015162ffffff169181019190915260800190565b6000602082526001600160a01b0383511660208301526020830151604083015260ff60408401511660608301526060830151608080840152612d0460a084018261307a565b90815260200190565b91825262ffffff16602082015260400190565b928352602083019190915262ffffff16604082015260600190565b9283526020830191909152604082015260600190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff811182821017156133cf57fe5b604052919050565b600067ffffffffffffffff8211156133eb57fe5b50601f01601f191660200190565b60005b838110156134145781810151838201526020016133fc565b8381111561053d5750506000910152565b6001600160a01b038116811461343a57600080fd5b50565b62ffffff8116811461343a57600080fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a26469706673582212207966a8d1a64f3eebd4cdd5a263bc2934c3f304d935a1b2eaf5f4667b66aa9f7a64736f6c63430007060033\",\n  \"devdoc\": {\n    \"author\": \"Opyn team\",\n    \"details\": \"CrabMigration contract\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"batchMigrate(uint256)\": {\n        \"params\": {\n          \"_strategyCap\": \"strategy cap in ETH\"\n        }\n      },\n      \"claimAndWithdraw(uint256,uint256,uint24)\": {\n        \"params\": {\n          \"_amountToWithdraw\": \"V2 shares to claim\",\n          \"_maxEthToPay\": \"maximum ETH to pay to buy back the owed wSqueeth debt\",\n          \"_poolFee\": \"Uniswap pool fee for flash withdraw\"\n        }\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_crabV1\": \"address of crab V1\",\n          \"_dToken\": \"address of euler liability token\",\n          \"_eulerExec\": \"address of euler exec contract\",\n          \"_eulerMainnet\": \"address of euler deployment on mainnet\",\n          \"_weth\": \"address of weth\"\n        }\n      },\n      \"depositV1Shares(uint256)\": {\n        \"params\": {\n          \"_amount\": \"amount of crabV1 shares to deposit\"\n        }\n      },\n      \"flashMigrateAndWithdrawFromV1toV2(uint256,uint256,uint256,uint256,uint24)\": {\n        \"params\": {\n          \"_ethToBorrow\": \"amount to flash loan to deposit in crab v2\",\n          \"_ethToFlashDeposit\": \"flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\",\n          \"_poolFee\": \"uniswap pool fee for the optional flash deposit into crab v2\",\n          \"_v1Shares\": \"V1 shares to migrate\",\n          \"_withdrawMaxEthToPay\": \"maximum ETH to pay to buy back the owed wSqueeth debt\"\n        }\n      },\n      \"flashMigrateFromV1toV2(uint256,uint256,uint24)\": {\n        \"params\": {\n          \"_ethToFlashDeposit\": \"flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\",\n          \"_poolFee\": \"uniswap pool fee for flash deposit\",\n          \"_v1Shares\": \"V1 shares to migrate\"\n        }\n      },\n      \"flashMigrationDetails(uint256)\": {\n        \"params\": {\n          \"_v1Shares\": \"amount of crab V1 shares\"\n        }\n      },\n      \"onDeferredLiquidityCheck(bytes)\": {\n        \"params\": {\n          \"encodedData\": \"callback data\"\n        }\n      },\n      \"owner()\": {\n        \"details\": \"Returns the address of the current owner.\"\n      },\n      \"renounceOwnership()\": {\n        \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n      },\n      \"setCrabV2(address)\": {\n        \"params\": {\n          \"_crabV2\": \"address of crab V2\"\n        }\n      },\n      \"transferOwnership(address)\": {\n        \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n      },\n      \"withdrawV1Shares(uint256)\": {\n        \"params\": {\n          \"_amount\": \"amount of V1 shares to withdraw\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"batchMigrate(uint256)\": {\n        \"notice\": \"the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes the V2 contract at the same collateral ratio as the V1 contract\"\n      },\n      \"claimAndWithdraw(uint256,uint256,uint24)\": {\n        \"notice\": \"claim crab V2 shares and flash withdraw from crab V2\"\n      },\n      \"claimV2Shares()\": {\n        \"notice\": \"claim crab V2 shares\"\n      },\n      \"constructor\": {\n        \"notice\": \"migration constructor\"\n      },\n      \"depositV1Shares(uint256)\": {\n        \"notice\": \"deposit crab V1 shares in the pool for migration\"\n      },\n      \"flashMigrateAndWithdrawFromV1toV2(uint256,uint256,uint256,uint256,uint24)\": {\n        \"notice\": \"used to migrate from crab V1 to crab V2 when CR1 < CR2\"\n      },\n      \"flashMigrateFromV1toV2(uint256,uint256,uint24)\": {\n        \"notice\": \"used to migrate from crab V1 to crab V2 when CR1 >= CR2\"\n      },\n      \"flashMigrationDetails(uint256)\": {\n        \"notice\": \"view details of flash migration for specified amount of V1 shares\"\n      },\n      \"onDeferredLiquidityCheck(bytes)\": {\n        \"notice\": \"Euler callback function\"\n      },\n      \"setCrabV2(address)\": {\n        \"notice\": \"set the crabV2 address\"\n      },\n      \"withdrawV1Shares(uint256)\": {\n        \"notice\": \"withdraw crab V1 shares in the pool before migration\"\n      }\n    },\n    \"notice\": \"Contract for Migrating from Crab V1 to Crab V2\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 7,\n        \"contract\": \"contracts/strategy/CrabMigration.sol:CrabMigration\",\n        \"label\": \"_owner\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 21326,\n        \"contract\": \"contracts/strategy/CrabMigration.sol:CrabMigration\",\n        \"label\": \"sharesDeposited\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 21328,\n        \"contract\": \"contracts/strategy/CrabMigration.sol:CrabMigration\",\n        \"label\": \"isMigrated\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 21330,\n        \"contract\": \"contracts/strategy/CrabMigration.sol:CrabMigration\",\n        \"label\": \"crabV1\",\n        \"offset\": 1,\n        \"slot\": \"2\",\n        \"type\": \"t_address_payable\"\n      },\n      {\n        \"astId\": 21332,\n        \"contract\": \"contracts/strategy/CrabMigration.sol:CrabMigration\",\n        \"label\": \"crabV2\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_address_payable\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_address_payable\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address payable\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/CrabStrategyV2.json",
    "content": "{\n  \"address\": \"0x3B960E47784150F5a63777201ee2B15253D713e8\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wSqueethController\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_oracle\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_weth\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniswapFactory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_ethWSqueethPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_timelock\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_crabMigration\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"lpAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Deposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"depositedAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tradedAmountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDeposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDepositCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdrawCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"bidId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"quantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"clearingPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"HedgeOTC\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"trader\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"bidId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"quantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"price\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"clearingPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"HedgeOTCSingle\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newHedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetHedgePriceThreshold\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newHedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetHedgeTimeThreshold\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint32\",\n          \"name\": \"newHedgingTwapPeriod\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"SetHedgingTwapPeriod\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"otcPriceTolerance\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetOTCPriceTolerance\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newCapAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetStrategyCap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newStrategy\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"VaultTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Withdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawShutdown\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"DOMAIN_SEPARATOR\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"MAX_OTC_PRICE_TOLERANCE\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"POWER_PERP_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"checkPriceHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"checkTimeHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"crabMigration\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"subtractedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"decreaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"deposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"ethWSqueethPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToDeposit\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashDeposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxEthToPay\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashWithdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getStrategyVaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getVaultDetails\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getWsqueethFromCrabAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_totalQuantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_clearingPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_isHedgeBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"bidId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"trader\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"quantity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"price\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"isBuying\",\n              \"type\": \"bool\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"expiry\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"nonce\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint8\",\n              \"name\": \"v\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"bytes32\",\n              \"name\": \"r\",\n              \"type\": \"bytes32\"\n            },\n            {\n              \"internalType\": \"bytes32\",\n              \"name\": \"s\",\n              \"type\": \"bytes32\"\n            }\n          ],\n          \"internalType\": \"struct CrabStrategyV2.Order[]\",\n          \"name\": \"_orders\",\n          \"type\": \"tuple[]\"\n        }\n      ],\n      \"name\": \"hedgeOTC\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgePriceThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgeTimeThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgingTwapPeriod\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"addedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"increaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wSqueethToMint\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabSharesToMint\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_timeAtLastHedge\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_priceAtLastHedge\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_strategyCap\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"initialize\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isInitialized\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"nonces\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"oracle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"otcPriceTolerance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"powerTokenController\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IController\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"priceAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"redeemShortShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setHedgePriceThreshold\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setHedgeTimeThreshold\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_hedgingTwapPeriod\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"setHedgingTwapPeriod\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_nonce\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setNonceTrue\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_otcPriceTolerance\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setOTCPriceTolerance\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_capAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setStrategyCap\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"strategyCap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"timeAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"timelock\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_newStrategy\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"vaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdrawShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0xd8d637b3c3947bcabe1f60d24261aedd90d5681252b39b9457d5765481b93ba6\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0x3B960E47784150F5a63777201ee2B15253D713e8\",\n    \"transactionIndex\": 48,\n    \"gasUsed\": \"5587910\",\n    \"logsBloom\": \"0x00004000000008000000000000000000000000000000000000800000000000000000000080000000100000080000000000080000001000000000000100000000020000001000000000000008000000000001010000000000000000004000000000000000020240000000000000000800000000000000000020000010000000400000000100000200002000000000000000000000000000000200000000000000040000000000000000000000800000004000000000000000000000001000000000000002000000000000000000000000040000000000000000000000000020000000000000002080000800000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0xbe2b5d7f2f13b4edfa775bb34ed743f4960ba8e961d844b5f816a23d9b8b5792\",\n    \"transactionHash\": \"0xd8d637b3c3947bcabe1f60d24261aedd90d5681252b39b9457d5765481b93ba6\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 48,\n        \"blockNumber\": 15134614,\n        \"transactionHash\": \"0xd8d637b3c3947bcabe1f60d24261aedd90d5681252b39b9457d5765481b93ba6\",\n        \"address\": \"0x64187ae08781B09368e6253F9E94951243A493D5\",\n        \"topics\": [\n          \"0x339e53729b0447795ff69e70a74fed98fc7fef6fe94b7521099b32f0f8de4822\"\n        ],\n        \"data\": \"0x00000000000000000000000000000000000000000000000007a4d61e4c0edbac00000000000000000000000000000000000000000000000007a498a650c5c6510000000000000000000000000000000000000000000000000000000062cebd5d0000000000000000000000000000000000000000000000000000000062cecd93\",\n        \"logIndex\": 113,\n        \"blockHash\": \"0xbe2b5d7f2f13b4edfa775bb34ed743f4960ba8e961d844b5f816a23d9b8b5792\"\n      },\n      {\n        \"transactionIndex\": 48,\n        \"blockNumber\": 15134614,\n        \"transactionHash\": \"0xd8d637b3c3947bcabe1f60d24261aedd90d5681252b39b9457d5765481b93ba6\",\n        \"address\": \"0x64187ae08781B09368e6253F9E94951243A493D5\",\n        \"topics\": [\n          \"0x3137fc9cd2e33c34f86e29c24d81f3c75b0bce639d3c4ed0d31eeff1160a7ff5\"\n        ],\n        \"data\": \"0x000000000000000000000000a653e22a963ff0026292cc8b67941c0ba7863a38000000000000000000000000000000000000000000000000000000000000011e0000000000000000000000000000000000000000000000000000000000000000\",\n        \"logIndex\": 114,\n        \"blockHash\": \"0xbe2b5d7f2f13b4edfa775bb34ed743f4960ba8e961d844b5f816a23d9b8b5792\"\n      },\n      {\n        \"transactionIndex\": 48,\n        \"blockNumber\": 15134614,\n        \"transactionHash\": \"0xd8d637b3c3947bcabe1f60d24261aedd90d5681252b39b9457d5765481b93ba6\",\n        \"address\": \"0xa653e22A963ff0026292Cc8B67941c0ba7863a38\",\n        \"topics\": [\n          \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8\",\n          \"0x000000000000000000000000000000000000000000000000000000000000011e\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 115,\n        \"blockHash\": \"0xbe2b5d7f2f13b4edfa775bb34ed743f4960ba8e961d844b5f816a23d9b8b5792\"\n      },\n      {\n        \"transactionIndex\": 48,\n        \"blockNumber\": 15134614,\n        \"transactionHash\": \"0xd8d637b3c3947bcabe1f60d24261aedd90d5681252b39b9457d5765481b93ba6\",\n        \"address\": \"0x64187ae08781B09368e6253F9E94951243A493D5\",\n        \"topics\": [\n          \"0x25ff1e0131762176a9084e92880f880f39d6d0e62134607f37e631efe1bad871\"\n        ],\n        \"data\": \"0x0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8000000000000000000000000000000000000000000000000000000000000011e\",\n        \"logIndex\": 116,\n        \"blockHash\": \"0xbe2b5d7f2f13b4edfa775bb34ed743f4960ba8e961d844b5f816a23d9b8b5792\"\n      },\n      {\n        \"transactionIndex\": 48,\n        \"blockNumber\": 15134614,\n        \"transactionHash\": \"0xd8d637b3c3947bcabe1f60d24261aedd90d5681252b39b9457d5765481b93ba6\",\n        \"address\": \"0x3B960E47784150F5a63777201ee2B15253D713e8\",\n        \"topics\": [\n          \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000005599b4eaddd319e2f462b27fc8378b0bfad309ca\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 117,\n        \"blockHash\": \"0xbe2b5d7f2f13b4edfa775bb34ed743f4960ba8e961d844b5f816a23d9b8b5792\"\n      }\n    ],\n    \"blockNumber\": 15134614,\n    \"cumulativeGasUsed\": \"9846511\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x64187ae08781B09368e6253F9E94951243A493D5\",\n    \"0x65D66c76447ccB45dAf1e8044e918fA786A483A1\",\n    \"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\",\n    \"0x1F98431c8aD98523631AE4a59f267346ea31F984\",\n    \"0x82c427AdFDf2d245Ec51D8046b41c4ee87F0d29C\",\n    \"0x67c083aE303741372F0f321Bf9cAD567CFEFE2DC\",\n    \"0xa1CAB67a4383312718a5799Eaa127906e9d4B19E\",\n    3600,\n    \"200000000000000000\"\n  ],\n  \"solcInputHash\": \"30afee76cfee2d4cc1c12451e0258499\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wSqueethController\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_oracle\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_weth\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniswapFactory\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_ethWSqueethPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_timelock\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_crabMigration\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"lpAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Deposit\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"depositedAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tradedAmountOut\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDeposit\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"flashswapDebt\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excess\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDepositCallback\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"flashswapDebt\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excess\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdrawCallback\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bidId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"quantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"clearingPrice\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"HedgeOTC\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"trader\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bidId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"quantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"price\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"clearingPrice\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"HedgeOTCSingle\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newHedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetHedgePriceThreshold\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newHedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetHedgeTimeThreshold\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"newHedgingTwapPeriod\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"SetHedgingTwapPeriod\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"otcPriceTolerance\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetOTCPriceTolerance\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newCapAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetStrategyCap\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newStrategy\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"VaultTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethWithdrawn\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Withdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethWithdrawn\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawShutdown\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"DOMAIN_SEPARATOR\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"MAX_OTC_PRICE_TOLERANCE\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"POWER_PERP_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"checkPriceHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"checkTimeHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"crabMigration\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"subtractedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"decreaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"deposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"ethWSqueethPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"factory\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashDeposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxEthToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashWithdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getStrategyVaultId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getVaultDetails\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"getWsqueethFromCrabAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_totalQuantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_clearingPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_isHedgeBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bidId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"trader\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"quantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"price\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"expiry\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"nonce\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"v\\\",\\\"type\\\":\\\"uint8\\\"},{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"r\\\",\\\"type\\\":\\\"bytes32\\\"},{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"s\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"internalType\\\":\\\"struct CrabStrategyV2.Order[]\\\",\\\"name\\\":\\\"_orders\\\",\\\"type\\\":\\\"tuple[]\\\"}],\\\"name\\\":\\\"hedgeOTC\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgePriceThreshold\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgeTimeThreshold\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgingTwapPeriod\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"addedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"increaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wSqueethToMint\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabSharesToMint\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_timeAtLastHedge\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_priceAtLastHedge\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_strategyCap\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"initialize\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isInitialized\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"nonces\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"oracle\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"otcPriceTolerance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"powerTokenController\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IController\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"priceAtLastHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"redeemShortShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setHedgePriceThreshold\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setHedgeTimeThreshold\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_hedgingTwapPeriod\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"setHedgingTwapPeriod\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_nonce\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setNonceTrue\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_otcPriceTolerance\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setOTCPriceTolerance\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_capAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setStrategyCap\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"strategyCap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"timeAtLastHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"timelock\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_newStrategy\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferVault\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount0Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount1Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"uniswapV3SwapCallback\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"vaultId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdrawShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"author\\\":\\\"Opyn team\\\",\\\"details\\\":\\\"CrabStrategyV2 contract\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"DOMAIN_SEPARATOR()\\\":{\\\"details\\\":\\\"view function to get the domain seperator used in signing\\\"},\\\"allowance(address,address)\\\":{\\\"details\\\":\\\"See {IERC20-allowance}.\\\"},\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC20-balanceOf}.\\\"},\\\"checkPriceHedge()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"true if hedging is allowed\\\"}},\\\"checkTimeHedge()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"true if hedging is allowed\\\"}},\\\"constructor\\\":{\\\"details\\\":\\\"this will open a vault in the power token contract and store the vault ID\\\",\\\"params\\\":{\\\"_crabMigration\\\":\\\"crab migration contract address\\\",\\\"_ethWSqueethPool\\\":\\\"eth:wSqueeth uniswap pool address\\\",\\\"_hedgePriceThreshold\\\":\\\"hedge price threshold (0.1*1e18 = 10%)\\\",\\\"_hedgeTimeThreshold\\\":\\\"hedge time threshold (seconds)\\\",\\\"_oracle\\\":\\\"oracle address\\\",\\\"_timelock\\\":\\\"timelock contract address\\\",\\\"_uniswapFactory\\\":\\\"uniswap factory address\\\",\\\"_wSqueethController\\\":\\\"power token controller address\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"decimals()\\\":{\\\"details\\\":\\\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\\\"},\\\"decreaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\\\"},\\\"deposit()\\\":{\\\"details\\\":\\\"provide ETH, return wSqueeth and strategy token\\\"},\\\"flashDeposit(uint256,uint24)\\\":{\\\"details\\\":\\\"this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth_ethToDeposit must be less than msg.value plus the proceeds from the flash swapthe difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\",\\\"params\\\":{\\\"_ethToDeposit\\\":\\\"total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\",\\\"_poolFee\\\":\\\"Uniswap pool fee\\\"}},\\\"flashWithdraw(uint256,uint256,uint24)\\\":{\\\"details\\\":\\\"this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\",\\\"params\\\":{\\\"_crabAmount\\\":\\\"strategy token amount to burn\\\",\\\"_maxEthToPay\\\":\\\"maximum ETH to pay to buy back the wSqueeth debt\\\",\\\"_poolFee\\\":\\\"Uniswap pool fee\\\"}},\\\"getStrategyVaultId()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"vault ID\\\"}},\\\"getVaultDetails()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"operator\\\",\\\"_1\\\":\\\"nft collateral id\\\",\\\"_2\\\":\\\"collateral amount\\\",\\\"_3\\\":\\\"short amount\\\"}},\\\"getWsqueethFromCrabAmount(uint256)\\\":{\\\"params\\\":{\\\"_crabAmount\\\":\\\"strategy token amount\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"wSqueeth amount\\\"}},\\\"hedgeOTC(uint256,uint256,bool,(uint256,address,uint256,uint256,bool,uint256,uint256,uint8,bytes32,bytes32)[])\\\":{\\\"details\\\":\\\"hedge function to reduce delta using an array of signed orders\\\",\\\"params\\\":{\\\"_clearingPrice\\\":\\\"clearing price in weth\\\",\\\"_isHedgeBuying\\\":\\\"direction of hedge trade\\\",\\\"_orders\\\":\\\"an array of signed order to swap tokens\\\",\\\"_totalQuantity\\\":\\\"quantity the manager wants to trade\\\"}},\\\"increaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\\\"},\\\"initialize(uint256,uint256,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_crabSharesToMint\\\":\\\"crab shares to mint\\\",\\\"_priceAtLastHedge\\\":\\\"price at last hedge for crab V1\\\",\\\"_strategyCap\\\":\\\"strategy cap for crab V2\\\",\\\"_timeAtLastHedge\\\":\\\"time at last hedge for crab V1\\\",\\\"_wSqueethToMint\\\":\\\"amount of wPowerPerp to mint\\\"}},\\\"name()\\\":{\\\"details\\\":\\\"Returns the name of the token.\\\"},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"redeemShortShutdown()\\\":{\\\"details\\\":\\\"needs to be called before users can exit strategy using withdrawShutdown\\\"},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"setHedgePriceThreshold(uint256)\\\":{\\\"params\\\":{\\\"_hedgePriceThreshold\\\":\\\"the hedge price threshold, in percent, scaled by 1e18\\\"}},\\\"setHedgeTimeThreshold(uint256)\\\":{\\\"params\\\":{\\\"_hedgeTimeThreshold\\\":\\\"the hedge time threshold, in seconds\\\"}},\\\"setHedgingTwapPeriod(uint32)\\\":{\\\"params\\\":{\\\"_hedgingTwapPeriod\\\":\\\"the twap period, in seconds\\\"}},\\\"setNonceTrue(uint256)\\\":{\\\"params\\\":{\\\"_nonce\\\":\\\"the number to be set true\\\"}},\\\"setOTCPriceTolerance(uint256)\\\":{\\\"params\\\":{\\\"_otcPriceTolerance\\\":\\\"the OTC price tolerance, in percent, scaled by 1e18\\\"}},\\\"setStrategyCap(uint256)\\\":{\\\"details\\\":\\\"deposits are rejected if it would put the strategy above the cap amountstrategy collateral can be above the cap amount due to hedging activities\\\",\\\"params\\\":{\\\"_capAmount\\\":\\\"the maximum strategy collateral in ETH, checked on deposits\\\"}},\\\"symbol()\\\":{\\\"details\\\":\\\"Returns the symbol of the token, usually a shorter version of the name.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC20-totalSupply}.\\\"},\\\"transfer(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\\\"},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"transferVault(address)\\\":{\\\"details\\\":\\\"strategy cap is set to 0 to avoid future deposits\\\",\\\"params\\\":{\\\"_newStrategy\\\":\\\"new strategy contract address\\\"}},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"params\\\":{\\\"_data\\\":\\\"callback data encoded as SwapCallbackData struct\\\",\\\"amount0Delta\\\":\\\"amount of token0\\\",\\\"amount1Delta\\\":\\\"amount of token1\\\"}},\\\"withdraw(uint256)\\\":{\\\"details\\\":\\\"provide strategy tokens and wSqueeth, returns ETH\\\",\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of strategy token to burn\\\"}},\\\"withdrawShutdown(uint256)\\\":{\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of strategy token to burn\\\"}}},\\\"stateVariables\\\":{\\\"ONE\\\":{\\\"details\\\":\\\"basic unit used for calculation\\\"},\\\"POWER_PERP_PERIOD\\\":{\\\"details\\\":\\\"the TWAP_PERIOD used in the PowerPerp Controller contract\\\"},\\\"_CRAB_BALANCE_TYPEHASH\\\":{\\\"details\\\":\\\"typehash for signed orders\\\"},\\\"ethWSqueethPool\\\":{\\\"details\\\":\\\"ETH:wSqueeth uniswap pool\\\"},\\\"hasRedeemedInShutdown\\\":{\\\"details\\\":\\\"set to true when redeemShortShutdown has been called\\\"},\\\"hedgePriceThreshold\\\":{\\\"details\\\":\\\"price movement to trigger a hedge (0.1*1e18 = 10%)\\\"},\\\"hedgeTimeThreshold\\\":{\\\"details\\\":\\\"time difference to trigger a hedge (seconds)\\\"},\\\"hedgingTwapPeriod\\\":{\\\"details\\\":\\\"twap period to use for hedge calculations\\\"},\\\"isInitialized\\\":{\\\"details\\\":\\\"true if CrabV2 was initialized\\\"},\\\"nonces\\\":{\\\"details\\\":\\\"store the used flag for a nonce for each address\\\"},\\\"oracle\\\":{\\\"details\\\":\\\"strategy uniswap oracle\\\"},\\\"priceAtLastHedge\\\":{\\\"details\\\":\\\"wSqueeth/Eth price when last hedge executed\\\"},\\\"strategyCap\\\":{\\\"details\\\":\\\"the cap in ETH for the strategy, above which deposits will be rejected\\\"},\\\"timeAtLastHedge\\\":{\\\"details\\\":\\\"timestamp when last hedge executed\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"checkPriceHedge()\\\":{\\\"notice\\\":\\\"check if hedging based on price threshold is allowed\\\"},\\\"checkTimeHedge()\\\":{\\\"notice\\\":\\\"check if hedging based on time threshold is allowed\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"strategy constructor\\\"},\\\"deposit()\\\":{\\\"notice\\\":\\\"deposit ETH into strategy\\\"},\\\"flashDeposit(uint256,uint24)\\\":{\\\"notice\\\":\\\"flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\"},\\\"flashWithdraw(uint256,uint256,uint24)\\\":{\\\"notice\\\":\\\"flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\"},\\\"getStrategyVaultId()\\\":{\\\"notice\\\":\\\"get power token strategy vault ID \\\"},\\\"getVaultDetails()\\\":{\\\"notice\\\":\\\"get the vault composition of the strategy \\\"},\\\"getWsqueethFromCrabAmount(uint256)\\\":{\\\"notice\\\":\\\"get wSqueeth debt amount associated with strategy token amount\\\"},\\\"initialize(uint256,uint256,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"initializes the collateral ratio after the first migration\\\"},\\\"redeemShortShutdown()\\\":{\\\"notice\\\":\\\"called to redeem the net value of a vault post shutdown\\\"},\\\"setHedgePriceThreshold(uint256)\\\":{\\\"notice\\\":\\\"owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\"},\\\"setHedgeTimeThreshold(uint256)\\\":{\\\"notice\\\":\\\"owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\"},\\\"setHedgingTwapPeriod(uint32)\\\":{\\\"notice\\\":\\\"owner can set the twap period in seconds that is used for calculating twaps for hedging\\\"},\\\"setNonceTrue(uint256)\\\":{\\\"notice\\\":\\\"set nonce to true\\\"},\\\"setOTCPriceTolerance(uint256)\\\":{\\\"notice\\\":\\\"owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\\"},\\\"setStrategyCap(uint256)\\\":{\\\"notice\\\":\\\"owner can set the strategy cap in ETH collateral terms\\\"},\\\"transferVault(address)\\\":{\\\"notice\\\":\\\"transfer vault NFT to new contract\\\"},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"notice\\\":\\\"uniswap swap callback function for flashes\\\"},\\\"withdraw(uint256)\\\":{\\\"notice\\\":\\\"withdraw WETH from strategy\\\"},\\\"withdrawShutdown(uint256)\\\":{\\\"notice\\\":\\\"called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\"}},\\\"notice\\\":\\\"Contract for Crab strategy\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/strategy/CrabStrategyV2.sol\\\":\\\"CrabStrategyV2\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\\\n *\\\\n * These functions can be used to verify that a message was signed by the holder\\\\n * of the private keys of a given address.\\\\n */\\\\nlibrary ECDSA {\\\\n    /**\\\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\\\n     * `signature`. This address can then be used for verification purposes.\\\\n     *\\\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\\\n     * this function rejects them by requiring the `s` value to be in the lower\\\\n     * half order, and the `v` value to be either 27 or 28.\\\\n     *\\\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\\\n     * verification to be secure: it is possible to craft signatures that\\\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\\\n     * this is by receiving a hash of the original message (which may otherwise\\\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\\\n     */\\\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\\\n        // Check the signature length\\\\n        if (signature.length != 65) {\\\\n            revert(\\\\\\\"ECDSA: invalid signature length\\\\\\\");\\\\n        }\\\\n\\\\n        // Divide the signature in r, s and v variables\\\\n        bytes32 r;\\\\n        bytes32 s;\\\\n        uint8 v;\\\\n\\\\n        // ecrecover takes the signature parameters, and the only way to get them\\\\n        // currently is to use assembly.\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly {\\\\n            r := mload(add(signature, 0x20))\\\\n            s := mload(add(signature, 0x40))\\\\n            v := byte(0, mload(add(signature, 0x60)))\\\\n        }\\\\n\\\\n        return recover(hash, v, r, s);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\\\n     * `r` and `s` signature fields separately.\\\\n     */\\\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\\\n        // the valid range for s in (281): 0 < s < secp256k1n \\\\u00f7 2 + 1, and for v in (282): v \\\\u2208 {27, 28}. Most\\\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\\\n        //\\\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\\\n        // these malleable signatures as well.\\\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\\\\\"ECDSA: invalid signature 's' value\\\\\\\");\\\\n        require(v == 27 || v == 28, \\\\\\\"ECDSA: invalid signature 'v' value\\\\\\\");\\\\n\\\\n        // If the signature is valid (and not malleable), return the signer address\\\\n        address signer = ecrecover(hash, v, r, s);\\\\n        require(signer != address(0), \\\\\\\"ECDSA: invalid signature\\\\\\\");\\\\n\\\\n        return signer;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\\\n     * replicates the behavior of the\\\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\\\n     * JSON-RPC method.\\\\n     *\\\\n     * See {recover}.\\\\n     */\\\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\\\n        // 32 is the length in bytes of hash,\\\\n        // enforced by the type signature above\\\\n        return keccak256(abi.encodePacked(\\\\\\\"\\\\\\\\x19Ethereum Signed Message:\\\\\\\\n32\\\\\\\", hash));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc80ce3fcc5e444a2c5bdb902fe4d4f4ecba04e9b416425697d00ae95c1955f82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/drafts/EIP712.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <0.8.0;\\\\n\\\\n/**\\\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\\\n *\\\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\\\n *\\\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\\\n * ({_hashTypedDataV4}).\\\\n *\\\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\\\n *\\\\n * NOTE: This contract implements the version of the encoding known as \\\\\\\"v4\\\\\\\", as implemented by the JSON RPC method\\\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\\\n *\\\\n * _Available since v3.4._\\\\n */\\\\nabstract contract EIP712 {\\\\n    /* solhint-disable var-name-mixedcase */\\\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\\\n    // invalidate the cached domain separator if the chain id changes.\\\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\\\n    uint256 private immutable _CACHED_CHAIN_ID;\\\\n\\\\n    bytes32 private immutable _HASHED_NAME;\\\\n    bytes32 private immutable _HASHED_VERSION;\\\\n    bytes32 private immutable _TYPE_HASH;\\\\n    /* solhint-enable var-name-mixedcase */\\\\n\\\\n    /**\\\\n     * @dev Initializes the domain separator and parameter caches.\\\\n     *\\\\n     * The meaning of `name` and `version` is specified in\\\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\\\n     *\\\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\\\n     * - `version`: the current major version of the signing domain.\\\\n     *\\\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\\\n     * contract upgrade].\\\\n     */\\\\n    constructor(string memory name, string memory version) {\\\\n        bytes32 hashedName = keccak256(bytes(name));\\\\n        bytes32 hashedVersion = keccak256(bytes(version));\\\\n        bytes32 typeHash = keccak256(\\\\\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\\\\\");\\\\n        _HASHED_NAME = hashedName;\\\\n        _HASHED_VERSION = hashedVersion;\\\\n        _CACHED_CHAIN_ID = _getChainId();\\\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\\\n        _TYPE_HASH = typeHash;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the domain separator for the current chain.\\\\n     */\\\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\\\n            return _CACHED_DOMAIN_SEPARATOR;\\\\n        } else {\\\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\\\n        }\\\\n    }\\\\n\\\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\\\n        return keccak256(\\\\n            abi.encode(\\\\n                typeHash,\\\\n                name,\\\\n                version,\\\\n                _getChainId(),\\\\n                address(this)\\\\n            )\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\\\n     *\\\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\\\n     *\\\\n     * ```solidity\\\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\\\n     *     keccak256(\\\\\\\"Mail(address to,string contents)\\\\\\\"),\\\\n     *     mailTo,\\\\n     *     keccak256(bytes(mailContents))\\\\n     * )));\\\\n     * address signer = ECDSA.recover(digest, signature);\\\\n     * ```\\\\n     */\\\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\\\n        return keccak256(abi.encodePacked(\\\\\\\"\\\\\\\\x19\\\\\\\\x01\\\\\\\", _domainSeparatorV4(), structHash));\\\\n    }\\\\n\\\\n    function _getChainId() private view returns (uint256 chainId) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly {\\\\n            chainId := chainid()\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4bc5cda2bfee483ff10334881c9ea5cc4df7faa7b18a5a4b8f02fc51cf8adca\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Safe casting methods\\\\n/// @notice Contains methods for safely casting between types\\\\nlibrary SafeCast {\\\\n    /// @notice Cast a uint256 to a uint160, revert on overflow\\\\n    /// @param y The uint256 to be downcasted\\\\n    /// @return z The downcasted integer, now type uint160\\\\n    function toUint160(uint256 y) internal pure returns (uint160 z) {\\\\n        require((z = uint160(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a int256 to a int128, revert on overflow or underflow\\\\n    /// @param y The int256 to be downcasted\\\\n    /// @return z The downcasted integer, now type int128\\\\n    function toInt128(int256 y) internal pure returns (int128 z) {\\\\n        require((z = int128(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a uint256 to a int256, revert on overflow\\\\n    /// @param y The uint256 to be casted\\\\n    /// @return z The casted integer, now type int256\\\\n    function toInt256(uint256 y) internal pure returns (int256 z) {\\\\n        require(y < 2**255);\\\\n        z = int256(y);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n/*\\\\n * @title Solidity Bytes Arrays Utils\\\\n * @author Gon\\\\u00e7alo S\\\\u00e1 <goncalo.sa@consensys.net>\\\\n *\\\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\\\n */\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nlibrary BytesLib {\\\\n    function slice(\\\\n        bytes memory _bytes,\\\\n        uint256 _start,\\\\n        uint256 _length\\\\n    ) internal pure returns (bytes memory) {\\\\n        require(_length + 31 >= _length, 'slice_overflow');\\\\n        require(_start + _length >= _start, 'slice_overflow');\\\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\\\n\\\\n        bytes memory tempBytes;\\\\n\\\\n        assembly {\\\\n            switch iszero(_length)\\\\n                case 0 {\\\\n                    // Get a location of some free memory and store it in tempBytes as\\\\n                    // Solidity does for memory variables.\\\\n                    tempBytes := mload(0x40)\\\\n\\\\n                    // The first word of the slice result is potentially a partial\\\\n                    // word read from the original array. To read it, we calculate\\\\n                    // the length of that partial word and start copying that many\\\\n                    // bytes into the array. The first word we copy will start with\\\\n                    // data we don't care about, but the last `lengthmod` bytes will\\\\n                    // land at the beginning of the contents of the new array. When\\\\n                    // we're done copying, we overwrite the full first word with\\\\n                    // the actual length of the slice.\\\\n                    let lengthmod := and(_length, 31)\\\\n\\\\n                    // The multiplication in the next line is necessary\\\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\\\n                    // the following copy loop was copying the origin's length\\\\n                    // and then ending prematurely not copying everything it should.\\\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\\\n                    let end := add(mc, _length)\\\\n\\\\n                    for {\\\\n                        // The multiplication in the next line has the same exact purpose\\\\n                        // as the one above.\\\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\\\n                    } lt(mc, end) {\\\\n                        mc := add(mc, 0x20)\\\\n                        cc := add(cc, 0x20)\\\\n                    } {\\\\n                        mstore(mc, mload(cc))\\\\n                    }\\\\n\\\\n                    mstore(tempBytes, _length)\\\\n\\\\n                    //update free-memory pointer\\\\n                    //allocating the array padded to 32 bytes like the compiler does now\\\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\\\n                }\\\\n                //if we want a zero-length slice let's just return a zero-length array\\\\n                default {\\\\n                    tempBytes := mload(0x40)\\\\n                    //zero out the 32 bytes slice we are about to return\\\\n                    //we need to do it because Solidity does not garbage collect\\\\n                    mstore(tempBytes, 0)\\\\n\\\\n                    mstore(0x40, add(tempBytes, 0x20))\\\\n                }\\\\n        }\\\\n\\\\n        return tempBytes;\\\\n    }\\\\n\\\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\\\n        address tempAddress;\\\\n\\\\n        assembly {\\\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\\\n        }\\\\n\\\\n        return tempAddress;\\\\n    }\\\\n\\\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\\\n        uint24 tempUint;\\\\n\\\\n        assembly {\\\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\\\n        }\\\\n\\\\n        return tempUint;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport './PoolAddress.sol';\\\\n\\\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\\\nlibrary CallbackValidation {\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param tokenA The contract address of either token0 or token1\\\\n    /// @param tokenB The contract address of the other token\\\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(\\\\n        address factory,\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool pool) {\\\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param poolKey The identifying key of the V3 pool\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\\\n        internal\\\\n        view\\\\n        returns (IUniswapV3Pool pool)\\\\n    {\\\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\\\n        require(msg.sender == address(pool));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.6.0;\\\\n\\\\nimport './BytesLib.sol';\\\\n\\\\n/// @title Functions for manipulating path data for multihop swaps\\\\nlibrary Path {\\\\n    using BytesLib for bytes;\\\\n\\\\n    /// @dev The length of the bytes encoded address\\\\n    uint256 private constant ADDR_SIZE = 20;\\\\n    /// @dev The length of the bytes encoded fee\\\\n    uint256 private constant FEE_SIZE = 3;\\\\n\\\\n    /// @dev The offset of a single token address and pool fee\\\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\\\n    /// @dev The offset of an encoded pool key\\\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\\\n\\\\n    /// @notice Returns true iff the path contains two or more pools\\\\n    /// @param path The encoded swap path\\\\n    /// @return True if path contains two or more pools, otherwise false\\\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\\\n    }\\\\n\\\\n    /// @notice Returns the number of pools in the path\\\\n    /// @param path The encoded swap path\\\\n    /// @return The number of pools in the path\\\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Decodes the first pool in path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return tokenA The first token of the given pool\\\\n    /// @return tokenB The second token of the given pool\\\\n    /// @return fee The fee level of the pool\\\\n    function decodeFirstPool(bytes memory path)\\\\n        internal\\\\n        pure\\\\n        returns (\\\\n            address tokenA,\\\\n            address tokenB,\\\\n            uint24 fee\\\\n        )\\\\n    {\\\\n        tokenA = path.toAddress(0);\\\\n        fee = path.toUint24(ADDR_SIZE);\\\\n        tokenB = path.toAddress(NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Gets the segment corresponding to the first pool in the path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return The segment containing all data necessary to target the first pool in the path\\\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(0, POP_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\\\n    /// @param path The swap path\\\\n    /// @return The remaining token + fee elements in the path\\\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/Power2Base.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary Power2Base {\\\\n    using SafeMath for uint256;\\\\n\\\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\\\n    uint256 private constant INDEX_SCALE = 1e4;\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    /**\\\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getUnscaledIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\\\n     */\\\\n    function _getDenormalizedMark(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _wSqueeth,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\\\n\\\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _weth weth address\\\\n     * @return returns value of debt in ETH\\\\n     */\\\\n    function _getDebtValueInEth(\\\\n        uint256 _debtAmount,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _wSqueeth,\\\\n        address _weth\\\\n    ) internal view returns (uint256) {\\\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle\\\\n     * @dev this will revert if period is > max period for the pool\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        // period reaching this point should be check, otherwise might revert\\\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\\\n     * @param _indexPriceForSettlement index price for settlement\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return amount in wei that should be paid to the token holder\\\\n     */\\\\n    function _getLongSettlementValue(\\\\n        uint256 _wsqueethAmount,\\\\n        uint256 _indexPriceForSettlement,\\\\n        uint256 _normalizationFactor\\\\n    ) internal pure returns (uint256) {\\\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1938180c41ec0ee817b841df605b199e15ffbbe94700b640d031b4e4665a89af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/CrabStrategyV2.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {StrategyBase} from \\\\\\\"./base/StrategyBase.sol\\\\\\\";\\\\nimport {StrategyFlashSwap} from \\\\\\\"./base/StrategyFlashSwap.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\nimport {EIP712} from \\\\\\\"@openzeppelin/contracts/drafts/EIP712.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./base/StrategyMath.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\nimport {ECDSA} from \\\\\\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Crab V2 Error Codes:\\\\n * C1: Caller is not timelock\\\\n * C2: Contract not yet initialized\\\\n * C3: Invalid oracle address\\\\n * C4: Invalid timelock address\\\\n * C5: Invalid ETH:WSqueeth address\\\\n * C6: Invalid crabMigration address\\\\n * C7: Invalid hedge time threshold\\\\n * C8: Invalid hedge price threshold\\\\n * C9: Cannot receive ETH\\\\n * C10: Caller not Crab Migration contract\\\\n * C11: Crab V2 already initialized\\\\n * C12: Squeeth contracts not shut down\\\\n * C13: Crab must redeemShortShutdown\\\\n * C14: Twap period is too short\\\\n * C15: Price tolerance is too high\\\\n * C16: Deposit exceeds strategy cap\\\\n * C17: Clearing Price should be below bid price\\\\n * C18: Clearing Price should be above offer price\\\\n * C19: Invalid offer signature\\\\n * C20: Order has expired\\\\n * C21: Manager Price should be greater than 0\\\\n * C22: Not a valid Time or Price hedge\\\\n * C23: Orders must take the opposite side of the hedge\\\\n * C24: All orders must be either buying or selling\\\\n * C25: Orders are not arranged properly\\\\n * C26: Crab contracts shut down\\\\n *  C27: Nonce already used.\\\\n */\\\\n\\\\n/**\\\\n * @dev CrabStrategyV2 contract\\\\n * @notice Contract for Crab strategy\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\\\n    uint256 public strategyCap;\\\\n\\\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\\\n\\\\n    /// @dev basic unit used for calculation\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    // @dev OTC price must be within this distance of the uniswap twap price\\\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\\\n\\\\n    // @dev OTC price tolerance cannot exceed 20%\\\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\\\n\\\\n    /// @dev twap period to use for hedge calculations\\\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\\\n    /// @dev true if CrabV2 was initialized\\\\n    bool public isInitialized;\\\\n\\\\n    /// @dev typehash for signed orders\\\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\\\n        keccak256(\\\\n            \\\\\\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\\\\\"\\\\n        );\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum FLASH_SOURCE {\\\\n        FLASH_DEPOSIT,\\\\n        FLASH_WITHDRAW\\\\n    }\\\\n\\\\n    /// @dev ETH:wSqueeth uniswap pool\\\\n    address public immutable ethWSqueethPool;\\\\n    /// @dev strategy uniswap oracle\\\\n    address public immutable oracle;\\\\n    address public immutable timelock;\\\\n    address public immutable crabMigration;\\\\n\\\\n    /// @dev time difference to trigger a hedge (seconds)\\\\n    uint256 public hedgeTimeThreshold;\\\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\\\n    uint256 public hedgePriceThreshold;\\\\n\\\\n    /// @dev timestamp when last hedge executed\\\\n    uint256 public timeAtLastHedge;\\\\n    /// @dev wSqueeth/Eth price when last hedge executed\\\\n    uint256 public priceAtLastHedge;\\\\n\\\\n    /// @dev set to true when redeemShortShutdown has been called\\\\n    bool private hasRedeemedInShutdown;\\\\n\\\\n    /// @dev store the used flag for a nonce for each address\\\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\\\n\\\\n    struct FlashDepositData {\\\\n        uint256 totalDeposit;\\\\n    }\\\\n\\\\n    struct FlashWithdrawData {\\\\n        uint256 crabAmount;\\\\n    }\\\\n\\\\n    struct Order {\\\\n        uint256 bidId;\\\\n        address trader;\\\\n        uint256 quantity;\\\\n        uint256 price;\\\\n        bool isBuying;\\\\n        uint256 expiry;\\\\n        uint256 nonce;\\\\n        uint8 v;\\\\n        bytes32 r;\\\\n        bytes32 s;\\\\n    }\\\\n\\\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\\\n    event HedgeOTCSingle(\\\\n        address trader,\\\\n        uint256 bidId,\\\\n        uint256 quantity,\\\\n        uint256 price,\\\\n        bool isBuying,\\\\n        uint256 clearingPrice\\\\n    );\\\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\\\n    event SetStrategyCap(uint256 newCapAmount);\\\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\\\n\\\\n    modifier onlyTimelock() {\\\\n        require(msg.sender == timelock, \\\\\\\"C1\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier afterInitialization() {\\\\n        require(isInitialized, \\\\\\\"C2\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy constructor\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _wSqueethController power token controller address\\\\n     * @param _oracle oracle address\\\\n     * @param _weth weth address\\\\n     * @param _uniswapFactory uniswap factory address\\\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\\\n     * @param _timelock timelock contract address\\\\n     * @param _crabMigration crab migration contract address\\\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\\\n     */\\\\n    constructor(\\\\n        address _wSqueethController,\\\\n        address _oracle,\\\\n        address _weth,\\\\n        address _uniswapFactory,\\\\n        address _ethWSqueethPool,\\\\n        address _timelock,\\\\n        address _crabMigration,\\\\n        uint256 _hedgeTimeThreshold,\\\\n        uint256 _hedgePriceThreshold\\\\n    )\\\\n        StrategyBase(_wSqueethController, _weth, \\\\\\\"Crab Strategy v2\\\\\\\", \\\\\\\"Crabv2\\\\\\\")\\\\n        StrategyFlashSwap(_uniswapFactory)\\\\n        EIP712(\\\\\\\"CrabOTC\\\\\\\", \\\\\\\"2\\\\\\\")\\\\n    {\\\\n        require(_oracle != address(0), \\\\\\\"C3\\\\\\\");\\\\n        require(_timelock != address(0), \\\\\\\"C4\\\\\\\");\\\\n        require(_ethWSqueethPool != address(0), \\\\\\\"C5\\\\\\\");\\\\n        require(_crabMigration != address(0), \\\\\\\"C6\\\\\\\");\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"C7\\\\\\\");\\\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\\\\\"C8\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        ethWSqueethPool = _ethWSqueethPool;\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n        timelock = _timelock;\\\\n        crabMigration = _crabMigration;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\\\\\"C9\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice initializes the collateral ratio after the first migration\\\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\\\n     * @param _crabSharesToMint crab shares to mint\\\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\\\n     * @param _strategyCap strategy cap for crab V2\\\\n     */\\\\n    function initialize(\\\\n        uint256 _wSqueethToMint,\\\\n        uint256 _crabSharesToMint,\\\\n        uint256 _timeAtLastHedge,\\\\n        uint256 _priceAtLastHedge,\\\\n        uint256 _strategyCap\\\\n    ) external payable {\\\\n        require(msg.sender == crabMigration, \\\\\\\"C10\\\\\\\");\\\\n        require(!isInitialized, \\\\\\\"C11\\\\\\\");\\\\n\\\\n        _setStrategyCap(_strategyCap);\\\\n\\\\n        uint256 amount = msg.value;\\\\n\\\\n        _checkStrategyCap(amount, 0);\\\\n\\\\n        // store hedge data from crab V1\\\\n        timeAtLastHedge = _timeAtLastHedge;\\\\n        priceAtLastHedge = _priceAtLastHedge;\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\\\n\\\\n        isInitialized = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice transfer vault NFT to new contract\\\\n     * @dev strategy cap is set to 0 to avoid future deposits\\\\n     * @param _newStrategy new strategy contract address\\\\n     */\\\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\\\n        _setStrategyCap(0);\\\\n\\\\n        emit VaultTransferred(_newStrategy, vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the strategy cap in ETH collateral terms\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\\\n        _setStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set strategy cap amount\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function _setStrategyCap(uint256 _capAmount) internal {\\\\n        strategyCap = _capAmount;\\\\n        emit SetStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to redeem the net value of a vault post shutdown\\\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\\\n     */\\\\n    function redeemShortShutdown() external afterInitialization {\\\\n        hasRedeemedInShutdown = true;\\\\n        powerTokenController.redeemShort(vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\\n     * @param _poolFee Uniswap pool fee\\\\n     */\\\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\\\n            _ethToDeposit,\\\\n            cachedStrategyDebt,\\\\n            cachedStrategyCollateral\\\\n        );\\\\n\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            _poolFee,\\\\n            wSqueethToMint,\\\\n            _ethToDeposit.sub(msg.value),\\\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\\\n            abi.encodePacked(_ethToDeposit)\\\\n        );\\\\n\\\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\\n     * @param _crabAmount strategy token amount to burn\\\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\\\n     * @param _poolFee Uniswap pool fee\\\\n\\\\n     */\\\\n    function flashWithdraw(\\\\n        uint256 _crabAmount,\\\\n        uint256 _maxEthToPay,\\\\n        uint24 _poolFee\\\\n    ) external nonReentrant {\\\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            _poolFee,\\\\n            exactWSqueethNeeded,\\\\n            _maxEthToPay,\\\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\\\n            abi.encodePacked(_crabAmount)\\\\n        );\\\\n\\\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit ETH into strategy\\\\n     * @dev provide ETH, return wSqueeth and strategy token\\\\n     */\\\\n    function deposit() external payable nonReentrant {\\\\n        uint256 amount = msg.value;\\\\n\\\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\\\n\\\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\\\n\\\\n        // send back ETH collateral\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n\\\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\\\n        require(powerTokenController.isShutDown(), \\\\\\\"C12\\\\\\\");\\\\n        require(hasRedeemedInShutdown, \\\\\\\"C13\\\\\\\");\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\\\n        _burn(msg.sender, _crabAmount);\\\\n\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set nonce to true\\\\n     * @param _nonce the number to be set true\\\\n     */\\\\n    function setNonceTrue(uint256 _nonce) external {\\\\n        nonces[msg.sender][_nonce] = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\\\n     * @param _crabAmount strategy token amount\\\\n     * @return wSqueeth amount\\\\n     */\\\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\\\n        return _getDebtFromStrategyAmount(_crabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\\\n     */\\\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\\\n        require(_hedgingTwapPeriod >= 180, \\\\\\\"C14\\\\\\\");\\\\n\\\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\\\n\\\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\\\n     */\\\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"C7\\\\\\\");\\\\n\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n\\\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\\\n     */\\\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\\\\\"C8\\\\\\\");\\\\n\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n\\\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\\\n     */\\\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\\\n        // Tolerance cannot be more than 20%\\\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\\\\\"C15\\\\\\\");\\\\n\\\\n        otcPriceTolerance = _otcPriceTolerance;\\\\n\\\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a user deposit puts the strategy above the cap\\\\n     * @dev reverts if a deposit amount puts strategy over the cap\\\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\\\n     * @param _depositAmount the user deposit amount in ETH\\\\n     * @param _strategyCollateral the updated strategy collateral\\\\n     */\\\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\\\\\"C16\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _strategyFlash(\\\\n        address _caller,\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        uint24 _fee,\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n\\\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\\\n            // will revert if data.totalDeposit is > eth balance in contract\\\\n            _deposit(_caller, data.totalDeposit, true);\\\\n\\\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\\\n\\\\n            // repay the flash swap\\\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\\\n\\\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\\\n\\\\n            // return excess eth to the user that was not needed for slippage\\\\n            if (address(this).balance > 0) {\\\\n                payable(_caller).sendValue(address(this).balance);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\\\n\\\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\\\n            uint256 ethToWithdraw = _withdraw(\\\\n                _caller,\\\\n                data.crabAmount,\\\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\\\n                true\\\\n            );\\\\n\\\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\\\n\\\\n            // use some amount of withdrawn ETH to repay flash swap\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\\\n\\\\n            // excess ETH not used to repay flash swap is transferred to the user\\\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\\\n\\\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\\\n\\\\n            if (proceeds > 0) {\\\\n                payable(_caller).sendValue(proceeds);\\\\n            }\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit into strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _depositor depositor address\\\\n     * @param _amount amount of ETH collateral to deposit\\\\n     * @param _isFlashDeposit true if called by flashDeposit\\\\n     * @return wSqueethToMint minted amount of WSqueeth\\\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\\\n     */\\\\n    function _deposit(\\\\n        address _depositor,\\\\n        uint256 _amount,\\\\n        bool _isFlashDeposit\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_amount, strategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\\\n\\\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\\\n\\\\n        return (wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\\\n     * @return ETH amount to withdraw\\\\n     */\\\\n    function _withdraw(\\\\n        address _from,\\\\n        uint256 _crabAmount,\\\\n        uint256 _wSqueethAmount,\\\\n        bool _isFlashWithdraw\\\\n    ) internal returns (uint256) {\\\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\\\n\\\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\\\n        _burn(_from, _crabAmount);\\\\n\\\\n        return ethToWithdraw;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev set nonce flag of the trader to true\\\\n     * @param _trader address of the signer\\\\n     * @param _nonce number that is to be traded only once\\\\n     */\\\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\\\n        require(!nonces[_trader][_nonce], \\\\\\\"C27\\\\\\\");\\\\n        nonces[_trader][_nonce] = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev view function to get the domain seperator used in signing\\\\n     */\\\\n    // solhint-disable-next-line func-name-mixedcase\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\\\n        return _domainSeparatorV4();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev check the signer and swap tokens in the order\\\\n     * @param _remainingAmount quantity the manager wants to trade\\\\n     * @param _clearingPrice the price at which all orders are traded\\\\n     * @param _order a signed order to swap tokens\\\\n     */\\\\n    function _execOrder(\\\\n        uint256 _remainingAmount,\\\\n        uint256 _clearingPrice,\\\\n        Order memory _order\\\\n    ) internal {\\\\n        // check that order beats clearing price\\\\n        if (_order.isBuying) {\\\\n            require(_clearingPrice <= _order.price, \\\\\\\"C17\\\\\\\");\\\\n        } else {\\\\n            require(_clearingPrice >= _order.price, \\\\\\\"C18\\\\\\\");\\\\n        }\\\\n\\\\n        _useNonce(_order.trader, _order.nonce);\\\\n        bytes32 structHash = keccak256(\\\\n            abi.encode(\\\\n                _CRAB_BALANCE_TYPEHASH,\\\\n                _order.bidId,\\\\n                _order.trader,\\\\n                _order.quantity,\\\\n                _order.price,\\\\n                _order.isBuying,\\\\n                _order.expiry,\\\\n                _order.nonce\\\\n            )\\\\n        );\\\\n\\\\n        bytes32 hash = _hashTypedDataV4(structHash);\\\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\\\n        require(offerSigner == _order.trader, \\\\\\\"C19\\\\\\\");\\\\n        require(_order.expiry >= block.timestamp, \\\\\\\"C20\\\\\\\");\\\\n\\\\n        // adjust quantity for partial fills\\\\n        if (_remainingAmount < _order.quantity) {\\\\n            _order.quantity = _remainingAmount;\\\\n        }\\\\n        // weth clearing price for the order\\\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\\\n\\\\n        if (_order.isBuying) {\\\\n            // trader sends weth and receives oSQTH\\\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\\\n            IWETH9(weth).withdraw(wethAmount);\\\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\\\n        } else {\\\\n            // trader sends oSQTH and receives weth\\\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\\\n            // wrap it\\\\n            IWETH9(weth).deposit{value: wethAmount}();\\\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\\\n        }\\\\n\\\\n        emit HedgeOTCSingle(\\\\n            _order.trader, // market maker\\\\n            _order.bidId,\\\\n            _order.quantity, // order oSQTH quantity\\\\n            _order.price, // order price\\\\n            _order.isBuying, // order direction\\\\n            _clearingPrice // executed price for order\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev hedge function to reduce delta using an array of signed orders\\\\n     * @param _totalQuantity quantity the manager wants to trade\\\\n     * @param _clearingPrice clearing price in weth\\\\n     * @param _isHedgeBuying direction of hedge trade\\\\n     * @param _orders an array of signed order to swap tokens\\\\n     */\\\\n    function hedgeOTC(\\\\n        uint256 _totalQuantity,\\\\n        uint256 _clearingPrice,\\\\n        bool _isHedgeBuying,\\\\n        Order[] memory _orders\\\\n    ) external onlyOwner afterInitialization {\\\\n        require(_clearingPrice > 0, \\\\\\\"C21\\\\\\\");\\\\n        require(_isTimeHedge() || _isPriceHedge(), \\\\\\\"C22\\\\\\\");\\\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\\\n\\\\n        timeAtLastHedge = block.timestamp;\\\\n        priceAtLastHedge = _clearingPrice;\\\\n\\\\n        uint256 remainingAmount = _totalQuantity;\\\\n        uint256 prevPrice = _orders[0].price;\\\\n        uint256 currentPrice = _orders[0].price;\\\\n        bool isOrderBuying = _orders[0].isBuying;\\\\n        require(_isHedgeBuying != isOrderBuying, \\\\\\\"C23\\\\\\\");\\\\n\\\\n        // iterate through order array and execute if valid\\\\n        for (uint256 i; i < _orders.length; ++i) {\\\\n            currentPrice = _orders[i].price;\\\\n            require(_orders[i].isBuying == isOrderBuying, \\\\\\\"C24\\\\\\\");\\\\n            if (_isHedgeBuying) {\\\\n                require(currentPrice >= prevPrice, \\\\\\\"C25\\\\\\\");\\\\n            } else {\\\\n                require(currentPrice <= prevPrice, \\\\\\\"C25\\\\\\\");\\\\n            }\\\\n            prevPrice = currentPrice;\\\\n\\\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\\\n\\\\n            if (remainingAmount > _orders[i].quantity) {\\\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\\\n            } else {\\\\n                break;\\\\n            }\\\\n        }\\\\n\\\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\\\n     * @param _price clearing price provided by manager\\\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\\\n     */\\\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\\\n        // Get twap\\\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\\\n\\\\n        if (_isHedgeBuying) {\\\\n            require(\\\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\\\n                \\\\\\\"Price too high relative to Uniswap twap.\\\\\\\"\\\\n            );\\\\n        } else {\\\\n            require(\\\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\\\n                \\\\\\\"Price too low relative to Uniswap twap.\\\\\\\"\\\\n            );\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sync strategy debt and collateral amount from vault\\\\n     * @return synced debt amount\\\\n     * @return synced collateral amount\\\\n     */\\\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\\\n\\\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\\\n     * @return the fee adjustment factor\\\\n     */\\\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\\\n            oracle,\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            POWER_PERP_PERIOD,\\\\n            false\\\\n        );\\\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\\\n     * @param _depositedAmount amount of deposited WETH\\\\n     * @param _strategyDebtAmount amount of strategy debt\\\\n     * @param _strategyCollateralAmount collateral amount in strategy\\\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\\\n     */\\\\n    function _calcWsqueethToMintAndFee(\\\\n        uint256 _depositedAmount,\\\\n        uint256 _strategyDebtAmount,\\\\n        uint256 _strategyCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 wSqueethToMint;\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\\\n        require(!isShutdown, \\\\\\\"C26\\\\\\\");\\\\n\\\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\\\n        );\\\\n\\\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\\\n\\\\n        return (wSqueethToMint, fee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if time hedging is allowed\\\\n     */\\\\n    function _isTimeHedge() internal view returns (bool) {\\\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function _isPriceHedge() internal view returns (bool) {\\\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\\\n\\\\n        return priceThreshold >= hedgePriceThreshold;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkPriceHedge() external view returns (bool) {\\\\n        return _isPriceHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkTimeHedge() external view returns (bool) {\\\\n        return _isTimeHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate amount of strategy token to mint for depositor\\\\n     * @param _amount amount of ETH deposited\\\\n     * @param _strategyCollateralAmount amount of strategy collateral\\\\n     * @param _crabTotalSupply total supply of strategy token\\\\n     * @return amount of strategy token to mint\\\\n     */\\\\n    function _calcSharesToMint(\\\\n        uint256 _amount,\\\\n        uint256 _strategyCollateralAmount,\\\\n        uint256 _crabTotalSupply\\\\n    ) internal pure returns (uint256) {\\\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\\\n\\\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\\\n\\\\n        return _amount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\\\n     * @param _crabAmount strategy token amount\\\\n     * @param _totalSupply strategy total supply\\\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\\\n     */\\\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\\\n        return _crabAmount.wdiv(_totalSupply);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\\\n     * @param _crabRatio crab ratio\\\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\\\n     * @return amount of ETH allowed to withdraw\\\\n     */\\\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8b1900ce7c5c79e38af489819462339a27d677e2bb8626f7aa6f784409cbf3fa\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyBase.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./StrategyMath.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../../libs/VaultLib.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev StrategyBase contract\\\\n * @notice base contract for PowerToken strategy\\\\n * @author opyn team\\\\n */\\\\ncontract StrategyBase is ERC20 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev power token controller\\\\n    IController public powerTokenController;\\\\n\\\\n    /// @dev WETH token\\\\n    address public immutable weth;\\\\n    address public immutable wPowerPerp;\\\\n\\\\n    /// @dev power token strategy vault ID\\\\n    uint256 public immutable vaultId;\\\\n\\\\n    /**\\\\n     * @notice constructor for StrategyBase\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _powerTokenController power token controller address\\\\n     * @param _weth weth token address\\\\n     * @param _name token name for strategy ERC20 token\\\\n     * @param _symbol token symbol for strategy ERC20 token\\\\n     */\\\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\\\n        require(_powerTokenController != address(0), \\\\\\\"invalid controller address\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"invalid weth address\\\\\\\");\\\\n\\\\n        weth = _weth;\\\\n        powerTokenController = IController(_powerTokenController);\\\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\\\n    }\\\\n    /**\\\\n     * @notice get power token strategy vault ID \\\\n     * @return vault ID\\\\n     */\\\\n    function getStrategyVaultId() external view returns (uint256) {\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n    */\\\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\\\n        return _getVaultDetails();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint WPowerPerp and deposit collateral\\\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\\\n     * @param _to receiver address\\\\n     * @param _wAmount amount of WPowerPerp to mint\\\\n     * @param _collateral amount of collateral to deposit\\\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\\\n     */\\\\n    function _mintWPowerPerp(\\\\n        address _to,\\\\n        uint256 _wAmount,\\\\n        uint256 _collateral,\\\\n        bool _keepWsqueeth\\\\n    ) internal {\\\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\\\n\\\\n        if (!_keepWsqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn WPowerPerp and withdraw collateral\\\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\\\n     * @param _from WPowerPerp holder address\\\\n     * @param _amount amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\\\n     */\\\\n    function _burnWPowerPerp(\\\\n        address _from,\\\\n        uint256 _amount,\\\\n        uint256 _collateralToWithdraw,\\\\n        bool _isOwnedWSqueeth\\\\n    ) internal {\\\\n        if (!_isOwnedWSqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\\\n        }\\\\n\\\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint strategy token\\\\n     * @param _to recepient address\\\\n     * @param _amount token amount\\\\n     */\\\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\\\n        _mint(_to, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get strategy debt amount for a specific strategy token amount\\\\n     * @param _strategyAmount strategy amount\\\\n     * @return debt amount\\\\n     */\\\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n     */\\\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\\\n\\\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\\\n    }\\\\n}\\\\n\\\\n\\\",\\\"keccak256\\\":\\\"0xa18ad4c34899e27bdf048a866834e05dda91ee8ff904fac23587dddf69a5d675\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyFlashSwap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\\\n\\\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\\\n    using Path for bytes;\\\\n    using SafeCast for uint256;\\\\n    using LowGasSafeMath for uint256;\\\\n    using LowGasSafeMath for int256;\\\\n\\\\n    /// @dev Uniswap factory address\\\\n    address public immutable factory;\\\\n\\\\n    struct SwapCallbackData {\\\\n        bytes path;\\\\n        address caller;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev constructor\\\\n     * @param _factory uniswap factory address\\\\n     */\\\\n    constructor(\\\\n        address _factory\\\\n    ) {\\\\n        require(_factory != address(0), \\\\\\\"invalid factory address\\\\\\\");\\\\n        factory = _factory;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap swap callback function for flashes\\\\n     * @param amount0Delta amount of token0\\\\n     * @param amount1Delta amount of token1\\\\n     * @param _data callback data encoded as SwapCallbackData struct\\\\n     */\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata _data\\\\n    ) external override {\\\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\\\n\\\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //ensure that callback comes from uniswap pool\\\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\\\n\\\\n        //determine the amount that needs to be repaid as part of the flashswap\\\\n        uint256 amountToPay =\\\\n            amount0Delta > 0\\\\n                ?  uint256(amount0Delta)\\\\n                :  uint256(amount1Delta);\\\\n        \\\\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountIn amount to sell\\\\n     * @param _amountOutMinimum minimum amount to receive\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountOut = _exactInputInternal(\\\\n            _amountIn,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n       \\\\n        //slippage limit check\\\\n        require(amountOut >= _amountOutMinimum, \\\\\\\"amount out less than min\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountOut exact amount to receive\\\\n     * @param _amountInMaximum maximum amount to sell\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountIn = _exactOutputInternal(\\\\n            _amountOut,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n        \\\\n        //slippage limit check\\\\n        require(amountIn <= _amountInMaximum, \\\\\\\"amount in greater than max\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice function to be called by uniswap callback. \\\\n     * @dev this function should be overridden by the child contract\\\\n     * param _caller initial strategy function caller\\\\n     * param _tokenIn token address sold\\\\n     * param _tokenOut token address bought\\\\n     * param _fee pool fee\\\\n     * param _amountToPay amount to pay for the pool second token\\\\n     * param _callData arbitrary data assigned with the flashswap call \\\\n     * param _callSource function call source\\\\n     */\\\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\\\n    \\\\n    /** \\\\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\\\n    * @param _amountIn amount of token to pay\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token bought (amountOut)\\\\n    */\\\\n    function _exactInputInternal(\\\\n        uint256 _amountIn,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n       \\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0, int256 amount1) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                _amountIn.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n        \\\\n        //determine the amountOut based on which token has a lower address\\\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\\\n    * @param _amountOut amount of token to receive\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token sold (amountIn)\\\\n    */\\\\n    function _exactOutputInternal(\\\\n        uint256 _amountOut,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n        \\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0Delta, int256 amount1Delta) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                -_amountOut.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n\\\\n        //determine the amountIn and amountOut based on which token has a lower address\\\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\\\n        // it's technically possible to not receive the full output amount,\\\\n        // so if no price limit has been specified, require this possibility away\\\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\\\n\\\\n        return amountIn;\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice returns the uniswap pool for the given token pair and fee\\\\n    * @dev the pool contract may or may not exist\\\\n    * @param tokenA address of first token \\\\n    * @param tokenB address of second token \\\\n    * @param fee fee tier for pool\\\\n    */\\\\n    function _getPool(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool) {\\\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x91b49caf229fd114fbb589e73056772cf15a0adaba0a6f5eca4dff9cd12b9575\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/base/StrategyMath.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: AGPL-3.0-only\\\\n\\\\n/// math.sol -- mixin for inline numerical wizardry\\\\n\\\\n// This program is free software: you can redistribute it and/or modify\\\\n// it under the terms of the GNU General Public License as published by\\\\n// the Free Software Foundation, either version 3 of the License, or\\\\n// (at your option) any later version.\\\\n\\\\n// This program is distributed in the hope that it will be useful,\\\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\\\n// GNU General Public License for more details.\\\\n\\\\n// You should have received a copy of the GNU General Public License\\\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\\\n\\\\npragma solidity >0.4.13;\\\\n\\\\n\\\\n/**\\\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\\\n * @dev change contract to library, added div() function\\\\n */\\\\nlibrary StrategyMath {\\\\n    function add(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x + y) >= x, \\\\\\\"ds-math-add-overflow\\\\\\\");\\\\n    }\\\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x - y) <= x, \\\\\\\"ds-math-sub-underflow\\\\\\\");\\\\n    }\\\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\\\n        require(y == 0 || (z = x * y) / y == x, \\\\\\\"ds-math-mul-overflow\\\\\\\");\\\\n    }\\\\n\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    function min(uint x, uint y) internal pure returns (uint z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function max(uint x, uint y) internal pure returns (uint z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n    function imin(int x, int y) internal pure returns (int z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function imax(int x, int y) internal pure returns (int z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n\\\\n    uint constant WAD = 10 ** 18;\\\\n    uint constant RAY = 10 ** 27;\\\\n\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), WAD / 2) / WAD;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), RAY / 2) / RAY;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, WAD), y / 2) / y;\\\\n    }\\\\n    //rounds to zero if x*y < RAY / 2\\\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, RAY), y / 2) / y;\\\\n    }\\\\n\\\\n    // Ceil A to a multiple m\\\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(sub(add(a, m), 1), m), m);\\\\n    }\\\\n\\\\n    // Floor A to a multiple m\\\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(a, m), m);\\\\n    }\\\\n\\\\n    // This famous algorithm is called \\\\\\\"exponentiation by squaring\\\\\\\"\\\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\\\n    //\\\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\\\n    //\\\\n    // These facts are why it works:\\\\n    //\\\\n    //  If n is even, then x^n = (x^2)^(n/2).\\\\n    //  If n is odd,  then x^n = x * x^(n-1),\\\\n    //   and applying the equation for even x gives\\\\n    //    x^n = x * (x^2)^((n-1) / 2).\\\\n    //\\\\n    //  Also, EVM division is flooring and\\\\n    //    floor[(n-1) / 2] = floor[n / 2].\\\\n    //\\\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\\\n        z = n % 2 != 0 ? x : RAY;\\\\n\\\\n        for (n /= 2; n != 0; n /= 2) {\\\\n            x = rmul(x, x);\\\\n\\\\n            if (n % 2 != 0) {\\\\n                z = rmul(z, x);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0xfec6fa07fbbb639f94321d6503f5363286776cf831215017ce28aae67295613b\\\",\\\"license\\\":\\\"AGPL-3.0-only\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x61022060405266b1a2bc2ec50000600955600a805463ffffffff19166101a41790553480156200002e57600080fd5b506040516200621538038062006215833981016040819052620000519162000669565b60405180604001604052806007815260200166437261624f544360c81b815250604051806040016040528060018152602001601960f91b815250878b8a6040518060400160405280601081526020016f21b930b11029ba3930ba32b3bc903b1960811b8152506040518060400160405280600681526020016521b930b13b1960d11b81525081818160039080519060200190620000f09291906200057c565b508051620001069060049060208401906200057c565b50506005805460ff19166012179055506001600160a01b038416620001485760405162461bcd60e51b81526004016200013f90620007af565b60405180910390fd5b6001600160a01b038316620001715760405162461bcd60e51b81526004016200013f90620007e6565b606083901b6001600160601b03191660805260058054610100600160a81b0319166101006001600160a01b0387811682029290921792839055604080516307f07b1360e41b815290519190930490911691637f07b130916004808301926020929190829003018186803b158015620001e857600080fd5b505afa158015620001fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000223919062000645565b6001600160601b031960609190911b1660a052600554604051630728cf2360e31b81526101009091046001600160a01b0316906339467918906200027190600090819081906004016200072a565b602060405180830381600087803b1580156200028c57600080fd5b505af1158015620002a1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002c7919062000711565b60c052505050506001600160a01b038116620002f75760405162461bcd60e51b81526004016200013f906200075c565b60601b6001600160601b03191660e052600160065560006200031862000510565b600780546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35081516020808401919091208251918301919091206101408290526101608190527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620003b162000514565b61012052620003c281848462000518565b6101005261018052505050506001600160a01b038816620003f75760405162461bcd60e51b81526004016200013f9062000855565b6001600160a01b038416620004205760405162461bcd60e51b81526004016200013f906200081d565b6001600160a01b038516620004495760405162461bcd60e51b81526004016200013f9062000871565b6001600160a01b038316620004725760405162461bcd60e51b81526004016200013f9062000740565b60008211620004955760405162461bcd60e51b81526004016200013f9062000793565b600081118015620004ae5750670de0b6b3a76400008111155b620004cd5760405162461bcd60e51b81526004016200013f9062000839565b6001600160601b0319606098891b81166101c05294881b85166101a052600b91909155600c5590851b82166101e05290931b90921661020052506200088d915050565b3390565b4690565b60008383836200052762000514565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620005b45760008555620005ff565b82601f10620005cf57805160ff1916838001178555620005ff565b82800160010185558215620005ff579182015b82811115620005ff578251825591602001919060010190620005e2565b506200060d92915062000611565b5090565b5b808211156200060d576000815560010162000612565b80516001600160a01b03811681146200064057600080fd5b919050565b60006020828403121562000657578081fd5b620006628262000628565b9392505050565b60008060008060008060008060006101208a8c03121562000688578485fd5b620006938a62000628565b9850620006a360208b0162000628565b9750620006b360408b0162000628565b9650620006c360608b0162000628565b9550620006d360808b0162000628565b9450620006e360a08b0162000628565b9350620006f360c08b0162000628565b925060e08a015191506101008a015190509295985092959850929598565b60006020828403121562000723578081fd5b5051919050565b9283526020830191909152604082015260600190565b602080825260029082015261219b60f11b604082015260600190565b60208082526017908201527f696e76616c696420666163746f72792061646472657373000000000000000000604082015260600190565b602080825260029082015261433760f01b604082015260600190565b6020808252601a908201527f696e76616c696420636f6e74726f6c6c65722061646472657373000000000000604082015260600190565b60208082526014908201527f696e76616c696420776574682061646472657373000000000000000000000000604082015260600190565b60208082526002908201526110cd60f21b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b602080825260029082015261433360f01b604082015260600190565b602080825260029082015261433560f01b604082015260600190565b60805160601c60a05160601c60c05160e05160601c61010051610120516101405161016051610180516101a05160601c6101c05160601c6101e05160601c6102005160601c615820620009f560003980610bb55280611d54525080611b495280611d2752508061119852806129395280612ace52806144a2525080610f4452806129665280612afb52806144c352508061264852508061268a5250806126695250806125ef52508061261f525080611a5f5280611fc45280614463525080610cb65280610fb6528061146e5280611c485280611cee5280612859528061328d5280613b3a5250806111bc52806118df52806120b052806129885280612b1d5280613329528061357952806136ad5280613a8152806144e452508061037f5280610f2052806118be52806120d152806129aa5280612b3f5280612e345280612ed65280612f6e5280612ff35280613465528061376152806137e7528061450552506158206000f3fe60806040526004361061036f5760003560e01c80637f07b130116101c6578063cae74029116100f7578063e9c3cb4f11610095578063f5d278e41161006f578063f5d278e41461095e578063f73e19c314610973578063fa461e3314610993578063fc5b73ff146109b3576103e1565b8063e9c3cb4f14610914578063f101d92f14610929578063f2fde38b1461093e576103e1565b8063d2dd9f79116100d1578063d2dd9f79146108ac578063d33219b4146108cc578063dcbab608146108e1578063dd62ed3e146108f4576103e1565b8063cae740291461087a578063cfa70b181461088f578063d0e30db0146108a4576103e1565b8063a457c2d711610164578063b52b7ff01161013e578063b52b7ff014610810578063bdd438b814610830578063c245168914610850578063c45a015514610865576103e1565b8063a457c2d7146107b0578063a9059cbb146107d0578063b24f719b146107f0576103e1565b80638f8b8dbc116101a05780638f8b8dbc1461074657806395d89b41146107665780639ff69a511461077b578063a319b29f1461079b576103e1565b80637f07b1301461070757806388626eb81461071c5780638da5cb5b14610731576103e1565b80633d65fdac116102a057806366a91b761161023e57806370a082311161021857806370a082311461069d578063715018a6146106bd5780637bcdc16e146106d25780637dc0d1d0146106f2576103e1565b806366a91b761461065e57806367b8c345146106735780636c1040a914610688576103e1565b80634d76e6fc1161027a5780634d76e6fc146105ef578063502e1a1614610604578063533092ef1461062457806363bbc4b614610649576103e1565b80633d65fdac146105a55780633dcb0c5d146105c55780633fc8cef3146105da576103e1565b8063313ce5671161030d578063392e53cd116102e7578063392e53cd1461052e5780633950935114610543578063395ebb69146105635780633d3a62ee14610585576103e1565b8063313ce567146104e257806333194c0a146105045780633644e51514610519576103e1565b806318160ddd1161034957806318160ddd1461045e57806323b872dd14610480578063281e78d1146104a05780632e1a7d4d146104c2576103e1565b806306fdde03146103e6578063095ea7b3146104115780630ca514cd1461043e576103e1565b366103e157336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103ba575060055461010090046001600160a01b031633145b6103df5760405162461bcd60e51b81526004016103d69061547e565b60405180910390fd5b005b600080fd5b3480156103f257600080fd5b506103fb6109c6565b604051610408919061511f565b60405180910390f35b34801561041d57600080fd5b5061043161042c366004614a72565b610a5d565b60405161040891906150d3565b34801561044a57600080fd5b506103df610459366004614cd2565b610a7b565b34801561046a57600080fd5b50610473610b25565b6040516104089190614fab565b34801561048c57600080fd5b5061043161049b366004614a32565b610b2b565b3480156104ac57600080fd5b506104b5610bb3565b6040516104089190614fb4565b3480156104ce57600080fd5b506103df6104dd366004614cd2565b610bd7565b3480156104ee57600080fd5b506104f7610cab565b604051610408919061559b565b34801561051057600080fd5b50610473610cb4565b34801561052557600080fd5b50610473610cd8565b34801561053a57600080fd5b50610431610ce7565b34801561054f57600080fd5b5061043161055e366004614a72565b610cf8565b34801561056f57600080fd5b50610578610d46565b604051610408919061558a565b34801561059157600080fd5b506103df6105a0366004614cd2565b610d4c565b3480156105b157600080fd5b506103df6105c0366004614cd2565b610ee4565b3480156105d157600080fd5b506104b5610f0a565b3480156105e657600080fd5b506104b5610f1e565b3480156105fb57600080fd5b506104b5610f42565b34801561061057600080fd5b5061043161061f366004614a72565b610f66565b34801561063057600080fd5b50610639610f86565b6040516104089493929190615078565b34801561065557600080fd5b50610473610fa2565b34801561066a57600080fd5b50610473610fa8565b34801561067f57600080fd5b50610473610fae565b34801561069457600080fd5b50610473610fb4565b3480156106a957600080fd5b506104736106b83660046149c2565b610fd8565b3480156106c957600080fd5b506103df610ff7565b3480156106de57600080fd5b506103df6106ed366004614cd2565b6110c2565b3480156106fe57600080fd5b506104b5611196565b34801561071357600080fd5b506104b56111ba565b34801561072857600080fd5b506104316111de565b34801561073d57600080fd5b506104b56111e8565b34801561075257600080fd5b506103df610761366004614ef1565b6111f7565b34801561077257600080fd5b506103fb6112d7565b34801561078757600080fd5b506103df610796366004614cd2565b611338565b3480156107a757600080fd5b506103df611409565b3480156107bc57600080fd5b506104316107cb366004614a72565b6114ca565b3480156107dc57600080fd5b506104316107eb366004614a72565b611532565b3480156107fc57600080fd5b506103df61080b366004614d2d565b611546565b34801561081c57600080fd5b506103df61082b366004614e83565b61184f565b34801561083c57600080fd5b506103df61084b366004614cd2565b611976565b34801561085c57600080fd5b50610431611a53565b34801561087157600080fd5b506104b5611a5d565b34801561088657600080fd5b50610473611a81565b34801561089b57600080fd5b50610473611a87565b6103df611a93565b3480156108b857600080fd5b506103df6108c73660046149c2565b611b3e565b3480156108d857600080fd5b506104b5611d25565b6103df6108ef366004614eb7565b611d49565b34801561090057600080fd5b5061047361090f3660046149fa565b611e0f565b34801561092057600080fd5b50610473611e3a565b34801561093557600080fd5b50610473611e40565b34801561094a57600080fd5b506103df6109593660046149c2565b611e46565b34801561096a57600080fd5b50610578611f68565b34801561097f57600080fd5b5061047361098e366004614cd2565b611f74565b34801561099f57600080fd5b506103df6109ae366004614adc565b611f7f565b6103df6109c1366004614d02565b612025565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b820191906000526020600020905b815481529060010190602001808311610a3557829003601f168201915b505050505090505b90565b6000610a71610a6a612172565b8484612176565b5060015b92915050565b610a83612172565b6001600160a01b0316610a946111e8565b6001600160a01b031614610aef576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff16610b195760405162461bcd60e51b81526004016103d6906151f7565b610b2281612262565b50565b60025490565b6000610b38848484612297565b610ba884610b44612172565b610ba385604051806060016040528060288152602001615734602891396001600160a01b038a16600090815260016020526040812090610b82612172565b6001600160a01b0316815260208101919091526040016000205491906123f2565b612176565b5060015b9392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60026006541415610c2f576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610c3f82612489565b90506000610c5033848460006124b4565b9050610c5c3382612501565b336001600160a01b03167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94848484604051610c9993929190615574565b60405180910390a25050600160065550565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce26125eb565b905090565b600a54640100000000900460ff1681565b6000610a71610d05612172565b84610ba38560016000610d16612172565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906126b5565b6101a481565b60026006541415610da4576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600681905550600560019054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610dfc57600080fd5b505af1158015610e10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e349190614a9d565b610e505760405162461bcd60e51b81526004016103d6906153ee565b600f5460ff16610e725760405162461bcd60e51b81526004016103d6906152aa565b6000610e8582610e80610b25565b61270f565b90506000610e93824761271b565b9050610e9f3384612727565b610ea93382612501565b336001600160a01b03167fe9ab9870b9093d99f8e981919f65ad09b7ae90ff80f1031639af9e0357eb9ed68483604051610c99929190615549565b33600090815260106020908152604080832093835292905220805460ff19166001179055565b60055461010090046001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b601060209081526000928352604080842090915290825290205460ff1681565b600080600080610f94612823565b935093509350935090919293565b600e5481565b600b5481565b600d5481565b7f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0381166000908152602081905260409020545b919050565b610fff612172565b6001600160a01b03166110106111e8565b6001600160a01b03161461106b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6007546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36007805473ffffffffffffffffffffffffffffffffffffffff19169055565b6110ca612172565b6001600160a01b03166110db6111e8565b6001600160a01b031614611136576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081116111565760405162461bcd60e51b81526004016103d69061540b565b600b8190556040517f28e0e4ee0b14d4b056ce88e1bcd890ccd32b22e213723c8765901381b5eae7059061118b908390614fab565b60405180910390a150565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce261291a565b6007546001600160a01b031690565b6111ff612172565b6001600160a01b03166112106111e8565b6001600160a01b03161461126b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60b48163ffffffff1610156112925760405162461bcd60e51b81526004016103d690615169565b600a805463ffffffff191663ffffffff83161790556040517f1cd9c7f99a5530a38c8f2b387dcc78e8a76cb5b203e0c4316a66777d993dee359061118b90839061558a565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b611340612172565b6001600160a01b03166113516111e8565b6001600160a01b0316146113ac576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6702c68af0bb1400008111156113d45760405162461bcd60e51b81526004016103d6906153d1565b60098190556040517f829c71710efa317bbdb8e5c4ca2b6d2551b7c2d7d37ea199975807eb3f5c0e7c9061118b908390614fab565b600a54640100000000900460ff166114335760405162461bcd60e51b81526004016103d6906151f7565b600f8054600160ff19909116179055600554604051634bf7d4a160e11b81526101009091046001600160a01b0316906397efa94290611496907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b600060405180830381600087803b1580156114b057600080fd5b505af11580156114c4573d6000803e3d6000fd5b50505050565b6000610a716114d7612172565b84610ba3856040518060600160405280602581526020016157c66025913960016000611501612172565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906123f2565b6000610a7161153f612172565b8484612297565b61154e612172565b6001600160a01b031661155f6111e8565b6001600160a01b0316146115ba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff166115e45760405162461bcd60e51b81526004016103d6906151f7565b600083116116045760405162461bcd60e51b81526004016103d690615398565b61160c612a90565b8061161a575061161a61291a565b6116365760405162461bcd60e51b81526004016103d690615444565b6116408383612ab1565b42600d55600e839055805184906000908390829061165a57fe5b602002602001015160600151905060008360008151811061167757fe5b602002602001015160600151905060008460008151811061169457fe5b602002602001015160800151905080151586151514156116c65760405162461bcd60e51b81526004016103d690615324565b60005b85518110156117ef578581815181106116de57fe5b60200260200101516060015192508115158682815181106116fb57fe5b6020026020010151608001511515146117265760405162461bcd60e51b81526004016103d690615427565b8615611751578383101561174c5760405162461bcd60e51b81526004016103d690615341565b611771565b838311156117715760405162461bcd60e51b81526004016103d690615341565b829350611792858988848151811061178557fe5b6020026020010151612c71565b85818151811061179e57fe5b6020026020010151604001518511156117e2576117db8682815181106117c057fe5b602002602001015160400151866130e390919063ffffffff16565b94506117e7565b6117ef565b6001016116c9565b507fbbc3ba742efe346cfdf333000069964e0ee3087c68da267dac977d299f2366fb8560008151811061181e57fe5b60200260200101516000015189888a60405161183d9493929190615557565b60405180910390a15050505050505050565b600260065414156118a7576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560006118b784612489565b90506119287f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084848760018a6040516020016119149190614fab565b60405160208183030381529060405261313b565b336001600160a01b03167fa13b272c1cf13ba724064d3d4809d9f557aab8da2bb582cba031a2f57e728e9d8583604051611963929190615549565b60405180910390a2505060016006555050565b61197e612172565b6001600160a01b031661198f6111e8565b6001600160a01b0316146119ea576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081118015611a025750670de0b6b3a76400008111155b611a1e5760405162461bcd60e51b81526004016103d6906154d4565b600c8190556040517f789e4b8ad1c375952cea7f07c9b3b6619a84b406432b948246cecb8ced96b9fa9061118b908390614fab565b6000610ce2612a90565b7f000000000000000000000000000000000000000000000000000000000000000081565b60085481565b6702c68af0bb14000081565b60026006541415611aeb576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065534600080611aff3384836131bc565b91509150336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158383604051610c99929190615549565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611b865760405162461bcd60e51b81526004016103d6906153b5565b600a54640100000000900460ff16611bb05760405162461bcd60e51b81526004016103d6906151f7565b600560019054906101000a90046001600160a01b03166001600160a01b0316639d4c94426040518163ffffffff1660e01b815260040160206040518083038186803b158015611bfe57600080fd5b505afa158015611c12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3691906149de565b6001600160a01b03166342842e0e30837f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401611c8593929190614fc8565b600060405180830381600087803b158015611c9f57600080fd5b505af1158015611cb3573d6000803e3d6000fd5b50505050611cc16000612262565b806001600160a01b03167fae97956757017853415251f661bfe857898f44ddb9c90b2483065719b84b0c697f0000000000000000000000000000000000000000000000000000000000000000604051611d1a9190614fab565b60405180910390a250565b7f000000000000000000000000000000000000000000000000000000000000000081565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611d915760405162461bcd60e51b81526004016103d69061528d565b600a54640100000000900460ff1615611dbc5760405162461bcd60e51b81526004016103d69061535e565b611dc581612262565b34611dd1816000613230565b600d849055600e839055611de8338783600061325f565b611df233866133b9565b5050600a805464ff00000000191664010000000017905550505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60095481565b600c5481565b611e4e612172565b6001600160a01b0316611e5f6111e8565b6001600160a01b031614611eba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611eff5760405162461bcd60e51b81526004018080602001828103825260268152602001806156486026913960400191505060405180910390fd5b6007546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600a5463ffffffff1681565b6000610a7582612489565b6000841380611f8e5750600083135b611f9757600080fd5b6000611fa582840184614b72565b90506000806000611fb984600001516133c3565b925092509250611feb7f00000000000000000000000000000000000000000000000000000000000000008484846133f4565b506000808913611ffb5787611ffd565b885b905061201a8560200151858585858a606001518b60400151613413565b505050505050505050565b6002600654141561207d576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560008061208d6138ec565b9150915061209b8482613230565b60006120a8858484613906565b5090506121237f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086846120fc8a346130e3565b60008b60405160200161210f9190614fab565b604051602081830303815290604052613995565b336001600160a01b03167f5d85169ff8329e90f3225f9798e0eba54d00c55d3bbfe201a0d1606febb23a8e868360405161215e929190615549565b60405180910390a250506001600655505050565b3390565b6001600160a01b0383166121bb5760405162461bcd60e51b81526004018080602001828103825260248152602001806157a26024913960400191505060405180910390fd5b6001600160a01b0382166122005760405162461bcd60e51b815260040180806020018281038252602281526020018061566e6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60088190556040517f29600e2e028c8c5c2b112d021938e0d0237d8fafcbb20394c56cf9fa4661ca279061118b908390614fab565b6001600160a01b0383166122dc5760405162461bcd60e51b815260040180806020018281038252602581526020018061577d6025913960400191505060405180910390fd5b6001600160a01b0382166123215760405162461bcd60e51b81526004018080602001828103825260238152602001806156036023913960400191505060405180910390fd5b61232c8383836125e6565b61236981604051806060016040528060268152602001615690602691396001600160a01b03861660009081526020819052604090205491906123f2565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461239890826126b5565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156124815760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561244657818101518382015260200161242e565b50505050905090810190601f1680156124735780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600080612494612823565b9350505050610bac6124a4610b25565b6124ae8386613a0c565b90613a45565b6000806124bf6138ec565b91505060006124d086610e80610b25565b905060006124de828461271b565b90506124ec88878388613a65565b6124f68888612727565b979650505050505050565b80471015612556576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146125a1576040519150601f19603f3d011682016040523d82523d6000602084013e6125a6565b606091505b50509050806125e65760405162461bcd60e51b815260040180806020018281038252603a8152602001806156b6603a913960400191505060405180910390fd5b505050565b60007f0000000000000000000000000000000000000000000000000000000000000000612616613b94565b141561264357507f0000000000000000000000000000000000000000000000000000000000000000610a5a565b6126ae7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000613b98565b9050610a5a565b600082820183811015610bac576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610bac8383613a45565b6000610bac8284613a0c565b6001600160a01b03821661276c5760405162461bcd60e51b815260040180806020018281038252602181526020018061575c6021913960400191505060405180910390fd5b612778826000836125e6565b6127b581604051806060016040528060228152602001615626602291396001600160a01b03851660009081526020819052604090205491906123f2565b6001600160a01b0383166000908152602081905260409020556002546127db9082613bfa565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600554604051634632752560e11b8152600091829182918291829161010090046001600160a01b031690638c64ea4a90612881907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b60806040518083038186803b15801561289957600080fd5b505afa1580156128ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d19190614c30565b805160208201516040830151606090930151919863ffffffff90911697506bffffffffffffffffffffffff90921695506fffffffffffffffffffffffffffffffff169350915050565b600a5460405163cce79bd560e01b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd5916129de917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff90911690600190600401614fec565b60206040518083038186803b1580156129f657600080fd5b505afa158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190614cea565b90506000612a47600e5483613a4590919063ffffffff16565b90506000670de0b6b3a76400008211612a7157612a6c670de0b6b3a7640000836130e3565b612a83565b612a8382670de0b6b3a76400006130e3565b600c541115935050505090565b6000612aa9600b54600d54613c5790919063ffffffff16565b421015905090565b600a5460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591612b71917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff1690600190600401614fec565b60206040518083038186803b158015612b8957600080fd5b505afa158015612b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc19190614cea565b90508115612c2657612c02670de0b6b3a7640000612bfc612bf5600954670de0b6b3a7640000613c5790919063ffffffff16565b8490613caf565b90613d1b565b831115612c215760405162461bcd60e51b81526004016103d6906152c7565b6125e6565b612c52670de0b6b3a7640000612bfc612bf5600954670de0b6b3a76400006130e390919063ffffffff16565b8310156125e65760405162461bcd60e51b81526004016103d690615230565b806080015115612ca4578060600151821115612c9f5760405162461bcd60e51b81526004016103d69061549a565b612cc8565b8060600151821015612cc85760405162461bcd60e51b81526004016103d69061537b565b612cda81602001518260c00151613d7a565b60007fc8aea8e60353611f3ed5409dad2d3173390bd252431198e7300eda67fefb66b1826000015183602001518460400151856060015186608001518760a001518860c00151604051602001612d379897969594939291906150de565b6040516020818303038152906040528051906020012090506000612d5a82613dee565b90506000612d78828560e00151866101000151876101200151613e3a565b905083602001516001600160a01b0316816001600160a01b031614612daf5760405162461bcd60e51b81526004016103d690615461565b428460a001511015612dd35760405162461bcd60e51b81526004016103d690615186565b8360400151861015612de757604084018690525b6000612e0c670de0b6b3a7640000612bfc888860400151613caf90919063ffffffff16565b9050846080015115612f575760208501516040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916323b872dd91612e6c919030908690600401614fc8565b602060405180830381600087803b158015612e8657600080fd5b505af1158015612e9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ebe9190614a9d565b50604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612f0b908490600401614fab565b600060405180830381600087803b158015612f2557600080fd5b505af1158015612f39573d6000803e3d6000fd5b50505050612f528560200151866040015183600061325f565b613085565b612f6c85602001518660400151836000613a65565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612fc757600080fd5b505af1158015612fdb573d6000803e3d6000fd5b50505050602086015160405163a9059cbb60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063a9059cbb9161303191859060040161505f565b602060405180830381600087803b15801561304b57600080fd5b505af115801561305f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130839190614a9d565b505b7f68c36f17c620d197a81d3aeff305f83abf3bb29943a38cd6efc299041238652d856020015186600001518760400151886060015189608001518b6040516130d29695949392919061509e565b60405180910390a150505050505050565b80820382811115610a75576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b60006131908530600060405180608001604052808c8c8f60405160200161316493929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052613faf565b9050838111156131b25760405162461bcd60e51b81526004016103d6906151c0565b5050505050505050565b6000806000806131ca6138ec565b915091506131d88682613230565b6000806131e6888585613906565b909250905060006132086131fa8a846130e3565b85613203610b25565b61411c565b90506132168a848b8b61325f565b6132208a826133b9565b9199919850909650505050505050565b60085461323d8284613c57565b111561325b5760405162461bcd60e51b81526004016103d690615213565b5050565b600554604051630728cf2360e31b81526101009091046001600160a01b03169063394679189084906132ba907f0000000000000000000000000000000000000000000000000000000000000000908890600090600401615574565b6020604051808303818588803b1580156132d357600080fd5b505af11580156132e7573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061330c9190614cea565b50806114c45760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613360908790879060040161505f565b602060405180830381600087803b15801561337a57600080fd5b505af115801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b29190614a9d565b5050505050565b61325b828261416b565b600080806133d1848261425b565b92506133de846014614327565b90506133eb84601761425b565b91509193909250565b600061340a856134058686866143e3565b614439565b95945050505050565b60008160ff16600181111561342457fe5b600181111561342f57fe5b14156136665760008280602001905181019061344b9190614b57565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906134a2903090600401614fb4565b60206040518083038186803b1580156134ba57600080fd5b505afa1580156134ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f29190614cea565b6040518263ffffffff1660e01b815260040161350e9190614fab565b600060405180830381600087803b15801561352857600080fd5b505af115801561353c573d6000803e3d6000fd5b5050505061355088826000015160016131bc565b5050600061355f88888861445c565b60405163a9059cbb60e01b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906135b0908490899060040161505f565b602060405180830381600087803b1580156135ca57600080fd5b505af11580156135de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136029190614a9d565b50886001600160a01b03167fc355ebece16d7e85e486911f0cde1074bc4bd3fec251c88cdddc7076d3e99adb864760405161363e929190615549565b60405180910390a2471561365f5761365f6001600160a01b038a1647612501565b50506138e3565b60018160ff16600181111561367757fe5b600181111561368257fe5b14156138e35760008280602001905181019061369e9190614b57565b9050600061374e8983600001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016136f79190614fb4565b60206040518083038186803b15801561370f57600080fd5b505afa158015613723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137479190614cea565b60016124b4565b9050600061375d89898961445c565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b1580156137ba57600080fd5b505af11580156137ce573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250613821915084908a9060040161505f565b602060405180830381600087803b15801561383b57600080fd5b505af115801561384f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138739190614a9d565b50600061388083886130e3565b90508a6001600160a01b03167f6f3269a64126ef2a1959892f3d921e81865181e09a7f72f55d3a49550c53b48d88836040516138bd929190615549565b60405180910390a280156138de576138de6001600160a01b038c1682612501565b505050505b50505050505050565b6000806000806138fa612823565b96509450505050509091565b60008060008061391461449a565b9050600086158015613924575085155b80156139365750613933610b25565b15155b905080156139565760405162461bcd60e51b81526004016103d6906151a3565b61397761396d6139668985613a0c565b8890613c57565b6124ae8a8a613a0c565b925060006139858484613a0c565b9399939850929650505050505050565b60006139ea8530600060405180608001604052808d8c8e6040516020016139be93929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526145d1565b9050838110156131b25760405162461bcd60e51b81526004016103d690615132565b6000670de0b6b3a7640000613a36613a248585613caf565b6002670de0b6b3a76400005b04613c57565b81613a3d57fe5b049392505050565b600081613a36613a5d85670de0b6b3a7640000613caf565b600285613a30565b80613b0e576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90613aba90879030908890600401614fc8565b602060405180830381600087803b158015613ad457600080fd5b505af1158015613ae8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b0c9190614a9d565b505b600554604051638632cb0360e01b81526101009091046001600160a01b031690638632cb0390613b66907f00000000000000000000000000000000000000000000000000000000000000009087908790600401615574565b600060405180830381600087803b158015613b8057600080fd5b505af11580156131b2573d6000803e3d6000fd5b4690565b6000838383613ba5613b94565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b600082821115613c51576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b80820182811015610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000811580613cca57505080820282828281613cc757fe5b04145b610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000808211613d71576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613a3d57fe5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff1615613dbe5760405162461bcd60e51b81526004016103d6906154b7565b6001600160a01b03909116600090815260106020908152604080832093835292905220805460ff19166001179055565b6000613df86125eb565b82604051602001808061190160f01b81525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613e9b5760405162461bcd60e51b81526004018080602001828103825260228152602001806156f06022913960400191505060405180910390fd5b8360ff16601b1480613eb057508360ff16601c145b613eeb5760405162461bcd60e51b81526004018080602001828103825260228152602001806157126022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613f47573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661340a576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b600080600080613fc285600001516133c3565b919450925090506001600160a01b0380841690831610600080613fe685878661445c565b6001600160a01b031663128acb088b85613fff8f614710565b6000036001600160a01b038e1615614017578d61403d565b876140365773fffd8963efd1fc6a506488495d951d5263988d2561403d565b6401000276a45b8d60405160200161404e91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161407d959493929190615025565b6040805180830381600087803b15801561409657600080fd5b505af11580156140aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140ce9190614ab9565b91509150600080846140e45782846000036140ea565b83836000035b915091508a6001600160a01b03166000141561410c578c811461410c57600080fd5b509b9a5050505050505050505050565b60008061413361412c8587613c57565b8690613a45565b905082156141625761415a614150670de0b6b3a7640000836130e3565b6124ae8584613a0c565b915050610bac565b50929392505050565b6001600160a01b0382166141c6576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6141d2600083836125e6565b6002546141df90826126b5565b6002556001600160a01b03821660009081526020819052604090205461420590826126b5565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000818260140110156142b5576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b816014018351101561430e576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015614381576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156143da576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6143eb6148c8565b826001600160a01b0316846001600160a01b03161115614409579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b60006144458383614726565b9050336001600160a01b03821614610a7557600080fd5b60006144927f000000000000000000000000000000000000000000000000000000000000000061448d8686866143e3565b614726565b949350505050565b60008061452e7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a46000614822565b90506000600560019054906101000a90046001600160a01b03166001600160a01b031663978bbdb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561458057600080fd5b505afa158015614594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145b89190614cea565b90506145ca612710612bfc8484613caf565b9250505090565b6000806000806145e485600001516133c3565b919450925090506001600160a01b038083169084161060008061460886868661445c565b6001600160a01b031663128acb088b856146218f614710565b6001600160a01b038e1615614636578d61465c565b876146555773fffd8963efd1fc6a506488495d951d5263988d2561465c565b6401000276a45b8d60405160200161466d91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161469c959493929190615025565b6040805180830381600087803b1580156146b557600080fd5b505af11580156146c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146ed9190614ab9565b91509150826146fc57816146fe565b805b6000039b9a5050505050505050505050565b6000600160ff1b821061472257600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b03161061474e57600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b15801561489157600080fd5b505afa1580156148a5573d6000803e3d6000fd5b505050506040513d60208110156148bb57600080fd5b5051979650505050505050565b604080516060810182526000808252602082018190529181019190915290565b8035610ff2816155cd565b8035610ff2816155e2565b600082601f83011261490e578081fd5b813567ffffffffffffffff81111561492257fe5b614935601f8201601f19166020016155a9565b818152846020838601011115614949578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215614974578081fd5b6040516020810181811067ffffffffffffffff8211171561499157fe5b6040529151825250919050565b803562ffffff81168114610ff257600080fd5b803560ff81168114610ff257600080fd5b6000602082840312156149d3578081fd5b8135610bac816155cd565b6000602082840312156149ef578081fd5b8151610bac816155cd565b60008060408385031215614a0c578081fd5b8235614a17816155cd565b91506020830135614a27816155cd565b809150509250929050565b600080600060608486031215614a46578081fd5b8335614a51816155cd565b92506020840135614a61816155cd565b929592945050506040919091013590565b60008060408385031215614a84578182fd5b8235614a8f816155cd565b946020939093013593505050565b600060208284031215614aae578081fd5b8151610bac816155e2565b60008060408385031215614acb578182fd5b505080516020909101519092909150565b60008060008060608587031215614af1578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614b16578384fd5b818701915087601f830112614b29578384fd5b813581811115614b37578485fd5b886020828501011115614b48578485fd5b95989497505060200194505050565b600060208284031215614b68578081fd5b610bac8383614963565b600060208284031215614b83578081fd5b813567ffffffffffffffff80821115614b9a578283fd5b9083019060808286031215614bad578283fd5b604051608081018181108382111715614bc257fe5b604052823582811115614bd3578485fd5b614bdf878286016148fe565b825250614bee602084016148e8565b6020820152614bff604084016149b1565b6040820152606083013582811115614c15578485fd5b614c21878286016148fe565b60608301525095945050505050565b600060808284031215614c41578081fd5b6040516080810181811067ffffffffffffffff82111715614c5e57fe5b6040528251614c6c816155cd565b81526020830151614c7c816155f0565b602082015260408301516bffffffffffffffffffffffff81168114614c9f578283fd5b604082015260608301516fffffffffffffffffffffffffffffffff81168114614cc6578283fd5b60608201529392505050565b600060208284031215614ce3578081fd5b5035919050565b600060208284031215614cfb578081fd5b5051919050565b60008060408385031215614d14578182fd5b82359150614d246020840161499e565b90509250929050565b60008060008060808587031215614d42578182fd5b843593506020808601359350604080870135614d5d816155e2565b9350606087013567ffffffffffffffff80821115614d79578485fd5b818901915089601f830112614d8c578485fd5b813581811115614d9857fe5b614da585868302016155a9565b8181528581019250838601610140808402860188018e1015614dc5578889fd5b8895505b83861015614e6f5780828f031215614ddf578889fd5b614de8816155a9565b82358152614df78984016148e8565b89820152878301358882015260608301356060820152614e19608084016148f3565b608082015260a0838101359082015260c0808401359082015260e0614e3f8185016149b1565b90820152610100838101359082015261012080840135908201528552600195909501949387019390810190614dc9565b505080965050505050505092959194509250565b600080600060608486031215614e97578081fd5b8335925060208401359150614eae6040850161499e565b90509250925092565b600080600080600060a08688031215614ece578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b600060208284031215614f02578081fd5b8135610bac816155f0565b60008151808452815b81811015614f3257602081850181015186830182015201614f16565b81811115614f435782602083870101525b50601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b90815260200190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a060808301526124f660a0830184614f0d565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b039690961686526020860194909452604085019290925260608401521515608083015260a082015260c00190565b901515815260200190565b97885260208801969096526001600160a01b0394909416604087015260608601929092526080850152151560a084015260c083015260e08201526101000190565b600060208252610bac6020830184614f0d565b60208082526018908201527f616d6f756e74206f7574206c657373207468616e206d696e0000000000000000604082015260600190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b6020808252601a908201527f616d6f756e7420696e2067726561746572207468616e206d6178000000000000604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526027908201527f507269636520746f6f206c6f772072656c617469766520746f20556e6973776160408201527f7020747761702e00000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526204331360ec1b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526028908201527f507269636520746f6f20686967682072656c617469766520746f20556e69737760408201527f617020747761702e000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526243313160e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b602080825260029082015261433960f01b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b60208082526003908201526243323760e81b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b60006020825282516080602084015261550c60a0840182614f0d565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f1984830301608085015261340a8282614f0d565b918252602082015260400190565b938452602084019290925215156040830152606082015260800190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b60405181810167ffffffffffffffff811182821017156155c557fe5b604052919050565b6001600160a01b0381168114610b2257600080fd5b8015158114610b2257600080fd5b63ffffffff81168114610b2257600080fdfe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445434453413a20696e76616c6964207369676e6174757265202773272076616c756545434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212205588e36b593aca521cd7221641031ca4fe125d2300af7c70ba2abc8ce18bf28564736f6c63430007060033\",\n  \"deployedBytecode\": \"0x60806040526004361061036f5760003560e01c80637f07b130116101c6578063cae74029116100f7578063e9c3cb4f11610095578063f5d278e41161006f578063f5d278e41461095e578063f73e19c314610973578063fa461e3314610993578063fc5b73ff146109b3576103e1565b8063e9c3cb4f14610914578063f101d92f14610929578063f2fde38b1461093e576103e1565b8063d2dd9f79116100d1578063d2dd9f79146108ac578063d33219b4146108cc578063dcbab608146108e1578063dd62ed3e146108f4576103e1565b8063cae740291461087a578063cfa70b181461088f578063d0e30db0146108a4576103e1565b8063a457c2d711610164578063b52b7ff01161013e578063b52b7ff014610810578063bdd438b814610830578063c245168914610850578063c45a015514610865576103e1565b8063a457c2d7146107b0578063a9059cbb146107d0578063b24f719b146107f0576103e1565b80638f8b8dbc116101a05780638f8b8dbc1461074657806395d89b41146107665780639ff69a511461077b578063a319b29f1461079b576103e1565b80637f07b1301461070757806388626eb81461071c5780638da5cb5b14610731576103e1565b80633d65fdac116102a057806366a91b761161023e57806370a082311161021857806370a082311461069d578063715018a6146106bd5780637bcdc16e146106d25780637dc0d1d0146106f2576103e1565b806366a91b761461065e57806367b8c345146106735780636c1040a914610688576103e1565b80634d76e6fc1161027a5780634d76e6fc146105ef578063502e1a1614610604578063533092ef1461062457806363bbc4b614610649576103e1565b80633d65fdac146105a55780633dcb0c5d146105c55780633fc8cef3146105da576103e1565b8063313ce5671161030d578063392e53cd116102e7578063392e53cd1461052e5780633950935114610543578063395ebb69146105635780633d3a62ee14610585576103e1565b8063313ce567146104e257806333194c0a146105045780633644e51514610519576103e1565b806318160ddd1161034957806318160ddd1461045e57806323b872dd14610480578063281e78d1146104a05780632e1a7d4d146104c2576103e1565b806306fdde03146103e6578063095ea7b3146104115780630ca514cd1461043e576103e1565b366103e157336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103ba575060055461010090046001600160a01b031633145b6103df5760405162461bcd60e51b81526004016103d69061547e565b60405180910390fd5b005b600080fd5b3480156103f257600080fd5b506103fb6109c6565b604051610408919061511f565b60405180910390f35b34801561041d57600080fd5b5061043161042c366004614a72565b610a5d565b60405161040891906150d3565b34801561044a57600080fd5b506103df610459366004614cd2565b610a7b565b34801561046a57600080fd5b50610473610b25565b6040516104089190614fab565b34801561048c57600080fd5b5061043161049b366004614a32565b610b2b565b3480156104ac57600080fd5b506104b5610bb3565b6040516104089190614fb4565b3480156104ce57600080fd5b506103df6104dd366004614cd2565b610bd7565b3480156104ee57600080fd5b506104f7610cab565b604051610408919061559b565b34801561051057600080fd5b50610473610cb4565b34801561052557600080fd5b50610473610cd8565b34801561053a57600080fd5b50610431610ce7565b34801561054f57600080fd5b5061043161055e366004614a72565b610cf8565b34801561056f57600080fd5b50610578610d46565b604051610408919061558a565b34801561059157600080fd5b506103df6105a0366004614cd2565b610d4c565b3480156105b157600080fd5b506103df6105c0366004614cd2565b610ee4565b3480156105d157600080fd5b506104b5610f0a565b3480156105e657600080fd5b506104b5610f1e565b3480156105fb57600080fd5b506104b5610f42565b34801561061057600080fd5b5061043161061f366004614a72565b610f66565b34801561063057600080fd5b50610639610f86565b6040516104089493929190615078565b34801561065557600080fd5b50610473610fa2565b34801561066a57600080fd5b50610473610fa8565b34801561067f57600080fd5b50610473610fae565b34801561069457600080fd5b50610473610fb4565b3480156106a957600080fd5b506104736106b83660046149c2565b610fd8565b3480156106c957600080fd5b506103df610ff7565b3480156106de57600080fd5b506103df6106ed366004614cd2565b6110c2565b3480156106fe57600080fd5b506104b5611196565b34801561071357600080fd5b506104b56111ba565b34801561072857600080fd5b506104316111de565b34801561073d57600080fd5b506104b56111e8565b34801561075257600080fd5b506103df610761366004614ef1565b6111f7565b34801561077257600080fd5b506103fb6112d7565b34801561078757600080fd5b506103df610796366004614cd2565b611338565b3480156107a757600080fd5b506103df611409565b3480156107bc57600080fd5b506104316107cb366004614a72565b6114ca565b3480156107dc57600080fd5b506104316107eb366004614a72565b611532565b3480156107fc57600080fd5b506103df61080b366004614d2d565b611546565b34801561081c57600080fd5b506103df61082b366004614e83565b61184f565b34801561083c57600080fd5b506103df61084b366004614cd2565b611976565b34801561085c57600080fd5b50610431611a53565b34801561087157600080fd5b506104b5611a5d565b34801561088657600080fd5b50610473611a81565b34801561089b57600080fd5b50610473611a87565b6103df611a93565b3480156108b857600080fd5b506103df6108c73660046149c2565b611b3e565b3480156108d857600080fd5b506104b5611d25565b6103df6108ef366004614eb7565b611d49565b34801561090057600080fd5b5061047361090f3660046149fa565b611e0f565b34801561092057600080fd5b50610473611e3a565b34801561093557600080fd5b50610473611e40565b34801561094a57600080fd5b506103df6109593660046149c2565b611e46565b34801561096a57600080fd5b50610578611f68565b34801561097f57600080fd5b5061047361098e366004614cd2565b611f74565b34801561099f57600080fd5b506103df6109ae366004614adc565b611f7f565b6103df6109c1366004614d02565b612025565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b820191906000526020600020905b815481529060010190602001808311610a3557829003601f168201915b505050505090505b90565b6000610a71610a6a612172565b8484612176565b5060015b92915050565b610a83612172565b6001600160a01b0316610a946111e8565b6001600160a01b031614610aef576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff16610b195760405162461bcd60e51b81526004016103d6906151f7565b610b2281612262565b50565b60025490565b6000610b38848484612297565b610ba884610b44612172565b610ba385604051806060016040528060288152602001615734602891396001600160a01b038a16600090815260016020526040812090610b82612172565b6001600160a01b0316815260208101919091526040016000205491906123f2565b612176565b5060015b9392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60026006541415610c2f576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610c3f82612489565b90506000610c5033848460006124b4565b9050610c5c3382612501565b336001600160a01b03167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94848484604051610c9993929190615574565b60405180910390a25050600160065550565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce26125eb565b905090565b600a54640100000000900460ff1681565b6000610a71610d05612172565b84610ba38560016000610d16612172565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906126b5565b6101a481565b60026006541415610da4576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600681905550600560019054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610dfc57600080fd5b505af1158015610e10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e349190614a9d565b610e505760405162461bcd60e51b81526004016103d6906153ee565b600f5460ff16610e725760405162461bcd60e51b81526004016103d6906152aa565b6000610e8582610e80610b25565b61270f565b90506000610e93824761271b565b9050610e9f3384612727565b610ea93382612501565b336001600160a01b03167fe9ab9870b9093d99f8e981919f65ad09b7ae90ff80f1031639af9e0357eb9ed68483604051610c99929190615549565b33600090815260106020908152604080832093835292905220805460ff19166001179055565b60055461010090046001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b601060209081526000928352604080842090915290825290205460ff1681565b600080600080610f94612823565b935093509350935090919293565b600e5481565b600b5481565b600d5481565b7f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0381166000908152602081905260409020545b919050565b610fff612172565b6001600160a01b03166110106111e8565b6001600160a01b03161461106b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6007546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36007805473ffffffffffffffffffffffffffffffffffffffff19169055565b6110ca612172565b6001600160a01b03166110db6111e8565b6001600160a01b031614611136576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081116111565760405162461bcd60e51b81526004016103d69061540b565b600b8190556040517f28e0e4ee0b14d4b056ce88e1bcd890ccd32b22e213723c8765901381b5eae7059061118b908390614fab565b60405180910390a150565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce261291a565b6007546001600160a01b031690565b6111ff612172565b6001600160a01b03166112106111e8565b6001600160a01b03161461126b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60b48163ffffffff1610156112925760405162461bcd60e51b81526004016103d690615169565b600a805463ffffffff191663ffffffff83161790556040517f1cd9c7f99a5530a38c8f2b387dcc78e8a76cb5b203e0c4316a66777d993dee359061118b90839061558a565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b611340612172565b6001600160a01b03166113516111e8565b6001600160a01b0316146113ac576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6702c68af0bb1400008111156113d45760405162461bcd60e51b81526004016103d6906153d1565b60098190556040517f829c71710efa317bbdb8e5c4ca2b6d2551b7c2d7d37ea199975807eb3f5c0e7c9061118b908390614fab565b600a54640100000000900460ff166114335760405162461bcd60e51b81526004016103d6906151f7565b600f8054600160ff19909116179055600554604051634bf7d4a160e11b81526101009091046001600160a01b0316906397efa94290611496907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b600060405180830381600087803b1580156114b057600080fd5b505af11580156114c4573d6000803e3d6000fd5b50505050565b6000610a716114d7612172565b84610ba3856040518060600160405280602581526020016157c66025913960016000611501612172565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906123f2565b6000610a7161153f612172565b8484612297565b61154e612172565b6001600160a01b031661155f6111e8565b6001600160a01b0316146115ba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff166115e45760405162461bcd60e51b81526004016103d6906151f7565b600083116116045760405162461bcd60e51b81526004016103d690615398565b61160c612a90565b8061161a575061161a61291a565b6116365760405162461bcd60e51b81526004016103d690615444565b6116408383612ab1565b42600d55600e839055805184906000908390829061165a57fe5b602002602001015160600151905060008360008151811061167757fe5b602002602001015160600151905060008460008151811061169457fe5b602002602001015160800151905080151586151514156116c65760405162461bcd60e51b81526004016103d690615324565b60005b85518110156117ef578581815181106116de57fe5b60200260200101516060015192508115158682815181106116fb57fe5b6020026020010151608001511515146117265760405162461bcd60e51b81526004016103d690615427565b8615611751578383101561174c5760405162461bcd60e51b81526004016103d690615341565b611771565b838311156117715760405162461bcd60e51b81526004016103d690615341565b829350611792858988848151811061178557fe5b6020026020010151612c71565b85818151811061179e57fe5b6020026020010151604001518511156117e2576117db8682815181106117c057fe5b602002602001015160400151866130e390919063ffffffff16565b94506117e7565b6117ef565b6001016116c9565b507fbbc3ba742efe346cfdf333000069964e0ee3087c68da267dac977d299f2366fb8560008151811061181e57fe5b60200260200101516000015189888a60405161183d9493929190615557565b60405180910390a15050505050505050565b600260065414156118a7576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560006118b784612489565b90506119287f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084848760018a6040516020016119149190614fab565b60405160208183030381529060405261313b565b336001600160a01b03167fa13b272c1cf13ba724064d3d4809d9f557aab8da2bb582cba031a2f57e728e9d8583604051611963929190615549565b60405180910390a2505060016006555050565b61197e612172565b6001600160a01b031661198f6111e8565b6001600160a01b0316146119ea576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081118015611a025750670de0b6b3a76400008111155b611a1e5760405162461bcd60e51b81526004016103d6906154d4565b600c8190556040517f789e4b8ad1c375952cea7f07c9b3b6619a84b406432b948246cecb8ced96b9fa9061118b908390614fab565b6000610ce2612a90565b7f000000000000000000000000000000000000000000000000000000000000000081565b60085481565b6702c68af0bb14000081565b60026006541415611aeb576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065534600080611aff3384836131bc565b91509150336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158383604051610c99929190615549565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611b865760405162461bcd60e51b81526004016103d6906153b5565b600a54640100000000900460ff16611bb05760405162461bcd60e51b81526004016103d6906151f7565b600560019054906101000a90046001600160a01b03166001600160a01b0316639d4c94426040518163ffffffff1660e01b815260040160206040518083038186803b158015611bfe57600080fd5b505afa158015611c12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3691906149de565b6001600160a01b03166342842e0e30837f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401611c8593929190614fc8565b600060405180830381600087803b158015611c9f57600080fd5b505af1158015611cb3573d6000803e3d6000fd5b50505050611cc16000612262565b806001600160a01b03167fae97956757017853415251f661bfe857898f44ddb9c90b2483065719b84b0c697f0000000000000000000000000000000000000000000000000000000000000000604051611d1a9190614fab565b60405180910390a250565b7f000000000000000000000000000000000000000000000000000000000000000081565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611d915760405162461bcd60e51b81526004016103d69061528d565b600a54640100000000900460ff1615611dbc5760405162461bcd60e51b81526004016103d69061535e565b611dc581612262565b34611dd1816000613230565b600d849055600e839055611de8338783600061325f565b611df233866133b9565b5050600a805464ff00000000191664010000000017905550505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60095481565b600c5481565b611e4e612172565b6001600160a01b0316611e5f6111e8565b6001600160a01b031614611eba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611eff5760405162461bcd60e51b81526004018080602001828103825260268152602001806156486026913960400191505060405180910390fd5b6007546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600a5463ffffffff1681565b6000610a7582612489565b6000841380611f8e5750600083135b611f9757600080fd5b6000611fa582840184614b72565b90506000806000611fb984600001516133c3565b925092509250611feb7f00000000000000000000000000000000000000000000000000000000000000008484846133f4565b506000808913611ffb5787611ffd565b885b905061201a8560200151858585858a606001518b60400151613413565b505050505050505050565b6002600654141561207d576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560008061208d6138ec565b9150915061209b8482613230565b60006120a8858484613906565b5090506121237f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086846120fc8a346130e3565b60008b60405160200161210f9190614fab565b604051602081830303815290604052613995565b336001600160a01b03167f5d85169ff8329e90f3225f9798e0eba54d00c55d3bbfe201a0d1606febb23a8e868360405161215e929190615549565b60405180910390a250506001600655505050565b3390565b6001600160a01b0383166121bb5760405162461bcd60e51b81526004018080602001828103825260248152602001806157a26024913960400191505060405180910390fd5b6001600160a01b0382166122005760405162461bcd60e51b815260040180806020018281038252602281526020018061566e6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60088190556040517f29600e2e028c8c5c2b112d021938e0d0237d8fafcbb20394c56cf9fa4661ca279061118b908390614fab565b6001600160a01b0383166122dc5760405162461bcd60e51b815260040180806020018281038252602581526020018061577d6025913960400191505060405180910390fd5b6001600160a01b0382166123215760405162461bcd60e51b81526004018080602001828103825260238152602001806156036023913960400191505060405180910390fd5b61232c8383836125e6565b61236981604051806060016040528060268152602001615690602691396001600160a01b03861660009081526020819052604090205491906123f2565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461239890826126b5565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156124815760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561244657818101518382015260200161242e565b50505050905090810190601f1680156124735780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600080612494612823565b9350505050610bac6124a4610b25565b6124ae8386613a0c565b90613a45565b6000806124bf6138ec565b91505060006124d086610e80610b25565b905060006124de828461271b565b90506124ec88878388613a65565b6124f68888612727565b979650505050505050565b80471015612556576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146125a1576040519150601f19603f3d011682016040523d82523d6000602084013e6125a6565b606091505b50509050806125e65760405162461bcd60e51b815260040180806020018281038252603a8152602001806156b6603a913960400191505060405180910390fd5b505050565b60007f0000000000000000000000000000000000000000000000000000000000000000612616613b94565b141561264357507f0000000000000000000000000000000000000000000000000000000000000000610a5a565b6126ae7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000613b98565b9050610a5a565b600082820183811015610bac576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610bac8383613a45565b6000610bac8284613a0c565b6001600160a01b03821661276c5760405162461bcd60e51b815260040180806020018281038252602181526020018061575c6021913960400191505060405180910390fd5b612778826000836125e6565b6127b581604051806060016040528060228152602001615626602291396001600160a01b03851660009081526020819052604090205491906123f2565b6001600160a01b0383166000908152602081905260409020556002546127db9082613bfa565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600554604051634632752560e11b8152600091829182918291829161010090046001600160a01b031690638c64ea4a90612881907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b60806040518083038186803b15801561289957600080fd5b505afa1580156128ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d19190614c30565b805160208201516040830151606090930151919863ffffffff90911697506bffffffffffffffffffffffff90921695506fffffffffffffffffffffffffffffffff169350915050565b600a5460405163cce79bd560e01b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd5916129de917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff90911690600190600401614fec565b60206040518083038186803b1580156129f657600080fd5b505afa158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190614cea565b90506000612a47600e5483613a4590919063ffffffff16565b90506000670de0b6b3a76400008211612a7157612a6c670de0b6b3a7640000836130e3565b612a83565b612a8382670de0b6b3a76400006130e3565b600c541115935050505090565b6000612aa9600b54600d54613c5790919063ffffffff16565b421015905090565b600a5460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591612b71917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff1690600190600401614fec565b60206040518083038186803b158015612b8957600080fd5b505afa158015612b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc19190614cea565b90508115612c2657612c02670de0b6b3a7640000612bfc612bf5600954670de0b6b3a7640000613c5790919063ffffffff16565b8490613caf565b90613d1b565b831115612c215760405162461bcd60e51b81526004016103d6906152c7565b6125e6565b612c52670de0b6b3a7640000612bfc612bf5600954670de0b6b3a76400006130e390919063ffffffff16565b8310156125e65760405162461bcd60e51b81526004016103d690615230565b806080015115612ca4578060600151821115612c9f5760405162461bcd60e51b81526004016103d69061549a565b612cc8565b8060600151821015612cc85760405162461bcd60e51b81526004016103d69061537b565b612cda81602001518260c00151613d7a565b60007fc8aea8e60353611f3ed5409dad2d3173390bd252431198e7300eda67fefb66b1826000015183602001518460400151856060015186608001518760a001518860c00151604051602001612d379897969594939291906150de565b6040516020818303038152906040528051906020012090506000612d5a82613dee565b90506000612d78828560e00151866101000151876101200151613e3a565b905083602001516001600160a01b0316816001600160a01b031614612daf5760405162461bcd60e51b81526004016103d690615461565b428460a001511015612dd35760405162461bcd60e51b81526004016103d690615186565b8360400151861015612de757604084018690525b6000612e0c670de0b6b3a7640000612bfc888860400151613caf90919063ffffffff16565b9050846080015115612f575760208501516040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916323b872dd91612e6c919030908690600401614fc8565b602060405180830381600087803b158015612e8657600080fd5b505af1158015612e9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ebe9190614a9d565b50604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612f0b908490600401614fab565b600060405180830381600087803b158015612f2557600080fd5b505af1158015612f39573d6000803e3d6000fd5b50505050612f528560200151866040015183600061325f565b613085565b612f6c85602001518660400151836000613a65565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612fc757600080fd5b505af1158015612fdb573d6000803e3d6000fd5b50505050602086015160405163a9059cbb60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063a9059cbb9161303191859060040161505f565b602060405180830381600087803b15801561304b57600080fd5b505af115801561305f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130839190614a9d565b505b7f68c36f17c620d197a81d3aeff305f83abf3bb29943a38cd6efc299041238652d856020015186600001518760400151886060015189608001518b6040516130d29695949392919061509e565b60405180910390a150505050505050565b80820382811115610a75576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b60006131908530600060405180608001604052808c8c8f60405160200161316493929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052613faf565b9050838111156131b25760405162461bcd60e51b81526004016103d6906151c0565b5050505050505050565b6000806000806131ca6138ec565b915091506131d88682613230565b6000806131e6888585613906565b909250905060006132086131fa8a846130e3565b85613203610b25565b61411c565b90506132168a848b8b61325f565b6132208a826133b9565b9199919850909650505050505050565b60085461323d8284613c57565b111561325b5760405162461bcd60e51b81526004016103d690615213565b5050565b600554604051630728cf2360e31b81526101009091046001600160a01b03169063394679189084906132ba907f0000000000000000000000000000000000000000000000000000000000000000908890600090600401615574565b6020604051808303818588803b1580156132d357600080fd5b505af11580156132e7573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061330c9190614cea565b50806114c45760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613360908790879060040161505f565b602060405180830381600087803b15801561337a57600080fd5b505af115801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b29190614a9d565b5050505050565b61325b828261416b565b600080806133d1848261425b565b92506133de846014614327565b90506133eb84601761425b565b91509193909250565b600061340a856134058686866143e3565b614439565b95945050505050565b60008160ff16600181111561342457fe5b600181111561342f57fe5b14156136665760008280602001905181019061344b9190614b57565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906134a2903090600401614fb4565b60206040518083038186803b1580156134ba57600080fd5b505afa1580156134ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f29190614cea565b6040518263ffffffff1660e01b815260040161350e9190614fab565b600060405180830381600087803b15801561352857600080fd5b505af115801561353c573d6000803e3d6000fd5b5050505061355088826000015160016131bc565b5050600061355f88888861445c565b60405163a9059cbb60e01b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906135b0908490899060040161505f565b602060405180830381600087803b1580156135ca57600080fd5b505af11580156135de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136029190614a9d565b50886001600160a01b03167fc355ebece16d7e85e486911f0cde1074bc4bd3fec251c88cdddc7076d3e99adb864760405161363e929190615549565b60405180910390a2471561365f5761365f6001600160a01b038a1647612501565b50506138e3565b60018160ff16600181111561367757fe5b600181111561368257fe5b14156138e35760008280602001905181019061369e9190614b57565b9050600061374e8983600001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016136f79190614fb4565b60206040518083038186803b15801561370f57600080fd5b505afa158015613723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137479190614cea565b60016124b4565b9050600061375d89898961445c565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b1580156137ba57600080fd5b505af11580156137ce573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250613821915084908a9060040161505f565b602060405180830381600087803b15801561383b57600080fd5b505af115801561384f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138739190614a9d565b50600061388083886130e3565b90508a6001600160a01b03167f6f3269a64126ef2a1959892f3d921e81865181e09a7f72f55d3a49550c53b48d88836040516138bd929190615549565b60405180910390a280156138de576138de6001600160a01b038c1682612501565b505050505b50505050505050565b6000806000806138fa612823565b96509450505050509091565b60008060008061391461449a565b9050600086158015613924575085155b80156139365750613933610b25565b15155b905080156139565760405162461bcd60e51b81526004016103d6906151a3565b61397761396d6139668985613a0c565b8890613c57565b6124ae8a8a613a0c565b925060006139858484613a0c565b9399939850929650505050505050565b60006139ea8530600060405180608001604052808d8c8e6040516020016139be93929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526145d1565b9050838110156131b25760405162461bcd60e51b81526004016103d690615132565b6000670de0b6b3a7640000613a36613a248585613caf565b6002670de0b6b3a76400005b04613c57565b81613a3d57fe5b049392505050565b600081613a36613a5d85670de0b6b3a7640000613caf565b600285613a30565b80613b0e576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90613aba90879030908890600401614fc8565b602060405180830381600087803b158015613ad457600080fd5b505af1158015613ae8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b0c9190614a9d565b505b600554604051638632cb0360e01b81526101009091046001600160a01b031690638632cb0390613b66907f00000000000000000000000000000000000000000000000000000000000000009087908790600401615574565b600060405180830381600087803b158015613b8057600080fd5b505af11580156131b2573d6000803e3d6000fd5b4690565b6000838383613ba5613b94565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b600082821115613c51576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b80820182811015610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000811580613cca57505080820282828281613cc757fe5b04145b610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000808211613d71576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613a3d57fe5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff1615613dbe5760405162461bcd60e51b81526004016103d6906154b7565b6001600160a01b03909116600090815260106020908152604080832093835292905220805460ff19166001179055565b6000613df86125eb565b82604051602001808061190160f01b81525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613e9b5760405162461bcd60e51b81526004018080602001828103825260228152602001806156f06022913960400191505060405180910390fd5b8360ff16601b1480613eb057508360ff16601c145b613eeb5760405162461bcd60e51b81526004018080602001828103825260228152602001806157126022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613f47573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661340a576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b600080600080613fc285600001516133c3565b919450925090506001600160a01b0380841690831610600080613fe685878661445c565b6001600160a01b031663128acb088b85613fff8f614710565b6000036001600160a01b038e1615614017578d61403d565b876140365773fffd8963efd1fc6a506488495d951d5263988d2561403d565b6401000276a45b8d60405160200161404e91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161407d959493929190615025565b6040805180830381600087803b15801561409657600080fd5b505af11580156140aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140ce9190614ab9565b91509150600080846140e45782846000036140ea565b83836000035b915091508a6001600160a01b03166000141561410c578c811461410c57600080fd5b509b9a5050505050505050505050565b60008061413361412c8587613c57565b8690613a45565b905082156141625761415a614150670de0b6b3a7640000836130e3565b6124ae8584613a0c565b915050610bac565b50929392505050565b6001600160a01b0382166141c6576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6141d2600083836125e6565b6002546141df90826126b5565b6002556001600160a01b03821660009081526020819052604090205461420590826126b5565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000818260140110156142b5576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b816014018351101561430e576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015614381576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156143da576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6143eb6148c8565b826001600160a01b0316846001600160a01b03161115614409579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b60006144458383614726565b9050336001600160a01b03821614610a7557600080fd5b60006144927f000000000000000000000000000000000000000000000000000000000000000061448d8686866143e3565b614726565b949350505050565b60008061452e7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a46000614822565b90506000600560019054906101000a90046001600160a01b03166001600160a01b031663978bbdb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561458057600080fd5b505afa158015614594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145b89190614cea565b90506145ca612710612bfc8484613caf565b9250505090565b6000806000806145e485600001516133c3565b919450925090506001600160a01b038083169084161060008061460886868661445c565b6001600160a01b031663128acb088b856146218f614710565b6001600160a01b038e1615614636578d61465c565b876146555773fffd8963efd1fc6a506488495d951d5263988d2561465c565b6401000276a45b8d60405160200161466d91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161469c959493929190615025565b6040805180830381600087803b1580156146b557600080fd5b505af11580156146c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146ed9190614ab9565b91509150826146fc57816146fe565b805b6000039b9a5050505050505050505050565b6000600160ff1b821061472257600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b03161061474e57600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b15801561489157600080fd5b505afa1580156148a5573d6000803e3d6000fd5b505050506040513d60208110156148bb57600080fd5b5051979650505050505050565b604080516060810182526000808252602082018190529181019190915290565b8035610ff2816155cd565b8035610ff2816155e2565b600082601f83011261490e578081fd5b813567ffffffffffffffff81111561492257fe5b614935601f8201601f19166020016155a9565b818152846020838601011115614949578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215614974578081fd5b6040516020810181811067ffffffffffffffff8211171561499157fe5b6040529151825250919050565b803562ffffff81168114610ff257600080fd5b803560ff81168114610ff257600080fd5b6000602082840312156149d3578081fd5b8135610bac816155cd565b6000602082840312156149ef578081fd5b8151610bac816155cd565b60008060408385031215614a0c578081fd5b8235614a17816155cd565b91506020830135614a27816155cd565b809150509250929050565b600080600060608486031215614a46578081fd5b8335614a51816155cd565b92506020840135614a61816155cd565b929592945050506040919091013590565b60008060408385031215614a84578182fd5b8235614a8f816155cd565b946020939093013593505050565b600060208284031215614aae578081fd5b8151610bac816155e2565b60008060408385031215614acb578182fd5b505080516020909101519092909150565b60008060008060608587031215614af1578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614b16578384fd5b818701915087601f830112614b29578384fd5b813581811115614b37578485fd5b886020828501011115614b48578485fd5b95989497505060200194505050565b600060208284031215614b68578081fd5b610bac8383614963565b600060208284031215614b83578081fd5b813567ffffffffffffffff80821115614b9a578283fd5b9083019060808286031215614bad578283fd5b604051608081018181108382111715614bc257fe5b604052823582811115614bd3578485fd5b614bdf878286016148fe565b825250614bee602084016148e8565b6020820152614bff604084016149b1565b6040820152606083013582811115614c15578485fd5b614c21878286016148fe565b60608301525095945050505050565b600060808284031215614c41578081fd5b6040516080810181811067ffffffffffffffff82111715614c5e57fe5b6040528251614c6c816155cd565b81526020830151614c7c816155f0565b602082015260408301516bffffffffffffffffffffffff81168114614c9f578283fd5b604082015260608301516fffffffffffffffffffffffffffffffff81168114614cc6578283fd5b60608201529392505050565b600060208284031215614ce3578081fd5b5035919050565b600060208284031215614cfb578081fd5b5051919050565b60008060408385031215614d14578182fd5b82359150614d246020840161499e565b90509250929050565b60008060008060808587031215614d42578182fd5b843593506020808601359350604080870135614d5d816155e2565b9350606087013567ffffffffffffffff80821115614d79578485fd5b818901915089601f830112614d8c578485fd5b813581811115614d9857fe5b614da585868302016155a9565b8181528581019250838601610140808402860188018e1015614dc5578889fd5b8895505b83861015614e6f5780828f031215614ddf578889fd5b614de8816155a9565b82358152614df78984016148e8565b89820152878301358882015260608301356060820152614e19608084016148f3565b608082015260a0838101359082015260c0808401359082015260e0614e3f8185016149b1565b90820152610100838101359082015261012080840135908201528552600195909501949387019390810190614dc9565b505080965050505050505092959194509250565b600080600060608486031215614e97578081fd5b8335925060208401359150614eae6040850161499e565b90509250925092565b600080600080600060a08688031215614ece578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b600060208284031215614f02578081fd5b8135610bac816155f0565b60008151808452815b81811015614f3257602081850181015186830182015201614f16565b81811115614f435782602083870101525b50601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b90815260200190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a060808301526124f660a0830184614f0d565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b039690961686526020860194909452604085019290925260608401521515608083015260a082015260c00190565b901515815260200190565b97885260208801969096526001600160a01b0394909416604087015260608601929092526080850152151560a084015260c083015260e08201526101000190565b600060208252610bac6020830184614f0d565b60208082526018908201527f616d6f756e74206f7574206c657373207468616e206d696e0000000000000000604082015260600190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b6020808252601a908201527f616d6f756e7420696e2067726561746572207468616e206d6178000000000000604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526027908201527f507269636520746f6f206c6f772072656c617469766520746f20556e6973776160408201527f7020747761702e00000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526204331360ec1b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526028908201527f507269636520746f6f20686967682072656c617469766520746f20556e69737760408201527f617020747761702e000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526243313160e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b602080825260029082015261433960f01b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b60208082526003908201526243323760e81b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b60006020825282516080602084015261550c60a0840182614f0d565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f1984830301608085015261340a8282614f0d565b918252602082015260400190565b938452602084019290925215156040830152606082015260800190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b60405181810167ffffffffffffffff811182821017156155c557fe5b604052919050565b6001600160a01b0381168114610b2257600080fd5b8015158114610b2257600080fd5b63ffffffff81168114610b2257600080fdfe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445434453413a20696e76616c6964207369676e6174757265202773272076616c756545434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212205588e36b593aca521cd7221641031ca4fe125d2300af7c70ba2abc8ce18bf28564736f6c63430007060033\",\n  \"devdoc\": {\n    \"author\": \"Opyn team\",\n    \"details\": \"CrabStrategyV2 contract\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"DOMAIN_SEPARATOR()\": {\n        \"details\": \"view function to get the domain seperator used in signing\"\n      },\n      \"allowance(address,address)\": {\n        \"details\": \"See {IERC20-allowance}.\"\n      },\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC20-balanceOf}.\"\n      },\n      \"checkPriceHedge()\": {\n        \"returns\": {\n          \"_0\": \"true if hedging is allowed\"\n        }\n      },\n      \"checkTimeHedge()\": {\n        \"returns\": {\n          \"_0\": \"true if hedging is allowed\"\n        }\n      },\n      \"constructor\": {\n        \"details\": \"this will open a vault in the power token contract and store the vault ID\",\n        \"params\": {\n          \"_crabMigration\": \"crab migration contract address\",\n          \"_ethWSqueethPool\": \"eth:wSqueeth uniswap pool address\",\n          \"_hedgePriceThreshold\": \"hedge price threshold (0.1*1e18 = 10%)\",\n          \"_hedgeTimeThreshold\": \"hedge time threshold (seconds)\",\n          \"_oracle\": \"oracle address\",\n          \"_timelock\": \"timelock contract address\",\n          \"_uniswapFactory\": \"uniswap factory address\",\n          \"_wSqueethController\": \"power token controller address\",\n          \"_weth\": \"weth address\"\n        }\n      },\n      \"decimals()\": {\n        \"details\": \"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"\n      },\n      \"decreaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"\n      },\n      \"deposit()\": {\n        \"details\": \"provide ETH, return wSqueeth and strategy token\"\n      },\n      \"flashDeposit(uint256,uint24)\": {\n        \"details\": \"this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth_ethToDeposit must be less than msg.value plus the proceeds from the flash swapthe difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\",\n        \"params\": {\n          \"_ethToDeposit\": \"total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\",\n          \"_poolFee\": \"Uniswap pool fee\"\n        }\n      },\n      \"flashWithdraw(uint256,uint256,uint24)\": {\n        \"details\": \"this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\",\n        \"params\": {\n          \"_crabAmount\": \"strategy token amount to burn\",\n          \"_maxEthToPay\": \"maximum ETH to pay to buy back the wSqueeth debt\",\n          \"_poolFee\": \"Uniswap pool fee\"\n        }\n      },\n      \"getStrategyVaultId()\": {\n        \"returns\": {\n          \"_0\": \"vault ID\"\n        }\n      },\n      \"getVaultDetails()\": {\n        \"returns\": {\n          \"_0\": \"operator\",\n          \"_1\": \"nft collateral id\",\n          \"_2\": \"collateral amount\",\n          \"_3\": \"short amount\"\n        }\n      },\n      \"getWsqueethFromCrabAmount(uint256)\": {\n        \"params\": {\n          \"_crabAmount\": \"strategy token amount\"\n        },\n        \"returns\": {\n          \"_0\": \"wSqueeth amount\"\n        }\n      },\n      \"hedgeOTC(uint256,uint256,bool,(uint256,address,uint256,uint256,bool,uint256,uint256,uint8,bytes32,bytes32)[])\": {\n        \"details\": \"hedge function to reduce delta using an array of signed orders\",\n        \"params\": {\n          \"_clearingPrice\": \"clearing price in weth\",\n          \"_isHedgeBuying\": \"direction of hedge trade\",\n          \"_orders\": \"an array of signed order to swap tokens\",\n          \"_totalQuantity\": \"quantity the manager wants to trade\"\n        }\n      },\n      \"increaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"initialize(uint256,uint256,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_crabSharesToMint\": \"crab shares to mint\",\n          \"_priceAtLastHedge\": \"price at last hedge for crab V1\",\n          \"_strategyCap\": \"strategy cap for crab V2\",\n          \"_timeAtLastHedge\": \"time at last hedge for crab V1\",\n          \"_wSqueethToMint\": \"amount of wPowerPerp to mint\"\n        }\n      },\n      \"name()\": {\n        \"details\": \"Returns the name of the token.\"\n      },\n      \"owner()\": {\n        \"details\": \"Returns the address of the current owner.\"\n      },\n      \"redeemShortShutdown()\": {\n        \"details\": \"needs to be called before users can exit strategy using withdrawShutdown\"\n      },\n      \"renounceOwnership()\": {\n        \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n      },\n      \"setHedgePriceThreshold(uint256)\": {\n        \"params\": {\n          \"_hedgePriceThreshold\": \"the hedge price threshold, in percent, scaled by 1e18\"\n        }\n      },\n      \"setHedgeTimeThreshold(uint256)\": {\n        \"params\": {\n          \"_hedgeTimeThreshold\": \"the hedge time threshold, in seconds\"\n        }\n      },\n      \"setHedgingTwapPeriod(uint32)\": {\n        \"params\": {\n          \"_hedgingTwapPeriod\": \"the twap period, in seconds\"\n        }\n      },\n      \"setNonceTrue(uint256)\": {\n        \"params\": {\n          \"_nonce\": \"the number to be set true\"\n        }\n      },\n      \"setOTCPriceTolerance(uint256)\": {\n        \"params\": {\n          \"_otcPriceTolerance\": \"the OTC price tolerance, in percent, scaled by 1e18\"\n        }\n      },\n      \"setStrategyCap(uint256)\": {\n        \"details\": \"deposits are rejected if it would put the strategy above the cap amountstrategy collateral can be above the cap amount due to hedging activities\",\n        \"params\": {\n          \"_capAmount\": \"the maximum strategy collateral in ETH, checked on deposits\"\n        }\n      },\n      \"symbol()\": {\n        \"details\": \"Returns the symbol of the token, usually a shorter version of the name.\"\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC20-totalSupply}.\"\n      },\n      \"transfer(address,uint256)\": {\n        \"details\": \"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"\n      },\n      \"transferOwnership(address)\": {\n        \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n      },\n      \"transferVault(address)\": {\n        \"details\": \"strategy cap is set to 0 to avoid future deposits\",\n        \"params\": {\n          \"_newStrategy\": \"new strategy contract address\"\n        }\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"params\": {\n          \"_data\": \"callback data encoded as SwapCallbackData struct\",\n          \"amount0Delta\": \"amount of token0\",\n          \"amount1Delta\": \"amount of token1\"\n        }\n      },\n      \"withdraw(uint256)\": {\n        \"details\": \"provide strategy tokens and wSqueeth, returns ETH\",\n        \"params\": {\n          \"_crabAmount\": \"amount of strategy token to burn\"\n        }\n      },\n      \"withdrawShutdown(uint256)\": {\n        \"params\": {\n          \"_crabAmount\": \"amount of strategy token to burn\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"ONE\": {\n        \"details\": \"basic unit used for calculation\"\n      },\n      \"POWER_PERP_PERIOD\": {\n        \"details\": \"the TWAP_PERIOD used in the PowerPerp Controller contract\"\n      },\n      \"_CRAB_BALANCE_TYPEHASH\": {\n        \"details\": \"typehash for signed orders\"\n      },\n      \"ethWSqueethPool\": {\n        \"details\": \"ETH:wSqueeth uniswap pool\"\n      },\n      \"hasRedeemedInShutdown\": {\n        \"details\": \"set to true when redeemShortShutdown has been called\"\n      },\n      \"hedgePriceThreshold\": {\n        \"details\": \"price movement to trigger a hedge (0.1*1e18 = 10%)\"\n      },\n      \"hedgeTimeThreshold\": {\n        \"details\": \"time difference to trigger a hedge (seconds)\"\n      },\n      \"hedgingTwapPeriod\": {\n        \"details\": \"twap period to use for hedge calculations\"\n      },\n      \"isInitialized\": {\n        \"details\": \"true if CrabV2 was initialized\"\n      },\n      \"nonces\": {\n        \"details\": \"store the used flag for a nonce for each address\"\n      },\n      \"oracle\": {\n        \"details\": \"strategy uniswap oracle\"\n      },\n      \"priceAtLastHedge\": {\n        \"details\": \"wSqueeth/Eth price when last hedge executed\"\n      },\n      \"strategyCap\": {\n        \"details\": \"the cap in ETH for the strategy, above which deposits will be rejected\"\n      },\n      \"timeAtLastHedge\": {\n        \"details\": \"timestamp when last hedge executed\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"checkPriceHedge()\": {\n        \"notice\": \"check if hedging based on price threshold is allowed\"\n      },\n      \"checkTimeHedge()\": {\n        \"notice\": \"check if hedging based on time threshold is allowed\"\n      },\n      \"constructor\": {\n        \"notice\": \"strategy constructor\"\n      },\n      \"deposit()\": {\n        \"notice\": \"deposit ETH into strategy\"\n      },\n      \"flashDeposit(uint256,uint24)\": {\n        \"notice\": \"flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\"\n      },\n      \"flashWithdraw(uint256,uint256,uint24)\": {\n        \"notice\": \"flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\"\n      },\n      \"getStrategyVaultId()\": {\n        \"notice\": \"get power token strategy vault ID \"\n      },\n      \"getVaultDetails()\": {\n        \"notice\": \"get the vault composition of the strategy \"\n      },\n      \"getWsqueethFromCrabAmount(uint256)\": {\n        \"notice\": \"get wSqueeth debt amount associated with strategy token amount\"\n      },\n      \"initialize(uint256,uint256,uint256,uint256,uint256)\": {\n        \"notice\": \"initializes the collateral ratio after the first migration\"\n      },\n      \"redeemShortShutdown()\": {\n        \"notice\": \"called to redeem the net value of a vault post shutdown\"\n      },\n      \"setHedgePriceThreshold(uint256)\": {\n        \"notice\": \"owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\"\n      },\n      \"setHedgeTimeThreshold(uint256)\": {\n        \"notice\": \"owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\"\n      },\n      \"setHedgingTwapPeriod(uint32)\": {\n        \"notice\": \"owner can set the twap period in seconds that is used for calculating twaps for hedging\"\n      },\n      \"setNonceTrue(uint256)\": {\n        \"notice\": \"set nonce to true\"\n      },\n      \"setOTCPriceTolerance(uint256)\": {\n        \"notice\": \"owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\"\n      },\n      \"setStrategyCap(uint256)\": {\n        \"notice\": \"owner can set the strategy cap in ETH collateral terms\"\n      },\n      \"transferVault(address)\": {\n        \"notice\": \"transfer vault NFT to new contract\"\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"notice\": \"uniswap swap callback function for flashes\"\n      },\n      \"withdraw(uint256)\": {\n        \"notice\": \"withdraw WETH from strategy\"\n      },\n      \"withdrawShutdown(uint256)\": {\n        \"notice\": \"called to exit a vault if the Squeeth Power Perp contracts are shutdown\"\n      }\n    },\n    \"notice\": \"Contract for Crab strategy\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 881,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_balances\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 887,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_allowances\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n      },\n      {\n        \"astId\": 889,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_totalSupply\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 891,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 893,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 895,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_decimals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint8\"\n      },\n      {\n        \"astId\": 27260,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"powerTokenController\",\n        \"offset\": 1,\n        \"slot\": \"5\",\n        \"type\": \"t_contract(IController)11604\"\n      },\n      {\n        \"astId\": 4176,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_owner\",\n        \"offset\": 0,\n        \"slot\": \"7\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 25273,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"strategyCap\",\n        \"offset\": 0,\n        \"slot\": \"8\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25287,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"otcPriceTolerance\",\n        \"offset\": 0,\n        \"slot\": \"9\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25294,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hedgingTwapPeriod\",\n        \"offset\": 0,\n        \"slot\": \"10\",\n        \"type\": \"t_uint32\"\n      },\n      {\n        \"astId\": 25297,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"isInitialized\",\n        \"offset\": 4,\n        \"slot\": \"10\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 25319,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hedgeTimeThreshold\",\n        \"offset\": 0,\n        \"slot\": \"11\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25322,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hedgePriceThreshold\",\n        \"offset\": 0,\n        \"slot\": \"12\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25325,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"timeAtLastHedge\",\n        \"offset\": 0,\n        \"slot\": \"13\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25328,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"priceAtLastHedge\",\n        \"offset\": 0,\n        \"slot\": \"14\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25331,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hasRedeemedInShutdown\",\n        \"offset\": 0,\n        \"slot\": \"15\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 25338,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"nonces\",\n        \"offset\": 0,\n        \"slot\": \"16\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_uint256,t_bool))\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_contract(IController)11604\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"contract IController\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => uint256))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_uint256)\"\n      },\n      \"t_mapping(t_address,t_mapping(t_uint256,t_bool))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(uint256 => bool))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_uint256,t_bool)\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_mapping(t_uint256,t_bool)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => bool)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_bool\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint32\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint32\",\n        \"numberOfBytes\": \"4\"\n      },\n      \"t_uint8\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint8\",\n        \"numberOfBytes\": \"1\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/Oracle.json",
    "content": "{\n  \"address\": \"0x65D66c76447ccB45dAf1e8044e918fA786A483A1\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_base\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_quote\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_secondsAgoToStartOfTwap\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_secondsAgoToEndOfTwap\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getHistoricalTwap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"getMaxPeriod\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getTimeWeightedAverageTickSafe\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"timeWeightedAverageTick\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_base\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_quote\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_checkPeriod\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getTwap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x4d0c737c0edf0caa8485a9b143b5e71e1f71d5354817159681c12fdeca737dd7\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xa3cB04d8BD927EEC8826BD77b7C71abE3d29c081\",\n    \"contractAddress\": \"0x65D66c76447ccB45dAf1e8044e918fA786A483A1\",\n    \"transactionIndex\": 53,\n    \"gasUsed\": \"874024\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x81d05eaef0fb7b3cb4c879eebc5e66f8ace5fbabb883e4f2601c99359b0dca6b\",\n    \"transactionHash\": \"0x4d0c737c0edf0caa8485a9b143b5e71e1f71d5354817159681c12fdeca737dd7\",\n    \"logs\": [],\n    \"blockNumber\": 13982498,\n    \"cumulativeGasUsed\": \"4186962\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"d97d3d4b09e0d70518330d405a7dd9ff\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_base\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_quote\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_secondsAgoToStartOfTwap\\\",\\\"type\\\":\\\"uint32\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_secondsAgoToEndOfTwap\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getHistoricalTwap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"getMaxPeriod\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getTimeWeightedAverageTickSafe\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"timeWeightedAverageTick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_base\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_quote\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_checkPeriod\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getTwap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"details\\\":\\\"if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"getHistoricalTwap(address,address,address,uint32,uint32)\\\":{\\\"details\\\":\\\"if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\",\\\"params\\\":{\\\"_base\\\":\\\"base currency. to get eth/usd price, eth is base token\\\",\\\"_pool\\\":\\\"uniswap pool address\\\",\\\"_quote\\\":\\\"quote currency. to get eth/usd price, usd is the quote currency\\\",\\\"_secondsAgoToEndOfTwap\\\":\\\"amount of seconds in the past to end calculating time-weighted average\\\",\\\"_secondsAgoToStartOfTwap\\\":\\\"amount of seconds in the past to start calculating time-weighted average\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"price of 1 base currency in quote currency. scaled by 1e18\\\"}},\\\"getMaxPeriod(address)\\\":{\\\"params\\\":{\\\"_pool\\\":\\\"uniswap pool address\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"max period can be used to request twap\\\"}},\\\"getTimeWeightedAverageTickSafe(address,uint32)\\\":{\\\"details\\\":\\\"this function will not revert\\\",\\\"params\\\":{\\\"_period\\\":\\\"period in second that we want to calculate average on\\\",\\\"_pool\\\":\\\"address of the pool\\\"},\\\"returns\\\":{\\\"timeWeightedAverageTick\\\":\\\"the time weighted average tick\\\"}},\\\"getTwap(address,address,address,uint32,bool)\\\":{\\\"details\\\":\\\"if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\",\\\"params\\\":{\\\"_base\\\":\\\"base currency. to get eth/usd price, eth is base token\\\",\\\"_period\\\":\\\"number of seconds in the past to start calculating time-weighted average\\\",\\\"_pool\\\":\\\"uniswap pool address\\\",\\\"_quote\\\":\\\"quote currency. to get eth/usd price, usd is the quote currency\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"price of 1 base currency in quote currency. scaled by 1e18\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"getHistoricalTwap(address,address,address,uint32,uint32)\\\":{\\\"notice\\\":\\\"get twap for a specific period of time, converted with base & quote token decimals\\\"},\\\"getMaxPeriod(address)\\\":{\\\"notice\\\":\\\"get the max period that can be used to request twap\\\"},\\\"getTimeWeightedAverageTickSafe(address,uint32)\\\":{\\\"notice\\\":\\\"get time weighed average tick, not converted to price\\\"},\\\"getTwap(address,address,address,uint32,bool)\\\":{\\\"notice\\\":\\\"get twap converted with base & quote token decimals\\\"}},\\\"notice\\\":\\\"read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/Oracle.sol\\\":\\\"Oracle\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/core/Oracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\n// uniswap Library only works under 0.7.6\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IERC20Detailed} from \\\\\\\"../interfaces/IERC20Detailed.sol\\\\\\\";\\\\n\\\\n//library\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"../libs/Uint256Casting.sol\\\\\\\";\\\\nimport {OracleLibrary} from \\\\\\\"../libs/OracleLibrary.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\\\n */\\\\ncontract Oracle {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint128 private constant ONE = 1e18;\\\\n\\\\n    /**\\\\n     * @notice get twap converted with base & quote token decimals\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\\\n     */\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256) {\\\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\\\n\\\\n        // make sure the requested period < maxPeriod the pool recorded.\\\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\\\n     */\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _secondsAgoToStartOfTwap,\\\\n        uint32 _secondsAgoToEndOfTwap\\\\n    ) external view returns (uint256) {\\\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the max period that can be used to request twap\\\\n     * @param _pool uniswap pool address\\\\n     * @return max period can be used to request twap\\\\n     */\\\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\\\n        return _getMaxPeriod(_pool);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get time weighed average tick, not converted to price\\\\n     * @dev this function will not revert\\\\n     * @param _pool address of the pool\\\\n     * @param _period period in second that we want to calculate average on\\\\n     * @return timeWeightedAverageTick the time weighted average tick\\\\n     */\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick)\\\\n    {\\\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap converted with base & quote token decimals\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return twap price which is scaled\\\\n     */\\\\n    function _fetchTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\\\n\\\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\\\n\\\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\\\n\\\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get raw twap from the uniswap pool\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\".\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return amount of quote currency received for _amountIn of base currency\\\\n     */\\\\n    function _fetchRawTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\\\n     */\\\\n    function _fetchHistoricTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _secondsAgoToStartOfTwap,\\\\n        uint32 _secondsAgoToEndOfTwap\\\\n    ) internal view returns (uint256) {\\\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\\\n\\\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the max period that can be used to request twap\\\\n     * @param _pool uniswap pool address\\\\n     * @return max period can be used to request twap\\\\n     */\\\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\\\n        // observationIndex: the index of the last oracle observation that was written\\\\n        // cardinality: the current maximum number of observations stored in the pool\\\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\\\n\\\\n        // first observation index\\\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\\\n\\\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\\\n\\\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\\\n\\\\n        // (index + 1) % cardinality is not the oldest index,\\\\n        // probably because cardinality is increased after last observation.\\\\n        // in this case, observation at index 0 should be the oldest.\\\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\\\n\\\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc264ae8c3df6e1db22a95c30e3bbca563d4a351fbfc7d0428fb0da76567aa661\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IERC20Detailed.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// uniswap Library only works under 0.7.6\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IERC20Detailed is IERC20 {\\\\n    function decimals() external view returns (uint8);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcd59a0158d0711810c499904b9d37a71fdb34d1c4403f3cb67ca47de5e88bf7b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/OracleLibrary.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\n//interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\n\\\\n/// @title oracle library\\\\n/// @notice provides functions to integrate with uniswap v3 oracle\\\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\\\nlibrary OracleLibrary {\\\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\\\n    /// @dev written by opyn team\\\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\\\n    function consultAtHistoricTime(\\\\n        address pool,\\\\n        uint32 _secondsAgoToStartOfTwap,\\\\n        uint32 _secondsAgoToEndOfTwap\\\\n    ) internal view returns (int24) {\\\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\\\\\"BP\\\\\\\");\\\\n        int24 timeWeightedAverageTick;\\\\n        uint32[] memory secondAgos = new uint32[](2);\\\\n\\\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\\\n\\\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\\\n\\\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\\\n\\\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\\\n\\\\n        // Always round to negative infinity\\\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\\\n\\\\n        return timeWeightedAverageTick;\\\\n    }\\\\n\\\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\\\n    /// @param tick tick value used to calculate the quote\\\\n    /// @param baseAmount amount of token to be converted\\\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\\\n    function getQuoteAtTick(\\\\n        int24 tick,\\\\n        uint128 baseAmount,\\\\n        address baseToken,\\\\n        address quoteToken\\\\n    ) internal pure returns (uint256 quoteAmount) {\\\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\\\n\\\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\\\n        if (sqrtRatioX96 <= type(uint128).max) {\\\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\\\n            quoteAmount = baseToken < quoteToken\\\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\\\n        } else {\\\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\\\n            quoteAmount = baseToken < quoteToken\\\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x83858224ba4dc88b7ab7f26de42c32d2debfd48a59bd5d011afe7be5d7cbb24f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x608060405234801561001057600080fd5b50610edc806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634a0a96eb146100515780634ac78d111461009a578063cce79bd5146100f6578063de5a6e2214610140575b600080fd5b6100836004803603604081101561006757600080fd5b5080356001600160a01b0316906020013563ffffffff1661017f565b6040805160029290920b8252519081900360200190f35b6100e4600480360360a08110156100b057600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013581169160800135166101c3565b60408051918252519081900360200190f35b6100e4600480360360a081101561010c57600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013516906080013515156101de565b6101666004803603602081101561015657600080fd5b50356001600160a01b031661023c565b6040805163ffffffff9092168252519081900360200190f35b60008061018b8461024f565b905060008163ffffffff168463ffffffff16116101a857836101aa565b815b90506101b8858260006103fb565b925050505b92915050565b60006101d28686868686610713565b90505b95945050505050565b6000816101f8576101f186868686610742565b90506101d5565b60006102038761024f565b905060008163ffffffff168563ffffffff16116102205784610222565b815b905061023088888884610742565b98975050505050505050565b60006102478261024f565b90505b919050565b600080829050600080826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561029157600080fd5b505afa1580156102a5573d6000803e3d6000fd5b505050506040513d60e08110156102bb57600080fd5b5060408101516060909101519092509050600061ffff808316906001850116816102e157fe5b069050600080856001600160a01b031663252c09d7846040518263ffffffff1660e01b8152600401808261ffff16815260200191505060806040518083038186803b15801561032f57600080fd5b505afa158015610343573d6000803e3d6000fd5b505050506040513d608081101561035957600080fd5b5080516060909101519092509050801561037c57504203945061024a9350505050565b856001600160a01b031663252c09d760006040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b1580156103c157600080fd5b505afa1580156103d5573d6000803e3d6000fd5b505050506040513d60808110156103eb57600080fd5b5051420398975050505050505050565b60008163ffffffff168363ffffffff1611610442576040805162461bcd60e51b8152602060048201526002602482015261042560f41b604482015290519081900360640190fd5b6040805160028082526060820183526000928392919060208301908036833701905050905060008486039050858260008151811061047c57fe5b602002602001019063ffffffff16908163ffffffff168152505084826001815181106104a457fe5b63ffffffff90921660209283029190910182015260405163883bdbfd60e01b8152600481018281528451602483015284516000936001600160a01b038c169363883bdbfd938893909283926044019185820191028083838b5b838110156105155781810151838201526020016104fd565b505050509050019250505060006040518083038186803b15801561053857600080fd5b505afa15801561054c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604090815281101561057557600080fd5b810190808051604051939291908464010000000082111561059557600080fd5b9083019060208201858111156105aa57600080fd5b82518660208202830111640100000000821117156105c757600080fd5b82525081516020918201928201910280838360005b838110156105f45781810151838201526020016105dc565b505050509050016040526020018051604051939291908464010000000082111561061d57600080fd5b90830190602082018581111561063257600080fd5b825186602082028301116401000000008211171561064f57600080fd5b82525081516020918201928201910280838360005b8381101561067c578181015183820152602001610664565b5050505090500160405250505050905060008160008151811061069b57fe5b6020026020010151826001815181106106b057fe5b60200260200101510390508263ffffffff168160060b816106cd57fe5b05945060008160060b1280156106f757508263ffffffff168160060b816106f057fe5b0760060b15155b1561070457600019909401935b509293505050505b9392505050565b6000806107218785856103fb565b905061073781670de0b6b3a76400008888610891565b979650505050505050565b600080610751868686866109b5565b90506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561078e57600080fd5b505afa1580156107a2573d6000803e3d6000fd5b505050506040513d60208110156107b857600080fd5b50516040805163313ce56760e01b815290519192506000916001600160a01b0388169163313ce567916004808301926020929190829003018186803b15801561080057600080fd5b505afa158015610814573d6000803e3d6000fd5b505050506040513d602081101561082a57600080fd5b5051905060ff828116908216141561084757829350505050610889565b8060ff168260ff161115610871576108678360ff83850316600a0a6109e4565b9350505050610889565b6108838360ff84840316600a0a610a3d565b93505050505b949350505050565b60008061089d86610aa4565b90506fffffffffffffffffffffffffffffffff6001600160a01b03821611610927576001600160a01b03808216800290848116908616106108fe576108f9600160c01b876fffffffffffffffffffffffffffffffff1683610dd6565b61091f565b61091f81876fffffffffffffffffffffffffffffffff16600160c01b610dd6565b9250506109ac565b60006109466001600160a01b0383168068010000000000000000610dd6565b9050836001600160a01b0316856001600160a01b03161061098757610982600160801b876fffffffffffffffffffffffffffffffff1683610dd6565b6109a8565b6109a881876fffffffffffffffffffffffffffffffff16600160801b610dd6565b9250505b50949350505050565b6000806109c4868460006103fb565b90506109da81670de0b6b3a76400008787610891565b9695505050505050565b6000826109f3575060006101bd565b82820282848281610a0057fe5b041461070c5760405162461bcd60e51b8152600401808060200182810382526021815260200180610e866021913960400191505060405180910390fd5b6000808211610a93576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610a9c57fe5b049392505050565b60008060008360020b12610abb578260020b610ac3565b8260020b6000035b9050620d89e8811115610b01576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216610b1557600160801b610b27565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610b5b576ffff97272373d413259a46990580e213a0260801c5b6004821615610b7a576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615610b99576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610bb8576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610bd7576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610bf6576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610c15576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610c35576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615610c55576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615610c75576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615610c95576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610cb5576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610cd5576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610cf5576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610d15576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610d36576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615610d56576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615610d75576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615610d92576b048a170391f7dc42444e8fa20260801c5b60008460020b1315610dad578060001981610da957fe5b0490505b640100000000810615610dc1576001610dc4565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080610e0c5760008411610e0157600080fd5b50829004905061070c565b808411610e1857600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a0290910302918190038190046001018684119095039490940291909403929092049190911791909102915050939250505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220b1a443112ea45879a00fbc518b3cc36f190c9940d1022cd43a38928e460276ce64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80634a0a96eb146100515780634ac78d111461009a578063cce79bd5146100f6578063de5a6e2214610140575b600080fd5b6100836004803603604081101561006757600080fd5b5080356001600160a01b0316906020013563ffffffff1661017f565b6040805160029290920b8252519081900360200190f35b6100e4600480360360a08110156100b057600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013581169160800135166101c3565b60408051918252519081900360200190f35b6100e4600480360360a081101561010c57600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013516906080013515156101de565b6101666004803603602081101561015657600080fd5b50356001600160a01b031661023c565b6040805163ffffffff9092168252519081900360200190f35b60008061018b8461024f565b905060008163ffffffff168463ffffffff16116101a857836101aa565b815b90506101b8858260006103fb565b925050505b92915050565b60006101d28686868686610713565b90505b95945050505050565b6000816101f8576101f186868686610742565b90506101d5565b60006102038761024f565b905060008163ffffffff168563ffffffff16116102205784610222565b815b905061023088888884610742565b98975050505050505050565b60006102478261024f565b90505b919050565b600080829050600080826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561029157600080fd5b505afa1580156102a5573d6000803e3d6000fd5b505050506040513d60e08110156102bb57600080fd5b5060408101516060909101519092509050600061ffff808316906001850116816102e157fe5b069050600080856001600160a01b031663252c09d7846040518263ffffffff1660e01b8152600401808261ffff16815260200191505060806040518083038186803b15801561032f57600080fd5b505afa158015610343573d6000803e3d6000fd5b505050506040513d608081101561035957600080fd5b5080516060909101519092509050801561037c57504203945061024a9350505050565b856001600160a01b031663252c09d760006040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b1580156103c157600080fd5b505afa1580156103d5573d6000803e3d6000fd5b505050506040513d60808110156103eb57600080fd5b5051420398975050505050505050565b60008163ffffffff168363ffffffff1611610442576040805162461bcd60e51b8152602060048201526002602482015261042560f41b604482015290519081900360640190fd5b6040805160028082526060820183526000928392919060208301908036833701905050905060008486039050858260008151811061047c57fe5b602002602001019063ffffffff16908163ffffffff168152505084826001815181106104a457fe5b63ffffffff90921660209283029190910182015260405163883bdbfd60e01b8152600481018281528451602483015284516000936001600160a01b038c169363883bdbfd938893909283926044019185820191028083838b5b838110156105155781810151838201526020016104fd565b505050509050019250505060006040518083038186803b15801561053857600080fd5b505afa15801561054c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604090815281101561057557600080fd5b810190808051604051939291908464010000000082111561059557600080fd5b9083019060208201858111156105aa57600080fd5b82518660208202830111640100000000821117156105c757600080fd5b82525081516020918201928201910280838360005b838110156105f45781810151838201526020016105dc565b505050509050016040526020018051604051939291908464010000000082111561061d57600080fd5b90830190602082018581111561063257600080fd5b825186602082028301116401000000008211171561064f57600080fd5b82525081516020918201928201910280838360005b8381101561067c578181015183820152602001610664565b5050505090500160405250505050905060008160008151811061069b57fe5b6020026020010151826001815181106106b057fe5b60200260200101510390508263ffffffff168160060b816106cd57fe5b05945060008160060b1280156106f757508263ffffffff168160060b816106f057fe5b0760060b15155b1561070457600019909401935b509293505050505b9392505050565b6000806107218785856103fb565b905061073781670de0b6b3a76400008888610891565b979650505050505050565b600080610751868686866109b5565b90506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561078e57600080fd5b505afa1580156107a2573d6000803e3d6000fd5b505050506040513d60208110156107b857600080fd5b50516040805163313ce56760e01b815290519192506000916001600160a01b0388169163313ce567916004808301926020929190829003018186803b15801561080057600080fd5b505afa158015610814573d6000803e3d6000fd5b505050506040513d602081101561082a57600080fd5b5051905060ff828116908216141561084757829350505050610889565b8060ff168260ff161115610871576108678360ff83850316600a0a6109e4565b9350505050610889565b6108838360ff84840316600a0a610a3d565b93505050505b949350505050565b60008061089d86610aa4565b90506fffffffffffffffffffffffffffffffff6001600160a01b03821611610927576001600160a01b03808216800290848116908616106108fe576108f9600160c01b876fffffffffffffffffffffffffffffffff1683610dd6565b61091f565b61091f81876fffffffffffffffffffffffffffffffff16600160c01b610dd6565b9250506109ac565b60006109466001600160a01b0383168068010000000000000000610dd6565b9050836001600160a01b0316856001600160a01b03161061098757610982600160801b876fffffffffffffffffffffffffffffffff1683610dd6565b6109a8565b6109a881876fffffffffffffffffffffffffffffffff16600160801b610dd6565b9250505b50949350505050565b6000806109c4868460006103fb565b90506109da81670de0b6b3a76400008787610891565b9695505050505050565b6000826109f3575060006101bd565b82820282848281610a0057fe5b041461070c5760405162461bcd60e51b8152600401808060200182810382526021815260200180610e866021913960400191505060405180910390fd5b6000808211610a93576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610a9c57fe5b049392505050565b60008060008360020b12610abb578260020b610ac3565b8260020b6000035b9050620d89e8811115610b01576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216610b1557600160801b610b27565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610b5b576ffff97272373d413259a46990580e213a0260801c5b6004821615610b7a576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615610b99576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610bb8576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610bd7576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610bf6576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610c15576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610c35576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615610c55576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615610c75576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615610c95576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610cb5576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610cd5576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610cf5576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610d15576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610d36576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615610d56576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615610d75576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615610d92576b048a170391f7dc42444e8fa20260801c5b60008460020b1315610dad578060001981610da957fe5b0490505b640100000000810615610dc1576001610dc4565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080610e0c5760008411610e0157600080fd5b50829004905061070c565b808411610e1857600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a0290910302918190038190046001018684119095039490940291909403929092049190911791909102915050939250505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220b1a443112ea45879a00fbc518b3cc36f190c9940d1022cd43a38928e460276ce64736f6c63430007060033\",\n  \"devdoc\": {\n    \"details\": \"if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"getHistoricalTwap(address,address,address,uint32,uint32)\": {\n        \"details\": \"if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\",\n        \"params\": {\n          \"_base\": \"base currency. to get eth/usd price, eth is base token\",\n          \"_pool\": \"uniswap pool address\",\n          \"_quote\": \"quote currency. to get eth/usd price, usd is the quote currency\",\n          \"_secondsAgoToEndOfTwap\": \"amount of seconds in the past to end calculating time-weighted average\",\n          \"_secondsAgoToStartOfTwap\": \"amount of seconds in the past to start calculating time-weighted average\"\n        },\n        \"returns\": {\n          \"_0\": \"price of 1 base currency in quote currency. scaled by 1e18\"\n        }\n      },\n      \"getMaxPeriod(address)\": {\n        \"params\": {\n          \"_pool\": \"uniswap pool address\"\n        },\n        \"returns\": {\n          \"_0\": \"max period can be used to request twap\"\n        }\n      },\n      \"getTimeWeightedAverageTickSafe(address,uint32)\": {\n        \"details\": \"this function will not revert\",\n        \"params\": {\n          \"_period\": \"period in second that we want to calculate average on\",\n          \"_pool\": \"address of the pool\"\n        },\n        \"returns\": {\n          \"timeWeightedAverageTick\": \"the time weighted average tick\"\n        }\n      },\n      \"getTwap(address,address,address,uint32,bool)\": {\n        \"details\": \"if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\",\n        \"params\": {\n          \"_base\": \"base currency. to get eth/usd price, eth is base token\",\n          \"_period\": \"number of seconds in the past to start calculating time-weighted average\",\n          \"_pool\": \"uniswap pool address\",\n          \"_quote\": \"quote currency. to get eth/usd price, usd is the quote currency\"\n        },\n        \"returns\": {\n          \"_0\": \"price of 1 base currency in quote currency. scaled by 1e18\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"getHistoricalTwap(address,address,address,uint32,uint32)\": {\n        \"notice\": \"get twap for a specific period of time, converted with base & quote token decimals\"\n      },\n      \"getMaxPeriod(address)\": {\n        \"notice\": \"get the max period that can be used to request twap\"\n      },\n      \"getTimeWeightedAverageTickSafe(address,uint32)\": {\n        \"notice\": \"get time weighed average tick, not converted to price\"\n      },\n      \"getTwap(address,address,address,uint32,bool)\": {\n        \"notice\": \"get twap converted with base & quote token decimals\"\n      }\n    },\n    \"notice\": \"read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/Quoter.json",
    "content": "{\n  \"address\": \"0xC8d3a4e6BB4952E3658CCA5081c358e6935Efa43\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_factory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_WETH9\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"WETH9\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"path\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"quoteExactInput\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160[]\",\n          \"name\": \"sqrtPriceX96AfterList\",\n          \"type\": \"uint160[]\"\n        },\n        {\n          \"internalType\": \"uint32[]\",\n          \"name\": \"initializedTicksCrossedList\",\n          \"type\": \"uint32[]\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountIn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct IQuoterV2.QuoteExactInputSingleParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"quoteExactInputSingle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96After\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"initializedTicksCrossed\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"path\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"quoteExactOutput\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160[]\",\n          \"name\": \"sqrtPriceX96AfterList\",\n          \"type\": \"uint160[]\"\n        },\n        {\n          \"internalType\": \"uint32[]\",\n          \"name\": \"initializedTicksCrossedList\",\n          \"type\": \"uint32[]\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct IQuoterV2.QuoteExactOutputSingleParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"quoteExactOutputSingle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96After\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"initializedTicksCrossed\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"path\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x8ab6f7118bff2702e2eec631b1565c78a094b2311f2a4b67e0c8525bfeb5d572\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x80010e7575b24f47097598474502F0fd0aDbF3a8\",\n    \"contractAddress\": \"0xC8d3a4e6BB4952E3658CCA5081c358e6935Efa43\",\n    \"transactionIndex\": 96,\n    \"gasUsed\": \"1836365\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x8889e8a97a48e2ac4f1705a761e087ba5c8c74c91e1adf663141c875b9f12a9e\",\n    \"transactionHash\": \"0x8ab6f7118bff2702e2eec631b1565c78a094b2311f2a4b67e0c8525bfeb5d572\",\n    \"logs\": [],\n    \"blockNumber\": 13977429,\n    \"cumulativeGasUsed\": \"7000518\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x1F98431c8aD98523631AE4a59f267346ea31F984\",\n    \"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\"\n  ],\n  \"bytecode\": \"0x60c06040523480156200001157600080fd5b506040516200212c3803806200212c833981016040819052620000349162000070565b6001600160601b0319606092831b8116608052911b1660a052620000a7565b80516001600160a01b03811681146200006b57600080fd5b919050565b6000806040838503121562000083578182fd5b6200008e8362000053565b91506200009e6020840162000053565b90509250929050565b60805160601c60a05160601c612051620000db60003980610321525080610577528061095d5280610b9252506120516000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063c45a01551161005b578063c45a0155146100e6578063c6a5026a146100ee578063cdca175314610101578063fa461e33146101145761007d565b80632f80bb1d146100825780634aa4a4fc146100ae578063bd21704a146100c3575b600080fd5b610095610090366004611b2b565b610129565b6040516100a59493929190611eac565b60405180910390f35b6100b661031f565b6040516100a59190611def565b6100d66100d1366004611c49565b610343565b6040516100a59493929190611f54565b6100b6610575565b6100d66100fc366004611c49565b610599565b61009561010f366004611b2b565b610754565b610127610122366004611b91565b61092c565b005b6000606080600061013986610ae8565b67ffffffffffffffff8111801561014f57600080fd5b50604051908082528060200260200182016040528015610179578160200160208202803683370190505b50925061018586610ae8565b67ffffffffffffffff8111801561019b57600080fd5b506040519080825280602002602001820160405280156101c5578160200160208202803683370190505b50915060005b60008060006101d98a610b17565b92509250925060008060008061025c6040518060a001604052808873ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018f81526020018762ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250610343565b9350935093509350828b898151811061027157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818a89815181106102b857fe5b63ffffffff90921660209283029190910190910152929b50968201966001909601958b926102e58e610b48565b156102fa576102f38e610b50565b9d5061030a565b8c9b505050505050505050610316565b505050505050506101cb565b92959194509250565b7f000000000000000000000000000000000000000000000000000000000000000081565b60208101518151606083015160009283928392839273ffffffffffffffffffffffffffffffffffffffff808216908416109284926103819290610b8b565b9050866080015173ffffffffffffffffffffffffffffffffffffffff16600014156103af5760408701516000555b60005a90508173ffffffffffffffffffffffffffffffffffffffff1663128acb0830856103df8c60400151610bc9565b6000038c6080015173ffffffffffffffffffffffffffffffffffffffff1660001461040e578c60800151610434565b8761042d5773fffd8963efd1fc6a506488495d951d5263988d25610434565b6401000276a45b8d602001518e606001518f6000015160405160200161045593929190611d89565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610484959493929190611e10565b6040805180830381600087803b15801561049d57600080fd5b505af19250505080156104eb575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526104e891810190611b6e565b60015b610568573d808015610519576040519150601f19603f3d011682016040523d82523d6000602084013e61051e565b606091505b505a82039450886080015173ffffffffffffffffffffffffffffffffffffffff166000141561054c57600080555b610557818487610bfb565b97509750975097505050505061056e565b50505050505b9193509193565b7f000000000000000000000000000000000000000000000000000000000000000081565b60208101518151606083015160009283928392839273ffffffffffffffffffffffffffffffffffffffff808216908416109284926105d79290610b8b565b905060005a90508173ffffffffffffffffffffffffffffffffffffffff1663128acb0830856106098c60400151610bc9565b60808d015173ffffffffffffffffffffffffffffffffffffffff1615610633578c60800151610659565b876106525773fffd8963efd1fc6a506488495d951d5263988d25610659565b6401000276a45b8d600001518e606001518f6020015160405160200161067a93929190611d89565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016106a9959493929190611e10565b6040805180830381600087803b1580156106c257600080fd5b505af1925050508015610710575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261070d91810190611b6e565b60015b610568573d80801561073e576040519150601f19603f3d011682016040523d82523d6000602084013e610743565b606091505b505a82039450610557818487610bfb565b6000606080600061076486610ae8565b67ffffffffffffffff8111801561077a57600080fd5b506040519080825280602002602001820160405280156107a4578160200160208202803683370190505b5092506107b086610ae8565b67ffffffffffffffff811180156107c657600080fd5b506040519080825280602002602001820160405280156107f0578160200160208202803683370190505b50915060005b60008060006108048a610b17565b9250925092506000806000806108876040518060a001604052808973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018f81526020018762ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250610599565b9350935093509350828b898151811061089c57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818a89815181106108e357fe5b63ffffffff90921660209283029190910190910152929b50968201966001909601958b926109108e610b48565b156102fa5761091e8e610b50565b9d50505050505050506107f6565b600083138061093b5750600082135b61094457600080fd5b600080600061095284610b17565b9250925092506109847f0000000000000000000000000000000000000000000000000000000000000000848484610ccf565b5060008060008089136109ca578573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1610888a6000036109ff565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161089896000035b9250925092506000610a12878787610b8b565b90506000808273ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610a5d57600080fd5b505afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190611c6b565b5050505050915091508515610abb57604051848152826020820152816040820152606081fd5b60005415610ad1576000548414610ad157600080fd5b604051858152826020820152816040820152606081fd5b805160177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec909101045b919050565b60008080610b258482610cee565b9250610b32846014610dee565b9050610b3f846017610cee565b91509193909250565b516042111590565b8051606090610b859083906017907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901610ede565b92915050565b6000610bc17f0000000000000000000000000000000000000000000000000000000000000000610bbc8686866110c5565b611142565b949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210610bf757600080fd5b5090565b6000806000806000808773ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610c4a57600080fd5b505afa158015610c5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c829190611c6b565b50939650610c9794508d935061127892505050565b91975095509050610cbf73ffffffffffffffffffffffffffffffffffffffff89168383611339565b9350869250505093509350935093565b6000610ce585610ce08686866110c5565b611991565b95945050505050565b600081826014011015610d6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b8160140183511015610dd557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015610e6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b8160030183511015610ed557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b60608182601f011015610f5257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b828284011015610fc357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b8183018451101561103557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015290519081900360640190fd5b60608215801561105457604051915060008252602082016040526110bc565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561108d578051835260209283019201611075565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6110cd6119fa565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161115611105579192915b506040805160608101825273ffffffffffffffffffffffffffffffffffffffff948516815292909316602083015262ffffff169181019190915290565b6000816020015173ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff161061118457600080fd5b508051602080830151604093840151845173ffffffffffffffffffffffffffffffffffffffff94851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b60008060008351606014611318576044845110156112cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c290611e75565b60405180910390fd5b600484019350838060200190518101906112e59190611bdf565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c29190611e62565b8380602001905181019061132c9190611d02565b9250925092509193909250565b60008060008060008060008060088b73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561138d57600080fd5b505afa1580156113a1573d6000803e3d6000fd5b505050506040513d60208110156113b757600080fd5b5051600290810b908c900b816113c957fe5b0560020b901d905060006101008c73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561141c57600080fd5b505afa158015611430573d6000803e3d6000fd5b505050506040513d602081101561144657600080fd5b5051600290810b908d900b8161145857fe5b0560020b8161146357fe5b079050600060088d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114b057600080fd5b505afa1580156114c4573d6000803e3d6000fd5b505050506040513d60208110156114da57600080fd5b5051600290810b908d900b816114ec57fe5b0560020b901d905060006101008e73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561153f57600080fd5b505afa158015611553573d6000803e3d6000fd5b505050506040513d602081101561156957600080fd5b5051600290810b908e900b8161157b57fe5b0560020b8161158657fe5b07905060008160ff166001901b8f73ffffffffffffffffffffffffffffffffffffffff16635339c296856040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b5051161180156116a457508d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561166257600080fd5b505afa158015611676573d6000803e3d6000fd5b505050506040513d602081101561168c57600080fd5b5051600290810b908d900b8161169e57fe5b0760020b155b80156116b557508b60020b8d60020b135b945060008360ff166001901b8f73ffffffffffffffffffffffffffffffffffffffff16635339c296876040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b15801561171557600080fd5b505afa158015611729573d6000803e3d6000fd5b505050506040513d602081101561173f57600080fd5b5051161180156117d257508d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561179057600080fd5b505afa1580156117a4573d6000803e3d6000fd5b505050506040513d60208110156117ba57600080fd5b5051600290810b908e900b816117cc57fe5b0760020b155b80156117e357508b60020b8d60020b125b95508160010b8460010b128061180f57508160010b8460010b14801561180f57508060ff168360ff1611155b1561182557839950829750819850809650611832565b8199508097508398508296505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff87161b9150505b8560010b8760010b13611969578560010b8760010b14156118a3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff858103161c165b6000818c73ffffffffffffffffffffffffffffffffffffffff16635339c2968a6040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b1580156118fa57600080fd5b505afa15801561190e573d6000803e3d6000fd5b505050506040513d602081101561192457600080fd5b5051169050611932816119c1565b61ffff16989098019750506001909501947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61185e565b8115611976576001880397505b8215611983576001880397505b505050505050509392505050565b600061199d8383611142565b90503373ffffffffffffffffffffffffffffffffffffffff821614610b8557600080fd5b6000805b8215610b85577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301909216916001016119c5565b604080516060810182526000808252602082018190529181019190915290565b600082601f830112611a2a578081fd5b8135611a3d611a3882611faf565b611f8b565b818152846020838601011115611a51578283fd5b816020850160208301379081016020019190915292915050565b8051600281900b8114610b1257600080fd5b600060a08284031215611a8e578081fd5b60405160a0810181811067ffffffffffffffff82111715611aab57fe5b6040529050808235611abc8161201f565b81526020830135611acc8161201f565b602082015260408381013590820152606083013562ffffff81168114611af157600080fd5b6060820152611b0260808401611b0e565b60808201525092915050565b8035610b128161201f565b805161ffff81168114610b1257600080fd5b60008060408385031215611b3d578182fd5b823567ffffffffffffffff811115611b53578283fd5b611b5f85828601611a1a565b95602094909401359450505050565b60008060408385031215611b80578182fd5b505080516020909101519092909150565b600080600060608486031215611ba5578081fd5b8335925060208401359150604084013567ffffffffffffffff811115611bc9578182fd5b611bd586828701611a1a565b9150509250925092565b600060208284031215611bf0578081fd5b815167ffffffffffffffff811115611c06578182fd5b8201601f81018413611c16578182fd5b8051611c24611a3882611faf565b818152856020838501011115611c38578384fd5b610ce5826020830160208601611fef565b600060a08284031215611c5a578081fd5b611c648383611a7d565b9392505050565b600080600080600080600060e0888a031215611c85578283fd5b8751611c908161201f565b9650611c9e60208901611a6b565b9550611cac60408901611b19565b9450611cba60608901611b19565b9350611cc860808901611b19565b925060a088015160ff81168114611cdd578283fd5b60c08901519092508015158114611cf2578182fd5b8091505092959891949750929550565b600080600060608486031215611d16578081fd5b835192506020840151611d288161201f565b9150611d3660408501611a6b565b90509250925092565b60008151808452611d57816020860160208601611fef565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a06080830152611e5760a0830184611d3f565b979650505050505050565b600060208252611c646020830184611d3f565b60208082526010908201527f556e6578706563746564206572726f7200000000000000000000000000000000604082015260600190565b600060808201868352602060808185015281875180845260a0860191508289019350845b81811015611f0257845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101611ed0565b505084810360408601528651808252908201925081870190845b81811015611f3e57825163ffffffff1685529383019391830191600101611f1c565b5050505060609290920192909252949350505050565b93845273ffffffffffffffffffffffffffffffffffffffff92909216602084015263ffffffff166040830152606082015260800190565b60405181810167ffffffffffffffff81118282101715611fa757fe5b604052919050565b600067ffffffffffffffff821115611fc357fe5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b8381101561200a578181015183820152602001611ff2565b83811115612019576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461204157600080fd5b5056fea164736f6c6343000706000a\"\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/ShortHelper.json",
    "content": "{\n  \"address\": \"0x3b4095D5ff0e629972CAAa50bd3004B09a1632C5\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controllerAddr\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_swapRouter\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wethAddr\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_withdrawAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOut\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountInMaximum\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactOutputSingleParams\",\n          \"name\": \"_exactOutputParams\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"closeShort\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"controller\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IController\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onERC721Received\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_powerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniNftId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountIn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOutMinimum\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactInputSingleParams\",\n          \"name\": \"_exactInputParams\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"openShort\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"router\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract ISwapRouter\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"shortPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IShortPowerPerp\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IWETH9\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0xed01b8ac049e86818eb3195840f6bf167bb7d84916dd12d66d4287dbcc6f4a76\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xa3cB04d8BD927EEC8826BD77b7C71abE3d29c081\",\n    \"contractAddress\": \"0x3b4095D5ff0e629972CAAa50bd3004B09a1632C5\",\n    \"transactionIndex\": 131,\n    \"gasUsed\": \"1067532\",\n    \"logsBloom\": \"0x00000002000000000000000000000000000000000000000000000100000000000000100000000000000000000000000002000000080000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000004100000100000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000020000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000800000000000000000000000000000000\",\n    \"blockHash\": \"0x22e5959137a7afadb6ba777526b440f8a2d8840c13406f506a02924f765a064e\",\n    \"transactionHash\": \"0xed01b8ac049e86818eb3195840f6bf167bb7d84916dd12d66d4287dbcc6f4a76\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 131,\n        \"blockNumber\": 13982573,\n        \"transactionHash\": \"0xed01b8ac049e86818eb3195840f6bf167bb7d84916dd12d66d4287dbcc6f4a76\",\n        \"address\": \"0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x0000000000000000000000003b4095d5ff0e629972caaa50bd3004b09a1632c5\",\n          \"0x000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 178,\n        \"blockHash\": \"0x22e5959137a7afadb6ba777526b440f8a2d8840c13406f506a02924f765a064e\"\n      },\n      {\n        \"transactionIndex\": 131,\n        \"blockNumber\": 13982573,\n        \"transactionHash\": \"0xed01b8ac049e86818eb3195840f6bf167bb7d84916dd12d66d4287dbcc6f4a76\",\n        \"address\": \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x0000000000000000000000003b4095d5ff0e629972caaa50bd3004b09a1632c5\",\n          \"0x000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 179,\n        \"blockHash\": \"0x22e5959137a7afadb6ba777526b440f8a2d8840c13406f506a02924f765a064e\"\n      }\n    ],\n    \"blockNumber\": 13982573,\n    \"cumulativeGasUsed\": \"10719031\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x64187ae08781B09368e6253F9E94951243A493D5\",\n    \"0xE592427A0AEce92De3Edee1F18E0157C05861564\",\n    \"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\"\n  ],\n  \"solcInputHash\": \"d97d3d4b09e0d70518330d405a7dd9ff\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controllerAddr\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_swapRouter\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wethAddr\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"deadline\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountOut\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountInMaximum\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceLimitX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"internalType\\\":\\\"struct ISwapRouter.ExactOutputSingleParams\\\",\\\"name\\\":\\\"_exactOutputParams\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"closeShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IController\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onERC721Received\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniNftId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"deadline\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountIn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountOutMinimum\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceLimitX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"internalType\\\":\\\"struct ISwapRouter.ExactInputSingleParams\\\",\\\"name\\\":\\\"_exactInputParams\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"openShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"router\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract ISwapRouter\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"shortPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IShortPowerPerp\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IWETH9\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"params\\\":{\\\"_vaultId\\\":\\\"short wPowerPerp vault id\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to burn\\\",\\\"_withdrawAmount\\\":\\\"amount to withdraw\\\"}},\\\"constructor\\\":{\\\"params\\\":{\\\"_controllerAddr\\\":\\\"controller address for wPowerPerp\\\",\\\"_swapRouter\\\":\\\"uniswap v3 swap router address\\\",\\\"_wethAddr\\\":\\\"weth address\\\"}},\\\"onERC721Received(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"accept erc721 from safeTransferFrom and safeMint after callback\\\",\\\"returns\\\":{\\\"_0\\\":\\\"returns received selector\\\"}},\\\"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"params\\\":{\\\"_powerPerpAmount\\\":\\\"amount of powerPerp to mint/sell\\\",\\\"_uniNftId\\\":\\\"uniswap v3 position token id\\\",\\\"_vaultId\\\":\\\"short wPowerPerp vault id\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"notice\\\":\\\"buy back wPowerPerp with eth on uniswap v3 and close position\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"constructor for short helper\\\"},\\\"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"notice\\\":\\\"mint power perp, trade with uniswap v3 and send back premium in eth\\\"}},\\\"notice\\\":\\\"contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/periphery/ShortHelper.sol\\\":\\\"ShortHelper\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\\\n\\\\n/// @title Router token swapping functionality\\\\n/// @notice Functions for swapping tokens via Uniswap V3\\\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\\\n    struct ExactInputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactInputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactOutputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\\\n\\\\n    struct ExactOutputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9bfaf1feb32814623e627ab70f2409760b15d95f1f9b058e2b3399a8bb732975\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnOnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc5d6230c8bafcaf2ae7260efd68c45ab13e91819ed9e11881b29dc48386e4bc7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8a9a4512f1fc29b14dcf97ca149f263f28de43191a3ee31336f2389e3f2f5f8e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x939175a827c8e9d8d09ee55957e8127a6a55bf42d6a0b3e48b0b59c895aa85af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/ShortHelper.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n// Interfaces\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\nimport {IERC721Receiver} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\\\\\";\\\\nimport {ISwapRouter} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\\\\\";\\\\n\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// Libraries\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ReentrancyGuard} from \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\\\n */\\\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    IController public immutable controller;\\\\n    ISwapRouter public immutable router;\\\\n    IWETH9 public immutable weth;\\\\n    IShortPowerPerp public immutable shortPowerPerp;\\\\n    address public immutable wPowerPerp;\\\\n\\\\n    /**\\\\n     * @notice constructor for short helper\\\\n     * @param _controllerAddr controller address for wPowerPerp\\\\n     * @param _swapRouter uniswap v3 swap router address\\\\n     * @param _wethAddr weth address\\\\n     */\\\\n    constructor(\\\\n        address _controllerAddr,\\\\n        address _swapRouter,\\\\n        address _wethAddr\\\\n    ) {\\\\n        require(_controllerAddr != address(0), \\\\\\\"Invalid controller address\\\\\\\");\\\\n        require(_swapRouter != address(0), \\\\\\\"Invalid swap router address\\\\\\\");\\\\n        require(_wethAddr != address(0), \\\\\\\"Invalid weth address\\\\\\\");\\\\n        IController _controller = IController(_controllerAddr);\\\\n        router = ISwapRouter(_swapRouter);\\\\n        wPowerPerp = _controller.wPowerPerp();\\\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\\\n        IWETH9 _weth = IWETH9(_wethAddr);\\\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\\\n        _weth.approve(_swapRouter, type(uint256).max);\\\\n\\\\n        // assign immutable variables\\\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\\\n        weth = _weth;\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\\\n     * @param _vaultId short wPowerPerp vault id\\\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\\\n     * @param _uniNftId uniswap v3 position token id\\\\n     */\\\\n    function openShort(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniNftId,\\\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\\\n    ) external payable nonReentrant {\\\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\\\\\"Not allowed\\\\\\\");\\\\n        require(\\\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\\\n            \\\\\\\"Wrong swap tokens\\\\\\\"\\\\n        );\\\\n\\\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\\\n            _vaultId,\\\\n            _powerPerpAmount,\\\\n            _uniNftId\\\\n        );\\\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\\\n\\\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\\\n\\\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\\\n        if (_exactInputParams.recipient == address(this)) {\\\\n            weth.withdraw(amountOut);\\\\n            payable(msg.sender).sendValue(amountOut);\\\\n        }\\\\n\\\\n        // this is a newly open vault, transfer to the user.\\\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\\\n     * @param _vaultId short wPowerPerp vault id\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\\\n     * @param _withdrawAmount amount to withdraw\\\\n     */\\\\n    function closeShort(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount,\\\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\\\n    ) external payable nonReentrant {\\\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\\\\\"Not allowed\\\\\\\");\\\\n        require(\\\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\\\n            \\\\\\\"Wrong swap tokens\\\\\\\"\\\\n        );\\\\n\\\\n        // wrap eth to weth\\\\n        weth.deposit{value: msg.value}();\\\\n\\\\n        // pay weth and get wPowerPerp in return.\\\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\\\n\\\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\\\n\\\\n        // send back unused eth and withdrawn collateral\\\\n        weth.withdraw(msg.value.sub(amountIn));\\\\n        // no eth should be left in the contract, so we send it all back\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev only receive eth from weth contract and controller.\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\\\\\"can't receive eth\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\\\n     * @return returns received selector\\\\n     */\\\\n    function onERC721Received(\\\\n        address,\\\\n        address,\\\\n        uint256,\\\\n        bytes memory\\\\n    ) public virtual override returns (bytes4) {\\\\n        return this.onERC721Received.selector;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x512bb00cb9e4a780ba460ef629f3c581feb8ca669373417beeefdcbc1233c4d1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101206040523480156200001257600080fd5b5060405162001643380380620016438339810160408190526200003591620003e6565b60016000556001600160a01b0383166200006c5760405162461bcd60e51b81526004016200006390620004a1565b60405180910390fd5b6001600160a01b038216620000955760405162461bcd60e51b81526004016200006390620004d8565b6001600160a01b038116620000be5760405162461bcd60e51b815260040162000063906200046a565b6000839050826001600160a01b031660a0816001600160a01b031660601b81525050806001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b1580156200011a57600080fd5b505afa1580156200012f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001559190620003c2565b6001600160a01b0316610100816001600160a01b031660601b815250506000816001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b158015620001ae57600080fd5b505afa158015620001c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001e99190620003c2565b60405163095ea7b360e01b815290915083906001600160a01b0383169063095ea7b390620002209088906000199060040162000451565b602060405180830381600087803b1580156200023b57600080fd5b505af115801562000250573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200027691906200042f565b5060405163095ea7b360e01b81526001600160a01b0382169063095ea7b390620002a99088906000199060040162000451565b602060405180830381600087803b158015620002c457600080fd5b505af1158015620002d9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ff91906200042f565b50826001600160a01b0316639d4c94426040518163ffffffff1660e01b815260040160206040518083038186803b1580156200033a57600080fd5b505afa1580156200034f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003759190620003c2565b6001600160601b0319606091821b811660e05291811b821660c0529290921b909116608052506200050f92505050565b80516001600160a01b0381168114620003bd57600080fd5b919050565b600060208284031215620003d4578081fd5b620003df82620003a5565b9392505050565b600080600060608486031215620003fb578182fd5b6200040684620003a5565b92506200041660208501620003a5565b91506200042660408501620003a5565b90509250925092565b60006020828403121562000441578081fd5b81518015158114620003df578182fd5b6001600160a01b03929092168252602082015260400190565b60208082526014908201527f496e76616c696420776574682061646472657373000000000000000000000000604082015260600190565b6020808252601a908201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604082015260600190565b6020808252601b908201527f496e76616c6964207377617020726f7574657220616464726573730000000000604082015260600190565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c611097620005ac60003980610314528061060a52806107b952508061025f528061062e52806106c45280610a1e525080608f528061035452806103aa528061054a52806105e65280610779528061098e52508061043452806108d85280610abe52508060c152806104d752806108125280610a9a52506110976000f3fe60806040526004361061007f5760003560e01c80639d4c94421161004e5780639d4c94421461018f578063e56cfbbe146101a4578063f77c4791146101b7578063f887ea40146101cc5761010a565b8063150b7a021461010f57806317fd9e0e146101455780633fc8cef3146101585780637f07b1301461017a5761010a565b3661010a57336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100e35750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6101085760405162461bcd60e51b81526004016100ff90610f86565b60405180910390fd5b005b600080fd5b34801561011b57600080fd5b5061012f61012a366004610d1e565b6101e1565b60405161013c9190610eeb565b60405180910390f35b610108610153366004610e0f565b6101f1565b34801561016457600080fd5b5061016d6105e4565b60405161013c9190610eb3565b34801561018657600080fd5b5061016d610608565b34801561019b57600080fd5b5061016d61062c565b6101086101b2366004610e0f565b610650565b3480156101c357600080fd5b5061016d610a98565b3480156101d857600080fd5b5061016d610abc565b630a85bd0160e11b949350505050565b60026000541415610249576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000556040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e9061029c908890600401610fcc565b60206040518083038186803b1580156102b457600080fd5b505afa1580156102c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ec9190610cfb565b6001600160a01b0316146103125760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b031614801561038c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b6103a85760405162461bcd60e51b81526004016100ff90610f18565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561040357600080fd5b505af1158015610417573d6000803e3d6000fd5b5050604051631b67c43360e31b8152600093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063db3e2198915061046b908590600401610fbd565b602060405180830381600087803b15801561048557600080fd5b505af1158015610499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104bd9190610dd4565b604051638632cb0360e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638632cb039061051090889088908890600401610fd5565b600060405180830381600087803b15801561052a57600080fd5b505af115801561053e573d6000803e3d6000fd5b50506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169150632e1a7d4d905061057d3484610ae0565b6040518263ffffffff1660e01b81526004016105999190610fcc565b600060405180830381600087803b1580156105b357600080fd5b505af11580156105c7573d6000803e3d6000fd5b506105d89250339150479050610b42565b50506001600055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600260005414156106a8576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000558315610777576040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90610701908890600401610fcc565b60206040518083038186803b15801561071957600080fd5b505afa15801561072d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107519190610cfb565b6001600160a01b0316146107775760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b03161480156107f157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b61080d5760405162461bcd60e51b81526004016100ff90610f18565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631bf7bf6c348888886040518563ffffffff1660e01b815260040161086193929190610fd5565b60408051808303818588803b15801561087957600080fd5b505af115801561088d573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906108b29190610dec565b60a0850181905260405163414bf38960e01b815291935091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063414bf3899061090d908790600401610fbd565b602060405180830381600087803b15801561092757600080fd5b505af115801561093b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095f9190610dd4565b60608501519091506001600160a01b0316301415610a0257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906109c3908490600401610fcc565b600060405180830381600087803b1580156109dd57600080fd5b505af11580156109f1573d6000803e3d6000fd5b50610a029250339150839050610b42565b86610a8a57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610a5790309033908890600401610ec7565b600060405180830381600087803b158015610a7157600080fd5b505af1158015610a85573d6000803e3d6000fd5b505050505b505060016000555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600082821115610b37576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b80471015610b97576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610be2576040519150601f19603f3d011682016040523d82523d6000602084013e610be7565b606091505b5050905080610c275760405162461bcd60e51b815260040180806020018281038252603a815260200180611028603a913960400191505060405180910390fd5b505050565b8035610c378161100f565b919050565b6000610100808385031215610c4f578182fd5b6040519081019067ffffffffffffffff82118183101715610c6c57fe5b81604052809250610c7c84610c2c565b8152610c8a60208501610c2c565b6020820152610c9b60408501610ce8565b6040820152610cac60608501610c2c565b60608201526080840135608082015260a084013560a082015260c084013560c0820152610cdb60e08501610c2c565b60e0820152505092915050565b803562ffffff81168114610c3757600080fd5b600060208284031215610d0c578081fd5b8151610d178161100f565b9392505050565b60008060008060808587031215610d33578283fd5b8435610d3e8161100f565b9350602085810135610d4f8161100f565b935060408601359250606086013567ffffffffffffffff80821115610d72578384fd5b818801915088601f830112610d85578384fd5b813581811115610d9157fe5b610da3601f8201601f19168501610feb565b91508082528984828501011115610db8578485fd5b8084840185840137810190920192909252939692955090935050565b600060208284031215610de5578081fd5b5051919050565b60008060408385031215610dfe578182fd5b505080516020909101519092909150565b6000806000806101608587031215610e25578384fd5b843593506020850135925060408501359150610e448660608701610c3c565b905092959194509250565b6001600160a01b0380825116835280602083015116602084015262ffffff60408301511660408401528060608301511660608401526080820151608084015260a082015160a084015260c082015160c08401528060e08301511660e0840152505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b60208082526011908201527f57726f6e67207377617020746f6b656e73000000000000000000000000000000604082015260600190565b6020808252600b908201527f4e6f7420616c6c6f776564000000000000000000000000000000000000000000604082015260600190565b60208082526011908201527f63616e2774207265636569766520657468000000000000000000000000000000604082015260600190565b6101008101610b3c8284610e4f565b90815260200190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561100757fe5b604052919050565b6001600160a01b038116811461102457600080fd5b5056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a2646970667358221220dca83f927accd8f5dd17b8c7ca8e2147659fcc484c1799c390e51729507a6b9f64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x60806040526004361061007f5760003560e01c80639d4c94421161004e5780639d4c94421461018f578063e56cfbbe146101a4578063f77c4791146101b7578063f887ea40146101cc5761010a565b8063150b7a021461010f57806317fd9e0e146101455780633fc8cef3146101585780637f07b1301461017a5761010a565b3661010a57336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100e35750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6101085760405162461bcd60e51b81526004016100ff90610f86565b60405180910390fd5b005b600080fd5b34801561011b57600080fd5b5061012f61012a366004610d1e565b6101e1565b60405161013c9190610eeb565b60405180910390f35b610108610153366004610e0f565b6101f1565b34801561016457600080fd5b5061016d6105e4565b60405161013c9190610eb3565b34801561018657600080fd5b5061016d610608565b34801561019b57600080fd5b5061016d61062c565b6101086101b2366004610e0f565b610650565b3480156101c357600080fd5b5061016d610a98565b3480156101d857600080fd5b5061016d610abc565b630a85bd0160e11b949350505050565b60026000541415610249576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000556040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e9061029c908890600401610fcc565b60206040518083038186803b1580156102b457600080fd5b505afa1580156102c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ec9190610cfb565b6001600160a01b0316146103125760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b031614801561038c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b6103a85760405162461bcd60e51b81526004016100ff90610f18565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561040357600080fd5b505af1158015610417573d6000803e3d6000fd5b5050604051631b67c43360e31b8152600093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063db3e2198915061046b908590600401610fbd565b602060405180830381600087803b15801561048557600080fd5b505af1158015610499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104bd9190610dd4565b604051638632cb0360e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638632cb039061051090889088908890600401610fd5565b600060405180830381600087803b15801561052a57600080fd5b505af115801561053e573d6000803e3d6000fd5b50506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169150632e1a7d4d905061057d3484610ae0565b6040518263ffffffff1660e01b81526004016105999190610fcc565b600060405180830381600087803b1580156105b357600080fd5b505af11580156105c7573d6000803e3d6000fd5b506105d89250339150479050610b42565b50506001600055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600260005414156106a8576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000558315610777576040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90610701908890600401610fcc565b60206040518083038186803b15801561071957600080fd5b505afa15801561072d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107519190610cfb565b6001600160a01b0316146107775760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b03161480156107f157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b61080d5760405162461bcd60e51b81526004016100ff90610f18565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631bf7bf6c348888886040518563ffffffff1660e01b815260040161086193929190610fd5565b60408051808303818588803b15801561087957600080fd5b505af115801561088d573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906108b29190610dec565b60a0850181905260405163414bf38960e01b815291935091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063414bf3899061090d908790600401610fbd565b602060405180830381600087803b15801561092757600080fd5b505af115801561093b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095f9190610dd4565b60608501519091506001600160a01b0316301415610a0257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906109c3908490600401610fcc565b600060405180830381600087803b1580156109dd57600080fd5b505af11580156109f1573d6000803e3d6000fd5b50610a029250339150839050610b42565b86610a8a57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610a5790309033908890600401610ec7565b600060405180830381600087803b158015610a7157600080fd5b505af1158015610a85573d6000803e3d6000fd5b505050505b505060016000555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600082821115610b37576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b80471015610b97576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610be2576040519150601f19603f3d011682016040523d82523d6000602084013e610be7565b606091505b5050905080610c275760405162461bcd60e51b815260040180806020018281038252603a815260200180611028603a913960400191505060405180910390fd5b505050565b8035610c378161100f565b919050565b6000610100808385031215610c4f578182fd5b6040519081019067ffffffffffffffff82118183101715610c6c57fe5b81604052809250610c7c84610c2c565b8152610c8a60208501610c2c565b6020820152610c9b60408501610ce8565b6040820152610cac60608501610c2c565b60608201526080840135608082015260a084013560a082015260c084013560c0820152610cdb60e08501610c2c565b60e0820152505092915050565b803562ffffff81168114610c3757600080fd5b600060208284031215610d0c578081fd5b8151610d178161100f565b9392505050565b60008060008060808587031215610d33578283fd5b8435610d3e8161100f565b9350602085810135610d4f8161100f565b935060408601359250606086013567ffffffffffffffff80821115610d72578384fd5b818801915088601f830112610d85578384fd5b813581811115610d9157fe5b610da3601f8201601f19168501610feb565b91508082528984828501011115610db8578485fd5b8084840185840137810190920192909252939692955090935050565b600060208284031215610de5578081fd5b5051919050565b60008060408385031215610dfe578182fd5b505080516020909101519092909150565b6000806000806101608587031215610e25578384fd5b843593506020850135925060408501359150610e448660608701610c3c565b905092959194509250565b6001600160a01b0380825116835280602083015116602084015262ffffff60408301511660408401528060608301511660608401526080820151608084015260a082015160a084015260c082015160c08401528060e08301511660e0840152505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b60208082526011908201527f57726f6e67207377617020746f6b656e73000000000000000000000000000000604082015260600190565b6020808252600b908201527f4e6f7420616c6c6f776564000000000000000000000000000000000000000000604082015260600190565b60208082526011908201527f63616e2774207265636569766520657468000000000000000000000000000000604082015260600190565b6101008101610b3c8284610e4f565b90815260200190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561100757fe5b604052919050565b6001600160a01b038116811461102457600080fd5b5056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a2646970667358221220dca83f927accd8f5dd17b8c7ca8e2147659fcc484c1799c390e51729507a6b9f64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"params\": {\n          \"_vaultId\": \"short wPowerPerp vault id\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to burn\",\n          \"_withdrawAmount\": \"amount to withdraw\"\n        }\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_controllerAddr\": \"controller address for wPowerPerp\",\n          \"_swapRouter\": \"uniswap v3 swap router address\",\n          \"_wethAddr\": \"weth address\"\n        }\n      },\n      \"onERC721Received(address,address,uint256,bytes)\": {\n        \"details\": \"accept erc721 from safeTransferFrom and safeMint after callback\",\n        \"returns\": {\n          \"_0\": \"returns received selector\"\n        }\n      },\n      \"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"params\": {\n          \"_powerPerpAmount\": \"amount of powerPerp to mint/sell\",\n          \"_uniNftId\": \"uniswap v3 position token id\",\n          \"_vaultId\": \"short wPowerPerp vault id\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"notice\": \"buy back wPowerPerp with eth on uniswap v3 and close position\"\n      },\n      \"constructor\": {\n        \"notice\": \"constructor for short helper\"\n      },\n      \"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"notice\": \"mint power perp, trade with uniswap v3 and send back premium in eth\"\n      }\n    },\n    \"notice\": \"contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 3698,\n        \"contract\": \"contracts/periphery/ShortHelper.sol:ShortHelper\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_uint256\"\n      }\n    ],\n    \"types\": {\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/ShortPowerPerp.json",
    "content": "{\n  \"address\": \"0xa653e22A963ff0026292Cc8B67941c0ba7863a38\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_name\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_symbol\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"approved\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"approved\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"ApprovalForAll\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"baseURI\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"controller\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getApproved\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controller\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"init\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"isApprovedForAll\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_recipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"mintNFT\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"nextId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ownerOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"safeTransferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"safeTransferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"approved\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"setApprovalForAll\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"interfaceId\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"name\": \"supportsInterface\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"index\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenByIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"index\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenOfOwnerByIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenURI\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0xb9d2a269993923dc908e89e1a02d9bc242df96a80503be150f5f31b186ab97d0\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xa3cB04d8BD927EEC8826BD77b7C71abE3d29c081\",\n    \"contractAddress\": \"0xa653e22A963ff0026292Cc8B67941c0ba7863a38\",\n    \"transactionIndex\": 23,\n    \"gasUsed\": \"1944232\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0xfb57ebbb216a9727f9003920d25985329d8f0ad0220a1d364294130d613df597\",\n    \"transactionHash\": \"0xb9d2a269993923dc908e89e1a02d9bc242df96a80503be150f5f31b186ab97d0\",\n    \"logs\": [],\n    \"blockNumber\": 13982499,\n    \"cumulativeGasUsed\": \"4596806\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"short Squeeth\",\n    \"sSQU\"\n  ],\n  \"solcInputHash\": \"d97d3d4b09e0d70518330d405a7dd9ff\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_name\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_symbol\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"ApprovalForAll\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"baseURI\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"getApproved\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controller\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"init\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"isApprovedForAll\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_recipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"mintNFT\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"nextId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ownerOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"safeTransferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"safeTransferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"setApprovalForAll\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"interfaceId\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"name\\\":\\\"supportsInterface\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"index\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenByIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"index\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenOfOwnerByIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenURI\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-approve}.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC721-balanceOf}.\\\"},\\\"baseURI()\\\":{\\\"details\\\":\\\"Returns the base URI set via {_setBaseURI}. This will be automatically added as a prefix in {tokenURI} to each token's URI, or to the token ID if no specific URI is set for that token ID.\\\"},\\\"constructor\\\":{\\\"params\\\":{\\\"_name\\\":\\\"token name for ERC721\\\",\\\"_symbol\\\":\\\"token symbol for ERC721\\\"}},\\\"getApproved(uint256)\\\":{\\\"details\\\":\\\"See {IERC721-getApproved}.\\\"},\\\"init(address)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\"}},\\\"isApprovedForAll(address,address)\\\":{\\\"details\\\":\\\"See {IERC721-isApprovedForAll}.\\\"},\\\"mintNFT(address)\\\":{\\\"details\\\":\\\"autoincrement tokenId starts at 1\\\",\\\"params\\\":{\\\"_recipient\\\":\\\"recipient address for NFT\\\"}},\\\"name()\\\":{\\\"details\\\":\\\"See {IERC721Metadata-name}.\\\"},\\\"ownerOf(uint256)\\\":{\\\"details\\\":\\\"See {IERC721-ownerOf}.\\\"},\\\"safeTransferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-safeTransferFrom}.\\\"},\\\"safeTransferFrom(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"See {IERC721-safeTransferFrom}.\\\"},\\\"setApprovalForAll(address,bool)\\\":{\\\"details\\\":\\\"See {IERC721-setApprovalForAll}.\\\"},\\\"supportsInterface(bytes4)\\\":{\\\"details\\\":\\\"See {IERC165-supportsInterface}. Time complexity O(1), guaranteed to always use less than 30 000 gas.\\\"},\\\"symbol()\\\":{\\\"details\\\":\\\"See {IERC721Metadata-symbol}.\\\"},\\\"tokenByIndex(uint256)\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-tokenByIndex}.\\\"},\\\"tokenOfOwnerByIndex(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-tokenOfOwnerByIndex}.\\\"},\\\"tokenURI(uint256)\\\":{\\\"details\\\":\\\"See {IERC721Metadata-tokenURI}.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-totalSupply}.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-transferFrom}.\\\"}},\\\"stateVariables\\\":{\\\"nextId\\\":{\\\"details\\\":\\\"tokenId for the next vault opened\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"constructor\\\":{\\\"notice\\\":\\\"short power perpetual constructor\\\"},\\\"init(address)\\\":{\\\"notice\\\":\\\"initialize short contract\\\"},\\\"mintNFT(address)\\\":{\\\"notice\\\":\\\"mint new NFT\\\"}},\\\"notice\\\":\\\"ERC721 NFT representing ownership of a vault (short position)\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/ShortPowerPerp.sol\\\":\\\"ShortPowerPerp\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/ERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Implementation of the {IERC165} interface.\\\\n *\\\\n * Contracts may inherit from this and call {_registerInterface} to declare\\\\n * their support of an interface.\\\\n */\\\\nabstract contract ERC165 is IERC165 {\\\\n    /*\\\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\\\n\\\\n    /**\\\\n     * @dev Mapping of interface ids to whether or not it's supported.\\\\n     */\\\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\\\n\\\\n    constructor () {\\\\n        // Derived contracts need only register support for their own interfaces,\\\\n        // we register support for ERC165 itself here\\\\n        _registerInterface(_INTERFACE_ID_ERC165);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC165-supportsInterface}.\\\\n     *\\\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\\\n        return _supportedInterfaces[interfaceId];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Registers the contract as an implementer of the interface defined by\\\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\\\n     * registering its interface id is not required.\\\\n     *\\\\n     * See {IERC165-supportsInterface}.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\\\n     */\\\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\\\n        require(interfaceId != 0xffffffff, \\\\\\\"ERC165: invalid interface id\\\\\\\");\\\\n        _supportedInterfaces[interfaceId] = true;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x234cdf2c3efd5f0dc17d32fe65d33c21674ca17de1e945eb60ac1076d7152d96\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// solhint-disable-next-line compiler-version\\\\npragma solidity >=0.4.24 <0.8.0;\\\\n\\\\nimport \\\\\\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\\\nabstract contract Initializable {\\\\n\\\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\\\n    function _isConstructor() private view returns (bool) {\\\\n        return !Address.isContract(address(this));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9abeffe138f098b16557187383ba0f9e8503602fa95cd668132986ee115237ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721Metadata.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721Enumerable.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721Receiver.sol\\\\\\\";\\\\nimport \\\\\\\"../../introspection/ERC165.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/Address.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/EnumerableSet.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/EnumerableMap.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/Strings.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\\\n    using SafeMath for uint256;\\\\n    using Address for address;\\\\n    using EnumerableSet for EnumerableSet.UintSet;\\\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\\\n    using Strings for uint256;\\\\n\\\\n    // Equals to `bytes4(keccak256(\\\\\\\"onERC721Received(address,address,uint256,bytes)\\\\\\\"))`\\\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\\\n\\\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\\\n\\\\n    // Enumerable mapping from token ids to their owners\\\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\\\n\\\\n    // Mapping from token ID to approved address\\\\n    mapping (uint256 => address) private _tokenApprovals;\\\\n\\\\n    // Mapping from owner to operator approvals\\\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\\\n\\\\n    // Token name\\\\n    string private _name;\\\\n\\\\n    // Token symbol\\\\n    string private _symbol;\\\\n\\\\n    // Optional mapping for token URIs\\\\n    mapping (uint256 => string) private _tokenURIs;\\\\n\\\\n    // Base URI\\\\n    string private _baseURI;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\\\n     *\\\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\\\n     *\\\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\\\n     *\\\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\\\n\\\\n    /**\\\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\\\n     */\\\\n    constructor (string memory name_, string memory symbol_) {\\\\n        _name = name_;\\\\n        _symbol = symbol_;\\\\n\\\\n        // register the supported interfaces to conform to ERC721 via ERC165\\\\n        _registerInterface(_INTERFACE_ID_ERC721);\\\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-balanceOf}.\\\\n     */\\\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\\\n        require(owner != address(0), \\\\\\\"ERC721: balance query for the zero address\\\\\\\");\\\\n        return _holderTokens[owner].length();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-ownerOf}.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\\\n        return _tokenOwners.get(tokenId, \\\\\\\"ERC721: owner query for nonexistent token\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-name}.\\\\n     */\\\\n    function name() public view virtual override returns (string memory) {\\\\n        return _name;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-symbol}.\\\\n     */\\\\n    function symbol() public view virtual override returns (string memory) {\\\\n        return _symbol;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-tokenURI}.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721Metadata: URI query for nonexistent token\\\\\\\");\\\\n\\\\n        string memory _tokenURI = _tokenURIs[tokenId];\\\\n        string memory base = baseURI();\\\\n\\\\n        // If there is no base URI, return the token URI.\\\\n        if (bytes(base).length == 0) {\\\\n            return _tokenURI;\\\\n        }\\\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\\\n        if (bytes(_tokenURI).length > 0) {\\\\n            return string(abi.encodePacked(base, _tokenURI));\\\\n        }\\\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\\\n        return string(abi.encodePacked(base, tokenId.toString()));\\\\n    }\\\\n\\\\n    /**\\\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\\\n    * to the token ID if no specific URI is set for that token ID.\\\\n    */\\\\n    function baseURI() public view virtual returns (string memory) {\\\\n        return _baseURI;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\\\n        return _holderTokens[owner].at(index);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-totalSupply}.\\\\n     */\\\\n    function totalSupply() public view virtual override returns (uint256) {\\\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\\\n        return _tokenOwners.length();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\\\n     */\\\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\\\n        return tokenId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-approve}.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) public virtual override {\\\\n        address owner = ERC721.ownerOf(tokenId);\\\\n        require(to != owner, \\\\\\\"ERC721: approval to current owner\\\\\\\");\\\\n\\\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\\\n            \\\\\\\"ERC721: approve caller is not owner nor approved for all\\\\\\\"\\\\n        );\\\\n\\\\n        _approve(to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-getApproved}.\\\\n     */\\\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721: approved query for nonexistent token\\\\\\\");\\\\n\\\\n        return _tokenApprovals[tokenId];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-setApprovalForAll}.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\\\n        require(operator != _msgSender(), \\\\\\\"ERC721: approve to caller\\\\\\\");\\\\n\\\\n        _operatorApprovals[_msgSender()][operator] = approved;\\\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-isApprovedForAll}.\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\\\n        return _operatorApprovals[owner][operator];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-transferFrom}.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\\\n        //solhint-disable-next-line max-line-length\\\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\\\\\"ERC721: transfer caller is not owner nor approved\\\\\\\");\\\\n\\\\n        _transfer(from, to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-safeTransferFrom}.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\\\n        safeTransferFrom(from, to, tokenId, \\\\\\\"\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-safeTransferFrom}.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\\\\\"ERC721: transfer caller is not owner nor approved\\\\\\\");\\\\n        _safeTransfer(from, to, tokenId, _data);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\\\n     *\\\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\\\n        _transfer(from, to, tokenId);\\\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns whether `tokenId` exists.\\\\n     *\\\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Tokens start existing when they are minted (`_mint`),\\\\n     * and stop existing when they are burned (`_burn`).\\\\n     */\\\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\\\n        return _tokenOwners.contains(tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721: operator query for nonexistent token\\\\\\\");\\\\n        address owner = ERC721.ownerOf(tokenId);\\\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\\\n     *\\\\n     * Requirements:\\\\n     d*\\\\n     * - `tokenId` must not exist.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\\\n        _safeMint(to, tokenId, \\\\\\\"\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\\\n     */\\\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\\\n        _mint(to, tokenId);\\\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Mints `tokenId` and transfers it to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must not exist.\\\\n     * - `to` cannot be the zero address.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _mint(address to, uint256 tokenId) internal virtual {\\\\n        require(to != address(0), \\\\\\\"ERC721: mint to the zero address\\\\\\\");\\\\n        require(!_exists(tokenId), \\\\\\\"ERC721: token already minted\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(address(0), to, tokenId);\\\\n\\\\n        _holderTokens[to].add(tokenId);\\\\n\\\\n        _tokenOwners.set(tokenId, to);\\\\n\\\\n        emit Transfer(address(0), to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Destroys `tokenId`.\\\\n     * The approval is cleared when the token is burned.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _burn(uint256 tokenId) internal virtual {\\\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\\\n\\\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\\\n\\\\n        // Clear approvals\\\\n        _approve(address(0), tokenId);\\\\n\\\\n        // Clear metadata (if any)\\\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\\\n            delete _tokenURIs[tokenId];\\\\n        }\\\\n\\\\n        _holderTokens[owner].remove(tokenId);\\\\n\\\\n        _tokenOwners.remove(tokenId);\\\\n\\\\n        emit Transfer(owner, address(0), tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` from `from` to `to`.\\\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\\\n        require(ERC721.ownerOf(tokenId) == from, \\\\\\\"ERC721: transfer of token that is not own\\\\\\\"); // internal owner\\\\n        require(to != address(0), \\\\\\\"ERC721: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(from, to, tokenId);\\\\n\\\\n        // Clear approvals from the previous owner\\\\n        _approve(address(0), tokenId);\\\\n\\\\n        _holderTokens[from].remove(tokenId);\\\\n        _holderTokens[to].add(tokenId);\\\\n\\\\n        _tokenOwners.set(tokenId, to);\\\\n\\\\n        emit Transfer(from, to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721Metadata: URI set of nonexistent token\\\\\\\");\\\\n        _tokenURIs[tokenId] = _tokenURI;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Internal function to set the base URI for all token IDs. It is\\\\n     * automatically added as a prefix to the value returned in {tokenURI},\\\\n     * or to the token ID if {tokenURI} is empty.\\\\n     */\\\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\\\n        _baseURI = baseURI_;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\\\n     * The call is not executed if the target address is not a contract.\\\\n     *\\\\n     * @param from address representing the previous owner of the given token ID\\\\n     * @param to target address that will receive the tokens\\\\n     * @param tokenId uint256 ID of the token to be transferred\\\\n     * @param _data bytes optional data to send along with the call\\\\n     * @return bool whether the call correctly returned the expected magic value\\\\n     */\\\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\\\n        private returns (bool)\\\\n    {\\\\n        if (!to.isContract()) {\\\\n            return true;\\\\n        }\\\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\\\n            IERC721Receiver(to).onERC721Received.selector,\\\\n            _msgSender(),\\\\n            from,\\\\n            tokenId,\\\\n            _data\\\\n        ), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\\\n        return (retval == _ERC721_RECEIVED);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Approve `to` to operate on `tokenId`\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function _approve(address to, uint256 tokenId) internal virtual {\\\\n        _tokenApprovals[tokenId] = to;\\\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Hook that is called before any token transfer. This includes minting\\\\n     * and burning.\\\\n     *\\\\n     * Calling conditions:\\\\n     *\\\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\\\n     * transferred to `to`.\\\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     *\\\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\\\n     */\\\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x93e4f65a89c3c888afbaa3ee18c3fa4f51c422419bbcd9cca47676a0f8e507ea\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/EnumerableMap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Library for managing an enumerable variant of Solidity's\\\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\\\n * type.\\\\n *\\\\n * Maps have the following properties:\\\\n *\\\\n * - Entries are added, removed, and checked for existence in constant time\\\\n * (O(1)).\\\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\\\n *\\\\n * ```\\\\n * contract Example {\\\\n *     // Add the library methods\\\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\\\n *\\\\n *     // Declare a set state variable\\\\n *     EnumerableMap.UintToAddressMap private myMap;\\\\n * }\\\\n * ```\\\\n *\\\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\\\n * supported.\\\\n */\\\\nlibrary EnumerableMap {\\\\n    // To implement this library for multiple types with as little code\\\\n    // repetition as possible, we write it in terms of a generic Map type with\\\\n    // bytes32 keys and values.\\\\n    // The Map implementation uses private functions, and user-facing\\\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\\\n    // the underlying Map.\\\\n    // This means that we can only create new EnumerableMaps for types that fit\\\\n    // in bytes32.\\\\n\\\\n    struct MapEntry {\\\\n        bytes32 _key;\\\\n        bytes32 _value;\\\\n    }\\\\n\\\\n    struct Map {\\\\n        // Storage of map keys and values\\\\n        MapEntry[] _entries;\\\\n\\\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\\\n        // because index 0 means a key is not in the map.\\\\n        mapping (bytes32 => uint256) _indexes;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\\\n     * key. O(1).\\\\n     *\\\\n     * Returns true if the key was added to the map, that is if it was not\\\\n     * already present.\\\\n     */\\\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\\\n        uint256 keyIndex = map._indexes[key];\\\\n\\\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\\\n            // The entry is stored at length-1, but we add 1 to all indexes\\\\n            // and use 0 as a sentinel value\\\\n            map._indexes[key] = map._entries.length;\\\\n            return true;\\\\n        } else {\\\\n            map._entries[keyIndex - 1]._value = value;\\\\n            return false;\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Removes a key-value pair from a map. O(1).\\\\n     *\\\\n     * Returns true if the key was removed from the map, that is if it was present.\\\\n     */\\\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\\\n        uint256 keyIndex = map._indexes[key];\\\\n\\\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\\\n            // This modifies the order of the array, as noted in {at}.\\\\n\\\\n            uint256 toDeleteIndex = keyIndex - 1;\\\\n            uint256 lastIndex = map._entries.length - 1;\\\\n\\\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\\\n\\\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\\\n\\\\n            // Move the last entry to the index where the entry to delete is\\\\n            map._entries[toDeleteIndex] = lastEntry;\\\\n            // Update the index for the moved entry\\\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\\\n\\\\n            // Delete the slot where the moved entry was stored\\\\n            map._entries.pop();\\\\n\\\\n            // Delete the index for the deleted slot\\\\n            delete map._indexes[key];\\\\n\\\\n            return true;\\\\n        } else {\\\\n            return false;\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns true if the key is in the map. O(1).\\\\n     */\\\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\\\n        return map._indexes[key] != 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\\\n     */\\\\n    function _length(Map storage map) private view returns (uint256) {\\\\n        return map._entries.length;\\\\n    }\\\\n\\\\n   /**\\\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\\\n    *\\\\n    * Note that there are no guarantees on the ordering of entries inside the\\\\n    * array, and it may change when more entries are added or removed.\\\\n    *\\\\n    * Requirements:\\\\n    *\\\\n    * - `index` must be strictly less than {length}.\\\\n    */\\\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\\\n        require(map._entries.length > index, \\\\\\\"EnumerableMap: index out of bounds\\\\\\\");\\\\n\\\\n        MapEntry storage entry = map._entries[index];\\\\n        return (entry._key, entry._value);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\\\n     * Does not revert if `key` is not in the map.\\\\n     */\\\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the value associated with `key`.  O(1).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `key` must be in the map.\\\\n     */\\\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        require(keyIndex != 0, \\\\\\\"EnumerableMap: nonexistent key\\\\\\\"); // Equivalent to contains(map, key)\\\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\\\n     */\\\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\\\n    }\\\\n\\\\n    // UintToAddressMap\\\\n\\\\n    struct UintToAddressMap {\\\\n        Map _inner;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\\\n     * key. O(1).\\\\n     *\\\\n     * Returns true if the key was added to the map, that is if it was not\\\\n     * already present.\\\\n     */\\\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Removes a value from a set. O(1).\\\\n     *\\\\n     * Returns true if the key was removed from the map, that is if it was present.\\\\n     */\\\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\\\n        return _remove(map._inner, bytes32(key));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns true if the key is in the map. O(1).\\\\n     */\\\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\\\n        return _contains(map._inner, bytes32(key));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the number of elements in the map. O(1).\\\\n     */\\\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\\\n        return _length(map._inner);\\\\n    }\\\\n\\\\n   /**\\\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\\\n        return (uint256(key), address(uint160(uint256(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\\\n     * Does not revert if `key` is not in the map.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\\\n        return (success, address(uint160(uint256(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the value associated with `key`.  O(1).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `key` must be in the map.\\\\n     */\\\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\\\n     */\\\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2114555153edb5f273008b3d34205f511db9af06b88f752e4c280dd612c4c549\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.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\\\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\\\n\\\\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] = toDeleteIndex + 1; // All indexes are 1-based\\\\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        require(set._values.length > index, \\\\\\\"EnumerableSet: index out of bounds\\\\\\\");\\\\n        return set._values[index];\\\\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    // 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    // 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\\\",\\\"keccak256\\\":\\\"0x9a2c1eebb65250f0e11882237038600f22a62376f0547db4acc0dfe0a3d8d34f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Strings.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev String operations.\\\\n */\\\\nlibrary Strings {\\\\n    /**\\\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\\\n        temp = value;\\\\n        while (temp != 0) {\\\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\\\n            temp /= 10;\\\\n        }\\\\n        return string(buffer);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x08e38e034333372aea8cb1b8846085b7fbab42c6b77a0af464d2c6827827c4f0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/core/ShortPowerPerp.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//contract\\\\nimport {ERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\\\\\";\\\\nimport {Initializable} from \\\\\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\\\n */\\\\ncontract ShortPowerPerp is ERC721, Initializable {\\\\n    /// @dev tokenId for the next vault opened\\\\n    uint256 public nextId = 1;\\\\n\\\\n    address public controller;\\\\n    address private immutable deployer;\\\\n\\\\n    modifier onlyController() {\\\\n        require(msg.sender == controller, \\\\\\\"Not controller\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice short power perpetual constructor\\\\n     * @param _name token name for ERC721\\\\n     * @param _symbol token symbol for ERC721\\\\n     */\\\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\\\n        deployer = msg.sender;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice initialize short contract\\\\n     * @param _controller controller address\\\\n     */\\\\n    function init(address _controller) public initializer {\\\\n        require(msg.sender == deployer, \\\\\\\"Invalid caller of init\\\\\\\");\\\\n        require(_controller != address(0), \\\\\\\"Invalid controller address\\\\\\\");\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint new NFT\\\\n     * @dev autoincrement tokenId starts at 1\\\\n     * @param _recipient recipient address for NFT\\\\n     */\\\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\\\n        // mint NFT\\\\n        _safeMint(_recipient, (tokenId = nextId++));\\\\n    }\\\\n\\\\n    function _beforeTokenTransfer(\\\\n        address, /* from */\\\\n        address, /* to */\\\\n        uint256 tokenId\\\\n    ) internal override {\\\\n        IController(controller).updateOperator(tokenId, address(0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5597686c00b4341803c9119e8402e9207b0d13ca722e724fa9d2c85e8ea6dbf5\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnOnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc5d6230c8bafcaf2ae7260efd68c45ab13e91819ed9e11881b29dc48386e4bc7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x939175a827c8e9d8d09ee55957e8127a6a55bf42d6a0b3e48b0b59c895aa85af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60a06040526001600b553480156200001657600080fd5b506040516200229c3803806200229c833981810160405260408110156200003c57600080fd5b81019080805160405193929190846401000000008211156200005d57600080fd5b9083019060208201858111156200007357600080fd5b82516401000000008111828201881017156200008e57600080fd5b82525081516020918201929091019080838360005b83811015620000bd578181015183820152602001620000a3565b50505050905090810190601f168015620000eb5780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200010f57600080fd5b9083019060208201858111156200012557600080fd5b82516401000000008111828201881017156200014057600080fd5b82525081516020918201929091019080838360005b838110156200016f57818101518382015260200162000155565b50505050905090810190601f1680156200019d5780820380516001836020036101000a031916815260200191505b5060405250839150829050620001ba6301ffc9a760e01b6200022d565b8151620001cf906006906020850190620002b2565b508051620001e5906007906020840190620002b2565b50620001f86380ac58cd60e01b6200022d565b6200020a635b5e139f60e01b6200022d565b6200021c63780e9d6360e01b6200022d565b5050503360601b608052506200035e565b6001600160e01b031980821614156200028d576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152602081905260409020805460ff19166001179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620002ea576000855562000335565b82601f106200030557805160ff191683800117855562000335565b8280016001018555821562000335579182015b828111156200033557825182559160200191906001019062000318565b506200034392915062000347565b5090565b5b8082111562000343576000815560010162000348565b60805160601c611f206200037c600039806107f75250611f206000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806354ba0f27116100d857806395d89b411161008c578063c87b56dd11610066578063c87b56dd14610505578063e985e9c514610522578063f77c47911461055057610177565b806395d89b4114610409578063a22cb46514610411578063b88d4fde1461043f57610177565b80636352211e116100bd5780636352211e146103be5780636c0360eb146103db57806370a08231146103e357610177565b806354ba0f271461039057806361b8ce8c146103b657610177565b806319ab453c1161012f5780632f745c59116101145780632f745c591461031157806342842e0e1461033d5780634f6ccce71461037357610177565b806319ab453c146102b557806323b872dd146102db57610177565b8063081812fc11610160578063081812fc14610234578063095ea7b31461026d57806318160ddd1461029b57610177565b806301ffc9a71461017c57806306fdde03146101b7575b600080fd5b6101a36004803603602081101561019257600080fd5b50356001600160e01b031916610558565b604080519115158252519081900360200190f35b6101bf61057b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f95781810151838201526020016101e1565b50505050905090810190601f1680156102265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102516004803603602081101561024a57600080fd5b5035610611565b604080516001600160a01b039092168252519081900360200190f35b6102996004803603604081101561028357600080fd5b506001600160a01b038135169060200135610673565b005b6102a361074e565b60408051918252519081900360200190f35b610299600480360360208110156102cb57600080fd5b50356001600160a01b031661075f565b610299600480360360608110156102f157600080fd5b506001600160a01b03813581169160208101359091169060400135610902565b6102a36004803603604081101561032757600080fd5b506001600160a01b038135169060200135610959565b6102996004803603606081101561035357600080fd5b506001600160a01b03813581169160208101359091169060400135610984565b6102a36004803603602081101561038957600080fd5b503561099f565b6102a3600480360360208110156103a657600080fd5b50356001600160a01b03166109b5565b6102a3610a2d565b610251600480360360208110156103d457600080fd5b5035610a33565b6101bf610a5b565b6102a3600480360360208110156103f957600080fd5b50356001600160a01b0316610abc565b6101bf610b24565b6102996004803603604081101561042757600080fd5b506001600160a01b0381351690602001351515610b85565b6102996004803603608081101561045557600080fd5b6001600160a01b0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561049057600080fd5b8201836020820111156104a257600080fd5b803590602001918460018302840111640100000000831117156104c457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610c8a945050505050565b6101bf6004803603602081101561051b57600080fd5b5035610ce8565b6101a36004803603604081101561053857600080fd5b506001600160a01b0381358116916020013516610f69565b610251610f97565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b820191906000526020600020905b8154815290600101906020018083116105ea57829003601f168201915b5050505050905090565b600061061c82610fa6565b6106575760405162461bcd60e51b815260040180806020018281038252602c815260200180611e15602c913960400191505060405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061067e82610a33565b9050806001600160a01b0316836001600160a01b031614156106d15760405162461bcd60e51b8152600401808060200182810382526021815260200180611e996021913960400191505060405180910390fd5b806001600160a01b03166106e3610fb3565b6001600160a01b031614806107045750610704816106ff610fb3565b610f69565b61073f5760405162461bcd60e51b8152600401808060200182810382526038815260200180611d3a6038913960400191505060405180910390fd5b6107498383610fb7565b505050565b600061075a6002611032565b905090565b600a54610100900460ff1680610778575061077861103d565b806107865750600a5460ff16155b6107c15760405162461bcd60e51b815260040180806020018281038252602e815260200180611dc5602e913960400191505060405180910390fd5b600a54610100900460ff161580156107ec57600a805460ff1961ff0019909116610100171660011790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610869576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166108c4576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600c805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905580156108fe57600a805461ff00191690555b5050565b61091361090d610fb3565b8261104e565b61094e5760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b6107498383836110f2565b6001600160a01b038216600090815260016020526040812061097b908361123e565b90505b92915050565b61074983838360405180602001604052806000815250610c8a565b6000806109ad60028461124a565b509392505050565b600c546000906001600160a01b03163314610a17576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b50600b8054600181019091556105768282611266565b600b5481565b600061097e82604051806060016040528060298152602001611d9c6029913960029190611280565b60098054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b60006001600160a01b038216610b035760405162461bcd60e51b815260040180806020018281038252602a815260200180611d72602a913960400191505060405180910390fd5b6001600160a01b038216600090815260016020526040902061097e90611032565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b610b8d610fb3565b6001600160a01b0316826001600160a01b03161415610bf3576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060056000610c00610fb3565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155610c44610fb3565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b610c9b610c95610fb3565b8361104e565b610cd65760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b610ce284848484611297565b50505050565b6060610cf382610fa6565b610d2e5760405162461bcd60e51b815260040180806020018281038252602f815260200180611e6a602f913960400191505060405180910390fd5b60008281526008602090815260408083208054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015610dc15780601f10610d9657610100808354040283529160200191610dc1565b820191906000526020600020905b815481529060010190602001808311610da457829003601f168201915b505050505090506000610dd2610a5b565b9050805160001415610de657509050610576565b815115610ea75780826040516020018083805190602001908083835b60208310610e215780518252601f199092019160209182019101610e02565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610e695780518252601f199092019160209182019101610e4a565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050610576565b80610eb1856112e9565b6040516020018083805190602001908083835b60208310610ee35780518252601f199092019160209182019101610ec4565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610f2b5780518252601f199092019160209182019101610f0c565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050919050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b600c546001600160a01b031681565b600061097e6002836113dc565b3390565b6000818152600460205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091558190610ff982610a33565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061097e826113e8565b6000611048306113ec565b15905090565b600061105982610fa6565b6110945760405162461bcd60e51b815260040180806020018281038252602c815260200180611d0e602c913960400191505060405180910390fd5b600061109f83610a33565b9050806001600160a01b0316846001600160a01b031614806110da5750836001600160a01b03166110cf84610611565b6001600160a01b0316145b806110ea57506110ea8185610f69565b949350505050565b826001600160a01b031661110582610a33565b6001600160a01b03161461114a5760405162461bcd60e51b8152600401808060200182810382526029815260200180611e416029913960400191505060405180910390fd5b6001600160a01b03821661118f5760405162461bcd60e51b8152600401808060200182810382526024815260200180611cea6024913960400191505060405180910390fd5b61119a8383836113f2565b6111a5600082610fb7565b6001600160a01b03831660009081526001602052604090206111c79082611462565b506001600160a01b03821660009081526001602052604090206111ea908261146e565b506111f76002828461147a565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061097b8383611490565b600080808061125986866114f4565b9097909650945050505050565b6108fe82826040518060200160405280600081525061156f565b600061128d8484846115c1565b90505b9392505050565b6112a28484846110f2565b6112ae8484848461168b565b610ce25760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b60608161130e57506040805180820190915260018152600360fc1b6020820152610576565b8160005b811561132657600101600a82049150611312565b60008167ffffffffffffffff8111801561133f57600080fd5b506040519080825280601f01601f19166020018201604052801561136a576020820181803683370190505b50859350905060001982015b83156113d357600a840660300160f81b8282806001900393508151811061139957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84049350611376565b50949350505050565b600061097b838361181d565b5490565b3b151590565b600c546040805163c65a391d60e01b81526004810184905260006024820181905291516001600160a01b039093169263c65a391d9260448084019391929182900301818387803b15801561144557600080fd5b505af1158015611459573d6000803e3d6000fd5b50505050505050565b600061097b8383611835565b600061097b83836118fb565b600061128d84846001600160a01b038516611945565b815460009082106114d25760405162461bcd60e51b8152600401808060200182810382526022815260200180611c966022913960400191505060405180910390fd5b8260000182815481106114e157fe5b9060005260206000200154905092915050565b8154600090819083106115385760405162461bcd60e51b8152600401808060200182810382526022815260200180611df36022913960400191505060405180910390fd5b600084600001848154811061154957fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b61157983836119dc565b611586600084848461168b565b6107495760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b6000828152600184016020526040812054828161165c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611621578181015183820152602001611609565b50505050905090810190601f16801561164e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5084600001600182038154811061166f57fe5b9060005260206000209060020201600101549150509392505050565b600061169f846001600160a01b03166113ec565b6116ab575060016110ea565b60006117e3630a85bd0160e11b6116c0610fb3565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561172757818101518382015260200161170f565b50505050905090810190601f1680156117545780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001611cb8603291396001600160a01b0388169190611b0a565b905060008180602001905160208110156117fc57600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b600081815260018301602052604081205480156118f1578354600019808301919081019060009087908390811061186857fe5b906000526020600020015490508087600001848154811061188557fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806118b557fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061097e565b600091505061097e565b6000611907838361181d565b61193d5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561097e565b50600061097e565b6000828152600184016020526040812054806119aa575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611290565b828560000160018303815481106119bd57fe5b9060005260206000209060020201600101819055506000915050611290565b6001600160a01b038216611a37576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b611a4081610fa6565b15611a92576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b611a9e600083836113f2565b6001600160a01b0382166000908152600160205260409020611ac0908261146e565b50611acd6002828461147a565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b606061128d848460008585611b1e856113ec565b611b6f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310611bad5780518252601f199092019160209182019101611b8e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611c0f576040519150601f19603f3d011682016040523d82523d6000602084013e611c14565b606091505b5091509150611c24828286611c2f565b979650505050505050565b60608315611c3e575081611290565b825115611c4e5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561162157818101518382015260200161160956fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a2646970667358221220d3f1a23837994f40417509b4bc6ecf5c3e0a993c2a5fa9467490d40d7655c57964736f6c63430007060033\",\n  \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101775760003560e01c806354ba0f27116100d857806395d89b411161008c578063c87b56dd11610066578063c87b56dd14610505578063e985e9c514610522578063f77c47911461055057610177565b806395d89b4114610409578063a22cb46514610411578063b88d4fde1461043f57610177565b80636352211e116100bd5780636352211e146103be5780636c0360eb146103db57806370a08231146103e357610177565b806354ba0f271461039057806361b8ce8c146103b657610177565b806319ab453c1161012f5780632f745c59116101145780632f745c591461031157806342842e0e1461033d5780634f6ccce71461037357610177565b806319ab453c146102b557806323b872dd146102db57610177565b8063081812fc11610160578063081812fc14610234578063095ea7b31461026d57806318160ddd1461029b57610177565b806301ffc9a71461017c57806306fdde03146101b7575b600080fd5b6101a36004803603602081101561019257600080fd5b50356001600160e01b031916610558565b604080519115158252519081900360200190f35b6101bf61057b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f95781810151838201526020016101e1565b50505050905090810190601f1680156102265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102516004803603602081101561024a57600080fd5b5035610611565b604080516001600160a01b039092168252519081900360200190f35b6102996004803603604081101561028357600080fd5b506001600160a01b038135169060200135610673565b005b6102a361074e565b60408051918252519081900360200190f35b610299600480360360208110156102cb57600080fd5b50356001600160a01b031661075f565b610299600480360360608110156102f157600080fd5b506001600160a01b03813581169160208101359091169060400135610902565b6102a36004803603604081101561032757600080fd5b506001600160a01b038135169060200135610959565b6102996004803603606081101561035357600080fd5b506001600160a01b03813581169160208101359091169060400135610984565b6102a36004803603602081101561038957600080fd5b503561099f565b6102a3600480360360208110156103a657600080fd5b50356001600160a01b03166109b5565b6102a3610a2d565b610251600480360360208110156103d457600080fd5b5035610a33565b6101bf610a5b565b6102a3600480360360208110156103f957600080fd5b50356001600160a01b0316610abc565b6101bf610b24565b6102996004803603604081101561042757600080fd5b506001600160a01b0381351690602001351515610b85565b6102996004803603608081101561045557600080fd5b6001600160a01b0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561049057600080fd5b8201836020820111156104a257600080fd5b803590602001918460018302840111640100000000831117156104c457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610c8a945050505050565b6101bf6004803603602081101561051b57600080fd5b5035610ce8565b6101a36004803603604081101561053857600080fd5b506001600160a01b0381358116916020013516610f69565b610251610f97565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b820191906000526020600020905b8154815290600101906020018083116105ea57829003601f168201915b5050505050905090565b600061061c82610fa6565b6106575760405162461bcd60e51b815260040180806020018281038252602c815260200180611e15602c913960400191505060405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061067e82610a33565b9050806001600160a01b0316836001600160a01b031614156106d15760405162461bcd60e51b8152600401808060200182810382526021815260200180611e996021913960400191505060405180910390fd5b806001600160a01b03166106e3610fb3565b6001600160a01b031614806107045750610704816106ff610fb3565b610f69565b61073f5760405162461bcd60e51b8152600401808060200182810382526038815260200180611d3a6038913960400191505060405180910390fd5b6107498383610fb7565b505050565b600061075a6002611032565b905090565b600a54610100900460ff1680610778575061077861103d565b806107865750600a5460ff16155b6107c15760405162461bcd60e51b815260040180806020018281038252602e815260200180611dc5602e913960400191505060405180910390fd5b600a54610100900460ff161580156107ec57600a805460ff1961ff0019909116610100171660011790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610869576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166108c4576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600c805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905580156108fe57600a805461ff00191690555b5050565b61091361090d610fb3565b8261104e565b61094e5760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b6107498383836110f2565b6001600160a01b038216600090815260016020526040812061097b908361123e565b90505b92915050565b61074983838360405180602001604052806000815250610c8a565b6000806109ad60028461124a565b509392505050565b600c546000906001600160a01b03163314610a17576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b50600b8054600181019091556105768282611266565b600b5481565b600061097e82604051806060016040528060298152602001611d9c6029913960029190611280565b60098054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b60006001600160a01b038216610b035760405162461bcd60e51b815260040180806020018281038252602a815260200180611d72602a913960400191505060405180910390fd5b6001600160a01b038216600090815260016020526040902061097e90611032565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b610b8d610fb3565b6001600160a01b0316826001600160a01b03161415610bf3576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060056000610c00610fb3565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155610c44610fb3565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b610c9b610c95610fb3565b8361104e565b610cd65760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b610ce284848484611297565b50505050565b6060610cf382610fa6565b610d2e5760405162461bcd60e51b815260040180806020018281038252602f815260200180611e6a602f913960400191505060405180910390fd5b60008281526008602090815260408083208054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015610dc15780601f10610d9657610100808354040283529160200191610dc1565b820191906000526020600020905b815481529060010190602001808311610da457829003601f168201915b505050505090506000610dd2610a5b565b9050805160001415610de657509050610576565b815115610ea75780826040516020018083805190602001908083835b60208310610e215780518252601f199092019160209182019101610e02565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610e695780518252601f199092019160209182019101610e4a565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050610576565b80610eb1856112e9565b6040516020018083805190602001908083835b60208310610ee35780518252601f199092019160209182019101610ec4565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610f2b5780518252601f199092019160209182019101610f0c565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050919050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b600c546001600160a01b031681565b600061097e6002836113dc565b3390565b6000818152600460205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091558190610ff982610a33565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061097e826113e8565b6000611048306113ec565b15905090565b600061105982610fa6565b6110945760405162461bcd60e51b815260040180806020018281038252602c815260200180611d0e602c913960400191505060405180910390fd5b600061109f83610a33565b9050806001600160a01b0316846001600160a01b031614806110da5750836001600160a01b03166110cf84610611565b6001600160a01b0316145b806110ea57506110ea8185610f69565b949350505050565b826001600160a01b031661110582610a33565b6001600160a01b03161461114a5760405162461bcd60e51b8152600401808060200182810382526029815260200180611e416029913960400191505060405180910390fd5b6001600160a01b03821661118f5760405162461bcd60e51b8152600401808060200182810382526024815260200180611cea6024913960400191505060405180910390fd5b61119a8383836113f2565b6111a5600082610fb7565b6001600160a01b03831660009081526001602052604090206111c79082611462565b506001600160a01b03821660009081526001602052604090206111ea908261146e565b506111f76002828461147a565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061097b8383611490565b600080808061125986866114f4565b9097909650945050505050565b6108fe82826040518060200160405280600081525061156f565b600061128d8484846115c1565b90505b9392505050565b6112a28484846110f2565b6112ae8484848461168b565b610ce25760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b60608161130e57506040805180820190915260018152600360fc1b6020820152610576565b8160005b811561132657600101600a82049150611312565b60008167ffffffffffffffff8111801561133f57600080fd5b506040519080825280601f01601f19166020018201604052801561136a576020820181803683370190505b50859350905060001982015b83156113d357600a840660300160f81b8282806001900393508151811061139957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84049350611376565b50949350505050565b600061097b838361181d565b5490565b3b151590565b600c546040805163c65a391d60e01b81526004810184905260006024820181905291516001600160a01b039093169263c65a391d9260448084019391929182900301818387803b15801561144557600080fd5b505af1158015611459573d6000803e3d6000fd5b50505050505050565b600061097b8383611835565b600061097b83836118fb565b600061128d84846001600160a01b038516611945565b815460009082106114d25760405162461bcd60e51b8152600401808060200182810382526022815260200180611c966022913960400191505060405180910390fd5b8260000182815481106114e157fe5b9060005260206000200154905092915050565b8154600090819083106115385760405162461bcd60e51b8152600401808060200182810382526022815260200180611df36022913960400191505060405180910390fd5b600084600001848154811061154957fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b61157983836119dc565b611586600084848461168b565b6107495760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b6000828152600184016020526040812054828161165c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611621578181015183820152602001611609565b50505050905090810190601f16801561164e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5084600001600182038154811061166f57fe5b9060005260206000209060020201600101549150509392505050565b600061169f846001600160a01b03166113ec565b6116ab575060016110ea565b60006117e3630a85bd0160e11b6116c0610fb3565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561172757818101518382015260200161170f565b50505050905090810190601f1680156117545780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001611cb8603291396001600160a01b0388169190611b0a565b905060008180602001905160208110156117fc57600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b600081815260018301602052604081205480156118f1578354600019808301919081019060009087908390811061186857fe5b906000526020600020015490508087600001848154811061188557fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806118b557fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061097e565b600091505061097e565b6000611907838361181d565b61193d5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561097e565b50600061097e565b6000828152600184016020526040812054806119aa575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611290565b828560000160018303815481106119bd57fe5b9060005260206000209060020201600101819055506000915050611290565b6001600160a01b038216611a37576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b611a4081610fa6565b15611a92576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b611a9e600083836113f2565b6001600160a01b0382166000908152600160205260409020611ac0908261146e565b50611acd6002828461147a565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b606061128d848460008585611b1e856113ec565b611b6f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310611bad5780518252601f199092019160209182019101611b8e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611c0f576040519150601f19603f3d011682016040523d82523d6000602084013e611c14565b606091505b5091509150611c24828286611c2f565b979650505050505050565b60608315611c3e575081611290565b825115611c4e5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561162157818101518382015260200161160956fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a2646970667358221220d3f1a23837994f40417509b4bc6ecf5c3e0a993c2a5fa9467490d40d7655c57964736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC721-approve}.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC721-balanceOf}.\"\n      },\n      \"baseURI()\": {\n        \"details\": \"Returns the base URI set via {_setBaseURI}. This will be automatically added as a prefix in {tokenURI} to each token's URI, or to the token ID if no specific URI is set for that token ID.\"\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_name\": \"token name for ERC721\",\n          \"_symbol\": \"token symbol for ERC721\"\n        }\n      },\n      \"getApproved(uint256)\": {\n        \"details\": \"See {IERC721-getApproved}.\"\n      },\n      \"init(address)\": {\n        \"params\": {\n          \"_controller\": \"controller address\"\n        }\n      },\n      \"isApprovedForAll(address,address)\": {\n        \"details\": \"See {IERC721-isApprovedForAll}.\"\n      },\n      \"mintNFT(address)\": {\n        \"details\": \"autoincrement tokenId starts at 1\",\n        \"params\": {\n          \"_recipient\": \"recipient address for NFT\"\n        }\n      },\n      \"name()\": {\n        \"details\": \"See {IERC721Metadata-name}.\"\n      },\n      \"ownerOf(uint256)\": {\n        \"details\": \"See {IERC721-ownerOf}.\"\n      },\n      \"safeTransferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC721-safeTransferFrom}.\"\n      },\n      \"safeTransferFrom(address,address,uint256,bytes)\": {\n        \"details\": \"See {IERC721-safeTransferFrom}.\"\n      },\n      \"setApprovalForAll(address,bool)\": {\n        \"details\": \"See {IERC721-setApprovalForAll}.\"\n      },\n      \"supportsInterface(bytes4)\": {\n        \"details\": \"See {IERC165-supportsInterface}. Time complexity O(1), guaranteed to always use less than 30 000 gas.\"\n      },\n      \"symbol()\": {\n        \"details\": \"See {IERC721Metadata-symbol}.\"\n      },\n      \"tokenByIndex(uint256)\": {\n        \"details\": \"See {IERC721Enumerable-tokenByIndex}.\"\n      },\n      \"tokenOfOwnerByIndex(address,uint256)\": {\n        \"details\": \"See {IERC721Enumerable-tokenOfOwnerByIndex}.\"\n      },\n      \"tokenURI(uint256)\": {\n        \"details\": \"See {IERC721Metadata-tokenURI}.\"\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC721Enumerable-totalSupply}.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC721-transferFrom}.\"\n      }\n    },\n    \"stateVariables\": {\n      \"nextId\": {\n        \"details\": \"tokenId for the next vault opened\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"constructor\": {\n        \"notice\": \"short power perpetual constructor\"\n      },\n      \"init(address)\": {\n        \"notice\": \"initialize short contract\"\n      },\n      \"mintNFT(address)\": {\n        \"notice\": \"mint new NFT\"\n      }\n    },\n    \"notice\": \"ERC721 NFT representing ownership of a vault (short position)\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 123,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_supportedInterfaces\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_bytes4,t_bool)\"\n      },\n      {\n        \"astId\": 1226,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_holderTokens\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_struct(UintSet)3592_storage)\"\n      },\n      {\n        \"astId\": 1228,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_tokenOwners\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_struct(UintToAddressMap)2969_storage\"\n      },\n      {\n        \"astId\": 1232,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_tokenApprovals\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_mapping(t_uint256,t_address)\"\n      },\n      {\n        \"astId\": 1238,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_operatorApprovals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_bool))\"\n      },\n      {\n        \"astId\": 1240,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 1242,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"7\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 1246,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_tokenURIs\",\n        \"offset\": 0,\n        \"slot\": \"8\",\n        \"type\": \"t_mapping(t_uint256,t_string_storage)\"\n      },\n      {\n        \"astId\": 1248,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_baseURI\",\n        \"offset\": 0,\n        \"slot\": \"9\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 540,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_initialized\",\n        \"offset\": 0,\n        \"slot\": \"10\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 543,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_initializing\",\n        \"offset\": 1,\n        \"slot\": \"10\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 10465,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"nextId\",\n        \"offset\": 0,\n        \"slot\": \"11\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 10467,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"controller\",\n        \"offset\": 0,\n        \"slot\": \"12\",\n        \"type\": \"t_address\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_array(t_bytes32)dyn_storage\": {\n        \"base\": \"t_bytes32\",\n        \"encoding\": \"dynamic_array\",\n        \"label\": \"bytes32[]\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_array(t_struct(MapEntry)2643_storage)dyn_storage\": {\n        \"base\": \"t_struct(MapEntry)2643_storage\",\n        \"encoding\": \"dynamic_array\",\n        \"label\": \"struct EnumerableMap.MapEntry[]\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_bytes32\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bytes32\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_bytes4\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bytes4\",\n        \"numberOfBytes\": \"4\"\n      },\n      \"t_mapping(t_address,t_bool)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => bool)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_bool\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_bool))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => bool))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_bool)\"\n      },\n      \"t_mapping(t_address,t_struct(UintSet)3592_storage)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => struct EnumerableSet.UintSet)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_struct(UintSet)3592_storage\"\n      },\n      \"t_mapping(t_bytes32,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_bytes32\",\n        \"label\": \"mapping(bytes32 => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_mapping(t_bytes4,t_bool)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_bytes4\",\n        \"label\": \"mapping(bytes4 => bool)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_bool\"\n      },\n      \"t_mapping(t_uint256,t_address)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => address)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_address\"\n      },\n      \"t_mapping(t_uint256,t_string_storage)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => string)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_string_storage\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_struct(Map)2651_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableMap.Map\",\n        \"members\": [\n          {\n            \"astId\": 2646,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_entries\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_array(t_struct(MapEntry)2643_storage)dyn_storage\"\n          },\n          {\n            \"astId\": 2650,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_indexes\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_mapping(t_bytes32,t_uint256)\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(MapEntry)2643_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableMap.MapEntry\",\n        \"members\": [\n          {\n            \"astId\": 2640,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_key\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_bytes32\"\n          },\n          {\n            \"astId\": 2642,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_value\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_bytes32\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(Set)3206_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableSet.Set\",\n        \"members\": [\n          {\n            \"astId\": 3201,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_values\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_array(t_bytes32)dyn_storage\"\n          },\n          {\n            \"astId\": 3205,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_indexes\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_mapping(t_bytes32,t_uint256)\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(UintSet)3592_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableSet.UintSet\",\n        \"members\": [\n          {\n            \"astId\": 3591,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_inner\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_struct(Set)3206_storage\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(UintToAddressMap)2969_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableMap.UintToAddressMap\",\n        \"members\": [\n          {\n            \"astId\": 2968,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_inner\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_struct(Map)2651_storage\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/SqrtPriceMathPartial.json",
    "content": "{\n  \"address\": \"0xb9127F2e97F6816DCd7b85d8617B7AcFe5E15419\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioAX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioBX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"roundUp\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getAmount0Delta\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioAX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioBX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"roundUp\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getAmount1Delta\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x2bdb3fc694628e83855123ddee85e255d1fb5a12955ca7c6905deebcb9d29dd5\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0xb9127F2e97F6816DCd7b85d8617B7AcFe5E15419\",\n    \"transactionIndex\": 48,\n    \"gasUsed\": \"245472\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x49521b7bb81c43ca68576110a738166dfe29d62e1428d3612dc63ad14aaefdce\",\n    \"transactionHash\": \"0x2bdb3fc694628e83855123ddee85e255d1fb5a12955ca7c6905deebcb9d29dd5\",\n    \"logs\": [],\n    \"blockNumber\": 14922911,\n    \"cumulativeGasUsed\": \"3944307\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"fc32ed9e00a9017e491333926bef5473\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioAX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioBX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"roundUp\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getAmount0Delta\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioAX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioBX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"roundUp\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getAmount1Delta\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"getAmount0Delta(uint160,uint160,uint128,bool)\\\":{\\\"details\\\":\\\"Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper), i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\",\\\"params\\\":{\\\"liquidity\\\":\\\"The amount of usable liquidity\\\",\\\"roundUp\\\":\\\"Whether to round the amount up or down\\\",\\\"sqrtRatioAX96\\\":\\\"A sqrt price\\\",\\\"sqrtRatioBX96\\\":\\\"Another sqrt price\\\"},\\\"returns\\\":{\\\"amount0\\\":\\\"Amount of token0 required to cover a position of size liquidity between the two passed prices\\\"}},\\\"getAmount1Delta(uint160,uint160,uint128,bool)\\\":{\\\"details\\\":\\\"Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\",\\\"params\\\":{\\\"liquidity\\\":\\\"The amount of usable liquidity\\\",\\\"roundUp\\\":\\\"Whether to round the amount up, or down\\\",\\\"sqrtRatioAX96\\\":\\\"A sqrt price\\\",\\\"sqrtRatioBX96\\\":\\\"Another sqrt price\\\"},\\\"returns\\\":{\\\"amount1\\\":\\\"Amount of token1 required to cover a position of size liquidity between the two passed prices\\\"}}},\\\"title\\\":\\\"Functions based on Q64.96 sqrt price and liquidity\\\",\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"getAmount0Delta(uint160,uint160,uint128,bool)\\\":{\\\"notice\\\":\\\"Gets the amount0 delta between two prices\\\"},\\\"getAmount1Delta(uint160,uint160,uint128,bool)\\\":{\\\"notice\\\":\\\"Gets the amount1 delta between two prices\\\"}},\\\"notice\\\":\\\"Exposes two functions from @uniswap/v3-core SqrtPriceMath that use square root of price as a Q64.96 and liquidity to compute deltas\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":\\\"SqrtPriceMathPartial\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/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\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x61037c610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80632c32d4b61461004557806348a0c5bd146100a7575b600080fd5b6100956004803603608081101561005b57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156100f7565b60408051918252519081900360200190f35b610095600480360360808110156100bd57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156101b4565b6000836001600160a01b0316856001600160a01b03161115610117579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661015357600080fd5b8361018357866001600160a01b03166101768383896001600160a01b0316610251565b8161017d57fe5b046101a9565b6101a961019a8383896001600160a01b0316610301565b886001600160a01b031661033b565b979650505050505050565b6000836001600160a01b0316856001600160a01b031611156101d4579293925b816102135761020e836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610251565b610248565b610248836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610301565b95945050505050565b6000808060001985870986860292508281109083900303905080610287576000841161027c57600080fd5b5082900490506102fa565b80841161029357600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b600061030e848484610251565b90506000828061031a57fe5b84860911156102fa57600019811061033157600080fd5b6001019392505050565b80820491061515019056fea264697066735822122015b1d5e98e518aedb03f0724756a56b09b753efd09a45ae663413fd3cad16d6d64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80632c32d4b61461004557806348a0c5bd146100a7575b600080fd5b6100956004803603608081101561005b57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156100f7565b60408051918252519081900360200190f35b610095600480360360808110156100bd57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156101b4565b6000836001600160a01b0316856001600160a01b03161115610117579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661015357600080fd5b8361018357866001600160a01b03166101768383896001600160a01b0316610251565b8161017d57fe5b046101a9565b6101a961019a8383896001600160a01b0316610301565b886001600160a01b031661033b565b979650505050505050565b6000836001600160a01b0316856001600160a01b031611156101d4579293925b816102135761020e836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610251565b610248565b610248836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610301565b95945050505050565b6000808060001985870986860292508281109083900303905080610287576000841161027c57600080fd5b5082900490506102fa565b80841161029357600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b600061030e848484610251565b90506000828061031a57fe5b84860911156102fa57600019811061033157600080fd5b6001019392505050565b80820491061515019056fea264697066735822122015b1d5e98e518aedb03f0724756a56b09b753efd09a45ae663413fd3cad16d6d64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"getAmount0Delta(uint160,uint160,uint128,bool)\": {\n        \"details\": \"Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper), i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\",\n        \"params\": {\n          \"liquidity\": \"The amount of usable liquidity\",\n          \"roundUp\": \"Whether to round the amount up or down\",\n          \"sqrtRatioAX96\": \"A sqrt price\",\n          \"sqrtRatioBX96\": \"Another sqrt price\"\n        },\n        \"returns\": {\n          \"amount0\": \"Amount of token0 required to cover a position of size liquidity between the two passed prices\"\n        }\n      },\n      \"getAmount1Delta(uint160,uint160,uint128,bool)\": {\n        \"details\": \"Calculates liquidity * (sqrt(upper) - sqrt(lower))\",\n        \"params\": {\n          \"liquidity\": \"The amount of usable liquidity\",\n          \"roundUp\": \"Whether to round the amount up, or down\",\n          \"sqrtRatioAX96\": \"A sqrt price\",\n          \"sqrtRatioBX96\": \"Another sqrt price\"\n        },\n        \"returns\": {\n          \"amount1\": \"Amount of token1 required to cover a position of size liquidity between the two passed prices\"\n        }\n      }\n    },\n    \"title\": \"Functions based on Q64.96 sqrt price and liquidity\",\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"getAmount0Delta(uint160,uint160,uint128,bool)\": {\n        \"notice\": \"Gets the amount0 delta between two prices\"\n      },\n      \"getAmount1Delta(uint160,uint160,uint128,bool)\": {\n        \"notice\": \"Gets the amount1 delta between two prices\"\n      }\n    },\n    \"notice\": \"Exposes two functions from @uniswap/v3-core SqrtPriceMath that use square root of price as a Q64.96 and liquidity to compute deltas\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/TickMathExternal.json",
    "content": "{\n  \"address\": \"0x8f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tick\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"name\": \"getSqrtRatioAtTick\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96\",\n          \"type\": \"uint160\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96\",\n          \"type\": \"uint160\"\n        }\n      ],\n      \"name\": \"getTickAtSqrtRatio\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tick\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x924419292a0d553f8e9f5c1b41d46bf17e67257eba2ff4ae43efade385a68339\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0x8f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D\",\n    \"transactionIndex\": 336,\n    \"gasUsed\": \"461403\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0xde3fe3d81c6cb82826700eb280469411c56a6fc3a8a0c16d5fc5409acb52ec65\",\n    \"transactionHash\": \"0x924419292a0d553f8e9f5c1b41d46bf17e67257eba2ff4ae43efade385a68339\",\n    \"logs\": [],\n    \"blockNumber\": 14922910,\n    \"cumulativeGasUsed\": \"23504504\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"fc32ed9e00a9017e491333926bef5473\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"tick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"name\\\":\\\"getSqrtRatioAtTick\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"name\\\":\\\"getTickAtSqrtRatio\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"tick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"getSqrtRatioAtTick(int24)\\\":{\\\"details\\\":\\\"Throws if |tick| > max tick\\\",\\\"params\\\":{\\\"tick\\\":\\\"The input tick for the above formula\\\"},\\\"returns\\\":{\\\"sqrtPriceX96\\\":\\\"A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) at the given tick\\\"}},\\\"getTickAtSqrtRatio(uint160)\\\":{\\\"details\\\":\\\"Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may ever return.\\\",\\\"params\\\":{\\\"sqrtPriceX96\\\":\\\"The sqrt ratio for which to compute the tick as a Q64.96\\\"},\\\"returns\\\":{\\\"tick\\\":\\\"The greatest tick for which the ratio is less than or equal to the input ratio\\\"}}},\\\"stateVariables\\\":{\\\"MAX_SQRT_RATIO\\\":{\\\"details\\\":\\\"The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\"},\\\"MAX_TICK\\\":{\\\"details\\\":\\\"The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\"},\\\"MIN_SQRT_RATIO\\\":{\\\"details\\\":\\\"The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\"},\\\"MIN_TICK\\\":{\\\"details\\\":\\\"The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\"}},\\\"title\\\":\\\"Math library for computing sqrt prices from ticks and vice versa\\\",\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"getSqrtRatioAtTick(int24)\\\":{\\\"notice\\\":\\\"Calculates sqrt(1.0001^tick) * 2^96\\\"},\\\"getTickAtSqrtRatio(uint160)\\\":{\\\"notice\\\":\\\"Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\"}},\\\"notice\\\":\\\"Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports prices between 2**-128 and 2**128\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/libs/TickMathExternal.sol\\\":\\\"TickMathExternal\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x610768610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80634f76c05814610045578063986cfba314610082575b600080fd5b61006b6004803603602081101561005b57600080fd5b50356001600160a01b03166100be565b6040805160029290920b8252519081900360200190f35b6100a26004803603602081101561009857600080fd5b503560020b6103f3565b604080516001600160a01b039092168252519081900360200190f35b60006401000276a36001600160a01b038316108015906100fa575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b61012f576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106101d957607f810383901c91506101e3565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146103e457886001600160a01b03166103c8826103f3565b6001600160a01b031611156103dd57816103df565b805b6103e6565b815b9998505050505050505050565b60008060008360020b1261040a578260020b610412565b8260020b6000035b9050620d89e8811115610450576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b60006001821661047157700100000000000000000000000000000000610483565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156104b7576ffff97272373d413259a46990580e213a0260801c5b60048216156104d6576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b60088216156104f5576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610514576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610533576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610552576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610571576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610591576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b6102008216156105b1576ff987a7253ac413176f2b074cf7815e540260801c5b6104008216156105d1576ff3392b0822b70005940c7a398e4b70f30260801c5b6108008216156105f1576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610611576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610631576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610651576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610671576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610692576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156106b2576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156106d1576d2216e584f5fa1ea926041bedfe980260801c5b620800008216156106ee576b048a170391f7dc42444e8fa20260801c5b60008460020b131561070957806000198161070557fe5b0490505b64010000000081061561071d576001610720565b60005b60ff16602082901c019250505091905056fea26469706673582212202e5ff2dd11e1c84c4b4e2364d3ed76b64538bfce96b28ff3a83052ea235fa8ed64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80634f76c05814610045578063986cfba314610082575b600080fd5b61006b6004803603602081101561005b57600080fd5b50356001600160a01b03166100be565b6040805160029290920b8252519081900360200190f35b6100a26004803603602081101561009857600080fd5b503560020b6103f3565b604080516001600160a01b039092168252519081900360200190f35b60006401000276a36001600160a01b038316108015906100fa575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b61012f576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106101d957607f810383901c91506101e3565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146103e457886001600160a01b03166103c8826103f3565b6001600160a01b031611156103dd57816103df565b805b6103e6565b815b9998505050505050505050565b60008060008360020b1261040a578260020b610412565b8260020b6000035b9050620d89e8811115610450576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b60006001821661047157700100000000000000000000000000000000610483565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156104b7576ffff97272373d413259a46990580e213a0260801c5b60048216156104d6576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b60088216156104f5576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610514576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610533576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610552576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610571576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610591576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b6102008216156105b1576ff987a7253ac413176f2b074cf7815e540260801c5b6104008216156105d1576ff3392b0822b70005940c7a398e4b70f30260801c5b6108008216156105f1576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610611576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610631576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610651576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610671576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610692576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156106b2576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156106d1576d2216e584f5fa1ea926041bedfe980260801c5b620800008216156106ee576b048a170391f7dc42444e8fa20260801c5b60008460020b131561070957806000198161070557fe5b0490505b64010000000081061561071d576001610720565b60005b60ff16602082901c019250505091905056fea26469706673582212202e5ff2dd11e1c84c4b4e2364d3ed76b64538bfce96b28ff3a83052ea235fa8ed64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"getSqrtRatioAtTick(int24)\": {\n        \"details\": \"Throws if |tick| > max tick\",\n        \"params\": {\n          \"tick\": \"The input tick for the above formula\"\n        },\n        \"returns\": {\n          \"sqrtPriceX96\": \"A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) at the given tick\"\n        }\n      },\n      \"getTickAtSqrtRatio(uint160)\": {\n        \"details\": \"Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may ever return.\",\n        \"params\": {\n          \"sqrtPriceX96\": \"The sqrt ratio for which to compute the tick as a Q64.96\"\n        },\n        \"returns\": {\n          \"tick\": \"The greatest tick for which the ratio is less than or equal to the input ratio\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"MAX_SQRT_RATIO\": {\n        \"details\": \"The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\"\n      },\n      \"MAX_TICK\": {\n        \"details\": \"The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\"\n      },\n      \"MIN_SQRT_RATIO\": {\n        \"details\": \"The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\"\n      },\n      \"MIN_TICK\": {\n        \"details\": \"The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\"\n      }\n    },\n    \"title\": \"Math library for computing sqrt prices from ticks and vice versa\",\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"getSqrtRatioAtTick(int24)\": {\n        \"notice\": \"Calculates sqrt(1.0001^tick) * 2^96\"\n      },\n      \"getTickAtSqrtRatio(uint160)\": {\n        \"notice\": \"Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\"\n      }\n    },\n    \"notice\": \"Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports prices between 2**-128 and 2**128\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/Timelock.json",
    "content": "{\n  \"address\": \"0x67c083aE303741372F0f321Bf9cAD567CFEFE2DC\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"admin_\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"delay_\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"bytes32\",\n          \"name\": \"txHash\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"CancelTransaction\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"bytes32\",\n          \"name\": \"txHash\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ExecuteTransaction\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newAdmin\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"NewAdmin\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"newDelay\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"NewDelay\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newPendingAdmin\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"NewPendingAdmin\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"bytes32\",\n          \"name\": \"txHash\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"QueueTransaction\",\n      \"type\": \"event\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"fallback\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"GRACE_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"MAXIMUM_DELAY\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"MINIMUM_DELAY\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"acceptAdmin\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"admin\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"cancelTransaction\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"delay\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"executeTransaction\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"pendingAdmin\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"queueTransaction\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"queuedTransactions\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"delay_\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setDelay\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"pendingAdmin_\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"setPendingAdmin\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x15d6c9b711fa40a806f640c8b7602989e708a516d3caaec1baa812fbbbe85afa\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0x67c083aE303741372F0f321Bf9cAD567CFEFE2DC\",\n    \"transactionIndex\": 91,\n    \"gasUsed\": \"1731292\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x600c42478cd9771e530d4fdf17697678dac7ef53593329f29d12c2bfe6a251ff\",\n    \"transactionHash\": \"0x15d6c9b711fa40a806f640c8b7602989e708a516d3caaec1baa812fbbbe85afa\",\n    \"logs\": [],\n    \"blockNumber\": 15134581,\n    \"cumulativeGasUsed\": \"8514703\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x609FFF64429e2A275a879e5C50e415cec842c629\",\n    432000\n  ],\n  \"solcInputHash\": \"e85d9fda89ae8c3780a8ae01da3f423c\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.8.10+commit.fc410830\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"admin_\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"delay_\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"txHash\\\",\\\"type\\\":\\\"bytes32\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"CancelTransaction\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"txHash\\\",\\\"type\\\":\\\"bytes32\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ExecuteTransaction\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newAdmin\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"NewAdmin\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newDelay\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"NewDelay\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newPendingAdmin\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"NewPendingAdmin\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"txHash\\\",\\\"type\\\":\\\"bytes32\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"QueueTransaction\\\",\\\"type\\\":\\\"event\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"fallback\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"GRACE_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"MAXIMUM_DELAY\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"MINIMUM_DELAY\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"acceptAdmin\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"admin\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"cancelTransaction\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"delay\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"executeTransaction\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"pendingAdmin\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"queueTransaction\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"name\\\":\\\"queuedTransactions\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"delay_\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setDelay\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"pendingAdmin_\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"setPendingAdmin\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/strategy/timelock/Timelock.sol\\\":\\\"Timelock\\\"},\\\"evmVersion\\\":\\\"london\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\"},\\\"optimizer\\\":{\\\"enabled\\\":false,\\\"runs\\\":200},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"contracts/strategy/timelock/SafeMath.sol\\\":{\\\"keccak256\\\":\\\"0x4096f1e15e33c0219aebf8c574521db0d47a23106edf539bbb21539a91716137\\\",\\\"license\\\":\\\"BSD-3-Clause\\\",\\\"urls\\\":[\\\"bzz-raw://a14a79ba570f2ca27848c0d8ea1bfc24c285e0559fd8c899804d96ab45f37039\\\",\\\"dweb:/ipfs/QmSrcv1vMeinEqSS2YDKrQDmwH4eXugWMAuLjMDAYMzNtk\\\"]},\\\"contracts/strategy/timelock/Timelock.sol\\\":{\\\"keccak256\\\":\\\"0x1255ec6e3c4fbd6b853907bb0c602b059ddbce72346d210c555cd93b3729429f\\\",\\\"license\\\":\\\"BSD-3-Clause\\\",\\\"urls\\\":[\\\"bzz-raw://61996a81280b3cbf08aa666dd0765468953367386c7290ba7396b9ec7278a402\\\",\\\"dweb:/ipfs/QmXssf8kKgEDaYGcxpM36Cx3gefdg4PQiSQny2d8DKbdbU\\\"]}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60806040523480156200001157600080fd5b50604051620020cc380380620020cc8339818101604052810190620000379190620001bd565b6202a30081101562000080576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000077906200028b565b60405180910390fd5b62278d00811115620000c9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000c09062000323565b60405180910390fd5b816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600281905550505062000345565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200014a826200011d565b9050919050565b6200015c816200013d565b81146200016857600080fd5b50565b6000815190506200017c8162000151565b92915050565b6000819050919050565b620001978162000182565b8114620001a357600080fd5b50565b600081519050620001b7816200018c565b92915050565b60008060408385031215620001d757620001d662000118565b5b6000620001e7858286016200016b565b9250506020620001fa85828601620001a6565b9150509250929050565b600082825260208201905092915050565b7f54696d656c6f636b3a3a636f6e7374727563746f723a2044656c6179206d757360008201527f7420657863656564206d696e696d756d2064656c61792e000000000000000000602082015250565b60006200027360378362000204565b9150620002808262000215565b604082019050919050565b60006020820190508181036000830152620002a68162000264565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206e60008201527f6f7420657863656564206d6178696d756d2064656c61792e0000000000000000602082015250565b60006200030b60388362000204565b91506200031882620002ad565b604082019050919050565b600060208201905081810360008301526200033e81620002fc565b9050919050565b611d7780620003556000396000f3fe6080604052600436106100c65760003560e01c80636a42b8f81161007f578063c1a287e211610059578063c1a287e21461024b578063e177246e14610276578063f2b065371461029f578063f851a440146102dc576100c7565b80636a42b8f8146101ca5780637d645fab146101f5578063b1b43ae514610220576100c7565b80630825f38f146100c95780630e18b681146100f957806326782247146101105780633a66f9011461013b5780634dd18bf514610178578063591fcdfe146101a1576100c7565b5b005b6100e360048036038101906100de9190611080565b610307565b6040516100f091906111bb565b60405180910390f35b34801561010557600080fd5b5061010e610654565b005b34801561011c57600080fd5b506101256107cb565b60405161013291906111ec565b60405180910390f35b34801561014757600080fd5b50610162600480360381019061015d9190611080565b6107f1565b60405161016f9190611220565b60405180910390f35b34801561018457600080fd5b5061019f600480360381019061019a919061123b565b6109a1565b005b3480156101ad57600080fd5b506101c860048036038101906101c39190611080565b610ab8565b005b3480156101d657600080fd5b506101df610c02565b6040516101ec9190611277565b60405180910390f35b34801561020157600080fd5b5061020a610c08565b6040516102179190611277565b60405180910390f35b34801561022c57600080fd5b50610235610c0f565b6040516102429190611277565b60405180910390f35b34801561025757600080fd5b50610260610c16565b60405161026d9190611277565b60405180910390f35b34801561028257600080fd5b5061029d60048036038101906102989190611292565b610c1d565b005b3480156102ab57600080fd5b506102c660048036038101906102c191906112eb565b610d50565b6040516102d39190611333565b60405180910390f35b3480156102e857600080fd5b506102f1610d70565b6040516102fe91906111ec565b60405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161038e906113d1565b60405180910390fd5b600086868686866040516020016103b2959493929190611435565b6040516020818303038152906040528051906020012090506003600082815260200190815260200160002060009054906101000a900460ff1661042a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042190611508565b60405180910390fd5b82610433610d94565b1015610474576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046b906115c0565b60405180910390fd5b61048a6212750084610d9c90919063ffffffff16565b610492610d94565b11156104d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104ca90611652565b60405180910390fd5b60006003600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060606000865114156105135784905061053f565b85805190602001208560405160200161052d9291906116fb565b60405160208183030381529060405290505b6000808973ffffffffffffffffffffffffffffffffffffffff1689846040516105689190611723565b60006040518083038185875af1925050503d80600081146105a5576040519150601f19603f3d011682016040523d82523d6000602084013e6105aa565b606091505b5091509150816105ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e6906117ac565b60405180910390fd5b8973ffffffffffffffffffffffffffffffffffffffff16847fa560e3198060a2f10670c1ec5b403077ea6ae93ca8de1c32b451dc1a943cd6e78b8b8b8b60405161063c94939291906117cc565b60405180910390a38094505050505095945050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106db90611891565b60405180910390fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c60405160405180910390a2565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610882576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087990611923565b60405180910390fd5b61089e600254610890610d94565b610d9c90919063ffffffff16565b8210156108e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d7906119db565b60405180910390fd5b600086868686866040516020016108fb959493929190611435565b60405160208183030381529060405280519060200120905060016003600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508673ffffffffffffffffffffffffffffffffffffffff16817f76e2796dc3a81d57b0e8504b647febcbeeb5f4af818e164f11eef8131a6a763f8888888860405161098c94939291906117cc565b60405180910390a38091505095945050505050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0690611a6d565b60405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f69d78e38a01985fbb1462961809b4b2d65531bc93b2b94037f3334b82ca4a75660405160405180910390a250565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b46576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3d90611aff565b60405180910390fd5b60008585858585604051602001610b61959493929190611435565b60405160208183030381529060405280519060200120905060006003600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508573ffffffffffffffffffffffffffffffffffffffff16817f2fffc091a501fd91bfbff27141450d3acb40fb8e6d8382b243ec7a812a3aaf8787878787604051610bf294939291906117cc565b60405180910390a3505050505050565b60025481565b62278d0081565b6202a30081565b6212750081565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8290611b91565b60405180910390fd5b6202a300811015610cd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc890611c23565b60405180910390fd5b62278d00811115610d17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0e90611cb5565b60405180910390fd5b806002819055506002547f948b1f6a42ee138b7e34058ba85a37f716d55ff25ff05a763f15bed6a04c8d2c60405160405180910390a250565b60036020528060005260406000206000915054906101000a900460ff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600042905090565b600080828401905083811015610de7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dde90611d21565b60405180910390fd5b8091505092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610e3082610e05565b9050919050565b610e4081610e25565b8114610e4b57600080fd5b50565b600081359050610e5d81610e37565b92915050565b6000819050919050565b610e7681610e63565b8114610e8157600080fd5b50565b600081359050610e9381610e6d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610eec82610ea3565b810181811067ffffffffffffffff82111715610f0b57610f0a610eb4565b5b80604052505050565b6000610f1e610df1565b9050610f2a8282610ee3565b919050565b600067ffffffffffffffff821115610f4a57610f49610eb4565b5b610f5382610ea3565b9050602081019050919050565b82818337600083830152505050565b6000610f82610f7d84610f2f565b610f14565b905082815260208101848484011115610f9e57610f9d610e9e565b5b610fa9848285610f60565b509392505050565b600082601f830112610fc657610fc5610e99565b5b8135610fd6848260208601610f6f565b91505092915050565b600067ffffffffffffffff821115610ffa57610ff9610eb4565b5b61100382610ea3565b9050602081019050919050565b600061102361101e84610fdf565b610f14565b90508281526020810184848401111561103f5761103e610e9e565b5b61104a848285610f60565b509392505050565b600082601f83011261106757611066610e99565b5b8135611077848260208601611010565b91505092915050565b600080600080600060a0868803121561109c5761109b610dfb565b5b60006110aa88828901610e4e565b95505060206110bb88828901610e84565b945050604086013567ffffffffffffffff8111156110dc576110db610e00565b5b6110e888828901610fb1565b935050606086013567ffffffffffffffff81111561110957611108610e00565b5b61111588828901611052565b925050608061112688828901610e84565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b8381101561116d578082015181840152602081019050611152565b8381111561117c576000848401525b50505050565b600061118d82611133565b611197818561113e565b93506111a781856020860161114f565b6111b081610ea3565b840191505092915050565b600060208201905081810360008301526111d58184611182565b905092915050565b6111e681610e25565b82525050565b600060208201905061120160008301846111dd565b92915050565b6000819050919050565b61121a81611207565b82525050565b60006020820190506112356000830184611211565b92915050565b60006020828403121561125157611250610dfb565b5b600061125f84828501610e4e565b91505092915050565b61127181610e63565b82525050565b600060208201905061128c6000830184611268565b92915050565b6000602082840312156112a8576112a7610dfb565b5b60006112b684828501610e84565b91505092915050565b6112c881611207565b81146112d357600080fd5b50565b6000813590506112e5816112bf565b92915050565b60006020828403121561130157611300610dfb565b5b600061130f848285016112d6565b91505092915050565b60008115159050919050565b61132d81611318565b82525050565b60006020820190506113486000830184611324565b92915050565b600082825260208201905092915050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20436160008201527f6c6c206d75737420636f6d652066726f6d2061646d696e2e0000000000000000602082015250565b60006113bb60388361134e565b91506113c68261135f565b604082019050919050565b600060208201905081810360008301526113ea816113ae565b9050919050565b600081519050919050565b6000611407826113f1565b611411818561134e565b935061142181856020860161114f565b61142a81610ea3565b840191505092915050565b600060a08201905061144a60008301886111dd565b6114576020830187611268565b818103604083015261146981866113fc565b9050818103606083015261147d8185611182565b905061148c6080830184611268565b9695505050505050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206861736e2774206265656e207175657565642e000000602082015250565b60006114f2603d8361134e565b91506114fd82611496565b604082019050919050565b60006020820190508181036000830152611521816114e5565b9050919050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206861736e2774207375727061737365642074696d652060208201527f6c6f636b2e000000000000000000000000000000000000000000000000000000604082015250565b60006115aa60458361134e565b91506115b582611528565b606082019050919050565b600060208201905081810360008301526115d98161159d565b9050919050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206973207374616c652e00000000000000000000000000602082015250565b600061163c60338361134e565b9150611647826115e0565b604082019050919050565b6000602082019050818103600083015261166b8161162f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b6116b96116b482611672565b61169e565b82525050565b600081905092915050565b60006116d582611133565b6116df81856116bf565b93506116ef81856020860161114f565b80840191505092915050565b600061170782856116a8565b60048201915061171782846116ca565b91508190509392505050565b600061172f82846116ca565b915081905092915050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e20657865637574696f6e2072657665727465642e000000602082015250565b6000611796603d8361134e565b91506117a18261173a565b604082019050919050565b600060208201905081810360008301526117c581611789565b9050919050565b60006080820190506117e16000830187611268565b81810360208301526117f381866113fc565b905081810360408301526118078185611182565b90506118166060830184611268565b95945050505050565b7f54696d656c6f636b3a3a61636365707441646d696e3a2043616c6c206d75737460008201527f20636f6d652066726f6d2070656e64696e6741646d696e2e0000000000000000602082015250565b600061187b60388361134e565b91506118868261181f565b604082019050919050565b600060208201905081810360008301526118aa8161186e565b9050919050565b7f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a2043616c6c60008201527f206d75737420636f6d652066726f6d2061646d696e2e00000000000000000000602082015250565b600061190d60368361134e565b9150611918826118b1565b604082019050919050565b6000602082019050818103600083015261193c81611900565b9050919050565b7f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a204573746960008201527f6d6174656420657865637574696f6e20626c6f636b206d75737420736174697360208201527f66792064656c61792e0000000000000000000000000000000000000000000000604082015250565b60006119c560498361134e565b91506119d082611943565b606082019050919050565b600060208201905081810360008301526119f4816119b8565b9050919050565b7f54696d656c6f636b3a3a73657450656e64696e6741646d696e3a2043616c6c2060008201527f6d75737420636f6d652066726f6d2054696d656c6f636b2e0000000000000000602082015250565b6000611a5760388361134e565b9150611a62826119fb565b604082019050919050565b60006020820190508181036000830152611a8681611a4a565b9050919050565b7f54696d656c6f636b3a3a63616e63656c5472616e73616374696f6e3a2043616c60008201527f6c206d75737420636f6d652066726f6d2061646d696e2e000000000000000000602082015250565b6000611ae960378361134e565b9150611af482611a8d565b604082019050919050565b60006020820190508181036000830152611b1881611adc565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2043616c6c206d75737420636f60008201527f6d652066726f6d2054696d656c6f636b2e000000000000000000000000000000602082015250565b6000611b7b60318361134e565b9150611b8682611b1f565b604082019050919050565b60006020820190508181036000830152611baa81611b6e565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206560008201527f7863656564206d696e696d756d2064656c61792e000000000000000000000000602082015250565b6000611c0d60348361134e565b9150611c1882611bb1565b604082019050919050565b60006020820190508181036000830152611c3c81611c00565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206e60008201527f6f7420657863656564206d6178696d756d2064656c61792e0000000000000000602082015250565b6000611c9f60388361134e565b9150611caa82611c43565b604082019050919050565b60006020820190508181036000830152611cce81611c92565b9050919050565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000600082015250565b6000611d0b601b8361134e565b9150611d1682611cd5565b602082019050919050565b60006020820190508181036000830152611d3a81611cfe565b905091905056fea2646970667358221220cf514a935c267519527cd5a3c0353bc9a6b4bf8a678929991b92751553d4419964736f6c634300080a0033\",\n  \"deployedBytecode\": \"0x6080604052600436106100c65760003560e01c80636a42b8f81161007f578063c1a287e211610059578063c1a287e21461024b578063e177246e14610276578063f2b065371461029f578063f851a440146102dc576100c7565b80636a42b8f8146101ca5780637d645fab146101f5578063b1b43ae514610220576100c7565b80630825f38f146100c95780630e18b681146100f957806326782247146101105780633a66f9011461013b5780634dd18bf514610178578063591fcdfe146101a1576100c7565b5b005b6100e360048036038101906100de9190611080565b610307565b6040516100f091906111bb565b60405180910390f35b34801561010557600080fd5b5061010e610654565b005b34801561011c57600080fd5b506101256107cb565b60405161013291906111ec565b60405180910390f35b34801561014757600080fd5b50610162600480360381019061015d9190611080565b6107f1565b60405161016f9190611220565b60405180910390f35b34801561018457600080fd5b5061019f600480360381019061019a919061123b565b6109a1565b005b3480156101ad57600080fd5b506101c860048036038101906101c39190611080565b610ab8565b005b3480156101d657600080fd5b506101df610c02565b6040516101ec9190611277565b60405180910390f35b34801561020157600080fd5b5061020a610c08565b6040516102179190611277565b60405180910390f35b34801561022c57600080fd5b50610235610c0f565b6040516102429190611277565b60405180910390f35b34801561025757600080fd5b50610260610c16565b60405161026d9190611277565b60405180910390f35b34801561028257600080fd5b5061029d60048036038101906102989190611292565b610c1d565b005b3480156102ab57600080fd5b506102c660048036038101906102c191906112eb565b610d50565b6040516102d39190611333565b60405180910390f35b3480156102e857600080fd5b506102f1610d70565b6040516102fe91906111ec565b60405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161038e906113d1565b60405180910390fd5b600086868686866040516020016103b2959493929190611435565b6040516020818303038152906040528051906020012090506003600082815260200190815260200160002060009054906101000a900460ff1661042a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042190611508565b60405180910390fd5b82610433610d94565b1015610474576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046b906115c0565b60405180910390fd5b61048a6212750084610d9c90919063ffffffff16565b610492610d94565b11156104d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104ca90611652565b60405180910390fd5b60006003600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060606000865114156105135784905061053f565b85805190602001208560405160200161052d9291906116fb565b60405160208183030381529060405290505b6000808973ffffffffffffffffffffffffffffffffffffffff1689846040516105689190611723565b60006040518083038185875af1925050503d80600081146105a5576040519150601f19603f3d011682016040523d82523d6000602084013e6105aa565b606091505b5091509150816105ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e6906117ac565b60405180910390fd5b8973ffffffffffffffffffffffffffffffffffffffff16847fa560e3198060a2f10670c1ec5b403077ea6ae93ca8de1c32b451dc1a943cd6e78b8b8b8b60405161063c94939291906117cc565b60405180910390a38094505050505095945050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106db90611891565b60405180910390fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c60405160405180910390a2565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610882576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087990611923565b60405180910390fd5b61089e600254610890610d94565b610d9c90919063ffffffff16565b8210156108e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d7906119db565b60405180910390fd5b600086868686866040516020016108fb959493929190611435565b60405160208183030381529060405280519060200120905060016003600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508673ffffffffffffffffffffffffffffffffffffffff16817f76e2796dc3a81d57b0e8504b647febcbeeb5f4af818e164f11eef8131a6a763f8888888860405161098c94939291906117cc565b60405180910390a38091505095945050505050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0690611a6d565b60405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f69d78e38a01985fbb1462961809b4b2d65531bc93b2b94037f3334b82ca4a75660405160405180910390a250565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b46576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3d90611aff565b60405180910390fd5b60008585858585604051602001610b61959493929190611435565b60405160208183030381529060405280519060200120905060006003600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508573ffffffffffffffffffffffffffffffffffffffff16817f2fffc091a501fd91bfbff27141450d3acb40fb8e6d8382b243ec7a812a3aaf8787878787604051610bf294939291906117cc565b60405180910390a3505050505050565b60025481565b62278d0081565b6202a30081565b6212750081565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8290611b91565b60405180910390fd5b6202a300811015610cd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc890611c23565b60405180910390fd5b62278d00811115610d17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0e90611cb5565b60405180910390fd5b806002819055506002547f948b1f6a42ee138b7e34058ba85a37f716d55ff25ff05a763f15bed6a04c8d2c60405160405180910390a250565b60036020528060005260406000206000915054906101000a900460ff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600042905090565b600080828401905083811015610de7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dde90611d21565b60405180910390fd5b8091505092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610e3082610e05565b9050919050565b610e4081610e25565b8114610e4b57600080fd5b50565b600081359050610e5d81610e37565b92915050565b6000819050919050565b610e7681610e63565b8114610e8157600080fd5b50565b600081359050610e9381610e6d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610eec82610ea3565b810181811067ffffffffffffffff82111715610f0b57610f0a610eb4565b5b80604052505050565b6000610f1e610df1565b9050610f2a8282610ee3565b919050565b600067ffffffffffffffff821115610f4a57610f49610eb4565b5b610f5382610ea3565b9050602081019050919050565b82818337600083830152505050565b6000610f82610f7d84610f2f565b610f14565b905082815260208101848484011115610f9e57610f9d610e9e565b5b610fa9848285610f60565b509392505050565b600082601f830112610fc657610fc5610e99565b5b8135610fd6848260208601610f6f565b91505092915050565b600067ffffffffffffffff821115610ffa57610ff9610eb4565b5b61100382610ea3565b9050602081019050919050565b600061102361101e84610fdf565b610f14565b90508281526020810184848401111561103f5761103e610e9e565b5b61104a848285610f60565b509392505050565b600082601f83011261106757611066610e99565b5b8135611077848260208601611010565b91505092915050565b600080600080600060a0868803121561109c5761109b610dfb565b5b60006110aa88828901610e4e565b95505060206110bb88828901610e84565b945050604086013567ffffffffffffffff8111156110dc576110db610e00565b5b6110e888828901610fb1565b935050606086013567ffffffffffffffff81111561110957611108610e00565b5b61111588828901611052565b925050608061112688828901610e84565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b8381101561116d578082015181840152602081019050611152565b8381111561117c576000848401525b50505050565b600061118d82611133565b611197818561113e565b93506111a781856020860161114f565b6111b081610ea3565b840191505092915050565b600060208201905081810360008301526111d58184611182565b905092915050565b6111e681610e25565b82525050565b600060208201905061120160008301846111dd565b92915050565b6000819050919050565b61121a81611207565b82525050565b60006020820190506112356000830184611211565b92915050565b60006020828403121561125157611250610dfb565b5b600061125f84828501610e4e565b91505092915050565b61127181610e63565b82525050565b600060208201905061128c6000830184611268565b92915050565b6000602082840312156112a8576112a7610dfb565b5b60006112b684828501610e84565b91505092915050565b6112c881611207565b81146112d357600080fd5b50565b6000813590506112e5816112bf565b92915050565b60006020828403121561130157611300610dfb565b5b600061130f848285016112d6565b91505092915050565b60008115159050919050565b61132d81611318565b82525050565b60006020820190506113486000830184611324565b92915050565b600082825260208201905092915050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20436160008201527f6c6c206d75737420636f6d652066726f6d2061646d696e2e0000000000000000602082015250565b60006113bb60388361134e565b91506113c68261135f565b604082019050919050565b600060208201905081810360008301526113ea816113ae565b9050919050565b600081519050919050565b6000611407826113f1565b611411818561134e565b935061142181856020860161114f565b61142a81610ea3565b840191505092915050565b600060a08201905061144a60008301886111dd565b6114576020830187611268565b818103604083015261146981866113fc565b9050818103606083015261147d8185611182565b905061148c6080830184611268565b9695505050505050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206861736e2774206265656e207175657565642e000000602082015250565b60006114f2603d8361134e565b91506114fd82611496565b604082019050919050565b60006020820190508181036000830152611521816114e5565b9050919050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206861736e2774207375727061737365642074696d652060208201527f6c6f636b2e000000000000000000000000000000000000000000000000000000604082015250565b60006115aa60458361134e565b91506115b582611528565b606082019050919050565b600060208201905081810360008301526115d98161159d565b9050919050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206973207374616c652e00000000000000000000000000602082015250565b600061163c60338361134e565b9150611647826115e0565b604082019050919050565b6000602082019050818103600083015261166b8161162f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b6116b96116b482611672565b61169e565b82525050565b600081905092915050565b60006116d582611133565b6116df81856116bf565b93506116ef81856020860161114f565b80840191505092915050565b600061170782856116a8565b60048201915061171782846116ca565b91508190509392505050565b600061172f82846116ca565b915081905092915050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e20657865637574696f6e2072657665727465642e000000602082015250565b6000611796603d8361134e565b91506117a18261173a565b604082019050919050565b600060208201905081810360008301526117c581611789565b9050919050565b60006080820190506117e16000830187611268565b81810360208301526117f381866113fc565b905081810360408301526118078185611182565b90506118166060830184611268565b95945050505050565b7f54696d656c6f636b3a3a61636365707441646d696e3a2043616c6c206d75737460008201527f20636f6d652066726f6d2070656e64696e6741646d696e2e0000000000000000602082015250565b600061187b60388361134e565b91506118868261181f565b604082019050919050565b600060208201905081810360008301526118aa8161186e565b9050919050565b7f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a2043616c6c60008201527f206d75737420636f6d652066726f6d2061646d696e2e00000000000000000000602082015250565b600061190d60368361134e565b9150611918826118b1565b604082019050919050565b6000602082019050818103600083015261193c81611900565b9050919050565b7f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a204573746960008201527f6d6174656420657865637574696f6e20626c6f636b206d75737420736174697360208201527f66792064656c61792e0000000000000000000000000000000000000000000000604082015250565b60006119c560498361134e565b91506119d082611943565b606082019050919050565b600060208201905081810360008301526119f4816119b8565b9050919050565b7f54696d656c6f636b3a3a73657450656e64696e6741646d696e3a2043616c6c2060008201527f6d75737420636f6d652066726f6d2054696d656c6f636b2e0000000000000000602082015250565b6000611a5760388361134e565b9150611a62826119fb565b604082019050919050565b60006020820190508181036000830152611a8681611a4a565b9050919050565b7f54696d656c6f636b3a3a63616e63656c5472616e73616374696f6e3a2043616c60008201527f6c206d75737420636f6d652066726f6d2061646d696e2e000000000000000000602082015250565b6000611ae960378361134e565b9150611af482611a8d565b604082019050919050565b60006020820190508181036000830152611b1881611adc565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2043616c6c206d75737420636f60008201527f6d652066726f6d2054696d656c6f636b2e000000000000000000000000000000602082015250565b6000611b7b60318361134e565b9150611b8682611b1f565b604082019050919050565b60006020820190508181036000830152611baa81611b6e565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206560008201527f7863656564206d696e696d756d2064656c61792e000000000000000000000000602082015250565b6000611c0d60348361134e565b9150611c1882611bb1565b604082019050919050565b60006020820190508181036000830152611c3c81611c00565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206e60008201527f6f7420657863656564206d6178696d756d2064656c61792e0000000000000000602082015250565b6000611c9f60388361134e565b9150611caa82611c43565b604082019050919050565b60006020820190508181036000830152611cce81611c92565b9050919050565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000600082015250565b6000611d0b601b8361134e565b9150611d1682611cd5565b602082019050919050565b60006020820190508181036000830152611d3a81611cfe565b905091905056fea2646970667358221220cf514a935c267519527cd5a3c0353bc9a6b4bf8a678929991b92751553d4419964736f6c634300080a0033\"\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/WPowerPerp.json",
    "content": "{\n  \"address\": \"0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_name\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_symbol\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burn\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"controller\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"subtractedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"decreaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"addedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"increaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controller\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"init\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"mint\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x7d501bc3f3cd097745d659b62c111d88f4202e5935c64087010dffea8d0c3475\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xa3cB04d8BD927EEC8826BD77b7C71abE3d29c081\",\n    \"contractAddress\": \"0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B\",\n    \"transactionIndex\": 62,\n    \"gasUsed\": \"1032138\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x28dfd89b3b42928d994cf6839a1f8d29ed4abd1493677bd95d2e01fe6af8643c\",\n    \"transactionHash\": \"0x7d501bc3f3cd097745d659b62c111d88f4202e5935c64087010dffea8d0c3475\",\n    \"logs\": [],\n    \"blockNumber\": 13982500,\n    \"cumulativeGasUsed\": \"4521902\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"Opyn Squeeth\",\n    \"oSQTH\"\n  ],\n  \"solcInputHash\": \"d97d3d4b09e0d70518330d405a7dd9ff\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_name\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_symbol\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burn\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"subtractedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"decreaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"addedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"increaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controller\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"init\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mint\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"details\\\":\\\"value of power perpetual is expected to go down over time through the impact of funding\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"allowance(address,address)\\\":{\\\"details\\\":\\\"See {IERC20-allowance}.\\\"},\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC20-balanceOf}.\\\"},\\\"burn(address,uint256)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"account to burn from\\\",\\\"_amount\\\":\\\"amount to burn\\\"}},\\\"constructor\\\":{\\\"params\\\":{\\\"_name\\\":\\\"token name for ERC20\\\",\\\"_symbol\\\":\\\"token symbol for ERC20\\\"}},\\\"decimals()\\\":{\\\"details\\\":\\\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\\\"},\\\"decreaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\\\"},\\\"increaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\\\"},\\\"init(address)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\"}},\\\"mint(address,uint256)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"account to mint to\\\",\\\"_amount\\\":\\\"amount to mint\\\"}},\\\"name()\\\":{\\\"details\\\":\\\"Returns the name of the token.\\\"},\\\"symbol()\\\":{\\\"details\\\":\\\"Returns the symbol of the token, usually a shorter version of the name.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC20-totalSupply}.\\\"},\\\"transfer(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"burn(address,uint256)\\\":{\\\"notice\\\":\\\"burn wPowerPerp\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"long power perpetual constructor\\\"},\\\"init(address)\\\":{\\\"notice\\\":\\\"init wPowerPerp contract\\\"},\\\"mint(address,uint256)\\\":{\\\"notice\\\":\\\"mint wPowerPerp\\\"}},\\\"notice\\\":\\\"ERC20 Token representing wrapped long power perpetual position\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/WPowerPerp.sol\\\":\\\"WPowerPerp\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// solhint-disable-next-line compiler-version\\\\npragma solidity >=0.4.24 <0.8.0;\\\\n\\\\nimport \\\\\\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\\\nabstract contract Initializable {\\\\n\\\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\\\n    function _isConstructor() private view returns (bool) {\\\\n        return !Address.isContract(address(this));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9abeffe138f098b16557187383ba0f9e8503602fa95cd668132986ee115237ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/core/WPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\n\\\\n//contract\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\nimport {Initializable} from \\\\\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice ERC20 Token representing wrapped long power perpetual position\\\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\\\n */\\\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\\\n    address public controller;\\\\n    address private immutable deployer;\\\\n\\\\n    /**\\\\n     * @notice long power perpetual constructor\\\\n     * @param _name token name for ERC20\\\\n     * @param _symbol token symbol for ERC20\\\\n     */\\\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\\\n        deployer = msg.sender;\\\\n    }\\\\n\\\\n    modifier onlyController() {\\\\n        require(msg.sender == controller, \\\\\\\"Not controller\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice init wPowerPerp contract\\\\n     * @param _controller controller address\\\\n     */\\\\n    function init(address _controller) external initializer {\\\\n        require(msg.sender == deployer, \\\\\\\"Invalid caller of init\\\\\\\");\\\\n        require(_controller != address(0), \\\\\\\"Invalid controller address\\\\\\\");\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp\\\\n     * @param _account account to mint to\\\\n     * @param _amount amount to mint\\\\n     */\\\\n    function mint(address _account, uint256 _amount) external override onlyController {\\\\n        _mint(_account, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp\\\\n     * @param _account account to burn from\\\\n     * @param _amount amount to burn\\\\n     */\\\\n    function burn(address _account, uint256 _amount) external override onlyController {\\\\n        _burn(_account, _amount);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x46a9dd6652f902a62c5e538d99c4566bcd23cbe21247621c2f17b67250c334c5\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60a06040523480156200001157600080fd5b506040516200130238038062001302833981810160405260408110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200010a57600080fd5b9083019060208201858111156200012057600080fd5b82516401000000008111828201881017156200013b57600080fd5b82525081516020918201929091019080838360005b838110156200016a57818101518382015260200162000150565b50505050905090810190601f168015620001985780820380516001836020036101000a031916815260200191505b50604052505082518391508290620001b8906003906020850190620001ed565b508051620001ce906004906020840190620001ed565b50506005805460ff191660121790555050503360601b60805262000299565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928262000225576000855562000270565b82601f106200024057805160ff191683800117855562000270565b8280016001018555821562000270579182015b828111156200027057825182559160200191906001019062000253565b506200027e92915062000282565b5090565b5b808211156200027e576000815560010162000283565b60805160601c61104b620002b760003980610505525061104b6000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806340c10f1911610097578063a457c2d711610066578063a457c2d7146102ff578063a9059cbb1461032b578063dd62ed3e14610357578063f77c479114610385576100f5565b806340c10f191461027957806370a08231146102a557806395d89b41146102cb5780639dc29fac146102d3576100f5565b806319ab453c116100d357806319ab453c146101d157806323b872dd146101f9578063313ce5671461022f578063395093511461024d576100f5565b806306fdde03146100fa578063095ea7b31461017757806318160ddd146101b7575b600080fd5b6101026103a9565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013c578181015183820152602001610124565b50505050905090810190601f1680156101695780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101a36004803603604081101561018d57600080fd5b506001600160a01b03813516906020013561043f565b604080519115158252519081900360200190f35b6101bf61045c565b60408051918252519081900360200190f35b6101f7600480360360208110156101e757600080fd5b50356001600160a01b0316610462565b005b6101a36004803603606081101561020f57600080fd5b506001600160a01b03813581169160208101359091169060400135610622565b6102376106a9565b6040805160ff9092168252519081900360200190f35b6101a36004803603604081101561026357600080fd5b506001600160a01b0381351690602001356106b2565b6101f76004803603604081101561028f57600080fd5b506001600160a01b038135169060200135610700565b6101bf600480360360208110156102bb57600080fd5b50356001600160a01b0316610761565b61010261077c565b6101f7600480360360408110156102e957600080fd5b506001600160a01b0381351690602001356107dd565b6101a36004803603604081101561031557600080fd5b506001600160a01b03813516906020013561083e565b6101a36004803603604081101561034157600080fd5b506001600160a01b0381351690602001356108a6565b6101bf6004803603604081101561036d57600080fd5b506001600160a01b03813581169160200135166108ba565b61038d6108e5565b604080516001600160a01b039092168252519081900360200190f35b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b820191906000526020600020905b81548152906001019060200180831161041857829003601f168201915b5050505050905090565b600061045361044c6108fb565b84846108ff565b50600192915050565b60025490565b60055462010000900460ff168061047c575061047c6109eb565b8061048f5750600554610100900460ff16155b6104ca5760405162461bcd60e51b815260040180806020018281038252602e815260200180610f31602e913960400191505060405180910390fd5b60055462010000900460ff161580156104fa576005805461ff001962ff0000199091166201000017166101001790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610577576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166105d2576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600580547fffffffffffffffffff0000000000000000000000000000000000000000ffffff1663010000006001600160a01b03851602179055801561061e576005805462ff0000191690555b5050565b600061062f8484846109fc565b61069f8461063b6108fb565b61069a85604051806060016040528060288152602001610f5f602891396001600160a01b038a166000908152600160205260408120906106796108fb565b6001600160a01b031681526020810191909152604001600020549190610b57565b6108ff565b5060019392505050565b60055460ff1690565b60006104536106bf6108fb565b8461069a85600160006106d06108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610bee565b600554630100000090046001600160a01b03163314610757576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610c4f565b6001600160a01b031660009081526020819052604090205490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b600554630100000090046001600160a01b03163314610834576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610d3f565b600061045361084b6108fb565b8461069a85604051806060016040528060258152602001610ff160259139600160006108756108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610b57565b60006104536108b36108fb565b84846109fc565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600554630100000090046001600160a01b031681565b3390565b6001600160a01b0383166109445760405162461bcd60e51b8152600401808060200182810382526024815260200180610fcd6024913960400191505060405180910390fd5b6001600160a01b0382166109895760405162461bcd60e51b8152600401808060200182810382526022815260200180610ee96022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60006109f630610e3b565b15905090565b6001600160a01b038316610a415760405162461bcd60e51b8152600401808060200182810382526025815260200180610fa86025913960400191505060405180910390fd5b6001600160a01b038216610a865760405162461bcd60e51b8152600401808060200182810382526023815260200180610ea46023913960400191505060405180910390fd5b610a91838383610e41565b610ace81604051806060016040528060268152602001610f0b602691396001600160a01b0386166000908152602081905260409020549190610b57565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610afd9082610bee565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610be65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610bab578181015183820152602001610b93565b50505050905090810190601f168015610bd85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610c48576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610caa576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610cb660008383610e41565b600254610cc39082610bee565b6002556001600160a01b038216600090815260208190526040902054610ce99082610bee565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610d845760405162461bcd60e51b8152600401808060200182810382526021815260200180610f876021913960400191505060405180910390fd5b610d9082600083610e41565b610dcd81604051806060016040528060228152602001610ec7602291396001600160a01b0385166000908152602081905260409020549190610b57565b6001600160a01b038316600090815260208190526040902055600254610df39082610e46565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b3b151590565b505050565b600082821115610e9d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220b212f681aae3a839369df006b7b5ca6280b5bb82909bb3e14edfc182234e45d164736f6c63430007060033\",\n  \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806340c10f1911610097578063a457c2d711610066578063a457c2d7146102ff578063a9059cbb1461032b578063dd62ed3e14610357578063f77c479114610385576100f5565b806340c10f191461027957806370a08231146102a557806395d89b41146102cb5780639dc29fac146102d3576100f5565b806319ab453c116100d357806319ab453c146101d157806323b872dd146101f9578063313ce5671461022f578063395093511461024d576100f5565b806306fdde03146100fa578063095ea7b31461017757806318160ddd146101b7575b600080fd5b6101026103a9565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013c578181015183820152602001610124565b50505050905090810190601f1680156101695780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101a36004803603604081101561018d57600080fd5b506001600160a01b03813516906020013561043f565b604080519115158252519081900360200190f35b6101bf61045c565b60408051918252519081900360200190f35b6101f7600480360360208110156101e757600080fd5b50356001600160a01b0316610462565b005b6101a36004803603606081101561020f57600080fd5b506001600160a01b03813581169160208101359091169060400135610622565b6102376106a9565b6040805160ff9092168252519081900360200190f35b6101a36004803603604081101561026357600080fd5b506001600160a01b0381351690602001356106b2565b6101f76004803603604081101561028f57600080fd5b506001600160a01b038135169060200135610700565b6101bf600480360360208110156102bb57600080fd5b50356001600160a01b0316610761565b61010261077c565b6101f7600480360360408110156102e957600080fd5b506001600160a01b0381351690602001356107dd565b6101a36004803603604081101561031557600080fd5b506001600160a01b03813516906020013561083e565b6101a36004803603604081101561034157600080fd5b506001600160a01b0381351690602001356108a6565b6101bf6004803603604081101561036d57600080fd5b506001600160a01b03813581169160200135166108ba565b61038d6108e5565b604080516001600160a01b039092168252519081900360200190f35b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b820191906000526020600020905b81548152906001019060200180831161041857829003601f168201915b5050505050905090565b600061045361044c6108fb565b84846108ff565b50600192915050565b60025490565b60055462010000900460ff168061047c575061047c6109eb565b8061048f5750600554610100900460ff16155b6104ca5760405162461bcd60e51b815260040180806020018281038252602e815260200180610f31602e913960400191505060405180910390fd5b60055462010000900460ff161580156104fa576005805461ff001962ff0000199091166201000017166101001790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610577576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166105d2576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600580547fffffffffffffffffff0000000000000000000000000000000000000000ffffff1663010000006001600160a01b03851602179055801561061e576005805462ff0000191690555b5050565b600061062f8484846109fc565b61069f8461063b6108fb565b61069a85604051806060016040528060288152602001610f5f602891396001600160a01b038a166000908152600160205260408120906106796108fb565b6001600160a01b031681526020810191909152604001600020549190610b57565b6108ff565b5060019392505050565b60055460ff1690565b60006104536106bf6108fb565b8461069a85600160006106d06108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610bee565b600554630100000090046001600160a01b03163314610757576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610c4f565b6001600160a01b031660009081526020819052604090205490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b600554630100000090046001600160a01b03163314610834576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610d3f565b600061045361084b6108fb565b8461069a85604051806060016040528060258152602001610ff160259139600160006108756108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610b57565b60006104536108b36108fb565b84846109fc565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600554630100000090046001600160a01b031681565b3390565b6001600160a01b0383166109445760405162461bcd60e51b8152600401808060200182810382526024815260200180610fcd6024913960400191505060405180910390fd5b6001600160a01b0382166109895760405162461bcd60e51b8152600401808060200182810382526022815260200180610ee96022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60006109f630610e3b565b15905090565b6001600160a01b038316610a415760405162461bcd60e51b8152600401808060200182810382526025815260200180610fa86025913960400191505060405180910390fd5b6001600160a01b038216610a865760405162461bcd60e51b8152600401808060200182810382526023815260200180610ea46023913960400191505060405180910390fd5b610a91838383610e41565b610ace81604051806060016040528060268152602001610f0b602691396001600160a01b0386166000908152602081905260409020549190610b57565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610afd9082610bee565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610be65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610bab578181015183820152602001610b93565b50505050905090810190601f168015610bd85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610c48576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610caa576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610cb660008383610e41565b600254610cc39082610bee565b6002556001600160a01b038216600090815260208190526040902054610ce99082610bee565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610d845760405162461bcd60e51b8152600401808060200182810382526021815260200180610f876021913960400191505060405180910390fd5b610d9082600083610e41565b610dcd81604051806060016040528060228152602001610ec7602291396001600160a01b0385166000908152602081905260409020549190610b57565b6001600160a01b038316600090815260208190526040902055600254610df39082610e46565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b3b151590565b505050565b600082821115610e9d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220b212f681aae3a839369df006b7b5ca6280b5bb82909bb3e14edfc182234e45d164736f6c63430007060033\",\n  \"devdoc\": {\n    \"details\": \"value of power perpetual is expected to go down over time through the impact of funding\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"allowance(address,address)\": {\n        \"details\": \"See {IERC20-allowance}.\"\n      },\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC20-balanceOf}.\"\n      },\n      \"burn(address,uint256)\": {\n        \"params\": {\n          \"_account\": \"account to burn from\",\n          \"_amount\": \"amount to burn\"\n        }\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_name\": \"token name for ERC20\",\n          \"_symbol\": \"token symbol for ERC20\"\n        }\n      },\n      \"decimals()\": {\n        \"details\": \"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"\n      },\n      \"decreaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"\n      },\n      \"increaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"init(address)\": {\n        \"params\": {\n          \"_controller\": \"controller address\"\n        }\n      },\n      \"mint(address,uint256)\": {\n        \"params\": {\n          \"_account\": \"account to mint to\",\n          \"_amount\": \"amount to mint\"\n        }\n      },\n      \"name()\": {\n        \"details\": \"Returns the name of the token.\"\n      },\n      \"symbol()\": {\n        \"details\": \"Returns the symbol of the token, usually a shorter version of the name.\"\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC20-totalSupply}.\"\n      },\n      \"transfer(address,uint256)\": {\n        \"details\": \"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"burn(address,uint256)\": {\n        \"notice\": \"burn wPowerPerp\"\n      },\n      \"constructor\": {\n        \"notice\": \"long power perpetual constructor\"\n      },\n      \"init(address)\": {\n        \"notice\": \"init wPowerPerp contract\"\n      },\n      \"mint(address,uint256)\": {\n        \"notice\": \"mint wPowerPerp\"\n      }\n    },\n    \"notice\": \"ERC20 Token representing wrapped long power perpetual position\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 616,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_balances\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 622,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_allowances\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n      },\n      {\n        \"astId\": 624,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_totalSupply\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 626,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 628,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 630,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_decimals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint8\"\n      },\n      {\n        \"astId\": 540,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_initialized\",\n        \"offset\": 1,\n        \"slot\": \"5\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 543,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_initializing\",\n        \"offset\": 2,\n        \"slot\": \"5\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 10590,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"controller\",\n        \"offset\": 3,\n        \"slot\": \"5\",\n        \"type\": \"t_address\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => uint256))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_uint256)\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint8\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint8\",\n        \"numberOfBytes\": \"1\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/solcInputs/30afee76cfee2d4cc1c12451e0258499.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // Ceil A to a multiple m\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(sub(add(a, m), 1), m), m);\\n    }\\n\\n    // Floor A to a multiple m\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(a, m), m);\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {EIP712} from \\\"@openzeppelin/contracts/drafts/EIP712.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\nimport {ECDSA} from \\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * Crab V2 Error Codes:\\n * C1: Caller is not timelock\\n * C2: Contract not yet initialized\\n * C3: Invalid oracle address\\n * C4: Invalid timelock address\\n * C5: Invalid ETH:WSqueeth address\\n * C6: Invalid crabMigration address\\n * C7: Invalid hedge time threshold\\n * C8: Invalid hedge price threshold\\n * C9: Cannot receive ETH\\n * C10: Caller not Crab Migration contract\\n * C11: Crab V2 already initialized\\n * C12: Squeeth contracts not shut down\\n * C13: Crab must redeemShortShutdown\\n * C14: Twap period is too short\\n * C15: Price tolerance is too high\\n * C16: Deposit exceeds strategy cap\\n * C17: Clearing Price should be below bid price\\n * C18: Clearing Price should be above offer price\\n * C19: Invalid offer signature\\n * C20: Order has expired\\n * C21: Manager Price should be greater than 0\\n * C22: Not a valid Time or Price hedge\\n * C23: Orders must take the opposite side of the hedge\\n * C24: All orders must be either buying or selling\\n * C25: Orders are not arranged properly\\n * C26: Crab contracts shut down\\n *  C27: Nonce already used.\\n */\\n\\n/**\\n * @dev CrabStrategyV2 contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    // @dev OTC price must be within this distance of the uniswap twap price\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\n\\n    // @dev OTC price tolerance cannot exceed 20%\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\n\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n    /// @dev true if CrabV2 was initialized\\n    bool public isInitialized;\\n\\n    /// @dev typehash for signed orders\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\n        keccak256(\\n            \\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\"\\n        );\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:wSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable timelock;\\n    address public immutable crabMigration;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev wSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    /// @dev store the used flag for a nonce for each address\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct Order {\\n        uint256 bidId;\\n        address trader;\\n        uint256 quantity;\\n        uint256 price;\\n        bool isBuying;\\n        uint256 expiry;\\n        uint256 nonce;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event HedgeOTCSingle(\\n        address trader,\\n        uint256 bidId,\\n        uint256 quantity,\\n        uint256 price,\\n        bool isBuying,\\n        uint256 clearingPrice\\n    );\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\n\\n    modifier onlyTimelock() {\\n        require(msg.sender == timelock, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialization() {\\n        require(isInitialized, \\\"C2\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _timelock timelock contract address\\n     * @param _crabMigration crab migration contract address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        address _timelock,\\n        address _crabMigration,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold\\n    )\\n        StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy v2\\\", \\\"Crabv2\\\")\\n        StrategyFlashSwap(_uniswapFactory)\\n        EIP712(\\\"CrabOTC\\\", \\\"2\\\")\\n    {\\n        require(_oracle != address(0), \\\"C3\\\");\\n        require(_timelock != address(0), \\\"C4\\\");\\n        require(_ethWSqueethPool != address(0), \\\"C5\\\");\\n        require(_crabMigration != address(0), \\\"C6\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        timelock = _timelock;\\n        crabMigration = _crabMigration;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"C9\\\");\\n    }\\n\\n    /**\\n     * @notice initializes the collateral ratio after the first migration\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\n     * @param _crabSharesToMint crab shares to mint\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\n     * @param _strategyCap strategy cap for crab V2\\n     */\\n    function initialize(\\n        uint256 _wSqueethToMint,\\n        uint256 _crabSharesToMint,\\n        uint256 _timeAtLastHedge,\\n        uint256 _priceAtLastHedge,\\n        uint256 _strategyCap\\n    ) external payable {\\n        require(msg.sender == crabMigration, \\\"C10\\\");\\n        require(!isInitialized, \\\"C11\\\");\\n\\n        _setStrategyCap(_strategyCap);\\n\\n        uint256 amount = msg.value;\\n\\n        _checkStrategyCap(amount, 0);\\n\\n        // store hedge data from crab V1\\n        timeAtLastHedge = _timeAtLastHedge;\\n        priceAtLastHedge = _priceAtLastHedge;\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\n\\n        isInitialized = true;\\n    }\\n\\n    /**\\n     * @notice transfer vault NFT to new contract\\n     * @dev strategy cap is set to 0 to avoid future deposits\\n     * @param _newStrategy new strategy contract address\\n     */\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\n        _setStrategyCap(0);\\n\\n        emit VaultTransferred(_newStrategy, vaultId);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\n        _setStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice set strategy cap amount\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function _setStrategyCap(uint256 _capAmount) internal {\\n        strategyCap = _capAmount;\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external afterInitialization {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     * @param _poolFee Uniswap pool fee\\n     */\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _poolFee,\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\n     * @param _poolFee Uniswap pool fee\\n\\n     */\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _poolFee,\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"C12\\\");\\n        require(hasRedeemedInShutdown, \\\"C13\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice set nonce to true\\n     * @param _nonce the number to be set true\\n     */\\n    function setNonceTrue(uint256 _nonce) external {\\n        nonces[msg.sender][_nonce] = true;\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"C14\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\n     */\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\n        // Tolerance cannot be more than 20%\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\"C15\\\");\\n\\n        otcPriceTolerance = _otcPriceTolerance;\\n\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"C16\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            // will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            // return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\n\\n            // excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @dev set nonce flag of the trader to true\\n     * @param _trader address of the signer\\n     * @param _nonce number that is to be traded only once\\n     */\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\n        require(!nonces[_trader][_nonce], \\\"C27\\\");\\n        nonces[_trader][_nonce] = true;\\n    }\\n\\n    /**\\n     * @dev view function to get the domain seperator used in signing\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev check the signer and swap tokens in the order\\n     * @param _remainingAmount quantity the manager wants to trade\\n     * @param _clearingPrice the price at which all orders are traded\\n     * @param _order a signed order to swap tokens\\n     */\\n    function _execOrder(\\n        uint256 _remainingAmount,\\n        uint256 _clearingPrice,\\n        Order memory _order\\n    ) internal {\\n        // check that order beats clearing price\\n        if (_order.isBuying) {\\n            require(_clearingPrice <= _order.price, \\\"C17\\\");\\n        } else {\\n            require(_clearingPrice >= _order.price, \\\"C18\\\");\\n        }\\n\\n        _useNonce(_order.trader, _order.nonce);\\n        bytes32 structHash = keccak256(\\n            abi.encode(\\n                _CRAB_BALANCE_TYPEHASH,\\n                _order.bidId,\\n                _order.trader,\\n                _order.quantity,\\n                _order.price,\\n                _order.isBuying,\\n                _order.expiry,\\n                _order.nonce\\n            )\\n        );\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\n        require(offerSigner == _order.trader, \\\"C19\\\");\\n        require(_order.expiry >= block.timestamp, \\\"C20\\\");\\n\\n        // adjust quantity for partial fills\\n        if (_remainingAmount < _order.quantity) {\\n            _order.quantity = _remainingAmount;\\n        }\\n        // weth clearing price for the order\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\n\\n        if (_order.isBuying) {\\n            // trader sends weth and receives oSQTH\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\n            IWETH9(weth).withdraw(wethAmount);\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n        } else {\\n            // trader sends oSQTH and receives weth\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n            // wrap it\\n            IWETH9(weth).deposit{value: wethAmount}();\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\n        }\\n\\n        emit HedgeOTCSingle(\\n            _order.trader, // market maker\\n            _order.bidId,\\n            _order.quantity, // order oSQTH quantity\\n            _order.price, // order price\\n            _order.isBuying, // order direction\\n            _clearingPrice // executed price for order\\n        );\\n    }\\n\\n    /**\\n     * @dev hedge function to reduce delta using an array of signed orders\\n     * @param _totalQuantity quantity the manager wants to trade\\n     * @param _clearingPrice clearing price in weth\\n     * @param _isHedgeBuying direction of hedge trade\\n     * @param _orders an array of signed order to swap tokens\\n     */\\n    function hedgeOTC(\\n        uint256 _totalQuantity,\\n        uint256 _clearingPrice,\\n        bool _isHedgeBuying,\\n        Order[] memory _orders\\n    ) external onlyOwner afterInitialization {\\n        require(_clearingPrice > 0, \\\"C21\\\");\\n        require(_isTimeHedge() || _isPriceHedge(), \\\"C22\\\");\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = _clearingPrice;\\n\\n        uint256 remainingAmount = _totalQuantity;\\n        uint256 prevPrice = _orders[0].price;\\n        uint256 currentPrice = _orders[0].price;\\n        bool isOrderBuying = _orders[0].isBuying;\\n        require(_isHedgeBuying != isOrderBuying, \\\"C23\\\");\\n\\n        // iterate through order array and execute if valid\\n        for (uint256 i; i < _orders.length; ++i) {\\n            currentPrice = _orders[i].price;\\n            require(_orders[i].isBuying == isOrderBuying, \\\"C24\\\");\\n            if (_isHedgeBuying) {\\n                require(currentPrice >= prevPrice, \\\"C25\\\");\\n            } else {\\n                require(currentPrice <= prevPrice, \\\"C25\\\");\\n            }\\n            prevPrice = currentPrice;\\n\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\n\\n            if (remainingAmount > _orders[i].quantity) {\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\n            } else {\\n                break;\\n            }\\n        }\\n\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\n    }\\n\\n    /**\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\n     * @param _price clearing price provided by manager\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\n     */\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\n        // Get twap\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n\\n        if (_isHedgeBuying) {\\n            require(\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\n                \\\"Price too high relative to Uniswap twap.\\\"\\n            );\\n        } else {\\n            require(\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\n                \\\"Price too low relative to Uniswap twap.\\\"\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\n        require(!isShutdown, \\\"C26\\\");\\n\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n        );\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     */\\n    function _isTimeHedge() internal view returns (bool) {\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge() internal view returns (bool) {\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge() external view returns (bool) {\\n        return _isPriceHedge();\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkTimeHedge() external view returns (bool) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/drafts/EIP712.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = _getChainId();\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n        return keccak256(\\n            abi.encode(\\n                typeHash,\\n                name,\\n                version,\\n                _getChainId(),\\n                address(this)\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/cryptography/ECDSA.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        // Check the signature length\\n        if (signature.length != 65) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        }\\n\\n        // Divide the signature in r, s and v variables\\n        bytes32 r;\\n        bytes32 s;\\n        uint8 v;\\n\\n        // ecrecover takes the signature parameters, and the only way to get them\\n        // currently is to use assembly.\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            r := mload(add(signature, 0x20))\\n            s := mload(add(signature, 0x40))\\n            v := byte(0, mload(add(signature, 0x60)))\\n        }\\n\\n        return recover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n        require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n        return signer;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * replicates the behavior of the\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n     * JSON-RPC method.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\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) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/strategy/CrabHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {ICrabStrategyV2} from \\\"../interfaces/ICrabStrategyV2.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {StrategySwap} from \\\"./helper/StrategySwap.sol\\\";\\n\\n/**\\n * @dev CrabHelper contract\\n * @notice Contract for Crab helper functions\\n * @author Opyn team\\n */\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\n    using Address for address payable;\\n\\n    address public immutable crab;\\n    address public immutable weth;\\n\\n    event FlashDepositERC20(\\n        address indexed depositor,\\n        address depositedERC20,\\n        uint256 depositedAmount,\\n        uint256 depositedEthAmount,\\n        uint256 crabAmount,\\n        uint256 returnedEth\\n    );\\n\\n    event FlashWithdrawERC20(\\n        address indexed withdrawer,\\n        address withdrawnERC20,\\n        uint256 withdrawnAmount,\\n        uint256 withdrawnEthAmount,\\n        uint256 crabAmount\\n    );\\n\\n    /**\\n     * @notice constructor\\n     * @param _crab address of crabV2 contract\\n     * @param _swapRouter address of Uniswap swap router\\n     */\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\n        require(_crab != address(0), \\\"Invalid crab address\\\");\\n\\n        crab = _crab;\\n        weth = ICrabStrategyV2(_crab).weth();\\n    }\\n\\n    /**\\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\\n     * @param _ethToDeposit amount of ETH to deposit\\n     * @param _amountIn amount of ERC20 token to swap for weth\\n     * @param _minEthToGet min amount of ETH to receive in the swap\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     * @param _tokenIn ERC20 token to pay\\n     */\\n    function flashDepositERC20(\\n        uint256 _ethToDeposit,\\n        uint256 _amountIn,\\n        uint256 _minEthToGet,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee,\\n        address _tokenIn\\n    ) external nonReentrant {\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\\n\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\\n\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\n\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\n\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\n\\n        if (address(this).balance > 0) {\\n            payable(msg.sender).sendValue(address(this).balance);\\n        }\\n    }\\n\\n    /**\\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\\n     * @param _crabAmount amount of crab shares to withdraw\\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\\n     * @param _tokenOut ERC20 token to receive\\n     * @param _minAmountOut min amount of ERC20 to receive\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     */\\n    function flashWithdrawERC20(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        address _tokenOut,\\n        uint256 _minAmountOut,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee\\n    ) external nonReentrant {\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\n\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\\n\\n        uint256 ethBalance = address(this).balance;\\n        IWETH9(weth).deposit{value: ethBalance}();\\n        uint256 tokenReceived = _swapExactInputSingle(\\n            weth,\\n            _tokenOut,\\n            address(this),\\n            msg.sender,\\n            ethBalance,\\n            _minAmountOut,\\n            _erc20Fee\\n        );\\n\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crab, \\\"Cannot receive eth\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/ICrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\ninterface ICrabStrategyV2 {\\n    function wPowerPerp() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\\n\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/strategy/helper/StrategySwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract StrategySwap {\\n    ISwapRouter public immutable swapRouter;\\n\\n    constructor(address _swapRouter) {\\n        require(_swapRouter != address(0), \\\"invalid swap router address\\\");\\n        swapRouter = ISwapRouter(_swapRouter);\\n    }\\n\\n    /**\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _from from which user we are selling\\n     * @param _to Recipient to get the tokens\\n     * @param _amountIn Exact amount to sell\\n     * @param _minAmountOut Minimum amount to be paid\\n     * @param _fee pool fee\\n     * @return amountOut The amount of WETH9 received.\\n     */\\n    function _swapExactInputSingle(\\n        address _tokenIn,\\n        address _tokenOut,\\n        address _from,\\n        address _to,\\n        uint256 _amountIn,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) internal returns (uint256 amountOut) {\\n        // _from must approve this contract\\n\\n        // Transfer the specified amount of tokenIn to this contract.\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\n\\n        // Approve the router to spend tokenIn.\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\n\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\n            tokenIn: _tokenIn,\\n            tokenOut: _tokenOut,\\n            fee: _fee,\\n            recipient: _to,\\n            deadline: block.timestamp,\\n            amountIn: _amountIn,\\n            amountOutMinimum: _minAmountOut,\\n            sqrtPriceLimitX96: 0\\n        });\\n\\n        // The call to `exactInputSingle` executes the swap.\\n        amountOut = swapRouter.exactInputSingle(params);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabMigration.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport {IEulerExec, IDToken} from \\\"../interfaces/IEuler.sol\\\";\\nimport {WETH9} from \\\"../external/WETH9.sol\\\";\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// contract\\nimport {CrabStrategyV2} from \\\"./CrabStrategyV2.sol\\\";\\nimport {CrabStrategy} from \\\"./CrabStrategy.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * Migration Error Codes:\\n * M1: Migration already happened\\n * M2: Migration has not yet happened\\n * M3: msg.sender is not Euler Mainnet Contract\\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\\n * M5: Can't withdraw more than you own\\n * M6: Not enough ETH to repay the loan\\n * M7: Invalid crabV2 address\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\n * M10: Wrong migration function, use flashMigrateFromV1toV2\\n * M11: crabV2 address not yet set\\n */\\n\\n/**\\n * @dev CrabMigration contract\\n * @notice Contract for Migrating from Crab V1 to Crab V2\\n * @author Opyn team\\n */\\ncontract CrabMigration is Ownable {\\n    using SafeERC20 for IERC20;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    mapping(address => uint256) public sharesDeposited;\\n    bool public isMigrated;\\n\\n    address payable public crabV1;\\n    address payable public crabV2;\\n    address public immutable euler;\\n    address public immutable weth;\\n\\n    address immutable EULER_MAINNET;\\n    address immutable dToken;\\n    address immutable wPowerPerp;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    struct BatchMigrate {\\n        uint256 strategyCap;\\n    }\\n\\n    struct FlashMigrateV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFee;\\n    }\\n\\n    struct FlashMigrateAndBuyV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 withdrawMaxEthToPay;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFeeFlashDeposit;\\n    }\\n\\n    enum FLASH_SOURCE {\\n        BATCH_MIGRATE,\\n        FLASH_MIGRATE_V1_TO_V2,\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\n    }\\n\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\\n\\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\\n\\n    modifier beforeMigration() {\\n        require(!isMigrated, \\\"M1\\\");\\n        _;\\n    }\\n\\n    modifier afterMigration() {\\n        require(isMigrated, \\\"M2\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialized() {\\n        require(crabV2 != address(0), \\\"M11\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice migration constructor\\n     * @param _crabV1 address of crab V1\\n     * @param _weth address of weth\\n     * @param _eulerExec address of euler exec contract\\n     * @param _dToken address of euler liability token\\n     * @param _eulerMainnet address of euler deployment on mainnet\\n     */\\n    constructor(\\n        address payable _crabV1,\\n        address _weth,\\n        address _eulerExec,\\n        address _dToken,\\n        address _eulerMainnet\\n    ) {\\n        require(_eulerExec != address(0), \\\"invalid _eulerExec address\\\");\\n        require(_dToken != address(0), \\\"invalid _dToken address\\\");\\n        require(_eulerMainnet != address(0), \\\"invalid _eulerMainnet address\\\");\\n        require(_weth != address(0), \\\"invalid _weth address\\\");\\n        require(_crabV1 != address(0), \\\"invalid _crabv1 address\\\");\\n        require(IDToken(_dToken).underlyingAsset() == _weth, \\\"dToken underlying asset should be weth\\\");\\n\\n        crabV1 = _crabV1;\\n        euler = _eulerExec;\\n        EULER_MAINNET = _eulerMainnet;\\n        weth = _weth;\\n        dToken = _dToken;\\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\\n    }\\n\\n    /**\\n     * @notice set the crabV2 address\\n     * @param _crabV2 address of crab V2\\n     */\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\n        require(_crabV2 != address(0), \\\"M7\\\");\\n        crabV2 = _crabV2;\\n    }\\n\\n    /**\\n     * @notice deposit crab V1 shares in the pool for migration\\n     * @param _amount amount of crabV1 shares to deposit\\n     */\\n    function depositV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] += _amount;\\n\\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\\n\\n        emit DepositV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice withdraw crab V1 shares in the pool before migration\\n     * @param _amount amount of V1 shares to withdraw\\n     */\\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\\n\\n        emit WithdrawV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\\n     * the V2 contract at the same collateral ratio as the V1 contract\\n     * @param _strategyCap strategy cap in ETH\\n     */\\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\\n        // 1. update isMigrated\\n        isMigrated = true;\\n\\n        // 2. flash floan eth from euler eq to amt\\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: amountEthToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Euler callback function\\n     * @param encodedData callback data\\n     */\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\n        require(msg.sender == EULER_MAINNET, \\\"M3\\\");\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        // 1. borrow weth\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\n        WETH9(weth).withdraw(data.amountToBorrow);\\n\\n        // 2. callback\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\n\\n        // 3. repay the weth\\n        WETH9(weth).deposit{value: data.amountToBorrow}();\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     * @notice callback function for flash actions\\n     * @param _initiator address of original function caller\\n     * @param _amount  amount to pay back for flashswap\\n     * @param _callSource identifier for which function triggered callback\\n     * @param _calldata arbitrary data attached to callback\\n\\n     */\\n    function _flashCallback(\\n        address _initiator,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\\n\\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n\\n            // 2. mint osqth in crab V2\\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\\n                wSqueethToMint,\\n                crabV1Balance,\\n                timeAtLastHedge,\\n                priceAtLastHedge,\\n                data.strategyCap\\n            );\\n\\n            // 3. call withdraw from crab V1\\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\n\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n\\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\\n\\n            // flash deposit remaining ETH, otherwise refund\\n            // if CR1 = CR2 ethToFlashDeposit should be 0\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFee\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n            // send back V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\\n\\n            // find crab amount for contract's sqth balance\\n            // remaining crab can be withdrawn using flash withdraw\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\n\\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\\n\\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\n            require(address(this).balance >= _amount, \\\"M6\\\");\\n\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFeeFlashDeposit\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n\\n            // send V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back the excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares\\n     */\\n    function claimV2Shares() external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        sharesDeposited[msg.sender] = 0;\\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares and flash withdraw from crab V2\\n     * @param _amountToWithdraw V2 shares to claim\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee Uniswap pool fee for flash withdraw\\n     */\\n    function claimAndWithdraw(\\n        uint256 _amountToWithdraw,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        require(_amountToWithdraw <= amountV1Deposited, \\\"M5\\\");\\n\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\\n\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\n\\n        // send eth to user\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice view details of flash migration for specified amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function flashMigrationDetails(uint256 _v1Shares)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return _flashMigrationDetails(_v1Shares);\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\n     * @param _poolFee uniswap pool fee for flash deposit\\n     */\\n    function flashMigrateFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(isFlashOnlyMigrate, \\\"M9\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: ethNeededForV2,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateV1toV2({\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFee: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\\n     */\\n    function flashMigrateAndWithdrawFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint256 _ethToBorrow,\\n        uint256 _withdrawMaxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(!isFlashOnlyMigrate, \\\"M10\\\");\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\"M8\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: _ethToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateAndBuyV1toV2({\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFeeFlashDeposit: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice get migration details for given amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function _flashMigrationDetails(uint256 _v1Shares)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\\n\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\\n\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \\\"M4\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IEuler.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\ninterface IEulerExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IDToken {\\n    function underlyingAsset() external view returns (address);\\n\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\"\n    },\n    \"contracts/external/WETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\n\\ncontract WETH9 {\\n    string public name = \\\"Wrapped Ether\\\";\\n    string public symbol = \\\"WETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        payable(msg.sender).transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockEulerDToken.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockEulerDToken {\\n    ERC20 weth;\\n\\n    constructor(address _weth) {\\n        weth = ERC20(_weth);\\n    }\\n\\n    function borrow(uint256, uint256 amount) external {\\n        weth.transfer(msg.sender, amount);\\n    }\\n\\n    function repay(uint256, uint256 amount) external {\\n        weth.transferFrom(msg.sender, address(this), amount);\\n    }\\n\\n    function underlyingAsset() external view returns (address) {\\n        return address(weth);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockCrab.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockCrab is ERC20 {\\n    address operator;\\n    uint256 vaultId;\\n    uint256 collateral;\\n    uint256 short;\\n    address public wPowerPerp;\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    function setVaultDetails(\\n        uint256 _vaultId,\\n        uint256 _collateral,\\n        uint256 _short\\n    ) external {\\n        vaultId = _vaultId;\\n        collateral = _collateral;\\n        short = _short;\\n    }\\n\\n    function getVaultDetails()\\n        external\\n        view\\n        returns (\\n            address,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return (operator, vaultId, collateral, short);\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"C3\\\");\\n\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/solcInputs/56b4ec4ab07157f3d2fb7e1de805d93e.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 6.9 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //125% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(_tick);\\n\\n        // the following line is copied from the _modifyPosition function implemented by Uniswap core\\n        // we use the same logic to determine how much token0, token1 equals to given \\\"liquidity\\\"\\n        // https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/UniswapV3Pool.sol#L306\\n\\n        // use these 2 functions directly, because liquidity is always positive\\n        // getAmount0Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L209\\n        // getAmount1Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L225\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity >=0.5.0;\\n\\nimport './LowGasSafeMath.sol';\\nimport './SafeCast.sol';\\n\\nimport './FullMath.sol';\\nimport './UnsafeMath.sol';\\nimport './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 LowGasSafeMath for uint256;\\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            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            return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96).add(amount)));\\n        } else {\\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    /// @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                (\\n                    amount <= type(uint160).max\\n                        ? (amount << FixedPoint96.RESOLUTION) / liquidity\\n                        : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)\\n                );\\n\\n            return uint256(sqrtPX96).add(quotient).toUint160();\\n        } else {\\n            uint256 quotient =\\n                (\\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            return uint160(sqrtPX96 - quotient);\\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        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @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        return\\n            liquidity < 0\\n                ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\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        return\\n            liquidity < 0\\n                ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 6.9 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnOnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later AND MIT\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid power token controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, all uint to uint256, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    // strategy will only allow hedging if collateral to trade is at least 0.1% of the total strategy collateral\\n    uint256 public constant DELTA_HEDGE_THRESHOLD = 1e15;\\n\\n    uint256 public strategyCap;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public immutable hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public immutable hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public immutable auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for end sell auction (scaled 1e18)\\n    uint256 public immutable minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public immutable maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n    uint256 public auctionStartTime;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount, uint256 oldCapAmount);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"auction min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid auction min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"auction max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     * @return wSqueethToMint minted amount of wSqueeth\\n     * @return depositorCrabAmount minted amount of strategy token\\n     */\\n    function deposit() external payable nonReentrant returns (uint256, uint256) {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external payable nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @param _minWSqueeth minimum WSqueeth amount of profit if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount of profit if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        require(block.timestamp >= auctionTriggerTime, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime timestamp where auction started\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime alleged timestamp where auction was triggered\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        return (isTimeHedgeAllowed, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @dev _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        uint256 oldCap = strategyCap;\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount, oldCap);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price greater than max accepted price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price greater than min accepted price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"can not execute hedging trade as auction type changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Contract unsafe due to full liquidation\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + TWAP_PERIOD,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        uint256 collateralRatioToHedge = targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta);\\n\\n        require(collateralRatioToHedge > DELTA_HEDGE_THRESHOLD, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 850\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/solcInputs/c53867cdbf46138ab42de1c7a1689875.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // Ceil A to a multiple m\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(sub(add(a, m), 1), m), m);\\n    }\\n\\n    // Floor A to a multiple m\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(a, m), m);\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {EIP712} from \\\"@openzeppelin/contracts/drafts/EIP712.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\nimport {ECDSA} from \\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * Crab V2 Error Codes:\\n * C1: Caller is not timelock\\n * C2: Contract not yet initialized\\n * C3: Invalid oracle address\\n * C4: Invalid timelock address\\n * C5: Invalid ETH:WSqueeth address\\n * C6: Invalid crabMigration address\\n * C7: Invalid hedge time threshold\\n * C8: Invalid hedge price threshold\\n * C9: Cannot receive ETH\\n * C10: Caller not Crab Migration contract\\n * C11: Crab V2 already initialized\\n * C12: Squeeth contracts not shut down\\n * C13: Crab must redeemShortShutdown\\n * C14: Twap period is too short\\n * C15: Price tolerance is too high\\n * C16: Deposit exceeds strategy cap\\n * C17: Clearing Price should be below bid price\\n * C18: Clearing Price should be above offer price\\n * C19: Invalid offer signature\\n * C20: Order has expired\\n * C21: Manager Price should be greater than 0\\n * C22: Not a valid Time or Price hedge\\n * C23: Orders must take the opposite side of the hedge\\n * C24: All orders must be either buying or selling\\n * C25: Orders are not arranged properly\\n * C26: Crab contracts shut down\\n *  C27: Nonce already used.\\n */\\n\\n/**\\n * @dev CrabStrategyV2 contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    // @dev OTC price must be within this distance of the uniswap twap price\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\n\\n    // @dev OTC price tolerance cannot exceed 20%\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\n\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n    /// @dev true if CrabV2 was initialized\\n    bool public isInitialized;\\n\\n    /// @dev typehash for signed orders\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\n        keccak256(\\n            \\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\"\\n        );\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:wSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable timelock;\\n    address public immutable crabMigration;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev wSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    /// @dev store the used flag for a nonce for each address\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct Order {\\n        uint256 bidId;\\n        address trader;\\n        uint256 quantity;\\n        uint256 price;\\n        bool isBuying;\\n        uint256 expiry;\\n        uint256 nonce;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event HedgeOTCSingle(\\n        address trader,\\n        uint256 bidId,\\n        uint256 quantity,\\n        uint256 price,\\n        bool isBuying,\\n        uint256 clearingPrice\\n    );\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\n\\n    modifier onlyTimelock() {\\n        require(msg.sender == timelock, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialization() {\\n        require(isInitialized, \\\"C2\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _timelock timelock contract address\\n     * @param _crabMigration crab migration contract address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        address _timelock,\\n        address _crabMigration,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold\\n    )\\n        StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy v2\\\", \\\"Crabv2\\\")\\n        StrategyFlashSwap(_uniswapFactory)\\n        EIP712(\\\"CrabOTC\\\", \\\"2\\\")\\n    {\\n        require(_oracle != address(0), \\\"C3\\\");\\n        require(_timelock != address(0), \\\"C4\\\");\\n        require(_ethWSqueethPool != address(0), \\\"C5\\\");\\n        require(_crabMigration != address(0), \\\"C6\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        timelock = _timelock;\\n        crabMigration = _crabMigration;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"C9\\\");\\n    }\\n\\n    /**\\n     * @notice initializes the collateral ratio after the first migration\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\n     * @param _crabSharesToMint crab shares to mint\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\n     * @param _strategyCap strategy cap for crab V2\\n     */\\n    function initialize(\\n        uint256 _wSqueethToMint,\\n        uint256 _crabSharesToMint,\\n        uint256 _timeAtLastHedge,\\n        uint256 _priceAtLastHedge,\\n        uint256 _strategyCap\\n    ) external payable {\\n        require(msg.sender == crabMigration, \\\"C10\\\");\\n        require(!isInitialized, \\\"C11\\\");\\n\\n        _setStrategyCap(_strategyCap);\\n\\n        uint256 amount = msg.value;\\n\\n        _checkStrategyCap(amount, 0);\\n\\n        // store hedge data from crab V1\\n        timeAtLastHedge = _timeAtLastHedge;\\n        priceAtLastHedge = _priceAtLastHedge;\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\n\\n        isInitialized = true;\\n    }\\n\\n    /**\\n     * @notice transfer vault NFT to new contract\\n     * @dev strategy cap is set to 0 to avoid future deposits\\n     * @param _newStrategy new strategy contract address\\n     */\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\n        _setStrategyCap(0);\\n\\n        emit VaultTransferred(_newStrategy, vaultId);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\n        _setStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice set strategy cap amount\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function _setStrategyCap(uint256 _capAmount) internal {\\n        strategyCap = _capAmount;\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external afterInitialization {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     * @param _poolFee Uniswap pool fee\\n     */\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _poolFee,\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\n     * @param _poolFee Uniswap pool fee\\n\\n     */\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _poolFee,\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"C12\\\");\\n        require(hasRedeemedInShutdown, \\\"C13\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice set nonce to true\\n     * @param _nonce the number to be set true\\n     */\\n    function setNonceTrue(uint256 _nonce) external {\\n        nonces[msg.sender][_nonce] = true;\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"C14\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\n     */\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\n        // Tolerance cannot be more than 20%\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\"C15\\\");\\n\\n        otcPriceTolerance = _otcPriceTolerance;\\n\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"C16\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            // will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            // return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\n\\n            // excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @dev set nonce flag of the trader to true\\n     * @param _trader address of the signer\\n     * @param _nonce number that is to be traded only once\\n     */\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\n        require(!nonces[_trader][_nonce], \\\"C27\\\");\\n        nonces[_trader][_nonce] = true;\\n    }\\n\\n    /**\\n     * @dev view function to get the domain seperator used in signing\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev check the signer and swap tokens in the order\\n     * @param _remainingAmount quantity the manager wants to trade\\n     * @param _clearingPrice the price at which all orders are traded\\n     * @param _order a signed order to swap tokens\\n     */\\n    function _execOrder(\\n        uint256 _remainingAmount,\\n        uint256 _clearingPrice,\\n        Order memory _order\\n    ) internal {\\n        // check that order beats clearing price\\n        if (_order.isBuying) {\\n            require(_clearingPrice <= _order.price, \\\"C17\\\");\\n        } else {\\n            require(_clearingPrice >= _order.price, \\\"C18\\\");\\n        }\\n\\n        _useNonce(_order.trader, _order.nonce);\\n        bytes32 structHash = keccak256(\\n            abi.encode(\\n                _CRAB_BALANCE_TYPEHASH,\\n                _order.bidId,\\n                _order.trader,\\n                _order.quantity,\\n                _order.price,\\n                _order.isBuying,\\n                _order.expiry,\\n                _order.nonce\\n            )\\n        );\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\n        require(offerSigner == _order.trader, \\\"C19\\\");\\n        require(_order.expiry >= block.timestamp, \\\"C20\\\");\\n\\n        // adjust quantity for partial fills\\n        if (_remainingAmount < _order.quantity) {\\n            _order.quantity = _remainingAmount;\\n        }\\n        // weth clearing price for the order\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\n\\n        if (_order.isBuying) {\\n            // trader sends weth and receives oSQTH\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\n            IWETH9(weth).withdraw(wethAmount);\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n        } else {\\n            // trader sends oSQTH and receives weth\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n            // wrap it\\n            IWETH9(weth).deposit{value: wethAmount}();\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\n        }\\n\\n        emit HedgeOTCSingle(\\n            _order.trader, // market maker\\n            _order.bidId,\\n            _order.quantity, // order oSQTH quantity\\n            _order.price, // order price\\n            _order.isBuying, // order direction\\n            _clearingPrice // executed price for order\\n        );\\n    }\\n\\n    /**\\n     * @dev hedge function to reduce delta using an array of signed orders\\n     * @param _totalQuantity quantity the manager wants to trade\\n     * @param _clearingPrice clearing price in weth\\n     * @param _isHedgeBuying direction of hedge trade\\n     * @param _orders an array of signed order to swap tokens\\n     */\\n    function hedgeOTC(\\n        uint256 _totalQuantity,\\n        uint256 _clearingPrice,\\n        bool _isHedgeBuying,\\n        Order[] memory _orders\\n    ) external onlyOwner afterInitialization {\\n        require(_clearingPrice > 0, \\\"C21\\\");\\n        require(_isTimeHedge() || _isPriceHedge(), \\\"C22\\\");\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = _clearingPrice;\\n\\n        uint256 remainingAmount = _totalQuantity;\\n        uint256 prevPrice = _orders[0].price;\\n        uint256 currentPrice = _orders[0].price;\\n        bool isOrderBuying = _orders[0].isBuying;\\n        require(_isHedgeBuying != isOrderBuying, \\\"C23\\\");\\n\\n        // iterate through order array and execute if valid\\n        for (uint256 i; i < _orders.length; ++i) {\\n            currentPrice = _orders[i].price;\\n            require(_orders[i].isBuying == isOrderBuying, \\\"C24\\\");\\n            if (_isHedgeBuying) {\\n                require(currentPrice >= prevPrice, \\\"C25\\\");\\n            } else {\\n                require(currentPrice <= prevPrice, \\\"C25\\\");\\n            }\\n            prevPrice = currentPrice;\\n\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\n\\n            if (remainingAmount > _orders[i].quantity) {\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\n            } else {\\n                break;\\n            }\\n        }\\n\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\n    }\\n\\n    /**\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\n     * @param _price clearing price provided by manager\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\n     */\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\n        // Get twap\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n\\n        if (_isHedgeBuying) {\\n            require(\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\n                \\\"Price too high relative to Uniswap twap.\\\"\\n            );\\n        } else {\\n            require(\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\n                \\\"Price too low relative to Uniswap twap.\\\"\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\n        require(!isShutdown, \\\"C26\\\");\\n\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n        );\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     */\\n    function _isTimeHedge() internal view returns (bool) {\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge() internal view returns (bool) {\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge() external view returns (bool) {\\n        return _isPriceHedge();\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkTimeHedge() external view returns (bool) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/drafts/EIP712.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = _getChainId();\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n        return keccak256(\\n            abi.encode(\\n                typeHash,\\n                name,\\n                version,\\n                _getChainId(),\\n                address(this)\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/cryptography/ECDSA.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        // Check the signature length\\n        if (signature.length != 65) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        }\\n\\n        // Divide the signature in r, s and v variables\\n        bytes32 r;\\n        bytes32 s;\\n        uint8 v;\\n\\n        // ecrecover takes the signature parameters, and the only way to get them\\n        // currently is to use assembly.\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            r := mload(add(signature, 0x20))\\n            s := mload(add(signature, 0x40))\\n            v := byte(0, mload(add(signature, 0x60)))\\n        }\\n\\n        return recover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n        require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n        return signer;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * replicates the behavior of the\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n     * JSON-RPC method.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\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) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/strategy/CrabHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {ICrabStrategyV2} from \\\"../interfaces/ICrabStrategyV2.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {StrategySwap} from \\\"./helper/StrategySwap.sol\\\";\\n\\n/**\\n * @dev CrabHelper contract\\n * @notice Contract for Crab helper functions\\n * @author Opyn team\\n */\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\n    using Address for address payable;\\n\\n    address public immutable crab;\\n    address public immutable weth;\\n\\n    event FlashDepositERC20(\\n        address indexed depositor,\\n        address depositedERC20,\\n        uint256 depositedAmount,\\n        uint256 depositedEthAmount,\\n        uint256 crabAmount,\\n        uint256 returnedEth\\n    );\\n\\n    event FlashWithdrawERC20(\\n        address indexed withdrawer,\\n        address withdrawnERC20,\\n        uint256 withdrawnAmount,\\n        uint256 withdrawnEthAmount,\\n        uint256 crabAmount\\n    );\\n\\n    /**\\n     * @notice constructor\\n     * @param _crab address of crabV2 contract\\n     * @param _swapRouter address of Uniswap swap router\\n     */\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\n        require(_crab != address(0), \\\"Invalid crab address\\\");\\n\\n        crab = _crab;\\n        weth = ICrabStrategyV2(_crab).weth();\\n    }\\n\\n    /**\\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\\n     * @param _ethToDeposit amount of ETH to deposit\\n     * @param _amountIn amount of ERC20 token to swap for weth\\n     * @param _minEthToGet min amount of ETH to receive in the swap\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     * @param _tokenIn ERC20 token to pay\\n     */\\n    function flashDepositERC20(\\n        uint256 _ethToDeposit,\\n        uint256 _amountIn,\\n        uint256 _minEthToGet,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee,\\n        address _tokenIn\\n    ) external nonReentrant {\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\\n\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\\n\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\n\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\n\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\n\\n        if (address(this).balance > 0) {\\n            payable(msg.sender).sendValue(address(this).balance);\\n        }\\n    }\\n\\n    /**\\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\\n     * @param _crabAmount amount of crab shares to withdraw\\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\\n     * @param _tokenOut ERC20 token to receive\\n     * @param _minAmountOut min amount of ERC20 to receive\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     */\\n    function flashWithdrawERC20(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        address _tokenOut,\\n        uint256 _minAmountOut,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee\\n    ) external nonReentrant {\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\n\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\\n\\n        uint256 ethBalance = address(this).balance;\\n        IWETH9(weth).deposit{value: ethBalance}();\\n        uint256 tokenReceived = _swapExactInputSingle(\\n            weth,\\n            _tokenOut,\\n            address(this),\\n            msg.sender,\\n            ethBalance,\\n            _minAmountOut,\\n            _erc20Fee\\n        );\\n\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crab, \\\"Cannot receive eth\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/ICrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\ninterface ICrabStrategyV2 {\\n    function wPowerPerp() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\\n\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/strategy/helper/StrategySwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract StrategySwap {\\n    ISwapRouter public immutable swapRouter;\\n\\n    constructor(address _swapRouter) {\\n        require(_swapRouter != address(0), \\\"invalid swap router address\\\");\\n        swapRouter = ISwapRouter(_swapRouter);\\n    }\\n\\n    /**\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _from from which user we are selling\\n     * @param _to Recipient to get the tokens\\n     * @param _amountIn Exact amount to sell\\n     * @param _minAmountOut Minimum amount to be paid\\n     * @param _fee pool fee\\n     * @return amountOut The amount of WETH9 received.\\n     */\\n    function _swapExactInputSingle(\\n        address _tokenIn,\\n        address _tokenOut,\\n        address _from,\\n        address _to,\\n        uint256 _amountIn,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) internal returns (uint256 amountOut) {\\n        // _from must approve this contract\\n\\n        // Transfer the specified amount of tokenIn to this contract.\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\n\\n        // Approve the router to spend tokenIn.\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\n\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\n            tokenIn: _tokenIn,\\n            tokenOut: _tokenOut,\\n            fee: _fee,\\n            recipient: _to,\\n            deadline: block.timestamp,\\n            amountIn: _amountIn,\\n            amountOutMinimum: _minAmountOut,\\n            sqrtPriceLimitX96: 0\\n        });\\n\\n        // The call to `exactInputSingle` executes the swap.\\n        amountOut = swapRouter.exactInputSingle(params);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabMigration.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport {IEulerExec, IDToken} from \\\"../interfaces/IEuler.sol\\\";\\nimport {WETH9} from \\\"../external/WETH9.sol\\\";\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// contract\\nimport {CrabStrategyV2} from \\\"./CrabStrategyV2.sol\\\";\\nimport {CrabStrategy} from \\\"./CrabStrategy.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * Migration Error Codes:\\n * M1: Migration already happened\\n * M2: Migration has not yet happened\\n * M3: msg.sender is not Euler Mainnet Contract\\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\\n * M5: Can't withdraw more than you own\\n * M6: Not enough ETH to repay the loan\\n * M7: Invalid crabV2 address\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\n * M10: Wrong migration function, use flashMigrateFromV1toV2\\n * M11: crabV2 address not yet set\\n */\\n\\n/**\\n * @dev CrabMigration contract\\n * @notice Contract for Migrating from Crab V1 to Crab V2\\n * @author Opyn team\\n */\\ncontract CrabMigration is Ownable {\\n    using SafeERC20 for IERC20;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    mapping(address => uint256) public sharesDeposited;\\n    bool public isMigrated;\\n\\n    address payable public crabV1;\\n    address payable public crabV2;\\n    address public immutable euler;\\n    address public immutable weth;\\n\\n    address immutable EULER_MAINNET;\\n    address immutable dToken;\\n    address immutable wPowerPerp;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    struct BatchMigrate {\\n        uint256 strategyCap;\\n    }\\n\\n    struct FlashMigrateV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFee;\\n    }\\n\\n    struct FlashMigrateAndBuyV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 withdrawMaxEthToPay;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFeeFlashDeposit;\\n    }\\n\\n    enum FLASH_SOURCE {\\n        BATCH_MIGRATE,\\n        FLASH_MIGRATE_V1_TO_V2,\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\n    }\\n\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\\n\\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\\n\\n    modifier beforeMigration() {\\n        require(!isMigrated, \\\"M1\\\");\\n        _;\\n    }\\n\\n    modifier afterMigration() {\\n        require(isMigrated, \\\"M2\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialized() {\\n        require(crabV2 != address(0), \\\"M11\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice migration constructor\\n     * @param _crabV1 address of crab V1\\n     * @param _weth address of weth\\n     * @param _eulerExec address of euler exec contract\\n     * @param _dToken address of euler liability token\\n     * @param _eulerMainnet address of euler deployment on mainnet\\n     */\\n    constructor(\\n        address payable _crabV1,\\n        address _weth,\\n        address _eulerExec,\\n        address _dToken,\\n        address _eulerMainnet\\n    ) {\\n        require(_eulerExec != address(0), \\\"invalid _eulerExec address\\\");\\n        require(_dToken != address(0), \\\"invalid _dToken address\\\");\\n        require(_eulerMainnet != address(0), \\\"invalid _eulerMainnet address\\\");\\n        require(_weth != address(0), \\\"invalid _weth address\\\");\\n        require(_crabV1 != address(0), \\\"invalid _crabv1 address\\\");\\n        require(IDToken(_dToken).underlyingAsset() == _weth, \\\"dToken underlying asset should be weth\\\");\\n\\n        crabV1 = _crabV1;\\n        euler = _eulerExec;\\n        EULER_MAINNET = _eulerMainnet;\\n        weth = _weth;\\n        dToken = _dToken;\\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\\n    }\\n\\n    /**\\n     * @notice set the crabV2 address\\n     * @param _crabV2 address of crab V2\\n     */\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\n        require(_crabV2 != address(0), \\\"M7\\\");\\n        crabV2 = _crabV2;\\n    }\\n\\n    /**\\n     * @notice deposit crab V1 shares in the pool for migration\\n     * @param _amount amount of crabV1 shares to deposit\\n     */\\n    function depositV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] += _amount;\\n\\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\\n\\n        emit DepositV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice withdraw crab V1 shares in the pool before migration\\n     * @param _amount amount of V1 shares to withdraw\\n     */\\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\\n\\n        emit WithdrawV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\\n     * the V2 contract at the same collateral ratio as the V1 contract\\n     * @param _strategyCap strategy cap in ETH\\n     */\\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\\n        // 1. update isMigrated\\n        isMigrated = true;\\n\\n        // 2. flash floan eth from euler eq to amt\\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: amountEthToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Euler callback function\\n     * @param encodedData callback data\\n     */\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\n        require(msg.sender == EULER_MAINNET, \\\"M3\\\");\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        // 1. borrow weth\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\n        WETH9(weth).withdraw(data.amountToBorrow);\\n\\n        // 2. callback\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\n\\n        // 3. repay the weth\\n        WETH9(weth).deposit{value: data.amountToBorrow}();\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     * @notice callback function for flash actions\\n     * @param _initiator address of original function caller\\n     * @param _amount  amount to pay back for flashswap\\n     * @param _callSource identifier for which function triggered callback\\n     * @param _calldata arbitrary data attached to callback\\n\\n     */\\n    function _flashCallback(\\n        address _initiator,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\\n\\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n\\n            // 2. mint osqth in crab V2\\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\\n                wSqueethToMint,\\n                crabV1Balance,\\n                timeAtLastHedge,\\n                priceAtLastHedge,\\n                data.strategyCap\\n            );\\n\\n            // 3. call withdraw from crab V1\\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\n\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n\\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\\n\\n            // flash deposit remaining ETH, otherwise refund\\n            // if CR1 = CR2 ethToFlashDeposit should be 0\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFee\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n            // send back V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\\n\\n            // find crab amount for contract's sqth balance\\n            // remaining crab can be withdrawn using flash withdraw\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\n\\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\\n\\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\n            require(address(this).balance >= _amount, \\\"M6\\\");\\n\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFeeFlashDeposit\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n\\n            // send V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back the excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares\\n     */\\n    function claimV2Shares() external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        sharesDeposited[msg.sender] = 0;\\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares and flash withdraw from crab V2\\n     * @param _amountToWithdraw V2 shares to claim\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee Uniswap pool fee for flash withdraw\\n     */\\n    function claimAndWithdraw(\\n        uint256 _amountToWithdraw,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        require(_amountToWithdraw <= amountV1Deposited, \\\"M5\\\");\\n\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\\n\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\n\\n        // send eth to user\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice view details of flash migration for specified amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function flashMigrationDetails(uint256 _v1Shares)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return _flashMigrationDetails(_v1Shares);\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\n     * @param _poolFee uniswap pool fee for flash deposit\\n     */\\n    function flashMigrateFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(isFlashOnlyMigrate, \\\"M9\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: ethNeededForV2,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateV1toV2({\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFee: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\\n     */\\n    function flashMigrateAndWithdrawFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint256 _ethToBorrow,\\n        uint256 _withdrawMaxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(!isFlashOnlyMigrate, \\\"M10\\\");\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\"M8\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: _ethToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateAndBuyV1toV2({\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFeeFlashDeposit: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice get migration details for given amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function _flashMigrationDetails(uint256 _v1Shares)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\\n\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\\n\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \\\"M4\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IEuler.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\ninterface IEulerExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IDToken {\\n    function underlyingAsset() external view returns (address);\\n\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\"\n    },\n    \"contracts/external/WETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\n\\ncontract WETH9 {\\n    string public name = \\\"Wrapped Ether\\\";\\n    string public symbol = \\\"WETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        payable(msg.sender).transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract MockErc20 is ERC20, Ownable {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external onlyOwner {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockEulerDToken.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockEulerDToken {\\n    ERC20 weth;\\n\\n    constructor(address _weth) {\\n        weth = ERC20(_weth);\\n    }\\n\\n    function borrow(uint256, uint256 amount) external {\\n        weth.transfer(msg.sender, amount);\\n    }\\n\\n    function repay(uint256, uint256 amount) external {\\n        weth.transferFrom(msg.sender, address(this), amount);\\n    }\\n\\n    function underlyingAsset() external view returns (address) {\\n        return address(weth);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockCrab.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockCrab is ERC20 {\\n    address operator;\\n    uint256 vaultId;\\n    uint256 collateral;\\n    uint256 short;\\n    address public wPowerPerp;\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    function setVaultDetails(\\n        uint256 _vaultId,\\n        uint256 _collateral,\\n        uint256 _short\\n    ) external {\\n        vaultId = _vaultId;\\n        collateral = _collateral;\\n        short = _short;\\n    }\\n\\n    function getVaultDetails()\\n        external\\n        view\\n        returns (\\n            address,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return (operator, vaultId, collateral, short);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"C3\\\");\\n\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/solcInputs/d97d3d4b09e0d70518330d405a7dd9ff.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 6.9 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 6.9 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnOnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid power token controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, all uint to uint256, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    // strategy will only allow hedging if collateral to trade is at least 0.1% of the total strategy collateral\\n    uint256 public constant DELTA_HEDGE_THRESHOLD = 1e15;\\n\\n    uint256 public strategyCap;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public immutable hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public immutable hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public immutable auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for end sell auction (scaled 1e18)\\n    uint256 public immutable minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public immutable maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n    uint256 public auctionStartTime;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool public hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount, uint256 oldCapAmount);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"auction min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid auction min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"auction max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     * @return wSqueethToMint minted amount of wSqueeth\\n     * @return depositorCrabAmount minted amount of strategy token\\n     */\\n    function deposit() external payable nonReentrant returns (uint256, uint256) {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external payable nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts are not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Strategy has not redeemed vault proceeds\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @param _minWSqueeth minimum WSqueeth amount of profit if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount of profit if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        require(block.timestamp >= auctionTriggerTime, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime timestamp where auction started\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime alleged timestamp where auction was triggered\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        return (isTimeHedgeAllowed, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @dev _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        uint256 oldCap = strategyCap;\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount, oldCap);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price greater than max accepted price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price greater than min accepted price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"can not execute hedging trade as auction type changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(\\n                totalSupply() == 0,\\n                \\\"Crab strategy shut down due to full liquidation or shutdown of squeeth contracts\\\"\\n            );\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + TWAP_PERIOD,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        uint256 collateralRatioToHedge = targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta);\\n\\n        require(collateralRatioToHedge > DELTA_HEDGE_THRESHOLD, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 825\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/solcInputs/e85d9fda89ae8c3780a8ae01da3f423c.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/strategy/timelock/Timelock.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity =0.8.10;\\n\\nimport \\\"./SafeMath.sol\\\";\\n\\ncontract Timelock {\\n    using SafeMath for uint;\\n\\n    event NewAdmin(address indexed newAdmin);\\n    event NewPendingAdmin(address indexed newPendingAdmin);\\n    event NewDelay(uint indexed newDelay);\\n    event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature,  bytes data, uint eta);\\n    event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature,  bytes data, uint eta);\\n    event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);\\n\\n    uint public constant GRACE_PERIOD = 14 days;\\n    uint public constant MINIMUM_DELAY = 2 days;\\n    uint public constant MAXIMUM_DELAY = 30 days;\\n\\n    address public admin;\\n    address public pendingAdmin;\\n    uint public delay;\\n\\n    mapping (bytes32 => bool) public queuedTransactions;\\n\\n\\n    constructor(address admin_, uint delay_) public {\\n        require(delay_ >= MINIMUM_DELAY, \\\"Timelock::constructor: Delay must exceed minimum delay.\\\");\\n        require(delay_ <= MAXIMUM_DELAY, \\\"Timelock::setDelay: Delay must not exceed maximum delay.\\\");\\n\\n        admin = admin_;\\n        delay = delay_;\\n    }\\n\\n    fallback() external payable { }\\n\\n    function setDelay(uint delay_) public {\\n        require(msg.sender == address(this), \\\"Timelock::setDelay: Call must come from Timelock.\\\");\\n        require(delay_ >= MINIMUM_DELAY, \\\"Timelock::setDelay: Delay must exceed minimum delay.\\\");\\n        require(delay_ <= MAXIMUM_DELAY, \\\"Timelock::setDelay: Delay must not exceed maximum delay.\\\");\\n        delay = delay_;\\n\\n        emit NewDelay(delay);\\n    }\\n\\n    function acceptAdmin() public {\\n        require(msg.sender == pendingAdmin, \\\"Timelock::acceptAdmin: Call must come from pendingAdmin.\\\");\\n        admin = msg.sender;\\n        pendingAdmin = address(0);\\n\\n        emit NewAdmin(admin);\\n    }\\n\\n    function setPendingAdmin(address pendingAdmin_) public {\\n        require(msg.sender == address(this), \\\"Timelock::setPendingAdmin: Call must come from Timelock.\\\");\\n        pendingAdmin = pendingAdmin_;\\n\\n        emit NewPendingAdmin(pendingAdmin);\\n    }\\n\\n    function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) {\\n        require(msg.sender == admin, \\\"Timelock::queueTransaction: Call must come from admin.\\\");\\n        require(eta >= getBlockTimestamp().add(delay), \\\"Timelock::queueTransaction: Estimated execution block must satisfy delay.\\\");\\n\\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\\n        queuedTransactions[txHash] = true;\\n\\n        emit QueueTransaction(txHash, target, value, signature, data, eta);\\n        return txHash;\\n    }\\n\\n    function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public {\\n        require(msg.sender == admin, \\\"Timelock::cancelTransaction: Call must come from admin.\\\");\\n\\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\\n        queuedTransactions[txHash] = false;\\n\\n        emit CancelTransaction(txHash, target, value, signature, data, eta);\\n    }\\n\\n    function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) {\\n        require(msg.sender == admin, \\\"Timelock::executeTransaction: Call must come from admin.\\\");\\n\\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\\n        require(queuedTransactions[txHash], \\\"Timelock::executeTransaction: Transaction hasn't been queued.\\\");\\n        require(getBlockTimestamp() >= eta, \\\"Timelock::executeTransaction: Transaction hasn't surpassed time lock.\\\");\\n        require(getBlockTimestamp() <= eta.add(GRACE_PERIOD), \\\"Timelock::executeTransaction: Transaction is stale.\\\");\\n\\n        queuedTransactions[txHash] = false;\\n\\n        bytes memory callData;\\n\\n        if (bytes(signature).length == 0) {\\n            callData = data;\\n        } else {\\n            callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);\\n        }\\n\\n        // solium-disable-next-line security/no-call-value\\n        (bool success, bytes memory returnData) = target.call{value: value}(callData);\\n        require(success, \\\"Timelock::executeTransaction: Transaction execution reverted.\\\");\\n\\n        emit ExecuteTransaction(txHash, target, value, signature, data, eta);\\n\\n        return returnData;\\n    }\\n\\n    function getBlockTimestamp() internal view returns (uint) {\\n        // solium-disable-next-line security/no-block-members\\n        return block.timestamp;\\n    }\\n}\"\n    },\n    \"contracts/strategy/timelock/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity =0.8.10;\\n\\n// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol\\n// Subject to the MIT license.\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c;\\n        unchecked { c = a + b; }\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        uint256 c;\\n        unchecked { c = a + b; }\\n        require(c >= a, errorMessage);\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     * - Subtraction cannot underflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return sub(a, b, \\\"SafeMath: subtraction underflow\\\");\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     * - Subtraction cannot underflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        uint256 c = a - b;\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) {\\n            return 0;\\n        }\\n\\n        uint256 c;\\n        unchecked { c = a * b; }\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) {\\n            return 0;\\n        }\\n\\n        uint256 c;\\n        unchecked { c = a * b; }\\n        require(c / a == b, errorMessage);\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers.\\n     * Reverts on division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return div(a, b, \\\"SafeMath: division by zero\\\");\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers.\\n     * Reverts with custom message on division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        // Solidity only automatically asserts when dividing by 0\\n        require(b > 0, errorMessage);\\n        uint256 c = a / b;\\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * Reverts when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * Reverts with custom message when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b != 0, errorMessage);\\n        return a % b;\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": false,\n      \"runs\": 200\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/mainnet/solcInputs/fc32ed9e00a9017e491333926bef5473.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/.chainId",
    "content": "421611"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/Controller.json",
    "content": "{\n    \"address\": \"0x6FBbc7eBd7E421839915e8e4fAcC9947dC32F4dE\",\n    \"abi\": [\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amount\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"vaultId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"BurnShort\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"vaultId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"CloseVault\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amount\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint128\",\n                    \"name\": \"collateralId\",\n                    \"type\": \"uint128\"\n                }\n            ],\n            \"name\": \"DepositCollateral\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"DepositUniPositionToken\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"oldFee\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"newFee\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"FeeRateUpdated\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"address\",\n                    \"name\": \"oldFeeRecipient\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"address\",\n                    \"name\": \"newFeeRecipient\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"FeeRecipientUpdated\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"debtAmount\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"collateralPaid\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"Liquidate\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amount\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"vaultId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"MintShort\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"oldNormFactor\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"newNormFactor\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"timestamp\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"NormalizationFactorUpdated\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"vaultId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"OpenVault\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"previousOwner\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"newOwner\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"OwnershipTransferred\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"address\",\n                    \"name\": \"operator\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"UpdateOperator\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amount\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint128\",\n                    \"name\": \"collateralId\",\n                    \"type\": \"uint128\"\n                }\n            ],\n            \"name\": \"WithdrawCollateral\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"WithdrawUniPositionToken\",\n            \"type\": \"event\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"PAUSE_TIME_LIMIT\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"applyFunding\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_powerPerpAmount\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_withdrawAmount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"burnPowerPerpAmount\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_wPowerPerpAmount\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_withdrawAmount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"burnWPowerPerpAmount\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"dai\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"deployTimestamp\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"deposit\",\n            \"outputs\": [],\n            \"stateMutability\": \"payable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_uniTokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"depositUniPositionToken\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"donate\",\n            \"outputs\": [],\n            \"stateMutability\": \"payable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"ethDaiPool\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"feeRate\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"feeRecipient\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint32\",\n                    \"name\": \"_period\",\n                    \"type\": \"uint32\"\n                }\n            ],\n            \"name\": \"getDenormalizedMark\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"getExpectedNormalizationFactor\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint32\",\n                    \"name\": \"_period\",\n                    \"type\": \"uint32\"\n                }\n            ],\n            \"name\": \"getIndex\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"indexForSettlement\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_oracle\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_vaultNFT\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_wPowerPerp\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_weth\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_dai\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_ethDaiPool\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_wPowerPerpPool\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_uniPositionManager\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"init\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"isShutDown\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"isSystemPaused\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"isVaultSafe\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"isWethToken0\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"lastFundingUpdateTimestamp\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"lastPauseTime\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_maxDebtAmount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"liquidate\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint128\",\n                    \"name\": \"_powerPerpAmount\",\n                    \"type\": \"uint128\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_uniTokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"mintPowerPerpAmount\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"payable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint128\",\n                    \"name\": \"_wPowerPerpAmount\",\n                    \"type\": \"uint128\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_uniTokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"mintWPowerPerpAmount\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"payable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"normalizationFactor\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"oracle\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"contract IOracle\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"owner\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"pause\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"pauseAndShutDown\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"pausesLeft\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_wPerpAmount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"redeemLong\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"redeemShort\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"reduceDebt\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"renounceOwnership\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_newFeeRate\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"setFeeRate\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_newFeeRecipient\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"setFeeRecipient\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"shutDown\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"newOwner\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"transferOwnership\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"unPauseAnyone\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"unPauseOwner\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"uniswapPositionManager\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_operator\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"updateOperator\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"vaultNFT\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"contract IVaultManagerNFT\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"vaults\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"operator\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint32\",\n                    \"name\": \"NftCollateralId\",\n                    \"type\": \"uint32\"\n                },\n                {\n                    \"internalType\": \"uint96\",\n                    \"name\": \"collateralAmount\",\n                    \"type\": \"uint96\"\n                },\n                {\n                    \"internalType\": \"uint128\",\n                    \"name\": \"shortAmount\",\n                    \"type\": \"uint128\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"wPowerPerp\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"contract IWPowerPerp\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"wPowerPerpPool\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"weth\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"withdraw\",\n            \"outputs\": [],\n            \"stateMutability\": \"payable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"withdrawUniPositionToken\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"stateMutability\": \"payable\",\n            \"type\": \"receive\"\n        }\n    ],\n    \"transactionHash\": \"0x3dd8d592301d27acba4692c5696ab7eca74bf81f46e5a8510e41424c34043399\",\n    \"receipt\": {\n        \"to\": null,\n        \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n        \"contractAddress\": \"0x6FBbc7eBd7E421839915e8e4fAcC9947dC32F4dE\",\n        \"transactionIndex\": 0,\n        \"gasUsed\": \"38738642\",\n        \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000200000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000020000000000000000000000000000000040000000000000000000000000000000000\",\n        \"blockHash\": \"0x1974b7282c91ec1d1f30ab3ef7a15f69b767032cd9a991a9dbcdeaed28389937\",\n        \"transactionHash\": \"0x3dd8d592301d27acba4692c5696ab7eca74bf81f46e5a8510e41424c34043399\",\n        \"logs\": [\n            {\n                \"transactionIndex\": 0,\n                \"blockNumber\": 5750462,\n                \"transactionHash\": \"0x3dd8d592301d27acba4692c5696ab7eca74bf81f46e5a8510e41424c34043399\",\n                \"address\": \"0x6FBbc7eBd7E421839915e8e4fAcC9947dC32F4dE\",\n                \"topics\": [\n                    \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n                    \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n                    \"0x0000000000000000000000005599b4eaddd319e2f462b27fc8378b0bfad309ca\"\n                ],\n                \"data\": \"0x\",\n                \"logIndex\": 0,\n                \"blockHash\": \"0x1974b7282c91ec1d1f30ab3ef7a15f69b767032cd9a991a9dbcdeaed28389937\"\n            }\n        ],\n        \"blockNumber\": 5750462,\n        \"cumulativeGasUsed\": \"796002\",\n        \"status\": 1,\n        \"byzantium\": true\n    },\n    \"args\": [],\n    \"solcInputHash\": \"49c79f88c6e4ede6ca1f2ffd46fef4fe\",\n    \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"BurnShort\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"CloseVault\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"collateralId\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"name\\\":\\\"DepositCollateral\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"DepositUniPositionToken\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"oldFee\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newFee\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FeeRateUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"oldFeeRecipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newFeeRecipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"FeeRecipientUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"debtAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralPaid\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Liquidate\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"MintShort\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"oldNormFactor\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newNormFactor\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"timestamp\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"NormalizationFactorUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"OpenVault\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"UpdateOperator\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"collateralId\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"name\\\":\\\"WithdrawCollateral\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawUniPositionToken\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"PAUSE_TIME_LIMIT\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"applyFunding\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burnPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burnWPowerPerpAmount\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"dai\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"deployTimestamp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"deposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"depositUniPositionToken\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"donate\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"ethDaiPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"feeRate\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"feeRecipient\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getDenormalizedMark\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getExpectedNormalizationFactor\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"indexForSettlement\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_oracle\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_vaultNFT\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wPowerPerp\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_weth\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_dai\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_ethDaiPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniPositionManager\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"init\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isShutDown\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isSystemPaused\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"isVaultSafe\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isWethToken0\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"lastFundingUpdateTimestamp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"lastPauseTime\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxDebtAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"liquidate\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mintPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mintWPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"normalizationFactor\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"oracle\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IOracle\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"pause\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"pauseAndShutDown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"pausesLeft\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"redeemLong\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"redeemShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"reduceDebt\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_newFeeRate\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setFeeRate\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_newFeeRecipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"setFeeRecipient\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"shutDown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"unPauseAnyone\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"unPauseOwner\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"uniswapPositionManager\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"updateOperator\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"vaultNFT\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IVaultManagerNFT\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"vaults\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"NftCollateralId\\\",\\\"type\\\":\\\"uint32\\\"},{\\\"internalType\\\":\\\"uint96\\\",\\\"name\\\":\\\"collateralAmount\\\",\\\"type\\\":\\\"uint96\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"shortAmount\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IWPowerPerp\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdrawUniPositionToken\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"applyFunding()\\\":{\\\"details\\\":\\\"update the normalization factor as a way to pay funding.\\\"},\\\"burnPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_powerPerpAmount\\\":\\\"amount of powerPerp to burn\\\",\\\"_vaultId\\\":\\\"id of the vault\\\",\\\"_withdrawAmount\\\":\\\"amount of eth to withdraw\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"amount of wPowerPerp burned\\\"}},\\\"burnWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to burn\\\",\\\"_withdrawAmount\\\":\\\"amount of eth to withdraw\\\"}},\\\"deposit(uint256)\\\":{\\\"details\\\":\\\"deposit collateral into a vault\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"depositUniPositionToken(uint256,uint256)\\\":{\\\"params\\\":{\\\"_uniTokenId\\\":\\\"uniswap v3 position token id\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"getDenormalizedMark(uint32)\\\":{\\\"params\\\":{\\\"_period\\\":\\\"period which you want to calculate twap with\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"mark price denominated in $USD, scaled by 1e18\\\"}},\\\"getExpectedNormalizationFactor()\\\":{\\\"details\\\":\\\"can be used for on-chain and off-chain calculations\\\"},\\\"getIndex(uint32)\\\":{\\\"params\\\":{\\\"_period\\\":\\\"period which you want to calculate twap with\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"index price denominated in $USD, scaled by 1e18\\\"}},\\\"init(address,address,address,address,address,address,address,address)\\\":{\\\"params\\\":{\\\"_dai\\\":\\\"dai address\\\",\\\"_ethDaiPool\\\":\\\"uniswap v3 pool for weth / dai\\\",\\\"_oracle\\\":\\\"oracle address\\\",\\\"_uniPositionManager\\\":\\\"uniswap v3 nonfungible position manager address\\\",\\\"_vaultNFT\\\":\\\"erc721 token address representing the short position\\\",\\\"_wPowerPerp\\\":\\\"erc20 token address representing non-rebasing long position\\\",\\\"_wPowerPerpPool\\\":\\\"uniswap v3 pool for wPowerPerp / weth\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"isVaultSafe(uint256)\\\":{\\\"details\\\":\\\"return if the vault is properly collateralized.\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"true if the vault is safe.\\\"}},\\\"liquidate(uint256,uint256)\\\":{\\\"details\\\":\\\"liquidator can get back (powerPerp burned) * (index price) * 110% in collateral\\\",\\\"params\\\":{\\\"_maxDebtAmount\\\":\\\"max amount of wPowerPerpetual you want to repay.\\\",\\\"_vaultId\\\":\\\"the vault you want to liquidate\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"amount of wPowerPerp repaid.\\\"}},\\\"mintPowerPerpAmount(uint256,uint128,uint256)\\\":{\\\"params\\\":{\\\"_powerPerpAmount\\\":\\\"amount of powerPerp you wish to mint\\\",\\\"_uniTokenId\\\":\\\"uniswap v3 position token id want to use to increase collateral ratio\\\",\\\"_vaultId\\\":\\\"the vault where you want to mint wPowerPerp in\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"vaultId\\\",\\\"_1\\\":\\\"amount of wPowerPerp minted\\\"}},\\\"mintWPowerPerpAmount(uint256,uint128,uint256)\\\":{\\\"params\\\":{\\\"_uniTokenId\\\":\\\"uniswap v3 position token id want to use to increase collateral ratio\\\",\\\"_vaultId\\\":\\\"the vault where you want to mint wPowerPerp in\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp you wish to mint\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"vaultId\\\"}},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"pause()\\\":{\\\"details\\\":\\\"pause the system for up to 24 hours after which any one can unpausecan only be called for 365 days since the contract was launched or 4 times, without triggering shutdown atomically\\\"},\\\"pauseAndShutDown()\\\":{\\\"details\\\":\\\"pause and then immediately shutdown the systemthis bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\\"},\\\"redeemLong(uint256)\\\":{\\\"details\\\":\\\"redeem wPowerPerp for its index value when the system is shutdown\\\",\\\"params\\\":{\\\"_wPerpAmount\\\":\\\"amount of wPowerPerp to burn\\\"}},\\\"redeemShort(uint256)\\\":{\\\"details\\\":\\\"redeem additional collateral from the vault when the system is shutdown\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"vauld id\\\"}},\\\"reduceDebt(uint256)\\\":{\\\"details\\\":\\\"the caller won't get any bounty. this is expected to be used by vault owner\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"the vault you want to save\\\"}},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"setFeeRate(uint256)\\\":{\\\"details\\\":\\\"set the fee rate when user deposit or withdraw collateralthis function cannot be called if the feeRecipient is still un-set\\\",\\\"params\\\":{\\\"_newFeeRate\\\":\\\"new fee rate in basis point. can't be higher than 2%\\\"}},\\\"setFeeRecipient(address)\\\":{\\\"details\\\":\\\"set the recipient who will receive the fee. this should be a contract handling insurance.\\\",\\\"params\\\":{\\\"_newFeeRecipient\\\":\\\"new fee recipient\\\"}},\\\"shutDown()\\\":{\\\"details\\\":\\\"shutdown the system and enable system settlement\\\"},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"unPauseAnyone()\\\":{\\\"details\\\":\\\"anyone can unpause the contract after 24 hours\\\"},\\\"unPauseOwner()\\\":{\\\"details\\\":\\\"owner can unpause at any time\\\"},\\\"updateOperator(uint256,address)\\\":{\\\"details\\\":\\\"can be revoke by setting address to 0.\\\",\\\"params\\\":{\\\"_operator\\\":\\\"new operator address\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"withdraw(uint256,uint256)\\\":{\\\"params\\\":{\\\"_amount\\\":\\\"amount of eth to withdraw\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"withdrawUniPositionToken(uint256)\\\":{\\\"details\\\":\\\"withdraw uniswap v3 position token from a vault\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"}}},\\\"stateVariables\\\":{\\\"PAUSE_TIME_LIMIT\\\":{\\\"details\\\":\\\"system can only be paused for 365 days from deployment\\\"},\\\"feeRate\\\":{\\\"details\\\":\\\"fee rate in basis point. feeRate of 1 = 0.01%\\\"},\\\"indexForSettlement\\\":{\\\"details\\\":\\\"the settlement price for each wPowerPerp for settlement\\\"},\\\"vaults\\\":{\\\"details\\\":\\\"The token ID vault data\\\"},\\\"wPowerPerpPool\\\":{\\\"details\\\":\\\"address of the powerPerp/weth pool\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"events\\\":{\\\"OpenVault(uint256)\\\":{\\\"notice\\\":\\\"Events\\\"}},\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"burnPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"burn powerPerp and remove collateral from a vault.\\\"},\\\"burnWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"burn wPowerPerp and remove collateral from a vault.\\\"},\\\"depositUniPositionToken(uint256,uint256)\\\":{\\\"notice\\\":\\\"deposit uniswap v3 position token into a vault to increase collateral ratio\\\"},\\\"donate()\\\":{\\\"notice\\\":\\\"a function to add eth into a contract, in case it got insolvent and have ensufficient eth to pay out for settlement.\\\"},\\\"getDenormalizedMark(uint32)\\\":{\\\"notice\\\":\\\"get the mark price of powerPerp.\\\"},\\\"getExpectedNormalizationFactor()\\\":{\\\"notice\\\":\\\"returns the expected normalization factor, if the funding is paid right now.\\\"},\\\"getIndex(uint32)\\\":{\\\"notice\\\":\\\"get the index price of powerPerp.\\\"},\\\"init(address,address,address,address,address,address,address,address)\\\":{\\\"notice\\\":\\\"initialize the contract\\\"},\\\"liquidate(uint256,uint256)\\\":{\\\"notice\\\":\\\"if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\\"},\\\"mintPowerPerpAmount(uint256,uint128,uint256)\\\":{\\\"notice\\\":\\\"put down collateral and mint wPowerPerp.\\\"},\\\"mintWPowerPerpAmount(uint256,uint128,uint256)\\\":{\\\"notice\\\":\\\"put down collateral and mint wPowerPerp.\\\"},\\\"reduceDebt(uint256)\\\":{\\\"notice\\\":\\\"if a vault is unsafe and has a UNI NFT in it, owner call redeem the NFT to pay back some debt.\\\"},\\\"updateOperator(uint256,address)\\\":{\\\"notice\\\":\\\"authorize an address to modify the vault.\\\"},\\\"withdraw(uint256,uint256)\\\":{\\\"notice\\\":\\\"withdraw collateral from a vault\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/Controller.sol\\\":\\\"Controller\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":2000},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC165Upgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../proxy/Initializable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Implementation of the {IERC165} interface.\\\\n *\\\\n * Contracts may inherit from this and call {_registerInterface} to declare\\\\n * their support of an interface.\\\\n */\\\\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\\\\n    /*\\\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\\\n\\\\n    /**\\\\n     * @dev Mapping of interface ids to whether or not it's supported.\\\\n     */\\\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\\\n\\\\n    function __ERC165_init() internal initializer {\\\\n        __ERC165_init_unchained();\\\\n    }\\\\n\\\\n    function __ERC165_init_unchained() internal initializer {\\\\n        // Derived contracts need only register support for their own interfaces,\\\\n        // we register support for ERC165 itself here\\\\n        _registerInterface(_INTERFACE_ID_ERC165);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC165-supportsInterface}.\\\\n     *\\\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\\\n        return _supportedInterfaces[interfaceId];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Registers the contract as an implementer of the interface defined by\\\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\\\n     * registering its interface id is not required.\\\\n     *\\\\n     * See {IERC165-supportsInterface}.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\\\n     */\\\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\\\n        require(interfaceId != 0xffffffff, \\\\\\\"ERC165: invalid interface id\\\\\\\");\\\\n        _supportedInterfaces[interfaceId] = true;\\\\n    }\\\\n    uint256[49] private __gap;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x758fecbab95111d05e9c8a48c4895ff615076c9b18bbd9fabdb6480285ede542\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/introspection/IERC165Upgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165Upgradeable {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x84621447d7f733143a21973a18d47782dcb9739ac97bb1ee7f8de214b6dc917d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMathUpgradeable {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfffa644e2e08507310f561f04060db8f19d39e95cc2ad46926aa51043a86e73c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// solhint-disable-next-line compiler-version\\\\npragma solidity >=0.4.24 <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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\\\nabstract contract Initializable {\\\\n\\\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\\\n    function _isConstructor() private view returns (bool) {\\\\n        return !AddressUpgradeable.isContract(address(this));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd8e4eb08dcc1d1860fb347ba5ffd595242b9a1b66d49a47f2b4cb51c3f35017e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/ContextUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721Upgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721MetadataUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721EnumerableUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721ReceiverUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../introspection/ERC165Upgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMathUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/AddressUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/EnumerableSetUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/EnumerableMapUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/StringsUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../proxy/Initializable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721EnumerableUpgradeable {\\\\n    using SafeMathUpgradeable for uint256;\\\\n    using AddressUpgradeable for address;\\\\n    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;\\\\n    using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;\\\\n    using StringsUpgradeable for uint256;\\\\n\\\\n    // Equals to `bytes4(keccak256(\\\\\\\"onERC721Received(address,address,uint256,bytes)\\\\\\\"))`\\\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\\\n\\\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\\\n    mapping (address => EnumerableSetUpgradeable.UintSet) private _holderTokens;\\\\n\\\\n    // Enumerable mapping from token ids to their owners\\\\n    EnumerableMapUpgradeable.UintToAddressMap private _tokenOwners;\\\\n\\\\n    // Mapping from token ID to approved address\\\\n    mapping (uint256 => address) private _tokenApprovals;\\\\n\\\\n    // Mapping from owner to operator approvals\\\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\\\n\\\\n    // Token name\\\\n    string private _name;\\\\n\\\\n    // Token symbol\\\\n    string private _symbol;\\\\n\\\\n    // Optional mapping for token URIs\\\\n    mapping (uint256 => string) private _tokenURIs;\\\\n\\\\n    // Base URI\\\\n    string private _baseURI;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\\\n     *\\\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\\\n     *\\\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\\\n     *\\\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\\\n\\\\n    /**\\\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\\\n     */\\\\n    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {\\\\n        __Context_init_unchained();\\\\n        __ERC165_init_unchained();\\\\n        __ERC721_init_unchained(name_, symbol_);\\\\n    }\\\\n\\\\n    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {\\\\n        _name = name_;\\\\n        _symbol = symbol_;\\\\n\\\\n        // register the supported interfaces to conform to ERC721 via ERC165\\\\n        _registerInterface(_INTERFACE_ID_ERC721);\\\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-balanceOf}.\\\\n     */\\\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\\\n        require(owner != address(0), \\\\\\\"ERC721: balance query for the zero address\\\\\\\");\\\\n        return _holderTokens[owner].length();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-ownerOf}.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\\\n        return _tokenOwners.get(tokenId, \\\\\\\"ERC721: owner query for nonexistent token\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-name}.\\\\n     */\\\\n    function name() public view virtual override returns (string memory) {\\\\n        return _name;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-symbol}.\\\\n     */\\\\n    function symbol() public view virtual override returns (string memory) {\\\\n        return _symbol;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-tokenURI}.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721Metadata: URI query for nonexistent token\\\\\\\");\\\\n\\\\n        string memory _tokenURI = _tokenURIs[tokenId];\\\\n        string memory base = baseURI();\\\\n\\\\n        // If there is no base URI, return the token URI.\\\\n        if (bytes(base).length == 0) {\\\\n            return _tokenURI;\\\\n        }\\\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\\\n        if (bytes(_tokenURI).length > 0) {\\\\n            return string(abi.encodePacked(base, _tokenURI));\\\\n        }\\\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\\\n        return string(abi.encodePacked(base, tokenId.toString()));\\\\n    }\\\\n\\\\n    /**\\\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\\\n    * to the token ID if no specific URI is set for that token ID.\\\\n    */\\\\n    function baseURI() public view virtual returns (string memory) {\\\\n        return _baseURI;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\\\n        return _holderTokens[owner].at(index);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-totalSupply}.\\\\n     */\\\\n    function totalSupply() public view virtual override returns (uint256) {\\\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\\\n        return _tokenOwners.length();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\\\n     */\\\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\\\n        return tokenId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-approve}.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) public virtual override {\\\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\\\n        require(to != owner, \\\\\\\"ERC721: approval to current owner\\\\\\\");\\\\n\\\\n        require(_msgSender() == owner || ERC721Upgradeable.isApprovedForAll(owner, _msgSender()),\\\\n            \\\\\\\"ERC721: approve caller is not owner nor approved for all\\\\\\\"\\\\n        );\\\\n\\\\n        _approve(to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-getApproved}.\\\\n     */\\\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721: approved query for nonexistent token\\\\\\\");\\\\n\\\\n        return _tokenApprovals[tokenId];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-setApprovalForAll}.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\\\n        require(operator != _msgSender(), \\\\\\\"ERC721: approve to caller\\\\\\\");\\\\n\\\\n        _operatorApprovals[_msgSender()][operator] = approved;\\\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-isApprovedForAll}.\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\\\n        return _operatorApprovals[owner][operator];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-transferFrom}.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\\\n        //solhint-disable-next-line max-line-length\\\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\\\\\"ERC721: transfer caller is not owner nor approved\\\\\\\");\\\\n\\\\n        _transfer(from, to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-safeTransferFrom}.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\\\n        safeTransferFrom(from, to, tokenId, \\\\\\\"\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-safeTransferFrom}.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\\\\\"ERC721: transfer caller is not owner nor approved\\\\\\\");\\\\n        _safeTransfer(from, to, tokenId, _data);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\\\n     *\\\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\\\n        _transfer(from, to, tokenId);\\\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns whether `tokenId` exists.\\\\n     *\\\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Tokens start existing when they are minted (`_mint`),\\\\n     * and stop existing when they are burned (`_burn`).\\\\n     */\\\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\\\n        return _tokenOwners.contains(tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721: operator query for nonexistent token\\\\\\\");\\\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721Upgradeable.isApprovedForAll(owner, spender));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\\\n     *\\\\n     * Requirements:\\\\n     d*\\\\n     * - `tokenId` must not exist.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\\\n        _safeMint(to, tokenId, \\\\\\\"\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\\\n     */\\\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\\\n        _mint(to, tokenId);\\\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Mints `tokenId` and transfers it to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must not exist.\\\\n     * - `to` cannot be the zero address.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _mint(address to, uint256 tokenId) internal virtual {\\\\n        require(to != address(0), \\\\\\\"ERC721: mint to the zero address\\\\\\\");\\\\n        require(!_exists(tokenId), \\\\\\\"ERC721: token already minted\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(address(0), to, tokenId);\\\\n\\\\n        _holderTokens[to].add(tokenId);\\\\n\\\\n        _tokenOwners.set(tokenId, to);\\\\n\\\\n        emit Transfer(address(0), to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Destroys `tokenId`.\\\\n     * The approval is cleared when the token is burned.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _burn(uint256 tokenId) internal virtual {\\\\n        address owner = ERC721Upgradeable.ownerOf(tokenId); // internal owner\\\\n\\\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\\\n\\\\n        // Clear approvals\\\\n        _approve(address(0), tokenId);\\\\n\\\\n        // Clear metadata (if any)\\\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\\\n            delete _tokenURIs[tokenId];\\\\n        }\\\\n\\\\n        _holderTokens[owner].remove(tokenId);\\\\n\\\\n        _tokenOwners.remove(tokenId);\\\\n\\\\n        emit Transfer(owner, address(0), tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` from `from` to `to`.\\\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\\\n        require(ERC721Upgradeable.ownerOf(tokenId) == from, \\\\\\\"ERC721: transfer of token that is not own\\\\\\\"); // internal owner\\\\n        require(to != address(0), \\\\\\\"ERC721: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(from, to, tokenId);\\\\n\\\\n        // Clear approvals from the previous owner\\\\n        _approve(address(0), tokenId);\\\\n\\\\n        _holderTokens[from].remove(tokenId);\\\\n        _holderTokens[to].add(tokenId);\\\\n\\\\n        _tokenOwners.set(tokenId, to);\\\\n\\\\n        emit Transfer(from, to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721Metadata: URI set of nonexistent token\\\\\\\");\\\\n        _tokenURIs[tokenId] = _tokenURI;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Internal function to set the base URI for all token IDs. It is\\\\n     * automatically added as a prefix to the value returned in {tokenURI},\\\\n     * or to the token ID if {tokenURI} is empty.\\\\n     */\\\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\\\n        _baseURI = baseURI_;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\\\n     * The call is not executed if the target address is not a contract.\\\\n     *\\\\n     * @param from address representing the previous owner of the given token ID\\\\n     * @param to target address that will receive the tokens\\\\n     * @param tokenId uint256 ID of the token to be transferred\\\\n     * @param _data bytes optional data to send along with the call\\\\n     * @return bool whether the call correctly returned the expected magic value\\\\n     */\\\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\\\n        private returns (bool)\\\\n    {\\\\n        if (!to.isContract()) {\\\\n            return true;\\\\n        }\\\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\\\n            IERC721ReceiverUpgradeable(to).onERC721Received.selector,\\\\n            _msgSender(),\\\\n            from,\\\\n            tokenId,\\\\n            _data\\\\n        ), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\\\n        return (retval == _ERC721_RECEIVED);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Approve `to` to operate on `tokenId`\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function _approve(address to, uint256 tokenId) internal virtual {\\\\n        _tokenApprovals[tokenId] = to;\\\\n        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); // internal owner\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Hook that is called before any token transfer. This includes minting\\\\n     * and burning.\\\\n     *\\\\n     * Calling conditions:\\\\n     *\\\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\\\n     * transferred to `to`.\\\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     *\\\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\\\n     */\\\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\\\n    uint256[41] private __gap;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x988d02c5a81d1223f7629f1e318606f4d58325591eb359baa621dfb5043646dc\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721EnumerableUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721Upgradeable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721EnumerableUpgradeable is IERC721Upgradeable {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2122334a6033b36e67e49040844724c5229d7cf840c9f4206d501ba61700dbd0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721MetadataUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721Upgradeable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x73990febc6e334839fc9db9e772eefad6754a46d53074fa6d1ba4170f354a3f5\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721ReceiverUpgradeable {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xafe63d2e30c9a730957f2e1b671acf2ff8e6d11f689d995dfbcc6c383c7b6a28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165Upgradeable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3c4838d816e09e5fd7347620cf53f7ab900bd23875ccf513f88c244e86077d72\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary 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    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1fd568d8b8ca285c801fbd1d3f40f848434d850a682c0273786cada3e0b84057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <0.8.0;\\\\nimport \\\\\\\"../proxy/Initializable.sol\\\\\\\";\\\\n\\\\n/*\\\\n * @dev Provides information about the current execution context, including the\\\\n * sender of the transaction and its data. While these are generally available\\\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\\\n * manner, since when dealing with GSN 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 initializer {\\\\n        __Context_init_unchained();\\\\n    }\\\\n\\\\n    function __Context_init_unchained() internal initializer {\\\\n    }\\\\n    function _msgSender() internal view virtual returns (address payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n    uint256[50] private __gap;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbbf8a21b9a66c48d45ff771b8563c6df19ba451d63dfb8380a865c1e1f29d1a0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/utils/EnumerableMapUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Library for managing an enumerable variant of Solidity's\\\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\\\n * type.\\\\n *\\\\n * Maps have the following properties:\\\\n *\\\\n * - Entries are added, removed, and checked for existence in constant time\\\\n * (O(1)).\\\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\\\n *\\\\n * ```\\\\n * contract Example {\\\\n *     // Add the library methods\\\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\\\n *\\\\n *     // Declare a set state variable\\\\n *     EnumerableMap.UintToAddressMap private myMap;\\\\n * }\\\\n * ```\\\\n *\\\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\\\n * supported.\\\\n */\\\\nlibrary EnumerableMapUpgradeable {\\\\n    // To implement this library for multiple types with as little code\\\\n    // repetition as possible, we write it in terms of a generic Map type with\\\\n    // bytes32 keys and values.\\\\n    // The Map implementation uses private functions, and user-facing\\\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\\\n    // the underlying Map.\\\\n    // This means that we can only create new EnumerableMaps for types that fit\\\\n    // in bytes32.\\\\n\\\\n    struct MapEntry {\\\\n        bytes32 _key;\\\\n        bytes32 _value;\\\\n    }\\\\n\\\\n    struct Map {\\\\n        // Storage of map keys and values\\\\n        MapEntry[] _entries;\\\\n\\\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\\\n        // because index 0 means a key is not in the map.\\\\n        mapping (bytes32 => uint256) _indexes;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\\\n     * key. O(1).\\\\n     *\\\\n     * Returns true if the key was added to the map, that is if it was not\\\\n     * already present.\\\\n     */\\\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\\\n        uint256 keyIndex = map._indexes[key];\\\\n\\\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\\\n            // The entry is stored at length-1, but we add 1 to all indexes\\\\n            // and use 0 as a sentinel value\\\\n            map._indexes[key] = map._entries.length;\\\\n            return true;\\\\n        } else {\\\\n            map._entries[keyIndex - 1]._value = value;\\\\n            return false;\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Removes a key-value pair from a map. O(1).\\\\n     *\\\\n     * Returns true if the key was removed from the map, that is if it was present.\\\\n     */\\\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\\\n        uint256 keyIndex = map._indexes[key];\\\\n\\\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\\\n            // This modifies the order of the array, as noted in {at}.\\\\n\\\\n            uint256 toDeleteIndex = keyIndex - 1;\\\\n            uint256 lastIndex = map._entries.length - 1;\\\\n\\\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\\\n\\\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\\\n\\\\n            // Move the last entry to the index where the entry to delete is\\\\n            map._entries[toDeleteIndex] = lastEntry;\\\\n            // Update the index for the moved entry\\\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\\\n\\\\n            // Delete the slot where the moved entry was stored\\\\n            map._entries.pop();\\\\n\\\\n            // Delete the index for the deleted slot\\\\n            delete map._indexes[key];\\\\n\\\\n            return true;\\\\n        } else {\\\\n            return false;\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns true if the key is in the map. O(1).\\\\n     */\\\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\\\n        return map._indexes[key] != 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\\\n     */\\\\n    function _length(Map storage map) private view returns (uint256) {\\\\n        return map._entries.length;\\\\n    }\\\\n\\\\n   /**\\\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\\\n    *\\\\n    * Note that there are no guarantees on the ordering of entries inside the\\\\n    * array, and it may change when more entries are added or removed.\\\\n    *\\\\n    * Requirements:\\\\n    *\\\\n    * - `index` must be strictly less than {length}.\\\\n    */\\\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\\\n        require(map._entries.length > index, \\\\\\\"EnumerableMap: index out of bounds\\\\\\\");\\\\n\\\\n        MapEntry storage entry = map._entries[index];\\\\n        return (entry._key, entry._value);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\\\n     * Does not revert if `key` is not in the map.\\\\n     */\\\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the value associated with `key`.  O(1).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `key` must be in the map.\\\\n     */\\\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        require(keyIndex != 0, \\\\\\\"EnumerableMap: nonexistent key\\\\\\\"); // Equivalent to contains(map, key)\\\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\\\n     */\\\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\\\n    }\\\\n\\\\n    // UintToAddressMap\\\\n\\\\n    struct UintToAddressMap {\\\\n        Map _inner;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\\\n     * key. O(1).\\\\n     *\\\\n     * Returns true if the key was added to the map, that is if it was not\\\\n     * already present.\\\\n     */\\\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Removes a value from a set. O(1).\\\\n     *\\\\n     * Returns true if the key was removed from the map, that is if it was present.\\\\n     */\\\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\\\n        return _remove(map._inner, bytes32(key));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns true if the key is in the map. O(1).\\\\n     */\\\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\\\n        return _contains(map._inner, bytes32(key));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the number of elements in the map. O(1).\\\\n     */\\\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\\\n        return _length(map._inner);\\\\n    }\\\\n\\\\n   /**\\\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\\\n        return (uint256(key), address(uint160(uint256(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\\\n     * Does not revert if `key` is not in the map.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\\\n        return (success, address(uint160(uint256(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the value associated with `key`.  O(1).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `key` must be in the map.\\\\n     */\\\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\\\n     */\\\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x736de5559b9ab9958c327854964ea731e85a720d5ceabf7eee2eef7c92744d91\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.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 EnumerableSetUpgradeable {\\\\n    // To implement this library for multiple types with as little code\\\\n    // repetition as possible, we write it in terms of a generic Set type with\\\\n    // bytes32 values.\\\\n    // The Set implementation uses private functions, and user-facing\\\\n    // implementations (such as AddressSet) are just wrappers around the\\\\n    // underlying Set.\\\\n    // This means that we can only create new EnumerableSets for types that fit\\\\n    // in bytes32.\\\\n\\\\n    struct Set {\\\\n        // Storage of set values\\\\n        bytes32[] _values;\\\\n\\\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\\\n\\\\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] = toDeleteIndex + 1; // All indexes are 1-based\\\\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        require(set._values.length > index, \\\\\\\"EnumerableSet: index out of bounds\\\\\\\");\\\\n        return set._values[index];\\\\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    // 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    // 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\\\",\\\"keccak256\\\":\\\"0xeb4d39f727e65fda4c7059105db14acde18654bd54d8916af89c3834211d7d88\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev String operations.\\\\n */\\\\nlibrary StringsUpgradeable {\\\\n    /**\\\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\\\n        temp = value;\\\\n        while (temp != 0) {\\\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\\\n            temp /= 10;\\\\n        }\\\\n        return string(buffer);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2835123cbd701f895669d17fda937ff6d003cc8357ada59d75078055c100e7ac\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// solhint-disable-next-line compiler-version\\\\npragma solidity >=0.4.24 <0.8.0;\\\\n\\\\nimport \\\\\\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\\\nabstract contract Initializable {\\\\n\\\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\\\n    function _isConstructor() private view returns (bool) {\\\\n        return !Address.isContract(address(this));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9abeffe138f098b16557187383ba0f9e8503602fa95cd668132986ee115237ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Safe casting methods\\\\n/// @notice Contains methods for safely casting between types\\\\nlibrary SafeCast {\\\\n    /// @notice Cast a uint256 to a uint160, revert on overflow\\\\n    /// @param y The uint256 to be downcasted\\\\n    /// @return z The downcasted integer, now type uint160\\\\n    function toUint160(uint256 y) internal pure returns (uint160 z) {\\\\n        require((z = uint160(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a int256 to a int128, revert on overflow or underflow\\\\n    /// @param y The int256 to be downcasted\\\\n    /// @return z The downcasted integer, now type int128\\\\n    function toInt128(int256 y) internal pure returns (int128 z) {\\\\n        require((z = int128(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a uint256 to a int256, revert on overflow\\\\n    /// @param y The uint256 to be casted\\\\n    /// @return z The casted integer, now type int256\\\\n    function toInt256(uint256 y) internal pure returns (int256 z) {\\\\n        require(y < 2**255);\\\\n        z = int256(y);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: BUSL-1.1\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './LowGasSafeMath.sol';\\\\nimport './SafeCast.sol';\\\\n\\\\nimport './FullMath.sol';\\\\nimport './UnsafeMath.sol';\\\\nimport './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 LowGasSafeMath for uint256;\\\\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            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            return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96).add(amount)));\\\\n        } else {\\\\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    /// @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                (\\\\n                    amount <= type(uint160).max\\\\n                        ? (amount << FixedPoint96.RESOLUTION) / liquidity\\\\n                        : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)\\\\n                );\\\\n\\\\n            return uint256(sqrtPX96).add(quotient).toUint160();\\\\n        } else {\\\\n            uint256 quotient =\\\\n                (\\\\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            return uint160(sqrtPX96 - quotient);\\\\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        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) internal pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n\\\\n    /// @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        return\\\\n            liquidity < 0\\\\n                ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\\\n                : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\\\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        return\\\\n            liquidity < 0\\\\n                ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\\\n                : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4f69701d331d364b69a1cda77cd7b983a0079d36ae0e06b0bb1d64ae56c3705e\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Oracle library\\\\n/// @notice Provides functions to integrate with V3 pool oracle\\\\nlibrary OracleLibrary {\\\\n    /// @notice Fetches time-weighted average tick using Uniswap V3 oracle\\\\n    /// @param pool Address of Uniswap V3 pool that we want to observe\\\\n    /// @param period Number of seconds in the past to start calculating time-weighted average\\\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - period) to block.timestamp\\\\n    function consult(address pool, uint32 period) internal view returns (int24 timeWeightedAverageTick) {\\\\n        require(period != 0, 'BP');\\\\n\\\\n        uint32[] memory secondAgos = new uint32[](2);\\\\n        secondAgos[0] = period;\\\\n        secondAgos[1] = 0;\\\\n\\\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\\\n\\\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / period);\\\\n\\\\n        // Always round to negative infinity\\\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % period != 0)) timeWeightedAverageTick--;\\\\n    }\\\\n\\\\n    /// @notice Given a tick and a token amount, calculates the amount of token received in exchange\\\\n    /// @param tick Tick value used to calculate the quote\\\\n    /// @param baseAmount Amount of token to be converted\\\\n    /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination\\\\n    /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination\\\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\\\n    function getQuoteAtTick(\\\\n        int24 tick,\\\\n        uint128 baseAmount,\\\\n        address baseToken,\\\\n        address quoteToken\\\\n    ) internal pure returns (uint256 quoteAmount) {\\\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\\\n\\\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\\\n        if (sqrtRatioX96 <= type(uint128).max) {\\\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\\\n            quoteAmount = baseToken < quoteToken\\\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\\\n        } else {\\\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\\\n            quoteAmount = baseToken < quoteToken\\\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x19517bf2478c3ec56253f37b48adde7f34a6acdb467e329f74d79f9e72e2a63f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/core/Controller.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\nimport \\\\\\\"hardhat/console.sol\\\\\\\";\\\\n\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IVaultManagerNFT} from \\\\\\\"../interfaces/IVaultManagerNFT.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\n\\\\nimport {ERC721Upgradeable} from \\\\\\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\\\\\";\\\\nimport {Initializable} from \\\\\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\n\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\n\\\\ncontract Controller is Initializable, Ownable {\\\\n    using SafeMath for uint256;\\\\n    using VaultLib for VaultLib.Vault;\\\\n    using Address for address payable;\\\\n\\\\n    uint32 internal constant SHUTDOWN_PERIOD = 600;\\\\n    uint256 internal constant SEC_IN_DAY = 86400;\\\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\\\n    /// @dev system can only be paused for 365 days from deployment\\\\n    uint256 public constant PAUSE_TIME_LIMIT = 182 days;\\\\n\\\\n    bool public isShutDown = false;\\\\n    bool public isSystemPaused = false;\\\\n    uint256 public pausesLeft = 4;\\\\n    uint256 public lastPauseTime = 0;\\\\n\\\\n    address public weth;\\\\n    address public dai;\\\\n    address public ethDaiPool;\\\\n    address public feeRecipient;\\\\n\\\\n    /// @dev address of the powerPerp/weth pool\\\\n    address public wPowerPerpPool;\\\\n\\\\n    address public uniswapPositionManager;\\\\n\\\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\\\n    uint256 public feeRate;\\\\n\\\\n    /// @dev the settlement price for each wPowerPerp for settlement\\\\n    uint256 public indexForSettlement;\\\\n\\\\n    uint256 public normalizationFactor;\\\\n    uint256 public lastFundingUpdateTimestamp;\\\\n    uint256 public deployTimestamp;\\\\n\\\\n    bool public isWethToken0;\\\\n\\\\n    /// @dev The token ID vault data\\\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\\\n\\\\n    IVaultManagerNFT public vaultNFT;\\\\n    IWPowerPerp public wPowerPerp;\\\\n    IOracle public oracle;\\\\n\\\\n    /// Events\\\\n    event OpenVault(uint256 vaultId);\\\\n    event CloseVault(uint256 vaultId);\\\\n    event DepositCollateral(uint256 vaultId, uint256 amount, uint128 collateralId);\\\\n    event DepositUniPositionToken(uint256 vaultId, uint256 tokenId);\\\\n    event WithdrawCollateral(uint256 vaultId, uint256 amount, uint128 collateralId);\\\\n    event WithdrawUniPositionToken(uint256 vaultId, uint256 tokenId);\\\\n    event MintShort(uint256 amount, uint256 vaultId);\\\\n    event BurnShort(uint256 amount, uint256 vaultId);\\\\n    event UpdateOperator(uint256 vaultId, address operator);\\\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\\\n    event Liquidate(uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\\\n    event NormalizationFactorUpdated(uint256 oldNormFactor, uint256 newNormFactor, uint256 timestamp);\\\\n\\\\n    modifier notPaused() {\\\\n        require(!isSystemPaused, \\\\\\\"paused\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier isPaused() {\\\\n        require(isSystemPaused, \\\\\\\"!paused\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier notShutdown() {\\\\n        require(!isShutDown, \\\\\\\"shutdown\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier isShutdown() {\\\\n        require(isShutDown, \\\\\\\"!shutdown\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * ======================\\\\n     * | External Functions |\\\\n     * ======================\\\\n     */\\\\n\\\\n    /**\\\\n     * @notice returns the expected normalization factor, if the funding is paid right now.\\\\n     * @dev can be used for on-chain and off-chain calculations\\\\n     */\\\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\\\n        return _getNewNormalizationFactor();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index price of powerPerp.\\\\n     * @param _period period which you want to calculate twap with\\\\n     * @return index price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getIndex(uint32 _period) external view returns (uint256) {\\\\n        return Power2Base._getIndex(_period, address(oracle), ethDaiPool, weth, dai);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the mark price of powerPerp.\\\\n     * @param _period period which you want to calculate twap with\\\\n     * @return mark price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\\\n        return\\\\n            Power2Base._getDenormalizedMark(\\\\n                _period,\\\\n                address(oracle),\\\\n                wPowerPerpPool,\\\\n                ethDaiPool,\\\\n                weth,\\\\n                dai,\\\\n                address(wPowerPerp),\\\\n                expectedNormalizationFactor\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev return if the vault is properly collateralized.\\\\n     * @param _vaultId id of the vault\\\\n     * @return true if the vault is safe.\\\\n     */\\\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\\\n        uint256 expectednormalizationFactor = _getNewNormalizationFactor();\\\\n        return _isVaultSafe(vault, expectednormalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice initialize the contract\\\\n     * @param _oracle oracle address\\\\n     * @param _vaultNFT erc721 token address representing the short position\\\\n     * @param _wPowerPerp erc20 token address representing non-rebasing long position\\\\n     * @param _weth weth address\\\\n     * @param _dai dai address\\\\n     * @param _ethDaiPool uniswap v3 pool for weth / dai\\\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\\\n     * @param _uniPositionManager uniswap v3 nonfungible position manager address\\\\n     */\\\\n    function init(\\\\n        address _oracle,\\\\n        address _vaultNFT,\\\\n        address _wPowerPerp,\\\\n        address _weth,\\\\n        address _dai,\\\\n        address _ethDaiPool,\\\\n        address _wPowerPerpPool,\\\\n        address _uniPositionManager\\\\n    ) public initializer {\\\\n        require(_oracle != address(0), \\\\\\\"Invalid oracle address\\\\\\\");\\\\n        require(_vaultNFT != address(0), \\\\\\\"Invalid vaultNFT address\\\\\\\");\\\\n        require(_wPowerPerp != address(0), \\\\\\\"Invalid power perp address\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"Invalid weth address\\\\\\\");\\\\n        require(_dai != address(0), \\\\\\\"Invalid quote currency address\\\\\\\");\\\\n        require(_ethDaiPool != address(0), \\\\\\\"Invalid eth:usd pool address\\\\\\\");\\\\n        require(_wPowerPerpPool != address(0), \\\\\\\"Invalid powerperp:eth pool address\\\\\\\");\\\\n        require(_uniPositionManager != address(0), \\\\\\\"Invalid uni position manager\\\\\\\");\\\\n\\\\n        oracle = IOracle(_oracle);\\\\n        vaultNFT = IVaultManagerNFT(_vaultNFT);\\\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\\\n\\\\n        ethDaiPool = _ethDaiPool;\\\\n        wPowerPerpPool = _wPowerPerpPool;\\\\n        uniswapPositionManager = _uniPositionManager;\\\\n\\\\n        weth = _weth;\\\\n        dai = _dai;\\\\n\\\\n        normalizationFactor = 1e18;\\\\n        lastFundingUpdateTimestamp = block.timestamp;\\\\n        deployTimestamp = block.timestamp;\\\\n\\\\n        isWethToken0 = weth < _wPowerPerp;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice put down collateral and mint wPowerPerp.\\\\n     * @param _vaultId the vault where you want to mint wPowerPerp in\\\\n     * @param _powerPerpAmount amount of powerPerp you wish to mint\\\\n     * @param _uniTokenId uniswap v3 position token id want to use to increase collateral ratio\\\\n     * @return vaultId\\\\n     * @return amount of wPowerPerp minted\\\\n     */\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint128 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable notPaused returns (uint256, uint256) {\\\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice put down collateral and mint wPowerPerp.\\\\n     * @param _vaultId the vault where you want to mint wPowerPerp in\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp you wish to mint\\\\n     * @param _uniTokenId uniswap v3 position token id want to use to increase collateral ratio\\\\n     * @return vaultId\\\\n     */\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint128 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable notPaused returns (uint256) {\\\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev deposit collateral into a vault\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable notPaused {\\\\n        _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit uniswap v3 position token into a vault to increase collateral ratio\\\\n     * @param _vaultId id of the vault\\\\n     * @param _uniTokenId uniswap v3 position token id\\\\n     */\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused {\\\\n        _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw collateral from a vault\\\\n     * @param _vaultId id of the vault\\\\n     * @param _amount amount of eth to withdraw\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable notPaused {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _withdrawCollateral(cachedVault, msg.sender, _vaultId, _amount);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev withdraw uniswap v3 position token from a vault\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp and remove collateral from a vault.\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\\\n     * @param _withdrawAmount amount of eth to withdraw\\\\n     */\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external notPaused {\\\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn powerPerp and remove collateral from a vault.\\\\n     * @param _vaultId id of the vault\\\\n     * @param _powerPerpAmount amount of powerPerp to burn\\\\n     * @param _withdrawAmount amount of eth to withdraw\\\\n     * @return amount of wPowerPerp burned\\\\n     */\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external notPaused returns (uint256) {\\\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice if a vault is unsafe and has a UNI NFT in it, owner call redeem the NFT to pay back some debt.\\\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\\\n     * @param _vaultId the vault you want to save\\\\n     */\\\\n    function reduceDebt(uint256 _vaultId) external notPaused {\\\\n        require(_canModifyVault(_vaultId, msg.sender), \\\\\\\"not allowed\\\\\\\");\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _reduceDebt(cachedVault, vaultNFT.ownerOf(_vaultId), cachedNormFactor, false);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\\\n     * @dev liquidator can get back (powerPerp burned) * (index price) * 110% in collateral\\\\n     * @param _vaultId the vault you want to liquidate\\\\n     * @param _maxDebtAmount max amount of wPowerPerpetual you want to repay.\\\\n     * @return amount of wPowerPerp repaid.\\\\n     */\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused returns (uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\\\\\"Can not liquidate safe vault\\\\\\\");\\\\n\\\\n        // try to save target vault before liquidation by reducing debt\\\\n        uint256 bounty = _reduceDebt(cachedVault, vaultNFT.ownerOf(_vaultId), cachedNormFactor, true);\\\\n\\\\n        // if vault is safe after saving, pay bounty and return early.\\\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\\\n            payable(msg.sender).sendValue(bounty);\\\\n            _writeVault(_vaultId, cachedVault);\\\\n            return 0;\\\\n        }\\\\n\\\\n        // add back the bounty amount, liquidators are only getting reward from liquidation.\\\\n        cachedVault.addEthCollateral(bounty);\\\\n\\\\n        // if the vault is still not safe after saving, liquidate it.\\\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\\\n            cachedVault,\\\\n            _maxDebtAmount,\\\\n            cachedNormFactor,\\\\n            msg.sender\\\\n        );\\\\n\\\\n        emit Liquidate(_vaultId, debtAmount, collateralPaid);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        return debtAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice authorize an address to modify the vault.\\\\n     * @dev can be revoke by setting address to 0.\\\\n     * @param _vaultId id of the vault\\\\n     * @param _operator new operator address\\\\n     */\\\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\\\n        require(_canModifyVault(_vaultId, msg.sender), \\\\\\\"not allowed\\\\\\\");\\\\n        vaults[_vaultId].operator = _operator;\\\\n        emit UpdateOperator(_vaultId, _operator);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev set the recipient who will receive the fee. this should be a contract handling insurance.\\\\n     * @param _newFeeRecipient new fee recipient\\\\n     */\\\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\\\n        require(_newFeeRecipient != address(0), \\\\\\\"invalid address\\\\\\\");\\\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\\\n        feeRecipient = _newFeeRecipient;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev set the fee rate when user deposit or withdraw collateral\\\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\\\n     * @param _newFeeRate new fee rate in basis point. can't be higher than 2%\\\\n     */\\\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\\\n        require(feeRecipient != address(0), \\\\\\\"set fee recipient first\\\\\\\");\\\\n        require(_newFeeRate <= 100, \\\\\\\"fee too high\\\\\\\");\\\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\\\n        feeRate = _newFeeRate;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev pause and then immediately shutdown the system\\\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\\\n     */\\\\n    function pauseAndShutDown() external notShutdown notPaused onlyOwner {\\\\n        isSystemPaused = true;\\\\n        isShutDown = true;\\\\n        indexForSettlement = Power2Base._getScaledTwap(address(oracle), ethDaiPool, weth, dai, 600);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev shutdown the system and enable system settlement\\\\n     */\\\\n    function shutDown() external notShutdown isPaused onlyOwner {\\\\n        isShutDown = true;\\\\n        indexForSettlement = Power2Base._getScaledTwap(address(oracle), ethDaiPool, weth, dai, 600);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev pause the system for up to 24 hours after which any one can unpause\\\\n     * @dev can only be called for 365 days since the contract was launched or 4 times, without triggering shutdown atomically\\\\n     */\\\\n    function pause() external notShutdown notPaused onlyOwner {\\\\n        require(pausesLeft > 0, \\\\\\\"paused too many times\\\\\\\");\\\\n        uint256 timeSinceDeploy = block.timestamp - deployTimestamp;\\\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\\\\\"pause time limit exceeded\\\\\\\");\\\\n        isSystemPaused = true;\\\\n        pausesLeft -= 1;\\\\n        lastPauseTime = block.timestamp;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev anyone can unpause the contract after 24 hours\\\\n     */\\\\n    function unPauseAnyone() external notShutdown isPaused {\\\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\\\\\"not enough paused time has passed\\\\\\\");\\\\n        isSystemPaused = false;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev owner can unpause at any time\\\\n     */\\\\n    function unPauseOwner() external notShutdown isPaused onlyOwner {\\\\n        isSystemPaused = false;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev redeem wPowerPerp for its index value when the system is shutdown\\\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\\\n     */\\\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown {\\\\n        wPowerPerp.burn(msg.sender, _wPerpAmount);\\\\n\\\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\\\n        payable(msg.sender).sendValue(longValue);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev redeem additional collateral from the vault when the system is shutdown\\\\n     * @param _vaultId vauld id\\\\n     */\\\\n    function redeemShort(uint256 _vaultId) external isShutdown {\\\\n        require(_canModifyVault(_vaultId, msg.sender), \\\\\\\"not allowed\\\\\\\");\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        uint256 cachedNormFactor = normalizationFactor;\\\\n\\\\n        _reduceDebt(cachedVault, msg.sender, cachedNormFactor, false);\\\\n\\\\n        uint256 debt = Power2Base._getLongSettlementValue(\\\\n            cachedVault.shortAmount,\\\\n            indexForSettlement,\\\\n            normalizationFactor\\\\n        );\\\\n        // if the debt is more than collateral, this line will revert\\\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\\\n\\\\n        // reset the vault but don't burn the nft, just because people may want to keep it.\\\\n        cachedVault.shortAmount = 0;\\\\n        cachedVault.collateralAmount = 0;\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        payable(msg.sender).sendValue(excess);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev update the normalization factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external notPaused {\\\\n        _applyFunding();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice a function to add eth into a contract, in case it got insolvent and have ensufficient eth to pay out for settlement.\\\\n     */\\\\n    function donate() external payable isShutdown {}\\\\n\\\\n    /**\\\\n     * fallback function to accept eth\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth, \\\\\\\"Cannot receive eth\\\\\\\");\\\\n    }\\\\n\\\\n    /*\\\\n     * ======================\\\\n     * | Internal Functions |\\\\n     * ======================\\\\n     */\\\\n\\\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\\\n        return vaultNFT.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice wrapper function which open a vault, add collateral and mint wPowerPerp\\\\n     * @param _account who should receive wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _mintAmount amount to mint\\\\n     * @param _depositAmount amount of eth as collateral\\\\n     * @param _isWAmount if the input amount is wPowerPerp\\\\n     * @return vaultId\\\\n     * @return total minted wPowerPower amount\\\\n     */\\\\n    function _openDepositMint(\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _mintAmount,\\\\n        uint256 _depositAmount,\\\\n        uint256 _uniTokenId,\\\\n        bool _isWAmount\\\\n    ) internal returns (uint256, uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        uint256 depositAmountWithFee = _depositAmount;\\\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(1e18).div(cachedNormFactor);\\\\n\\\\n        VaultLib.Vault memory cachedVault;\\\\n\\\\n        // load vault or create new a new one\\\\n        if (_vaultId == 0) {\\\\n            (_vaultId, cachedVault) = _openVault(_account);\\\\n        } else {\\\\n            cachedVault = vaults[_vaultId];\\\\n        }\\\\n\\\\n        if (wPowerPerpAmount > 0) {\\\\n            depositAmountWithFee = _payFee(cachedVault, _account, _vaultId, wPowerPerpAmount, _depositAmount);\\\\n        }\\\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\\\n\\\\n        if (wPowerPerpAmount > 0) _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\\\n\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        return (_vaultId, wPowerPerpAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice wrapper function which burn wPowerPerp and redeem collateral\\\\n     * @param _account who should receive wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _burnAmount amount to mint\\\\n     * @param _withdrawAmount amount of eth as collateral\\\\n     * @param _isWAmount true if the amount is wPowerPerp\\\\n     * @return total burned wPowerPower amount\\\\n     */\\\\n    function _burnAndWithdraw(\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _burnAmount,\\\\n        uint256 _withdrawAmount,\\\\n        bool _isWAmount\\\\n    ) internal returns (uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n\\\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(1e18).div(cachedNormFactor);\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _account, _vaultId, _withdrawAmount);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        return wBurnAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev create a new vault and bind it with a new short vault id.\\\\n     * @return id of the newly created vault\\\\n     * @return newly created vault memory\\\\n     */\\\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\\\n        uint256 vaultId = vaultNFT.mintNFT(_recipient);\\\\n\\\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\\\n            NftCollateralId: 0,\\\\n            collateralAmount: 0,\\\\n            shortAmount: 0,\\\\n            operator: address(0)\\\\n        });\\\\n        emit OpenVault(vaultId);\\\\n        return (vaultId, vault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev deposit uni v3 position token into a vault.\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _account account we should transfer the uni nft from\\\\n     * @param _vaultId id of the vault\\\\n     * @param _uniTokenId uniswap v3 position token id\\\\n     */\\\\n    function _depositUniPositionToken(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _uniTokenId\\\\n    ) internal {\\\\n        _checkUniNFT(_uniTokenId);\\\\n        _vault.addUniNftCollateral(_uniTokenId);\\\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(_account, address(this), _uniTokenId);\\\\n        emit DepositUniPositionToken(_vaultId, _uniTokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev add eth collateral into a vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _amount amount of eth adding to the vault\\\\n     */\\\\n    function _addEthCollateral(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _vaultId,\\\\n        uint256 _amount\\\\n    ) internal {\\\\n        _vault.addEthCollateral(_amount);\\\\n        emit DepositCollateral(_vaultId, _amount, 0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev remove uniswap v3 position token from the vault\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _account where to send the uni position token to\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function _withdrawUniPositionToken(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId\\\\n    ) internal {\\\\n        require(_canModifyVault(_vaultId, _account), \\\\\\\"not allowed\\\\\\\");\\\\n\\\\n        uint256 tokenId = _vault.NftCollateralId;\\\\n        _vault.removeUniNftCollateral();\\\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(address(this), _account, tokenId);\\\\n        emit WithdrawUniPositionToken(_vaultId, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev remove eth collateral from the vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _account where to send collateral to\\\\n     * @param _vaultId id of the vault\\\\n     * @param _amount amount of eth to withdraw\\\\n     */\\\\n    function _withdrawCollateral(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _amount\\\\n    ) internal {\\\\n        require(_canModifyVault(_vaultId, _account), \\\\\\\"not allowed\\\\\\\");\\\\n\\\\n        _vault.removeEthCollateral(_amount);\\\\n        payable(_account).sendValue(_amount);\\\\n\\\\n        emit WithdrawCollateral(_vaultId, _amount, 0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev mint wPowerPerp (ERC20) to an account\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _account who should receive wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\\\n     */\\\\n    function _mintWPowerPerp(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount\\\\n    ) internal {\\\\n        require(_canModifyVault(_vaultId, _account), \\\\\\\"not allowed\\\\\\\");\\\\n\\\\n        _vault.addShort(_wPowerPerpAmount);\\\\n        wPowerPerp.mint(_account, _wPowerPerpAmount);\\\\n\\\\n        emit MintShort(_wPowerPerpAmount, _vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev burn wPowerPerp (ERC20) from an account.\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _account who pay the wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\\\n     */\\\\n    function _burnWPowerPerp(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount\\\\n    ) internal {\\\\n        _vault.removeShort(_wPowerPerpAmount);\\\\n        wPowerPerp.burn(_account, _wPowerPerpAmount);\\\\n\\\\n        emit BurnShort(_wPowerPerpAmount, _vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice liquidate a vault, pay the liquidator\\\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _maxWPowerPerpAmount max debt amount liquidator is willing to repay\\\\n     * @param _liquidator address which will receive eth\\\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\\\n     * @return collateralToPay amount of collateral paid to liquidator\\\\n     */\\\\n    function _liquidate(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _maxWPowerPerpAmount,\\\\n        uint256 _normalizationFactor,\\\\n        address _liquidator\\\\n    ) internal returns (uint256, uint256) {\\\\n        // cast numbers to uint256 and cache them\\\\n        uint256 vaultShortAmount = uint256(_vault.shortAmount);\\\\n        uint256 vaultCollateralAmount = uint256(_vault.collateralAmount);\\\\n\\\\n        // try limiting max liquidatable amount to half of the vault\\\\n        (uint256 wAmountToLiquidate, uint256 collateralToPay) = _getLiquidationAmount(\\\\n            _maxWPowerPerpAmount,\\\\n            vaultShortAmount.div(2),\\\\n            _normalizationFactor\\\\n        );\\\\n\\\\n        if (vaultCollateralAmount > collateralToPay) {\\\\n            if (vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\\\n                // the vault is left with dust after liquidation, allow liquidating full vault.\\\\n                // calculate the new liquidation amount and collateral again based on the new limit\\\\n                (wAmountToLiquidate, collateralToPay) = _getLiquidationAmount(\\\\n                    _maxWPowerPerpAmount,\\\\n                    vaultShortAmount,\\\\n                    _normalizationFactor\\\\n                );\\\\n            }\\\\n        }\\\\n\\\\n        // check if final collateral to pay is greater than vault amount.\\\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\\\n        if (collateralToPay > vaultCollateralAmount) {\\\\n            // force liquidator to pay full debt amount\\\\n            require(_maxWPowerPerpAmount >= vaultShortAmount, \\\\\\\"need full liquidation\\\\\\\");\\\\n            collateralToPay = vaultCollateralAmount;\\\\n            wAmountToLiquidate = vaultShortAmount;\\\\n        }\\\\n\\\\n        wPowerPerp.burn(_liquidator, wAmountToLiquidate);\\\\n        _vault.removeShort(wAmountToLiquidate);\\\\n        _vault.removeEthCollateral(collateralToPay);\\\\n\\\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        require(!isDust, \\\\\\\"dust vault left\\\\\\\");\\\\n\\\\n        // pay the liquidator\\\\n        payable(_liquidator).sendValue(collateralToPay);\\\\n\\\\n        return (wAmountToLiquidate, collateralToPay);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice this function will redeem the NFT in a vault\\\\n     * @notice and reduce debt in the target vault if there's a nft in the vault\\\\n     * @dev this function will be executed before liquidation if there's a NFT in the vault.\\\\n     * @dev when it's called by liquidate(), it pays out a small bounty to the liquidator.\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _owner where should the excess go to\\\\n     * @param _isLiquidation whether we're paying to the recipient the 2% discount or not.\\\\n     * @return bounty amount of bounty paid for liquidator\\\\n     */\\\\n    function _reduceDebt(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _owner,\\\\n        uint256 _normalizationFactor,\\\\n        bool _isLiquidation\\\\n    ) internal returns (uint256) {\\\\n        uint256 nftId = _vault.NftCollateralId;\\\\n        if (nftId == 0) return 0;\\\\n\\\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\\\n\\\\n        // change weth back to eth\\\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\\\n\\\\n        // the bounty is 2% on top of total value withdrawn from the NFT.\\\\n        uint256 bounty;\\\\n        if (_isLiquidation) {\\\\n            uint256 totalValue = Power2Base\\\\n                ._getCollateralByRepayAmount(\\\\n                    withdrawnWPowerPerpAmount,\\\\n                    address(oracle),\\\\n                    ethDaiPool,\\\\n                    weth,\\\\n                    dai,\\\\n                    _normalizationFactor\\\\n                )\\\\n                .add(withdrawnEthAmount);\\\\n\\\\n            bounty = totalValue.mul(2).div(100);\\\\n        }\\\\n\\\\n        _vault.removeUniNftCollateral();\\\\n        _vault.addEthCollateral(withdrawnEthAmount);\\\\n        _vault.removeEthCollateral(bounty);\\\\n\\\\n        // burn min of (shortAmount, withdrawnWPowerPerpAmount) from the vault.\\\\n        if (withdrawnWPowerPerpAmount > _vault.shortAmount) {\\\\n            uint256 excess = withdrawnWPowerPerpAmount.sub(_vault.shortAmount);\\\\n            withdrawnWPowerPerpAmount = _vault.shortAmount;\\\\n            wPowerPerp.transfer(_owner, excess);\\\\n        }\\\\n\\\\n        _vault.removeShort(withdrawnWPowerPerpAmount);\\\\n        wPowerPerp.burn(address(this), withdrawnWPowerPerpAmount);\\\\n\\\\n        return bounty;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev pay the fee to the fee recipient in eth from either the vault or the deposit amount\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _account the user address that pays the fee (either from transferred eth or vault eth)\\\\n     * @param _vaultId the user vault Id\\\\n     * @param _wSqueethAmount the amount of wSqueeth to mint\\\\n     * @param _depositAmount the amount depositing or withdrawing\\\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was removed from it\\\\n     */\\\\n    function _payFee(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _wSqueethAmount,\\\\n        uint256 _depositAmount\\\\n    ) internal returns (uint256) {\\\\n        uint256 cachedFeeRate = feeRate;\\\\n        if (cachedFeeRate == 0) return _depositAmount;\\\\n        uint256 depositAmountAfterFee;\\\\n        uint256 ethEquivalentMinted = Power2Base._getCollateralByRepayAmount(\\\\n            _wSqueethAmount,\\\\n            address(oracle),\\\\n            ethDaiPool,\\\\n            weth,\\\\n            dai,\\\\n            normalizationFactor\\\\n        );\\\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\\\n\\\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\\\n        if (_depositAmount > feeAmount) {\\\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\\\n            payable(feeRecipient).sendValue(feeAmount);\\\\n            // if not, adjust the vault to pay from the vault collateral\\\\n        } else {\\\\n            _vault.removeEthCollateral(feeAmount);\\\\n            payable(feeRecipient).sendValue(feeAmount);\\\\n            depositAmountAfterFee = _depositAmount;\\\\n        }\\\\n        //return the deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\\\n        return depositAmountAfterFee;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev write new vault structure to storage.\\\\n     */\\\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\\\n        vaults[_vaultId] = _vault;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev redeem a uni v3 position token and get back wPerp and eth.\\\\n     * @param _uniTokenId uniswap v3 position token id\\\\n     * @return wethAmount amount of weth withdrawn from uniswap\\\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\\\n     */\\\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\\\n\\\\n        (, , uint128 liquidity) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\\\n\\\\n        // prepare parameters to withdraw liquidity from Uniswap V3 Position Manager.\\\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\\\n            .DecreaseLiquidityParams({\\\\n                tokenId: _uniTokenId,\\\\n                liquidity: liquidity,\\\\n                amount0Min: 0,\\\\n                amount1Min: 0,\\\\n                deadline: block.timestamp\\\\n            });\\\\n\\\\n        // the decreaseLiquidity function returns the amount collectable by the owner.\\\\n        (uint256 amount0, uint256 amount1) = positionManager.decreaseLiquidity(decreaseParams);\\\\n\\\\n        // withdraw weth and wPowerPerp from Uniswap V3.\\\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\\\n            tokenId: _uniTokenId,\\\\n            recipient: address(this),\\\\n            amount0Max: uint128(amount0),\\\\n            amount1Max: uint128(amount1)\\\\n        });\\\\n\\\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\\\n\\\\n        bool cacheIsWethToken0 = isWethToken0; // cache storage variable\\\\n        uint256 wethAmount = cacheIsWethToken0 ? collectedToken0 : collectedToken1;\\\\n        uint256 wPowerPerpAmount = cacheIsWethToken0 ? collectedToken1 : collectedToken0;\\\\n\\\\n        return (wethAmount, wPowerPerpAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice Update the normalization factor as a way to pay funding.\\\\n     **/\\\\n    function _applyFunding() internal returns (uint256) {\\\\n        // only update the norm factor once per block\\\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\\\n\\\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\\\n\\\\n        emit NormalizationFactorUpdated(normalizationFactor, newNormalizationFactor, block.timestamp);\\\\n\\\\n        normalizationFactor = newNormalizationFactor;\\\\n        lastFundingUpdateTimestamp = block.timestamp;\\\\n\\\\n        return newNormalizationFactor;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate new normalization factor base on the current timestamp.\\\\n     * @return new normalization factor if funding happens in the current block.\\\\n     */\\\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\\\n        uint32 period = uint32(block.timestamp - lastFundingUpdateTimestamp);\\\\n\\\\n        // make sure we use the same period for mark and index, and this period won't cause revert.\\\\n        uint32 fairPeriod = _getFairPeriodForOracle(period);\\\\n\\\\n        // avoid reading normalizationFactor  from storage multiple times\\\\n        uint256 cacheNormFactor = normalizationFactor;\\\\n\\\\n        uint256 mark = Power2Base._getDenormalizedMark(\\\\n            fairPeriod,\\\\n            address(oracle),\\\\n            wPowerPerpPool,\\\\n            ethDaiPool,\\\\n            weth,\\\\n            dai,\\\\n            address(wPowerPerp),\\\\n            cacheNormFactor\\\\n        );\\\\n        uint256 index = Power2Base._getIndex(fairPeriod, address(oracle), ethDaiPool, weth, dai);\\\\n        uint256 rFunding = (uint256(1e18).mul(uint256(period))).div(SEC_IN_DAY);\\\\n\\\\n        // Truncate mark to be at least 80% of index\\\\n        uint256 lowerBound = index.mul(4).div(5);\\\\n        if (mark < lowerBound) mark = lowerBound;\\\\n\\\\n        // Truncate mark to be at most 120% of index\\\\n        uint256 upperBound = index.mul(5).div(4);\\\\n        if (mark > upperBound) mark = upperBound;\\\\n\\\\n        // mul by 1e36 to keep newNormalizationFactor in 18 decimals\\\\n        // uint256 newNormalizationFactor = (mark * 1e36) / (((1e18 + rFunding) * mark - index * rFunding));\\\\n        uint256 newNormalizationFactor = (mark.mul(1e36)).div(\\\\n            ((uint256(1e18).add(rFunding)).mul(mark).sub(index.mul(rFunding)))\\\\n        );\\\\n\\\\n        return cacheNormFactor.mul(newNormalizationFactor).div(1e18);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev check that the specified uni tokenId is a valid powerPerp/weth lp token.\\\\n     * @param _uniTokenId uniswap v3 position token id\\\\n     */\\\\n    function _checkUniNFT(uint256 _uniTokenId) internal view {\\\\n        (, , address token0, address token1, , , , , , , , ) = INonfungiblePositionManager(uniswapPositionManager)\\\\n            .positions(_uniTokenId);\\\\n        // only check token0 and token1, ignore fee.\\\\n        // If there are multiple wPowerPerp/eth pools with different fee rate, we accept LP tokens from all of them.\\\\n        address wPowerPerpAddr = address(wPowerPerp); // cache storage variable\\\\n        address wethAddr = weth; // cache storage variable\\\\n        require(\\\\n            (token0 == wPowerPerpAddr && token1 == wethAddr) || (token1 == wPowerPerpAddr && token0 == wethAddr),\\\\n            \\\\\\\"Invalid nft\\\\\\\"\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev revert if the vault is insolvent, or a dust vault\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _normalizationFactor normalization factor\\\\n     */\\\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        require(isSafe, \\\\\\\"Invalid state\\\\\\\");\\\\n        require(!isDust, \\\\\\\"dust vault\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev check that the vault is properly collateralized\\\\n     * @return if the vault is properly collateralized.\\\\n     */\\\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        return isSafe;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev get the vault latest status, if it's above water or a dust vault\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _normalizationFactor normalization factor\\\\n     * @return if the vault is safe\\\\n     * @return if the vault is a dust vault\\\\n     */\\\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\\\n        internal\\\\n        view\\\\n        returns (bool, bool)\\\\n    {\\\\n        uint256 scaledEthPrice = Power2Base._getScaledTwapSafe(address(oracle), ethDaiPool, weth, dai, 300);\\\\n        int24 perpPoolTick = oracle.getTimeWeightedAverageTickSafe(wPowerPerpPool, 300);\\\\n        return\\\\n            VaultLib.getVaultStatus(\\\\n                _vault,\\\\n                uniswapPositionManager,\\\\n                _normalizationFactor,\\\\n                scaledEthPrice,\\\\n                MIN_COLLATERAL,\\\\n                perpPoolTick,\\\\n                isWethToken0\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev get how much wPowerPerp will be exchanged for collateral given a max wPowerPerp amount and debt ceiling\\\\n     * @param _maxInputWAmount max wPowerPerp amount liquidator is willing to pay\\\\n     * @param _maxLiquidatableWAmount max wPowerPerp amount a liquidator can take out from a vault\\\\n     * @param _normalizationFactor normalization factor\\\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\\\n     * @return collateralToPay total collateral the liquidator will get\\\\n     */\\\\n    function _getLiquidationAmount(\\\\n        uint256 _maxInputWAmount,\\\\n        uint256 _maxLiquidatableWAmount,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\\\n            ? _maxLiquidatableWAmount\\\\n            : _maxInputWAmount;\\\\n\\\\n        uint256 collateralToPay = Power2Base._getCollateralByRepayAmount(\\\\n            finalWAmountToLiquidate,\\\\n            address(oracle),\\\\n            ethDaiPool,\\\\n            weth,\\\\n            dai,\\\\n            _normalizationFactor\\\\n        );\\\\n\\\\n        // add 10% bonus for liquidators\\\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\\\n\\\\n        return (finalWAmountToLiquidate, collateralToPay);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get a fair period that should be used to request twap for 2 pools\\\\n     * @dev if the period we want to use is greater than min(max_pool_1, max_pool_2),\\\\n     *      return min(max_pool_1, max_pool_2)\\\\n     * @param _period max period that we intend to use\\\\n     * @return fair period not greator than _period to be used for both pools.\\\\n     */\\\\n    function _getFairPeriodForOracle(uint32 _period) internal view returns (uint32) {\\\\n        uint32 maxSafePeriod = _getMaxSafePeriod();\\\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev get the smaller of the max periods of 2 pools\\\\n     * @return return min(max_pool_1, max_pool_2)\\\\n     */\\\\n    function _getMaxSafePeriod() internal view returns (uint32) {\\\\n        uint32 maxPeriodPool1 = oracle.getMaxPeriod(ethDaiPool);\\\\n        uint32 maxPeriodPool2 = oracle.getMaxPeriod(wPowerPerpPool);\\\\n        return maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb25cc0250b75c74be6e8841a78a103fc107a4649b7a0d535f451f68a852db006\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwapSafe(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc2a9dc58cdc5a3468bdc3ca484a74a74cbfdd409064290742611a62c1dffb347\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IVaultManagerNFT.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IVaultManagerNFT is IERC721 {\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x81f45bd99b1b8b1d67f5684145c8b3723ae8e50d950408a1e7079dd89b899057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8a9a4512f1fc29b14dcf97ca149f263f28de43191a3ee31336f2389e3f2f5f8e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/Power2Base.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {OracleLibrary} from \\\\\\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\\\\\";\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\nlibrary Power2Base {\\\\n    using SafeMath for uint256;\\\\n\\\\n    uint256 constant INDEX_SCALE = 1e4;\\\\n\\\\n    /**\\\\n     * @dev return the index of the power perp in DAI, scaled by 18 decimals\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethDaiPool,\\\\n        address _weth,\\\\n        address _dai\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethDaiPrice = _getScaledTwap(_oracle, _ethDaiPool, _weth, _dai, _period);\\\\n        return ethDaiPrice.mul(ethDaiPrice).div(1e18);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev return the mark price of power perp in DAI, scaled by 18 decimals\\\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\\\n     */\\\\n    function _getDenormalizedMark(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _ethDaiPool,\\\\n        address _weth,\\\\n        address _dai,\\\\n        address _wsqueeth,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethDaiPrice = _getScaledTwap(_oracle, _ethDaiPool, _weth, _dai, _period);\\\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, address(_wsqueeth), _weth, _period);\\\\n\\\\n        return wsqueethEthPrice.mul(ethDaiPrice).div(_normalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev get fair collateral amount to pay out to a liquidator repaying _debtAmount debt\\\\n     * @dev the actual amount liquidator can get should have a x% bonus on top of this value.\\\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\\\n     * @return\\\\n     */\\\\n    function _getCollateralByRepayAmount(\\\\n        uint256 _debtAmount,\\\\n        address _oracle,\\\\n        address _ethDaiPool,\\\\n        address _weth,\\\\n        address _dai,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethDaiPrice = _getScaledTwap(_oracle, _ethDaiPool, _weth, _dai, 600);\\\\n        return _debtAmount.mul(_normalizationFactor).mul(ethDaiPrice).div(1e36);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev request twap from our oracle, scaled down by INDEX_SCALE\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev request twap from our oracle, sacled down by INDEX_SCALE\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwapSafe(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwapSafe(_oracle, _pool, _base, _quote, _period);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev request twap from our oracle.\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        // period reaching this point should be check, otherwise might revert\\\\n        uint256 twap = IOracle(_oracle).getTwap(_pool, _base, _quote, _period);\\\\n        require(twap != 0, \\\\\\\"WAP WAP WAP\\\\\\\");\\\\n        return twap;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev request twap from our oracle.\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwapSafe(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        return IOracle(_oracle).getTwapSafe(_pool, _base, _quote, _period);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\\\n     * @param _indexPriceForSettlement scaled down price used for settlement.\\\\n     * @return amount in wei that should be paid to the token holder\\\\n     */\\\\n    function _getLongSettlementValue(\\\\n        uint256 _wsqueethAmount,\\\\n        uint256 _indexPriceForSettlement,\\\\n        uint256 _normalizationFactor\\\\n    ) internal pure returns (uint256) {\\\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(1e36);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7c595e71fb1d8b69733b55146e52c1ee6d03fff21a1d9959b40c5affba7aebda\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\\\\\\\";\\\\n\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n\\\\n    struct Vault {\\\\n        // the address who can update the vault.\\\\n        address operator;\\\\n        // uniswap v3 position token id deposited into the vault to increase collateral ratio\\\\n        // 2^32 is 4,294,967,296. If Uniswap has more than 4 billion positions, our vault structure might stop working.\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // uint96 is safe enough cuz 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth.\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow.\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint96(uint256(_vault.collateralAmount).add(_amount));\\\\n    }\\\\n\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"Vault already had nft\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"invalid id\\\\\\\");\\\\n        _vault.NftCollateralId = uint32(_tokenId);\\\\n    }\\\\n\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint96(uint256(_vault.collateralAmount).sub(_amount));\\\\n    }\\\\n\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"Vault has no NFT\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint128(uint256(_vault.shortAmount).add(_amount));\\\\n    }\\\\n\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint128(uint256(_vault.shortAmount).sub(_amount));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev see if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uni v3 position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethDaiPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral min collateral need to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is above water.\\\\n     * @return true if the vault is considered as a dust vault.\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethDaiPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n        return\\\\n            _getVaultStatus(\\\\n                _vault,\\\\n                _positionManager,\\\\n                _normalizationFactor,\\\\n                _ethDaiPrice,\\\\n                _minCollateral,\\\\n                _wsqueethPoolTick,\\\\n                _isWethToken0\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev see if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uni v3 position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethDaiPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral min collateral need to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is above water.\\\\n     * @return true if the vault is considered as a dust vault.\\\\n     */\\\\n    function _getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethDaiPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethDaiPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(2) >= debtValueInETH.mul(3);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uni position token equivelent amount of eth.\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uni v3 position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethDaiPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethDaiPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposit univ3 position token as collateral, see how much eth / squeeth the LP token has.\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from NFT as equivalent amount of collateral.\\\\n        uint256 equivalentCollateral = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\\\n        // add ETH value from NFT as collateral.\\\\n        return nftEthAmount.add(equivalentCollateral).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get how much eth / squeeth the LP position is worth.\\\\n     * @param _positionManager address of the uni v3 position manager\\\\n     * @param _tokenId lp token id\\\\n     * @param _wsqueethPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount thie LP token is worth\\\\n     * @return squeethAmount the squeeth amount this LP token is worth\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 squeethAmount) {\\\\n        (int24 tickLower, int24 tickUpper, uint128 liquidity) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wsqueethPoolTick,\\\\n            liquidity\\\\n        );\\\\n        return (_isWethToken0 ? amount0 : amount1, _isWethToken0 ? amount1 : amount0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the LP info and tick bond of the LP position.\\\\n     * @param _positionManager address of the uni v3 position manager\\\\n     * @param _tokenId LP token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (, , , , , int24 tickLower, int24 tickUpper, uint128 liquidity, , , , ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get how much token0 / token1 a LP position is worth.\\\\n     * @param _tickLower address of the uni v3 position manager\\\\n     * @param _tickUpper LP token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 this LP token is worth\\\\n     * @return amount1 the amount of token1 this LP token is worth\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from squeethPool\\\\n        uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(_tick);\\\\n\\\\n        // the following line is copied from the _modifyPosition function implemented by Uniswap core.\\\\n        // we use the same logic to determine how much token0, token1 equals to given \\\\\\\"liquidity\\\\\\\"\\\\n        // https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/UniswapV3Pool.sol#L306\\\\n\\\\n        // use these 2 functions directly, cuz liquidity is always positive\\\\n        // getAmount0Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L209\\\\n        // getAmount1Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L225\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb587ac0a5a37cc635bb6ec45c88b7ddedf0133196131cd0230c41ecd8b753aa6\\\",\\\"license\\\":\\\"MIT\\\"},\\\"hardhat/console.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >= 0.4.22 <0.9.0;\\\\n\\\\nlibrary console {\\\\n\\\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\\\n\\\\n\\\\tfunction _sendLogPayload(bytes memory payload) private view {\\\\n\\\\t\\\\tuint256 payloadLength = payload.length;\\\\n\\\\t\\\\taddress consoleAddress = CONSOLE_ADDRESS;\\\\n\\\\t\\\\tassembly {\\\\n\\\\t\\\\t\\\\tlet payloadStart := add(payload, 32)\\\\n\\\\t\\\\t\\\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\\\n\\\\t\\\\t}\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log() internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log()\\\\\\\"));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logInt(int p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(int)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logUint(uint p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logString(string memory p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBool(bool p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logAddress(address p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes(bytes memory p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes1(bytes1 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes1)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes2(bytes2 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes2)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes3(bytes3 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes3)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes4(bytes4 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes4)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes5(bytes5 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes5)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes6(bytes6 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes6)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes7(bytes7 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes7)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes8(bytes8 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes8)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes9(bytes9 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes9)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes10(bytes10 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes10)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes11(bytes11 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes11)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes12(bytes12 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes12)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes13(bytes13 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes13)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes14(bytes14 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes14)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes15(bytes15 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes15)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes16(bytes16 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes16)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes17(bytes17 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes17)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes18(bytes18 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes18)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes19(bytes19 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes19)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes20(bytes20 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes20)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes21(bytes21 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes21)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes22(bytes22 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes22)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes23(bytes23 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes23)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes24(bytes24 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes24)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes25(bytes25 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes25)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes26(bytes26 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes26)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes27(bytes27 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes27)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes28(bytes28 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes28)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes29(bytes29 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes29)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes30(bytes30 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes30)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes31(bytes31 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes31)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction logBytes32(bytes32 p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bytes32)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address)\\\\\\\", p0));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address)\\\\\\\", p0, p1));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, uint p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,uint)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, string memory p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,string)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, bool p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,bool)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, address p2) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,address)\\\\\\\", p0, p1, p2));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,uint,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,string,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,bool,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(uint,address,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,uint,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,string,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,bool,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(string,address,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,uint,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,string,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,bool,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(bool,address,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,uint,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,string,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,bool,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,uint,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,uint,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,uint,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,uint,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,string,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,string,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,string,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,string,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,bool,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,bool,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,bool,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,bool,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,address,uint)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,address,string)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,address,bool)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n\\\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\\\n\\\\t\\\\t_sendLogPayload(abi.encodeWithSignature(\\\\\\\"log(address,address,address,address)\\\\\\\", p0, p1, p2, p3));\\\\n\\\\t}\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x72b6a1d297cd3b033d7c2e4a7e7864934bb767db6453623f1c3082c6534547f4\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n    \"bytecode\": \"0x60806040526000805461ffff60b01b1916815560046001556002553480156200002757600080fd5b506000620000346200008e565b6000805462010000600160b01b031916620100006001600160a01b038416908102919091178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35062000092565b3390565b6152da80620000a26000396000f3fe6080604052600436106103385760003560e01c80638c64ea4a116101b0578063cc4b1473116100ec578063ed88c68e11610095578063f2fde38b1161006f578063f2fde38b1461082f578063f3a50fe31461084f578063f4b9fa7514610870578063ff9475251461088557610372565b8063ed88c68e146107f2578063ee3189ff146107fa578063ef0b69dd1461081a57610372565b8063de4a427a116100c6578063de4a427a146107a8578063e5047b30146107bd578063e74b981b146107d257610372565b8063cc4b147314610760578063d296d1f114610773578063d52725841461079357610372565b806397efa94211610159578063b6b55f2511610133578063b6b55f25146106f8578063b707ab991461070b578063c65a391d14610720578063c9e77ee81461074057610372565b806397efa94214610698578063a847e674146106b8578063ac6cd5ef146106d857610372565b806391b4ded91161018a57806391b4ded91461064e57806391b8d34a14610663578063978bbdb91461068357610372565b80638c64ea4a146105e95780638cd21d7c146106195780638da5cb5b1461063957610372565b8063607ad0d71161027f5780637b44b4fd116102285780638146b09f116102025780638146b09f1461058a5780638456cb591461059f57806384dea1a1146105b45780638632cb03146105c957610372565b80637b44b4fd1461054b5780637dc0d1d0146105605780637f07b1301461057557610372565b8063715018a611610259578063715018a6146104ff5780637691c4ac1461051457806376adb9641461053657610372565b8063607ad0d7146104b557806363b38ae4146104ca578063713d517f146104df57610372565b80634394318d116102e157806346904840116102bb578063469048401461046b5780634be2822c14610480578063525240c01461049557610372565b80634394318d14610418578063441a3e701461043857806345596e2e1461044b57610372565b806324f5f5311161031257806324f5f531146103b65780632d8f1d90146103e15780633fc8cef3146103f657610372565b8063076336691461037757806310b9e5831461038c578063200f4b8d146103a157610372565b36610372576003546001600160a01b031633146103705760405162461bcd60e51b815260040161036790614d4b565b60405180910390fd5b005b600080fd5b34801561038357600080fd5b5061037061089a565b34801561039857600080fd5b5061037061098b565b3480156103ad57600080fd5b50610370610ab0565b3480156103c257600080fd5b506103cb610ae5565b6040516103d89190615156565b60405180910390f35b3480156103ed57600080fd5b50610370610af5565b34801561040257600080fd5b5061040b610c40565b6040516103d89190614a16565b34801561042457600080fd5b506103cb6104333660046148d4565b610c4f565b610370610446366004614890565b610c92565b34801561045757600080fd5b506103706104663660046147fa565b610d5b565b34801561047757600080fd5b5061040b610e58565b34801561048c57600080fd5b506103cb610e67565b3480156104a157600080fd5b506103706104b0366004614718565b610e6d565b3480156104c157600080fd5b506103cb6110f8565b3480156104d657600080fd5b506103cb6110fe565b3480156104eb57600080fd5b506103706104fa3660046147fa565b611104565b34801561050b57600080fd5b506103706111cb565b34801561052057600080fd5b506105296112a6565b6040516103d89190614ae3565b34801561054257600080fd5b5061040b6112b6565b34801561055757600080fd5b506103cb6112c5565b34801561056c57600080fd5b5061040b6112cc565b34801561058157600080fd5b5061040b6112db565b34801561059657600080fd5b506103706112ea565b3480156105ab57600080fd5b50610370611363565b3480156105c057600080fd5b5061040b6114b3565b3480156105d557600080fd5b506103706105e43660046148d4565b6114c2565b3480156105f557600080fd5b506106096106043660046147fa565b6114fa565b6040516103d89493929190614aa0565b34801561062557600080fd5b506103cb6106343660046148ff565b61154c565b34801561064557600080fd5b5061040b611583565b34801561065a57600080fd5b506103cb611598565b34801561066f57600080fd5b5061037061067e366004614890565b61159e565b34801561068f57600080fd5b506103cb611649565b3480156106a457600080fd5b506103706106b33660046147fa565b61164f565b3480156106c457600080fd5b506105296106d33660046147fa565b61178f565b3480156106e457600080fd5b506103706106f33660046147fa565b611816565b6103706107063660046147fa565b6118c4565b34801561071757600080fd5b5061040b611978565b34801561072c57600080fd5b5061037061073b36600461482a565b611987565b34801561074c57600080fd5b5061037061075b3660046147fa565b611a1f565b6103cb61076e366004614859565b611b77565b34801561077f57600080fd5b506103cb61078e366004614890565b611bc6565b34801561079f57600080fd5b506103cb611dc0565b3480156107b457600080fd5b506103cb611dc6565b3480156107c957600080fd5b5061040b611dcc565b3480156107de57600080fd5b506103706107ed3660046146e0565b611ddb565b610370611eeb565b34801561080657600080fd5b506103cb6108153660046148ff565b611f16565b34801561082657600080fd5b50610529611f5b565b34801561083b57600080fd5b5061037061084a3660046146e0565b611f64565b61086261085d366004614859565b61209c565b6040516103d8929190615176565b34801561087c57600080fd5b5061040b6120ed565b34801561089157600080fd5b506105296120fc565b600054600160b01b900460ff16156108c45760405162461bcd60e51b815260040161036790614ff4565b600054600160b81b900460ff166108ed5760405162461bcd60e51b815260040161036790614d14565b6108f561210c565b6001600160a01b0316610906611583565b6001600160a01b031614610961576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff169055565b600054600160b01b900460ff16156109b55760405162461bcd60e51b815260040161036790614ff4565b600054600160b81b900460ff166109de5760405162461bcd60e51b815260040161036790614d14565b6109e661210c565b6001600160a01b03166109f7611583565b6001600160a01b031614610a52576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff16600160b01b179055601254600554600354600454610aab936001600160a01b039081169381169281169116610258612110565b600a55565b600054600160b81b900460ff1615610ada5760405162461bcd60e51b81526004016103679061502b565b610ae261213b565b50565b6000610aef6121a7565b90505b90565b600054600160b01b900460ff1615610b1f5760405162461bcd60e51b815260040161036790614ff4565b600054600160b81b900460ff1615610b495760405162461bcd60e51b81526004016103679061502b565b610b5161210c565b6001600160a01b0316610b62611583565b6001600160a01b031614610bbd576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff909116600160b81b1716600160b01b179055601254600554600354600454610aab936001600160a01b039081169381169281169116610258612110565b6003546001600160a01b031681565b60008054600160b81b900460ff1615610c7a5760405162461bcd60e51b81526004016103679061502b565b610c88338585856000612311565b90505b9392505050565b600054600160b81b900460ff1615610cbc5760405162461bcd60e51b81526004016103679061502b565b6000610cc661213b565b6000848152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b03166060820152909150610d41813386866123f5565b610d4b818361247a565b610d5584826124c6565b50505050565b610d6361210c565b6001600160a01b0316610d74611583565b6001600160a01b031614610dcf576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6006546001600160a01b0316610df75760405162461bcd60e51b815260040161036790614e16565b6064811115610e185760405162461bcd60e51b815260040161036790614e84565b7f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95760095482604051610e4b929190615176565b60405180910390a1600955565b6006546001600160a01b031681565b600c5481565b600054610100900460ff1680610e865750610e866125be565b80610e94575060005460ff16155b610ecf5760405162461bcd60e51b815260040180806020018281038252602e815260200180615256602e913960400191505060405180910390fd5b600054610100900460ff16158015610efa576000805460ff1961ff0019909116610100171660011790555b6001600160a01b038916610f205760405162461bcd60e51b815260040161036790614f29565b6001600160a01b038816610f465760405162461bcd60e51b815260040161036790614b25565b6001600160a01b038716610f6c5760405162461bcd60e51b815260040161036790614aee565b6001600160a01b038616610f925760405162461bcd60e51b815260040161036790614ef2565b6001600160a01b038516610fb85760405162461bcd60e51b815260040161036790614c38565b6001600160a01b038416610fde5760405162461bcd60e51b815260040161036790614ebb565b6001600160a01b0383166110045760405162461bcd60e51b815260040161036790614db9565b6001600160a01b03821661102a5760405162461bcd60e51b815260040161036790614cdd565b6012805473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b038c8116919091179092556010805482168b84161790556011805482168a84169081179091556005805483168885161790556007805483168785161790556008805483168685161790556003805483168a851617908190556004805490931689851617909255670de0b6b3a7640000600b5542600c819055600d55600e8054929093161060ff1990911617905580156110ed576000805461ff00191690555b505050505050505050565b600d5481565b60015481565b600054600160b81b900460ff161561112e5760405162461bcd60e51b81526004016103679061502b565b600061113861213b565b6000838152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b031660608201529091506111b28133856125cf565b6111bc818361247a565b6111c683826124c6565b505050565b6111d361210c565b6001600160a01b03166111e4611583565b6001600160a01b03161461123f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60008054604051620100009091046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff169055565b600054600160b81b900460ff1681565b6005546001600160a01b031681565b62eff10081565b6012546001600160a01b031681565b6011546001600160a01b031681565b600054600160b01b900460ff16156113145760405162461bcd60e51b815260040161036790614ff4565b600054600160b81b900460ff1661133d5760405162461bcd60e51b815260040161036790614d14565b600254620151800142116109615760405162461bcd60e51b815260040161036790614f97565b600054600160b01b900460ff161561138d5760405162461bcd60e51b815260040161036790614ff4565b600054600160b81b900460ff16156113b75760405162461bcd60e51b81526004016103679061502b565b6113bf61210c565b6001600160a01b03166113d0611583565b6001600160a01b03161461142b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60006001541161144d5760405162461bcd60e51b815260040161036790614f60565b600d54420362eff10081106114745760405162461bcd60e51b815260040161036790614bca565b50600080547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16600160b81b1790556001805460001901905542600255565b6010546001600160a01b031681565b600054600160b81b900460ff16156114ec5760405162461bcd60e51b81526004016103679061502b565b610d55338484846001612311565b600f60205260009081526040902080546001909101546001600160a01b03821691600160a01b900463ffffffff16906bffffffffffffffffffffffff811690600160601b90046001600160801b031684565b60125460055460035460045460009361157b9386936001600160a01b03928316939183169290811691166126b9565b90505b919050565b6000546201000090046001600160a01b031690565b60025481565b600054600160b81b900460ff16156115c85760405162461bcd60e51b81526004016103679061502b565b6115d061213b565b506000828152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b031660608201526111bc813385856126e1565b60095481565b600054600160b01b900460ff166116785760405162461bcd60e51b815260040161036790614b5c565b61168281336127a4565b61169e5760405162461bcd60e51b815260040161036790614c01565b6000818152600f60209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546bffffffffffffffffffffffff811691830191909152600160601b90046001600160801b03166060820152600b54909161171c9083903390849061285c565b50600061173b83606001516001600160801b0316600a54600b54612ae8565b905060006117648285604001516bffffffffffffffffffffffff16612b0b90919063ffffffff16565b6000606086018190526040860152905061177e85856124c6565b6117883382612b68565b5050505050565b6000818152600f60209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546bffffffffffffffffffffffff811691830191909152600160601b90046001600160801b03166060820152816118026121a7565b905061180e8282612c4d565b949350505050565b600054600160b01b900460ff1661183f5760405162461bcd60e51b815260040161036790614b5c565b601154604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac906118719033908590600401614a4e565b600060405180830381600087803b15801561188b57600080fd5b505af115801561189f573d6000803e3d6000fd5b5050505060006118b482600a54600b54612ae8565b90506118c03382612b68565b5050565b600054600160b81b900460ff16156118ee5760405162461bcd60e51b81526004016103679061502b565b6118f661213b565b506000818152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b0316606082015261196e818334612c63565b6118c082826124c6565b6007546001600160a01b031681565b61199182336127a4565b6119ad5760405162461bcd60e51b815260040161036790614c01565b6000828152600f602052604090819020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038416179055517f9d9dd80a56a16f715df6eb40b771e24ff8cbea6eed9de28473ce0f28fe5602a990611a13908490849061515f565b60405180910390a15050565b600054600160b81b900460ff1615611a495760405162461bcd60e51b81526004016103679061502b565b611a5381336127a4565b611a6f5760405162461bcd60e51b815260040161036790614c01565b6000611a7961213b565b6000838152600f6020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093526001909101546bffffffffffffffffffffffff811682850152600160601b90046001600160801b0316606082015260105492516331a9108f60e11b815293945092611b6c9284921690636352211e90611b14908890600401615156565b60206040518083038186803b158015611b2c57600080fd5b505afa158015611b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6491906146fc565b84600061285c565b506111c683826124c6565b60008054600160b81b900460ff1615611ba25760405162461bcd60e51b81526004016103679061502b565b6000611bbc3386866001600160801b031634876001612cae565b5095945050505050565b60008054600160b81b900460ff1615611bf15760405162461bcd60e51b81526004016103679061502b565b6000611bfb61213b565b6000858152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b03166060820152909150611c748183612c4d565b15611c915760405162461bcd60e51b815260040161036790614c6f565b6010546040516331a9108f60e11b8152600091611d209184916001600160a01b031690636352211e90611cc8908b90600401615156565b60206040518083038186803b158015611ce057600080fd5b505afa158015611cf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1891906146fc565b85600161285c565b9050611d2c8284612c4d565b15611d5157611d3b3382612b68565b611d4586836124c6565b60009350505050611dba565b611d5b8282612de1565b600080611d6a84888733612e18565b915091507f199c51a8cd3b6aa8f80abc4f5c713f20c111837887163a1bbaa2dd5f61a554ab888383604051611da1939291906151a3565b60405180910390a1611db388856124c6565b5093505050505b92915050565b600b5481565b600a5481565b6008546001600160a01b031681565b611de361210c565b6001600160a01b0316611df4611583565b6001600160a01b031614611e4f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611e755760405162461bcd60e51b815260040161036790614ca6565b6006546040517faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d391611eb4916001600160a01b03909116908490614a67565b60405180910390a16006805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600054600160b01b900460ff16611f145760405162461bcd60e51b815260040161036790614b5c565b565b600080611f216121a7565b601254600754600554600354600454601154959650610c8b9589956001600160a01b03908116958116948116938116928116911688612f8d565b600e5460ff1681565b611f6c61210c565b6001600160a01b0316611f7d611583565b6001600160a01b031614611fd8576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03811661201d5760405162461bcd60e51b81526004018080602001828103825260268152602001806151f66026913960400191505060405180910390fd5b600080546040516001600160a01b03808516936201000090930416917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0390921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff909216919091179055565b600080548190600160b81b900460ff16156120c95760405162461bcd60e51b81526004016103679061502b565b6120e13386866001600160801b031634876000612cae565b91509150935093915050565b6004546001600160a01b031681565b600054600160b01b900460ff1681565b3390565b6000806121208787878787612fcd565b905061212e816127106130db565b9150505b95945050505050565b600042600c5414156121505750600b54610af2565b600061215a6121a7565b90507fa5e6eb88e05b1ccc7e1a9a5096d0a5b8aef97d5204e0ad78ffda42affd8374a8600b548242604051612191939291906151a3565b60405180910390a1600b81905542600c55905090565b600c546000904203816121b982613142565b600b5460125460075460055460035460045460115496975094956000956121fe9589956001600160a01b03918216959082169490821693908216928216911689612f8d565b6012546005546003546004549394506000936122309388936001600160a01b03918216939082169290821691166126b9565b9050600061225c62015180612256670de0b6b3a764000063ffffffff808b169061316816565b906130db565b905060006122706005612256856004613168565b90508084101561227e578093505b60006122906004612256866005613168565b90508085111561229e578094505b60006122eb6122d26122b08787613168565b6122cc896122c6670de0b6b3a76400008a6131c1565b90613168565b90612b0b565b612256886ec097ce7bc90715b34b9f1000000000613168565b9050612303670de0b6b3a76400006122568984613168565b995050505050505050505090565b60008061231c61213b565b90506000836123405761233b8261225688670de0b6b3a7640000613168565b612342565b855b6000888152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b0316606082015290915081156123c3576123c3818a8a8561321b565b85156123d5576123d5818a8a896123f5565b6123df818461247a565b6123e988826124c6565b50979650505050505050565b6123ff82846127a4565b61241b5760405162461bcd60e51b815260040161036790614c01565b61242584826132ba565b6124386001600160a01b03841682612b68565b7ffd6fe60d4c49c077689d373f95adff80f09e02e5f719b842f6e3cfc812546a908282600060405161246c93929190615184565b60405180910390a150505050565b60008061248784846132d7565b91509150816124a85760405162461bcd60e51b815260040161036790614d82565b8015610d555760405162461bcd60e51b815260040161036790614e4d565b6000918252600f6020908152604092839020825181549284015163ffffffff16600160a01b027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff6001600160a01b0390921673ffffffffffffffffffffffffffffffffffffffff19909416939093171691909117815591810151600190920180546060909201516001600160801b0316600160601b027fffffffff00000000000000000000000000000000ffffffffffffffffffffffff6bffffffffffffffffffffffff9094167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009093169290921792909216179055565b60006125c9306133f0565b15905090565b6125d981836127a4565b6125f55760405162461bcd60e51b815260040161036790614c01565b602083015163ffffffff16612609846133f6565b6008546040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906323b872dd9061265690309087908690600401614a2a565b600060405180830381600087803b15801561267057600080fd5b505af1158015612684573d6000803e3d6000fd5b505050507fe408b929e3c702ebaee90bb2112c954eabc66448f7d3e6a26faf67e40af3666b828260405161246c929190615176565b6000806126c9868686868b612110565b905061212e670de0b6b3a76400006122568380613168565b6126ea8161345c565b6126f48482613597565b6008546040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906323b872dd9061274190869030908690600401614a2a565b600060405180830381600087803b15801561275b57600080fd5b505af115801561276f573d6000803e3d6000fd5b505050507fa73a85546850efb41a3bae76ec46116507eaa88fef566468556ce065e24519a4828260405161246c929190615176565b6010546040516331a9108f60e11b81526000916001600160a01b0380851692911690636352211e906127da908790600401615156565b60206040518083038186803b1580156127f257600080fd5b505afa158015612806573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282a91906146fc565b6001600160a01b03161480610c8b5750506000918252600f6020526040909120546001600160a01b0390811691161490565b602084015160009063ffffffff168061287957600091505061180e565b60008061288583613654565b9092509050811561290c576003546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632e1a7d4d906128d9908590600401615156565b600060405180830381600087803b1580156128f357600080fd5b505af1158015612907573d6000803e3d6000fd5b505050505b600085156129645760125460055460035460045460009361294e9388936129489389936001600160a01b0390811693811692811691168f613834565b906131c1565b90506129606064612256836002613168565b9150505b61296d896133f6565b6129778984612de1565b61298189826132ba565b88606001516001600160801b0316821115612a6d5760006129b88a606001516001600160801b031684612b0b90919063ffffffff16565b60608b01516011546040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160801b0390921695509192506001600160a01b039091169063a9059cbb90612a18908c908590600401614a4e565b602060405180830381600087803b158015612a3257600080fd5b505af1158015612a46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6a91906147c0565b50505b612a778983613875565b601154604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac90612aa99030908690600401614a4e565b600060405180830381600087803b158015612ac357600080fd5b505af1158015612ad7573d6000803e3d6000fd5b50929b9a5050505050505050505050565b6000610c886ec097ce7bc90715b34b9f1000000000612256856122c68887613168565b600082821115612b62576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b80471015612bbd576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114612c08576040519150601f19603f3d011682016040523d82523d6000602084013e612c0d565b606091505b50509050806111c65760405162461bcd60e51b815260040180806020018281038252603a81526020018061521c603a913960400191505060405180910390fd5b600080612c5a84846132d7565b50949350505050565b612c6d8382612de1565b7f7a0373b035a03ee781adee2e2f1920bf98084e3485bfdd8a99acf44fd0feaace82826000604051612ca193929190615184565b60405180910390a1505050565b6000806000612cbb61213b565b905085600085612ce057612cdb836122568b670de0b6b3a7640000613168565b612ce2565b885b9050612cec61467e565b8a612d0457612cfa8c6138a2565b909b509050612d72565b5060008a8152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b031660608201525b8115612d8857612d85818d8d858d6139ae565b92505b8815612d9957612d99818c85612c63565b8715612dab57612dab818d8d8b6126e1565b8115612dbd57612dbd818d8d85613a70565b612dc7818561247a565b612dd18b826124c6565b50989a9899505050505050505050565b6040820151612dfe906bffffffffffffffffffffffff16826131c1565b6bffffffffffffffffffffffff1660409092019190915250565b6060840151604085015160009182916001600160801b03909116906bffffffffffffffffffffffff168280612e5889612e528660026130db565b8a613b4e565b9150915080831115612e8e576706f05b59d3b20000612e778483612b0b565b1015612e8e57612e8889858a613b4e565b90925090505b82811115612ebc5783891015612eb65760405162461bcd60e51b815260040161036790614b93565b50829050815b601154604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac90612eee908a908690600401614a4e565b600060405180830381600087803b158015612f0857600080fd5b505af1158015612f1c573d6000803e3d6000fd5b50505050612f33828b61387590919063ffffffff16565b612f3d8a826132ba565b6000612f498b8a6132d7565b9150508015612f6a5760405162461bcd60e51b815260040161036790615062565b612f7d6001600160a01b03891683612b68565b5090999098509650505050505050565b600080612f9d898888888e612110565b90506000612fae8a8a878a8f612fcd565b9050612fbe846122568385613168565b9b9a5050505050505050505050565b604080517f821b972a0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301528581166024830152848116604483015263ffffffff84166064830152915160009283929089169163821b972a91608480820192602092909190829003018186803b15801561305157600080fd5b505afa158015613065573d6000803e3d6000fd5b505050506040513d602081101561307b57600080fd5b50519050806130d1576040805162461bcd60e51b815260206004820152600b60248201527f5741502057415020574150000000000000000000000000000000000000000000604482015290519081900360640190fd5b9695505050505050565b6000808211613131576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161313a57fe5b049392505050565b60008061314d613bba565b90508063ffffffff168363ffffffff1611611dba5782610c8b565b60008261317757506000611dba565b8282028284828161318457fe5b0414610c8b5760405162461bcd60e51b81526004018080602001828103825260218152602001806152846021913960400191505060405180910390fd5b600082820183811015610c8b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6132258482613875565b601154604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac906132579086908590600401614a4e565b600060405180830381600087803b15801561327157600080fd5b505af1158015613285573d6000803e3d6000fd5b505050507fc3fe83ab1ba331ef06ed00bc6f8615de1577dc77772a83e3264864de6a94ea8d818360405161246c929190615176565b6040820151612dfe906bffffffffffffffffffffffff1682612b0b565b6012546005546003546004546000938493849361330b936001600160a01b039384169392831692918216911661012c613d22565b6012546007546040517f4a0a96eb0000000000000000000000000000000000000000000000000000000081529293506000926001600160a01b0392831692634a0a96eb926133629291169061012c90600401614a81565b60206040518083038186803b15801561337a57600080fd5b505afa15801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b291906147e0565b600854600e549192506133e39188916001600160a01b031690889086906706f05b59d3b2000090879060ff16613d32565b9350935050509250929050565b3b151590565b602081015163ffffffff16613452576040805162461bcd60e51b815260206004820152601060248201527f5661756c7420686173206e6f204e465400000000000000000000000000000000604482015290519081900360640190fd5b6000602090910152565b6008546040517f99fbab8800000000000000000000000000000000000000000000000000000000815260009182916001600160a01b03909116906399fbab88906134aa908690600401615156565b6101806040518083038186803b1580156134c357600080fd5b505afa1580156134d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fb9190614937565b5050601154600354989c50969a50506001600160a01b03958616985050509383169450505085168314905080156135435750806001600160a01b0316836001600160a01b0316145b8061357b5750816001600160a01b0316836001600160a01b031614801561357b5750806001600160a01b0316846001600160a01b0316145b6117885760405162461bcd60e51b815260040161036790615099565b602082015163ffffffff16156135f4576040805162461bcd60e51b815260206004820152601560248201527f5661756c7420616c726561647920686164206e66740000000000000000000000604482015290519081900360640190fd5b80613646576040805162461bcd60e51b815260206004820152600a60248201527f696e76616c696420696400000000000000000000000000000000000000000000604482015290519081900360640190fd5b63ffffffff16602090910152565b60085460009081906001600160a01b0316816136708286613d77565b9250505060006040518060a00160405280878152602001836001600160801b031681526020016000815260200160008152602001428152509050600080846001600160a01b0316630c49ccbe846040518263ffffffff1660e01b81526004016136d99190615113565b6040805180830381600087803b1580156136f257600080fd5b505af1158015613706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061372a91906148b1565b604080516080810182528b81523060208201526001600160801b03808516828401528316606082015290517ffc6f78650000000000000000000000000000000000000000000000000000000081529294509092509060009081906001600160a01b0389169063fc6f7865906137a39086906004016150d0565b6040805180830381600087803b1580156137bc57600080fd5b505af11580156137d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137f491906148b1565b600e54919350915060ff1660008161380c578261380e565b835b905060008261381d578461381f565b835b919c50909a5050505050505050505050915091565b60008061384687878787610258612110565b90506138696ec097ce7bc90715b34b9f1000000000612256836122c68c88613168565b98975050505050505050565b606082015161388d906001600160801b031682612b0b565b6001600160801b031660609092019190915250565b60006138ac61467e565b6010546040517f54ba0f270000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906354ba0f27906138f6908790600401614a16565b602060405180830381600087803b15801561391057600080fd5b505af1158015613924573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139489190614812565b6040805160808101825260008082526020820181905281830181905260608201529051919250907f5f5dd6438bd675e0dba85db7517ba5931be5b31a11e5af8c04ea0e9152fa7ec59061399c908490615156565b60405180910390a19092509050915091565b600954600090806139c25782915050612132565b601254600554600354600454600b5460009485946139f8948b946001600160a01b03938416949284169391821692911690613834565b90506000613a0c6127106122568487613168565b905080861115613a3e57613a208682612b0b565b600654909350613a39906001600160a01b031682612b68565b613a62565b613a488a826132ba565b600654613a5e906001600160a01b031682612b68565b8592505b509098975050505050505050565b613a7a82846127a4565b613a965760405162461bcd60e51b815260040161036790614c01565b613aa08482613e17565b6011546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906340c10f1990613aeb9086908590600401614a4e565b600060405180830381600087803b158015613b0557600080fd5b505af1158015613b19573d6000803e3d6000fd5b505050507f0dd703a01208414af8d8c0d38f96263f1c708720550808d8af1985608014387a818360405161246c929190615176565b6000806000848611613b605785613b62565b845b601254600554600354600454939450600093613b959386936001600160a01b03918216939082169290821691168a613834565b9050613bac613ba582600a6130db565b82906131c1565b919791965090945050505050565b6012546005546040517fde5a6e2200000000000000000000000000000000000000000000000000000000815260009283926001600160a01b039182169263de5a6e2292613c0b921690600401614a16565b60206040518083038186803b158015613c2357600080fd5b505afa158015613c37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c5b919061491b565b6012546007546040517fde5a6e220000000000000000000000000000000000000000000000000000000081529293506000926001600160a01b039283169263de5a6e2292613cae92911690600401614a16565b60206040518083038186803b158015613cc657600080fd5b505afa158015613cda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cfe919061491b565b90508063ffffffff168263ffffffff1611613d195781613d1b565b805b9250505090565b6000806121208787878787613e2f565b60008088606001516001600160801b031660001415613d575750600190506000613d6b565b613d6689898989898989613ee5565b915091505b97509795505050505050565b6000806000808590506000806000836001600160a01b03166399fbab88896040518263ffffffff1660e01b8152600401808281526020019150506101806040518083038186803b158015613dca57600080fd5b505afa158015613dde573d6000803e3d6000fd5b505050506040513d610180811015613df557600080fd5b5060a081015160c082015160e090920151909b919a5098509650505050505050565b606082015161388d906001600160801b0316826131c1565b604080517fd6906e6d0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301528581166024830152848116604483015263ffffffff84166064830152915160009288169163d6906e6d916084808301926020929190829003018186803b158015613eaf57600080fd5b505afa158015613ec3573d6000803e3d6000fd5b505050506040513d6020811015613ed957600080fd5b50519695505050505050565b6000806000613f216ec097ce7bc90715b34b9f1000000000612256896122c68c8f606001516001600160801b031661316890919063ffffffff16565b90506000613f338b8b8b8b8a8a613f65565b90508681106000613f45846003613168565b613f50846002613168565b10159d919c50909a5050505050505050505050565b6000866020015163ffffffff1660001415613f93575060408601516bffffffffffffffffffffffff166130d1565b600080613fac888a6020015163ffffffff168787614006565b90925090506000613fd46ec097ce7bc90715b34b9f1000000000612256896122c6868d613168565b60408b0151909150613ff8906bffffffffffffffffffffffff1661294885846131c1565b9a9950505050505050505050565b60008060008060006140188989613d77565b92509250925060008061402d85858b8661405d565b915091508761403c578061403e565b815b88614049578261404b565b815b96509650505050505094509492505050565b600080600061406b85614102565b90508660020b8560020b121561409f5761409861408788614102565b61409088614102565b86600161445d565b92506140f8565b8560020b8560020b12156140d8576140ba8161409088614102565b92506140d16140c888614102565b8286600161451a565b91506140f8565b6140f56140e488614102565b6140ed88614102565b86600161451a565b91505b5094509492505050565b60008060008360020b12614119578260020b614121565b8260020b6000035b9050620d89e881111561417b576040805162461bcd60e51b815260206004820152600160248201527f5400000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60006001821661419c577001000000000000000000000000000000006141ae565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156141e2576ffff97272373d413259a46990580e213a0260801c5b6004821615614201576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615614220576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b601082161561423f576fffcb9843d60f6159c9db58835c9266440260801c5b602082161561425e576fff973b41fa98c081472e6896dfb254c00260801c5b604082161561427d576fff2ea16466c96a3843ec78b326b528610260801c5b608082161561429c576ffe5dee046a99a2a811c461f1969c30530260801c5b6101008216156142bc576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b6102008216156142dc576ff987a7253ac413176f2b074cf7815e540260801c5b6104008216156142fc576ff3392b0822b70005940c7a398e4b70f30260801c5b61080082161561431c576fe7159475a2c29b7443b29c7fa6e889d90260801c5b61100082161561433c576fd097f3bdfd2022b8845ad8f792aa58250260801c5b61200082161561435c576fa9f746462d870fdf8a65dc1f90e061e50260801c5b61400082161561437c576f70d869a156d2a1b890bb3df62baf32f70260801c5b61800082161561439c576f31be135f97d08fd981231505542fcfa60260801c5b620100008216156143bd576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156143dd576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156143fc576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615614419576b048a170391f7dc42444e8fa20260801c5b60008460020b131561443457806000198161443057fe5b0490505b64010000000081061561444857600161444b565b60005b60ff16602082901c0192505050919050565b6000836001600160a01b0316856001600160a01b0316111561447d579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b0386860381169087166144b957600080fd5b836144e957866001600160a01b03166144dc8383896001600160a01b031661458a565b816144e357fe5b0461450f565b61450f6145008383896001600160a01b0316614639565b886001600160a01b0316614673565b979650505050505050565b6000836001600160a01b0316856001600160a01b0316111561453a579293925b8161456757614562836001600160801b03168686036001600160a01b0316600160601b61458a565b612132565b612132836001600160801b03168686036001600160a01b0316600160601b614639565b60008080600019858709868602925082811090839003039050806145c057600084116145b557600080fd5b508290049050610c8b565b8084116145cc57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b600061464684848461458a565b90506000828061465257fe5b8486091115610c8b57600019811061466957600080fd5b6001019392505050565b808204910615150190565b60408051608081018252600080825260208201819052918101829052606081019190915290565b805161157e816151b9565b8051600281900b811461157e57600080fd5b805161157e816151ce565b805162ffffff8116811461157e57600080fd5b6000602082840312156146f1578081fd5b8135610c8b816151b9565b60006020828403121561470d578081fd5b8151610c8b816151b9565b600080600080600080600080610100898b031215614734578384fd5b883561473f816151b9565b9750602089013561474f816151b9565b9650604089013561475f816151b9565b9550606089013561476f816151b9565b9450608089013561477f816151b9565b935060a089013561478f816151b9565b925060c089013561479f816151b9565b915060e08901356147af816151b9565b809150509295985092959890939650565b6000602082840312156147d1578081fd5b81518015158114610c8b578182fd5b6000602082840312156147f1578081fd5b610c8b826146b0565b60006020828403121561480b578081fd5b5035919050565b600060208284031215614823578081fd5b5051919050565b6000806040838503121561483c578182fd5b82359150602083013561484e816151b9565b809150509250929050565b60008060006060848603121561486d578283fd5b83359250602084013561487f816151ce565b929592945050506040919091013590565b600080604083850312156148a2578182fd5b50508035926020909101359150565b600080604083850312156148c3578182fd5b505080516020909101519092909150565b6000806000606084860312156148e8578283fd5b505081359360208301359350604090920135919050565b600060208284031215614910578081fd5b8135610c8b816151e3565b60006020828403121561492c578081fd5b8151610c8b816151e3565b6000806000806000806000806000806000806101808d8f031215614959578586fd5b8c516bffffffffffffffffffffffff81168114614974578687fd5b9b5061498260208e016146a5565b9a5061499060408e016146a5565b995061499e60608e016146a5565b98506149ac60808e016146cd565b97506149ba60a08e016146b0565b96506149c860c08e016146b0565b95506149d660e08e016146c2565b94506101008d015193506101208d015192506149f56101408e016146c2565b9150614a046101608e016146c2565b90509295989b509295989b509295989b565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0392909216825263ffffffff16602082015260400190565b6001600160a01b0394909416845263ffffffff9290921660208401526bffffffffffffffffffffffff1660408301526001600160801b0316606082015260800190565b901515815260200190565b6020808252601a908201527f496e76616c696420706f77657220706572702061646472657373000000000000604082015260600190565b60208082526018908201527f496e76616c6964207661756c744e465420616464726573730000000000000000604082015260600190565b60208082526009908201527f2173687574646f776e0000000000000000000000000000000000000000000000604082015260600190565b60208082526015908201527f6e6565642066756c6c206c69717569646174696f6e0000000000000000000000604082015260600190565b60208082526019908201527f70617573652074696d65206c696d697420657863656564656400000000000000604082015260600190565b6020808252600b908201527f6e6f7420616c6c6f776564000000000000000000000000000000000000000000604082015260600190565b6020808252601e908201527f496e76616c69642071756f74652063757272656e637920616464726573730000604082015260600190565b6020808252601c908201527f43616e206e6f74206c69717569646174652073616665207661756c7400000000604082015260600190565b6020808252600f908201527f696e76616c696420616464726573730000000000000000000000000000000000604082015260600190565b6020808252601c908201527f496e76616c696420756e6920706f736974696f6e206d616e6167657200000000604082015260600190565b60208082526007908201527f2170617573656400000000000000000000000000000000000000000000000000604082015260600190565b60208082526012908201527f43616e6e6f742072656365697665206574680000000000000000000000000000604082015260600190565b6020808252600d908201527f496e76616c696420737461746500000000000000000000000000000000000000604082015260600190565b60208082526022908201527f496e76616c696420706f776572706572703a65746820706f6f6c20616464726560408201527f7373000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526017908201527f7365742066656520726563697069656e74206669727374000000000000000000604082015260600190565b6020808252600a908201527f64757374207661756c7400000000000000000000000000000000000000000000604082015260600190565b6020808252600c908201527f66656520746f6f20686967680000000000000000000000000000000000000000604082015260600190565b6020808252601c908201527f496e76616c6964206574683a75736420706f6f6c206164647265737300000000604082015260600190565b60208082526014908201527f496e76616c696420776574682061646472657373000000000000000000000000604082015260600190565b60208082526016908201527f496e76616c6964206f7261636c65206164647265737300000000000000000000604082015260600190565b60208082526015908201527f70617573656420746f6f206d616e792074696d65730000000000000000000000604082015260600190565b60208082526021908201527f6e6f7420656e6f756768207061757365642074696d652068617320706173736560408201527f6400000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526008908201527f73687574646f776e000000000000000000000000000000000000000000000000604082015260600190565b60208082526006908201527f7061757365640000000000000000000000000000000000000000000000000000604082015260600190565b6020808252600f908201527f64757374207661756c74206c6566740000000000000000000000000000000000604082015260600190565b6020808252600b908201527f496e76616c6964206e6674000000000000000000000000000000000000000000604082015260600190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b90815260200190565b9182526001600160a01b0316602082015260400190565b918252602082015260400190565b92835260208301919091526001600160801b0316604082015260600190565b9283526020830191909152604082015260600190565b6001600160a01b0381168114610ae257600080fd5b6001600160801b0381168114610ae257600080fd5b63ffffffff81168114610ae257600080fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a3c94c16a83a11318941b1f7d33e0d7b30d2dd36812bc47893db211e7ae0db0164736f6c63430007060033\",\n    \"deployedBytecode\": \"0x6080604052600436106103385760003560e01c80638c64ea4a116101b0578063cc4b1473116100ec578063ed88c68e11610095578063f2fde38b1161006f578063f2fde38b1461082f578063f3a50fe31461084f578063f4b9fa7514610870578063ff9475251461088557610372565b8063ed88c68e146107f2578063ee3189ff146107fa578063ef0b69dd1461081a57610372565b8063de4a427a116100c6578063de4a427a146107a8578063e5047b30146107bd578063e74b981b146107d257610372565b8063cc4b147314610760578063d296d1f114610773578063d52725841461079357610372565b806397efa94211610159578063b6b55f2511610133578063b6b55f25146106f8578063b707ab991461070b578063c65a391d14610720578063c9e77ee81461074057610372565b806397efa94214610698578063a847e674146106b8578063ac6cd5ef146106d857610372565b806391b4ded91161018a57806391b4ded91461064e57806391b8d34a14610663578063978bbdb91461068357610372565b80638c64ea4a146105e95780638cd21d7c146106195780638da5cb5b1461063957610372565b8063607ad0d71161027f5780637b44b4fd116102285780638146b09f116102025780638146b09f1461058a5780638456cb591461059f57806384dea1a1146105b45780638632cb03146105c957610372565b80637b44b4fd1461054b5780637dc0d1d0146105605780637f07b1301461057557610372565b8063715018a611610259578063715018a6146104ff5780637691c4ac1461051457806376adb9641461053657610372565b8063607ad0d7146104b557806363b38ae4146104ca578063713d517f146104df57610372565b80634394318d116102e157806346904840116102bb578063469048401461046b5780634be2822c14610480578063525240c01461049557610372565b80634394318d14610418578063441a3e701461043857806345596e2e1461044b57610372565b806324f5f5311161031257806324f5f531146103b65780632d8f1d90146103e15780633fc8cef3146103f657610372565b8063076336691461037757806310b9e5831461038c578063200f4b8d146103a157610372565b36610372576003546001600160a01b031633146103705760405162461bcd60e51b815260040161036790614d4b565b60405180910390fd5b005b600080fd5b34801561038357600080fd5b5061037061089a565b34801561039857600080fd5b5061037061098b565b3480156103ad57600080fd5b50610370610ab0565b3480156103c257600080fd5b506103cb610ae5565b6040516103d89190615156565b60405180910390f35b3480156103ed57600080fd5b50610370610af5565b34801561040257600080fd5b5061040b610c40565b6040516103d89190614a16565b34801561042457600080fd5b506103cb6104333660046148d4565b610c4f565b610370610446366004614890565b610c92565b34801561045757600080fd5b506103706104663660046147fa565b610d5b565b34801561047757600080fd5b5061040b610e58565b34801561048c57600080fd5b506103cb610e67565b3480156104a157600080fd5b506103706104b0366004614718565b610e6d565b3480156104c157600080fd5b506103cb6110f8565b3480156104d657600080fd5b506103cb6110fe565b3480156104eb57600080fd5b506103706104fa3660046147fa565b611104565b34801561050b57600080fd5b506103706111cb565b34801561052057600080fd5b506105296112a6565b6040516103d89190614ae3565b34801561054257600080fd5b5061040b6112b6565b34801561055757600080fd5b506103cb6112c5565b34801561056c57600080fd5b5061040b6112cc565b34801561058157600080fd5b5061040b6112db565b34801561059657600080fd5b506103706112ea565b3480156105ab57600080fd5b50610370611363565b3480156105c057600080fd5b5061040b6114b3565b3480156105d557600080fd5b506103706105e43660046148d4565b6114c2565b3480156105f557600080fd5b506106096106043660046147fa565b6114fa565b6040516103d89493929190614aa0565b34801561062557600080fd5b506103cb6106343660046148ff565b61154c565b34801561064557600080fd5b5061040b611583565b34801561065a57600080fd5b506103cb611598565b34801561066f57600080fd5b5061037061067e366004614890565b61159e565b34801561068f57600080fd5b506103cb611649565b3480156106a457600080fd5b506103706106b33660046147fa565b61164f565b3480156106c457600080fd5b506105296106d33660046147fa565b61178f565b3480156106e457600080fd5b506103706106f33660046147fa565b611816565b6103706107063660046147fa565b6118c4565b34801561071757600080fd5b5061040b611978565b34801561072c57600080fd5b5061037061073b36600461482a565b611987565b34801561074c57600080fd5b5061037061075b3660046147fa565b611a1f565b6103cb61076e366004614859565b611b77565b34801561077f57600080fd5b506103cb61078e366004614890565b611bc6565b34801561079f57600080fd5b506103cb611dc0565b3480156107b457600080fd5b506103cb611dc6565b3480156107c957600080fd5b5061040b611dcc565b3480156107de57600080fd5b506103706107ed3660046146e0565b611ddb565b610370611eeb565b34801561080657600080fd5b506103cb6108153660046148ff565b611f16565b34801561082657600080fd5b50610529611f5b565b34801561083b57600080fd5b5061037061084a3660046146e0565b611f64565b61086261085d366004614859565b61209c565b6040516103d8929190615176565b34801561087c57600080fd5b5061040b6120ed565b34801561089157600080fd5b506105296120fc565b600054600160b01b900460ff16156108c45760405162461bcd60e51b815260040161036790614ff4565b600054600160b81b900460ff166108ed5760405162461bcd60e51b815260040161036790614d14565b6108f561210c565b6001600160a01b0316610906611583565b6001600160a01b031614610961576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff169055565b600054600160b01b900460ff16156109b55760405162461bcd60e51b815260040161036790614ff4565b600054600160b81b900460ff166109de5760405162461bcd60e51b815260040161036790614d14565b6109e661210c565b6001600160a01b03166109f7611583565b6001600160a01b031614610a52576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff16600160b01b179055601254600554600354600454610aab936001600160a01b039081169381169281169116610258612110565b600a55565b600054600160b81b900460ff1615610ada5760405162461bcd60e51b81526004016103679061502b565b610ae261213b565b50565b6000610aef6121a7565b90505b90565b600054600160b01b900460ff1615610b1f5760405162461bcd60e51b815260040161036790614ff4565b600054600160b81b900460ff1615610b495760405162461bcd60e51b81526004016103679061502b565b610b5161210c565b6001600160a01b0316610b62611583565b6001600160a01b031614610bbd576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff909116600160b81b1716600160b01b179055601254600554600354600454610aab936001600160a01b039081169381169281169116610258612110565b6003546001600160a01b031681565b60008054600160b81b900460ff1615610c7a5760405162461bcd60e51b81526004016103679061502b565b610c88338585856000612311565b90505b9392505050565b600054600160b81b900460ff1615610cbc5760405162461bcd60e51b81526004016103679061502b565b6000610cc661213b565b6000848152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b03166060820152909150610d41813386866123f5565b610d4b818361247a565b610d5584826124c6565b50505050565b610d6361210c565b6001600160a01b0316610d74611583565b6001600160a01b031614610dcf576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6006546001600160a01b0316610df75760405162461bcd60e51b815260040161036790614e16565b6064811115610e185760405162461bcd60e51b815260040161036790614e84565b7f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95760095482604051610e4b929190615176565b60405180910390a1600955565b6006546001600160a01b031681565b600c5481565b600054610100900460ff1680610e865750610e866125be565b80610e94575060005460ff16155b610ecf5760405162461bcd60e51b815260040180806020018281038252602e815260200180615256602e913960400191505060405180910390fd5b600054610100900460ff16158015610efa576000805460ff1961ff0019909116610100171660011790555b6001600160a01b038916610f205760405162461bcd60e51b815260040161036790614f29565b6001600160a01b038816610f465760405162461bcd60e51b815260040161036790614b25565b6001600160a01b038716610f6c5760405162461bcd60e51b815260040161036790614aee565b6001600160a01b038616610f925760405162461bcd60e51b815260040161036790614ef2565b6001600160a01b038516610fb85760405162461bcd60e51b815260040161036790614c38565b6001600160a01b038416610fde5760405162461bcd60e51b815260040161036790614ebb565b6001600160a01b0383166110045760405162461bcd60e51b815260040161036790614db9565b6001600160a01b03821661102a5760405162461bcd60e51b815260040161036790614cdd565b6012805473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b038c8116919091179092556010805482168b84161790556011805482168a84169081179091556005805483168885161790556007805483168785161790556008805483168685161790556003805483168a851617908190556004805490931689851617909255670de0b6b3a7640000600b5542600c819055600d55600e8054929093161060ff1990911617905580156110ed576000805461ff00191690555b505050505050505050565b600d5481565b60015481565b600054600160b81b900460ff161561112e5760405162461bcd60e51b81526004016103679061502b565b600061113861213b565b6000838152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b031660608201529091506111b28133856125cf565b6111bc818361247a565b6111c683826124c6565b505050565b6111d361210c565b6001600160a01b03166111e4611583565b6001600160a01b03161461123f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60008054604051620100009091046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff169055565b600054600160b81b900460ff1681565b6005546001600160a01b031681565b62eff10081565b6012546001600160a01b031681565b6011546001600160a01b031681565b600054600160b01b900460ff16156113145760405162461bcd60e51b815260040161036790614ff4565b600054600160b81b900460ff1661133d5760405162461bcd60e51b815260040161036790614d14565b600254620151800142116109615760405162461bcd60e51b815260040161036790614f97565b600054600160b01b900460ff161561138d5760405162461bcd60e51b815260040161036790614ff4565b600054600160b81b900460ff16156113b75760405162461bcd60e51b81526004016103679061502b565b6113bf61210c565b6001600160a01b03166113d0611583565b6001600160a01b03161461142b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60006001541161144d5760405162461bcd60e51b815260040161036790614f60565b600d54420362eff10081106114745760405162461bcd60e51b815260040161036790614bca565b50600080547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16600160b81b1790556001805460001901905542600255565b6010546001600160a01b031681565b600054600160b81b900460ff16156114ec5760405162461bcd60e51b81526004016103679061502b565b610d55338484846001612311565b600f60205260009081526040902080546001909101546001600160a01b03821691600160a01b900463ffffffff16906bffffffffffffffffffffffff811690600160601b90046001600160801b031684565b60125460055460035460045460009361157b9386936001600160a01b03928316939183169290811691166126b9565b90505b919050565b6000546201000090046001600160a01b031690565b60025481565b600054600160b81b900460ff16156115c85760405162461bcd60e51b81526004016103679061502b565b6115d061213b565b506000828152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b031660608201526111bc813385856126e1565b60095481565b600054600160b01b900460ff166116785760405162461bcd60e51b815260040161036790614b5c565b61168281336127a4565b61169e5760405162461bcd60e51b815260040161036790614c01565b6000818152600f60209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546bffffffffffffffffffffffff811691830191909152600160601b90046001600160801b03166060820152600b54909161171c9083903390849061285c565b50600061173b83606001516001600160801b0316600a54600b54612ae8565b905060006117648285604001516bffffffffffffffffffffffff16612b0b90919063ffffffff16565b6000606086018190526040860152905061177e85856124c6565b6117883382612b68565b5050505050565b6000818152600f60209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546bffffffffffffffffffffffff811691830191909152600160601b90046001600160801b03166060820152816118026121a7565b905061180e8282612c4d565b949350505050565b600054600160b01b900460ff1661183f5760405162461bcd60e51b815260040161036790614b5c565b601154604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac906118719033908590600401614a4e565b600060405180830381600087803b15801561188b57600080fd5b505af115801561189f573d6000803e3d6000fd5b5050505060006118b482600a54600b54612ae8565b90506118c03382612b68565b5050565b600054600160b81b900460ff16156118ee5760405162461bcd60e51b81526004016103679061502b565b6118f661213b565b506000818152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b0316606082015261196e818334612c63565b6118c082826124c6565b6007546001600160a01b031681565b61199182336127a4565b6119ad5760405162461bcd60e51b815260040161036790614c01565b6000828152600f602052604090819020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038416179055517f9d9dd80a56a16f715df6eb40b771e24ff8cbea6eed9de28473ce0f28fe5602a990611a13908490849061515f565b60405180910390a15050565b600054600160b81b900460ff1615611a495760405162461bcd60e51b81526004016103679061502b565b611a5381336127a4565b611a6f5760405162461bcd60e51b815260040161036790614c01565b6000611a7961213b565b6000838152600f6020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093526001909101546bffffffffffffffffffffffff811682850152600160601b90046001600160801b0316606082015260105492516331a9108f60e11b815293945092611b6c9284921690636352211e90611b14908890600401615156565b60206040518083038186803b158015611b2c57600080fd5b505afa158015611b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6491906146fc565b84600061285c565b506111c683826124c6565b60008054600160b81b900460ff1615611ba25760405162461bcd60e51b81526004016103679061502b565b6000611bbc3386866001600160801b031634876001612cae565b5095945050505050565b60008054600160b81b900460ff1615611bf15760405162461bcd60e51b81526004016103679061502b565b6000611bfb61213b565b6000858152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b03166060820152909150611c748183612c4d565b15611c915760405162461bcd60e51b815260040161036790614c6f565b6010546040516331a9108f60e11b8152600091611d209184916001600160a01b031690636352211e90611cc8908b90600401615156565b60206040518083038186803b158015611ce057600080fd5b505afa158015611cf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1891906146fc565b85600161285c565b9050611d2c8284612c4d565b15611d5157611d3b3382612b68565b611d4586836124c6565b60009350505050611dba565b611d5b8282612de1565b600080611d6a84888733612e18565b915091507f199c51a8cd3b6aa8f80abc4f5c713f20c111837887163a1bbaa2dd5f61a554ab888383604051611da1939291906151a3565b60405180910390a1611db388856124c6565b5093505050505b92915050565b600b5481565b600a5481565b6008546001600160a01b031681565b611de361210c565b6001600160a01b0316611df4611583565b6001600160a01b031614611e4f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611e755760405162461bcd60e51b815260040161036790614ca6565b6006546040517faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d391611eb4916001600160a01b03909116908490614a67565b60405180910390a16006805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600054600160b01b900460ff16611f145760405162461bcd60e51b815260040161036790614b5c565b565b600080611f216121a7565b601254600754600554600354600454601154959650610c8b9589956001600160a01b03908116958116948116938116928116911688612f8d565b600e5460ff1681565b611f6c61210c565b6001600160a01b0316611f7d611583565b6001600160a01b031614611fd8576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03811661201d5760405162461bcd60e51b81526004018080602001828103825260268152602001806151f66026913960400191505060405180910390fd5b600080546040516001600160a01b03808516936201000090930416917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0390921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff909216919091179055565b600080548190600160b81b900460ff16156120c95760405162461bcd60e51b81526004016103679061502b565b6120e13386866001600160801b031634876000612cae565b91509150935093915050565b6004546001600160a01b031681565b600054600160b01b900460ff1681565b3390565b6000806121208787878787612fcd565b905061212e816127106130db565b9150505b95945050505050565b600042600c5414156121505750600b54610af2565b600061215a6121a7565b90507fa5e6eb88e05b1ccc7e1a9a5096d0a5b8aef97d5204e0ad78ffda42affd8374a8600b548242604051612191939291906151a3565b60405180910390a1600b81905542600c55905090565b600c546000904203816121b982613142565b600b5460125460075460055460035460045460115496975094956000956121fe9589956001600160a01b03918216959082169490821693908216928216911689612f8d565b6012546005546003546004549394506000936122309388936001600160a01b03918216939082169290821691166126b9565b9050600061225c62015180612256670de0b6b3a764000063ffffffff808b169061316816565b906130db565b905060006122706005612256856004613168565b90508084101561227e578093505b60006122906004612256866005613168565b90508085111561229e578094505b60006122eb6122d26122b08787613168565b6122cc896122c6670de0b6b3a76400008a6131c1565b90613168565b90612b0b565b612256886ec097ce7bc90715b34b9f1000000000613168565b9050612303670de0b6b3a76400006122568984613168565b995050505050505050505090565b60008061231c61213b565b90506000836123405761233b8261225688670de0b6b3a7640000613168565b612342565b855b6000888152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b0316606082015290915081156123c3576123c3818a8a8561321b565b85156123d5576123d5818a8a896123f5565b6123df818461247a565b6123e988826124c6565b50979650505050505050565b6123ff82846127a4565b61241b5760405162461bcd60e51b815260040161036790614c01565b61242584826132ba565b6124386001600160a01b03841682612b68565b7ffd6fe60d4c49c077689d373f95adff80f09e02e5f719b842f6e3cfc812546a908282600060405161246c93929190615184565b60405180910390a150505050565b60008061248784846132d7565b91509150816124a85760405162461bcd60e51b815260040161036790614d82565b8015610d555760405162461bcd60e51b815260040161036790614e4d565b6000918252600f6020908152604092839020825181549284015163ffffffff16600160a01b027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff6001600160a01b0390921673ffffffffffffffffffffffffffffffffffffffff19909416939093171691909117815591810151600190920180546060909201516001600160801b0316600160601b027fffffffff00000000000000000000000000000000ffffffffffffffffffffffff6bffffffffffffffffffffffff9094167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009093169290921792909216179055565b60006125c9306133f0565b15905090565b6125d981836127a4565b6125f55760405162461bcd60e51b815260040161036790614c01565b602083015163ffffffff16612609846133f6565b6008546040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906323b872dd9061265690309087908690600401614a2a565b600060405180830381600087803b15801561267057600080fd5b505af1158015612684573d6000803e3d6000fd5b505050507fe408b929e3c702ebaee90bb2112c954eabc66448f7d3e6a26faf67e40af3666b828260405161246c929190615176565b6000806126c9868686868b612110565b905061212e670de0b6b3a76400006122568380613168565b6126ea8161345c565b6126f48482613597565b6008546040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906323b872dd9061274190869030908690600401614a2a565b600060405180830381600087803b15801561275b57600080fd5b505af115801561276f573d6000803e3d6000fd5b505050507fa73a85546850efb41a3bae76ec46116507eaa88fef566468556ce065e24519a4828260405161246c929190615176565b6010546040516331a9108f60e11b81526000916001600160a01b0380851692911690636352211e906127da908790600401615156565b60206040518083038186803b1580156127f257600080fd5b505afa158015612806573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282a91906146fc565b6001600160a01b03161480610c8b5750506000918252600f6020526040909120546001600160a01b0390811691161490565b602084015160009063ffffffff168061287957600091505061180e565b60008061288583613654565b9092509050811561290c576003546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632e1a7d4d906128d9908590600401615156565b600060405180830381600087803b1580156128f357600080fd5b505af1158015612907573d6000803e3d6000fd5b505050505b600085156129645760125460055460035460045460009361294e9388936129489389936001600160a01b0390811693811692811691168f613834565b906131c1565b90506129606064612256836002613168565b9150505b61296d896133f6565b6129778984612de1565b61298189826132ba565b88606001516001600160801b0316821115612a6d5760006129b88a606001516001600160801b031684612b0b90919063ffffffff16565b60608b01516011546040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160801b0390921695509192506001600160a01b039091169063a9059cbb90612a18908c908590600401614a4e565b602060405180830381600087803b158015612a3257600080fd5b505af1158015612a46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6a91906147c0565b50505b612a778983613875565b601154604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac90612aa99030908690600401614a4e565b600060405180830381600087803b158015612ac357600080fd5b505af1158015612ad7573d6000803e3d6000fd5b50929b9a5050505050505050505050565b6000610c886ec097ce7bc90715b34b9f1000000000612256856122c68887613168565b600082821115612b62576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b80471015612bbd576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114612c08576040519150601f19603f3d011682016040523d82523d6000602084013e612c0d565b606091505b50509050806111c65760405162461bcd60e51b815260040180806020018281038252603a81526020018061521c603a913960400191505060405180910390fd5b600080612c5a84846132d7565b50949350505050565b612c6d8382612de1565b7f7a0373b035a03ee781adee2e2f1920bf98084e3485bfdd8a99acf44fd0feaace82826000604051612ca193929190615184565b60405180910390a1505050565b6000806000612cbb61213b565b905085600085612ce057612cdb836122568b670de0b6b3a7640000613168565b612ce2565b885b9050612cec61467e565b8a612d0457612cfa8c6138a2565b909b509050612d72565b5060008a8152600f6020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546bffffffffffffffffffffffff811692820192909252600160601b9091046001600160801b031660608201525b8115612d8857612d85818d8d858d6139ae565b92505b8815612d9957612d99818c85612c63565b8715612dab57612dab818d8d8b6126e1565b8115612dbd57612dbd818d8d85613a70565b612dc7818561247a565b612dd18b826124c6565b50989a9899505050505050505050565b6040820151612dfe906bffffffffffffffffffffffff16826131c1565b6bffffffffffffffffffffffff1660409092019190915250565b6060840151604085015160009182916001600160801b03909116906bffffffffffffffffffffffff168280612e5889612e528660026130db565b8a613b4e565b9150915080831115612e8e576706f05b59d3b20000612e778483612b0b565b1015612e8e57612e8889858a613b4e565b90925090505b82811115612ebc5783891015612eb65760405162461bcd60e51b815260040161036790614b93565b50829050815b601154604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac90612eee908a908690600401614a4e565b600060405180830381600087803b158015612f0857600080fd5b505af1158015612f1c573d6000803e3d6000fd5b50505050612f33828b61387590919063ffffffff16565b612f3d8a826132ba565b6000612f498b8a6132d7565b9150508015612f6a5760405162461bcd60e51b815260040161036790615062565b612f7d6001600160a01b03891683612b68565b5090999098509650505050505050565b600080612f9d898888888e612110565b90506000612fae8a8a878a8f612fcd565b9050612fbe846122568385613168565b9b9a5050505050505050505050565b604080517f821b972a0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301528581166024830152848116604483015263ffffffff84166064830152915160009283929089169163821b972a91608480820192602092909190829003018186803b15801561305157600080fd5b505afa158015613065573d6000803e3d6000fd5b505050506040513d602081101561307b57600080fd5b50519050806130d1576040805162461bcd60e51b815260206004820152600b60248201527f5741502057415020574150000000000000000000000000000000000000000000604482015290519081900360640190fd5b9695505050505050565b6000808211613131576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161313a57fe5b049392505050565b60008061314d613bba565b90508063ffffffff168363ffffffff1611611dba5782610c8b565b60008261317757506000611dba565b8282028284828161318457fe5b0414610c8b5760405162461bcd60e51b81526004018080602001828103825260218152602001806152846021913960400191505060405180910390fd5b600082820183811015610c8b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6132258482613875565b601154604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac906132579086908590600401614a4e565b600060405180830381600087803b15801561327157600080fd5b505af1158015613285573d6000803e3d6000fd5b505050507fc3fe83ab1ba331ef06ed00bc6f8615de1577dc77772a83e3264864de6a94ea8d818360405161246c929190615176565b6040820151612dfe906bffffffffffffffffffffffff1682612b0b565b6012546005546003546004546000938493849361330b936001600160a01b039384169392831692918216911661012c613d22565b6012546007546040517f4a0a96eb0000000000000000000000000000000000000000000000000000000081529293506000926001600160a01b0392831692634a0a96eb926133629291169061012c90600401614a81565b60206040518083038186803b15801561337a57600080fd5b505afa15801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b291906147e0565b600854600e549192506133e39188916001600160a01b031690889086906706f05b59d3b2000090879060ff16613d32565b9350935050509250929050565b3b151590565b602081015163ffffffff16613452576040805162461bcd60e51b815260206004820152601060248201527f5661756c7420686173206e6f204e465400000000000000000000000000000000604482015290519081900360640190fd5b6000602090910152565b6008546040517f99fbab8800000000000000000000000000000000000000000000000000000000815260009182916001600160a01b03909116906399fbab88906134aa908690600401615156565b6101806040518083038186803b1580156134c357600080fd5b505afa1580156134d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fb9190614937565b5050601154600354989c50969a50506001600160a01b03958616985050509383169450505085168314905080156135435750806001600160a01b0316836001600160a01b0316145b8061357b5750816001600160a01b0316836001600160a01b031614801561357b5750806001600160a01b0316846001600160a01b0316145b6117885760405162461bcd60e51b815260040161036790615099565b602082015163ffffffff16156135f4576040805162461bcd60e51b815260206004820152601560248201527f5661756c7420616c726561647920686164206e66740000000000000000000000604482015290519081900360640190fd5b80613646576040805162461bcd60e51b815260206004820152600a60248201527f696e76616c696420696400000000000000000000000000000000000000000000604482015290519081900360640190fd5b63ffffffff16602090910152565b60085460009081906001600160a01b0316816136708286613d77565b9250505060006040518060a00160405280878152602001836001600160801b031681526020016000815260200160008152602001428152509050600080846001600160a01b0316630c49ccbe846040518263ffffffff1660e01b81526004016136d99190615113565b6040805180830381600087803b1580156136f257600080fd5b505af1158015613706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061372a91906148b1565b604080516080810182528b81523060208201526001600160801b03808516828401528316606082015290517ffc6f78650000000000000000000000000000000000000000000000000000000081529294509092509060009081906001600160a01b0389169063fc6f7865906137a39086906004016150d0565b6040805180830381600087803b1580156137bc57600080fd5b505af11580156137d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137f491906148b1565b600e54919350915060ff1660008161380c578261380e565b835b905060008261381d578461381f565b835b919c50909a5050505050505050505050915091565b60008061384687878787610258612110565b90506138696ec097ce7bc90715b34b9f1000000000612256836122c68c88613168565b98975050505050505050565b606082015161388d906001600160801b031682612b0b565b6001600160801b031660609092019190915250565b60006138ac61467e565b6010546040517f54ba0f270000000000000000000000000000000000000000000000000000000081526000916001600160a01b0316906354ba0f27906138f6908790600401614a16565b602060405180830381600087803b15801561391057600080fd5b505af1158015613924573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139489190614812565b6040805160808101825260008082526020820181905281830181905260608201529051919250907f5f5dd6438bd675e0dba85db7517ba5931be5b31a11e5af8c04ea0e9152fa7ec59061399c908490615156565b60405180910390a19092509050915091565b600954600090806139c25782915050612132565b601254600554600354600454600b5460009485946139f8948b946001600160a01b03938416949284169391821692911690613834565b90506000613a0c6127106122568487613168565b905080861115613a3e57613a208682612b0b565b600654909350613a39906001600160a01b031682612b68565b613a62565b613a488a826132ba565b600654613a5e906001600160a01b031682612b68565b8592505b509098975050505050505050565b613a7a82846127a4565b613a965760405162461bcd60e51b815260040161036790614c01565b613aa08482613e17565b6011546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906340c10f1990613aeb9086908590600401614a4e565b600060405180830381600087803b158015613b0557600080fd5b505af1158015613b19573d6000803e3d6000fd5b505050507f0dd703a01208414af8d8c0d38f96263f1c708720550808d8af1985608014387a818360405161246c929190615176565b6000806000848611613b605785613b62565b845b601254600554600354600454939450600093613b959386936001600160a01b03918216939082169290821691168a613834565b9050613bac613ba582600a6130db565b82906131c1565b919791965090945050505050565b6012546005546040517fde5a6e2200000000000000000000000000000000000000000000000000000000815260009283926001600160a01b039182169263de5a6e2292613c0b921690600401614a16565b60206040518083038186803b158015613c2357600080fd5b505afa158015613c37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c5b919061491b565b6012546007546040517fde5a6e220000000000000000000000000000000000000000000000000000000081529293506000926001600160a01b039283169263de5a6e2292613cae92911690600401614a16565b60206040518083038186803b158015613cc657600080fd5b505afa158015613cda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cfe919061491b565b90508063ffffffff168263ffffffff1611613d195781613d1b565b805b9250505090565b6000806121208787878787613e2f565b60008088606001516001600160801b031660001415613d575750600190506000613d6b565b613d6689898989898989613ee5565b915091505b97509795505050505050565b6000806000808590506000806000836001600160a01b03166399fbab88896040518263ffffffff1660e01b8152600401808281526020019150506101806040518083038186803b158015613dca57600080fd5b505afa158015613dde573d6000803e3d6000fd5b505050506040513d610180811015613df557600080fd5b5060a081015160c082015160e090920151909b919a5098509650505050505050565b606082015161388d906001600160801b0316826131c1565b604080517fd6906e6d0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301528581166024830152848116604483015263ffffffff84166064830152915160009288169163d6906e6d916084808301926020929190829003018186803b158015613eaf57600080fd5b505afa158015613ec3573d6000803e3d6000fd5b505050506040513d6020811015613ed957600080fd5b50519695505050505050565b6000806000613f216ec097ce7bc90715b34b9f1000000000612256896122c68c8f606001516001600160801b031661316890919063ffffffff16565b90506000613f338b8b8b8b8a8a613f65565b90508681106000613f45846003613168565b613f50846002613168565b10159d919c50909a5050505050505050505050565b6000866020015163ffffffff1660001415613f93575060408601516bffffffffffffffffffffffff166130d1565b600080613fac888a6020015163ffffffff168787614006565b90925090506000613fd46ec097ce7bc90715b34b9f1000000000612256896122c6868d613168565b60408b0151909150613ff8906bffffffffffffffffffffffff1661294885846131c1565b9a9950505050505050505050565b60008060008060006140188989613d77565b92509250925060008061402d85858b8661405d565b915091508761403c578061403e565b815b88614049578261404b565b815b96509650505050505094509492505050565b600080600061406b85614102565b90508660020b8560020b121561409f5761409861408788614102565b61409088614102565b86600161445d565b92506140f8565b8560020b8560020b12156140d8576140ba8161409088614102565b92506140d16140c888614102565b8286600161451a565b91506140f8565b6140f56140e488614102565b6140ed88614102565b86600161451a565b91505b5094509492505050565b60008060008360020b12614119578260020b614121565b8260020b6000035b9050620d89e881111561417b576040805162461bcd60e51b815260206004820152600160248201527f5400000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60006001821661419c577001000000000000000000000000000000006141ae565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156141e2576ffff97272373d413259a46990580e213a0260801c5b6004821615614201576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615614220576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b601082161561423f576fffcb9843d60f6159c9db58835c9266440260801c5b602082161561425e576fff973b41fa98c081472e6896dfb254c00260801c5b604082161561427d576fff2ea16466c96a3843ec78b326b528610260801c5b608082161561429c576ffe5dee046a99a2a811c461f1969c30530260801c5b6101008216156142bc576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b6102008216156142dc576ff987a7253ac413176f2b074cf7815e540260801c5b6104008216156142fc576ff3392b0822b70005940c7a398e4b70f30260801c5b61080082161561431c576fe7159475a2c29b7443b29c7fa6e889d90260801c5b61100082161561433c576fd097f3bdfd2022b8845ad8f792aa58250260801c5b61200082161561435c576fa9f746462d870fdf8a65dc1f90e061e50260801c5b61400082161561437c576f70d869a156d2a1b890bb3df62baf32f70260801c5b61800082161561439c576f31be135f97d08fd981231505542fcfa60260801c5b620100008216156143bd576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156143dd576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156143fc576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615614419576b048a170391f7dc42444e8fa20260801c5b60008460020b131561443457806000198161443057fe5b0490505b64010000000081061561444857600161444b565b60005b60ff16602082901c0192505050919050565b6000836001600160a01b0316856001600160a01b0316111561447d579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b0386860381169087166144b957600080fd5b836144e957866001600160a01b03166144dc8383896001600160a01b031661458a565b816144e357fe5b0461450f565b61450f6145008383896001600160a01b0316614639565b886001600160a01b0316614673565b979650505050505050565b6000836001600160a01b0316856001600160a01b0316111561453a579293925b8161456757614562836001600160801b03168686036001600160a01b0316600160601b61458a565b612132565b612132836001600160801b03168686036001600160a01b0316600160601b614639565b60008080600019858709868602925082811090839003039050806145c057600084116145b557600080fd5b508290049050610c8b565b8084116145cc57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b600061464684848461458a565b90506000828061465257fe5b8486091115610c8b57600019811061466957600080fd5b6001019392505050565b808204910615150190565b60408051608081018252600080825260208201819052918101829052606081019190915290565b805161157e816151b9565b8051600281900b811461157e57600080fd5b805161157e816151ce565b805162ffffff8116811461157e57600080fd5b6000602082840312156146f1578081fd5b8135610c8b816151b9565b60006020828403121561470d578081fd5b8151610c8b816151b9565b600080600080600080600080610100898b031215614734578384fd5b883561473f816151b9565b9750602089013561474f816151b9565b9650604089013561475f816151b9565b9550606089013561476f816151b9565b9450608089013561477f816151b9565b935060a089013561478f816151b9565b925060c089013561479f816151b9565b915060e08901356147af816151b9565b809150509295985092959890939650565b6000602082840312156147d1578081fd5b81518015158114610c8b578182fd5b6000602082840312156147f1578081fd5b610c8b826146b0565b60006020828403121561480b578081fd5b5035919050565b600060208284031215614823578081fd5b5051919050565b6000806040838503121561483c578182fd5b82359150602083013561484e816151b9565b809150509250929050565b60008060006060848603121561486d578283fd5b83359250602084013561487f816151ce565b929592945050506040919091013590565b600080604083850312156148a2578182fd5b50508035926020909101359150565b600080604083850312156148c3578182fd5b505080516020909101519092909150565b6000806000606084860312156148e8578283fd5b505081359360208301359350604090920135919050565b600060208284031215614910578081fd5b8135610c8b816151e3565b60006020828403121561492c578081fd5b8151610c8b816151e3565b6000806000806000806000806000806000806101808d8f031215614959578586fd5b8c516bffffffffffffffffffffffff81168114614974578687fd5b9b5061498260208e016146a5565b9a5061499060408e016146a5565b995061499e60608e016146a5565b98506149ac60808e016146cd565b97506149ba60a08e016146b0565b96506149c860c08e016146b0565b95506149d660e08e016146c2565b94506101008d015193506101208d015192506149f56101408e016146c2565b9150614a046101608e016146c2565b90509295989b509295989b509295989b565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0392909216825263ffffffff16602082015260400190565b6001600160a01b0394909416845263ffffffff9290921660208401526bffffffffffffffffffffffff1660408301526001600160801b0316606082015260800190565b901515815260200190565b6020808252601a908201527f496e76616c696420706f77657220706572702061646472657373000000000000604082015260600190565b60208082526018908201527f496e76616c6964207661756c744e465420616464726573730000000000000000604082015260600190565b60208082526009908201527f2173687574646f776e0000000000000000000000000000000000000000000000604082015260600190565b60208082526015908201527f6e6565642066756c6c206c69717569646174696f6e0000000000000000000000604082015260600190565b60208082526019908201527f70617573652074696d65206c696d697420657863656564656400000000000000604082015260600190565b6020808252600b908201527f6e6f7420616c6c6f776564000000000000000000000000000000000000000000604082015260600190565b6020808252601e908201527f496e76616c69642071756f74652063757272656e637920616464726573730000604082015260600190565b6020808252601c908201527f43616e206e6f74206c69717569646174652073616665207661756c7400000000604082015260600190565b6020808252600f908201527f696e76616c696420616464726573730000000000000000000000000000000000604082015260600190565b6020808252601c908201527f496e76616c696420756e6920706f736974696f6e206d616e6167657200000000604082015260600190565b60208082526007908201527f2170617573656400000000000000000000000000000000000000000000000000604082015260600190565b60208082526012908201527f43616e6e6f742072656365697665206574680000000000000000000000000000604082015260600190565b6020808252600d908201527f496e76616c696420737461746500000000000000000000000000000000000000604082015260600190565b60208082526022908201527f496e76616c696420706f776572706572703a65746820706f6f6c20616464726560408201527f7373000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526017908201527f7365742066656520726563697069656e74206669727374000000000000000000604082015260600190565b6020808252600a908201527f64757374207661756c7400000000000000000000000000000000000000000000604082015260600190565b6020808252600c908201527f66656520746f6f20686967680000000000000000000000000000000000000000604082015260600190565b6020808252601c908201527f496e76616c6964206574683a75736420706f6f6c206164647265737300000000604082015260600190565b60208082526014908201527f496e76616c696420776574682061646472657373000000000000000000000000604082015260600190565b60208082526016908201527f496e76616c6964206f7261636c65206164647265737300000000000000000000604082015260600190565b60208082526015908201527f70617573656420746f6f206d616e792074696d65730000000000000000000000604082015260600190565b60208082526021908201527f6e6f7420656e6f756768207061757365642074696d652068617320706173736560408201527f6400000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526008908201527f73687574646f776e000000000000000000000000000000000000000000000000604082015260600190565b60208082526006908201527f7061757365640000000000000000000000000000000000000000000000000000604082015260600190565b6020808252600f908201527f64757374207661756c74206c6566740000000000000000000000000000000000604082015260600190565b6020808252600b908201527f496e76616c6964206e6674000000000000000000000000000000000000000000604082015260600190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b90815260200190565b9182526001600160a01b0316602082015260400190565b918252602082015260400190565b92835260208301919091526001600160801b0316604082015260600190565b9283526020830191909152604082015260600190565b6001600160a01b0381168114610ae257600080fd5b6001600160801b0381168114610ae257600080fd5b63ffffffff81168114610ae257600080fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220a3c94c16a83a11318941b1f7d33e0d7b30d2dd36812bc47893db211e7ae0db0164736f6c63430007060033\",\n    \"devdoc\": {\n        \"kind\": \"dev\",\n        \"methods\": {\n            \"applyFunding()\": {\n                \"details\": \"update the normalization factor as a way to pay funding.\"\n            },\n            \"burnPowerPerpAmount(uint256,uint256,uint256)\": {\n                \"params\": {\n                    \"_powerPerpAmount\": \"amount of powerPerp to burn\",\n                    \"_vaultId\": \"id of the vault\",\n                    \"_withdrawAmount\": \"amount of eth to withdraw\"\n                },\n                \"returns\": {\n                    \"_0\": \"amount of wPowerPerp burned\"\n                }\n            },\n            \"burnWPowerPerpAmount(uint256,uint256,uint256)\": {\n                \"params\": {\n                    \"_vaultId\": \"id of the vault\",\n                    \"_wPowerPerpAmount\": \"amount of wPowerPerp to burn\",\n                    \"_withdrawAmount\": \"amount of eth to withdraw\"\n                }\n            },\n            \"deposit(uint256)\": {\n                \"details\": \"deposit collateral into a vault\",\n                \"params\": {\n                    \"_vaultId\": \"id of the vault\"\n                }\n            },\n            \"depositUniPositionToken(uint256,uint256)\": {\n                \"params\": {\n                    \"_uniTokenId\": \"uniswap v3 position token id\",\n                    \"_vaultId\": \"id of the vault\"\n                }\n            },\n            \"getDenormalizedMark(uint32)\": {\n                \"params\": {\n                    \"_period\": \"period which you want to calculate twap with\"\n                },\n                \"returns\": {\n                    \"_0\": \"mark price denominated in $USD, scaled by 1e18\"\n                }\n            },\n            \"getExpectedNormalizationFactor()\": {\n                \"details\": \"can be used for on-chain and off-chain calculations\"\n            },\n            \"getIndex(uint32)\": {\n                \"params\": {\n                    \"_period\": \"period which you want to calculate twap with\"\n                },\n                \"returns\": {\n                    \"_0\": \"index price denominated in $USD, scaled by 1e18\"\n                }\n            },\n            \"init(address,address,address,address,address,address,address,address)\": {\n                \"params\": {\n                    \"_dai\": \"dai address\",\n                    \"_ethDaiPool\": \"uniswap v3 pool for weth / dai\",\n                    \"_oracle\": \"oracle address\",\n                    \"_uniPositionManager\": \"uniswap v3 nonfungible position manager address\",\n                    \"_vaultNFT\": \"erc721 token address representing the short position\",\n                    \"_wPowerPerp\": \"erc20 token address representing non-rebasing long position\",\n                    \"_wPowerPerpPool\": \"uniswap v3 pool for wPowerPerp / weth\",\n                    \"_weth\": \"weth address\"\n                }\n            },\n            \"isVaultSafe(uint256)\": {\n                \"details\": \"return if the vault is properly collateralized.\",\n                \"params\": {\n                    \"_vaultId\": \"id of the vault\"\n                },\n                \"returns\": {\n                    \"_0\": \"true if the vault is safe.\"\n                }\n            },\n            \"liquidate(uint256,uint256)\": {\n                \"details\": \"liquidator can get back (powerPerp burned) * (index price) * 110% in collateral\",\n                \"params\": {\n                    \"_maxDebtAmount\": \"max amount of wPowerPerpetual you want to repay.\",\n                    \"_vaultId\": \"the vault you want to liquidate\"\n                },\n                \"returns\": {\n                    \"_0\": \"amount of wPowerPerp repaid.\"\n                }\n            },\n            \"mintPowerPerpAmount(uint256,uint128,uint256)\": {\n                \"params\": {\n                    \"_powerPerpAmount\": \"amount of powerPerp you wish to mint\",\n                    \"_uniTokenId\": \"uniswap v3 position token id want to use to increase collateral ratio\",\n                    \"_vaultId\": \"the vault where you want to mint wPowerPerp in\"\n                },\n                \"returns\": {\n                    \"_0\": \"vaultId\",\n                    \"_1\": \"amount of wPowerPerp minted\"\n                }\n            },\n            \"mintWPowerPerpAmount(uint256,uint128,uint256)\": {\n                \"params\": {\n                    \"_uniTokenId\": \"uniswap v3 position token id want to use to increase collateral ratio\",\n                    \"_vaultId\": \"the vault where you want to mint wPowerPerp in\",\n                    \"_wPowerPerpAmount\": \"amount of wPowerPerp you wish to mint\"\n                },\n                \"returns\": {\n                    \"_0\": \"vaultId\"\n                }\n            },\n            \"owner()\": {\n                \"details\": \"Returns the address of the current owner.\"\n            },\n            \"pause()\": {\n                \"details\": \"pause the system for up to 24 hours after which any one can unpausecan only be called for 365 days since the contract was launched or 4 times, without triggering shutdown atomically\"\n            },\n            \"pauseAndShutDown()\": {\n                \"details\": \"pause and then immediately shutdown the systemthis bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\"\n            },\n            \"redeemLong(uint256)\": {\n                \"details\": \"redeem wPowerPerp for its index value when the system is shutdown\",\n                \"params\": {\n                    \"_wPerpAmount\": \"amount of wPowerPerp to burn\"\n                }\n            },\n            \"redeemShort(uint256)\": {\n                \"details\": \"redeem additional collateral from the vault when the system is shutdown\",\n                \"params\": {\n                    \"_vaultId\": \"vauld id\"\n                }\n            },\n            \"reduceDebt(uint256)\": {\n                \"details\": \"the caller won't get any bounty. this is expected to be used by vault owner\",\n                \"params\": {\n                    \"_vaultId\": \"the vault you want to save\"\n                }\n            },\n            \"renounceOwnership()\": {\n                \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n            },\n            \"setFeeRate(uint256)\": {\n                \"details\": \"set the fee rate when user deposit or withdraw collateralthis function cannot be called if the feeRecipient is still un-set\",\n                \"params\": {\n                    \"_newFeeRate\": \"new fee rate in basis point. can't be higher than 2%\"\n                }\n            },\n            \"setFeeRecipient(address)\": {\n                \"details\": \"set the recipient who will receive the fee. this should be a contract handling insurance.\",\n                \"params\": {\n                    \"_newFeeRecipient\": \"new fee recipient\"\n                }\n            },\n            \"shutDown()\": {\n                \"details\": \"shutdown the system and enable system settlement\"\n            },\n            \"transferOwnership(address)\": {\n                \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n            },\n            \"unPauseAnyone()\": {\n                \"details\": \"anyone can unpause the contract after 24 hours\"\n            },\n            \"unPauseOwner()\": {\n                \"details\": \"owner can unpause at any time\"\n            },\n            \"updateOperator(uint256,address)\": {\n                \"details\": \"can be revoke by setting address to 0.\",\n                \"params\": {\n                    \"_operator\": \"new operator address\",\n                    \"_vaultId\": \"id of the vault\"\n                }\n            },\n            \"withdraw(uint256,uint256)\": {\n                \"params\": {\n                    \"_amount\": \"amount of eth to withdraw\",\n                    \"_vaultId\": \"id of the vault\"\n                }\n            },\n            \"withdrawUniPositionToken(uint256)\": {\n                \"details\": \"withdraw uniswap v3 position token from a vault\",\n                \"params\": {\n                    \"_vaultId\": \"id of the vault\"\n                }\n            }\n        },\n        \"stateVariables\": {\n            \"PAUSE_TIME_LIMIT\": {\n                \"details\": \"system can only be paused for 365 days from deployment\"\n            },\n            \"feeRate\": {\n                \"details\": \"fee rate in basis point. feeRate of 1 = 0.01%\"\n            },\n            \"indexForSettlement\": {\n                \"details\": \"the settlement price for each wPowerPerp for settlement\"\n            },\n            \"vaults\": {\n                \"details\": \"The token ID vault data\"\n            },\n            \"wPowerPerpPool\": {\n                \"details\": \"address of the powerPerp/weth pool\"\n            }\n        },\n        \"version\": 1\n    },\n    \"userdoc\": {\n        \"events\": {\n            \"OpenVault(uint256)\": {\n                \"notice\": \"Events\"\n            }\n        },\n        \"kind\": \"user\",\n        \"methods\": {\n            \"burnPowerPerpAmount(uint256,uint256,uint256)\": {\n                \"notice\": \"burn powerPerp and remove collateral from a vault.\"\n            },\n            \"burnWPowerPerpAmount(uint256,uint256,uint256)\": {\n                \"notice\": \"burn wPowerPerp and remove collateral from a vault.\"\n            },\n            \"depositUniPositionToken(uint256,uint256)\": {\n                \"notice\": \"deposit uniswap v3 position token into a vault to increase collateral ratio\"\n            },\n            \"donate()\": {\n                \"notice\": \"a function to add eth into a contract, in case it got insolvent and have ensufficient eth to pay out for settlement.\"\n            },\n            \"getDenormalizedMark(uint32)\": {\n                \"notice\": \"get the mark price of powerPerp.\"\n            },\n            \"getExpectedNormalizationFactor()\": {\n                \"notice\": \"returns the expected normalization factor, if the funding is paid right now.\"\n            },\n            \"getIndex(uint32)\": {\n                \"notice\": \"get the index price of powerPerp.\"\n            },\n            \"init(address,address,address,address,address,address,address,address)\": {\n                \"notice\": \"initialize the contract\"\n            },\n            \"liquidate(uint256,uint256)\": {\n                \"notice\": \"if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\"\n            },\n            \"mintPowerPerpAmount(uint256,uint128,uint256)\": {\n                \"notice\": \"put down collateral and mint wPowerPerp.\"\n            },\n            \"mintWPowerPerpAmount(uint256,uint128,uint256)\": {\n                \"notice\": \"put down collateral and mint wPowerPerp.\"\n            },\n            \"reduceDebt(uint256)\": {\n                \"notice\": \"if a vault is unsafe and has a UNI NFT in it, owner call redeem the NFT to pay back some debt.\"\n            },\n            \"updateOperator(uint256,address)\": {\n                \"notice\": \"authorize an address to modify the vault.\"\n            },\n            \"withdraw(uint256,uint256)\": {\n                \"notice\": \"withdraw collateral from a vault\"\n            }\n        },\n        \"version\": 1\n    },\n    \"storageLayout\": {\n        \"storage\": [\n            {\n                \"astId\": 3642,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"_initialized\",\n                \"offset\": 0,\n                \"slot\": \"0\",\n                \"type\": \"t_bool\"\n            },\n            {\n                \"astId\": 3645,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"_initializing\",\n                \"offset\": 1,\n                \"slot\": \"0\",\n                \"type\": \"t_bool\"\n            },\n            {\n                \"astId\": 3109,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"_owner\",\n                \"offset\": 2,\n                \"slot\": \"0\",\n                \"type\": \"t_address\"\n            },\n            {\n                \"astId\": 10967,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"isShutDown\",\n                \"offset\": 22,\n                \"slot\": \"0\",\n                \"type\": \"t_bool\"\n            },\n            {\n                \"astId\": 10970,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"isSystemPaused\",\n                \"offset\": 23,\n                \"slot\": \"0\",\n                \"type\": \"t_bool\"\n            },\n            {\n                \"astId\": 10973,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"pausesLeft\",\n                \"offset\": 0,\n                \"slot\": \"1\",\n                \"type\": \"t_uint256\"\n            },\n            {\n                \"astId\": 10976,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"lastPauseTime\",\n                \"offset\": 0,\n                \"slot\": \"2\",\n                \"type\": \"t_uint256\"\n            },\n            {\n                \"astId\": 10978,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"weth\",\n                \"offset\": 0,\n                \"slot\": \"3\",\n                \"type\": \"t_address\"\n            },\n            {\n                \"astId\": 10980,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"dai\",\n                \"offset\": 0,\n                \"slot\": \"4\",\n                \"type\": \"t_address\"\n            },\n            {\n                \"astId\": 10982,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"ethDaiPool\",\n                \"offset\": 0,\n                \"slot\": \"5\",\n                \"type\": \"t_address\"\n            },\n            {\n                \"astId\": 10984,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"feeRecipient\",\n                \"offset\": 0,\n                \"slot\": \"6\",\n                \"type\": \"t_address\"\n            },\n            {\n                \"astId\": 10987,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"wPowerPerpPool\",\n                \"offset\": 0,\n                \"slot\": \"7\",\n                \"type\": \"t_address\"\n            },\n            {\n                \"astId\": 10989,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"uniswapPositionManager\",\n                \"offset\": 0,\n                \"slot\": \"8\",\n                \"type\": \"t_address\"\n            },\n            {\n                \"astId\": 10992,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"feeRate\",\n                \"offset\": 0,\n                \"slot\": \"9\",\n                \"type\": \"t_uint256\"\n            },\n            {\n                \"astId\": 10995,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"indexForSettlement\",\n                \"offset\": 0,\n                \"slot\": \"10\",\n                \"type\": \"t_uint256\"\n            },\n            {\n                \"astId\": 10997,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"normalizationFactor\",\n                \"offset\": 0,\n                \"slot\": \"11\",\n                \"type\": \"t_uint256\"\n            },\n            {\n                \"astId\": 10999,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"lastFundingUpdateTimestamp\",\n                \"offset\": 0,\n                \"slot\": \"12\",\n                \"type\": \"t_uint256\"\n            },\n            {\n                \"astId\": 11001,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"deployTimestamp\",\n                \"offset\": 0,\n                \"slot\": \"13\",\n                \"type\": \"t_uint256\"\n            },\n            {\n                \"astId\": 11003,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"isWethToken0\",\n                \"offset\": 0,\n                \"slot\": \"14\",\n                \"type\": \"t_bool\"\n            },\n            {\n                \"astId\": 11008,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"vaults\",\n                \"offset\": 0,\n                \"slot\": \"15\",\n                \"type\": \"t_mapping(t_uint256,t_struct(Vault)14581_storage)\"\n            },\n            {\n                \"astId\": 11010,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"vaultNFT\",\n                \"offset\": 0,\n                \"slot\": \"16\",\n                \"type\": \"t_contract(IVaultManagerNFT)14224\"\n            },\n            {\n                \"astId\": 11012,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"wPowerPerp\",\n                \"offset\": 0,\n                \"slot\": \"17\",\n                \"type\": \"t_contract(IWPowerPerp)14260\"\n            },\n            {\n                \"astId\": 11014,\n                \"contract\": \"contracts/core/Controller.sol:Controller\",\n                \"label\": \"oracle\",\n                \"offset\": 0,\n                \"slot\": \"18\",\n                \"type\": \"t_contract(IOracle)14210\"\n            }\n        ],\n        \"types\": {\n            \"t_address\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"address\",\n                \"numberOfBytes\": \"20\"\n            },\n            \"t_bool\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"bool\",\n                \"numberOfBytes\": \"1\"\n            },\n            \"t_contract(IOracle)14210\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"contract IOracle\",\n                \"numberOfBytes\": \"20\"\n            },\n            \"t_contract(IVaultManagerNFT)14224\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"contract IVaultManagerNFT\",\n                \"numberOfBytes\": \"20\"\n            },\n            \"t_contract(IWPowerPerp)14260\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"contract IWPowerPerp\",\n                \"numberOfBytes\": \"20\"\n            },\n            \"t_mapping(t_uint256,t_struct(Vault)14581_storage)\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_uint256\",\n                \"label\": \"mapping(uint256 => struct VaultLib.Vault)\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_struct(Vault)14581_storage\"\n            },\n            \"t_struct(Vault)14581_storage\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"struct VaultLib.Vault\",\n                \"members\": [\n                    {\n                        \"astId\": 14574,\n                        \"contract\": \"contracts/core/Controller.sol:Controller\",\n                        \"label\": \"operator\",\n                        \"offset\": 0,\n                        \"slot\": \"0\",\n                        \"type\": \"t_address\"\n                    },\n                    {\n                        \"astId\": 14576,\n                        \"contract\": \"contracts/core/Controller.sol:Controller\",\n                        \"label\": \"NftCollateralId\",\n                        \"offset\": 20,\n                        \"slot\": \"0\",\n                        \"type\": \"t_uint32\"\n                    },\n                    {\n                        \"astId\": 14578,\n                        \"contract\": \"contracts/core/Controller.sol:Controller\",\n                        \"label\": \"collateralAmount\",\n                        \"offset\": 0,\n                        \"slot\": \"1\",\n                        \"type\": \"t_uint96\"\n                    },\n                    {\n                        \"astId\": 14580,\n                        \"contract\": \"contracts/core/Controller.sol:Controller\",\n                        \"label\": \"shortAmount\",\n                        \"offset\": 12,\n                        \"slot\": \"1\",\n                        \"type\": \"t_uint128\"\n                    }\n                ],\n                \"numberOfBytes\": \"64\"\n            },\n            \"t_uint128\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"uint128\",\n                \"numberOfBytes\": \"16\"\n            },\n            \"t_uint256\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"uint256\",\n                \"numberOfBytes\": \"32\"\n            },\n            \"t_uint32\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"uint32\",\n                \"numberOfBytes\": \"4\"\n            },\n            \"t_uint96\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"uint96\",\n                \"numberOfBytes\": \"12\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/MockErc20.json",
    "content": "{\n    \"address\": \"0xc4D15025D49a88D70B023870d810f4cAa5c18a63\",\n    \"abi\": [\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"string\",\n                    \"name\": \"_name\",\n                    \"type\": \"string\"\n                },\n                {\n                    \"internalType\": \"string\",\n                    \"name\": \"_symbol\",\n                    \"type\": \"string\"\n                },\n                {\n                    \"internalType\": \"uint8\",\n                    \"name\": \"_decimals\",\n                    \"type\": \"uint8\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"constructor\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"owner\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"spender\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"value\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"Approval\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"from\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"to\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"value\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"Transfer\",\n            \"type\": \"event\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"owner\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"spender\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"allowance\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"spender\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"approve\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"account\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"balanceOf\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_account\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"burn\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"decimals\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint8\",\n                    \"name\": \"\",\n                    \"type\": \"uint8\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"spender\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"subtractedValue\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"decreaseAllowance\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"spender\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"addedValue\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"increaseAllowance\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_account\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"mint\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"name\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"string\",\n                    \"name\": \"\",\n                    \"type\": \"string\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"symbol\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"string\",\n                    \"name\": \"\",\n                    \"type\": \"string\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"totalSupply\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"recipient\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"transfer\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"sender\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"recipient\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"transferFrom\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        }\n    ],\n    \"transactionHash\": \"0x01de4cc94e540ca59eeceb47e5dd07fce2e96f8d4c735f07758e0551e46e8233\",\n    \"receipt\": {\n        \"to\": null,\n        \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n        \"contractAddress\": \"0xc6F00D0f00f335Ead438e05Cfe4FB2D5d296Fbd8\",\n        \"transactionIndex\": 0,\n        \"gasUsed\": \"29963423\",\n        \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n        \"blockHash\": \"0x1468ef6fa43a9ec518322a8fa37e3becdf2f96b090117efac39498afa3a768d9\",\n        \"transactionHash\": \"0x01de4cc94e540ca59eeceb47e5dd07fce2e96f8d4c735f07758e0551e46e8233\",\n        \"logs\": [],\n        \"blockNumber\": 5750357,\n        \"cumulativeGasUsed\": \"21938723\",\n        \"status\": 1,\n        \"byzantium\": true\n    },\n    \"args\": [\"DAI\", \"DAI\", 18],\n    \"solcInputHash\": \"49c79f88c6e4ede6ca1f2ffd46fef4fe\",\n    \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_name\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_symbol\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"_decimals\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burn\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"subtractedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"decreaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"addedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"increaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mint\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"allowance(address,address)\\\":{\\\"details\\\":\\\"See {IERC20-allowance}.\\\"},\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC20-balanceOf}.\\\"},\\\"decimals()\\\":{\\\"details\\\":\\\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\\\"},\\\"decreaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\\\"},\\\"increaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\\\"},\\\"name()\\\":{\\\"details\\\":\\\"Returns the name of the token.\\\"},\\\"symbol()\\\":{\\\"details\\\":\\\"Returns the symbol of the token, usually a shorter version of the name.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC20-totalSupply}.\\\"},\\\"transfer(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/mocks/MockErc20.sol\\\":\\\"MockErc20\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":2000},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/mocks/MockErc20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\n\\\\ncontract MockErc20 is ERC20 {\\\\n    constructor(\\\\n        string memory _name,\\\\n        string memory _symbol,\\\\n        uint8 _decimals\\\\n    ) ERC20(_name, _symbol) {\\\\n        _setupDecimals(_decimals);\\\\n    }\\\\n\\\\n    function mint(address _account, uint256 _amount) external {\\\\n        _mint(_account, _amount);\\\\n    }\\\\n\\\\n    function burn(address _account, uint256 _amount) external {\\\\n        _burn(_account, _amount);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0b401e514fdf4396a3b75281e10c256f257cc9857e0330747226d811ad49307d\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n    \"bytecode\": \"0x60806040523480156200001157600080fd5b5060405162000fef38038062000fef833981810160405260608110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200010a57600080fd5b9083019060208201858111156200012057600080fd5b82516401000000008111828201881017156200013b57600080fd5b82525081516020918201929091019080838360005b838110156200016a57818101518382015260200162000150565b50505050905090810190601f168015620001985780820380516001836020036101000a031916815260200191505b5060405260209081015185519093508592508491620001bd916003918501906200020d565b508051620001d39060049060208401906200020d565b50506005805460ff1916601217905550620001ee81620001f7565b505050620002b9565b6005805460ff191660ff92909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928262000245576000855562000290565b82601f106200026057805160ff191683800117855562000290565b8280016001018555821562000290579182015b828111156200029057825182559160200191906001019062000273565b506200029e929150620002a2565b5090565b5b808211156200029e5760008155600101620002a3565b610d2680620002c96000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c806340c10f191161008c5780639dc29fac116100665780639dc29fac14610297578063a457c2d7146102c3578063a9059cbb146102ef578063dd62ed3e1461031b576100df565b806340c10f191461023b57806370a082311461026957806395d89b411461028f576100df565b806323b872dd116100bd57806323b872dd146101bb578063313ce567146101f1578063395093511461020f576100df565b806306fdde03146100e4578063095ea7b31461016157806318160ddd146101a1575b600080fd5b6100ec610349565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561012657818101518382015260200161010e565b50505050905090810190601f1680156101535780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61018d6004803603604081101561017757600080fd5b506001600160a01b0381351690602001356103df565b604080519115158252519081900360200190f35b6101a96103fc565b60408051918252519081900360200190f35b61018d600480360360608110156101d157600080fd5b506001600160a01b03813581169160208101359091169060400135610402565b6101f9610489565b6040805160ff9092168252519081900360200190f35b61018d6004803603604081101561022557600080fd5b506001600160a01b038135169060200135610492565b6102676004803603604081101561025157600080fd5b506001600160a01b0381351690602001356104e0565b005b6101a96004803603602081101561027f57600080fd5b50356001600160a01b03166104ee565b6100ec610509565b610267600480360360408110156102ad57600080fd5b506001600160a01b03813516906020013561056a565b61018d600480360360408110156102d957600080fd5b506001600160a01b038135169060200135610574565b61018d6004803603604081101561030557600080fd5b506001600160a01b0381351690602001356105dc565b6101a96004803603604081101561033157600080fd5b506001600160a01b03813581169160200135166105f0565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156103d55780601f106103aa576101008083540402835291602001916103d5565b820191906000526020600020905b8154815290600101906020018083116103b857829003601f168201915b5050505050905090565b60006103f36103ec61061b565b848461061f565b50600192915050565b60025490565b600061040f84848461070b565b61047f8461041b61061b565b61047a85604051806060016040528060288152602001610c3a602891396001600160a01b038a1660009081526001602052604081209061045961061b565b6001600160a01b031681526020810191909152604001600020549190610866565b61061f565b5060019392505050565b60055460ff1690565b60006103f361049f61061b565b8461047a85600160006104b061061b565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906108fd565b6104ea828261095e565b5050565b6001600160a01b031660009081526020819052604090205490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156103d55780601f106103aa576101008083540402835291602001916103d5565b6104ea8282610a4e565b60006103f361058161061b565b8461047a85604051806060016040528060258152602001610ccc60259139600160006105ab61061b565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610866565b60006103f36105e961061b565b848461070b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3390565b6001600160a01b0383166106645760405162461bcd60e51b8152600401808060200182810382526024815260200180610ca86024913960400191505060405180910390fd5b6001600160a01b0382166106a95760405162461bcd60e51b8152600401808060200182810382526022815260200180610bf26022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166107505760405162461bcd60e51b8152600401808060200182810382526025815260200180610c836025913960400191505060405180910390fd5b6001600160a01b0382166107955760405162461bcd60e51b8152600401808060200182810382526023815260200180610bad6023913960400191505060405180910390fd5b6107a0838383610b4a565b6107dd81604051806060016040528060268152602001610c14602691396001600160a01b0386166000908152602081905260409020549190610866565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461080c90826108fd565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156108f55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156108ba5781810151838201526020016108a2565b50505050905090810190601f1680156108e75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610957576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b0382166109b9576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6109c560008383610b4a565b6002546109d290826108fd565b6002556001600160a01b0382166000908152602081905260409020546109f890826108fd565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610a935760405162461bcd60e51b8152600401808060200182810382526021815260200180610c626021913960400191505060405180910390fd5b610a9f82600083610b4a565b610adc81604051806060016040528060228152602001610bd0602291396001600160a01b0385166000908152602081905260409020549190610866565b6001600160a01b038316600090815260208190526040902055600254610b029082610b4f565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b505050565b600082821115610ba6576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220a5b9341e66228c9608963e685c83976b2be2510618fcb4b84654c2a99d4a2cfd64736f6c63430007060033\",\n    \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100df5760003560e01c806340c10f191161008c5780639dc29fac116100665780639dc29fac14610297578063a457c2d7146102c3578063a9059cbb146102ef578063dd62ed3e1461031b576100df565b806340c10f191461023b57806370a082311461026957806395d89b411461028f576100df565b806323b872dd116100bd57806323b872dd146101bb578063313ce567146101f1578063395093511461020f576100df565b806306fdde03146100e4578063095ea7b31461016157806318160ddd146101a1575b600080fd5b6100ec610349565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561012657818101518382015260200161010e565b50505050905090810190601f1680156101535780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61018d6004803603604081101561017757600080fd5b506001600160a01b0381351690602001356103df565b604080519115158252519081900360200190f35b6101a96103fc565b60408051918252519081900360200190f35b61018d600480360360608110156101d157600080fd5b506001600160a01b03813581169160208101359091169060400135610402565b6101f9610489565b6040805160ff9092168252519081900360200190f35b61018d6004803603604081101561022557600080fd5b506001600160a01b038135169060200135610492565b6102676004803603604081101561025157600080fd5b506001600160a01b0381351690602001356104e0565b005b6101a96004803603602081101561027f57600080fd5b50356001600160a01b03166104ee565b6100ec610509565b610267600480360360408110156102ad57600080fd5b506001600160a01b03813516906020013561056a565b61018d600480360360408110156102d957600080fd5b506001600160a01b038135169060200135610574565b61018d6004803603604081101561030557600080fd5b506001600160a01b0381351690602001356105dc565b6101a96004803603604081101561033157600080fd5b506001600160a01b03813581169160200135166105f0565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156103d55780601f106103aa576101008083540402835291602001916103d5565b820191906000526020600020905b8154815290600101906020018083116103b857829003601f168201915b5050505050905090565b60006103f36103ec61061b565b848461061f565b50600192915050565b60025490565b600061040f84848461070b565b61047f8461041b61061b565b61047a85604051806060016040528060288152602001610c3a602891396001600160a01b038a1660009081526001602052604081209061045961061b565b6001600160a01b031681526020810191909152604001600020549190610866565b61061f565b5060019392505050565b60055460ff1690565b60006103f361049f61061b565b8461047a85600160006104b061061b565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906108fd565b6104ea828261095e565b5050565b6001600160a01b031660009081526020819052604090205490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156103d55780601f106103aa576101008083540402835291602001916103d5565b6104ea8282610a4e565b60006103f361058161061b565b8461047a85604051806060016040528060258152602001610ccc60259139600160006105ab61061b565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610866565b60006103f36105e961061b565b848461070b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3390565b6001600160a01b0383166106645760405162461bcd60e51b8152600401808060200182810382526024815260200180610ca86024913960400191505060405180910390fd5b6001600160a01b0382166106a95760405162461bcd60e51b8152600401808060200182810382526022815260200180610bf26022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166107505760405162461bcd60e51b8152600401808060200182810382526025815260200180610c836025913960400191505060405180910390fd5b6001600160a01b0382166107955760405162461bcd60e51b8152600401808060200182810382526023815260200180610bad6023913960400191505060405180910390fd5b6107a0838383610b4a565b6107dd81604051806060016040528060268152602001610c14602691396001600160a01b0386166000908152602081905260409020549190610866565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461080c90826108fd565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156108f55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156108ba5781810151838201526020016108a2565b50505050905090810190601f1680156108e75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610957576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b0382166109b9576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6109c560008383610b4a565b6002546109d290826108fd565b6002556001600160a01b0382166000908152602081905260409020546109f890826108fd565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610a935760405162461bcd60e51b8152600401808060200182810382526021815260200180610c626021913960400191505060405180910390fd5b610a9f82600083610b4a565b610adc81604051806060016040528060228152602001610bd0602291396001600160a01b0385166000908152602081905260409020549190610866565b6001600160a01b038316600090815260208190526040902055600254610b029082610b4f565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b505050565b600082821115610ba6576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220a5b9341e66228c9608963e685c83976b2be2510618fcb4b84654c2a99d4a2cfd64736f6c63430007060033\",\n    \"devdoc\": {\n        \"kind\": \"dev\",\n        \"methods\": {\n            \"allowance(address,address)\": {\n                \"details\": \"See {IERC20-allowance}.\"\n            },\n            \"approve(address,uint256)\": {\n                \"details\": \"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"\n            },\n            \"balanceOf(address)\": {\n                \"details\": \"See {IERC20-balanceOf}.\"\n            },\n            \"decimals()\": {\n                \"details\": \"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"\n            },\n            \"decreaseAllowance(address,uint256)\": {\n                \"details\": \"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"\n            },\n            \"increaseAllowance(address,uint256)\": {\n                \"details\": \"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"\n            },\n            \"name()\": {\n                \"details\": \"Returns the name of the token.\"\n            },\n            \"symbol()\": {\n                \"details\": \"Returns the symbol of the token, usually a shorter version of the name.\"\n            },\n            \"totalSupply()\": {\n                \"details\": \"See {IERC20-totalSupply}.\"\n            },\n            \"transfer(address,uint256)\": {\n                \"details\": \"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"\n            },\n            \"transferFrom(address,address,uint256)\": {\n                \"details\": \"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"\n            }\n        },\n        \"version\": 1\n    },\n    \"userdoc\": {\n        \"kind\": \"user\",\n        \"methods\": {},\n        \"version\": 1\n    },\n    \"storageLayout\": {\n        \"storage\": [\n            {\n                \"astId\": 3718,\n                \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n                \"label\": \"_balances\",\n                \"offset\": 0,\n                \"slot\": \"0\",\n                \"type\": \"t_mapping(t_address,t_uint256)\"\n            },\n            {\n                \"astId\": 3724,\n                \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n                \"label\": \"_allowances\",\n                \"offset\": 0,\n                \"slot\": \"1\",\n                \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n            },\n            {\n                \"astId\": 3726,\n                \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n                \"label\": \"_totalSupply\",\n                \"offset\": 0,\n                \"slot\": \"2\",\n                \"type\": \"t_uint256\"\n            },\n            {\n                \"astId\": 3728,\n                \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n                \"label\": \"_name\",\n                \"offset\": 0,\n                \"slot\": \"3\",\n                \"type\": \"t_string_storage\"\n            },\n            {\n                \"astId\": 3730,\n                \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n                \"label\": \"_symbol\",\n                \"offset\": 0,\n                \"slot\": \"4\",\n                \"type\": \"t_string_storage\"\n            },\n            {\n                \"astId\": 3732,\n                \"contract\": \"contracts/mocks/MockErc20.sol:MockErc20\",\n                \"label\": \"_decimals\",\n                \"offset\": 0,\n                \"slot\": \"5\",\n                \"type\": \"t_uint8\"\n            }\n        ],\n        \"types\": {\n            \"t_address\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"address\",\n                \"numberOfBytes\": \"20\"\n            },\n            \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_address\",\n                \"label\": \"mapping(address => mapping(address => uint256))\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_mapping(t_address,t_uint256)\"\n            },\n            \"t_mapping(t_address,t_uint256)\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_address\",\n                \"label\": \"mapping(address => uint256)\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_uint256\"\n            },\n            \"t_string_storage\": {\n                \"encoding\": \"bytes\",\n                \"label\": \"string\",\n                \"numberOfBytes\": \"32\"\n            },\n            \"t_uint256\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"uint256\",\n                \"numberOfBytes\": \"32\"\n            },\n            \"t_uint8\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"uint8\",\n                \"numberOfBytes\": \"1\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/Oracle.json",
    "content": "{\n    \"address\": \"0xe790Afe86c0bdc4Dd7C6CBb7dB087552Ec85F6fB\",\n    \"abi\": [\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_pool\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"getMaxPeriod\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint32\",\n                    \"name\": \"\",\n                    \"type\": \"uint32\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_pool\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint32\",\n                    \"name\": \"_period\",\n                    \"type\": \"uint32\"\n                }\n            ],\n            \"name\": \"getTimeWeightedAverageTickSafe\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"int24\",\n                    \"name\": \"timeWeightedAverageTick\",\n                    \"type\": \"int24\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_pool\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_base\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_quote\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint32\",\n                    \"name\": \"_period\",\n                    \"type\": \"uint32\"\n                }\n            ],\n            \"name\": \"getTwap\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_pool\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_base\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_quote\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint32\",\n                    \"name\": \"_period\",\n                    \"type\": \"uint32\"\n                }\n            ],\n            \"name\": \"getTwapSafe\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        }\n    ],\n    \"transactionHash\": \"0x08142c247da4d6a00b94c6448c1c65013b42ae216cfda3e1ee1ba6aa96a42722\",\n    \"receipt\": {\n        \"to\": null,\n        \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n        \"contractAddress\": \"0xe790Afe86c0bdc4Dd7C6CBb7dB087552Ec85F6fB\",\n        \"transactionIndex\": 0,\n        \"gasUsed\": \"7596567\",\n        \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n        \"blockHash\": \"0x8130e9cbd701c0dbfc740a28e162b7dcf7fd0376c20137d78377863555f12572\",\n        \"transactionHash\": \"0x08142c247da4d6a00b94c6448c1c65013b42ae216cfda3e1ee1ba6aa96a42722\",\n        \"logs\": [],\n        \"blockNumber\": 5750458,\n        \"cumulativeGasUsed\": \"72807\",\n        \"status\": 1,\n        \"byzantium\": true\n    },\n    \"args\": [],\n    \"solcInputHash\": \"49c79f88c6e4ede6ca1f2ffd46fef4fe\",\n    \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"getMaxPeriod\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getTimeWeightedAverageTickSafe\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"timeWeightedAverageTick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_base\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_quote\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getTwap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_base\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_quote\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getTwapSafe\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"getMaxPeriod(address)\\\":{\\\"params\\\":{\\\"_pool\\\":\\\"uniswap pool address\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"max period can be used to request twap\\\"}},\\\"getTimeWeightedAverageTickSafe(address,uint32)\\\":{\\\"details\\\":\\\"this function will not revert\\\",\\\"params\\\":{\\\"_period\\\":\\\"period in second that we want to calculate average on\\\",\\\"_pool\\\":\\\"address of the pool\\\"},\\\"returns\\\":{\\\"timeWeightedAverageTick\\\":\\\"the time weighted average tick\\\"}},\\\"getTwap(address,address,address,uint32)\\\":{\\\"details\\\":\\\"if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\".\\\",\\\"params\\\":{\\\"_base\\\":\\\"base currency. to get eth/dai price, eth is base token\\\",\\\"_period\\\":\\\"number of seconds in the past to start calculating time-weighted average\\\",\\\"_pool\\\":\\\"uniswap pool address\\\",\\\"_quote\\\":\\\"quote currency. to get eth/dai price, dai is the quote currency\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"price of 1 base currency in quote currency. scaled by 1e18\\\"}},\\\"getTwapSafe(address,address,address,uint32)\\\":{\\\"params\\\":{\\\"_base\\\":\\\"base currency. to get eth/dai price, eth is base token\\\",\\\"_period\\\":\\\"number of seconds in the past to start calculating time-weighted average\\\",\\\"_pool\\\":\\\"uniswap pool address\\\",\\\"_quote\\\":\\\"quote currency. to get eth/dai price, dai is the quote currency\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"price of 1 base currency in quote currency. scaled by 1e18\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"getMaxPeriod(address)\\\":{\\\"notice\\\":\\\"get the max period that can be used to request twap.\\\"},\\\"getTimeWeightedAverageTickSafe(address,uint32)\\\":{\\\"notice\\\":\\\"get time weighed average tick, not converted to price\\\"},\\\"getTwap(address,address,address,uint32)\\\":{\\\"notice\\\":\\\"get twap converted with base & quote token decimals\\\"},\\\"getTwapSafe(address,address,address,uint32)\\\":{\\\"notice\\\":\\\"get twap converted with base & quote token decimals, never reverts\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/Oracle.sol\\\":\\\"Oracle\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":2000},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Oracle library\\\\n/// @notice Provides functions to integrate with V3 pool oracle\\\\nlibrary OracleLibrary {\\\\n    /// @notice Fetches time-weighted average tick using Uniswap V3 oracle\\\\n    /// @param pool Address of Uniswap V3 pool that we want to observe\\\\n    /// @param period Number of seconds in the past to start calculating time-weighted average\\\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - period) to block.timestamp\\\\n    function consult(address pool, uint32 period) internal view returns (int24 timeWeightedAverageTick) {\\\\n        require(period != 0, 'BP');\\\\n\\\\n        uint32[] memory secondAgos = new uint32[](2);\\\\n        secondAgos[0] = period;\\\\n        secondAgos[1] = 0;\\\\n\\\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\\\n\\\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / period);\\\\n\\\\n        // Always round to negative infinity\\\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % period != 0)) timeWeightedAverageTick--;\\\\n    }\\\\n\\\\n    /// @notice Given a tick and a token amount, calculates the amount of token received in exchange\\\\n    /// @param tick Tick value used to calculate the quote\\\\n    /// @param baseAmount Amount of token to be converted\\\\n    /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination\\\\n    /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination\\\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\\\n    function getQuoteAtTick(\\\\n        int24 tick,\\\\n        uint128 baseAmount,\\\\n        address baseToken,\\\\n        address quoteToken\\\\n    ) internal pure returns (uint256 quoteAmount) {\\\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\\\n\\\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\\\n        if (sqrtRatioX96 <= type(uint128).max) {\\\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\\\n            quoteAmount = baseToken < quoteToken\\\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\\\n        } else {\\\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\\\n            quoteAmount = baseToken < quoteToken\\\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x19517bf2478c3ec56253f37b48adde7f34a6acdb467e329f74d79f9e72e2a63f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/core/Oracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// uniswap Library only works under 0.7.6\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {OracleLibrary} from \\\\\\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\\\\\";\\\\nimport {IERC20Detailed} from \\\\\\\"../interfaces/IERC20Detailed.sol\\\\\\\";\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\ncontract Oracle {\\\\n    using SafeMath for uint256;\\\\n\\\\n    /**\\\\n     * @notice get twap converted with base & quote token decimals\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\".\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/dai price, eth is base token\\\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\\\n     */\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) external view returns (uint256) {\\\\n        return _fetchTwap(_pool, _base, _quote, _period);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap converted with base & quote token decimals, never reverts\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/dai price, eth is base token\\\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\\\n     */\\\\n    function getTwapSafe(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) external view returns (uint256) {\\\\n        return _fetchTwapSafe(_pool, _base, _quote, _period);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the max period that can be used to request twap.\\\\n     * @param _pool uniswap pool address\\\\n     * @return max period can be used to request twap\\\\n     */\\\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\\\n        return _getMaxPeriod(_pool);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get time weighed average tick, not converted to price\\\\n     * @dev this function will not revert\\\\n     * @param _pool address of the pool\\\\n     * @param _period period in second that we want to calculate average on\\\\n     * @return timeWeightedAverageTick the time weighted average tick\\\\n     */\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick)\\\\n    {\\\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\\\n        return OracleLibrary.consult(_pool, requestPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap converted with base & quote token decimals, never reverts.\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\".\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/dai price, eth is base token\\\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return twap price which is scaled\\\\n     */\\\\n    function _fetchTwapSafe(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap converted with base & quote token decimals\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\".\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/dai price, eth is base token\\\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return twap price which is scaled\\\\n     */\\\\n    function _fetchTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period, uint256(1e18));\\\\n\\\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\\\n\\\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\\\n\\\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get raw twap from the uniswap pool\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\".\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/dai price, eth is base token\\\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return Amount of quoteToken received for _amountIn of baseToken\\\\n     */\\\\n    function _fetchRawTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint256 _amountIn\\\\n    ) internal view returns (uint256) {\\\\n        int24 twapTick = OracleLibrary.consult(_pool, _period);\\\\n        return OracleLibrary.getQuoteAtTick(twapTick, toUint128(_amountIn), _base, _quote);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the max period that can be used to request twap.\\\\n     * @param _pool uniswap pool address\\\\n     * @return max period can be used to request twap\\\\n     */\\\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\\\n        // observationIndex: the index of the last oracle observation that was written\\\\n        // cardinality: The current maximum number of observations stored in the pool\\\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\\\n\\\\n        // first observation index\\\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\\\n\\\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\\\n\\\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\\\n\\\\n        // index + 1 % cardinality is not the oldest index,\\\\n        // probably because cardinality is increased after last observation.\\\\n        // in this case, observation at index 0 should be the oldest.\\\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\\\n\\\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice Cast a uint256 to a uint128, revert on overflow\\\\n     * @param y The uint256 to be downcasted\\\\n     * @return z The downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"overflow\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e753c62c4bd700ac27a8951778ae9af847654e202e001cf24fbe73075975053\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IERC20Detailed.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// uniswap Library only works under 0.7.6\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IERC20Detailed is IERC20 {\\\\n    function decimals() external view returns (uint8);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcd59a0158d0711810c499904b9d37a71fdb34d1c4403f3cb67ca47de5e88bf7b\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n    \"bytecode\": \"0x608060405234801561001057600080fd5b50610fb4806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634a0a96eb14610051578063821b972a1461009a578063d6906e6d146100ef578063de5a6e2214610132575b600080fd5b6100836004803603604081101561006757600080fd5b5080356001600160a01b0316906020013563ffffffff16610171565b6040805160029290920b8252519081900360200190f35b6100dd600480360360808110156100b057600080fd5b5080356001600160a01b03908116916020810135821691604082013516906060013563ffffffff166101b3565b60408051918252519081900360200190f35b6100dd6004803603608081101561010557600080fd5b5080356001600160a01b03908116916020810135821691604082013516906060013563ffffffff166101cc565b6101586004803603602081101561014857600080fd5b50356001600160a01b03166101da565b6040805163ffffffff9092168252519081900360200190f35b60008061017d846101ed565b905060008163ffffffff168463ffffffff161161019a578361019c565b815b90506101a88582610399565b925050505b92915050565b60006101c1858585856106eb565b90505b949350505050565b60006101c18585858561085a565b60006101e5826101ed565b90505b919050565b600080829050600080826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561022f57600080fd5b505afa158015610243573d6000803e3d6000fd5b505050506040513d60e081101561025957600080fd5b5060408101516060909101519092509050600061ffff8083169060018501168161027f57fe5b069050600080856001600160a01b031663252c09d7846040518263ffffffff1660e01b8152600401808261ffff16815260200191505060806040518083038186803b1580156102cd57600080fd5b505afa1580156102e1573d6000803e3d6000fd5b505050506040513d60808110156102f757600080fd5b5080516060909101519092509050801561031a5750420394506101e89350505050565b856001600160a01b031663252c09d760006040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b15801561035f57600080fd5b505afa158015610373573d6000803e3d6000fd5b505050506040513d608081101561038957600080fd5b5051420398975050505050505050565b600063ffffffff82166103f3576040805162461bcd60e51b815260206004820152600260248201527f4250000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b604080516002808252606082018352600092602083019080368337019050509050828160008151811061042257fe5b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061044b57fe5b63ffffffff9092166020928302919091018201526040517f883bdbfd000000000000000000000000000000000000000000000000000000008152600481018281528351602483015283516000936001600160a01b0389169363883bdbfd938793909283926044019185820191028083838b5b838110156104d55781810151838201526020016104bd565b505050509050019250505060006040518083038186803b1580156104f857600080fd5b505afa15801561050c573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604090815281101561055357600080fd5b810190808051604051939291908464010000000082111561057357600080fd5b90830190602082018581111561058857600080fd5b82518660208202830111640100000000821117156105a557600080fd5b82525081516020918201928201910280838360005b838110156105d25781810151838201526020016105ba565b50505050905001604052602001805160405193929190846401000000008211156105fb57600080fd5b90830190602082018581111561061057600080fd5b825186602082028301116401000000008211171561062d57600080fd5b82525081516020918201928201910280838360005b8381101561065a578181015183820152602001610642565b5050505090500160405250505050905060008160008151811061067957fe5b60200260200101518260018151811061068e57fe5b60200260200101510390508463ffffffff168160060b816106ab57fe5b05935060008160060b1280156106d557508463ffffffff168160060b816106ce57fe5b0760060b15155b156106e257600019909301925b50505092915050565b60008061070386868686670de0b6b3a764000061089e565b90506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561074057600080fd5b505afa158015610754573d6000803e3d6000fd5b505050506040513d602081101561076a57600080fd5b5051604080517f313ce56700000000000000000000000000000000000000000000000000000000815290519192506000916001600160a01b0388169163313ce567916004808301926020929190829003018186803b1580156107cb57600080fd5b505afa1580156107df573d6000803e3d6000fd5b505050506040513d60208110156107f557600080fd5b5051905060ff8281169082161415610812578293505050506101c4565b8060ff168260ff16111561083c576108328360ff83850316600a0a6108c1565b93505050506101c4565b61084e8360ff84840316600a0a610921565b98975050505050505050565b600080610866866101ed565b905060008163ffffffff168463ffffffff16116108835783610885565b815b9050610893878787846106eb565b979650505050505050565b6000806108ab8785610399565b9050610893816108ba85610988565b88886109ef565b6000826108d0575060006101ad565b828202828482816108dd57fe5b041461091a5760405162461bcd60e51b8152600401808060200182810382526021815260200180610f5e6021913960400191505060405180910390fd5b9392505050565b6000808211610977576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161098057fe5b049392505050565b806fffffffffffffffffffffffffffffffff811681146101e8576040805162461bcd60e51b815260206004820152600860248201527f6f766572666c6f77000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000806109fb86610b53565b90506fffffffffffffffffffffffffffffffff6001600160a01b03821611610aaf576001600160a01b0380821680029084811690861610610a7157610a6c7801000000000000000000000000000000000000000000000000876fffffffffffffffffffffffffffffffff1683610eae565b610aa7565b610aa781876fffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000610eae565b925050610b4a565b6000610ace6001600160a01b0383168068010000000000000000610eae565b9050836001600160a01b0316856001600160a01b031610610b1c57610b17700100000000000000000000000000000000876fffffffffffffffffffffffffffffffff1683610eae565b610893565b61089381876fffffffffffffffffffffffffffffffff16700100000000000000000000000000000000610eae565b50949350505050565b60008060008360020b12610b6a578260020b610b72565b8260020b6000035b9050620d89e8811115610bcc576040805162461bcd60e51b815260206004820152600160248201527f5400000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600060018216610bed57700100000000000000000000000000000000610bff565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610c33576ffff97272373d413259a46990580e213a0260801c5b6004821615610c52576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615610c71576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610c90576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610caf576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610cce576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610ced576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610d0d576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615610d2d576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615610d4d576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615610d6d576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610d8d576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610dad576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610dcd576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610ded576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610e0e576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615610e2e576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615610e4d576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615610e6a576b048a170391f7dc42444e8fa20260801c5b60008460020b1315610e85578060001981610e8157fe5b0490505b640100000000810615610e99576001610e9c565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080610ee45760008411610ed957600080fd5b50829004905061091a565b808411610ef057600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a0290910302918190038190046001018684119095039490940291909403929092049190911791909102915050939250505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122066b8796d6eaa9e442553dfea824352c26024cac255ba074d0ca1af24b0e0978d64736f6c63430007060033\",\n    \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80634a0a96eb14610051578063821b972a1461009a578063d6906e6d146100ef578063de5a6e2214610132575b600080fd5b6100836004803603604081101561006757600080fd5b5080356001600160a01b0316906020013563ffffffff16610171565b6040805160029290920b8252519081900360200190f35b6100dd600480360360808110156100b057600080fd5b5080356001600160a01b03908116916020810135821691604082013516906060013563ffffffff166101b3565b60408051918252519081900360200190f35b6100dd6004803603608081101561010557600080fd5b5080356001600160a01b03908116916020810135821691604082013516906060013563ffffffff166101cc565b6101586004803603602081101561014857600080fd5b50356001600160a01b03166101da565b6040805163ffffffff9092168252519081900360200190f35b60008061017d846101ed565b905060008163ffffffff168463ffffffff161161019a578361019c565b815b90506101a88582610399565b925050505b92915050565b60006101c1858585856106eb565b90505b949350505050565b60006101c18585858561085a565b60006101e5826101ed565b90505b919050565b600080829050600080826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561022f57600080fd5b505afa158015610243573d6000803e3d6000fd5b505050506040513d60e081101561025957600080fd5b5060408101516060909101519092509050600061ffff8083169060018501168161027f57fe5b069050600080856001600160a01b031663252c09d7846040518263ffffffff1660e01b8152600401808261ffff16815260200191505060806040518083038186803b1580156102cd57600080fd5b505afa1580156102e1573d6000803e3d6000fd5b505050506040513d60808110156102f757600080fd5b5080516060909101519092509050801561031a5750420394506101e89350505050565b856001600160a01b031663252c09d760006040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b15801561035f57600080fd5b505afa158015610373573d6000803e3d6000fd5b505050506040513d608081101561038957600080fd5b5051420398975050505050505050565b600063ffffffff82166103f3576040805162461bcd60e51b815260206004820152600260248201527f4250000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b604080516002808252606082018352600092602083019080368337019050509050828160008151811061042257fe5b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061044b57fe5b63ffffffff9092166020928302919091018201526040517f883bdbfd000000000000000000000000000000000000000000000000000000008152600481018281528351602483015283516000936001600160a01b0389169363883bdbfd938793909283926044019185820191028083838b5b838110156104d55781810151838201526020016104bd565b505050509050019250505060006040518083038186803b1580156104f857600080fd5b505afa15801561050c573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604090815281101561055357600080fd5b810190808051604051939291908464010000000082111561057357600080fd5b90830190602082018581111561058857600080fd5b82518660208202830111640100000000821117156105a557600080fd5b82525081516020918201928201910280838360005b838110156105d25781810151838201526020016105ba565b50505050905001604052602001805160405193929190846401000000008211156105fb57600080fd5b90830190602082018581111561061057600080fd5b825186602082028301116401000000008211171561062d57600080fd5b82525081516020918201928201910280838360005b8381101561065a578181015183820152602001610642565b5050505090500160405250505050905060008160008151811061067957fe5b60200260200101518260018151811061068e57fe5b60200260200101510390508463ffffffff168160060b816106ab57fe5b05935060008160060b1280156106d557508463ffffffff168160060b816106ce57fe5b0760060b15155b156106e257600019909301925b50505092915050565b60008061070386868686670de0b6b3a764000061089e565b90506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561074057600080fd5b505afa158015610754573d6000803e3d6000fd5b505050506040513d602081101561076a57600080fd5b5051604080517f313ce56700000000000000000000000000000000000000000000000000000000815290519192506000916001600160a01b0388169163313ce567916004808301926020929190829003018186803b1580156107cb57600080fd5b505afa1580156107df573d6000803e3d6000fd5b505050506040513d60208110156107f557600080fd5b5051905060ff8281169082161415610812578293505050506101c4565b8060ff168260ff16111561083c576108328360ff83850316600a0a6108c1565b93505050506101c4565b61084e8360ff84840316600a0a610921565b98975050505050505050565b600080610866866101ed565b905060008163ffffffff168463ffffffff16116108835783610885565b815b9050610893878787846106eb565b979650505050505050565b6000806108ab8785610399565b9050610893816108ba85610988565b88886109ef565b6000826108d0575060006101ad565b828202828482816108dd57fe5b041461091a5760405162461bcd60e51b8152600401808060200182810382526021815260200180610f5e6021913960400191505060405180910390fd5b9392505050565b6000808211610977576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161098057fe5b049392505050565b806fffffffffffffffffffffffffffffffff811681146101e8576040805162461bcd60e51b815260206004820152600860248201527f6f766572666c6f77000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000806109fb86610b53565b90506fffffffffffffffffffffffffffffffff6001600160a01b03821611610aaf576001600160a01b0380821680029084811690861610610a7157610a6c7801000000000000000000000000000000000000000000000000876fffffffffffffffffffffffffffffffff1683610eae565b610aa7565b610aa781876fffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000610eae565b925050610b4a565b6000610ace6001600160a01b0383168068010000000000000000610eae565b9050836001600160a01b0316856001600160a01b031610610b1c57610b17700100000000000000000000000000000000876fffffffffffffffffffffffffffffffff1683610eae565b610893565b61089381876fffffffffffffffffffffffffffffffff16700100000000000000000000000000000000610eae565b50949350505050565b60008060008360020b12610b6a578260020b610b72565b8260020b6000035b9050620d89e8811115610bcc576040805162461bcd60e51b815260206004820152600160248201527f5400000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600060018216610bed57700100000000000000000000000000000000610bff565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610c33576ffff97272373d413259a46990580e213a0260801c5b6004821615610c52576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615610c71576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610c90576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610caf576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610cce576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610ced576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610d0d576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615610d2d576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615610d4d576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615610d6d576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610d8d576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610dad576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610dcd576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610ded576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610e0e576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615610e2e576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615610e4d576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615610e6a576b048a170391f7dc42444e8fa20260801c5b60008460020b1315610e85578060001981610e8157fe5b0490505b640100000000810615610e99576001610e9c565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080610ee45760008411610ed957600080fd5b50829004905061091a565b808411610ef057600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a0290910302918190038190046001018684119095039490940291909403929092049190911791909102915050939250505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122066b8796d6eaa9e442553dfea824352c26024cac255ba074d0ca1af24b0e0978d64736f6c63430007060033\",\n    \"devdoc\": {\n        \"kind\": \"dev\",\n        \"methods\": {\n            \"getMaxPeriod(address)\": {\n                \"params\": {\n                    \"_pool\": \"uniswap pool address\"\n                },\n                \"returns\": {\n                    \"_0\": \"max period can be used to request twap\"\n                }\n            },\n            \"getTimeWeightedAverageTickSafe(address,uint32)\": {\n                \"details\": \"this function will not revert\",\n                \"params\": {\n                    \"_period\": \"period in second that we want to calculate average on\",\n                    \"_pool\": \"address of the pool\"\n                },\n                \"returns\": {\n                    \"timeWeightedAverageTick\": \"the time weighted average tick\"\n                }\n            },\n            \"getTwap(address,address,address,uint32)\": {\n                \"details\": \"if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\",\n                \"params\": {\n                    \"_base\": \"base currency. to get eth/dai price, eth is base token\",\n                    \"_period\": \"number of seconds in the past to start calculating time-weighted average\",\n                    \"_pool\": \"uniswap pool address\",\n                    \"_quote\": \"quote currency. to get eth/dai price, dai is the quote currency\"\n                },\n                \"returns\": {\n                    \"_0\": \"price of 1 base currency in quote currency. scaled by 1e18\"\n                }\n            },\n            \"getTwapSafe(address,address,address,uint32)\": {\n                \"params\": {\n                    \"_base\": \"base currency. to get eth/dai price, eth is base token\",\n                    \"_period\": \"number of seconds in the past to start calculating time-weighted average\",\n                    \"_pool\": \"uniswap pool address\",\n                    \"_quote\": \"quote currency. to get eth/dai price, dai is the quote currency\"\n                },\n                \"returns\": {\n                    \"_0\": \"price of 1 base currency in quote currency. scaled by 1e18\"\n                }\n            }\n        },\n        \"version\": 1\n    },\n    \"userdoc\": {\n        \"kind\": \"user\",\n        \"methods\": {\n            \"getMaxPeriod(address)\": {\n                \"notice\": \"get the max period that can be used to request twap.\"\n            },\n            \"getTimeWeightedAverageTickSafe(address,uint32)\": {\n                \"notice\": \"get time weighed average tick, not converted to price\"\n            },\n            \"getTwap(address,address,address,uint32)\": {\n                \"notice\": \"get twap converted with base & quote token decimals\"\n            },\n            \"getTwapSafe(address,address,address,uint32)\": {\n                \"notice\": \"get twap converted with base & quote token decimals, never reverts\"\n            }\n        },\n        \"version\": 1\n    },\n    \"storageLayout\": {\n        \"storage\": [],\n        \"types\": null\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/Quoter.json",
    "content": "{\n    \"address\": \"0x8f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D\",\n    \"abi\": [\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_factory\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_WETH9\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"constructor\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"WETH9\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"factory\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"bytes\",\n                    \"name\": \"path\",\n                    \"type\": \"bytes\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amountIn\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"quoteExactInput\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amountOut\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint160[]\",\n                    \"name\": \"sqrtPriceX96AfterList\",\n                    \"type\": \"uint160[]\"\n                },\n                {\n                    \"internalType\": \"uint32[]\",\n                    \"name\": \"initializedTicksCrossedList\",\n                    \"type\": \"uint32[]\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"gasEstimate\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"components\": [\n                        {\n                            \"internalType\": \"address\",\n                            \"name\": \"tokenIn\",\n                            \"type\": \"address\"\n                        },\n                        {\n                            \"internalType\": \"address\",\n                            \"name\": \"tokenOut\",\n                            \"type\": \"address\"\n                        },\n                        {\n                            \"internalType\": \"uint256\",\n                            \"name\": \"amountIn\",\n                            \"type\": \"uint256\"\n                        },\n                        {\n                            \"internalType\": \"uint24\",\n                            \"name\": \"fee\",\n                            \"type\": \"uint24\"\n                        },\n                        {\n                            \"internalType\": \"uint160\",\n                            \"name\": \"sqrtPriceLimitX96\",\n                            \"type\": \"uint160\"\n                        }\n                    ],\n                    \"internalType\": \"struct IQuoterV2.QuoteExactInputSingleParams\",\n                    \"name\": \"params\",\n                    \"type\": \"tuple\"\n                }\n            ],\n            \"name\": \"quoteExactInputSingle\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amountOut\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint160\",\n                    \"name\": \"sqrtPriceX96After\",\n                    \"type\": \"uint160\"\n                },\n                {\n                    \"internalType\": \"uint32\",\n                    \"name\": \"initializedTicksCrossed\",\n                    \"type\": \"uint32\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"gasEstimate\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"bytes\",\n                    \"name\": \"path\",\n                    \"type\": \"bytes\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amountOut\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"quoteExactOutput\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amountIn\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint160[]\",\n                    \"name\": \"sqrtPriceX96AfterList\",\n                    \"type\": \"uint160[]\"\n                },\n                {\n                    \"internalType\": \"uint32[]\",\n                    \"name\": \"initializedTicksCrossedList\",\n                    \"type\": \"uint32[]\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"gasEstimate\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"components\": [\n                        {\n                            \"internalType\": \"address\",\n                            \"name\": \"tokenIn\",\n                            \"type\": \"address\"\n                        },\n                        {\n                            \"internalType\": \"address\",\n                            \"name\": \"tokenOut\",\n                            \"type\": \"address\"\n                        },\n                        {\n                            \"internalType\": \"uint256\",\n                            \"name\": \"amount\",\n                            \"type\": \"uint256\"\n                        },\n                        {\n                            \"internalType\": \"uint24\",\n                            \"name\": \"fee\",\n                            \"type\": \"uint24\"\n                        },\n                        {\n                            \"internalType\": \"uint160\",\n                            \"name\": \"sqrtPriceLimitX96\",\n                            \"type\": \"uint160\"\n                        }\n                    ],\n                    \"internalType\": \"struct IQuoterV2.QuoteExactOutputSingleParams\",\n                    \"name\": \"params\",\n                    \"type\": \"tuple\"\n                }\n            ],\n            \"name\": \"quoteExactOutputSingle\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amountIn\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint160\",\n                    \"name\": \"sqrtPriceX96After\",\n                    \"type\": \"uint160\"\n                },\n                {\n                    \"internalType\": \"uint32\",\n                    \"name\": \"initializedTicksCrossed\",\n                    \"type\": \"uint32\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"gasEstimate\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"int256\",\n                    \"name\": \"amount0Delta\",\n                    \"type\": \"int256\"\n                },\n                {\n                    \"internalType\": \"int256\",\n                    \"name\": \"amount1Delta\",\n                    \"type\": \"int256\"\n                },\n                {\n                    \"internalType\": \"bytes\",\n                    \"name\": \"path\",\n                    \"type\": \"bytes\"\n                }\n            ],\n            \"name\": \"uniswapV3SwapCallback\",\n            \"outputs\": [],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        }\n    ],\n    \"transactionHash\": \"0xff3e2e15dfbab75e217e21b643f8879211984934080c7e541f4c5e652da61eb8\",\n    \"receipt\": {\n        \"to\": null,\n        \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n        \"contractAddress\": \"0x8f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D\",\n        \"transactionIndex\": 0,\n        \"gasUsed\": \"67285581\",\n        \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n        \"blockHash\": \"0x24eb0e17b9198cdc24a6b84510a4017df307969ce8f2765f0b1da3a0a3a83622\",\n        \"transactionHash\": \"0xff3e2e15dfbab75e217e21b643f8879211984934080c7e541f4c5e652da61eb8\",\n        \"logs\": [],\n        \"blockNumber\": 3910585,\n        \"cumulativeGasUsed\": \"52128121\",\n        \"status\": 1,\n        \"byzantium\": true\n    },\n    \"args\": [\"0x1F98431c8aD98523631AE4a59f267346ea31F984\", \"0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681\"],\n    \"bytecode\": \"0x60c06040523480156200001157600080fd5b506040516200212c3803806200212c833981016040819052620000349162000070565b6001600160601b0319606092831b8116608052911b1660a052620000a7565b80516001600160a01b03811681146200006b57600080fd5b919050565b6000806040838503121562000083578182fd5b6200008e8362000053565b91506200009e6020840162000053565b90509250929050565b60805160601c60a05160601c612051620000db60003980610321525080610577528061095d5280610b9252506120516000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063c45a01551161005b578063c45a0155146100e6578063c6a5026a146100ee578063cdca175314610101578063fa461e33146101145761007d565b80632f80bb1d146100825780634aa4a4fc146100ae578063bd21704a146100c3575b600080fd5b610095610090366004611b2b565b610129565b6040516100a59493929190611eac565b60405180910390f35b6100b661031f565b6040516100a59190611def565b6100d66100d1366004611c49565b610343565b6040516100a59493929190611f54565b6100b6610575565b6100d66100fc366004611c49565b610599565b61009561010f366004611b2b565b610754565b610127610122366004611b91565b61092c565b005b6000606080600061013986610ae8565b67ffffffffffffffff8111801561014f57600080fd5b50604051908082528060200260200182016040528015610179578160200160208202803683370190505b50925061018586610ae8565b67ffffffffffffffff8111801561019b57600080fd5b506040519080825280602002602001820160405280156101c5578160200160208202803683370190505b50915060005b60008060006101d98a610b17565b92509250925060008060008061025c6040518060a001604052808873ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018f81526020018762ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250610343565b9350935093509350828b898151811061027157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818a89815181106102b857fe5b63ffffffff90921660209283029190910190910152929b50968201966001909601958b926102e58e610b48565b156102fa576102f38e610b50565b9d5061030a565b8c9b505050505050505050610316565b505050505050506101cb565b92959194509250565b7f000000000000000000000000000000000000000000000000000000000000000081565b60208101518151606083015160009283928392839273ffffffffffffffffffffffffffffffffffffffff808216908416109284926103819290610b8b565b9050866080015173ffffffffffffffffffffffffffffffffffffffff16600014156103af5760408701516000555b60005a90508173ffffffffffffffffffffffffffffffffffffffff1663128acb0830856103df8c60400151610bc9565b6000038c6080015173ffffffffffffffffffffffffffffffffffffffff1660001461040e578c60800151610434565b8761042d5773fffd8963efd1fc6a506488495d951d5263988d25610434565b6401000276a45b8d602001518e606001518f6000015160405160200161045593929190611d89565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610484959493929190611e10565b6040805180830381600087803b15801561049d57600080fd5b505af19250505080156104eb575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526104e891810190611b6e565b60015b610568573d808015610519576040519150601f19603f3d011682016040523d82523d6000602084013e61051e565b606091505b505a82039450886080015173ffffffffffffffffffffffffffffffffffffffff166000141561054c57600080555b610557818487610bfb565b97509750975097505050505061056e565b50505050505b9193509193565b7f000000000000000000000000000000000000000000000000000000000000000081565b60208101518151606083015160009283928392839273ffffffffffffffffffffffffffffffffffffffff808216908416109284926105d79290610b8b565b905060005a90508173ffffffffffffffffffffffffffffffffffffffff1663128acb0830856106098c60400151610bc9565b60808d015173ffffffffffffffffffffffffffffffffffffffff1615610633578c60800151610659565b876106525773fffd8963efd1fc6a506488495d951d5263988d25610659565b6401000276a45b8d600001518e606001518f6020015160405160200161067a93929190611d89565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016106a9959493929190611e10565b6040805180830381600087803b1580156106c257600080fd5b505af1925050508015610710575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261070d91810190611b6e565b60015b610568573d80801561073e576040519150601f19603f3d011682016040523d82523d6000602084013e610743565b606091505b505a82039450610557818487610bfb565b6000606080600061076486610ae8565b67ffffffffffffffff8111801561077a57600080fd5b506040519080825280602002602001820160405280156107a4578160200160208202803683370190505b5092506107b086610ae8565b67ffffffffffffffff811180156107c657600080fd5b506040519080825280602002602001820160405280156107f0578160200160208202803683370190505b50915060005b60008060006108048a610b17565b9250925092506000806000806108876040518060a001604052808973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018f81526020018762ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250610599565b9350935093509350828b898151811061089c57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818a89815181106108e357fe5b63ffffffff90921660209283029190910190910152929b50968201966001909601958b926109108e610b48565b156102fa5761091e8e610b50565b9d50505050505050506107f6565b600083138061093b5750600082135b61094457600080fd5b600080600061095284610b17565b9250925092506109847f0000000000000000000000000000000000000000000000000000000000000000848484610ccf565b5060008060008089136109ca578573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1610888a6000036109ff565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161089896000035b9250925092506000610a12878787610b8b565b90506000808273ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610a5d57600080fd5b505afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190611c6b565b5050505050915091508515610abb57604051848152826020820152816040820152606081fd5b60005415610ad1576000548414610ad157600080fd5b604051858152826020820152816040820152606081fd5b805160177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec909101045b919050565b60008080610b258482610cee565b9250610b32846014610dee565b9050610b3f846017610cee565b91509193909250565b516042111590565b8051606090610b859083906017907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901610ede565b92915050565b6000610bc17f0000000000000000000000000000000000000000000000000000000000000000610bbc8686866110c5565b611142565b949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210610bf757600080fd5b5090565b6000806000806000808773ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610c4a57600080fd5b505afa158015610c5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c829190611c6b565b50939650610c9794508d935061127892505050565b91975095509050610cbf73ffffffffffffffffffffffffffffffffffffffff89168383611339565b9350869250505093509350935093565b6000610ce585610ce08686866110c5565b611991565b95945050505050565b600081826014011015610d6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b8160140183511015610dd557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015610e6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b8160030183511015610ed557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b60608182601f011015610f5257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b828284011015610fc357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b8183018451101561103557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015290519081900360640190fd5b60608215801561105457604051915060008252602082016040526110bc565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561108d578051835260209283019201611075565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6110cd6119fa565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161115611105579192915b506040805160608101825273ffffffffffffffffffffffffffffffffffffffff948516815292909316602083015262ffffff169181019190915290565b6000816020015173ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff161061118457600080fd5b508051602080830151604093840151845173ffffffffffffffffffffffffffffffffffffffff94851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b60008060008351606014611318576044845110156112cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c290611e75565b60405180910390fd5b600484019350838060200190518101906112e59190611bdf565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c29190611e62565b8380602001905181019061132c9190611d02565b9250925092509193909250565b60008060008060008060008060088b73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561138d57600080fd5b505afa1580156113a1573d6000803e3d6000fd5b505050506040513d60208110156113b757600080fd5b5051600290810b908c900b816113c957fe5b0560020b901d905060006101008c73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561141c57600080fd5b505afa158015611430573d6000803e3d6000fd5b505050506040513d602081101561144657600080fd5b5051600290810b908d900b8161145857fe5b0560020b8161146357fe5b079050600060088d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114b057600080fd5b505afa1580156114c4573d6000803e3d6000fd5b505050506040513d60208110156114da57600080fd5b5051600290810b908d900b816114ec57fe5b0560020b901d905060006101008e73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561153f57600080fd5b505afa158015611553573d6000803e3d6000fd5b505050506040513d602081101561156957600080fd5b5051600290810b908e900b8161157b57fe5b0560020b8161158657fe5b07905060008160ff166001901b8f73ffffffffffffffffffffffffffffffffffffffff16635339c296856040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b5051161180156116a457508d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561166257600080fd5b505afa158015611676573d6000803e3d6000fd5b505050506040513d602081101561168c57600080fd5b5051600290810b908d900b8161169e57fe5b0760020b155b80156116b557508b60020b8d60020b135b945060008360ff166001901b8f73ffffffffffffffffffffffffffffffffffffffff16635339c296876040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b15801561171557600080fd5b505afa158015611729573d6000803e3d6000fd5b505050506040513d602081101561173f57600080fd5b5051161180156117d257508d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561179057600080fd5b505afa1580156117a4573d6000803e3d6000fd5b505050506040513d60208110156117ba57600080fd5b5051600290810b908e900b816117cc57fe5b0760020b155b80156117e357508b60020b8d60020b125b95508160010b8460010b128061180f57508160010b8460010b14801561180f57508060ff168360ff1611155b1561182557839950829750819850809650611832565b8199508097508398508296505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff87161b9150505b8560010b8760010b13611969578560010b8760010b14156118a3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff858103161c165b6000818c73ffffffffffffffffffffffffffffffffffffffff16635339c2968a6040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b1580156118fa57600080fd5b505afa15801561190e573d6000803e3d6000fd5b505050506040513d602081101561192457600080fd5b5051169050611932816119c1565b61ffff16989098019750506001909501947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61185e565b8115611976576001880397505b8215611983576001880397505b505050505050509392505050565b600061199d8383611142565b90503373ffffffffffffffffffffffffffffffffffffffff821614610b8557600080fd5b6000805b8215610b85577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301909216916001016119c5565b604080516060810182526000808252602082018190529181019190915290565b600082601f830112611a2a578081fd5b8135611a3d611a3882611faf565b611f8b565b818152846020838601011115611a51578283fd5b816020850160208301379081016020019190915292915050565b8051600281900b8114610b1257600080fd5b600060a08284031215611a8e578081fd5b60405160a0810181811067ffffffffffffffff82111715611aab57fe5b6040529050808235611abc8161201f565b81526020830135611acc8161201f565b602082015260408381013590820152606083013562ffffff81168114611af157600080fd5b6060820152611b0260808401611b0e565b60808201525092915050565b8035610b128161201f565b805161ffff81168114610b1257600080fd5b60008060408385031215611b3d578182fd5b823567ffffffffffffffff811115611b53578283fd5b611b5f85828601611a1a565b95602094909401359450505050565b60008060408385031215611b80578182fd5b505080516020909101519092909150565b600080600060608486031215611ba5578081fd5b8335925060208401359150604084013567ffffffffffffffff811115611bc9578182fd5b611bd586828701611a1a565b9150509250925092565b600060208284031215611bf0578081fd5b815167ffffffffffffffff811115611c06578182fd5b8201601f81018413611c16578182fd5b8051611c24611a3882611faf565b818152856020838501011115611c38578384fd5b610ce5826020830160208601611fef565b600060a08284031215611c5a578081fd5b611c648383611a7d565b9392505050565b600080600080600080600060e0888a031215611c85578283fd5b8751611c908161201f565b9650611c9e60208901611a6b565b9550611cac60408901611b19565b9450611cba60608901611b19565b9350611cc860808901611b19565b925060a088015160ff81168114611cdd578283fd5b60c08901519092508015158114611cf2578182fd5b8091505092959891949750929550565b600080600060608486031215611d16578081fd5b835192506020840151611d288161201f565b9150611d3660408501611a6b565b90509250925092565b60008151808452611d57816020860160208601611fef565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a06080830152611e5760a0830184611d3f565b979650505050505050565b600060208252611c646020830184611d3f565b60208082526010908201527f556e6578706563746564206572726f7200000000000000000000000000000000604082015260600190565b600060808201868352602060808185015281875180845260a0860191508289019350845b81811015611f0257845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101611ed0565b505084810360408601528651808252908201925081870190845b81811015611f3e57825163ffffffff1685529383019391830191600101611f1c565b5050505060609290920192909252949350505050565b93845273ffffffffffffffffffffffffffffffffffffffff92909216602084015263ffffffff166040830152606082015260800190565b60405181810167ffffffffffffffff81118282101715611fa757fe5b604052919050565b600067ffffffffffffffff821115611fc357fe5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b8381101561200a578181015183820152602001611ff2565b83811115612019576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461204157600080fd5b5056fea164736f6c6343000706000a\"\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/ShortHelper.json",
    "content": "{\n    \"address\": \"0x5A30a1E3873A2B5Fc9DB9b2b52491C4b6086FAe0\",\n    \"abi\": [\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_controllerAddr\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_swapRouter\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_wethAddr\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"constructor\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_wPowerPerpAmount\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint128\",\n                    \"name\": \"_withdrawAmount\",\n                    \"type\": \"uint128\"\n                },\n                {\n                    \"components\": [\n                        {\n                            \"internalType\": \"address\",\n                            \"name\": \"tokenIn\",\n                            \"type\": \"address\"\n                        },\n                        {\n                            \"internalType\": \"address\",\n                            \"name\": \"tokenOut\",\n                            \"type\": \"address\"\n                        },\n                        {\n                            \"internalType\": \"uint24\",\n                            \"name\": \"fee\",\n                            \"type\": \"uint24\"\n                        },\n                        {\n                            \"internalType\": \"address\",\n                            \"name\": \"recipient\",\n                            \"type\": \"address\"\n                        },\n                        {\n                            \"internalType\": \"uint256\",\n                            \"name\": \"deadline\",\n                            \"type\": \"uint256\"\n                        },\n                        {\n                            \"internalType\": \"uint256\",\n                            \"name\": \"amountOut\",\n                            \"type\": \"uint256\"\n                        },\n                        {\n                            \"internalType\": \"uint256\",\n                            \"name\": \"amountInMaximum\",\n                            \"type\": \"uint256\"\n                        },\n                        {\n                            \"internalType\": \"uint160\",\n                            \"name\": \"sqrtPriceLimitX96\",\n                            \"type\": \"uint160\"\n                        }\n                    ],\n                    \"internalType\": \"struct ISwapRouter.ExactOutputSingleParams\",\n                    \"name\": \"_exactOutputParams\",\n                    \"type\": \"tuple\"\n                }\n            ],\n            \"name\": \"closeShort\",\n            \"outputs\": [],\n            \"stateMutability\": \"payable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"controller\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"contract IController\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_vaultId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"uint128\",\n                    \"name\": \"_powerPerpAmount\",\n                    \"type\": \"uint128\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_uniNftId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"components\": [\n                        {\n                            \"internalType\": \"address\",\n                            \"name\": \"tokenIn\",\n                            \"type\": \"address\"\n                        },\n                        {\n                            \"internalType\": \"address\",\n                            \"name\": \"tokenOut\",\n                            \"type\": \"address\"\n                        },\n                        {\n                            \"internalType\": \"uint24\",\n                            \"name\": \"fee\",\n                            \"type\": \"uint24\"\n                        },\n                        {\n                            \"internalType\": \"address\",\n                            \"name\": \"recipient\",\n                            \"type\": \"address\"\n                        },\n                        {\n                            \"internalType\": \"uint256\",\n                            \"name\": \"deadline\",\n                            \"type\": \"uint256\"\n                        },\n                        {\n                            \"internalType\": \"uint256\",\n                            \"name\": \"amountIn\",\n                            \"type\": \"uint256\"\n                        },\n                        {\n                            \"internalType\": \"uint256\",\n                            \"name\": \"amountOutMinimum\",\n                            \"type\": \"uint256\"\n                        },\n                        {\n                            \"internalType\": \"uint160\",\n                            \"name\": \"sqrtPriceLimitX96\",\n                            \"type\": \"uint160\"\n                        }\n                    ],\n                    \"internalType\": \"struct ISwapRouter.ExactInputSingleParams\",\n                    \"name\": \"_exactInputParams\",\n                    \"type\": \"tuple\"\n                }\n            ],\n            \"name\": \"openShort\",\n            \"outputs\": [],\n            \"stateMutability\": \"payable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"router\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"contract ISwapRouter\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"vaultNFT\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"contract IVaultManagerNFT\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"weth\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"contract IWETH9\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"stateMutability\": \"payable\",\n            \"type\": \"receive\"\n        }\n    ],\n    \"transactionHash\": \"0x52cfda76b30215eb5d29879b788b1b8d686fdd594ad2d505c25577ccda72e278\",\n    \"receipt\": {\n        \"to\": null,\n        \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n        \"contractAddress\": \"0x5A30a1E3873A2B5Fc9DB9b2b52491C4b6086FAe0\",\n        \"transactionIndex\": 0,\n        \"gasUsed\": \"27532561\",\n        \"logsBloom\": \"0x00000002000000000000000000000080000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000010000000000000000002000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000020000000000000001004000800000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000020000000000000000000000000000\",\n        \"blockHash\": \"0xe02e2a2e57ca28a92dc08c81b6350a884bed800b31b02fb8a8a3165e37bed2d1\",\n        \"transactionHash\": \"0x52cfda76b30215eb5d29879b788b1b8d686fdd594ad2d505c25577ccda72e278\",\n        \"logs\": [\n            {\n                \"transactionIndex\": 0,\n                \"blockNumber\": 5750498,\n                \"transactionHash\": \"0x52cfda76b30215eb5d29879b788b1b8d686fdd594ad2d505c25577ccda72e278\",\n                \"address\": \"0xEC0db8766bc003C14861af996e411beA6Bf800aB\",\n                \"topics\": [\n                    \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n                    \"0x0000000000000000000000005a30a1e3873a2b5fc9db9b2b52491c4b6086fae0\",\n                    \"0x000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564\"\n                ],\n                \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n                \"logIndex\": 0,\n                \"blockHash\": \"0xe02e2a2e57ca28a92dc08c81b6350a884bed800b31b02fb8a8a3165e37bed2d1\"\n            },\n            {\n                \"transactionIndex\": 0,\n                \"blockNumber\": 5750498,\n                \"transactionHash\": \"0x52cfda76b30215eb5d29879b788b1b8d686fdd594ad2d505c25577ccda72e278\",\n                \"address\": \"0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681\",\n                \"topics\": [\n                    \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n                    \"0x0000000000000000000000005a30a1e3873a2b5fc9db9b2b52491c4b6086fae0\",\n                    \"0x000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564\"\n                ],\n                \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n                \"logIndex\": 1,\n                \"blockHash\": \"0xe02e2a2e57ca28a92dc08c81b6350a884bed800b31b02fb8a8a3165e37bed2d1\"\n            }\n        ],\n        \"blockNumber\": 5750498,\n        \"cumulativeGasUsed\": \"20324361\",\n        \"status\": 1,\n        \"byzantium\": true\n    },\n    \"args\": [\n        \"0x6FBbc7eBd7E421839915e8e4fAcC9947dC32F4dE\",\n        \"0xE592427A0AEce92De3Edee1F18E0157C05861564\",\n        \"0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681\"\n    ],\n    \"solcInputHash\": \"49c79f88c6e4ede6ca1f2ffd46fef4fe\",\n    \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controllerAddr\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_swapRouter\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wethAddr\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"deadline\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountOut\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountInMaximum\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceLimitX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"internalType\\\":\\\"struct ISwapRouter.ExactOutputSingleParams\\\",\\\"name\\\":\\\"_exactOutputParams\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"closeShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IController\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniNftId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"deadline\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountIn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountOutMinimum\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceLimitX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"internalType\\\":\\\"struct ISwapRouter.ExactInputSingleParams\\\",\\\"name\\\":\\\"_exactInputParams\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"openShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"router\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract ISwapRouter\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"vaultNFT\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IVaultManagerNFT\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IWETH9\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"closeShort(uint256,uint256,uint128,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"notice\\\":\\\"buy back some squeeth and close the position.\\\"},\\\"openShort(uint256,uint128,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"notice\\\":\\\"mint power perp, trade with uniswap and send back premium in eth.\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/periphery/ShortHelper.sol\\\":\\\"ShortHelper\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":2000},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\\\n\\\\n/// @title Router token swapping functionality\\\\n/// @notice Functions for swapping tokens via Uniswap V3\\\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\\\n    struct ExactInputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactInputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactOutputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\\\n\\\\n    struct ExactOutputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9bfaf1feb32814623e627ab70f2409760b15d95f1f9b058e2b3399a8bb732975\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IController {\\\\n    function vaultNFT() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint128 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint128 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnOnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x29a0f5cfe4dfe0db93f7f7c6b77849cbf744272d12359b68ea83e7c0b0b3c586\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IVaultManagerNFT.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IVaultManagerNFT is IERC721 {\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x81f45bd99b1b8b1d67f5684145c8b3723ae8e50d950408a1e7079dd89b899057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8a9a4512f1fc29b14dcf97ca149f263f28de43191a3ee31336f2389e3f2f5f8e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/periphery/ShortHelper.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n// Interfaces\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {ISwapRouter} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IVaultManagerNFT} from \\\\\\\"../interfaces/IVaultManagerNFT.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\n// Libraries\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\ncontract ShortHelper {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    IController public immutable controller;\\\\n    ISwapRouter public immutable router;\\\\n    IWETH9 public immutable weth;\\\\n    IVaultManagerNFT public immutable vaultNFT;\\\\n\\\\n    constructor(\\\\n        address _controllerAddr,\\\\n        address _swapRouter,\\\\n        address _wethAddr\\\\n    ) {\\\\n        IController _controller = IController(_controllerAddr);\\\\n        router = ISwapRouter(_swapRouter);\\\\n\\\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\\\n        IWETH9 _weth = IWETH9(_wethAddr);\\\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\\\n        _weth.approve(_swapRouter, type(uint256).max);\\\\n\\\\n        // assign immutable variables\\\\n        vaultNFT = IVaultManagerNFT(_controller.vaultNFT());\\\\n        weth = _weth;\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    /**\\\\n     * mint power perp, trade with uniswap and send back premium in eth.\\\\n     */\\\\n    function openShort(\\\\n        uint256 _vaultId,\\\\n        uint128 _powerPerpAmount,\\\\n        uint256 _uniNftId,\\\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\\\n    ) external payable {\\\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\\\n            _vaultId,\\\\n            _powerPerpAmount,\\\\n            _uniNftId\\\\n        );\\\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\\\n\\\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\\\n\\\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\\\n        if (_exactInputParams.recipient == address(this) && _exactInputParams.tokenOut == address(weth)) {\\\\n            weth.withdraw(amountOut);\\\\n            payable(msg.sender).sendValue(amountOut);\\\\n        }\\\\n\\\\n        // this is a newly open vault, transfer to the user.\\\\n        if (_vaultId == 0) vaultNFT.transferFrom(address(this), msg.sender, vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * buy back some squeeth and close the position.\\\\n     */\\\\n    function closeShort(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint128 _withdrawAmount,\\\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\\\n    ) external payable {\\\\n        // wrap eth to weth\\\\n        weth.deposit{value: msg.value}();\\\\n\\\\n        // pay weth and get squeeth in return.\\\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\\\n\\\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\\\n\\\\n        // send back unused eth and withdrawn collateral\\\\n        weth.withdraw(msg.value.sub(amountIn));\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev only receive eth from weth contract and controller.\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\\\\\"can't receive eth\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xece2f947d6062b5191a49d755e12fcf8024f383a1307ca48032bfb311bc8c38b\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n    \"bytecode\": \"0x6101006040523480156200001257600080fd5b506040516200100a3803806200100a8339810160408190526200003591620002cb565b6000839050826001600160a01b031660a0816001600160a01b031660601b815250506000816001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b1580156200009357600080fd5b505afa158015620000a8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ce9190620002a7565b60405163095ea7b360e01b815290915083906001600160a01b0383169063095ea7b390620001059088906000199060040162000336565b602060405180830381600087803b1580156200012057600080fd5b505af115801562000135573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200015b919062000314565b5060405163095ea7b360e01b81526001600160a01b0382169063095ea7b3906200018e9088906000199060040162000336565b602060405180830381600087803b158015620001a957600080fd5b505af1158015620001be573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001e4919062000314565b50826001600160a01b03166384dea1a16040518163ffffffff1660e01b815260040160206040518083038186803b1580156200021f57600080fd5b505afa15801562000234573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200025a9190620002a7565b6001600160601b0319606091821b811660e05291811b821660c0529290921b909116608052506200034f92505050565b80516001600160a01b0381168114620002a257600080fd5b919050565b600060208284031215620002b9578081fd5b620002c4826200028a565b9392505050565b600080600060608486031215620002e0578182fd5b620002eb846200028a565b9250620002fb602085016200028a565b91506200030b604085016200028a565b90509250925092565b60006020828403121562000326578081fd5b81518015158114620002c4578182fd5b6001600160a01b03929092168252602082015260400190565b60805160601c60a05160601c60c05160601c60e05160601c610c44620003c66000398061044a52806104c15250806079528061018b528061033452806103a152806104e552806106b75250806102915280610588528061077252508060ab52806101b25280610644528061074e5250610c446000f3fe6080604052600436106100695760003560e01c8063918e1cda11610043578063918e1cda1461014c578063f77c47911461015f578063f887ea4014610174576100f4565b80633fc8cef3146100f9578063583f7b0e1461012457806384dea1a114610137576100f4565b366100f457336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100cd5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6100f25760405162461bcd60e51b81526004016100e990610b35565b60405180910390fd5b005b600080fd5b34801561010557600080fd5b5061010e610189565b60405161011b9190610b21565b60405180910390f35b6100f26101323660046109f3565b6101ad565b34801561014357600080fd5b5061010e6104bf565b6100f261015a366004610a5d565b6104e3565b34801561016b57600080fd5b5061010e61074c565b34801561018057600080fd5b5061010e610770565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f3a50fe3348888886040518563ffffffff1660e01b815260040161020193929190610b84565b60408051808303818588803b15801561021957600080fd5b505af115801561022d573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906102529190610a3a565b60a085018190526040517f414bf38900000000000000000000000000000000000000000000000000000000815291935091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063414bf389906102c6908790600401610b6c565b602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031891906109db565b60608501519091506001600160a01b03163014801561036c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031684602001516001600160a01b0316145b15610415576040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906103d6908490600401610b7b565b600060405180830381600087803b1580156103f057600080fd5b505af1158015610404573d6000803e3d6000fd5b506104159250339150839050610794565b866104b6576040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd9061048390309033908890600401610afd565b600060405180830381600087803b15801561049d57600080fd5b505af11580156104b1573d6000803e3d6000fd5b505050505b50505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561053e57600080fd5b505af1158015610552573d6000803e3d6000fd5b50506040517fdb3e2198000000000000000000000000000000000000000000000000000000008152600093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063db3e219891506105bf908590600401610b6c565b602060405180830381600087803b1580156105d957600080fd5b505af11580156105ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061191906109db565b6040517f8632cb030000000000000000000000000000000000000000000000000000000081529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638632cb039061067d90889088908890600401610bac565b600060405180830381600087803b15801561069757600080fd5b505af11580156106ab573d6000803e3d6000fd5b50506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169150632e1a7d4d90506106ea348461087e565b6040518263ffffffff1660e01b81526004016107069190610b7b565b600060405180830381600087803b15801561072057600080fd5b505af1158015610734573d6000803e3d6000fd5b506107459250339150479050610794565b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b804710156107e9576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610834576040519150601f19603f3d011682016040523d82523d6000602084013e610839565b606091505b50509050806108795760405162461bcd60e51b815260040180806020018281038252603a815260200180610bd5603a913960400191505060405180910390fd5b505050565b6000828211156108d5576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b80356001600160a01b03811681146108f757600080fd5b919050565b600061010080838503121561090f578182fd5b6040519081019067ffffffffffffffff8211818310171561092c57fe5b8160405280925061093c846108e0565b815261094a602085016108e0565b602082015261095b604085016109c8565b604082015261096c606085016108e0565b60608201526080840135608082015260a084013560a082015260c084013560c082015261099b60e085016108e0565b60e0820152505092915050565b80356fffffffffffffffffffffffffffffffff811681146108f757600080fd5b803562ffffff811681146108f757600080fd5b6000602082840312156109ec578081fd5b5051919050565b6000806000806101608587031215610a09578283fd5b84359350610a19602086016109a8565b925060408501359150610a2f86606087016108fc565b905092959194509250565b60008060408385031215610a4c578182fd5b505080516020909101519092909150565b6000806000806101608587031215610a73578384fd5b8435935060208501359250610a8a604086016109a8565b9150610a2f86606087016108fc565b6001600160a01b0380825116835280602083015116602084015262ffffff60408301511660408401528060608301511660608401526080820151608084015260a082015160a084015260c082015160c08401528060e08301511660e0840152505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0391909116815260200190565b60208082526011908201527f63616e2774207265636569766520657468000000000000000000000000000000604082015260600190565b61010081016108da8284610a99565b90815260200190565b9283526fffffffffffffffffffffffffffffffff919091166020830152604082015260600190565b92835260208301919091526fffffffffffffffffffffffffffffffff1660408201526060019056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a264697066735822122056ae9c698b1a26c77f7eed5817e82bcae8cab32dcf585047dd6e0397740e3e2564736f6c63430007060033\",\n    \"deployedBytecode\": \"0x6080604052600436106100695760003560e01c8063918e1cda11610043578063918e1cda1461014c578063f77c47911461015f578063f887ea4014610174576100f4565b80633fc8cef3146100f9578063583f7b0e1461012457806384dea1a114610137576100f4565b366100f457336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100cd5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6100f25760405162461bcd60e51b81526004016100e990610b35565b60405180910390fd5b005b600080fd5b34801561010557600080fd5b5061010e610189565b60405161011b9190610b21565b60405180910390f35b6100f26101323660046109f3565b6101ad565b34801561014357600080fd5b5061010e6104bf565b6100f261015a366004610a5d565b6104e3565b34801561016b57600080fd5b5061010e61074c565b34801561018057600080fd5b5061010e610770565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f3a50fe3348888886040518563ffffffff1660e01b815260040161020193929190610b84565b60408051808303818588803b15801561021957600080fd5b505af115801561022d573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906102529190610a3a565b60a085018190526040517f414bf38900000000000000000000000000000000000000000000000000000000815291935091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063414bf389906102c6908790600401610b6c565b602060405180830381600087803b1580156102e057600080fd5b505af11580156102f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031891906109db565b60608501519091506001600160a01b03163014801561036c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031684602001516001600160a01b0316145b15610415576040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906103d6908490600401610b7b565b600060405180830381600087803b1580156103f057600080fd5b505af1158015610404573d6000803e3d6000fd5b506104159250339150839050610794565b866104b6576040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd9061048390309033908890600401610afd565b600060405180830381600087803b15801561049d57600080fd5b505af11580156104b1573d6000803e3d6000fd5b505050505b50505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561053e57600080fd5b505af1158015610552573d6000803e3d6000fd5b50506040517fdb3e2198000000000000000000000000000000000000000000000000000000008152600093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063db3e219891506105bf908590600401610b6c565b602060405180830381600087803b1580156105d957600080fd5b505af11580156105ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061191906109db565b6040517f8632cb030000000000000000000000000000000000000000000000000000000081529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638632cb039061067d90889088908890600401610bac565b600060405180830381600087803b15801561069757600080fd5b505af11580156106ab573d6000803e3d6000fd5b50506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169150632e1a7d4d90506106ea348461087e565b6040518263ffffffff1660e01b81526004016107069190610b7b565b600060405180830381600087803b15801561072057600080fd5b505af1158015610734573d6000803e3d6000fd5b506107459250339150479050610794565b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b804710156107e9576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610834576040519150601f19603f3d011682016040523d82523d6000602084013e610839565b606091505b50509050806108795760405162461bcd60e51b815260040180806020018281038252603a815260200180610bd5603a913960400191505060405180910390fd5b505050565b6000828211156108d5576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b80356001600160a01b03811681146108f757600080fd5b919050565b600061010080838503121561090f578182fd5b6040519081019067ffffffffffffffff8211818310171561092c57fe5b8160405280925061093c846108e0565b815261094a602085016108e0565b602082015261095b604085016109c8565b604082015261096c606085016108e0565b60608201526080840135608082015260a084013560a082015260c084013560c082015261099b60e085016108e0565b60e0820152505092915050565b80356fffffffffffffffffffffffffffffffff811681146108f757600080fd5b803562ffffff811681146108f757600080fd5b6000602082840312156109ec578081fd5b5051919050565b6000806000806101608587031215610a09578283fd5b84359350610a19602086016109a8565b925060408501359150610a2f86606087016108fc565b905092959194509250565b60008060408385031215610a4c578182fd5b505080516020909101519092909150565b6000806000806101608587031215610a73578384fd5b8435935060208501359250610a8a604086016109a8565b9150610a2f86606087016108fc565b6001600160a01b0380825116835280602083015116602084015262ffffff60408301511660408401528060608301511660608401526080820151608084015260a082015160a084015260c082015160c08401528060e08301511660e0840152505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0391909116815260200190565b60208082526011908201527f63616e2774207265636569766520657468000000000000000000000000000000604082015260600190565b61010081016108da8284610a99565b90815260200190565b9283526fffffffffffffffffffffffffffffffff919091166020830152604082015260600190565b92835260208301919091526fffffffffffffffffffffffffffffffff1660408201526060019056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a264697066735822122056ae9c698b1a26c77f7eed5817e82bcae8cab32dcf585047dd6e0397740e3e2564736f6c63430007060033\",\n    \"devdoc\": {\n        \"kind\": \"dev\",\n        \"methods\": {},\n        \"version\": 1\n    },\n    \"userdoc\": {\n        \"kind\": \"user\",\n        \"methods\": {\n            \"closeShort(uint256,uint256,uint128,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n                \"notice\": \"buy back some squeeth and close the position.\"\n            },\n            \"openShort(uint256,uint128,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n                \"notice\": \"mint power perp, trade with uniswap and send back premium in eth.\"\n            }\n        },\n        \"version\": 1\n    },\n    \"storageLayout\": {\n        \"storage\": [],\n        \"types\": null\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/VaultNFTManager.json",
    "content": "{\n    \"address\": \"0x40FA4273a739667D7dBf1C46755C27338eAa0728\",\n    \"abi\": [\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"owner\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"approved\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"Approval\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"owner\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"operator\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"bool\",\n                    \"name\": \"approved\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"name\": \"ApprovalForAll\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"from\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"to\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"Transfer\",\n            \"type\": \"event\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"to\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"approve\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"owner\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"balanceOf\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"baseURI\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"string\",\n                    \"name\": \"\",\n                    \"type\": \"string\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"controller\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"getApproved\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_controller\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"init\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"owner\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"operator\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"isApprovedForAll\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_recipient\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"mintNFT\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"name\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"string\",\n                    \"name\": \"\",\n                    \"type\": \"string\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"nextId\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"ownerOf\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"from\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"to\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"safeTransferFrom\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"from\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"to\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                },\n                {\n                    \"internalType\": \"bytes\",\n                    \"name\": \"_data\",\n                    \"type\": \"bytes\"\n                }\n            ],\n            \"name\": \"safeTransferFrom\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"operator\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"approved\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"name\": \"setApprovalForAll\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"bytes4\",\n                    \"name\": \"interfaceId\",\n                    \"type\": \"bytes4\"\n                }\n            ],\n            \"name\": \"supportsInterface\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"symbol\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"string\",\n                    \"name\": \"\",\n                    \"type\": \"string\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"index\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"tokenByIndex\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"owner\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"index\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"tokenOfOwnerByIndex\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"tokenURI\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"string\",\n                    \"name\": \"\",\n                    \"type\": \"string\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"totalSupply\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"from\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"to\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"tokenId\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"transferFrom\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        }\n    ],\n    \"transactionHash\": \"0x673c8730155a592c32e0c20d3072c55194a16b3b406f85baf276af32836a4ce2\",\n    \"receipt\": {\n        \"to\": null,\n        \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n        \"contractAddress\": \"0x40FA4273a739667D7dBf1C46755C27338eAa0728\",\n        \"transactionIndex\": 0,\n        \"gasUsed\": \"16689810\",\n        \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n        \"blockHash\": \"0x7906848d9644a7dc9b5d4c4c5af70ecc21e17c850a4026428f25fc7458061065\",\n        \"transactionHash\": \"0x673c8730155a592c32e0c20d3072c55194a16b3b406f85baf276af32836a4ce2\",\n        \"logs\": [],\n        \"blockNumber\": 5750466,\n        \"cumulativeGasUsed\": \"365330\",\n        \"status\": 1,\n        \"byzantium\": true\n    },\n    \"args\": [],\n    \"solcInputHash\": \"49c79f88c6e4ede6ca1f2ffd46fef4fe\",\n    \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"ApprovalForAll\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"baseURI\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"getApproved\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controller\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"init\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"isApprovedForAll\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_recipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"mintNFT\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"nextId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ownerOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"safeTransferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"safeTransferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"setApprovalForAll\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"interfaceId\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"name\\\":\\\"supportsInterface\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"index\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenByIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"index\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenOfOwnerByIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenURI\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-approve}.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC721-balanceOf}.\\\"},\\\"baseURI()\\\":{\\\"details\\\":\\\"Returns the base URI set via {_setBaseURI}. This will be automatically added as a prefix in {tokenURI} to each token's URI, or to the token ID if no specific URI is set for that token ID.\\\"},\\\"getApproved(uint256)\\\":{\\\"details\\\":\\\"See {IERC721-getApproved}.\\\"},\\\"isApprovedForAll(address,address)\\\":{\\\"details\\\":\\\"See {IERC721-isApprovedForAll}.\\\"},\\\"name()\\\":{\\\"details\\\":\\\"See {IERC721Metadata-name}.\\\"},\\\"ownerOf(uint256)\\\":{\\\"details\\\":\\\"See {IERC721-ownerOf}.\\\"},\\\"safeTransferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-safeTransferFrom}.\\\"},\\\"safeTransferFrom(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"See {IERC721-safeTransferFrom}.\\\"},\\\"setApprovalForAll(address,bool)\\\":{\\\"details\\\":\\\"See {IERC721-setApprovalForAll}.\\\"},\\\"supportsInterface(bytes4)\\\":{\\\"details\\\":\\\"See {IERC165-supportsInterface}. Time complexity O(1), guaranteed to always use less than 30 000 gas.\\\"},\\\"symbol()\\\":{\\\"details\\\":\\\"See {IERC721Metadata-symbol}.\\\"},\\\"tokenByIndex(uint256)\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-tokenByIndex}.\\\"},\\\"tokenOfOwnerByIndex(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-tokenOfOwnerByIndex}.\\\"},\\\"tokenURI(uint256)\\\":{\\\"details\\\":\\\"See {IERC721Metadata-tokenURI}.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-totalSupply}.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-transferFrom}.\\\"}},\\\"stateVariables\\\":{\\\"nextId\\\":{\\\"details\\\":\\\"tokenId for the next vault opened\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"mintNFT(address)\\\":{\\\"notice\\\":\\\"mint new NFT, create a new vault struct\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/VaultManagerNFT.sol\\\":\\\"VaultNFTManager\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":2000},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC165Upgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../proxy/Initializable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Implementation of the {IERC165} interface.\\\\n *\\\\n * Contracts may inherit from this and call {_registerInterface} to declare\\\\n * their support of an interface.\\\\n */\\\\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\\\\n    /*\\\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\\\n\\\\n    /**\\\\n     * @dev Mapping of interface ids to whether or not it's supported.\\\\n     */\\\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\\\n\\\\n    function __ERC165_init() internal initializer {\\\\n        __ERC165_init_unchained();\\\\n    }\\\\n\\\\n    function __ERC165_init_unchained() internal initializer {\\\\n        // Derived contracts need only register support for their own interfaces,\\\\n        // we register support for ERC165 itself here\\\\n        _registerInterface(_INTERFACE_ID_ERC165);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC165-supportsInterface}.\\\\n     *\\\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\\\n        return _supportedInterfaces[interfaceId];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Registers the contract as an implementer of the interface defined by\\\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\\\n     * registering its interface id is not required.\\\\n     *\\\\n     * See {IERC165-supportsInterface}.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\\\n     */\\\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\\\n        require(interfaceId != 0xffffffff, \\\\\\\"ERC165: invalid interface id\\\\\\\");\\\\n        _supportedInterfaces[interfaceId] = true;\\\\n    }\\\\n    uint256[49] private __gap;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x758fecbab95111d05e9c8a48c4895ff615076c9b18bbd9fabdb6480285ede542\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/introspection/IERC165Upgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165Upgradeable {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x84621447d7f733143a21973a18d47782dcb9739ac97bb1ee7f8de214b6dc917d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMathUpgradeable {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfffa644e2e08507310f561f04060db8f19d39e95cc2ad46926aa51043a86e73c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// solhint-disable-next-line compiler-version\\\\npragma solidity >=0.4.24 <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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\\\nabstract contract Initializable {\\\\n\\\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\\\n    function _isConstructor() private view returns (bool) {\\\\n        return !AddressUpgradeable.isContract(address(this));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd8e4eb08dcc1d1860fb347ba5ffd595242b9a1b66d49a47f2b4cb51c3f35017e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/ContextUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721Upgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721MetadataUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721EnumerableUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721ReceiverUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../introspection/ERC165Upgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMathUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/AddressUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/EnumerableSetUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/EnumerableMapUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/StringsUpgradeable.sol\\\\\\\";\\\\nimport \\\\\\\"../../proxy/Initializable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721EnumerableUpgradeable {\\\\n    using SafeMathUpgradeable for uint256;\\\\n    using AddressUpgradeable for address;\\\\n    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;\\\\n    using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;\\\\n    using StringsUpgradeable for uint256;\\\\n\\\\n    // Equals to `bytes4(keccak256(\\\\\\\"onERC721Received(address,address,uint256,bytes)\\\\\\\"))`\\\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\\\n\\\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\\\n    mapping (address => EnumerableSetUpgradeable.UintSet) private _holderTokens;\\\\n\\\\n    // Enumerable mapping from token ids to their owners\\\\n    EnumerableMapUpgradeable.UintToAddressMap private _tokenOwners;\\\\n\\\\n    // Mapping from token ID to approved address\\\\n    mapping (uint256 => address) private _tokenApprovals;\\\\n\\\\n    // Mapping from owner to operator approvals\\\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\\\n\\\\n    // Token name\\\\n    string private _name;\\\\n\\\\n    // Token symbol\\\\n    string private _symbol;\\\\n\\\\n    // Optional mapping for token URIs\\\\n    mapping (uint256 => string) private _tokenURIs;\\\\n\\\\n    // Base URI\\\\n    string private _baseURI;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\\\n     *\\\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\\\n     *\\\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\\\n     *\\\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\\\n\\\\n    /**\\\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\\\n     */\\\\n    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {\\\\n        __Context_init_unchained();\\\\n        __ERC165_init_unchained();\\\\n        __ERC721_init_unchained(name_, symbol_);\\\\n    }\\\\n\\\\n    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {\\\\n        _name = name_;\\\\n        _symbol = symbol_;\\\\n\\\\n        // register the supported interfaces to conform to ERC721 via ERC165\\\\n        _registerInterface(_INTERFACE_ID_ERC721);\\\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-balanceOf}.\\\\n     */\\\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\\\n        require(owner != address(0), \\\\\\\"ERC721: balance query for the zero address\\\\\\\");\\\\n        return _holderTokens[owner].length();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-ownerOf}.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\\\n        return _tokenOwners.get(tokenId, \\\\\\\"ERC721: owner query for nonexistent token\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-name}.\\\\n     */\\\\n    function name() public view virtual override returns (string memory) {\\\\n        return _name;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-symbol}.\\\\n     */\\\\n    function symbol() public view virtual override returns (string memory) {\\\\n        return _symbol;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-tokenURI}.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721Metadata: URI query for nonexistent token\\\\\\\");\\\\n\\\\n        string memory _tokenURI = _tokenURIs[tokenId];\\\\n        string memory base = baseURI();\\\\n\\\\n        // If there is no base URI, return the token URI.\\\\n        if (bytes(base).length == 0) {\\\\n            return _tokenURI;\\\\n        }\\\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\\\n        if (bytes(_tokenURI).length > 0) {\\\\n            return string(abi.encodePacked(base, _tokenURI));\\\\n        }\\\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\\\n        return string(abi.encodePacked(base, tokenId.toString()));\\\\n    }\\\\n\\\\n    /**\\\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\\\n    * to the token ID if no specific URI is set for that token ID.\\\\n    */\\\\n    function baseURI() public view virtual returns (string memory) {\\\\n        return _baseURI;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\\\n        return _holderTokens[owner].at(index);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-totalSupply}.\\\\n     */\\\\n    function totalSupply() public view virtual override returns (uint256) {\\\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\\\n        return _tokenOwners.length();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\\\n     */\\\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\\\n        return tokenId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-approve}.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) public virtual override {\\\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\\\n        require(to != owner, \\\\\\\"ERC721: approval to current owner\\\\\\\");\\\\n\\\\n        require(_msgSender() == owner || ERC721Upgradeable.isApprovedForAll(owner, _msgSender()),\\\\n            \\\\\\\"ERC721: approve caller is not owner nor approved for all\\\\\\\"\\\\n        );\\\\n\\\\n        _approve(to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-getApproved}.\\\\n     */\\\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721: approved query for nonexistent token\\\\\\\");\\\\n\\\\n        return _tokenApprovals[tokenId];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-setApprovalForAll}.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\\\n        require(operator != _msgSender(), \\\\\\\"ERC721: approve to caller\\\\\\\");\\\\n\\\\n        _operatorApprovals[_msgSender()][operator] = approved;\\\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-isApprovedForAll}.\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\\\n        return _operatorApprovals[owner][operator];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-transferFrom}.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\\\n        //solhint-disable-next-line max-line-length\\\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\\\\\"ERC721: transfer caller is not owner nor approved\\\\\\\");\\\\n\\\\n        _transfer(from, to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-safeTransferFrom}.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\\\n        safeTransferFrom(from, to, tokenId, \\\\\\\"\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-safeTransferFrom}.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\\\\\"ERC721: transfer caller is not owner nor approved\\\\\\\");\\\\n        _safeTransfer(from, to, tokenId, _data);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\\\n     *\\\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\\\n        _transfer(from, to, tokenId);\\\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns whether `tokenId` exists.\\\\n     *\\\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Tokens start existing when they are minted (`_mint`),\\\\n     * and stop existing when they are burned (`_burn`).\\\\n     */\\\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\\\n        return _tokenOwners.contains(tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721: operator query for nonexistent token\\\\\\\");\\\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721Upgradeable.isApprovedForAll(owner, spender));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\\\n     *\\\\n     * Requirements:\\\\n     d*\\\\n     * - `tokenId` must not exist.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\\\n        _safeMint(to, tokenId, \\\\\\\"\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\\\n     */\\\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\\\n        _mint(to, tokenId);\\\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Mints `tokenId` and transfers it to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must not exist.\\\\n     * - `to` cannot be the zero address.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _mint(address to, uint256 tokenId) internal virtual {\\\\n        require(to != address(0), \\\\\\\"ERC721: mint to the zero address\\\\\\\");\\\\n        require(!_exists(tokenId), \\\\\\\"ERC721: token already minted\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(address(0), to, tokenId);\\\\n\\\\n        _holderTokens[to].add(tokenId);\\\\n\\\\n        _tokenOwners.set(tokenId, to);\\\\n\\\\n        emit Transfer(address(0), to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Destroys `tokenId`.\\\\n     * The approval is cleared when the token is burned.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _burn(uint256 tokenId) internal virtual {\\\\n        address owner = ERC721Upgradeable.ownerOf(tokenId); // internal owner\\\\n\\\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\\\n\\\\n        // Clear approvals\\\\n        _approve(address(0), tokenId);\\\\n\\\\n        // Clear metadata (if any)\\\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\\\n            delete _tokenURIs[tokenId];\\\\n        }\\\\n\\\\n        _holderTokens[owner].remove(tokenId);\\\\n\\\\n        _tokenOwners.remove(tokenId);\\\\n\\\\n        emit Transfer(owner, address(0), tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` from `from` to `to`.\\\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\\\n        require(ERC721Upgradeable.ownerOf(tokenId) == from, \\\\\\\"ERC721: transfer of token that is not own\\\\\\\"); // internal owner\\\\n        require(to != address(0), \\\\\\\"ERC721: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(from, to, tokenId);\\\\n\\\\n        // Clear approvals from the previous owner\\\\n        _approve(address(0), tokenId);\\\\n\\\\n        _holderTokens[from].remove(tokenId);\\\\n        _holderTokens[to].add(tokenId);\\\\n\\\\n        _tokenOwners.set(tokenId, to);\\\\n\\\\n        emit Transfer(from, to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721Metadata: URI set of nonexistent token\\\\\\\");\\\\n        _tokenURIs[tokenId] = _tokenURI;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Internal function to set the base URI for all token IDs. It is\\\\n     * automatically added as a prefix to the value returned in {tokenURI},\\\\n     * or to the token ID if {tokenURI} is empty.\\\\n     */\\\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\\\n        _baseURI = baseURI_;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\\\n     * The call is not executed if the target address is not a contract.\\\\n     *\\\\n     * @param from address representing the previous owner of the given token ID\\\\n     * @param to target address that will receive the tokens\\\\n     * @param tokenId uint256 ID of the token to be transferred\\\\n     * @param _data bytes optional data to send along with the call\\\\n     * @return bool whether the call correctly returned the expected magic value\\\\n     */\\\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\\\n        private returns (bool)\\\\n    {\\\\n        if (!to.isContract()) {\\\\n            return true;\\\\n        }\\\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\\\n            IERC721ReceiverUpgradeable(to).onERC721Received.selector,\\\\n            _msgSender(),\\\\n            from,\\\\n            tokenId,\\\\n            _data\\\\n        ), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\\\n        return (retval == _ERC721_RECEIVED);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Approve `to` to operate on `tokenId`\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function _approve(address to, uint256 tokenId) internal virtual {\\\\n        _tokenApprovals[tokenId] = to;\\\\n        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); // internal owner\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Hook that is called before any token transfer. This includes minting\\\\n     * and burning.\\\\n     *\\\\n     * Calling conditions:\\\\n     *\\\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\\\n     * transferred to `to`.\\\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     *\\\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\\\n     */\\\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\\\n    uint256[41] private __gap;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x988d02c5a81d1223f7629f1e318606f4d58325591eb359baa621dfb5043646dc\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721EnumerableUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721Upgradeable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721EnumerableUpgradeable is IERC721Upgradeable {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2122334a6033b36e67e49040844724c5229d7cf840c9f4206d501ba61700dbd0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721MetadataUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721Upgradeable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x73990febc6e334839fc9db9e772eefad6754a46d53074fa6d1ba4170f354a3f5\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721ReceiverUpgradeable {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xafe63d2e30c9a730957f2e1b671acf2ff8e6d11f689d995dfbcc6c383c7b6a28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165Upgradeable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3c4838d816e09e5fd7347620cf53f7ab900bd23875ccf513f88c244e86077d72\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary 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    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1fd568d8b8ca285c801fbd1d3f40f848434d850a682c0273786cada3e0b84057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <0.8.0;\\\\nimport \\\\\\\"../proxy/Initializable.sol\\\\\\\";\\\\n\\\\n/*\\\\n * @dev Provides information about the current execution context, including the\\\\n * sender of the transaction and its data. While these are generally available\\\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\\\n * manner, since when dealing with GSN 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 initializer {\\\\n        __Context_init_unchained();\\\\n    }\\\\n\\\\n    function __Context_init_unchained() internal initializer {\\\\n    }\\\\n    function _msgSender() internal view virtual returns (address payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n    uint256[50] private __gap;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbbf8a21b9a66c48d45ff771b8563c6df19ba451d63dfb8380a865c1e1f29d1a0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/utils/EnumerableMapUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Library for managing an enumerable variant of Solidity's\\\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\\\n * type.\\\\n *\\\\n * Maps have the following properties:\\\\n *\\\\n * - Entries are added, removed, and checked for existence in constant time\\\\n * (O(1)).\\\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\\\n *\\\\n * ```\\\\n * contract Example {\\\\n *     // Add the library methods\\\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\\\n *\\\\n *     // Declare a set state variable\\\\n *     EnumerableMap.UintToAddressMap private myMap;\\\\n * }\\\\n * ```\\\\n *\\\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\\\n * supported.\\\\n */\\\\nlibrary EnumerableMapUpgradeable {\\\\n    // To implement this library for multiple types with as little code\\\\n    // repetition as possible, we write it in terms of a generic Map type with\\\\n    // bytes32 keys and values.\\\\n    // The Map implementation uses private functions, and user-facing\\\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\\\n    // the underlying Map.\\\\n    // This means that we can only create new EnumerableMaps for types that fit\\\\n    // in bytes32.\\\\n\\\\n    struct MapEntry {\\\\n        bytes32 _key;\\\\n        bytes32 _value;\\\\n    }\\\\n\\\\n    struct Map {\\\\n        // Storage of map keys and values\\\\n        MapEntry[] _entries;\\\\n\\\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\\\n        // because index 0 means a key is not in the map.\\\\n        mapping (bytes32 => uint256) _indexes;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\\\n     * key. O(1).\\\\n     *\\\\n     * Returns true if the key was added to the map, that is if it was not\\\\n     * already present.\\\\n     */\\\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\\\n        uint256 keyIndex = map._indexes[key];\\\\n\\\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\\\n            // The entry is stored at length-1, but we add 1 to all indexes\\\\n            // and use 0 as a sentinel value\\\\n            map._indexes[key] = map._entries.length;\\\\n            return true;\\\\n        } else {\\\\n            map._entries[keyIndex - 1]._value = value;\\\\n            return false;\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Removes a key-value pair from a map. O(1).\\\\n     *\\\\n     * Returns true if the key was removed from the map, that is if it was present.\\\\n     */\\\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\\\n        uint256 keyIndex = map._indexes[key];\\\\n\\\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\\\n            // This modifies the order of the array, as noted in {at}.\\\\n\\\\n            uint256 toDeleteIndex = keyIndex - 1;\\\\n            uint256 lastIndex = map._entries.length - 1;\\\\n\\\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\\\n\\\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\\\n\\\\n            // Move the last entry to the index where the entry to delete is\\\\n            map._entries[toDeleteIndex] = lastEntry;\\\\n            // Update the index for the moved entry\\\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\\\n\\\\n            // Delete the slot where the moved entry was stored\\\\n            map._entries.pop();\\\\n\\\\n            // Delete the index for the deleted slot\\\\n            delete map._indexes[key];\\\\n\\\\n            return true;\\\\n        } else {\\\\n            return false;\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns true if the key is in the map. O(1).\\\\n     */\\\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\\\n        return map._indexes[key] != 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\\\n     */\\\\n    function _length(Map storage map) private view returns (uint256) {\\\\n        return map._entries.length;\\\\n    }\\\\n\\\\n   /**\\\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\\\n    *\\\\n    * Note that there are no guarantees on the ordering of entries inside the\\\\n    * array, and it may change when more entries are added or removed.\\\\n    *\\\\n    * Requirements:\\\\n    *\\\\n    * - `index` must be strictly less than {length}.\\\\n    */\\\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\\\n        require(map._entries.length > index, \\\\\\\"EnumerableMap: index out of bounds\\\\\\\");\\\\n\\\\n        MapEntry storage entry = map._entries[index];\\\\n        return (entry._key, entry._value);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\\\n     * Does not revert if `key` is not in the map.\\\\n     */\\\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the value associated with `key`.  O(1).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `key` must be in the map.\\\\n     */\\\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        require(keyIndex != 0, \\\\\\\"EnumerableMap: nonexistent key\\\\\\\"); // Equivalent to contains(map, key)\\\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\\\n     */\\\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\\\n    }\\\\n\\\\n    // UintToAddressMap\\\\n\\\\n    struct UintToAddressMap {\\\\n        Map _inner;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\\\n     * key. O(1).\\\\n     *\\\\n     * Returns true if the key was added to the map, that is if it was not\\\\n     * already present.\\\\n     */\\\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Removes a value from a set. O(1).\\\\n     *\\\\n     * Returns true if the key was removed from the map, that is if it was present.\\\\n     */\\\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\\\n        return _remove(map._inner, bytes32(key));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns true if the key is in the map. O(1).\\\\n     */\\\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\\\n        return _contains(map._inner, bytes32(key));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the number of elements in the map. O(1).\\\\n     */\\\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\\\n        return _length(map._inner);\\\\n    }\\\\n\\\\n   /**\\\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\\\n        return (uint256(key), address(uint160(uint256(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\\\n     * Does not revert if `key` is not in the map.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\\\n        return (success, address(uint160(uint256(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the value associated with `key`.  O(1).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `key` must be in the map.\\\\n     */\\\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\\\n     */\\\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x736de5559b9ab9958c327854964ea731e85a720d5ceabf7eee2eef7c92744d91\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.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 EnumerableSetUpgradeable {\\\\n    // To implement this library for multiple types with as little code\\\\n    // repetition as possible, we write it in terms of a generic Set type with\\\\n    // bytes32 values.\\\\n    // The Set implementation uses private functions, and user-facing\\\\n    // implementations (such as AddressSet) are just wrappers around the\\\\n    // underlying Set.\\\\n    // This means that we can only create new EnumerableSets for types that fit\\\\n    // in bytes32.\\\\n\\\\n    struct Set {\\\\n        // Storage of set values\\\\n        bytes32[] _values;\\\\n\\\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\\\n\\\\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] = toDeleteIndex + 1; // All indexes are 1-based\\\\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        require(set._values.length > index, \\\\\\\"EnumerableSet: index out of bounds\\\\\\\");\\\\n        return set._values[index];\\\\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    // 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    // 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\\\",\\\"keccak256\\\":\\\"0xeb4d39f727e65fda4c7059105db14acde18654bd54d8916af89c3834211d7d88\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev String operations.\\\\n */\\\\nlibrary StringsUpgradeable {\\\\n    /**\\\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\\\n        temp = value;\\\\n        while (temp != 0) {\\\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\\\n            temp /= 10;\\\\n        }\\\\n        return string(buffer);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2835123cbd701f895669d17fda937ff6d003cc8357ada59d75078055c100e7ac\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/core/VaultManagerNFT.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {ERC721Upgradeable} from \\\\\\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\\\\\";\\\\n\\\\ncontract VaultNFTManager is ERC721Upgradeable {\\\\n    /// @dev tokenId for the next vault opened\\\\n    uint256 public nextId = 1;\\\\n\\\\n    address public controller;\\\\n\\\\n    modifier onlyController() {\\\\n        require(msg.sender == controller, \\\\\\\"not controller\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    function init(address _controller) public initializer {\\\\n        // init nft\\\\n        __ERC721_init(\\\\\\\"Short Opyn Squeeth Position\\\\\\\", \\\\\\\"sSqueeth\\\\\\\");\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    /**\\\\n     * mint new NFT, create a new vault struct\\\\n     */\\\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\\\n        // mint NFT\\\\n        _mint(_recipient, (tokenId = nextId++));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x67d85be229add87f661bcada9d80516af6ee7915474dceafc94d355e86a17679\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n    \"bytecode\": \"0x6080604052600160975534801561001557600080fd5b50612326806100256000396000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806354ba0f27116100d857806395d89b411161008c578063c87b56dd11610066578063c87b56dd1461051d578063e985e9c51461053a578063f77c47911461056857610177565b806395d89b4114610421578063a22cb46514610429578063b88d4fde1461045757610177565b80636352211e116100bd5780636352211e146103d65780636c0360eb146103f357806370a08231146103fb57610177565b806354ba0f27146103a857806361b8ce8c146103ce57610177565b806319ab453c1161012f5780632f745c59116101145780632f745c591461032957806342842e0e146103555780634f6ccce71461038b57610177565b806319ab453c146102cd57806323b872dd146102f357610177565b8063081812fc11610160578063081812fc1461024c578063095ea7b31461028557806318160ddd146102b357610177565b806301ffc9a71461017c57806306fdde03146101cf575b600080fd5b6101bb6004803603602081101561019257600080fd5b50357fffffffff0000000000000000000000000000000000000000000000000000000016610570565b604080519115158252519081900360200190f35b6101d76105ab565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102115781810151838201526020016101f9565b50505050905090810190601f16801561023e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102696004803603602081101561026257600080fd5b5035610641565b604080516001600160a01b039092168252519081900360200190f35b6102b16004803603604081101561029b57600080fd5b506001600160a01b0381351690602001356106a3565b005b6102bb61077e565b60408051918252519081900360200190f35b6102b1600480360360208110156102e357600080fd5b50356001600160a01b031661078f565b6102b16004803603606081101561030957600080fd5b506001600160a01b038135811691602081013590911690604001356108d9565b6102bb6004803603604081101561033f57600080fd5b506001600160a01b038135169060200135610930565b6102b16004803603606081101561036b57600080fd5b506001600160a01b0381358116916020810135909116906040013561095b565b6102bb600480360360208110156103a157600080fd5b5035610976565b6102bb600480360360208110156103be57600080fd5b50356001600160a01b031661098c565b6102bb610a04565b610269600480360360208110156103ec57600080fd5b5035610a0a565b6101d7610a32565b6102bb6004803603602081101561041157600080fd5b50356001600160a01b0316610a93565b6101d7610afb565b6102b16004803603604081101561043f57600080fd5b506001600160a01b0381351690602001351515610b5c565b6102b16004803603608081101561046d57600080fd5b6001600160a01b038235811692602081013590911691604082013591908101906080810160608201356401000000008111156104a857600080fd5b8201836020820111156104ba57600080fd5b803590602001918460018302840111640100000000831117156104dc57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610c61945050505050565b6101d76004803603602081101561053357600080fd5b5035610cbf565b6101bb6004803603604081101561055057600080fd5b506001600160a01b0381358116916020013516610f40565b610269610f6e565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081526033602052604090205460ff165b919050565b606a8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106375780601f1061060c57610100808354040283529160200191610637565b820191906000526020600020905b81548152906001019060200180831161061a57829003601f168201915b5050505050905090565b600061064c82610f7d565b6106875760405162461bcd60e51b815260040180806020018281038252602c81526020018061221b602c913960400191505060405180910390fd5b506000908152606860205260409020546001600160a01b031690565b60006106ae82610a0a565b9050806001600160a01b0316836001600160a01b031614156107015760405162461bcd60e51b815260040180806020018281038252602181526020018061229f6021913960400191505060405180910390fd5b806001600160a01b0316610713610f8a565b6001600160a01b0316148061073457506107348161072f610f8a565b610f40565b61076f5760405162461bcd60e51b81526004018080602001828103825260388152602001806121406038913960400191505060405180910390fd5b6107798383610f8e565b505050565b600061078a6066611014565b905090565b600054610100900460ff16806107a857506107a861101f565b806107b6575060005460ff16155b6107f15760405162461bcd60e51b815260040180806020018281038252602e8152602001806121cb602e913960400191505060405180910390fd5b600054610100900460ff1615801561081c576000805460ff1961ff0019909116610100171660011790555b6108906040518060400160405280601b81526020017f53686f7274204f70796e205371756565746820506f736974696f6e00000000008152506040518060400160405280600881526020017f7353717565657468000000000000000000000000000000000000000000000000815250611030565b609880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03841617905580156108d5576000805461ff00191690555b5050565b6108ea6108e4610f8a565b826110ed565b6109255760405162461bcd60e51b81526004018080602001828103825260318152602001806122c06031913960400191505060405180910390fd5b610779838383611191565b6001600160a01b038216600090815260656020526040812061095290836112dd565b90505b92915050565b61077983838360405180602001604052806000815250610c61565b6000806109846066846112e9565b509392505050565b6098546000906001600160a01b031633146109ee576040805162461bcd60e51b815260206004820152600e60248201527f6e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b5060978054600181019091556105a68282611305565b60975481565b6000610955826040518060600160405280602981526020016121a26029913960669190611433565b606d8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106375780601f1061060c57610100808354040283529160200191610637565b60006001600160a01b038216610ada5760405162461bcd60e51b815260040180806020018281038252602a815260200180612178602a913960400191505060405180910390fd5b6001600160a01b038216600090815260656020526040902061095590611014565b606b8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106375780601f1061060c57610100808354040283529160200191610637565b610b64610f8a565b6001600160a01b0316826001600160a01b03161415610bca576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060696000610bd7610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155610c1b610f8a565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b610c72610c6c610f8a565b836110ed565b610cad5760405162461bcd60e51b81526004018080602001828103825260318152602001806122c06031913960400191505060405180910390fd5b610cb98484848461144a565b50505050565b6060610cca82610f7d565b610d055760405162461bcd60e51b815260040180806020018281038252602f815260200180612270602f913960400191505060405180910390fd5b6000828152606c602090815260408083208054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015610d985780601f10610d6d57610100808354040283529160200191610d98565b820191906000526020600020905b815481529060010190602001808311610d7b57829003601f168201915b505050505090506000610da9610a32565b9050805160001415610dbd575090506105a6565b815115610e7e5780826040516020018083805190602001908083835b60208310610df85780518252601f199092019160209182019101610dd9565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610e405780518252601f199092019160209182019101610e21565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052925050506105a6565b80610e888561149c565b6040516020018083805190602001908083835b60208310610eba5780518252601f199092019160209182019101610e9b565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610f025780518252601f199092019160209182019101610ee3565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050919050565b6001600160a01b03918216600090815260696020908152604080832093909416825291909152205460ff1690565b6098546001600160a01b031681565b60006109556066836115ab565b3390565b600081815260686020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384169081179091558190610fdb82610a0a565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000610955826115b7565b600061102a306115bb565b15905090565b600054610100900460ff1680611049575061104961101f565b80611057575060005460ff16155b6110925760405162461bcd60e51b815260040180806020018281038252602e8152602001806121cb602e913960400191505060405180910390fd5b600054610100900460ff161580156110bd576000805460ff1961ff0019909116610100171660011790555b6110c56115c1565b6110cd611663565b6110d78383611719565b8015610779576000805461ff0019169055505050565b60006110f882610f7d565b6111335760405162461bcd60e51b815260040180806020018281038252602c815260200180612114602c913960400191505060405180910390fd5b600061113e83610a0a565b9050806001600160a01b0316846001600160a01b031614806111795750836001600160a01b031661116e84610641565b6001600160a01b0316145b8061118957506111898185610f40565b949350505050565b826001600160a01b03166111a482610a0a565b6001600160a01b0316146111e95760405162461bcd60e51b81526004018080602001828103825260298152602001806122476029913960400191505060405180910390fd5b6001600160a01b03821661122e5760405162461bcd60e51b81526004018080602001828103825260248152602001806120f06024913960400191505060405180910390fd5b611239838383610779565b611244600082610f8e565b6001600160a01b03831660009081526065602052604090206112669082611849565b506001600160a01b03821660009081526065602052604090206112899082611855565b5061129660668284611861565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60006109528383611877565b60008080806112f886866118db565b9097909650945050505050565b6001600160a01b038216611360576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b61136981610f7d565b156113bb576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b6113c760008383610779565b6001600160a01b03821660009081526065602052604090206113e99082611855565b506113f660668284611861565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000611440848484611956565b90505b9392505050565b611455848484611191565b61146184848484611a20565b610cb95760405162461bcd60e51b81526004018080602001828103825260328152602001806120be6032913960400191505060405180910390fd5b6060816114dd575060408051808201909152600181527f300000000000000000000000000000000000000000000000000000000000000060208201526105a6565b8160005b81156114f557600101600a820491506114e1565b60008167ffffffffffffffff8111801561150e57600080fd5b506040519080825280601f01601f191660200182016040528015611539576020820181803683370190505b50859350905060001982015b83156115a257600a840660300160f81b8282806001900393508151811061156857fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84049350611545565b50949350505050565b60006109528383611bfc565b5490565b3b151590565b600054610100900460ff16806115da57506115da61101f565b806115e8575060005460ff16155b6116235760405162461bcd60e51b815260040180806020018281038252602e8152602001806121cb602e913960400191505060405180910390fd5b600054610100900460ff1615801561164e576000805460ff1961ff0019909116610100171660011790555b8015611660576000805461ff00191690555b50565b600054610100900460ff168061167c575061167c61101f565b8061168a575060005460ff16155b6116c55760405162461bcd60e51b815260040180806020018281038252602e8152602001806121cb602e913960400191505060405180910390fd5b600054610100900460ff161580156116f0576000805460ff1961ff0019909116610100171660011790555b61164e7f01ffc9a700000000000000000000000000000000000000000000000000000000611c14565b600054610100900460ff1680611732575061173261101f565b80611740575060005460ff16155b61177b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121cb602e913960400191505060405180910390fd5b600054610100900460ff161580156117a6576000805460ff1961ff0019909116610100171660011790555b82516117b990606a906020860190611ffa565b5081516117cd90606b906020850190611ffa565b506117f77f80ac58cd00000000000000000000000000000000000000000000000000000000611c14565b6118207f5b5e139f00000000000000000000000000000000000000000000000000000000611c14565b6110d77f780e9d6300000000000000000000000000000000000000000000000000000000611c14565b60006109528383611cc8565b60006109528383611d8e565b600061144084846001600160a01b038516611dd8565b815460009082106118b95760405162461bcd60e51b815260040180806020018281038252602281526020018061209c6022913960400191505060405180910390fd5b8260000182815481106118c857fe5b9060005260206000200154905092915050565b81546000908190831061191f5760405162461bcd60e51b81526004018080602001828103825260228152602001806121f96022913960400191505060405180910390fd5b600084600001848154811061193057fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816119f15760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156119b657818101518382015260200161199e565b50505050905090810190601f1680156119e35780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50846000016001820381548110611a0457fe5b9060005260206000209060020201600101549150509392505050565b6000611a34846001600160a01b03166115bb565b611a4057506001611189565b6000611b917f150b7a0200000000000000000000000000000000000000000000000000000000611a6e610f8a565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611ad5578181015183820152602001611abd565b50505050905090810190601f168015611b025780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518060600160405280603281526020016120be603291396001600160a01b0388169190611e6f565b90506000818060200190516020811015611baa57600080fd5b50517fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001492505050949350505050565b60009081526001919091016020526040902054151590565b7fffffffff000000000000000000000000000000000000000000000000000000008082161415611c8b576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152603360205260409020805460ff19166001179055565b60008181526001830160205260408120548015611d845783546000198083019190810190600090879083908110611cfb57fe5b9060005260206000200154905080876000018481548110611d1857fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080611d4857fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610955565b6000915050610955565b6000611d9a8383611bfc565b611dd057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610955565b506000610955565b600082815260018401602052604081205480611e3d575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611443565b82856000016001830381548110611e5057fe5b9060005260206000209060020201600101819055506000915050611443565b6060611440848460008585611e83856115bb565b611ed4576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310611f125780518252601f199092019160209182019101611ef3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611f74576040519150601f19603f3d011682016040523d82523d6000602084013e611f79565b606091505b5091509150611f89828286611f94565b979650505050505050565b60608315611fa3575081611443565b825115611fb35782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156119b657818101518382015260200161199e565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826120305760008555612076565b82601f1061204957805160ff1916838001178555612076565b82800160010185558215612076579182015b8281111561207657825182559160200191906001019061205b565b50612082929150612086565b5090565b5b80821115612082576000815560010161208756fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a2646970667358221220216d9f9bacbb088d4243637fbdbb6b451558e88ee42a435e3ff6aa9366de6b6f64736f6c63430007060033\",\n    \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101775760003560e01c806354ba0f27116100d857806395d89b411161008c578063c87b56dd11610066578063c87b56dd1461051d578063e985e9c51461053a578063f77c47911461056857610177565b806395d89b4114610421578063a22cb46514610429578063b88d4fde1461045757610177565b80636352211e116100bd5780636352211e146103d65780636c0360eb146103f357806370a08231146103fb57610177565b806354ba0f27146103a857806361b8ce8c146103ce57610177565b806319ab453c1161012f5780632f745c59116101145780632f745c591461032957806342842e0e146103555780634f6ccce71461038b57610177565b806319ab453c146102cd57806323b872dd146102f357610177565b8063081812fc11610160578063081812fc1461024c578063095ea7b31461028557806318160ddd146102b357610177565b806301ffc9a71461017c57806306fdde03146101cf575b600080fd5b6101bb6004803603602081101561019257600080fd5b50357fffffffff0000000000000000000000000000000000000000000000000000000016610570565b604080519115158252519081900360200190f35b6101d76105ab565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102115781810151838201526020016101f9565b50505050905090810190601f16801561023e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102696004803603602081101561026257600080fd5b5035610641565b604080516001600160a01b039092168252519081900360200190f35b6102b16004803603604081101561029b57600080fd5b506001600160a01b0381351690602001356106a3565b005b6102bb61077e565b60408051918252519081900360200190f35b6102b1600480360360208110156102e357600080fd5b50356001600160a01b031661078f565b6102b16004803603606081101561030957600080fd5b506001600160a01b038135811691602081013590911690604001356108d9565b6102bb6004803603604081101561033f57600080fd5b506001600160a01b038135169060200135610930565b6102b16004803603606081101561036b57600080fd5b506001600160a01b0381358116916020810135909116906040013561095b565b6102bb600480360360208110156103a157600080fd5b5035610976565b6102bb600480360360208110156103be57600080fd5b50356001600160a01b031661098c565b6102bb610a04565b610269600480360360208110156103ec57600080fd5b5035610a0a565b6101d7610a32565b6102bb6004803603602081101561041157600080fd5b50356001600160a01b0316610a93565b6101d7610afb565b6102b16004803603604081101561043f57600080fd5b506001600160a01b0381351690602001351515610b5c565b6102b16004803603608081101561046d57600080fd5b6001600160a01b038235811692602081013590911691604082013591908101906080810160608201356401000000008111156104a857600080fd5b8201836020820111156104ba57600080fd5b803590602001918460018302840111640100000000831117156104dc57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610c61945050505050565b6101d76004803603602081101561053357600080fd5b5035610cbf565b6101bb6004803603604081101561055057600080fd5b506001600160a01b0381358116916020013516610f40565b610269610f6e565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081526033602052604090205460ff165b919050565b606a8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106375780601f1061060c57610100808354040283529160200191610637565b820191906000526020600020905b81548152906001019060200180831161061a57829003601f168201915b5050505050905090565b600061064c82610f7d565b6106875760405162461bcd60e51b815260040180806020018281038252602c81526020018061221b602c913960400191505060405180910390fd5b506000908152606860205260409020546001600160a01b031690565b60006106ae82610a0a565b9050806001600160a01b0316836001600160a01b031614156107015760405162461bcd60e51b815260040180806020018281038252602181526020018061229f6021913960400191505060405180910390fd5b806001600160a01b0316610713610f8a565b6001600160a01b0316148061073457506107348161072f610f8a565b610f40565b61076f5760405162461bcd60e51b81526004018080602001828103825260388152602001806121406038913960400191505060405180910390fd5b6107798383610f8e565b505050565b600061078a6066611014565b905090565b600054610100900460ff16806107a857506107a861101f565b806107b6575060005460ff16155b6107f15760405162461bcd60e51b815260040180806020018281038252602e8152602001806121cb602e913960400191505060405180910390fd5b600054610100900460ff1615801561081c576000805460ff1961ff0019909116610100171660011790555b6108906040518060400160405280601b81526020017f53686f7274204f70796e205371756565746820506f736974696f6e00000000008152506040518060400160405280600881526020017f7353717565657468000000000000000000000000000000000000000000000000815250611030565b609880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03841617905580156108d5576000805461ff00191690555b5050565b6108ea6108e4610f8a565b826110ed565b6109255760405162461bcd60e51b81526004018080602001828103825260318152602001806122c06031913960400191505060405180910390fd5b610779838383611191565b6001600160a01b038216600090815260656020526040812061095290836112dd565b90505b92915050565b61077983838360405180602001604052806000815250610c61565b6000806109846066846112e9565b509392505050565b6098546000906001600160a01b031633146109ee576040805162461bcd60e51b815260206004820152600e60248201527f6e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b5060978054600181019091556105a68282611305565b60975481565b6000610955826040518060600160405280602981526020016121a26029913960669190611433565b606d8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106375780601f1061060c57610100808354040283529160200191610637565b60006001600160a01b038216610ada5760405162461bcd60e51b815260040180806020018281038252602a815260200180612178602a913960400191505060405180910390fd5b6001600160a01b038216600090815260656020526040902061095590611014565b606b8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106375780601f1061060c57610100808354040283529160200191610637565b610b64610f8a565b6001600160a01b0316826001600160a01b03161415610bca576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060696000610bd7610f8a565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155610c1b610f8a565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b610c72610c6c610f8a565b836110ed565b610cad5760405162461bcd60e51b81526004018080602001828103825260318152602001806122c06031913960400191505060405180910390fd5b610cb98484848461144a565b50505050565b6060610cca82610f7d565b610d055760405162461bcd60e51b815260040180806020018281038252602f815260200180612270602f913960400191505060405180910390fd5b6000828152606c602090815260408083208054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015610d985780601f10610d6d57610100808354040283529160200191610d98565b820191906000526020600020905b815481529060010190602001808311610d7b57829003601f168201915b505050505090506000610da9610a32565b9050805160001415610dbd575090506105a6565b815115610e7e5780826040516020018083805190602001908083835b60208310610df85780518252601f199092019160209182019101610dd9565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610e405780518252601f199092019160209182019101610e21565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052925050506105a6565b80610e888561149c565b6040516020018083805190602001908083835b60208310610eba5780518252601f199092019160209182019101610e9b565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610f025780518252601f199092019160209182019101610ee3565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050919050565b6001600160a01b03918216600090815260696020908152604080832093909416825291909152205460ff1690565b6098546001600160a01b031681565b60006109556066836115ab565b3390565b600081815260686020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384169081179091558190610fdb82610a0a565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000610955826115b7565b600061102a306115bb565b15905090565b600054610100900460ff1680611049575061104961101f565b80611057575060005460ff16155b6110925760405162461bcd60e51b815260040180806020018281038252602e8152602001806121cb602e913960400191505060405180910390fd5b600054610100900460ff161580156110bd576000805460ff1961ff0019909116610100171660011790555b6110c56115c1565b6110cd611663565b6110d78383611719565b8015610779576000805461ff0019169055505050565b60006110f882610f7d565b6111335760405162461bcd60e51b815260040180806020018281038252602c815260200180612114602c913960400191505060405180910390fd5b600061113e83610a0a565b9050806001600160a01b0316846001600160a01b031614806111795750836001600160a01b031661116e84610641565b6001600160a01b0316145b8061118957506111898185610f40565b949350505050565b826001600160a01b03166111a482610a0a565b6001600160a01b0316146111e95760405162461bcd60e51b81526004018080602001828103825260298152602001806122476029913960400191505060405180910390fd5b6001600160a01b03821661122e5760405162461bcd60e51b81526004018080602001828103825260248152602001806120f06024913960400191505060405180910390fd5b611239838383610779565b611244600082610f8e565b6001600160a01b03831660009081526065602052604090206112669082611849565b506001600160a01b03821660009081526065602052604090206112899082611855565b5061129660668284611861565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60006109528383611877565b60008080806112f886866118db565b9097909650945050505050565b6001600160a01b038216611360576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b61136981610f7d565b156113bb576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b6113c760008383610779565b6001600160a01b03821660009081526065602052604090206113e99082611855565b506113f660668284611861565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000611440848484611956565b90505b9392505050565b611455848484611191565b61146184848484611a20565b610cb95760405162461bcd60e51b81526004018080602001828103825260328152602001806120be6032913960400191505060405180910390fd5b6060816114dd575060408051808201909152600181527f300000000000000000000000000000000000000000000000000000000000000060208201526105a6565b8160005b81156114f557600101600a820491506114e1565b60008167ffffffffffffffff8111801561150e57600080fd5b506040519080825280601f01601f191660200182016040528015611539576020820181803683370190505b50859350905060001982015b83156115a257600a840660300160f81b8282806001900393508151811061156857fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84049350611545565b50949350505050565b60006109528383611bfc565b5490565b3b151590565b600054610100900460ff16806115da57506115da61101f565b806115e8575060005460ff16155b6116235760405162461bcd60e51b815260040180806020018281038252602e8152602001806121cb602e913960400191505060405180910390fd5b600054610100900460ff1615801561164e576000805460ff1961ff0019909116610100171660011790555b8015611660576000805461ff00191690555b50565b600054610100900460ff168061167c575061167c61101f565b8061168a575060005460ff16155b6116c55760405162461bcd60e51b815260040180806020018281038252602e8152602001806121cb602e913960400191505060405180910390fd5b600054610100900460ff161580156116f0576000805460ff1961ff0019909116610100171660011790555b61164e7f01ffc9a700000000000000000000000000000000000000000000000000000000611c14565b600054610100900460ff1680611732575061173261101f565b80611740575060005460ff16155b61177b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806121cb602e913960400191505060405180910390fd5b600054610100900460ff161580156117a6576000805460ff1961ff0019909116610100171660011790555b82516117b990606a906020860190611ffa565b5081516117cd90606b906020850190611ffa565b506117f77f80ac58cd00000000000000000000000000000000000000000000000000000000611c14565b6118207f5b5e139f00000000000000000000000000000000000000000000000000000000611c14565b6110d77f780e9d6300000000000000000000000000000000000000000000000000000000611c14565b60006109528383611cc8565b60006109528383611d8e565b600061144084846001600160a01b038516611dd8565b815460009082106118b95760405162461bcd60e51b815260040180806020018281038252602281526020018061209c6022913960400191505060405180910390fd5b8260000182815481106118c857fe5b9060005260206000200154905092915050565b81546000908190831061191f5760405162461bcd60e51b81526004018080602001828103825260228152602001806121f96022913960400191505060405180910390fd5b600084600001848154811061193057fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816119f15760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156119b657818101518382015260200161199e565b50505050905090810190601f1680156119e35780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50846000016001820381548110611a0457fe5b9060005260206000209060020201600101549150509392505050565b6000611a34846001600160a01b03166115bb565b611a4057506001611189565b6000611b917f150b7a0200000000000000000000000000000000000000000000000000000000611a6e610f8a565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611ad5578181015183820152602001611abd565b50505050905090810190601f168015611b025780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518060600160405280603281526020016120be603291396001600160a01b0388169190611e6f565b90506000818060200190516020811015611baa57600080fd5b50517fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001492505050949350505050565b60009081526001919091016020526040902054151590565b7fffffffff000000000000000000000000000000000000000000000000000000008082161415611c8b576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152603360205260409020805460ff19166001179055565b60008181526001830160205260408120548015611d845783546000198083019190810190600090879083908110611cfb57fe5b9060005260206000200154905080876000018481548110611d1857fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080611d4857fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610955565b6000915050610955565b6000611d9a8383611bfc565b611dd057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610955565b506000610955565b600082815260018401602052604081205480611e3d575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611443565b82856000016001830381548110611e5057fe5b9060005260206000209060020201600101819055506000915050611443565b6060611440848460008585611e83856115bb565b611ed4576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310611f125780518252601f199092019160209182019101611ef3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611f74576040519150601f19603f3d011682016040523d82523d6000602084013e611f79565b606091505b5091509150611f89828286611f94565b979650505050505050565b60608315611fa3575081611443565b825115611fb35782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156119b657818101518382015260200161199e565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826120305760008555612076565b82601f1061204957805160ff1916838001178555612076565b82800160010185558215612076579182015b8281111561207657825182559160200191906001019061205b565b50612082929150612086565b5090565b5b80821115612082576000815560010161208756fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a2646970667358221220216d9f9bacbb088d4243637fbdbb6b451558e88ee42a435e3ff6aa9366de6b6f64736f6c63430007060033\",\n    \"devdoc\": {\n        \"kind\": \"dev\",\n        \"methods\": {\n            \"approve(address,uint256)\": {\n                \"details\": \"See {IERC721-approve}.\"\n            },\n            \"balanceOf(address)\": {\n                \"details\": \"See {IERC721-balanceOf}.\"\n            },\n            \"baseURI()\": {\n                \"details\": \"Returns the base URI set via {_setBaseURI}. This will be automatically added as a prefix in {tokenURI} to each token's URI, or to the token ID if no specific URI is set for that token ID.\"\n            },\n            \"getApproved(uint256)\": {\n                \"details\": \"See {IERC721-getApproved}.\"\n            },\n            \"isApprovedForAll(address,address)\": {\n                \"details\": \"See {IERC721-isApprovedForAll}.\"\n            },\n            \"name()\": {\n                \"details\": \"See {IERC721Metadata-name}.\"\n            },\n            \"ownerOf(uint256)\": {\n                \"details\": \"See {IERC721-ownerOf}.\"\n            },\n            \"safeTransferFrom(address,address,uint256)\": {\n                \"details\": \"See {IERC721-safeTransferFrom}.\"\n            },\n            \"safeTransferFrom(address,address,uint256,bytes)\": {\n                \"details\": \"See {IERC721-safeTransferFrom}.\"\n            },\n            \"setApprovalForAll(address,bool)\": {\n                \"details\": \"See {IERC721-setApprovalForAll}.\"\n            },\n            \"supportsInterface(bytes4)\": {\n                \"details\": \"See {IERC165-supportsInterface}. Time complexity O(1), guaranteed to always use less than 30 000 gas.\"\n            },\n            \"symbol()\": {\n                \"details\": \"See {IERC721Metadata-symbol}.\"\n            },\n            \"tokenByIndex(uint256)\": {\n                \"details\": \"See {IERC721Enumerable-tokenByIndex}.\"\n            },\n            \"tokenOfOwnerByIndex(address,uint256)\": {\n                \"details\": \"See {IERC721Enumerable-tokenOfOwnerByIndex}.\"\n            },\n            \"tokenURI(uint256)\": {\n                \"details\": \"See {IERC721Metadata-tokenURI}.\"\n            },\n            \"totalSupply()\": {\n                \"details\": \"See {IERC721Enumerable-totalSupply}.\"\n            },\n            \"transferFrom(address,address,uint256)\": {\n                \"details\": \"See {IERC721-transferFrom}.\"\n            }\n        },\n        \"stateVariables\": {\n            \"nextId\": {\n                \"details\": \"tokenId for the next vault opened\"\n            }\n        },\n        \"version\": 1\n    },\n    \"userdoc\": {\n        \"kind\": \"user\",\n        \"methods\": {\n            \"mintNFT(address)\": {\n                \"notice\": \"mint new NFT, create a new vault struct\"\n            }\n        },\n        \"version\": 1\n    },\n    \"storageLayout\": {\n        \"storage\": [\n            {\n                \"astId\": 448,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"_initialized\",\n                \"offset\": 0,\n                \"slot\": \"0\",\n                \"type\": \"t_bool\"\n            },\n            {\n                \"astId\": 451,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"_initializing\",\n                \"offset\": 1,\n                \"slot\": \"0\",\n                \"type\": \"t_bool\"\n            },\n            {\n                \"astId\": 1961,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"__gap\",\n                \"offset\": 0,\n                \"slot\": \"1\",\n                \"type\": \"t_array(t_uint256)50_storage\"\n            },\n            {\n                \"astId\": 16,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"_supportedInterfaces\",\n                \"offset\": 0,\n                \"slot\": \"51\",\n                \"type\": \"t_mapping(t_bytes4,t_bool)\"\n            },\n            {\n                \"astId\": 73,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"__gap\",\n                \"offset\": 0,\n                \"slot\": \"52\",\n                \"type\": \"t_array(t_uint256)49_storage\"\n            },\n            {\n                \"astId\": 556,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"_holderTokens\",\n                \"offset\": 0,\n                \"slot\": \"101\",\n                \"type\": \"t_mapping(t_address,t_struct(UintSet)2919_storage)\"\n            },\n            {\n                \"astId\": 558,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"_tokenOwners\",\n                \"offset\": 0,\n                \"slot\": \"102\",\n                \"type\": \"t_struct(UintToAddressMap)2296_storage\"\n            },\n            {\n                \"astId\": 562,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"_tokenApprovals\",\n                \"offset\": 0,\n                \"slot\": \"104\",\n                \"type\": \"t_mapping(t_uint256,t_address)\"\n            },\n            {\n                \"astId\": 568,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"_operatorApprovals\",\n                \"offset\": 0,\n                \"slot\": \"105\",\n                \"type\": \"t_mapping(t_address,t_mapping(t_address,t_bool))\"\n            },\n            {\n                \"astId\": 570,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"_name\",\n                \"offset\": 0,\n                \"slot\": \"106\",\n                \"type\": \"t_string_storage\"\n            },\n            {\n                \"astId\": 572,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"_symbol\",\n                \"offset\": 0,\n                \"slot\": \"107\",\n                \"type\": \"t_string_storage\"\n            },\n            {\n                \"astId\": 576,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"_tokenURIs\",\n                \"offset\": 0,\n                \"slot\": \"108\",\n                \"type\": \"t_mapping(t_uint256,t_string_storage)\"\n            },\n            {\n                \"astId\": 578,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"_baseURI\",\n                \"offset\": 0,\n                \"slot\": \"109\",\n                \"type\": \"t_string_storage\"\n            },\n            {\n                \"astId\": 1480,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"__gap\",\n                \"offset\": 0,\n                \"slot\": \"110\",\n                \"type\": \"t_array(t_uint256)41_storage\"\n            },\n            {\n                \"astId\": 13931,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"nextId\",\n                \"offset\": 0,\n                \"slot\": \"151\",\n                \"type\": \"t_uint256\"\n            },\n            {\n                \"astId\": 13933,\n                \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                \"label\": \"controller\",\n                \"offset\": 0,\n                \"slot\": \"152\",\n                \"type\": \"t_address\"\n            }\n        ],\n        \"types\": {\n            \"t_address\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"address\",\n                \"numberOfBytes\": \"20\"\n            },\n            \"t_array(t_bytes32)dyn_storage\": {\n                \"base\": \"t_bytes32\",\n                \"encoding\": \"dynamic_array\",\n                \"label\": \"bytes32[]\",\n                \"numberOfBytes\": \"32\"\n            },\n            \"t_array(t_struct(MapEntry)1970_storage)dyn_storage\": {\n                \"base\": \"t_struct(MapEntry)1970_storage\",\n                \"encoding\": \"dynamic_array\",\n                \"label\": \"struct EnumerableMapUpgradeable.MapEntry[]\",\n                \"numberOfBytes\": \"32\"\n            },\n            \"t_array(t_uint256)41_storage\": {\n                \"base\": \"t_uint256\",\n                \"encoding\": \"inplace\",\n                \"label\": \"uint256[41]\",\n                \"numberOfBytes\": \"1312\"\n            },\n            \"t_array(t_uint256)49_storage\": {\n                \"base\": \"t_uint256\",\n                \"encoding\": \"inplace\",\n                \"label\": \"uint256[49]\",\n                \"numberOfBytes\": \"1568\"\n            },\n            \"t_array(t_uint256)50_storage\": {\n                \"base\": \"t_uint256\",\n                \"encoding\": \"inplace\",\n                \"label\": \"uint256[50]\",\n                \"numberOfBytes\": \"1600\"\n            },\n            \"t_bool\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"bool\",\n                \"numberOfBytes\": \"1\"\n            },\n            \"t_bytes32\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"bytes32\",\n                \"numberOfBytes\": \"32\"\n            },\n            \"t_bytes4\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"bytes4\",\n                \"numberOfBytes\": \"4\"\n            },\n            \"t_mapping(t_address,t_bool)\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_address\",\n                \"label\": \"mapping(address => bool)\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_bool\"\n            },\n            \"t_mapping(t_address,t_mapping(t_address,t_bool))\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_address\",\n                \"label\": \"mapping(address => mapping(address => bool))\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_mapping(t_address,t_bool)\"\n            },\n            \"t_mapping(t_address,t_struct(UintSet)2919_storage)\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_address\",\n                \"label\": \"mapping(address => struct EnumerableSetUpgradeable.UintSet)\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_struct(UintSet)2919_storage\"\n            },\n            \"t_mapping(t_bytes32,t_uint256)\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_bytes32\",\n                \"label\": \"mapping(bytes32 => uint256)\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_uint256\"\n            },\n            \"t_mapping(t_bytes4,t_bool)\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_bytes4\",\n                \"label\": \"mapping(bytes4 => bool)\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_bool\"\n            },\n            \"t_mapping(t_uint256,t_address)\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_uint256\",\n                \"label\": \"mapping(uint256 => address)\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_address\"\n            },\n            \"t_mapping(t_uint256,t_string_storage)\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_uint256\",\n                \"label\": \"mapping(uint256 => string)\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_string_storage\"\n            },\n            \"t_string_storage\": {\n                \"encoding\": \"bytes\",\n                \"label\": \"string\",\n                \"numberOfBytes\": \"32\"\n            },\n            \"t_struct(Map)1978_storage\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"struct EnumerableMapUpgradeable.Map\",\n                \"members\": [\n                    {\n                        \"astId\": 1973,\n                        \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                        \"label\": \"_entries\",\n                        \"offset\": 0,\n                        \"slot\": \"0\",\n                        \"type\": \"t_array(t_struct(MapEntry)1970_storage)dyn_storage\"\n                    },\n                    {\n                        \"astId\": 1977,\n                        \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                        \"label\": \"_indexes\",\n                        \"offset\": 0,\n                        \"slot\": \"1\",\n                        \"type\": \"t_mapping(t_bytes32,t_uint256)\"\n                    }\n                ],\n                \"numberOfBytes\": \"64\"\n            },\n            \"t_struct(MapEntry)1970_storage\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"struct EnumerableMapUpgradeable.MapEntry\",\n                \"members\": [\n                    {\n                        \"astId\": 1967,\n                        \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                        \"label\": \"_key\",\n                        \"offset\": 0,\n                        \"slot\": \"0\",\n                        \"type\": \"t_bytes32\"\n                    },\n                    {\n                        \"astId\": 1969,\n                        \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                        \"label\": \"_value\",\n                        \"offset\": 0,\n                        \"slot\": \"1\",\n                        \"type\": \"t_bytes32\"\n                    }\n                ],\n                \"numberOfBytes\": \"64\"\n            },\n            \"t_struct(Set)2533_storage\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"struct EnumerableSetUpgradeable.Set\",\n                \"members\": [\n                    {\n                        \"astId\": 2528,\n                        \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                        \"label\": \"_values\",\n                        \"offset\": 0,\n                        \"slot\": \"0\",\n                        \"type\": \"t_array(t_bytes32)dyn_storage\"\n                    },\n                    {\n                        \"astId\": 2532,\n                        \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                        \"label\": \"_indexes\",\n                        \"offset\": 0,\n                        \"slot\": \"1\",\n                        \"type\": \"t_mapping(t_bytes32,t_uint256)\"\n                    }\n                ],\n                \"numberOfBytes\": \"64\"\n            },\n            \"t_struct(UintSet)2919_storage\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"struct EnumerableSetUpgradeable.UintSet\",\n                \"members\": [\n                    {\n                        \"astId\": 2918,\n                        \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                        \"label\": \"_inner\",\n                        \"offset\": 0,\n                        \"slot\": \"0\",\n                        \"type\": \"t_struct(Set)2533_storage\"\n                    }\n                ],\n                \"numberOfBytes\": \"64\"\n            },\n            \"t_struct(UintToAddressMap)2296_storage\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"struct EnumerableMapUpgradeable.UintToAddressMap\",\n                \"members\": [\n                    {\n                        \"astId\": 2295,\n                        \"contract\": \"contracts/core/VaultManagerNFT.sol:VaultNFTManager\",\n                        \"label\": \"_inner\",\n                        \"offset\": 0,\n                        \"slot\": \"0\",\n                        \"type\": \"t_struct(Map)1978_storage\"\n                    }\n                ],\n                \"numberOfBytes\": \"64\"\n            },\n            \"t_uint256\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"uint256\",\n                \"numberOfBytes\": \"32\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/WSqueeth.json",
    "content": "{\n    \"address\": \"0xEC0db8766bc003C14861af996e411beA6Bf800aB\",\n    \"abi\": [\n        {\n            \"inputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"constructor\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"owner\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"spender\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"value\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"Approval\",\n            \"type\": \"event\"\n        },\n        {\n            \"anonymous\": false,\n            \"inputs\": [\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"from\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": true,\n                    \"internalType\": \"address\",\n                    \"name\": \"to\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"indexed\": false,\n                    \"internalType\": \"uint256\",\n                    \"name\": \"value\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"Transfer\",\n            \"type\": \"event\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"owner\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"spender\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"allowance\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"spender\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"approve\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"account\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"balanceOf\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_account\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"burn\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"controller\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"decimals\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint8\",\n                    \"name\": \"\",\n                    \"type\": \"uint8\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"spender\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"subtractedValue\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"decreaseAllowance\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"spender\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"addedValue\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"increaseAllowance\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_controller\",\n                    \"type\": \"address\"\n                }\n            ],\n            \"name\": \"init\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"_account\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"_amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"mint\",\n            \"outputs\": [],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"name\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"string\",\n                    \"name\": \"\",\n                    \"type\": \"string\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"symbol\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"string\",\n                    \"name\": \"\",\n                    \"type\": \"string\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [],\n            \"name\": \"totalSupply\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"stateMutability\": \"view\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"recipient\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"transfer\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        },\n        {\n            \"inputs\": [\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"sender\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"address\",\n                    \"name\": \"recipient\",\n                    \"type\": \"address\"\n                },\n                {\n                    \"internalType\": \"uint256\",\n                    \"name\": \"amount\",\n                    \"type\": \"uint256\"\n                }\n            ],\n            \"name\": \"transferFrom\",\n            \"outputs\": [\n                {\n                    \"internalType\": \"bool\",\n                    \"name\": \"\",\n                    \"type\": \"bool\"\n                }\n            ],\n            \"stateMutability\": \"nonpayable\",\n            \"type\": \"function\"\n        }\n    ],\n    \"transactionHash\": \"0x9e5a2b088e8acb0c0ec7b80a18ea35abfc9c911824dd3313c1b1265d985be197\",\n    \"receipt\": {\n        \"to\": null,\n        \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n        \"contractAddress\": \"0xEC0db8766bc003C14861af996e411beA6Bf800aB\",\n        \"transactionIndex\": 0,\n        \"gasUsed\": \"9016141\",\n        \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n        \"blockHash\": \"0x64bdea7bfd98eeee10fb27ebb66fa3888fca5166511d35b47fa35ec0c1a3ac5d\",\n        \"transactionHash\": \"0x9e5a2b088e8acb0c0ec7b80a18ea35abfc9c911824dd3313c1b1265d985be197\",\n        \"logs\": [],\n        \"blockNumber\": 5750472,\n        \"cumulativeGasUsed\": \"678181\",\n        \"status\": 1,\n        \"byzantium\": true\n    },\n    \"args\": [],\n    \"solcInputHash\": \"49c79f88c6e4ede6ca1f2ffd46fef4fe\",\n    \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burn\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"subtractedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"decreaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"addedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"increaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controller\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"init\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mint\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"details\\\":\\\"this contract implements IWPowerPerp interface, makes it controllable by Controller.decimals of squeeth is chosen as 14.\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"allowance(address,address)\\\":{\\\"details\\\":\\\"See {IERC20-allowance}.\\\"},\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC20-balanceOf}.\\\"},\\\"decimals()\\\":{\\\"details\\\":\\\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\\\"},\\\"decreaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\\\"},\\\"increaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\\\"},\\\"name()\\\":{\\\"details\\\":\\\"Returns the name of the token.\\\"},\\\"symbol()\\\":{\\\"details\\\":\\\"Returns the symbol of the token, usually a shorter version of the name.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC20-totalSupply}.\\\"},\\\"transfer(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{},\\\"notice\\\":\\\"this is the ERC20 contract for long position of Squeeth\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/WSqueeth.sol\\\":\\\"WSqueeth\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":2000},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// solhint-disable-next-line compiler-version\\\\npragma solidity >=0.4.24 <0.8.0;\\\\n\\\\nimport \\\\\\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\\\nabstract contract Initializable {\\\\n\\\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\\\n    function _isConstructor() private view returns (bool) {\\\\n        return !Address.isContract(address(this));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9abeffe138f098b16557187383ba0f9e8503602fa95cd668132986ee115237ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/core/WSqueeth.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\nimport {Initializable} from \\\\\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\n\\\\n/// @notice this is the ERC20 contract for long position of Squeeth\\\\n/// @dev this contract implements IWPowerPerp interface, makes it controllable by Controller.\\\\n/// @dev decimals of squeeth is chosen as 14.\\\\ncontract WSqueeth is ERC20, Initializable, IWPowerPerp {\\\\n    address public controller;\\\\n\\\\n    constructor() ERC20(\\\\\\\"Wrapped Squeeth\\\\\\\", \\\\\\\"WSQTH\\\\\\\") {}\\\\n\\\\n    modifier onlyController() {\\\\n        require(msg.sender == controller, \\\\\\\"not controller\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    function init(address _controller) external initializer {\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    function mint(address _account, uint256 _amount) external override onlyController {\\\\n        _mint(_account, _amount);\\\\n    }\\\\n\\\\n    function burn(address _account, uint256 _amount) external override onlyController {\\\\n        _burn(_account, _amount);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4546c84b2b027305d90cf6296d74c13bceebd15cf06fb02b55d80b242df3c9d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n    \"bytecode\": \"0x608060405234801561001057600080fd5b50604080518082018252600f81526e0aee4c2e0e0cac840a6e2eacacae8d608b1b6020808301918252835180850190945260058452640aea6a2a8960db1b9084015281519192916100639160039161008c565b50805161007790600490602084019061008c565b50506005805460ff191660121790555061012d565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826100c25760008555610108565b82601f106100db57805160ff1916838001178555610108565b82800160010185558215610108579182015b828111156101085782518255916020019190600101906100ed565b50610114929150610118565b5090565b5b808211156101145760008155600101610119565b610fae806200013d6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806340c10f1911610097578063a457c2d711610066578063a457c2d7146102ff578063a9059cbb1461032b578063dd62ed3e14610357578063f77c479114610385576100f5565b806340c10f191461027957806370a08231146102a557806395d89b41146102cb5780639dc29fac146102d3576100f5565b806319ab453c116100d357806319ab453c146101d157806323b872dd146101f9578063313ce5671461022f578063395093511461024d576100f5565b806306fdde03146100fa578063095ea7b31461017757806318160ddd146101b7575b600080fd5b6101026103a9565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013c578181015183820152602001610124565b50505050905090810190601f1680156101695780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101a36004803603604081101561018d57600080fd5b506001600160a01b03813516906020013561043f565b604080519115158252519081900360200190f35b6101bf61045c565b60408051918252519081900360200190f35b6101f7600480360360208110156101e757600080fd5b50356001600160a01b0316610462565b005b6101a36004803603606081101561020f57600080fd5b506001600160a01b03813581169160208101359091169060400135610567565b6102376105ee565b6040805160ff9092168252519081900360200190f35b6101a36004803603604081101561026357600080fd5b506001600160a01b0381351690602001356105f7565b6101f76004803603604081101561028f57600080fd5b506001600160a01b038135169060200135610645565b6101bf600480360360208110156102bb57600080fd5b50356001600160a01b03166106b5565b6101026106d0565b6101f7600480360360408110156102e957600080fd5b506001600160a01b038135169060200135610731565b6101a36004803603604081101561031557600080fd5b506001600160a01b0381351690602001356107a1565b6101a36004803603604081101561034157600080fd5b506001600160a01b038135169060200135610809565b6101bf6004803603604081101561036d57600080fd5b506001600160a01b038135811691602001351661081d565b61038d610848565b604080516001600160a01b039092168252519081900360200190f35b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b820191906000526020600020905b81548152906001019060200180831161041857829003601f168201915b5050505050905090565b600061045361044c61085e565b8484610862565b50600192915050565b60025490565b60055462010000900460ff168061047c575061047c61094e565b8061048f5750600554610100900460ff16155b6104ca5760405162461bcd60e51b815260040180806020018281038252602e815260200180610e94602e913960400191505060405180910390fd5b60055462010000900460ff1615801561051757600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff62ff0000199091166201000017166101001790555b600580547fffffffffffffffffff0000000000000000000000000000000000000000ffffff1663010000006001600160a01b038516021790558015610563576005805462ff0000191690555b5050565b600061057484848461095f565b6105e48461058061085e565b6105df85604051806060016040528060288152602001610ec2602891396001600160a01b038a166000908152600160205260408120906105be61085e565b6001600160a01b031681526020810191909152604001600020549190610aba565b610862565b5060019392505050565b60055460ff1690565b600061045361060461085e565b846105df856001600061061561085e565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610b51565b600554630100000090046001600160a01b031633146106ab576040805162461bcd60e51b815260206004820152600e60248201527f6e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b6105638282610bb2565b6001600160a01b031660009081526020819052604090205490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b600554630100000090046001600160a01b03163314610797576040805162461bcd60e51b815260206004820152600e60248201527f6e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b6105638282610ca2565b60006104536107ae61085e565b846105df85604051806060016040528060258152602001610f5460259139600160006107d861085e565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610aba565b600061045361081661085e565b848461095f565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600554630100000090046001600160a01b031681565b3390565b6001600160a01b0383166108a75760405162461bcd60e51b8152600401808060200182810382526024815260200180610f306024913960400191505060405180910390fd5b6001600160a01b0382166108ec5760405162461bcd60e51b8152600401808060200182810382526022815260200180610e4c6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600061095930610d9e565b15905090565b6001600160a01b0383166109a45760405162461bcd60e51b8152600401808060200182810382526025815260200180610f0b6025913960400191505060405180910390fd5b6001600160a01b0382166109e95760405162461bcd60e51b8152600401808060200182810382526023815260200180610e076023913960400191505060405180910390fd5b6109f4838383610da4565b610a3181604051806060016040528060268152602001610e6e602691396001600160a01b0386166000908152602081905260409020549190610aba565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610a609082610b51565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610b495760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610b0e578181015183820152602001610af6565b50505050905090810190601f168015610b3b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610bab576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610c0d576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610c1960008383610da4565b600254610c269082610b51565b6002556001600160a01b038216600090815260208190526040902054610c4c9082610b51565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610ce75760405162461bcd60e51b8152600401808060200182810382526021815260200180610eea6021913960400191505060405180910390fd5b610cf382600083610da4565b610d3081604051806060016040528060228152602001610e2a602291396001600160a01b0385166000908152602081905260409020549190610aba565b6001600160a01b038316600090815260208190526040902055600254610d569082610da9565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b3b151590565b505050565b600082821115610e00576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220c9e674bd72d4e131d4aeabcfdd36976c928c683225e4d5725ac9f7cf5ae0908164736f6c63430007060033\",\n    \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806340c10f1911610097578063a457c2d711610066578063a457c2d7146102ff578063a9059cbb1461032b578063dd62ed3e14610357578063f77c479114610385576100f5565b806340c10f191461027957806370a08231146102a557806395d89b41146102cb5780639dc29fac146102d3576100f5565b806319ab453c116100d357806319ab453c146101d157806323b872dd146101f9578063313ce5671461022f578063395093511461024d576100f5565b806306fdde03146100fa578063095ea7b31461017757806318160ddd146101b7575b600080fd5b6101026103a9565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013c578181015183820152602001610124565b50505050905090810190601f1680156101695780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101a36004803603604081101561018d57600080fd5b506001600160a01b03813516906020013561043f565b604080519115158252519081900360200190f35b6101bf61045c565b60408051918252519081900360200190f35b6101f7600480360360208110156101e757600080fd5b50356001600160a01b0316610462565b005b6101a36004803603606081101561020f57600080fd5b506001600160a01b03813581169160208101359091169060400135610567565b6102376105ee565b6040805160ff9092168252519081900360200190f35b6101a36004803603604081101561026357600080fd5b506001600160a01b0381351690602001356105f7565b6101f76004803603604081101561028f57600080fd5b506001600160a01b038135169060200135610645565b6101bf600480360360208110156102bb57600080fd5b50356001600160a01b03166106b5565b6101026106d0565b6101f7600480360360408110156102e957600080fd5b506001600160a01b038135169060200135610731565b6101a36004803603604081101561031557600080fd5b506001600160a01b0381351690602001356107a1565b6101a36004803603604081101561034157600080fd5b506001600160a01b038135169060200135610809565b6101bf6004803603604081101561036d57600080fd5b506001600160a01b038135811691602001351661081d565b61038d610848565b604080516001600160a01b039092168252519081900360200190f35b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b820191906000526020600020905b81548152906001019060200180831161041857829003601f168201915b5050505050905090565b600061045361044c61085e565b8484610862565b50600192915050565b60025490565b60055462010000900460ff168061047c575061047c61094e565b8061048f5750600554610100900460ff16155b6104ca5760405162461bcd60e51b815260040180806020018281038252602e815260200180610e94602e913960400191505060405180910390fd5b60055462010000900460ff1615801561051757600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff62ff0000199091166201000017166101001790555b600580547fffffffffffffffffff0000000000000000000000000000000000000000ffffff1663010000006001600160a01b038516021790558015610563576005805462ff0000191690555b5050565b600061057484848461095f565b6105e48461058061085e565b6105df85604051806060016040528060288152602001610ec2602891396001600160a01b038a166000908152600160205260408120906105be61085e565b6001600160a01b031681526020810191909152604001600020549190610aba565b610862565b5060019392505050565b60055460ff1690565b600061045361060461085e565b846105df856001600061061561085e565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610b51565b600554630100000090046001600160a01b031633146106ab576040805162461bcd60e51b815260206004820152600e60248201527f6e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b6105638282610bb2565b6001600160a01b031660009081526020819052604090205490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b600554630100000090046001600160a01b03163314610797576040805162461bcd60e51b815260206004820152600e60248201527f6e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b6105638282610ca2565b60006104536107ae61085e565b846105df85604051806060016040528060258152602001610f5460259139600160006107d861085e565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610aba565b600061045361081661085e565b848461095f565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600554630100000090046001600160a01b031681565b3390565b6001600160a01b0383166108a75760405162461bcd60e51b8152600401808060200182810382526024815260200180610f306024913960400191505060405180910390fd5b6001600160a01b0382166108ec5760405162461bcd60e51b8152600401808060200182810382526022815260200180610e4c6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600061095930610d9e565b15905090565b6001600160a01b0383166109a45760405162461bcd60e51b8152600401808060200182810382526025815260200180610f0b6025913960400191505060405180910390fd5b6001600160a01b0382166109e95760405162461bcd60e51b8152600401808060200182810382526023815260200180610e076023913960400191505060405180910390fd5b6109f4838383610da4565b610a3181604051806060016040528060268152602001610e6e602691396001600160a01b0386166000908152602081905260409020549190610aba565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610a609082610b51565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610b495760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610b0e578181015183820152602001610af6565b50505050905090810190601f168015610b3b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610bab576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610c0d576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610c1960008383610da4565b600254610c269082610b51565b6002556001600160a01b038216600090815260208190526040902054610c4c9082610b51565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610ce75760405162461bcd60e51b8152600401808060200182810382526021815260200180610eea6021913960400191505060405180910390fd5b610cf382600083610da4565b610d3081604051806060016040528060228152602001610e2a602291396001600160a01b0385166000908152602081905260409020549190610aba565b6001600160a01b038316600090815260208190526040902055600254610d569082610da9565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b3b151590565b505050565b600082821115610e00576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220c9e674bd72d4e131d4aeabcfdd36976c928c683225e4d5725ac9f7cf5ae0908164736f6c63430007060033\",\n    \"devdoc\": {\n        \"details\": \"this contract implements IWPowerPerp interface, makes it controllable by Controller.decimals of squeeth is chosen as 14.\",\n        \"kind\": \"dev\",\n        \"methods\": {\n            \"allowance(address,address)\": {\n                \"details\": \"See {IERC20-allowance}.\"\n            },\n            \"approve(address,uint256)\": {\n                \"details\": \"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"\n            },\n            \"balanceOf(address)\": {\n                \"details\": \"See {IERC20-balanceOf}.\"\n            },\n            \"decimals()\": {\n                \"details\": \"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"\n            },\n            \"decreaseAllowance(address,uint256)\": {\n                \"details\": \"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"\n            },\n            \"increaseAllowance(address,uint256)\": {\n                \"details\": \"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"\n            },\n            \"name()\": {\n                \"details\": \"Returns the name of the token.\"\n            },\n            \"symbol()\": {\n                \"details\": \"Returns the symbol of the token, usually a shorter version of the name.\"\n            },\n            \"totalSupply()\": {\n                \"details\": \"See {IERC20-totalSupply}.\"\n            },\n            \"transfer(address,uint256)\": {\n                \"details\": \"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"\n            },\n            \"transferFrom(address,address,uint256)\": {\n                \"details\": \"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"\n            }\n        },\n        \"version\": 1\n    },\n    \"userdoc\": {\n        \"kind\": \"user\",\n        \"methods\": {},\n        \"notice\": \"this is the ERC20 contract for long position of Squeeth\",\n        \"version\": 1\n    },\n    \"storageLayout\": {\n        \"storage\": [\n            {\n                \"astId\": 3718,\n                \"contract\": \"contracts/core/WSqueeth.sol:WSqueeth\",\n                \"label\": \"_balances\",\n                \"offset\": 0,\n                \"slot\": \"0\",\n                \"type\": \"t_mapping(t_address,t_uint256)\"\n            },\n            {\n                \"astId\": 3724,\n                \"contract\": \"contracts/core/WSqueeth.sol:WSqueeth\",\n                \"label\": \"_allowances\",\n                \"offset\": 0,\n                \"slot\": \"1\",\n                \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n            },\n            {\n                \"astId\": 3726,\n                \"contract\": \"contracts/core/WSqueeth.sol:WSqueeth\",\n                \"label\": \"_totalSupply\",\n                \"offset\": 0,\n                \"slot\": \"2\",\n                \"type\": \"t_uint256\"\n            },\n            {\n                \"astId\": 3728,\n                \"contract\": \"contracts/core/WSqueeth.sol:WSqueeth\",\n                \"label\": \"_name\",\n                \"offset\": 0,\n                \"slot\": \"3\",\n                \"type\": \"t_string_storage\"\n            },\n            {\n                \"astId\": 3730,\n                \"contract\": \"contracts/core/WSqueeth.sol:WSqueeth\",\n                \"label\": \"_symbol\",\n                \"offset\": 0,\n                \"slot\": \"4\",\n                \"type\": \"t_string_storage\"\n            },\n            {\n                \"astId\": 3732,\n                \"contract\": \"contracts/core/WSqueeth.sol:WSqueeth\",\n                \"label\": \"_decimals\",\n                \"offset\": 0,\n                \"slot\": \"5\",\n                \"type\": \"t_uint8\"\n            },\n            {\n                \"astId\": 3642,\n                \"contract\": \"contracts/core/WSqueeth.sol:WSqueeth\",\n                \"label\": \"_initialized\",\n                \"offset\": 1,\n                \"slot\": \"5\",\n                \"type\": \"t_bool\"\n            },\n            {\n                \"astId\": 3645,\n                \"contract\": \"contracts/core/WSqueeth.sol:WSqueeth\",\n                \"label\": \"_initializing\",\n                \"offset\": 2,\n                \"slot\": \"5\",\n                \"type\": \"t_bool\"\n            },\n            {\n                \"astId\": 14000,\n                \"contract\": \"contracts/core/WSqueeth.sol:WSqueeth\",\n                \"label\": \"controller\",\n                \"offset\": 3,\n                \"slot\": \"5\",\n                \"type\": \"t_address\"\n            }\n        ],\n        \"types\": {\n            \"t_address\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"address\",\n                \"numberOfBytes\": \"20\"\n            },\n            \"t_bool\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"bool\",\n                \"numberOfBytes\": \"1\"\n            },\n            \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_address\",\n                \"label\": \"mapping(address => mapping(address => uint256))\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_mapping(t_address,t_uint256)\"\n            },\n            \"t_mapping(t_address,t_uint256)\": {\n                \"encoding\": \"mapping\",\n                \"key\": \"t_address\",\n                \"label\": \"mapping(address => uint256)\",\n                \"numberOfBytes\": \"32\",\n                \"value\": \"t_uint256\"\n            },\n            \"t_string_storage\": {\n                \"encoding\": \"bytes\",\n                \"label\": \"string\",\n                \"numberOfBytes\": \"32\"\n            },\n            \"t_uint256\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"uint256\",\n                \"numberOfBytes\": \"32\"\n            },\n            \"t_uint8\": {\n                \"encoding\": \"inplace\",\n                \"label\": \"uint8\",\n                \"numberOfBytes\": \"1\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/solcInputs/1eb2d8df0d50660ef74af8c7c5cd526b.json",
    "content": "{\n    \"language\": \"Solidity\",\n    \"sources\": {\n        \"contracts/core/Controller.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract Controller is Initializable, Ownable {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n    uint256 internal constant minCollateral = 0.5 ether;\\n\\n    bool public isShutDown = false;\\n\\n    address public weth;\\n    address public dai;\\n    address public ethDaiPool;\\n    address public feeRecipient;\\n\\n    /// @dev address of the powerPerp/weth pool\\n    address public powerPerpPool;\\n\\n    address public uniswapPositionManager;\\n\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n\\n    uint256 public shutDownEthPriceSnapshot;\\n    uint256 public normalizationFactor;\\n    uint256 public lastFundingUpdateTimestamp;\\n\\n    bool public isWethToken0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IVaultManagerNFT public vaultNFT;\\n    IWPowerPerp public wPowerPerp;\\n    IOracle public oracle;\\n\\n    /// Events\\n    event OpenVault(uint256 vaultId);\\n    event CloseVault(uint256 vaultId);\\n    event DepositCollateral(uint256 vaultId, uint256 amount, uint128 collateralId);\\n    event DepositUniPositionToken(uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(uint256 vaultId, uint256 amount, uint128 collateralId);\\n    event WithdrawUniPositionToken(uint256 vaultId, uint256 tokenId);\\n    event MintShort(uint256 amount, uint256 vaultId);\\n    event BurnShort(uint256 amount, uint256 vaultId);\\n    event UpdateOperator(uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(uint256 oldNormFactor, uint256 newNormFactor, uint256 timestamp);\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"shutdown\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"!shutdown\\\");\\n        _;\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now.\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of powerPerp.\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, address(oracle), ethDaiPool, weth, dai);\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp.\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                address(oracle),\\n                powerPerpPool,\\n                ethDaiPool,\\n                weth,\\n                dai,\\n                address(wPowerPerp),\\n                expectedNormalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized.\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is safe.\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectednormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectednormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice initialize the contract\\n     * @param _oracle oracle address\\n     * @param _vaultNFT erc721 token address representing the short position\\n     * @param _wPowerPerp erc20 token address representing non-rebasing long position\\n     * @param _weth weth address\\n     * @param _dai dai address\\n     * @param _ethDaiPool uniswap v3 pool for weth / dai\\n     * @param _powerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 nonfungible position manager address\\n     */\\n    function init(\\n        address _oracle,\\n        address _vaultNFT,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _dai,\\n        address _ethDaiPool,\\n        address _powerPerpPool,\\n        address _uniPositionManager\\n    ) public initializer {\\n        require(_oracle != address(0), \\\"Invalid oracle address\\\");\\n        require(_vaultNFT != address(0), \\\"Invalid vaultNFT address\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid power perp address\\\");\\n        require(_weth != address(0), \\\"Invalid weth address\\\");\\n        require(_dai != address(0), \\\"Invalid quote currency address\\\");\\n        require(_ethDaiPool != address(0), \\\"Invalid eth:usd pool address\\\");\\n        require(_powerPerpPool != address(0), \\\"Invalid powerperp:eth pool address\\\");\\n        require(_uniPositionManager != address(0), \\\"Invalid uni position manager\\\");\\n\\n        oracle = IOracle(_oracle);\\n        vaultNFT = IVaultManagerNFT(_vaultNFT);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n\\n        ethDaiPool = _ethDaiPool;\\n        powerPerpPool = _powerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n\\n        weth = _weth;\\n        dai = _dai;\\n\\n        normalizationFactor = 1e18;\\n        lastFundingUpdateTimestamp = block.timestamp;\\n\\n        isWethToken0 = weth < _wPowerPerp;\\n    }\\n\\n    /**\\n     * @notice put down collateral and mint wPowerPerp.\\n     * @param _vaultId the vault where you want to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp you wish to mint\\n     * @param _uniTokenId uniswap v3 position token id want to use to increase collateral ratio\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint128 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notShutdown returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice put down collateral and mint wPowerPerp.\\n     * @param _vaultId the vault where you want to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp you wish to mint\\n     * @param _uniTokenId uniswap v3 position token id want to use to increase collateral ratio\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint128 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notShutdown returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notShutdown {\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap v3 position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notShutdown {\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable notShutdown {\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, msg.sender, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @dev withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notShutdown {\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault.\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notShutdown {\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault.\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notShutdown returns (uint256) {\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice if a vault is unsafe and has a UNI NFT in it, owner call redeem the NFT to pay back some debt.\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId the vault you want to save\\n     */\\n    function reduceDebt(uint256 _vaultId) external notShutdown {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, vaultNFT.ownerOf(_vaultId), cachedNormFactor, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (powerPerp burned) * (index price) * 110% in collateral\\n     * @param _vaultId the vault you want to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual you want to repay.\\n     * @return amount of wPowerPerp repaid.\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notShutdown returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"Can not liquidate safe vault\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, vaultNFT.ownerOf(_vaultId), cachedNormFactor, true);\\n\\n        // if vault is safe after saving, pay bounty and return early.\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            payable(msg.sender).sendValue(bounty);\\n            _writeVault(_vaultId, cachedVault);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators are only getting reward from liquidation.\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it.\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(_vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault.\\n     * @dev can be revoke by setting address to 0.\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(_vaultId, _operator);\\n    }\\n\\n    /**\\n     * @dev set the recipient who will receive the fee. this should be a contract handling insurance.\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"invalid address\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @dev set the fee rate when user deposit or withdraw collateral\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis point. can't be higher than 2%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"set fee recipient first\\\");\\n        require(_newFeeRate <= 100, \\\"fee too high\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @dev shutdown the system and enable system settlement\\n     */\\n    function shutDown() external notShutdown onlyOwner {\\n        isShutDown = true;\\n        shutDownEthPriceSnapshot = oracle.getTwapSafe(ethDaiPool, weth, dai, 600);\\n    }\\n\\n    /**\\n     * @dev redeem wPowerPerp for its index value when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown {\\n        wPowerPerp.burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(\\n            _wPerpAmount,\\n            shutDownEthPriceSnapshot,\\n            normalizationFactor\\n        );\\n        payable(msg.sender).sendValue(longValue);\\n    }\\n\\n    /**\\n     * @dev redeem additional collateral from the vault when the system is shutdown\\n     * @param _vaultId vauld id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, cachedNormFactor, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            shutDownEthPriceSnapshot,\\n            normalizationFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it.\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n    }\\n\\n    /**\\n     * @dev update the normalization factor as a way to pay funding.\\n     */\\n    function applyFunding() external {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice a function to add eth into a contract, in case it got insolvent and have ensufficient eth to pay out for settlement.\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"Cannot receive eth\\\");\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return vaultNFT.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    /**\\n     * @notice wrapper function which open a vault, add collateral and mint wPowerPerp\\n     * @param _account who should receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _isWAmount if the input amount is wPowerPerp\\n     * @return vaultId\\n     * @return total minted wPowerPower amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(1e18).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, _depositAmount);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        if (wPowerPerpAmount > 0) _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function which burn wPowerPerp and redeem collateral\\n     * @param _account who should receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount to mint\\n     * @param _withdrawAmount amount of eth as collateral\\n     * @param _isWAmount true if the amount is wPowerPerp\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(1e18).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _account, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @dev create a new vault and bind it with a new short vault id.\\n     * @return id of the newly created vault\\n     * @return newly created vault memory\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = vaultNFT.mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @dev deposit uni v3 position token into a vault.\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _account account we should transfer the uni nft from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap v3 position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        _checkUniNFT(_uniTokenId);\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(_vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @dev add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _totalAmount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _totalAmount\\n    ) internal {\\n        uint256 depositAmount = _payFee(_totalAmount);\\n\\n        _vault.addEthCollateral(depositAmount);\\n        emit DepositCollateral(_vaultId, depositAmount, 0);\\n    }\\n\\n    /**\\n     * @dev remove uniswap v3 position token from the vault\\n     * @param _vault the Vault memory to update.\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(_vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @dev remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _account where to send collateral to\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n\\n        _vault.removeEthCollateral(_amount);\\n        uint256 withdrawAmount = _payFee(_amount);\\n\\n        payable(_account).sendValue(withdrawAmount);\\n\\n        emit WithdrawCollateral(_vaultId, _amount, 0);\\n    }\\n\\n    /**\\n     * @dev mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _account who should receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n\\n        _vault.addShort(_wPowerPerpAmount);\\n        wPowerPerp.mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(_wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @dev burn wPowerPerp (ERC20) from an account.\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _account who pay the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        wPowerPerp.burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(_wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _maxWPowerPerpAmount max debt amount liquidator is willing to repay\\n     * @param _liquidator address which will receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        // cast numbers to uint256 and cache them\\n        uint256 vaultShortAmount = uint256(_vault.shortAmount);\\n        uint256 vaultCollateralAmount = uint256(_vault.collateralAmount);\\n\\n        // try limiting max liquidatable amount to half of the vault\\n        (uint256 wAmountToLiquidate, uint256 collateralToPay) = _getLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            vaultShortAmount.div(2),\\n            _normalizationFactor\\n        );\\n\\n        if (vaultCollateralAmount > collateralToPay) {\\n            if (vaultCollateralAmount.sub(collateralToPay) < minCollateral) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault.\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (wAmountToLiquidate, collateralToPay) = _getLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    vaultShortAmount,\\n                    _normalizationFactor\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            require(_maxWPowerPerpAmount >= vaultShortAmount, \\\"need full liquidation\\\");\\n            collateralToPay = vaultCollateralAmount;\\n            wAmountToLiquidate = vaultShortAmount;\\n        }\\n\\n        wPowerPerp.burn(_liquidator, wAmountToLiquidate);\\n        _vault.removeShort(wAmountToLiquidate);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"dust vault left\\\");\\n\\n        // pay the liquidator\\n        payable(_liquidator).sendValue(collateralToPay);\\n\\n        return (wAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice this function will redeem the NFT in a vault\\n     * @notice and reduce debt in the target vault if there's a nft in the vault\\n     * @dev this function will be executed before liquidation if there's a NFT in the vault.\\n     * @dev when it's called by liquidate(), it pays out a small bounty to the liquidator.\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _owner where should the excess go to\\n     * @param _isLiquidation whether we're paying to the recipient the 2% discount or not.\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _normalizationFactor,\\n        bool _isLiquidation\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        // the bounty is 2% on top of total value withdrawn from the NFT.\\n        uint256 bounty;\\n        if (_isLiquidation) {\\n            uint256 totalValue = Power2Base\\n                ._getCollateralByRepayAmount(\\n                    withdrawnWPowerPerpAmount,\\n                    address(oracle),\\n                    ethDaiPool,\\n                    weth,\\n                    dai,\\n                    _normalizationFactor\\n                )\\n                .add(withdrawnEthAmount);\\n\\n            bounty = totalValue.mul(2).div(100);\\n        }\\n\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(withdrawnEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        // burn min of (shortAmount, withdrawnWPowerPerpAmount) from the vault.\\n        if (withdrawnWPowerPerpAmount > _vault.shortAmount) {\\n            uint256 excess = withdrawnWPowerPerpAmount.sub(_vault.shortAmount);\\n            withdrawnWPowerPerpAmount = _vault.shortAmount;\\n            wPowerPerp.transfer(_owner, excess);\\n        }\\n\\n        _vault.removeShort(withdrawnWPowerPerpAmount);\\n        wPowerPerp.burn(address(this), withdrawnWPowerPerpAmount);\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @dev pay the fee to the fee recipient in eth.\\n     * @param _amount the amount depositing or withdrawing\\n     * @return the remaining amount after charging fee.\\n     */\\n    function _payFee(uint256 _amount) internal returns (uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return _amount;\\n\\n        uint256 feeAmount = _amount.mul(cachedFeeRate).div(10000);\\n        payable(feeRecipient).sendValue(feeAmount);\\n        return _amount.sub(feeAmount);\\n    }\\n\\n    /**\\n     * @dev write new vault structure to storage.\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni v3 position token and get back wPerp and eth.\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from Uniswap V3 Position Manager.\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        // the decreaseLiquidity function returns the amount collectable by the owner.\\n        (uint256 amount0, uint256 amount1) = positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw weth and wPowerPerp from Uniswap V3.\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(amount0),\\n            amount1Max: uint128(amount1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        bool cacheIsWethToken0 = isWethToken0; // cache storage variable\\n        uint256 wethAmount = cacheIsWethToken0 ? collectedToken0 : collectedToken1;\\n        uint256 wPowerPerpAmount = cacheIsWethToken0 ? collectedToken1 : collectedToken0;\\n\\n        return (wethAmount, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice Update the normalization factor as a way to pay funding.\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(normalizationFactor, newNormalizationFactor, block.timestamp);\\n\\n        normalizationFactor = newNormalizationFactor;\\n        lastFundingUpdateTimestamp = block.timestamp;\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp.\\n     * @return new normalization factor if funding happens in the current block.\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = uint32(block.timestamp - lastFundingUpdateTimestamp);\\n\\n        // make sure we use the same period for mark and index, and this period won't cause revert.\\n        uint32 fairPeriod = _getFairPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor  from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            fairPeriod,\\n            address(oracle),\\n            powerPerpPool,\\n            ethDaiPool,\\n            weth,\\n            dai,\\n            address(wPowerPerp),\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(fairPeriod, address(oracle), ethDaiPool, weth, dai);\\n        uint256 rFunding = (uint256(1e18).mul(uint256(period))).div(secInDay);\\n\\n        // mul by 1e36 to keep newNormalizationFactor in 18 decimals\\n        // uint256 newNormalizationFactor = (mark * 1e36) / (((1e18 + rFunding) * mark - index * rFunding));\\n        uint256 newNormalizationFactor = (mark.mul(1e36)).div(\\n            ((uint256(1e18).add(rFunding)).mul(mark).sub(index.mul(rFunding)))\\n        );\\n\\n        return cacheNormFactor.mul(newNormalizationFactor).div(1e18);\\n    }\\n\\n    /**\\n     * @dev check that the specified uni tokenId is a valid powerPerp/weth lp token.\\n     * @param _uniTokenId uniswap v3 position token id\\n     */\\n    function _checkUniNFT(uint256 _uniTokenId) internal view {\\n        (, , address token0, address token1, , , , , , , , ) = INonfungiblePositionManager(uniswapPositionManager)\\n            .positions(_uniTokenId);\\n        // only check token0 and token1, ignore fee.\\n        // If there are multiple wPowerPerp/eth pools with different fee rate, we accept LP tokens from all of them.\\n        address wPowerPerpAddr = address(wPowerPerp); // cache storage variable\\n        address wethAddr = weth; // cache storage variable\\n        require(\\n            (token0 == wPowerPerpAddr && token1 == wethAddr) || (token1 == wPowerPerpAddr && token0 == wethAddr),\\n            \\\"Invalid nft\\\"\\n        );\\n    }\\n\\n    /**\\n     * @dev revert if the vault is insolvent, or a dust vault\\n     * @param _vault the Vault memory to update.\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"Invalid state\\\");\\n        require(!isDust, \\\"dust vault\\\");\\n    }\\n\\n    /**\\n     * @dev check that the vault is properly collateralized\\n     * @return if the vault is properly collateralized.\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @dev get the vault latest status, if it's above water or a dust vault\\n     * @param _vault the Vault memory to update.\\n     * @param _normalizationFactor normalization factor\\n     * @return if the vault is safe\\n     * @return if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 ethDaiPrice = oracle.getTwapSafe(ethDaiPool, weth, dai, 300);\\n        int24 perpPoolTick = oracle.getTimeWeightedAverageTickSafe(powerPerpPool, 300);\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                ethDaiPrice,\\n                minCollateral,\\n                perpPoolTick,\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @dev get how much wPowerPerp will be exchanged for collateral given a max wPowerPerp amount and debt ceiling\\n     * @param _maxInputWAmount max wPowerPerp amount liquidator is willing to pay\\n     * @param _maxLiquidatableWAmount max wPowerPerp amount a liquidator can take out from a vault\\n     * @param _normalizationFactor normalization factor\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getCollateralByRepayAmount(\\n            finalWAmountToLiquidate,\\n            address(oracle),\\n            ethDaiPool,\\n            weth,\\n            dai,\\n            _normalizationFactor\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a fair period that should be used to request twap for 2 pools\\n     * @dev if the period we want to use is greater than min(max_pool_1, max_pool_2),\\n     *      return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getFairPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxSafePeriod = _getMaxSafePeriod();\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n\\n    /**\\n     * @dev get the smaller of the max periods of 2 pools\\n     * @return return min(max_pool_1, max_pool_2)\\n     */\\n    function _getMaxSafePeriod() internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = oracle.getMaxPeriod(ethDaiPool);\\n        uint32 maxPeriodPool2 = oracle.getMaxPeriod(powerPerpPool);\\n        return maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n    }\\n}\\n\"\n        },\n        \"hardhat/console.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >= 0.4.22 <0.9.0;\\n\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction _sendLogPayload(bytes memory payload) private view {\\n\\t\\tuint256 payloadLength = payload.length;\\n\\t\\taddress consoleAddress = CONSOLE_ADDRESS;\\n\\t\\tassembly {\\n\\t\\t\\tlet payloadStart := add(payload, 32)\\n\\t\\t\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n\\t\\t}\\n\\t}\\n\\n\\tfunction log() internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t}\\n\\n\\tfunction logInt(int p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n}\\n\"\n        },\n        \"contracts/interfaces/IWPowerPerp.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n        },\n        \"contracts/interfaces/IVaultManagerNFT.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IVaultManagerNFT is IERC721 {\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n        },\n        \"contracts/interfaces/IOracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n        },\n        \"contracts/interfaces/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./IERC721Upgradeable.sol\\\";\\nimport \\\"./IERC721MetadataUpgradeable.sol\\\";\\nimport \\\"./IERC721EnumerableUpgradeable.sol\\\";\\nimport \\\"./IERC721ReceiverUpgradeable.sol\\\";\\nimport \\\"../../introspection/ERC165Upgradeable.sol\\\";\\nimport \\\"../../math/SafeMathUpgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableSetUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableMapUpgradeable.sol\\\";\\nimport \\\"../../utils/StringsUpgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721EnumerableUpgradeable {\\n    using SafeMathUpgradeable for uint256;\\n    using AddressUpgradeable for address;\\n    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;\\n    using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;\\n    using StringsUpgradeable for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSetUpgradeable.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMapUpgradeable.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {\\n        __Context_init_unchained();\\n        __ERC165_init_unchained();\\n        __ERC721_init_unchained(name_, symbol_);\\n    }\\n\\n    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721Upgradeable.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721Upgradeable.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721Upgradeable.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721ReceiverUpgradeable(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n    uint256[41] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/access/Ownable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/math/SafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Address.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/VaultLib.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\\\";\\n\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n\\n    struct Vault {\\n        // the address who can update the vault.\\n        address operator;\\n        // uniswap v3 position token id deposited into the vault to increase collateral ratio\\n        // 2^32 is 4,294,967,296. If Uniswap has more than 4 billion positions, our vault structure might stop working.\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // uint96 is safe enough cuz 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth.\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow.\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint96(uint256(_vault.collateralAmount).add(_amount));\\n    }\\n\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"Vault already had nft\\\");\\n        require(_tokenId != 0, \\\"invalid id\\\");\\n        _vault.NftCollateralId = uint32(_tokenId);\\n    }\\n\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint96(uint256(_vault.collateralAmount).sub(_amount));\\n    }\\n\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"Vault has no NFT\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint128(uint256(_vault.shortAmount).add(_amount));\\n    }\\n\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint128(uint256(_vault.shortAmount).sub(_amount));\\n    }\\n\\n    /**\\n     * @dev see if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethDaiPrice current eth price scaled by 1e18\\n     * @param _minCollateral min collateral need to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is above water.\\n     * @return true if the vault is considered as a dust vault.\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n        return\\n            _getVaultStatus(\\n                _vault,\\n                _positionManager,\\n                _normalizationFactor,\\n                _ethDaiPrice,\\n                _minCollateral,\\n                _wsqueethPoolTick,\\n                _isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @dev see if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethDaiPrice current eth price scaled by 1e18\\n     * @param _minCollateral min collateral need to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is above water.\\n     * @return true if the vault is considered as a dust vault.\\n     */\\n    function _getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethDaiPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(2) >= debtValueInETH.mul(3);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uni position token equivelent amount of eth.\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethDaiPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposit univ3 position token as collateral, see how much eth / squeeth the LP token has.\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from NFT as equivalent amount of collateral.\\n        uint256 equivalentCollateral = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\n        // add ETH value from NFT as collateral.\\n        return nftEthAmount.add(equivalentCollateral).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice get how much eth / squeeth the LP position is worth.\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _tokenId lp token id\\n     * @param _wsqueethPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount thie LP token is worth\\n     * @return squeethAmount the squeeth amount this LP token is worth\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 squeethAmount) {\\n        (int24 tickLower, int24 tickUpper, uint128 liquidity) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wsqueethPoolTick,\\n            liquidity\\n        );\\n        return (_isWethToken0 ? amount0 : amount1, _isWethToken0 ? amount1 : amount0);\\n    }\\n\\n    /**\\n     * @notice get the LP info and tick bond of the LP position.\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _tokenId LP token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (, , , , , int24 tickLower, int24 tickUpper, uint128 liquidity, , , , ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity);\\n    }\\n\\n    /**\\n     * @notice get how much token0 / token1 a LP position is worth.\\n     * @param _tickLower address of the uni v3 position manager\\n     * @param _tickUpper LP token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 this LP token is worth\\n     * @return amount1 the amount of token1 this LP token is worth\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from squeethPool\\n        uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(_tick);\\n\\n        // the following line is copied from the _modifyPosition function implemented by Uniswap core.\\n        // we use the same logic to determine how much token0, token1 equals to given \\\"liquidity\\\"\\n        // https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/UniswapV3Pool.sol#L306\\n\\n        // use these 2 functions directly, cuz liquidity is always positive\\n        // getAmount0Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L209\\n        // getAmount1Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L225\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/Power2Base.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {OracleLibrary} from \\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    /**\\n     * @dev return the index of the power perp in DAI, scaled by 18 decimals\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = _getTwap(_oracle, _ethDaiPool, _weth, _dai, _period);\\n        return ethDaiPrice.mul(ethDaiPrice).div(1e18);\\n    }\\n\\n    /**\\n     * @dev return the mark price of power perp in DAI, scaled by 18 decimals\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _squeethEthPool,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai,\\n        address _wsqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = _getTwap(_oracle, _ethDaiPool, _weth, _dai, _period);\\n        uint256 squeethEthPrice = _getTwap(_oracle, _squeethEthPool, address(_wsqueeth), _weth, _period);\\n\\n        return squeethEthPrice.mul(ethDaiPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @dev get fair collateral amount to pay out to a liquidator repaying _debtAmount debt\\n     * @dev the actual amount liquidator can get should have a x% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @return\\n     */\\n    function _getCollateralByRepayAmount(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = IOracle(_oracle).getTwapSafe(_ethDaiPool, _weth, _dai, 600);\\n        return _debtAmount.mul(_normalizationFactor).mul(ethDaiPrice).div(1e36);\\n    }\\n\\n    /**\\n     * @dev request twap from our oracle.\\n     * @return price scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        uint256 twap = IOracle(_oracle).getTwap(_pool, _base, _quote, _period);\\n        require(twap != 0, \\\"WAP WAP WAP\\\");\\n\\n        return twap;\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _ethSettlementPrice eth price used for settlement. scaled with 1e18\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _ethSettlementPrice,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_ethSettlementPrice).div(1e36);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n            \"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\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN 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 initializer {\\n        __Context_init_unchained();\\n    }\\n\\n    function __Context_init_unchained() internal initializer {\\n    }\\n    function _msgSender() internal view virtual returns (address payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n    uint256[50] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165Upgradeable.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721MetadataUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721EnumerableUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721EnumerableUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721ReceiverUpgradeable {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165Upgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    function __ERC165_init() internal initializer {\\n        __ERC165_init_unchained();\\n    }\\n\\n    function __ERC165_init_unchained() internal initializer {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n    uint256[49] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMathUpgradeable {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary 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    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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 EnumerableSetUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Set type with\\n    // bytes32 values.\\n    // The Set implementation uses private functions, and user-facing\\n    // implementations (such as AddressSet) are just wrappers around the\\n    // underlying Set.\\n    // This means that we can only create new EnumerableSets for types that fit\\n    // in bytes32.\\n\\n    struct Set {\\n        // Storage of set values\\n        bytes32[] _values;\\n\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableMapUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMapUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary StringsUpgradeable {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !AddressUpgradeable.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/IERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165Upgradeable {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Context.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity >=0.5.0;\\n\\nimport './LowGasSafeMath.sol';\\nimport './SafeCast.sol';\\n\\nimport './FullMath.sol';\\nimport './UnsafeMath.sol';\\nimport './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 LowGasSafeMath for uint256;\\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            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            return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96).add(amount)));\\n        } else {\\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    /// @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                (\\n                    amount <= type(uint160).max\\n                        ? (amount << FixedPoint96.RESOLUTION) / liquidity\\n                        : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)\\n                );\\n\\n            return uint256(sqrtPX96).add(quotient).toUint160();\\n        } else {\\n            uint256 quotient =\\n                (\\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            return uint160(sqrtPX96 - quotient);\\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        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @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        return\\n            liquidity < 0\\n                ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\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        return\\n            liquidity < 0\\n                ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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        },\n        \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0 <0.8.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Oracle library\\n/// @notice Provides functions to integrate with V3 pool oracle\\nlibrary OracleLibrary {\\n    /// @notice Fetches time-weighted average tick using Uniswap V3 oracle\\n    /// @param pool Address of Uniswap V3 pool that we want to observe\\n    /// @param period Number of seconds in the past to start calculating time-weighted average\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - period) to block.timestamp\\n    function consult(address pool, uint32 period) internal view returns (int24 timeWeightedAverageTick) {\\n        require(period != 0, 'BP');\\n\\n        uint32[] memory secondAgos = new uint32[](2);\\n        secondAgos[0] = period;\\n        secondAgos[1] = 0;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / period);\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % period != 0)) timeWeightedAverageTick--;\\n    }\\n\\n    /// @notice Given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick Tick value used to calculate the quote\\n    /// @param baseAmount Amount of token to be converted\\n    /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/test/StrategyFlashSwapTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n// contract\\nimport {StrategyFlashSwap} from \\\"../strategy/base/StrategyFlashSwap.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\n/// @dev this contract just to test receiving the flashswap callback\\ncontract StrategyFlashSwapTester is StrategyFlashSwap {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n    \\n    enum FlashSwapSource{\\n        FLASH_DEPOSIT\\n    }\\n\\n    uint8 public callbackData;\\n\\n    /**\\n     * @notice StrategyFlashSwapTester constructor\\n     * @param _factory uniswap v3 factory\\n     * @param _weth weth address\\n     */\\n    constructor(\\n        address _factory,\\n        address _weth\\n    ) StrategyFlashSwap(_factory, _weth) {\\n    }\\n\\n    function flashLoan(address _token0, address _token1, uint256 _amount0, uint256 _amount1, uint256 _fee1) external {\\n        initFlash(\\n            FlashParams({\\n                token0: _token0,\\n                token1: _token1,\\n                fee1: uint24(_fee1),\\n                amount0: _amount0,\\n                amount1: _amount1, \\n                fee2: uint24(0),\\n                fee3: uint24(0),\\n                flashSource: uint8(FlashSwapSource.FLASH_DEPOSIT)\\n            })\\n        );\\n    }\\n\\n    function _strategyFlash(address _token0, address _token1, uint256 _amount0, uint256 _amount1, uint8 _flashSource) internal override {\\n        require(_flashSource == uint8(FlashSwapSource.FLASH_DEPOSIT));\\n\\n        callbackData = _flashSource;\\n    }\\n}\"\n        },\n        \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\n\\n// contract\\nimport \\\"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\\\";\\nimport '@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol';\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3FlashCallback, PeripheryPayments {\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    struct FlashParams {\\n        address token0;\\n        address token1;\\n        uint24 fee1;\\n        uint256 amount0;\\n        uint256 amount1;\\n        uint24 fee2;\\n        uint24 fee3;\\n        uint8 flashSource;\\n    }\\n\\n    struct FlashCallbackData {\\n        uint256 amount0;\\n        uint256 amount1;\\n        address payer;\\n        PoolAddress.PoolKey poolKey;\\n        uint24 poolFee2;\\n        uint24 poolFee3;\\n        uint8 flashSource;\\n    }\\n\\n    constructor(\\n        address _factory,\\n        address _weth\\n    ) PeripheryImmutableState(_factory, _weth) {\\n    }\\n\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external override {\\n        FlashCallbackData memory decoded = abi.decode(data, (FlashCallbackData));\\n\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        address token0 = decoded.poolKey.token0;\\n        address token1 = decoded.poolKey.token1;\\n        uint256 amount0 = decoded.amount0;\\n        uint256 amount1 = decoded.amount1;\\n\\n        _strategyFlash(token0, token1, amount0, amount1, decoded.flashSource);\\n\\n        uint256 amount0Owed = LowGasSafeMath.add(amount0, fee0);\\n        uint256 amount1Owed = LowGasSafeMath.add(amount1, fee1);\\n\\n        TransferHelper.safeApprove(token0, address(this), amount0Owed);\\n        TransferHelper.safeApprove(token1, address(this), amount1Owed);\\n\\n        if (amount0Owed > 0) pay(token0, address(this), msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(token1, address(this), msg.sender, amount1Owed);\\n    }\\n\\n    function initFlash(FlashParams memory params) internal {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee1});\\n\\n        IUniswapV3Pool pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        pool.flash(\\n            address(this),\\n            params.amount0,\\n            params.amount1,\\n            abi.encode(\\n                FlashCallbackData({\\n                    amount0: params.amount0,\\n                    amount1: params.amount1,\\n                    payer: msg.sender,\\n                    poolKey: poolKey,\\n                    poolFee2: params.fee2,\\n                    poolFee3: params.fee3,\\n                    flashSource: params.flashSource\\n                })\\n            )\\n        );\\n    }\\n\\n    function _strategyFlash(address _token0, address _token1, uint256 _amount0, uint256 _amount1, uint8 _flashSource) internal virtual {}\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n        },\n        \"contracts/strategy/CrabStrategy.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\n// interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n// contract\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\n\\n// lib\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    uint32 public constant TWAP_PERIOD = 600;\\n\\n    /// @dev ETH:DAI uniswap V3 pool\\n    address public wSqueethEthPool;\\n    /// @dev startegy UNI v3 oracle\\n    address public oracle;\\n\\n    /// @dev latest rebalance timestamp\\n    uint256 internal _latestRebalanceTimestamp;\\n    /// @dev trading slippage limit for Uni v3\\n    uint256 internal _slippageLimit;\\n    /// @dev strategy debt amount\\n    uint256 internal _wSqueethDebt;\\n    /// @dev strategy collateral amount\\n    uint256 internal _ethCollateral;\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n\\n    /**\\n     * @notice Strategy base constructor\\n     * @dev this will open a vault in the power token contract and store vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _wSqueethEthPool eth:dai uniswap v3 address\\n     * @param _name strategy name\\n     * @param _symbol strategy symbol\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _wSqueethEthPool,\\n        string memory _name,\\n        string memory _symbol\\n    ) StrategyBase(_wSqueethController, _weth, _name, _symbol) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_wSqueethEthPool != address(0), \\\"invalid ETH:DAI address\\\");\\n\\n        oracle = _oracle;\\n        wSqueethEthPool = _wSqueethEthPool;\\n    }\\n\\n    /**\\n     * fallback function to accept eth\\n     */\\n    receive() external payable {}\\n\\n    /// TODO: implement flashswap in diff PR\\n    function flashDeposit() external payable returns (uint256, uint256) {\\n        uint256 amount = msg.value;\\n\\n        // load vars for gas optimization\\n        uint256 strategyCollateral = _ethCollateral;\\n        uint256 strategyDebt = _wSqueethDebt;\\n\\n        uint256 wSqueethToMint = calcWsqueethToMint(amount, strategyDebt, strategyCollateral);\\n        uint256 depositorStrategyShare = calcSharesToMint(amount, strategyCollateral, totalSupply());\\n\\n        // update strategy state\\n        _ethCollateral = strategyCollateral.add(amount);\\n        _wSqueethDebt = strategyDebt.add(wSqueethToMint);\\n\\n        // mint wSqueeth\\n        _mintWsqueeth(msg.sender, wSqueethToMint, 0, true);\\n        // mint LP to depositor\\n        _mint(msg.sender, depositorStrategyShare);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorStrategyShare);\\n\\n        return (wSqueethToMint, depositorStrategyShare);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev this function do not use flashswap\\n     * @return minted debt amount of LP amount\\n     */\\n    function deposit() external payable returns (uint256, uint256) {\\n        uint256 amount = msg.value;\\n\\n        // load vars for gas optimization\\n        uint256 strategyCollateral = _ethCollateral;\\n        uint256 strategyDebt = _wSqueethDebt;\\n\\n        uint256 wSqueethToMint = calcWsqueethToMint(amount, strategyDebt, strategyCollateral);\\n        uint256 depositorStrategyShare = calcSharesToMint(amount, strategyCollateral, totalSupply());\\n\\n        // update strategy state\\n        _ethCollateral = strategyCollateral.add(amount);\\n        _wSqueethDebt = strategyDebt.add(wSqueethToMint);\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWsqueeth(msg.sender, wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mint(msg.sender, depositorStrategyShare);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorStrategyShare);\\n\\n        return (wSqueethToMint, depositorStrategyShare);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev this function do not use flashswap\\n     * @param _crabAmountAmount amount of crab token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     */\\n    function withdraw(uint256 _crabAmountAmount, uint256 _wSqueethAmount) external {\\n        // load vars for gas optimization\\n        uint256 strategyCollateral = _ethCollateral;\\n        uint256 strategyDebt = _wSqueethDebt;\\n\\n        (uint256 strategyShare, uint256 ethToWithdraw) = calcCrabPercentageAndEthToWithdraw(\\n            _crabAmountAmount,\\n            strategyCollateral,\\n            totalSupply()\\n        );\\n\\n        require(_wSqueethAmount.wdiv(strategyDebt) == strategyShare, \\\"invalid ratio\\\");\\n\\n        // update strategy state\\n        _wSqueethDebt = strategyDebt.sub(_wSqueethAmount);\\n        _ethCollateral = strategyCollateral.sub(ethToWithdraw);\\n\\n        _burnWsqueeth(msg.sender, _wSqueethAmount, ethToWithdraw, false);\\n        _burn(msg.sender, _crabAmountAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmountAmount, _wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice return strategy debt amount\\n     */\\n    function getStrategyDebt() external view returns (uint256) {\\n        return _wSqueethDebt;\\n    }\\n\\n    /**\\n     * @notice return strategy collateral amount\\n     */\\n    function getStrategyCollateral() external view returns (uint256) {\\n        return _ethCollateral;\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount from specific startegy token amount\\n     * @notice _crabAmountAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromStrategyAmount(uint256 _crabAmountAmount) external view returns (uint256) {\\n        return _wSqueethDebt.wmul(_crabAmountAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice mint wSqueeth\\n     * @dev this function will keep minted wSqueeth in this contract if _keepWsqueeth == true\\n     * @param _receiver receiver address\\n     * @param _wAmount amount of wSqueeth to mint\\n     * @param _collateral amount of ETH collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWsqueeth(\\n        address _receiver,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(_vaultId, uint128(_wAmount), 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp wSqueeth = IWPowerPerp(powerTokenController.wPowerPerp());\\n            wSqueeth.transfer(_receiver, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn Wsqueeth\\n     * @dev this function will not take wSqueeth from msg.sender if _isFlashSwap == true\\n     * @param _from wSqueeth holder address\\n     * @param _amount amount to burn\\n     * @param _collateralToWithdraw amount of collateral to unlock from wSqueeth vault\\n     * @param _isFlashSwap transfer wSqueeth from holder if it is set to false\\n     */\\n    function _burnWsqueeth(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isFlashSwap\\n    ) internal {\\n        IWPowerPerp wSqueeth = IWPowerPerp(powerTokenController.wPowerPerp());\\n\\n        if (!_isFlashSwap) {\\n            wSqueeth.transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(_vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @dev calculate amount of debt to mint\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebt amount of strategy debt\\n     * @param _strategyCollateral collateral amount in strategy\\n     * @return amount of minted wSqueeth\\n     */\\n    function calcWsqueethToMint(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebt,\\n        uint256 _strategyCollateral\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethToMint;\\n\\n        if (_strategyDebt == 0) {\\n            IWPowerPerp wSqueeth = IWPowerPerp(powerTokenController.wPowerPerp());\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwapSafe(\\n                wSqueethEthPool,\\n                address(weth),\\n                address(wSqueeth),\\n                TWAP_PERIOD\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.mul(2);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta);\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebt).wdiv(_strategyCollateral);\\n        }\\n\\n        return wSqueethToMint;\\n    }\\n\\n    /**\\n     * @dev calculate amount of LP to mint for depositor\\n     * @param _amount amount of WETH deposited\\n     * @param _strategyCollateral amount of strategy collateral\\n     * @param _crabTotalSupply amount of crab token total supply\\n     * @return amount of new minted LP token\\n     */\\n    function calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateral,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateral.add(_amount));\\n\\n        uint256 depositorStrategyShare;\\n        if (_crabTotalSupply != 0) {\\n            depositorStrategyShare = (_crabTotalSupply.wmul(depositorShare)).wdiv(uint256(1e18).sub(depositorShare));\\n        } else {\\n            depositorStrategyShare = _amount;\\n        }\\n\\n        return depositorStrategyShare;\\n    }\\n\\n    /**\\n     * @dev calculate amount of crab shares and ETH to withdraw\\n     * @param _crabAmountAmount crab token amount\\n     * @param _strategyCollateral strategy total collateral amount\\n     * @param _totalSupply crab total supply amount\\n     * @return withdrawer strategy share and weth amount to withdraw\\n     */\\n    function calcCrabPercentageAndEthToWithdraw(\\n        uint256 _crabAmountAmount,\\n        uint256 _strategyCollateral,\\n        uint256 _totalSupply\\n    ) internal pure returns (uint256, uint256) {\\n        uint256 strategyShare = _crabAmountAmount.wdiv(_totalSupply);\\n        uint256 ethToWithdraw = _strategyCollateral.wmul(strategyShare);\\n\\n        return (strategyShare, ethToWithdraw);\\n    }\\n}\\n\"\n        },\n        \"contracts/strategy/base/StrategyBase.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice Base contract for PowerToken strategy\\n * @author Opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev WETH token\\n    IWETH9 public weth;\\n    /// @dev Power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev Strategy vault ID\\n    uint256 internal _vaultId;\\n\\n    /// @dev emit when strategy open short position\\n    event OpenVault(uint256 vaultId);\\n\\n    /**\\n     * @notice Strategy base constructor\\n     * @dev this will open a vault in the power token contract and store vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid power token controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = IWETH9(_weth);\\n        powerTokenController = IController(_powerTokenController);\\n\\n        _openVault();\\n    }\\n\\n    /**\\n     * @notice Get strategy vault ID in Squeeth contract\\n     * @return vauld ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return _vaultId;\\n    }\\n    \\n    /**\\n     * @notice Open a short vault\\n     * @dev Should only be called at constructor\\n     */\\n    function _openVault() internal {\\n        uint256 shortVaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n\\n        _vaultId = shortVaultId;\\n\\n        emit OpenVault(shortVaultId);\\n    }\\n}\\n\\n\"\n        },\n        \"contracts/strategy/base/StrategyMath.sol\": {\n            \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n/// @dev This is copied from DSMath contract\\n/// @dev changed contract to library\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n        },\n        \"contracts/interfaces/IController.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IController {\\n    function vaultNFT() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint128 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint128 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnOnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n        },\n        \"contracts/periphery/ShortHelper.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ncontract ShortHelper {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IVaultManagerNFT public immutable vaultNFT;\\n\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        vaultNFT = IVaultManagerNFT(_controller.vaultNFT());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * mint power perp, trade with uniswap and send back premium in eth.\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint128 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable {\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this) && _exactInputParams.tokenOut == address(weth)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) vaultNFT.transferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * buy back some squeeth and close the position.\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint128 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable {\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get squeeth in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n            \"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\"\n        },\n        \"contracts/test/ControllerTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n//import {Controller} from \\\"../core/Oracle.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n        },\n        \"contracts/mocks/MockController.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport \\\"hardhat/console.sol\\\";\\n\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    uint256 public normalizationFactor;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IVaultManagerNFT public vaultNFT;\\n\\n    function init(address _vaultNFT, address _wPowerPerp) public {\\n        require(_vaultNFT != address(0), \\\"Invalid vaultNFT address\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        vaultNFT = IVaultManagerNFT(_vaultNFT);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint128 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wSqueethMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wSqueethMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wSqueethMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = vaultNFT.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        payable(_account).sendValue(_amount);\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _squeethAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n\\n        amountToMint = _squeethAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return vaultNFT.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n}\\n\"\n        },\n        \"contracts/test/VaultTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _squeethPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 squeethAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _squeethPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockUniPositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Strings.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"contracts/core/Oracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {OracleLibrary} from \\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\";\\n\\ncontract Oracle {\\n    /**\\n     * @notice get twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwap(_pool, _base, _quote, _period, uint256(1e18));\\n    }\\n\\n    /**\\n     * @notice get twap from the uniswap pool, never revert\\n     * @dev if period is larger than the max period stored by the pool, default to the max period.\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price scaled by 1e18\\n     */\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwapSafe(_pool, _base, _quote, _period, uint256(1e18));\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap.\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consult(_pool, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap from the uniswap pool, never revert\\n     * @dev if period is larger than the max period stored by the pool, default to the max period.\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _amountIn Amount of token to be converted\\n     * @return amountOut Amount of quoteToken received for baseAmount of baseToken\\n     */\\n    function _fetchTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint256 _amountIn\\n    ) internal view returns (uint256 amountOut) {\\n        // make sure the max period we use is reasonable\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod, _amountIn);\\n    }\\n\\n    /**\\n     * @notice get twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price scaled by 1e18\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint256 _amountIn\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consult(_pool, _period);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, toUint128(_amountIn), _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap.\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: The current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // index + 1 % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n\\n    /**\\n     * @notice Cast a uint256 to a uint128, revert on overflow\\n     * @param y The uint256 to be downcasted\\n     * @return z The downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"overflow\\\");\\n    }\\n}\\n\"\n        },\n        \"contracts/test/OracleTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwapSafe(_pool, _base, _quote, period);\\n  }\\n\\n  function testToUint128(uint256 y) external returns (uint128 z) {\\n      toUint128(y);\\n  }\\n}\"\n        },\n        \"contracts/import/Uni.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"contracts/mocks/MockWSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWSqueeth is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSqueeth\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockUniswapV3Pool.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(address factory, PoolKey memory key) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockErc20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/core/WSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n/// @notice this is the ERC20 contract for long position of Squeeth\\n/// @dev this contract implements IWPowerPerp interface, makes it controllable by Controller.\\n/// @dev decimals of squeeth is chosen as 14.\\ncontract WSqueeth is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSQTH\\\") {}\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * override decimals with 14.\\n     */\\n    function decimals() public pure override returns (uint8) {\\n        return 14;\\n    }\\n\\n    function init(address _controller) external initializer {\\n        controller = _controller;\\n    }\\n\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockVaultNFTManager.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract MockVaultNFTManager is ERC721Upgradeable {\\n    uint256 public nextId = 1;\\n\\n    function mintNFT(address _recipient) external returns (uint256 tokenId) {\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function burnNFT(uint256 _tokenId) external {\\n        _burn(_tokenId);\\n    }\\n}\\n\"\n        },\n        \"contracts/core/VaultManagerNFT.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract VaultNFTManager is ERC721Upgradeable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"not controller\\\");\\n        _;\\n    }\\n\\n    function init(address _controller) public initializer {\\n        // init nft\\n        __ERC721_init(\\\"Short Opyn Squeeth Position\\\", \\\"sSqueeth\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * mint new NFT, create a new vault struct\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n}\\n\"\n        }\n    },\n    \"settings\": {\n        \"optimizer\": {\n            \"enabled\": true,\n            \"runs\": 2000\n        },\n        \"outputSelection\": {\n            \"*\": {\n                \"*\": [\n                    \"abi\",\n                    \"evm.bytecode\",\n                    \"evm.deployedBytecode\",\n                    \"evm.methodIdentifiers\",\n                    \"metadata\",\n                    \"devdoc\",\n                    \"userdoc\",\n                    \"storageLayout\",\n                    \"evm.gasEstimates\"\n                ],\n                \"\": [\"ast\"]\n            }\n        },\n        \"metadata\": {\n            \"useLiteralContent\": true\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/solcInputs/49c79f88c6e4ede6ca1f2ffd46fef4fe.json",
    "content": "{\n    \"language\": \"Solidity\",\n    \"sources\": {\n        \"contracts/core/Controller.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract Controller is Initializable, Ownable {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint32 internal constant SHUTDOWN_PERIOD = 600;\\n    uint256 internal constant SEC_IN_DAY = 86400;\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 365 days from deployment\\n    uint256 public constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    bool public isShutDown = false;\\n    bool public isSystemPaused = false;\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime = 0;\\n\\n    address public weth;\\n    address public dai;\\n    address public ethDaiPool;\\n    address public feeRecipient;\\n\\n    /// @dev address of the powerPerp/weth pool\\n    address public wPowerPerpPool;\\n\\n    address public uniswapPositionManager;\\n\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public normalizationFactor;\\n    uint256 public lastFundingUpdateTimestamp;\\n    uint256 public deployTimestamp;\\n\\n    bool public isWethToken0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IVaultManagerNFT public vaultNFT;\\n    IWPowerPerp public wPowerPerp;\\n    IOracle public oracle;\\n\\n    /// Events\\n    event OpenVault(uint256 vaultId);\\n    event CloseVault(uint256 vaultId);\\n    event DepositCollateral(uint256 vaultId, uint256 amount, uint128 collateralId);\\n    event DepositUniPositionToken(uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(uint256 vaultId, uint256 amount, uint128 collateralId);\\n    event WithdrawUniPositionToken(uint256 vaultId, uint256 tokenId);\\n    event MintShort(uint256 amount, uint256 vaultId);\\n    event BurnShort(uint256 amount, uint256 vaultId);\\n    event UpdateOperator(uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(uint256 oldNormFactor, uint256 newNormFactor, uint256 timestamp);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"paused\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"!paused\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"shutdown\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"!shutdown\\\");\\n        _;\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now.\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of powerPerp.\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, address(oracle), ethDaiPool, weth, dai);\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp.\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                address(oracle),\\n                wPowerPerpPool,\\n                ethDaiPool,\\n                weth,\\n                dai,\\n                address(wPowerPerp),\\n                expectedNormalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized.\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is safe.\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectednormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectednormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice initialize the contract\\n     * @param _oracle oracle address\\n     * @param _vaultNFT erc721 token address representing the short position\\n     * @param _wPowerPerp erc20 token address representing non-rebasing long position\\n     * @param _weth weth address\\n     * @param _dai dai address\\n     * @param _ethDaiPool uniswap v3 pool for weth / dai\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 nonfungible position manager address\\n     */\\n    function init(\\n        address _oracle,\\n        address _vaultNFT,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _dai,\\n        address _ethDaiPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) public initializer {\\n        require(_oracle != address(0), \\\"Invalid oracle address\\\");\\n        require(_vaultNFT != address(0), \\\"Invalid vaultNFT address\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid power perp address\\\");\\n        require(_weth != address(0), \\\"Invalid weth address\\\");\\n        require(_dai != address(0), \\\"Invalid quote currency address\\\");\\n        require(_ethDaiPool != address(0), \\\"Invalid eth:usd pool address\\\");\\n        require(_wPowerPerpPool != address(0), \\\"Invalid powerperp:eth pool address\\\");\\n        require(_uniPositionManager != address(0), \\\"Invalid uni position manager\\\");\\n\\n        oracle = IOracle(_oracle);\\n        vaultNFT = IVaultManagerNFT(_vaultNFT);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n\\n        ethDaiPool = _ethDaiPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n\\n        weth = _weth;\\n        dai = _dai;\\n\\n        normalizationFactor = 1e18;\\n        lastFundingUpdateTimestamp = block.timestamp;\\n        deployTimestamp = block.timestamp;\\n\\n        isWethToken0 = weth < _wPowerPerp;\\n    }\\n\\n    /**\\n     * @notice put down collateral and mint wPowerPerp.\\n     * @param _vaultId the vault where you want to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp you wish to mint\\n     * @param _uniTokenId uniswap v3 position token id want to use to increase collateral ratio\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint128 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice put down collateral and mint wPowerPerp.\\n     * @param _vaultId the vault where you want to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp you wish to mint\\n     * @param _uniTokenId uniswap v3 position token id want to use to increase collateral ratio\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint128 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused {\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap v3 position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused {\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable notPaused {\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, msg.sender, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @dev withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused {\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault.\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused {\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault.\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused returns (uint256) {\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice if a vault is unsafe and has a UNI NFT in it, owner call redeem the NFT to pay back some debt.\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId the vault you want to save\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, vaultNFT.ownerOf(_vaultId), cachedNormFactor, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (powerPerp burned) * (index price) * 110% in collateral\\n     * @param _vaultId the vault you want to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual you want to repay.\\n     * @return amount of wPowerPerp repaid.\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"Can not liquidate safe vault\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, vaultNFT.ownerOf(_vaultId), cachedNormFactor, true);\\n\\n        // if vault is safe after saving, pay bounty and return early.\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            payable(msg.sender).sendValue(bounty);\\n            _writeVault(_vaultId, cachedVault);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators are only getting reward from liquidation.\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it.\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(_vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault.\\n     * @dev can be revoke by setting address to 0.\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(_vaultId, _operator);\\n    }\\n\\n    /**\\n     * @dev set the recipient who will receive the fee. this should be a contract handling insurance.\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"invalid address\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @dev set the fee rate when user deposit or withdraw collateral\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis point. can't be higher than 2%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"set fee recipient first\\\");\\n        require(_newFeeRate <= 100, \\\"fee too high\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @dev pause and then immediately shutdown the system\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function pauseAndShutDown() external notShutdown notPaused onlyOwner {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(address(oracle), ethDaiPool, weth, dai, 600);\\n    }\\n\\n    /**\\n     * @dev shutdown the system and enable system settlement\\n     */\\n    function shutDown() external notShutdown isPaused onlyOwner {\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(address(oracle), ethDaiPool, weth, dai, 600);\\n    }\\n\\n    /**\\n     * @dev pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times, without triggering shutdown atomically\\n     */\\n    function pause() external notShutdown notPaused onlyOwner {\\n        require(pausesLeft > 0, \\\"paused too many times\\\");\\n        uint256 timeSinceDeploy = block.timestamp - deployTimestamp;\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"pause time limit exceeded\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n    }\\n\\n    /**\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external notShutdown isPaused {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"not enough paused time has passed\\\");\\n        isSystemPaused = false;\\n    }\\n\\n    /**\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external notShutdown isPaused onlyOwner {\\n        isSystemPaused = false;\\n    }\\n\\n    /**\\n     * @dev redeem wPowerPerp for its index value when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown {\\n        wPowerPerp.burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n    }\\n\\n    /**\\n     * @dev redeem additional collateral from the vault when the system is shutdown\\n     * @param _vaultId vauld id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, cachedNormFactor, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            normalizationFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it.\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n    }\\n\\n    /**\\n     * @dev update the normalization factor as a way to pay funding.\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice a function to add eth into a contract, in case it got insolvent and have ensufficient eth to pay out for settlement.\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"Cannot receive eth\\\");\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return vaultNFT.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    /**\\n     * @notice wrapper function which open a vault, add collateral and mint wPowerPerp\\n     * @param _account who should receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _isWAmount if the input amount is wPowerPerp\\n     * @return vaultId\\n     * @return total minted wPowerPower amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(1e18).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            depositAmountWithFee = _payFee(cachedVault, _account, _vaultId, wPowerPerpAmount, _depositAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        if (wPowerPerpAmount > 0) _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function which burn wPowerPerp and redeem collateral\\n     * @param _account who should receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount to mint\\n     * @param _withdrawAmount amount of eth as collateral\\n     * @param _isWAmount true if the amount is wPowerPerp\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(1e18).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _account, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @dev create a new vault and bind it with a new short vault id.\\n     * @return id of the newly created vault\\n     * @return newly created vault memory\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = vaultNFT.mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @dev deposit uni v3 position token into a vault.\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _account account we should transfer the uni nft from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap v3 position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        _checkUniNFT(_uniTokenId);\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(_vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @dev add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(_vaultId, _amount, 0);\\n    }\\n\\n    /**\\n     * @dev remove uniswap v3 position token from the vault\\n     * @param _vault the Vault memory to update.\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(_vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @dev remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _account where to send collateral to\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n\\n        _vault.removeEthCollateral(_amount);\\n        payable(_account).sendValue(_amount);\\n\\n        emit WithdrawCollateral(_vaultId, _amount, 0);\\n    }\\n\\n    /**\\n     * @dev mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _account who should receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n\\n        _vault.addShort(_wPowerPerpAmount);\\n        wPowerPerp.mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(_wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @dev burn wPowerPerp (ERC20) from an account.\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _account who pay the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        wPowerPerp.burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(_wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _maxWPowerPerpAmount max debt amount liquidator is willing to repay\\n     * @param _liquidator address which will receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        // cast numbers to uint256 and cache them\\n        uint256 vaultShortAmount = uint256(_vault.shortAmount);\\n        uint256 vaultCollateralAmount = uint256(_vault.collateralAmount);\\n\\n        // try limiting max liquidatable amount to half of the vault\\n        (uint256 wAmountToLiquidate, uint256 collateralToPay) = _getLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            vaultShortAmount.div(2),\\n            _normalizationFactor\\n        );\\n\\n        if (vaultCollateralAmount > collateralToPay) {\\n            if (vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault.\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (wAmountToLiquidate, collateralToPay) = _getLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    vaultShortAmount,\\n                    _normalizationFactor\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            require(_maxWPowerPerpAmount >= vaultShortAmount, \\\"need full liquidation\\\");\\n            collateralToPay = vaultCollateralAmount;\\n            wAmountToLiquidate = vaultShortAmount;\\n        }\\n\\n        wPowerPerp.burn(_liquidator, wAmountToLiquidate);\\n        _vault.removeShort(wAmountToLiquidate);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"dust vault left\\\");\\n\\n        // pay the liquidator\\n        payable(_liquidator).sendValue(collateralToPay);\\n\\n        return (wAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice this function will redeem the NFT in a vault\\n     * @notice and reduce debt in the target vault if there's a nft in the vault\\n     * @dev this function will be executed before liquidation if there's a NFT in the vault.\\n     * @dev when it's called by liquidate(), it pays out a small bounty to the liquidator.\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _owner where should the excess go to\\n     * @param _isLiquidation whether we're paying to the recipient the 2% discount or not.\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _normalizationFactor,\\n        bool _isLiquidation\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        // the bounty is 2% on top of total value withdrawn from the NFT.\\n        uint256 bounty;\\n        if (_isLiquidation) {\\n            uint256 totalValue = Power2Base\\n                ._getCollateralByRepayAmount(\\n                    withdrawnWPowerPerpAmount,\\n                    address(oracle),\\n                    ethDaiPool,\\n                    weth,\\n                    dai,\\n                    _normalizationFactor\\n                )\\n                .add(withdrawnEthAmount);\\n\\n            bounty = totalValue.mul(2).div(100);\\n        }\\n\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(withdrawnEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        // burn min of (shortAmount, withdrawnWPowerPerpAmount) from the vault.\\n        if (withdrawnWPowerPerpAmount > _vault.shortAmount) {\\n            uint256 excess = withdrawnWPowerPerpAmount.sub(_vault.shortAmount);\\n            withdrawnWPowerPerpAmount = _vault.shortAmount;\\n            wPowerPerp.transfer(_owner, excess);\\n        }\\n\\n        _vault.removeShort(withdrawnWPowerPerpAmount);\\n        wPowerPerp.burn(address(this), withdrawnWPowerPerpAmount);\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @dev pay the fee to the fee recipient in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update.\\n     * @param _account the user address that pays the fee (either from transferred eth or vault eth)\\n     * @param _vaultId the user vault Id\\n     * @param _wSqueethAmount the amount of wSqueeth to mint\\n     * @param _depositAmount the amount depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was removed from it\\n     */\\n    function _payFee(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wSqueethAmount,\\n        uint256 _depositAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return _depositAmount;\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getCollateralByRepayAmount(\\n            _wSqueethAmount,\\n            address(oracle),\\n            ethDaiPool,\\n            weth,\\n            dai,\\n            normalizationFactor\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            payable(feeRecipient).sendValue(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            payable(feeRecipient).sendValue(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return depositAmountAfterFee;\\n    }\\n\\n    /**\\n     * @dev write new vault structure to storage.\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni v3 position token and get back wPerp and eth.\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from Uniswap V3 Position Manager.\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        // the decreaseLiquidity function returns the amount collectable by the owner.\\n        (uint256 amount0, uint256 amount1) = positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw weth and wPowerPerp from Uniswap V3.\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(amount0),\\n            amount1Max: uint128(amount1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        bool cacheIsWethToken0 = isWethToken0; // cache storage variable\\n        uint256 wethAmount = cacheIsWethToken0 ? collectedToken0 : collectedToken1;\\n        uint256 wPowerPerpAmount = cacheIsWethToken0 ? collectedToken1 : collectedToken0;\\n\\n        return (wethAmount, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice Update the normalization factor as a way to pay funding.\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(normalizationFactor, newNormalizationFactor, block.timestamp);\\n\\n        normalizationFactor = newNormalizationFactor;\\n        lastFundingUpdateTimestamp = block.timestamp;\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp.\\n     * @return new normalization factor if funding happens in the current block.\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = uint32(block.timestamp - lastFundingUpdateTimestamp);\\n\\n        // make sure we use the same period for mark and index, and this period won't cause revert.\\n        uint32 fairPeriod = _getFairPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor  from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            fairPeriod,\\n            address(oracle),\\n            wPowerPerpPool,\\n            ethDaiPool,\\n            weth,\\n            dai,\\n            address(wPowerPerp),\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(fairPeriod, address(oracle), ethDaiPool, weth, dai);\\n        uint256 rFunding = (uint256(1e18).mul(uint256(period))).div(SEC_IN_DAY);\\n\\n        // Truncate mark to be at least 80% of index\\n        uint256 lowerBound = index.mul(4).div(5);\\n        if (mark < lowerBound) mark = lowerBound;\\n\\n        // Truncate mark to be at most 120% of index\\n        uint256 upperBound = index.mul(5).div(4);\\n        if (mark > upperBound) mark = upperBound;\\n\\n        // mul by 1e36 to keep newNormalizationFactor in 18 decimals\\n        // uint256 newNormalizationFactor = (mark * 1e36) / (((1e18 + rFunding) * mark - index * rFunding));\\n        uint256 newNormalizationFactor = (mark.mul(1e36)).div(\\n            ((uint256(1e18).add(rFunding)).mul(mark).sub(index.mul(rFunding)))\\n        );\\n\\n        return cacheNormFactor.mul(newNormalizationFactor).div(1e18);\\n    }\\n\\n    /**\\n     * @dev check that the specified uni tokenId is a valid powerPerp/weth lp token.\\n     * @param _uniTokenId uniswap v3 position token id\\n     */\\n    function _checkUniNFT(uint256 _uniTokenId) internal view {\\n        (, , address token0, address token1, , , , , , , , ) = INonfungiblePositionManager(uniswapPositionManager)\\n            .positions(_uniTokenId);\\n        // only check token0 and token1, ignore fee.\\n        // If there are multiple wPowerPerp/eth pools with different fee rate, we accept LP tokens from all of them.\\n        address wPowerPerpAddr = address(wPowerPerp); // cache storage variable\\n        address wethAddr = weth; // cache storage variable\\n        require(\\n            (token0 == wPowerPerpAddr && token1 == wethAddr) || (token1 == wPowerPerpAddr && token0 == wethAddr),\\n            \\\"Invalid nft\\\"\\n        );\\n    }\\n\\n    /**\\n     * @dev revert if the vault is insolvent, or a dust vault\\n     * @param _vault the Vault memory to update.\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"Invalid state\\\");\\n        require(!isDust, \\\"dust vault\\\");\\n    }\\n\\n    /**\\n     * @dev check that the vault is properly collateralized\\n     * @return if the vault is properly collateralized.\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @dev get the vault latest status, if it's above water or a dust vault\\n     * @param _vault the Vault memory to update.\\n     * @param _normalizationFactor normalization factor\\n     * @return if the vault is safe\\n     * @return if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwapSafe(address(oracle), ethDaiPool, weth, dai, 300);\\n        int24 perpPoolTick = oracle.getTimeWeightedAverageTickSafe(wPowerPerpPool, 300);\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                perpPoolTick,\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @dev get how much wPowerPerp will be exchanged for collateral given a max wPowerPerp amount and debt ceiling\\n     * @param _maxInputWAmount max wPowerPerp amount liquidator is willing to pay\\n     * @param _maxLiquidatableWAmount max wPowerPerp amount a liquidator can take out from a vault\\n     * @param _normalizationFactor normalization factor\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getCollateralByRepayAmount(\\n            finalWAmountToLiquidate,\\n            address(oracle),\\n            ethDaiPool,\\n            weth,\\n            dai,\\n            _normalizationFactor\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a fair period that should be used to request twap for 2 pools\\n     * @dev if the period we want to use is greater than min(max_pool_1, max_pool_2),\\n     *      return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getFairPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxSafePeriod = _getMaxSafePeriod();\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n\\n    /**\\n     * @dev get the smaller of the max periods of 2 pools\\n     * @return return min(max_pool_1, max_pool_2)\\n     */\\n    function _getMaxSafePeriod() internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = oracle.getMaxPeriod(ethDaiPool);\\n        uint32 maxPeriodPool2 = oracle.getMaxPeriod(wPowerPerpPool);\\n        return maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n    }\\n}\\n\"\n        },\n        \"hardhat/console.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >= 0.4.22 <0.9.0;\\n\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction _sendLogPayload(bytes memory payload) private view {\\n\\t\\tuint256 payloadLength = payload.length;\\n\\t\\taddress consoleAddress = CONSOLE_ADDRESS;\\n\\t\\tassembly {\\n\\t\\t\\tlet payloadStart := add(payload, 32)\\n\\t\\t\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n\\t\\t}\\n\\t}\\n\\n\\tfunction log() internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t}\\n\\n\\tfunction logInt(int p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n}\\n\"\n        },\n        \"contracts/interfaces/IWPowerPerp.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n        },\n        \"contracts/interfaces/IVaultManagerNFT.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IVaultManagerNFT is IERC721 {\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n        },\n        \"contracts/interfaces/IOracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n        },\n        \"contracts/interfaces/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./IERC721Upgradeable.sol\\\";\\nimport \\\"./IERC721MetadataUpgradeable.sol\\\";\\nimport \\\"./IERC721EnumerableUpgradeable.sol\\\";\\nimport \\\"./IERC721ReceiverUpgradeable.sol\\\";\\nimport \\\"../../introspection/ERC165Upgradeable.sol\\\";\\nimport \\\"../../math/SafeMathUpgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableSetUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableMapUpgradeable.sol\\\";\\nimport \\\"../../utils/StringsUpgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721EnumerableUpgradeable {\\n    using SafeMathUpgradeable for uint256;\\n    using AddressUpgradeable for address;\\n    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;\\n    using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;\\n    using StringsUpgradeable for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSetUpgradeable.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMapUpgradeable.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {\\n        __Context_init_unchained();\\n        __ERC165_init_unchained();\\n        __ERC721_init_unchained(name_, symbol_);\\n    }\\n\\n    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721Upgradeable.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721Upgradeable.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721Upgradeable.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721ReceiverUpgradeable(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n    uint256[41] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/access/Ownable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/math/SafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Address.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/VaultLib.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\\\";\\n\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n\\n    struct Vault {\\n        // the address who can update the vault.\\n        address operator;\\n        // uniswap v3 position token id deposited into the vault to increase collateral ratio\\n        // 2^32 is 4,294,967,296. If Uniswap has more than 4 billion positions, our vault structure might stop working.\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // uint96 is safe enough cuz 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth.\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow.\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint96(uint256(_vault.collateralAmount).add(_amount));\\n    }\\n\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"Vault already had nft\\\");\\n        require(_tokenId != 0, \\\"invalid id\\\");\\n        _vault.NftCollateralId = uint32(_tokenId);\\n    }\\n\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint96(uint256(_vault.collateralAmount).sub(_amount));\\n    }\\n\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"Vault has no NFT\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint128(uint256(_vault.shortAmount).add(_amount));\\n    }\\n\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint128(uint256(_vault.shortAmount).sub(_amount));\\n    }\\n\\n    /**\\n     * @dev see if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethDaiPrice current eth price scaled by 1e18\\n     * @param _minCollateral min collateral need to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is above water.\\n     * @return true if the vault is considered as a dust vault.\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n        return\\n            _getVaultStatus(\\n                _vault,\\n                _positionManager,\\n                _normalizationFactor,\\n                _ethDaiPrice,\\n                _minCollateral,\\n                _wsqueethPoolTick,\\n                _isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @dev see if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethDaiPrice current eth price scaled by 1e18\\n     * @param _minCollateral min collateral need to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is above water.\\n     * @return true if the vault is considered as a dust vault.\\n     */\\n    function _getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethDaiPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(2) >= debtValueInETH.mul(3);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uni position token equivelent amount of eth.\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethDaiPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposit univ3 position token as collateral, see how much eth / squeeth the LP token has.\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from NFT as equivalent amount of collateral.\\n        uint256 equivalentCollateral = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\n        // add ETH value from NFT as collateral.\\n        return nftEthAmount.add(equivalentCollateral).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice get how much eth / squeeth the LP position is worth.\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _tokenId lp token id\\n     * @param _wsqueethPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount thie LP token is worth\\n     * @return squeethAmount the squeeth amount this LP token is worth\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 squeethAmount) {\\n        (int24 tickLower, int24 tickUpper, uint128 liquidity) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wsqueethPoolTick,\\n            liquidity\\n        );\\n        return (_isWethToken0 ? amount0 : amount1, _isWethToken0 ? amount1 : amount0);\\n    }\\n\\n    /**\\n     * @notice get the LP info and tick bond of the LP position.\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _tokenId LP token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (, , , , , int24 tickLower, int24 tickUpper, uint128 liquidity, , , , ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity);\\n    }\\n\\n    /**\\n     * @notice get how much token0 / token1 a LP position is worth.\\n     * @param _tickLower address of the uni v3 position manager\\n     * @param _tickUpper LP token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 this LP token is worth\\n     * @return amount1 the amount of token1 this LP token is worth\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from squeethPool\\n        uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(_tick);\\n\\n        // the following line is copied from the _modifyPosition function implemented by Uniswap core.\\n        // we use the same logic to determine how much token0, token1 equals to given \\\"liquidity\\\"\\n        // https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/UniswapV3Pool.sol#L306\\n\\n        // use these 2 functions directly, cuz liquidity is always positive\\n        // getAmount0Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L209\\n        // getAmount1Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L225\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/Power2Base.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {OracleLibrary} from \\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint256 constant INDEX_SCALE = 1e4;\\n\\n    /**\\n     * @dev return the index of the power perp in DAI, scaled by 18 decimals\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = _getScaledTwap(_oracle, _ethDaiPool, _weth, _dai, _period);\\n        return ethDaiPrice.mul(ethDaiPrice).div(1e18);\\n    }\\n\\n    /**\\n     * @dev return the mark price of power perp in DAI, scaled by 18 decimals\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai,\\n        address _wsqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = _getScaledTwap(_oracle, _ethDaiPool, _weth, _dai, _period);\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, address(_wsqueeth), _weth, _period);\\n\\n        return wsqueethEthPrice.mul(ethDaiPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @dev get fair collateral amount to pay out to a liquidator repaying _debtAmount debt\\n     * @dev the actual amount liquidator can get should have a x% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @return\\n     */\\n    function _getCollateralByRepayAmount(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = _getScaledTwap(_oracle, _ethDaiPool, _weth, _dai, 600);\\n        return _debtAmount.mul(_normalizationFactor).mul(ethDaiPrice).div(1e36);\\n    }\\n\\n    /**\\n     * @dev request twap from our oracle, scaled down by INDEX_SCALE\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @dev request twap from our oracle, sacled down by INDEX_SCALE\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwapSafe(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwapSafe(_oracle, _pool, _base, _quote, _period);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @dev request twap from our oracle.\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        uint256 twap = IOracle(_oracle).getTwap(_pool, _base, _quote, _period);\\n        require(twap != 0, \\\"WAP WAP WAP\\\");\\n        return twap;\\n    }\\n\\n    /**\\n     * @dev request twap from our oracle.\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwapSafe(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        return IOracle(_oracle).getTwapSafe(_pool, _base, _quote, _period);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement scaled down price used for settlement.\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(1e36);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n            \"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\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN 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 initializer {\\n        __Context_init_unchained();\\n    }\\n\\n    function __Context_init_unchained() internal initializer {\\n    }\\n    function _msgSender() internal view virtual returns (address payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n    uint256[50] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165Upgradeable.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721MetadataUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721EnumerableUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721EnumerableUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721ReceiverUpgradeable {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165Upgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    function __ERC165_init() internal initializer {\\n        __ERC165_init_unchained();\\n    }\\n\\n    function __ERC165_init_unchained() internal initializer {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n    uint256[49] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMathUpgradeable {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary 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    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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 EnumerableSetUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Set type with\\n    // bytes32 values.\\n    // The Set implementation uses private functions, and user-facing\\n    // implementations (such as AddressSet) are just wrappers around the\\n    // underlying Set.\\n    // This means that we can only create new EnumerableSets for types that fit\\n    // in bytes32.\\n\\n    struct Set {\\n        // Storage of set values\\n        bytes32[] _values;\\n\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableMapUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMapUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary StringsUpgradeable {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !AddressUpgradeable.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/IERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165Upgradeable {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Context.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity >=0.5.0;\\n\\nimport './LowGasSafeMath.sol';\\nimport './SafeCast.sol';\\n\\nimport './FullMath.sol';\\nimport './UnsafeMath.sol';\\nimport './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 LowGasSafeMath for uint256;\\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            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            return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96).add(amount)));\\n        } else {\\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    /// @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                (\\n                    amount <= type(uint160).max\\n                        ? (amount << FixedPoint96.RESOLUTION) / liquidity\\n                        : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)\\n                );\\n\\n            return uint256(sqrtPX96).add(quotient).toUint160();\\n        } else {\\n            uint256 quotient =\\n                (\\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            return uint160(sqrtPX96 - quotient);\\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        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @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        return\\n            liquidity < 0\\n                ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\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        return\\n            liquidity < 0\\n                ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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        },\n        \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0 <0.8.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Oracle library\\n/// @notice Provides functions to integrate with V3 pool oracle\\nlibrary OracleLibrary {\\n    /// @notice Fetches time-weighted average tick using Uniswap V3 oracle\\n    /// @param pool Address of Uniswap V3 pool that we want to observe\\n    /// @param period Number of seconds in the past to start calculating time-weighted average\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - period) to block.timestamp\\n    function consult(address pool, uint32 period) internal view returns (int24 timeWeightedAverageTick) {\\n        require(period != 0, 'BP');\\n\\n        uint32[] memory secondAgos = new uint32[](2);\\n        secondAgos[0] = period;\\n        secondAgos[1] = 0;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / period);\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % period != 0)) timeWeightedAverageTick--;\\n    }\\n\\n    /// @notice Given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick Tick value used to calculate the quote\\n    /// @param baseAmount Amount of token to be converted\\n    /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/test/OracleTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwapSafe(_pool, _base, _quote, period);\\n  }\\n\\n  function testToUint128(uint256 y) external returns (uint128 z) {\\n      toUint128(y);\\n  }\\n}\"\n        },\n        \"contracts/core/Oracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {OracleLibrary} from \\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ncontract Oracle {\\n    using SafeMath for uint256;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwap(_pool, _base, _quote, _period);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals, never reverts\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwapSafe(_pool, _base, _quote, _period);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap.\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consult(_pool, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals, never reverts.\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period, uint256(1e18));\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return Amount of quoteToken received for _amountIn of baseToken\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint256 _amountIn\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consult(_pool, _period);\\n        return OracleLibrary.getQuoteAtTick(twapTick, toUint128(_amountIn), _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap.\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: The current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // index + 1 % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n\\n    /**\\n     * @notice Cast a uint256 to a uint128, revert on overflow\\n     * @param y The uint256 to be downcasted\\n     * @return z The downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"overflow\\\");\\n    }\\n}\\n\"\n        },\n        \"contracts/interfaces/IERC20Detailed.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n        },\n        \"contracts/periphery/ShortHelper.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ncontract ShortHelper {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IVaultManagerNFT public immutable vaultNFT;\\n\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        vaultNFT = IVaultManagerNFT(_controller.vaultNFT());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * mint power perp, trade with uniswap and send back premium in eth.\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint128 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable {\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this) && _exactInputParams.tokenOut == address(weth)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) vaultNFT.transferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * buy back some squeeth and close the position.\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint128 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable {\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get squeeth in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"contracts/interfaces/IController.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IController {\\n    function vaultNFT() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint128 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint128 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnOnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n            \"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\"\n        },\n        \"contracts/strategy/CrabStrategy.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// contract\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    uint32 public constant TWAP_PERIOD = 600;\\n\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap V3 pool\\n    address public ethWSqueethPool;\\n    /// @dev startegy UNI v3 oracle\\n    address public oracle;\\n\\n    /// @dev latest rebalance timestamp\\n    uint256 internal _latestRebalanceTimestamp;\\n    /// @dev trading slippage limit for Uni v3\\n    uint256 internal _slippageLimit;\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(\\n        address indexed depositor,\\n        uint256 depositedAmount,\\n        uint256 borrowedAmount,\\n        uint256 totalDepositedAmount,\\n        uint256 tradedAmountOut\\n    );\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n\\n    /**\\n     * @notice Strategy base constructor\\n     * @dev this will open a vault in the power token contract and store vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:dai uniswap v3 address\\n     * @param _name strategy name\\n     * @param _symbol strategy symbol\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        string memory _name,\\n        string memory _symbol\\n    ) StrategyBase(_wSqueethController, _weth, _name, _symbol) StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash deposit\\n     * @dev this function sell minted WSqueeth for _ethToBorrow\\n     * @param _ethToDeposit ETH sent from depositor\\n     * @param _ethToBorrow ETH to flashswap on uni v3\\n     */\\n    function flashDeposit(uint256 _ethToDeposit, uint256 _ethToBorrow) external payable {\\n        require(msg.value > _ethToDeposit, \\\"Need some buffer\\\");\\n\\n        uint256 wSqueethToMint = _calcWsqueethToMint(\\n            _ethToDeposit.add(_ethToBorrow),\\n            _strategyDebt,\\n            _strategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.add(_ethToBorrow).sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            _ethToDeposit.add(_ethToBorrow)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, _ethToBorrow, msg.value, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw\\n     * @dev this function will borrow wSqueeth amount and repay for selling some of the ETH collateral\\n     * @param _crabAmount crab token amount to burn\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external {\\n        uint256 exactWSqueethNeeded = _strategyDebt.wmul(_crabAmount).wdiv(totalSupply());\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            _crabAmount\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev this function do not use flashswap\\n     * @return minted debt amount of LP amount\\n     */\\n    function deposit() external payable returns (uint256, uint256) {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev this function do not use flashswap\\n     * @param _crabAmount amount of crab token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     */\\n    function withdraw(uint256 _crabAmount, uint256 _wSqueethAmount) external payable {\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, _wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, _wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice startegy uniswap flash swap\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _tokenIn token IN address\\n     * @param _tokenOut token OUT address\\n     * @param _fee uniswap pool fee\\n     * @param _amountToPay amount to pay back for flashswap\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountToPay,\\n        uint256 _callAmount,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            // convert WETH to ETH as Uniswap use WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            _deposit(_caller, _callAmount, true);\\n\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        }\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                _callAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @dev deposit into strategy\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if this function is called by flash deposit\\n     * @return minted amount of WSqueeth and minted CRAB token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        // load vars for gas optimization\\n        uint256 strategyCollateral = _strategyCollateral;\\n        uint256 strategyDebt = _strategyDebt;\\n\\n        uint256 wSqueethToMint = _calcWsqueethToMint(_amount, strategyDebt, strategyCollateral);\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount, strategyCollateral, totalSupply());\\n\\n        // update strategy state\\n        _strategyCollateral = strategyCollateral.add(_amount);\\n        _strategyDebt = strategyDebt.add(wSqueethToMint);\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev this function do not use flashswap\\n     * @param _crabAmount amount of crab token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        // load vars for gas optimization\\n        uint256 strategyCollateral = _strategyCollateral;\\n        uint256 strategyDebt = _strategyDebt;\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        require(_wSqueethAmount.wdiv(strategyDebt) == strategyShare, \\\"invalid ratio\\\");\\n\\n        // update strategy state\\n        _strategyDebt = strategyDebt.sub(_wSqueethAmount);\\n        _strategyCollateral = strategyCollateral.sub(ethToWithdraw);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount from crab token amount\\n     * @notice _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @dev calculate amount of debt to mint\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth\\n     */\\n    function _calcWsqueethToMint(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethToMint;\\n\\n        if (_strategyDebtAmount == 0) {\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwapSafe(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD);\\n            uint256 squeethDelta = wSqueethEthPrice.mul(2);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta);\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(_strategyCollateralAmount);\\n        }\\n\\n        return wSqueethToMint;\\n    }\\n\\n    /**\\n     * @dev calculate amount of LP to mint for depositor\\n     * @param _amount amount of WETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply amount of crab token total supply\\n     * @return amount of new minted LP token\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        uint256 depositorCrabAmount;\\n        if (_crabTotalSupply != 0) {\\n            depositorCrabAmount = (_crabTotalSupply.wmul(depositorShare)).wdiv(uint256(1e18).sub(depositorShare));\\n        } else {\\n            depositorCrabAmount = _amount;\\n        }\\n\\n        return depositorCrabAmount;\\n    }\\n\\n    /**\\n     * @notice calc crab ratio\\n     * @param _crabAmount crab token amount\\n     * @param _totalSupply crab total supply\\n     * @return ratio\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calc ETH to withdraw from strategy\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n        },\n        \"contracts/strategy/base/StrategyBase.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\n// import {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice Base contract for PowerToken strategy\\n * @author Opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev Power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev Strategy vault ID\\n    uint256 internal immutable _vaultId;\\n    /// @dev strategy debt amount\\n    uint256 internal _strategyDebt;\\n    /// @dev strategy collateral amount\\n    uint256 internal _strategyCollateral;\\n\\n    /**\\n     * @notice Strategy base constructor\\n     * @dev this will open a vault in the power token contract and store vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid power token controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        _vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice Get strategy vault ID in Squeeth contract\\n     * @return vauld ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return _vaultId;\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount\\n     * @return debt amount\\n     */\\n    function getStrategyDebt() external view returns (uint256) {\\n        return _strategyDebt;\\n    }\\n\\n    /**\\n     * @notice get strategy collateral amount\\n     * @return collateral amount\\n     */\\n    function getStrategyCollateral() external view returns (uint256) {\\n        return _strategyCollateral;\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp\\n     * @param _to receiver address\\n     * @param _wAmount amount of wPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(_vaultId, uint128(_wAmount), 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp\\n     * @dev this function will not take wSqueeth from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount to burn\\n     * @param _collateralToWithdraw amount of collateral to unlock from WPowerPerp vault\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(_vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount from specific startegy token amount\\n     * @notice _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        return _strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n}\\n\\n\"\n        },\n        \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap v3 factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        uint256 callAmount;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice Uniswap v3 swap callback function\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callAmount, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact in flash swap\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to get\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to get\\n     * @param _callSource function call source\\n     * @param _callAmount arbitrary amount assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, uint256 _callAmount) internal {\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callAmount: _callAmount})\\n        );\\n\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact out flash swap\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to get\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to get\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _callAmount arbitrary amount assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, uint256 _callAmount) internal {\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callAmount: _callAmount})\\n        );\\n\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @dev function to get called by uniswap callback\\n     * @param _caller initial strategy function caller\\n     * @param _tokenIn token address sold\\n     * @param _tokenOut token address bought\\n     * @param _fee pool fee\\n     * @param _amountToPay amount to pay for the pool second token\\n     * @param _callAmount arbitrary amount assigned with the flashswap call \\n     * @param _callSource function call source\\n     */\\n    function _strategyFlash(address _caller, address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountToPay, uint256 _callAmount, uint8 _callSource) internal virtual {}\\n\\n    /// @dev Performs a single exact input swap\\n    function _exactInputInternal(\\n        uint256 amountIn,\\n        address recipient,\\n        uint160 sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                recipient,\\n                zeroForOne,\\n                amountIn.toInt256(),\\n                sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /// @dev Performs a single exact output swap\\n    function _exactOutputInternal(\\n        uint256 amountOut,\\n        address recipient,\\n        uint160 sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                recipient,\\n                zeroForOne,\\n                -amountOut.toInt256(),\\n                sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (sqrtPriceLimitX96 == 0) require(amountOutReceived == amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /// @dev Returns the pool for the given token pair and fee. The pool contract may or may not exist.\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n        },\n        \"contracts/strategy/base/StrategyMath.sol\": {\n            \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n/// @dev This is copied from DSMath contract, changed contract to library\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockWSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWSqueeth is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSqueeth\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockUniswapV3Pool.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(address factory, PoolKey memory key) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockErc20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockUniPositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Strings.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockController.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport \\\"hardhat/console.sol\\\";\\n\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    uint256 public normalizationFactor;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IVaultManagerNFT public vaultNFT;\\n\\n    function init(address _vaultNFT, address _wPowerPerp) public {\\n        require(_vaultNFT != address(0), \\\"Invalid vaultNFT address\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        vaultNFT = IVaultManagerNFT(_vaultNFT);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint128 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wSqueethMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wSqueethMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wSqueethMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = vaultNFT.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        payable(_account).sendValue(_amount);\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _squeethAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n\\n        amountToMint = _squeethAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return vaultNFT.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n}\\n\"\n        },\n        \"contracts/test/VaultTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _squeethPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 squeethAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _squeethPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/import/Uni.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"contracts/core/WSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n/// @notice this is the ERC20 contract for long position of Squeeth\\n/// @dev this contract implements IWPowerPerp interface, makes it controllable by Controller.\\n/// @dev decimals of squeeth is chosen as 14.\\ncontract WSqueeth is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSQTH\\\") {}\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"not controller\\\");\\n        _;\\n    }\\n\\n    function init(address _controller) external initializer {\\n        controller = _controller;\\n    }\\n\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/test/ControllerTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n//import {Controller} from \\\"../core/Oracle.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n        },\n        \"contracts/mocks/MockVaultNFTManager.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract MockVaultNFTManager is ERC721Upgradeable {\\n    uint256 public nextId = 1;\\n\\n    function mintNFT(address _recipient) external returns (uint256 tokenId) {\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function burnNFT(uint256 _tokenId) external {\\n        _burn(_tokenId);\\n    }\\n}\\n\"\n        },\n        \"contracts/core/VaultManagerNFT.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract VaultNFTManager is ERC721Upgradeable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"not controller\\\");\\n        _;\\n    }\\n\\n    function init(address _controller) public initializer {\\n        // init nft\\n        __ERC721_init(\\\"Short Opyn Squeeth Position\\\", \\\"sSqueeth\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * mint new NFT, create a new vault struct\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n}\\n\"\n        }\n    },\n    \"settings\": {\n        \"optimizer\": {\n            \"enabled\": true,\n            \"runs\": 2000\n        },\n        \"outputSelection\": {\n            \"*\": {\n                \"*\": [\n                    \"abi\",\n                    \"evm.bytecode\",\n                    \"evm.deployedBytecode\",\n                    \"evm.methodIdentifiers\",\n                    \"metadata\",\n                    \"devdoc\",\n                    \"userdoc\",\n                    \"storageLayout\",\n                    \"evm.gasEstimates\"\n                ],\n                \"\": [\"ast\"]\n            }\n        },\n        \"metadata\": {\n            \"useLiteralContent\": true\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/solcInputs/4ad189f955354b6f5c4f3b0e4a7b5326.json",
    "content": "{\n    \"language\": \"Solidity\",\n    \"sources\": {\n        \"contracts/core/Controller.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\nimport {IWSqueeth} from \\\"../interfaces/IWSqueeth.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract Controller is Initializable, Ownable {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n    bool public isShutDown = false;\\n    uint256 public shutDownEthPriceSnapshot;\\n\\n    address public weth;\\n    address public dai;\\n\\n    address public ethUSDPool;\\n    address public wSqueethEthPool;\\n\\n    uint256 public normalizationFactor;\\n    uint256 public lastFundingUpdateTimestamp;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IVaultManagerNFT public vaultNFT;\\n    IWSqueeth public wsqueeth;\\n    IOracle public oracle;\\n\\n    /// Events\\n    event OpenVault(uint256 vaultId);\\n    event CloseVault(uint256 vaultId);\\n    event DepositCollateral(uint256 vaultId, uint128 amount, uint128 collateralId);\\n    event WithdrawCollateral(uint256 vaultId, uint256 amount, uint128 collateralId);\\n    event addShort(uint256 amount, uint256 vaultId);\\n    event removeShort(uint256 amount, uint256 vaultId);\\n    event UpdateOperator(uint256 vaultId, address operator);\\n    event Liquidate(uint256 vaultId, uint256 debtAmount, uint256 collateralToSell);\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"shutdown\\\");\\n        _;\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * init controller with squeeth and short NFT address\\n     */\\n    function init(\\n        address _oracle,\\n        address _vaultNFT,\\n        address _squeeth,\\n        address _weth,\\n        address _dai,\\n        address _ethUsdPool,\\n        address _wSqueethEthPool\\n    ) public initializer {\\n        require(_oracle != address(0), \\\"Invalid oracle address\\\");\\n        require(_vaultNFT != address(0), \\\"Invalid vaultNFT address\\\");\\n        require(_squeeth != address(0), \\\"Invalid squeeth address\\\");\\n        require(_ethUsdPool != address(0), \\\"Invalid eth:usd pool address\\\");\\n        require(_wSqueethEthPool != address(0), \\\"Invalid wsqueeth:usd pool address\\\");\\n\\n        oracle = IOracle(_oracle);\\n        vaultNFT = IVaultManagerNFT(_vaultNFT);\\n        wsqueeth = IWSqueeth(_squeeth);\\n\\n        ethUSDPool = _ethUsdPool;\\n        wSqueethEthPool = _wSqueethEthPool;\\n\\n        weth = _weth;\\n        dai = _dai;\\n\\n        normalizationFactor = 1e18;\\n        lastFundingUpdateTimestamp = block.timestamp;\\n    }\\n\\n    /**\\n     * put down collateral and mint squeeth.\\n     * This mints an amount of rSqueeth.\\n     */\\n    function mint(uint256 _vaultId, uint128 _mintAmount)\\n        external\\n        payable\\n        notShutdown\\n        returns (uint256, uint256 _wSqueethMinted)\\n    {\\n        _applyFunding();\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            _wSqueethMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n        _checkVault(_vaultId);\\n        return (_vaultId, _wSqueethMinted);\\n    }\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notShutdown {\\n        _applyFunding();\\n        _addEthCollateral(_vaultId, msg.value);\\n    }\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable notShutdown {\\n        _applyFunding();\\n        _withdrawCollateral(msg.sender, _vaultId, _amount);\\n        _checkVault(_vaultId);\\n    }\\n\\n    /**\\n     * burn squueth and remove collateral from a vault.\\n     * This burns an amount of wSqueeth.\\n     */\\n    function burn(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external notShutdown {\\n        _applyFunding();\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        _checkVault(_vaultId);\\n    }\\n\\n    function liquidate(uint256 _vaultId, uint256 _debtAmount) external notShutdown {\\n        _applyFunding();\\n\\n        require(!_isVaultSafe(vaults[_vaultId]), \\\"Can not liquidate\\\");\\n\\n        uint256 indexPrice = _getIndex(600); // get index price using TWAP furing last 10min\\n        uint256 collateralToSell = (indexPrice * _debtAmount) / 1e18;\\n        // tood: add 10% of collateral\\n\\n        wsqueeth.burn(msg.sender, _debtAmount);\\n        payable(msg.sender).sendValue(collateralToSell);\\n\\n        emit Liquidate(_vaultId, _debtAmount, collateralToSell);\\n    }\\n\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return _getIndex(_period);\\n    }\\n\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return _getDenormalizedMark(_period);\\n    }\\n\\n    /**\\n     * Authorize an address to modify the vault. Can be revoke by setting address to 0.\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(_vaultId, _operator);\\n    }\\n\\n    /**\\n     * shutdown the system and enable redeeming long and short\\n     */\\n    function shutDown() external onlyOwner {\\n        require(!isShutDown, \\\"shutdown\\\");\\n        isShutDown = true;\\n        shutDownEthPriceSnapshot = oracle.getTwapSafe(ethUSDPool, weth, dai, 600);\\n    }\\n\\n    function redeemLong(uint256 _wsqueethAmount) external {\\n        require(isShutDown, \\\"!shutdown\\\");\\n        wsqueeth.burn(msg.sender, _wsqueethAmount);\\n        // convert wSqueeth amount to real short position with normalizationFactor\\n        uint256 longValue = _wsqueethAmount.mul(normalizationFactor).mul(shutDownEthPriceSnapshot).div(1e36);\\n        payable(msg.sender).sendValue(longValue);\\n    }\\n\\n    function redeemShort(uint256 _vaultId) external {\\n        require(isShutDown, \\\"!shutdown\\\");\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n\\n        uint256 _shortSqueethAmount = vaults[_vaultId].shortAmount;\\n        uint256 debt = _shortSqueethAmount.mul(shutDownEthPriceSnapshot).mul(normalizationFactor).div(1e36);\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = vaults[_vaultId].collateralAmount.sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it.\\n        vaults[_vaultId].shortAmount = 0;\\n        vaults[_vaultId].collateralAmount = 0;\\n\\n        // todo: handle uni nft collateral\\n\\n        payable(msg.sender).sendValue(excess);\\n    }\\n\\n    /**\\n     * Update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * a function to add eth into a contract, in case it got insolvent and have ensufficient eth to pay out.\\n     */\\n    function donate() external payable {}\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return vaultNFT.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    /**\\n     * create a new vault and bind it with a new NFT id.\\n     */\\n    function _openVault(address _recipient) internal returns (uint256 vaultId) {\\n        vaultId = vaultNFT.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(vaultId);\\n    }\\n\\n    /**\\n     * add collateral to a vault\\n     */\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        vaults[_vaultId].addEthCollateral(uint128(_amount));\\n        emit DepositCollateral(_vaultId, uint128(_amount), 0);\\n    }\\n\\n    /**\\n     * remove collateral from the vault\\n     */\\n    function _withdrawCollateral(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n        vaults[_vaultId].removeEthCollateral(_amount);\\n        payable(_account).sendValue(_amount);\\n        emit WithdrawCollateral(_vaultId, _amount, 0);\\n    }\\n\\n    /**\\n     * mint wsqueeth (ERC20) to an account\\n     */\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _squeethAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n\\n        amountToMint = _squeethAmount.mul(1e18).div(normalizationFactor);\\n\\n        vaults[_vaultId].addShort(amountToMint);\\n\\n        emit addShort(amountToMint, _vaultId);\\n\\n        wsqueeth.mint(_account, amountToMint);\\n    }\\n\\n    /**\\n     * burn wsqueeth (ERC20) from an account.\\n     */\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        vaults[_vaultId].removeShort(_amount);\\n        emit removeShort(_amount, _vaultId);\\n\\n        wsqueeth.burn(_account, _amount);\\n    }\\n\\n    /**\\n     * Update the normalized factor as a way to pay funding.\\n     */\\n    function _applyFunding() internal {\\n        uint32 period = uint32(block.timestamp - lastFundingUpdateTimestamp);\\n\\n        // make sure we use the same period for mark and index, and this period won't cause revert.\\n        uint32 fairPeriod = _getFairPeriodForOracle(period);\\n\\n        uint256 mark = _getDenormalizedMark(fairPeriod);\\n        uint256 index = _getIndex(fairPeriod);\\n        uint256 rFunding = (uint256(1e18).mul(uint256(period))).div(secInDay);\\n\\n        // mul by 1e36 to keep newNormalizationFactor in 18 decimals\\n        // uint256 newNormalizationFactor = (mark * 1e36) / (((1e18 + rFunding) * mark - index * rFunding));\\n        uint256 newNormalizationFactor = (mark.mul(1e36)).div(\\n            ((uint256(1e18).add(rFunding)).mul(mark).sub(index.mul(rFunding)))\\n        );\\n\\n        normalizationFactor = normalizationFactor.mul(newNormalizationFactor).div(1e18);\\n        lastFundingUpdateTimestamp = block.timestamp;\\n    }\\n\\n    /**\\n     * @dev check that the vault is solvent and has enough collateral.\\n     */\\n    function _checkVault(uint256 _vaultId) internal view {\\n        if (_vaultId == 0) return;\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n\\n        require(_isVaultSafe(vault), \\\"Invalid state\\\");\\n    }\\n\\n    function _isVaultSafe(VaultLib.Vault memory _vault) internal view returns (bool) {\\n        // todo: make sure the period here is safe to request in oracle.\\n        // need to be shorter than the max that oracle can handle\\n        uint32 period = 1;\\n        uint256 ethUsdPrice = _getTwap(ethUSDPool, weth, dai, period);\\n\\n        return VaultLib.isProperlyCollateralized(_vault, normalizationFactor, ethUsdPrice);\\n    }\\n\\n    function _getIndex(uint32 _period) internal view returns (uint256) {\\n        uint256 ethUSDPrice = _getTwap(ethUSDPool, weth, dai, _period);\\n        return ethUSDPrice.mul(ethUSDPrice).div(1e18);\\n    }\\n\\n    function _getDenormalizedMark(uint32 _period) public view returns (uint256) {\\n        uint256 ethUSDPrice = _getTwap(ethUSDPool, weth, dai, _period);\\n        uint256 squeethEthPrice = _getTwap(wSqueethEthPool, address(wsqueeth), weth, _period);\\n\\n        return squeethEthPrice.mul(ethUSDPrice).div(normalizationFactor);\\n    }\\n\\n    function _getFairPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxSafePeriod = _getMaxSafePeriod();\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n\\n    /**\\n     * return the smaller of the max periods of 2 pools\\n     */\\n    function _getMaxSafePeriod() internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = oracle.getMaxPeriod(ethUSDPool);\\n        uint32 maxPeriodPool2 = oracle.getMaxPeriod(wSqueethEthPool);\\n        return maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n    }\\n\\n    function _getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        uint256 twap = oracle.getTwap(_pool, _base, _quote, _period);\\n        require(twap != 0, \\\"WAP WAP WAP\\\");\\n\\n        return twap;\\n    }\\n}\\n\"\n        },\n        \"hardhat/console.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >= 0.4.22 <0.9.0;\\n\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction _sendLogPayload(bytes memory payload) private view {\\n\\t\\tuint256 payloadLength = payload.length;\\n\\t\\taddress consoleAddress = CONSOLE_ADDRESS;\\n\\t\\tassembly {\\n\\t\\t\\tlet payloadStart := add(payload, 32)\\n\\t\\t\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n\\t\\t}\\n\\t}\\n\\n\\tfunction log() internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t}\\n\\n\\tfunction logInt(int p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n}\\n\"\n        },\n        \"contracts/interfaces/IWSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWSqueeth is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n        },\n        \"contracts/interfaces/IVaultManagerNFT.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IVaultManagerNFT is IERC721 {\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n        },\n        \"contracts/interfaces/IOracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./IERC721Upgradeable.sol\\\";\\nimport \\\"./IERC721MetadataUpgradeable.sol\\\";\\nimport \\\"./IERC721EnumerableUpgradeable.sol\\\";\\nimport \\\"./IERC721ReceiverUpgradeable.sol\\\";\\nimport \\\"../../introspection/ERC165Upgradeable.sol\\\";\\nimport \\\"../../math/SafeMathUpgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableSetUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableMapUpgradeable.sol\\\";\\nimport \\\"../../utils/StringsUpgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721EnumerableUpgradeable {\\n    using SafeMathUpgradeable for uint256;\\n    using AddressUpgradeable for address;\\n    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;\\n    using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;\\n    using StringsUpgradeable for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSetUpgradeable.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMapUpgradeable.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {\\n        __Context_init_unchained();\\n        __ERC165_init_unchained();\\n        __ERC721_init_unchained(name_, symbol_);\\n    }\\n\\n    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721Upgradeable.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721Upgradeable.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721Upgradeable.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721ReceiverUpgradeable(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n    uint256[41] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/access/Ownable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/math/SafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Address.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/VaultLib.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    /** \\n     collateral is always eth, \\n     while we can also add a Uniswap V3 NFT in to the vault to reduce collateral amount.\\n    */\\n    struct Vault {\\n        address operator;\\n        // address NFTCollateralAddress; // the uni v3 pool address, may not need this if we only support ETH / SQUEETH;\\n        uint256 NftCollateralId; // the uni v3 pool NFT id\\n        uint256 collateralAmount;\\n        uint256 shortAmount;\\n    }\\n\\n    function isEmpty(Vault storage _vault) internal view returns (bool) {\\n        return _vault.collateralAmount == 0 && _vault.shortAmount == 0;\\n    }\\n\\n    function addEthCollateral(Vault storage _vault, uint256 _amount) internal {\\n        _vault.collateralAmount = _vault.collateralAmount.add(_amount);\\n    }\\n\\n    function removeEthCollateral(Vault storage _vault, uint256 _amount) internal {\\n        _vault.collateralAmount = _vault.collateralAmount.sub(_amount);\\n    }\\n\\n    function addShort(Vault storage _vault, uint256 _amount) internal {\\n        _vault.shortAmount = _vault.shortAmount.add(_amount);\\n    }\\n\\n    function removeShort(Vault storage _vault, uint256 _amount) internal {\\n        _vault.shortAmount = _vault.shortAmount.sub(_amount);\\n    }\\n\\n    function isProperlyCollateralized(\\n        Vault memory _vault,\\n        uint256 _normalizedFactor,\\n        uint256 _ethUsdPrice\\n    ) internal pure returns (bool) {\\n        if (_vault.shortAmount == 0) return true;\\n        return _isProperlyCollateralized(_vault, _normalizedFactor, _ethUsdPrice);\\n    }\\n\\n    function _isProperlyCollateralized(\\n        Vault memory _vault,\\n        uint256 _normalizedFactor,\\n        uint256 _ethUsdPrice\\n    ) internal pure returns (bool) {\\n        uint256 debtValueInETH = _vault.shortAmount.mul(_normalizedFactor).mul(_ethUsdPrice).div(1e36);\\n        return _vault.collateralAmount.mul(2) >= debtValueInETH.mul(3);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n            \"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\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN 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 initializer {\\n        __Context_init_unchained();\\n    }\\n\\n    function __Context_init_unchained() internal initializer {\\n    }\\n    function _msgSender() internal view virtual returns (address payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n    uint256[50] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165Upgradeable.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721MetadataUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721EnumerableUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721EnumerableUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721ReceiverUpgradeable {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165Upgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    function __ERC165_init() internal initializer {\\n        __ERC165_init_unchained();\\n    }\\n\\n    function __ERC165_init_unchained() internal initializer {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n    uint256[49] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMathUpgradeable {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary 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    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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 EnumerableSetUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Set type with\\n    // bytes32 values.\\n    // The Set implementation uses private functions, and user-facing\\n    // implementations (such as AddressSet) are just wrappers around the\\n    // underlying Set.\\n    // This means that we can only create new EnumerableSets for types that fit\\n    // in bytes32.\\n\\n    struct Set {\\n        // Storage of set values\\n        bytes32[] _values;\\n\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableMapUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMapUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary StringsUpgradeable {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !AddressUpgradeable.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/IERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165Upgradeable {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Context.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n        },\n        \"contracts/mocks/MockWSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWSqueeth is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSqueeth\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockErc20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/interfaces/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n        },\n        \"contracts/periphery/ShortHelper.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IWSqueeth} from \\\"../interfaces/IWSqueeth.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\ncontract ShortHelper {\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWSqueeth public immutable wsqueeth;\\n    IWETH9 public immutable weth;\\n    IVaultManagerNFT public immutable vaultNFT;\\n\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n\\n        IWSqueeth _wsqueeth = IWSqueeth(_controller.wsqueeth());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wsqueeth.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        vaultNFT = IVaultManagerNFT(_controller.vaultNFT());\\n        weth = _weth;\\n        controller = _controller;\\n        wsqueeth = _wsqueeth;\\n    }\\n\\n    /**\\n     * mint squeeth, trade with uniswap and send back premium in eth.\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint128 _shortSqueethAmount,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable {\\n        // vaultNFT.transferFrom(msg.sender, address(this), _vaultId);\\n        (uint256 vaultId, uint256 wsqueethAmount) = controller.mint{value: msg.value}(_vaultId, _shortSqueethAmount);\\n        _exactInputParams.amountIn = wsqueethAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this) && _exactInputParams.tokenOut == address(weth)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) vaultNFT.transferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * buy back some squeeth and close the position.\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _removeShortAmount,\\n        uint128 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable {\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get squeeth in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burn(_vaultId, _removeShortAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value - amountIn);\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"contracts/interfaces/IController.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IController {\\n    function vaultNFT() external view returns (address);\\n\\n    function wsqueeth() external view returns (address);\\n\\n    /**\\n     * put down collateral and mint squeeth.\\n     */\\n    function mint(uint256 _vaultId, uint128 _mintAmount)\\n        external\\n        payable\\n        returns (uint256 vaultId, uint256 _wSqueethMinted);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    /**\\n     * burn squueth and remove collateral from a vault.\\n     */\\n    function burn(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n            \"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\"\n        },\n        \"contracts/core/WSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\ncontract WSqueeth is ERC20, Initializable {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSqueeth\\\") {}\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * override decimals with 14.\\n     */\\n    function decimals() public pure override returns (uint8) {\\n        return 14;\\n    }\\n\\n    function init(address _controller) external initializer {\\n        controller = _controller;\\n    }\\n\\n    function mint(address _account, uint256 _amount) external onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function _getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0 <0.8.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Oracle library\\n/// @notice Provides functions to integrate with V3 pool oracle\\nlibrary OracleLibrary {\\n    /// @notice Fetches time-weighted average tick using Uniswap V3 oracle\\n    /// @param pool Address of Uniswap V3 pool that we want to observe\\n    /// @param period Number of seconds in the past to start calculating time-weighted average\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - period) to block.timestamp\\n    function consult(address pool, uint32 period) internal view returns (int24 timeWeightedAverageTick) {\\n        require(period != 0, 'BP');\\n\\n        uint32[] memory secondAgos = new uint32[](2);\\n        secondAgos[0] = period;\\n        secondAgos[1] = 0;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / period);\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % period != 0)) timeWeightedAverageTick--;\\n    }\\n\\n    /// @notice Given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick Tick value used to calculate the quote\\n    /// @param baseAmount Amount of token to be converted\\n    /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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        },\n        \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n        },\n        \"contracts/import/Uni.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\n\\nimport '@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol';\\nimport '@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol';\\nimport '@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol';\\n\\ncontract Uni { \\n  // hack: force hardhat to import all the interfaces at compile time\\n}\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"contracts/core/Oracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {OracleLibrary} from \\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\";\\n\\ncontract Oracle {\\n    using OracleLibrary for address;\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwap(_pool, _base, _quote, _period, uint256(1e18));\\n    }\\n\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwapSafe(_pool, _base, _quote, _period, uint256(1e18));\\n    }\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * request TWAP from uni v3 pool\\n     * if the period requested is too long, capped at max period we can go back\\n     */\\n    function _fetchTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _twapPeriod,\\n        uint256 _amountIn\\n    ) internal view returns (uint256 amountOut) {\\n        // make sure the max period we use is reasonable\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _twapPeriod > maxPeriod ? maxPeriod : _twapPeriod;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod, _amountIn);\\n    }\\n\\n    /**\\n     * request TWAP from a uni v3 pool\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _twapPeriod,\\n        uint256 _amountIn\\n    ) internal view returns (uint256 amountOut) {\\n        int24 twapTick = OracleLibrary.consult(_pool, _twapPeriod);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, toUint128(_amountIn), _base, _quote);\\n    }\\n\\n    /**\\n     * get the max number of period we can use to request twap for a pool\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: The current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // index + 1 % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n\\n    /// @notice Cast a uint256 to a uint128, revert on overflow\\n    /// @param y The uint256 to be downcasted\\n    /// @return z The downcasted integer, now type uint128\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockVaultNFTManager.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract MockVaultNFTManager is ERC721Upgradeable {\\n    uint256 public nextId = 1;\\n\\n    function mintNFT(address _recipient) external returns (uint256 tokenId) {\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function burnNFT(uint256 _tokenId) external {\\n        _burn(_tokenId);\\n    }\\n}\\n\"\n        },\n        \"contracts/core/VaultManagerNFT.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract VaultNFTManager is ERC721Upgradeable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller);\\n        _;\\n    }\\n\\n    function init(address _controller) public initializer {\\n        // init nft\\n        __ERC721_init(\\\"Short Opyn Squeeth Position\\\", \\\"sSqueeth\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * mint new NFT, create a new vault struct\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n}\\n\"\n        },\n        \"contracts/test/OracleTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester {\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwapSafe(_pool, _base, _quote, period);\\n  }\\n}\"\n        }\n    },\n    \"settings\": {\n        \"optimizer\": {\n            \"enabled\": true,\n            \"runs\": 2000\n        },\n        \"outputSelection\": {\n            \"*\": {\n                \"*\": [\n                    \"abi\",\n                    \"evm.bytecode\",\n                    \"evm.deployedBytecode\",\n                    \"evm.methodIdentifiers\",\n                    \"metadata\",\n                    \"devdoc\",\n                    \"userdoc\",\n                    \"storageLayout\",\n                    \"evm.gasEstimates\"\n                ],\n                \"\": [\"ast\"]\n            }\n        },\n        \"metadata\": {\n            \"useLiteralContent\": true\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/solcInputs/63325f69769d83fcd46161b0222ee3cc.json",
    "content": "{\n    \"language\": \"Solidity\",\n    \"sources\": {\n        \"contracts/core/Controller.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract Controller is Initializable, Ownable {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    bool public isShutDown = false;\\n\\n    address public weth;\\n    address public dai;\\n    address public ethDaiPool;\\n\\n    /// @dev address of the powerPerp/weth pool\\n    address public powerPerpPool;\\n\\n    address public uniswapPositionManager;\\n\\n    uint256 public shutDownEthPriceSnapshot;\\n    uint256 public normalizationFactor;\\n    uint256 public lastFundingUpdateTimestamp;\\n\\n    bool public isWethToken0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IVaultManagerNFT public vaultNFT;\\n    IWPowerPerp public wPowerPerp;\\n    IOracle public oracle;\\n\\n    /// Events\\n    event OpenVault(uint256 vaultId);\\n    event CloseVault(uint256 vaultId);\\n    event DepositCollateral(uint256 vaultId, uint128 amount, uint128 collateralId);\\n    event DepositUniNftCollateral(uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(uint256 vaultId, uint256 amount, uint128 collateralId);\\n    event WithdrawUniNftCollateral(uint256 vaultId, uint256 tokenId);\\n    event MintShort(uint256 amount, uint256 vaultId);\\n    event BurnShort(uint256 amount, uint256 vaultId);\\n    event UpdateOperator(uint256 vaultId, address operator);\\n    event Liquidate(uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"shutdown\\\");\\n        _;\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * init controller with squeeth and short NFT address\\n     */\\n    function init(\\n        address _oracle,\\n        address _vaultNFT,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _dai,\\n        address _ethDaiPool,\\n        address _powerPerpPool,\\n        address _uniPositionManager\\n    ) public initializer {\\n        require(_oracle != address(0), \\\"Invalid oracle address\\\");\\n        require(_vaultNFT != address(0), \\\"Invalid vaultNFT address\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid power perp address\\\");\\n        require(_ethDaiPool != address(0), \\\"Invalid eth:dai pool address\\\");\\n        require(_powerPerpPool != address(0), \\\"Invalid powerperp:eth pool address\\\");\\n\\n        oracle = IOracle(_oracle);\\n        vaultNFT = IVaultManagerNFT(_vaultNFT);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n\\n        ethDaiPool = _ethDaiPool;\\n        powerPerpPool = _powerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n\\n        weth = _weth;\\n        dai = _dai;\\n\\n        normalizationFactor = 1e18;\\n        lastFundingUpdateTimestamp = block.timestamp;\\n\\n        isWethToken0 = weth < _wPowerPerp;\\n    }\\n\\n    /**\\n     * put down collateral and mint squeeth.\\n     * This mints an amount of rSqueeth.\\n     */\\n    function mint(\\n        uint256 _vaultId,\\n        uint128 _mintAmount,\\n        uint256 _nftTokenId\\n    ) external payable notShutdown returns (uint256, uint256 _wSqueethMinted) {\\n        _applyFunding();\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_nftTokenId != 0) _depositUniNFT(msg.sender, _vaultId, _nftTokenId);\\n        if (_mintAmount > 0) {\\n            _wSqueethMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n        _checkVault(_vaultId);\\n        return (_vaultId, _wSqueethMinted);\\n    }\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notShutdown {\\n        _applyFunding();\\n        _addEthCollateral(_vaultId, msg.value);\\n    }\\n\\n    /**\\n     * Deposit Uni NFT as collateral\\n     */\\n    function depositUniNFT(uint256 _vaultId, uint256 _tokenId) external notShutdown {\\n        _applyFunding();\\n        _depositUniNFT(msg.sender, _vaultId, _tokenId);\\n    }\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable notShutdown {\\n        _applyFunding();\\n        _withdrawCollateral(msg.sender, _vaultId, _amount);\\n        _checkVault(_vaultId);\\n    }\\n\\n    /**\\n     * Withdraw Uni NFT from a vault\\n     */\\n    function withdrawUniNFT(uint256 _vaultId) external notShutdown {\\n        _applyFunding();\\n        _withdrawUniNFT(msg.sender, _vaultId);\\n        _checkVault(_vaultId);\\n    }\\n\\n    /**\\n     * burn squueth and remove collateral from a vault.\\n     * This burns an amount of wSqueeth.\\n     */\\n    function burn(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external notShutdown {\\n        _applyFunding();\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        _checkVault(_vaultId);\\n    }\\n\\n    /**\\n     * @notice if a vault is unsafe, but has a UNI NFT in it, owner call redeem the NFT to pay back some debt.\\n     * @notice the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId the vault you want to save\\n     */\\n    function reduceDebt(uint256 _vaultId) external notShutdown {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n        _applyFunding();\\n        VaultLib.Vault storage vault = vaults[_vaultId];\\n\\n        (, uint256 wPowerPerpExcess) = _reduceDebt(vault, false);\\n\\n        if (wPowerPerpExcess > 0) {\\n            wPowerPerp.transfer(vaultNFT.ownerOf(_vaultId), wPowerPerpExcess);\\n        }\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (powerPerp burned) * (index price) * 110% in collateral\\n     * @param _vaultId the vault you want to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual you want to repay.\\n     * @return amount of wSqueeth repaid.\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notShutdown returns (uint256) {\\n        _applyFunding();\\n\\n        VaultLib.Vault storage vault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(vault), \\\"Can not liquidate safe vault\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        (uint256 bounty, uint256 wPowerPerpExcess) = _reduceDebt(vault, true);\\n\\n        // transfer extra wPowerPerp to the vault owner\\n        if (wPowerPerpExcess > 0) {\\n            wPowerPerp.transfer(vaultNFT.ownerOf(_vaultId), wPowerPerpExcess);\\n        }\\n\\n        // if vault is safe after saving, pay bounty and return early.\\n        if (_isVaultSafe(vault)) {\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators are only getting reward from liquidation.\\n        vault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it.\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(vault, _maxDebtAmount, msg.sender);\\n\\n        emit Liquidate(_vaultId, debtAmount, collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now.\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, address(oracle), ethDaiPool, weth, dai);\\n    }\\n\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                address(oracle),\\n                powerPerpPool,\\n                ethDaiPool,\\n                weth,\\n                dai,\\n                address(wPowerPerp),\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * Authorize an address to modify the vault. Can be revoke by setting address to 0.\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(_vaultId, _operator);\\n    }\\n\\n    /**\\n     * shutdown the system and enable redeeming long and short\\n     */\\n    function shutDown() external onlyOwner {\\n        require(!isShutDown, \\\"shutdown\\\");\\n        isShutDown = true;\\n        shutDownEthPriceSnapshot = oracle.getTwapSafe(ethDaiPool, weth, dai, 600);\\n    }\\n\\n    /**\\n     * @dev redeem wPowerPerp for its index value when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external {\\n        require(isShutDown, \\\"!shutdown\\\");\\n        wPowerPerp.burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(\\n            _wPerpAmount,\\n            shutDownEthPriceSnapshot,\\n            normalizationFactor\\n        );\\n        payable(msg.sender).sendValue(longValue);\\n    }\\n\\n    /**\\n     * @dev redeem additional collateral from the vault when the system is shutdown\\n     * @param _vaultId vauld id\\n     */\\n    function redeemShort(uint256 _vaultId) external {\\n        require(isShutDown, \\\"!shutdown\\\");\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            vaults[_vaultId].shortAmount,\\n            shutDownEthPriceSnapshot,\\n            normalizationFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = vaults[_vaultId].collateralAmount.sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it.\\n        vaults[_vaultId].shortAmount = 0;\\n        vaults[_vaultId].collateralAmount = 0;\\n\\n        // todo: handle uni nft collateral\\n\\n        payable(msg.sender).sendValue(excess);\\n    }\\n\\n    /**\\n     * Update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * a function to add eth into a contract, in case it got insolvent and have ensufficient eth to pay out.\\n     */\\n    function donate() external payable {}\\n\\n    /**\\n     * fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"Cannot receive eth\\\");\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return vaultNFT.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    /**\\n     * create a new vault and bind it with a new NFT id.\\n     */\\n    function _openVault(address _recipient) internal returns (uint256 vaultId) {\\n        vaultId = vaultNFT.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(vaultId);\\n    }\\n\\n    function _depositUniNFT(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _tokenId\\n    ) internal {\\n        _checkUniNFT(_tokenId);\\n        vaults[_vaultId].addUniNftCollateral(_tokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(_account, address(this), _tokenId);\\n        emit DepositUniNftCollateral(_vaultId, _tokenId);\\n    }\\n\\n    /**\\n     * add collateral to a vault\\n     */\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        vaults[_vaultId].addEthCollateral(uint128(_amount));\\n        emit DepositCollateral(_vaultId, uint128(_amount), 0);\\n    }\\n\\n    /**\\n     * withdraw uni nft\\n     */\\n    function _withdrawUniNFT(address _account, uint256 _vaultId) internal {\\n        uint256 tokenId = vaults[_vaultId].removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniNftCollateral(_vaultId, tokenId);\\n    }\\n\\n    /**\\n     * remove collateral from the vault\\n     */\\n    function _withdrawCollateral(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n        vaults[_vaultId].removeEthCollateral(_amount);\\n        payable(_account).sendValue(_amount);\\n        emit WithdrawCollateral(_vaultId, _amount, 0);\\n    }\\n\\n    /**\\n     * mint wsqueeth (ERC20) to an account\\n     */\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _squeethAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n\\n        amountToMint = _squeethAmount.mul(1e18).div(normalizationFactor);\\n        vaults[_vaultId].addShort(amountToMint);\\n        wPowerPerp.mint(_account, amountToMint);\\n\\n        emit MintShort(amountToMint, _vaultId);\\n    }\\n\\n    /**\\n     * burn wsqueeth (ERC20) from an account.\\n     */\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        vaults[_vaultId].removeShort(_amount);\\n        wPowerPerp.burn(_account, _amount);\\n\\n        emit BurnShort(_amount, _vaultId);\\n    }\\n\\n    /**\\n     * @dev liquidate a vault, pay the liquidator\\n     * @param _vault the vault storage\\n     * @param _maxDebtAmount max debt amount liquidator is willing to repay\\n     * @param _liquidator address which will receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault storage _vault,\\n        uint256 _maxDebtAmount,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        uint256 maxLiquidationAmount = _vault.shortAmount.div(2);\\n\\n        uint256 debtAmount = _maxDebtAmount > maxLiquidationAmount ? maxLiquidationAmount : _maxDebtAmount;\\n\\n        uint256 collateralToPay = Power2Base._getCollateralByRepayAmount(\\n            debtAmount,\\n            address(oracle),\\n            ethDaiPool,\\n            weth,\\n            dai,\\n            normalizationFactor\\n        );\\n\\n        // 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        // if collateralToPay is higher than the total collateral in the vault\\n        // the system only pays out the amount the vault has, which may not be profitable\\n        uint256 collateralInVault = _vault.collateralAmount;\\n        if (collateralToPay > collateralInVault) collateralToPay = collateralInVault;\\n\\n        wPowerPerp.burn(_liquidator, debtAmount);\\n        _vault.removeShort(debtAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        // pay the liquidator\\n        payable(_liquidator).sendValue(collateralToPay);\\n\\n        return (debtAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice this function will redeem the NFT in a vault\\n     * @notice and reduce debt in the target vault if there's a nft in the vault\\n     * @dev this function will be executed before liquidation if there's a NFT in the vault.\\n     * @dev when it's called by liquidate(), it pays out a small bounty to the liquidator.\\n     * @param _vault the vault storage we're saving\\n     * @param _isLiquidation whether we're paying to the recipient the 2% discount or not.\\n     * @return bounty amount of bounty paid for liquidator\\n     * @return excess amount of wPowerPerp should be transfer to the vault owner\\n     */\\n    function _reduceDebt(VaultLib.Vault storage _vault, bool _isLiquidation) internal returns (uint256, uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return (0, 0);\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniNFT(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        // the bounty is 2% on top of total value withdrawn from the NFT.\\n        uint256 bounty;\\n        if (_isLiquidation) {\\n            uint256 totalValue = Power2Base\\n                ._getCollateralByRepayAmount(\\n                    withdrawnWPowerPerpAmount,\\n                    address(oracle),\\n                    ethDaiPool,\\n                    weth,\\n                    dai,\\n                    normalizationFactor\\n                )\\n                .add(withdrawnEthAmount);\\n\\n            bounty = totalValue.mul(2).div(100);\\n        }\\n\\n        _vault.removeUniNftCollateral();\\n        // todo: batch SSTORE\\n        _vault.addEthCollateral(withdrawnEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        // burn min of (shortAmount, withdrawnWPowerPerpAmount) from the vault.\\n        uint256 cacheShortAmount = _vault.shortAmount;\\n        uint256 excess;\\n        if (withdrawnWPowerPerpAmount > cacheShortAmount) {\\n            excess = withdrawnWPowerPerpAmount.sub(cacheShortAmount);\\n            withdrawnWPowerPerpAmount = cacheShortAmount;\\n        }\\n        _vault.removeShort(withdrawnWPowerPerpAmount);\\n        wPowerPerp.burn(address(this), withdrawnWPowerPerpAmount);\\n\\n        return (bounty, excess);\\n    }\\n\\n    /**\\n     * @dev redeem a uni v3 nft and get back wPerp and eth.\\n     */\\n    function _redeemUniNFT(uint256 _nftId) internal returns (uint256 wethAmount, uint256 wPowerPerpAmount) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _nftId);\\n\\n        // prepare parameters to withdraw liquidity from Uniswap V3 Position Manager.\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _nftId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        // the decreaseLiquidity function returns the amount collectable by the owner.\\n        (uint256 amount0, uint256 amount1) = positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw weth and wPowerPerp from Uniswap V3.\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _nftId,\\n            recipient: address(this),\\n            amount0Max: uint128(amount0),\\n            amount1Max: uint128(amount1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        bool cacheIsWethToken0 = isWethToken0; // cache storage variable\\n        wethAmount = cacheIsWethToken0 ? collectedToken0 : collectedToken1;\\n        wPowerPerpAmount = cacheIsWethToken0 ? collectedToken1 : collectedToken0;\\n    }\\n\\n    /// @notice Update the normalized factor as a way to pay funding.\\n    /// @dev funding is calculated as mark - index.\\n    function _applyFunding() internal {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return;\\n\\n        normalizationFactor = _getNewNormalizationFactor();\\n        lastFundingUpdateTimestamp = block.timestamp;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp.\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = uint32(block.timestamp - lastFundingUpdateTimestamp);\\n\\n        // make sure we use the same period for mark and index, and this period won't cause revert.\\n        uint32 fairPeriod = _getFairPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor  from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            fairPeriod,\\n            address(oracle),\\n            powerPerpPool,\\n            ethDaiPool,\\n            weth,\\n            dai,\\n            address(wPowerPerp),\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(fairPeriod, address(oracle), ethDaiPool, weth, dai);\\n        uint256 rFunding = (uint256(1e18).mul(uint256(period))).div(secInDay);\\n\\n        // mul by 1e36 to keep newNormalizationFactor in 18 decimals\\n        // uint256 newNormalizationFactor = (mark * 1e36) / (((1e18 + rFunding) * mark - index * rFunding));\\n        uint256 newNormalizationFactor = (mark.mul(1e36)).div(\\n            ((uint256(1e18).add(rFunding)).mul(mark).sub(index.mul(rFunding)))\\n        );\\n\\n        return cacheNormFactor.mul(newNormalizationFactor).div(1e18);\\n    }\\n\\n    /**\\n     * check that the specified tokenId is a valid squeeth/weth lp token.\\n     */\\n    function _checkUniNFT(uint256 _tokenId) internal view {\\n        (, , address token0, address token1, , , , , , , , ) = INonfungiblePositionManager(uniswapPositionManager)\\n            .positions(_tokenId);\\n        // only check token0 and token1, ignore fee.\\n        // If there are multiple wsqueeth/eth pools with different fee rate, we accept LP tokens from all of them.\\n        address wsqueethAddr = address(wPowerPerp); // cache storage variable\\n        address wethAddr = weth; // cache storage variable\\n        require(\\n            (token0 == wsqueethAddr && token1 == wethAddr) || (token1 == wsqueethAddr && token0 == wethAddr),\\n            \\\"Invalid nft\\\"\\n        );\\n    }\\n\\n    /**\\n     * @dev check that the vault is solvent and has enough collateral.\\n     */\\n    function _checkVault(uint256 _vaultId) internal view {\\n        if (_vaultId == 0) return;\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n\\n        require(_isVaultSafe(vault), \\\"Invalid state\\\");\\n    }\\n\\n    function _isVaultSafe(VaultLib.Vault memory _vault) internal view returns (bool) {\\n        uint256 ethDaiPrice = oracle.getTwapSafe(ethDaiPool, weth, dai, 300);\\n        int24 perpPoolTick = oracle.getTimeWeightedAverageTickSafe(powerPerpPool, 300);\\n        return\\n            VaultLib.isProperlyCollateralized(\\n                _vault,\\n                uniswapPositionManager,\\n                normalizationFactor,\\n                ethDaiPrice,\\n                perpPoolTick,\\n                isWethToken0\\n            );\\n    }\\n\\n    function _getFairPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxSafePeriod = _getMaxSafePeriod();\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n\\n    /**\\n     * return the smaller of the max periods of 2 pools\\n     */\\n    function _getMaxSafePeriod() internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = oracle.getMaxPeriod(ethDaiPool);\\n        uint32 maxPeriodPool2 = oracle.getMaxPeriod(powerPerpPool);\\n        return maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n    }\\n}\\n\"\n        },\n        \"hardhat/console.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >= 0.4.22 <0.9.0;\\n\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction _sendLogPayload(bytes memory payload) private view {\\n\\t\\tuint256 payloadLength = payload.length;\\n\\t\\taddress consoleAddress = CONSOLE_ADDRESS;\\n\\t\\tassembly {\\n\\t\\t\\tlet payloadStart := add(payload, 32)\\n\\t\\t\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n\\t\\t}\\n\\t}\\n\\n\\tfunction log() internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t}\\n\\n\\tfunction logInt(int p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n}\\n\"\n        },\n        \"contracts/interfaces/IWPowerPerp.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n        },\n        \"contracts/interfaces/IVaultManagerNFT.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IVaultManagerNFT is IERC721 {\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n        },\n        \"contracts/interfaces/IOracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n        },\n        \"contracts/interfaces/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./IERC721Upgradeable.sol\\\";\\nimport \\\"./IERC721MetadataUpgradeable.sol\\\";\\nimport \\\"./IERC721EnumerableUpgradeable.sol\\\";\\nimport \\\"./IERC721ReceiverUpgradeable.sol\\\";\\nimport \\\"../../introspection/ERC165Upgradeable.sol\\\";\\nimport \\\"../../math/SafeMathUpgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableSetUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableMapUpgradeable.sol\\\";\\nimport \\\"../../utils/StringsUpgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721EnumerableUpgradeable {\\n    using SafeMathUpgradeable for uint256;\\n    using AddressUpgradeable for address;\\n    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;\\n    using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;\\n    using StringsUpgradeable for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSetUpgradeable.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMapUpgradeable.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {\\n        __Context_init_unchained();\\n        __ERC165_init_unchained();\\n        __ERC721_init_unchained(name_, symbol_);\\n    }\\n\\n    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721Upgradeable.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721Upgradeable.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721Upgradeable.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721ReceiverUpgradeable(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n    uint256[41] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/access/Ownable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/math/SafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Address.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/VaultLib.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\\\";\\n\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    /** \\n     collateral is always eth, \\n     while we can also add a Uniswap V3 NFT in to the vault to reduce collateral amount.\\n    */\\n    struct Vault {\\n        address operator;\\n        // address NFTCollateralAddress; // the uni v3 pool address, may not need this if we only support ETH / SQUEETH;\\n        uint256 NftCollateralId; // the uni v3 pool NFT id\\n        uint256 collateralAmount;\\n        uint256 shortAmount;\\n    }\\n\\n    function addEthCollateral(Vault storage _vault, uint256 _amount) internal {\\n        _vault.collateralAmount = _vault.collateralAmount.add(_amount);\\n    }\\n\\n    function addUniNftCollateral(Vault storage _vault, uint256 _tokenId) internal {\\n        require(_vault.NftCollateralId == 0, \\\"Vault already had nft\\\");\\n        require(_tokenId != 0, \\\"invalid id\\\");\\n        _vault.NftCollateralId = _tokenId;\\n    }\\n\\n    function removeEthCollateral(Vault storage _vault, uint256 _amount) internal {\\n        _vault.collateralAmount = _vault.collateralAmount.sub(_amount);\\n    }\\n\\n    function removeUniNftCollateral(Vault storage _vault) internal returns (uint256 tokenId) {\\n        require(_vault.NftCollateralId != 0, \\\"Vault has no NFT\\\");\\n        tokenId = _vault.NftCollateralId;\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    function addShort(Vault storage _vault, uint256 _amount) internal {\\n        _vault.shortAmount = _vault.shortAmount.add(_amount);\\n    }\\n\\n    function removeShort(Vault storage _vault, uint256 _amount) internal {\\n        _vault.shortAmount = _vault.shortAmount.sub(_amount);\\n    }\\n\\n    /// @dev see if a vault is properly collateralized\\n    /// @param _vault the vault we want to check\\n    /// @param _positionManager address of the uni v3 position manager\\n    /// @param _normalizationFactor current _normalizationFactor\\n    /// @param _ethDaiPrice current eth price scaled by 1e18\\n    /// @param _wsqueethPoolTick current price tick for wsqueeth pool\\n    /// @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n    /// @return true if the vault is above water.\\n    function isProperlyCollateralized(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool) {\\n        if (_vault.shortAmount == 0) return true;\\n        return\\n            _isProperlyCollateralized(\\n                _vault,\\n                _positionManager,\\n                _normalizationFactor,\\n                _ethDaiPrice,\\n                _wsqueethPoolTick,\\n                _isWethToken0\\n            );\\n    }\\n\\n    /// @dev see if a vault is properly collateralized\\n    /// @param _vault the vault we want to check\\n    /// @param _positionManager address of the uni v3 position manager\\n    /// @param _normalizationFactor current _normalizationFactor\\n    /// @param _ethDaiPrice current eth price scaled by 1e18\\n    /// @param _wsqueethPoolTick current price tick for wsqueeth pool\\n    /// @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n    /// @return true if the vault is above water.\\n    function _isProperlyCollateralized(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool) {\\n        uint256 totalCollateral = _vault.collateralAmount;\\n        if (_vault.NftCollateralId != 0) {\\n            // if user deposit univ3 nft as collateral, see how much eth / squeeth the LP token has.\\n            (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n                _positionManager,\\n                _vault.NftCollateralId,\\n                _wsqueethPoolTick,\\n                _isWethToken0\\n            );\\n            // convert squeeth amount from NFT as equivalent amount of collateral.\\n            uint256 equivalentCollateral = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\n            // add ETH value from NFT as collateral.\\n            totalCollateral = totalCollateral.add(equivalentCollateral).add(nftEthAmount);\\n        }\\n        uint256 debtValueInETH = _vault.shortAmount.mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\n        return totalCollateral.mul(2) >= debtValueInETH.mul(3);\\n    }\\n\\n    /// @notice get how much eth / squeeth the LP position is worth.\\n    /// @param _positionManager address of the uni v3 position manager\\n    /// @param _tokenId lp token id\\n    /// @param _wsqueethPoolTick current price tick\\n    /// @param _isWethToken0 whether weth is token0 in the pool\\n    /// @return ethAmount the eth amount thie LP token is worth\\n    /// @return squeethAmount the squeeth amount this LP token is worth\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 squeethAmount) {\\n        (int24 tickLower, int24 tickUpper, uint128 liquidity) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wsqueethPoolTick,\\n            liquidity\\n        );\\n        return (_isWethToken0 ? amount0 : amount1, _isWethToken0 ? amount1 : amount0);\\n    }\\n\\n    /**\\n     * @notice get the LP info and tick bond of the LP position.\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _tokenId LP token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (, , , , , int24 tickLower, int24 tickUpper, uint128 liquidity, , , , ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity);\\n    }\\n\\n    /**\\n     * @notice get how much token0 / token1 a LP position is worth.\\n     * @param _tickLower address of the uni v3 position manager\\n     * @param _tickUpper LP token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 this LP token is worth\\n     * @return amount1 the amount of token1 this LP token is worth\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from squeethPool\\n        uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(_tick);\\n\\n        // the following line is copied from the _modifyPosition function implemented by Uniswap core.\\n        // we use the same logic to determine how much token0, token1 equals to given \\\"liquidity\\\"\\n        // https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/UniswapV3Pool.sol#L306\\n\\n        // use these 2 functions directly, cuz liquidity is always positive\\n        // getAmount0Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L209\\n        // getAmount1Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L225\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/Power2Base.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {OracleLibrary} from \\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    /**\\n     * @dev return the index of the power perp in DAI, scaled by 18 decimals\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = _getTwap(_oracle, _ethDaiPool, _weth, _dai, _period);\\n        return ethDaiPrice.mul(ethDaiPrice).div(1e18);\\n    }\\n\\n    /**\\n     * @dev return the mark price of power perp in DAI, scaled by 18 decimals\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _squeethEthPool,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai,\\n        address _wsqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = _getTwap(_oracle, _ethDaiPool, _weth, _dai, _period);\\n        uint256 squeethEthPrice = _getTwap(_oracle, _squeethEthPool, address(_wsqueeth), _weth, _period);\\n\\n        return squeethEthPrice.mul(ethDaiPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @dev get fair collateral amount to pay out to a liquidator repaying _debtAmount debt\\n     * @dev the actual amount liquidator can get should have a x% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @return\\n     */\\n    function _getCollateralByRepayAmount(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = IOracle(_oracle).getTwapSafe(_ethDaiPool, _weth, _dai, 600);\\n        return _debtAmount.mul(_normalizationFactor).mul(ethDaiPrice).div(1e36);\\n    }\\n\\n    /**\\n     * @dev request twap from our oracle.\\n     * @return price scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        uint256 twap = IOracle(_oracle).getTwap(_pool, _base, _quote, _period);\\n        require(twap != 0, \\\"WAP WAP WAP\\\");\\n\\n        return twap;\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _ethSettlementPrice eth price used for settlement. scaled with 1e18\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _ethSettlementPrice,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_ethSettlementPrice).div(1e36);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n            \"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\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function _getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN 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 initializer {\\n        __Context_init_unchained();\\n    }\\n\\n    function __Context_init_unchained() internal initializer {\\n    }\\n    function _msgSender() internal view virtual returns (address payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n    uint256[50] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165Upgradeable.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721MetadataUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721EnumerableUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721EnumerableUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721ReceiverUpgradeable {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165Upgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    function __ERC165_init() internal initializer {\\n        __ERC165_init_unchained();\\n    }\\n\\n    function __ERC165_init_unchained() internal initializer {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n    uint256[49] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMathUpgradeable {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary 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    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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 EnumerableSetUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Set type with\\n    // bytes32 values.\\n    // The Set implementation uses private functions, and user-facing\\n    // implementations (such as AddressSet) are just wrappers around the\\n    // underlying Set.\\n    // This means that we can only create new EnumerableSets for types that fit\\n    // in bytes32.\\n\\n    struct Set {\\n        // Storage of set values\\n        bytes32[] _values;\\n\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableMapUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMapUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary StringsUpgradeable {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !AddressUpgradeable.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/IERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165Upgradeable {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Context.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity >=0.5.0;\\n\\nimport './LowGasSafeMath.sol';\\nimport './SafeCast.sol';\\n\\nimport './FullMath.sol';\\nimport './UnsafeMath.sol';\\nimport './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 LowGasSafeMath for uint256;\\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            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            return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96).add(amount)));\\n        } else {\\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    /// @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                (\\n                    amount <= type(uint160).max\\n                        ? (amount << FixedPoint96.RESOLUTION) / liquidity\\n                        : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)\\n                );\\n\\n            return uint256(sqrtPX96).add(quotient).toUint160();\\n        } else {\\n            uint256 quotient =\\n                (\\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            return uint160(sqrtPX96 - quotient);\\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        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @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        return\\n            liquidity < 0\\n                ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\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        return\\n            liquidity < 0\\n                ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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        },\n        \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0 <0.8.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Oracle library\\n/// @notice Provides functions to integrate with V3 pool oracle\\nlibrary OracleLibrary {\\n    /// @notice Fetches time-weighted average tick using Uniswap V3 oracle\\n    /// @param pool Address of Uniswap V3 pool that we want to observe\\n    /// @param period Number of seconds in the past to start calculating time-weighted average\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - period) to block.timestamp\\n    function consult(address pool, uint32 period) internal view returns (int24 timeWeightedAverageTick) {\\n        require(period != 0, 'BP');\\n\\n        uint32[] memory secondAgos = new uint32[](2);\\n        secondAgos[0] = period;\\n        secondAgos[1] = 0;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / period);\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % period != 0)) timeWeightedAverageTick--;\\n    }\\n\\n    /// @notice Given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick Tick value used to calculate the quote\\n    /// @param baseAmount Amount of token to be converted\\n    /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/test/OracleTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester {\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwapSafe(_pool, _base, _quote, period);\\n  }\\n}\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Strings.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"contracts/periphery/ShortHelper.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\ncontract ShortHelper {\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWPowerPerp public immutable wsqueeth;\\n    IWETH9 public immutable weth;\\n    IVaultManagerNFT public immutable vaultNFT;\\n\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n\\n        IWPowerPerp _wsqueeth = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wsqueeth.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        vaultNFT = IVaultManagerNFT(_controller.vaultNFT());\\n        weth = _weth;\\n        controller = _controller;\\n        wsqueeth = _wsqueeth;\\n    }\\n\\n    /**\\n     * mint squeeth, trade with uniswap and send back premium in eth.\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint128 _shortSqueethAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable {\\n        (uint256 vaultId, uint256 wsqueethAmount) = controller.mint{value: msg.value}(\\n            _vaultId,\\n            _shortSqueethAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wsqueethAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this) && _exactInputParams.tokenOut == address(weth)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) vaultNFT.transferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * buy back some squeeth and close the position.\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _removeShortAmount,\\n        uint128 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable {\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get squeeth in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burn(_vaultId, _removeShortAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value - amountIn);\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"contracts/interfaces/IController.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IController {\\n    function vaultNFT() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    /**\\n     * put down collateral and mint squeeth.\\n     */\\n    function mint(\\n        uint256 _vaultId,\\n        uint128 _mintAmount,\\n        uint256 _nftId\\n    ) external payable returns (uint256 vaultId, uint256 _wSqueethMinted);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    /**\\n     * burn squueth and remove collateral from a vault.\\n     */\\n    function burn(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n            \"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\"\n        },\n        \"contracts/mocks/MockUniPositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress._getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/core/Oracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {OracleLibrary} from \\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\";\\n\\ncontract Oracle {\\n    /**\\n     * @notice get twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwap(_pool, _base, _quote, _period, uint256(1e18));\\n    }\\n\\n    /**\\n     * @notice get twap from the uniswap pool, never revert\\n     * @dev if period is larger than the max period stored by the pool, default to the max period.\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price scaled by 1e18\\n     */\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwapSafe(_pool, _base, _quote, _period, uint256(1e18));\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap.\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consult(_pool, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap from the uniswap pool, never revert\\n     * @dev if period is larger than the max period stored by the pool, default to the max period.\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _amountIn Amount of token to be converted\\n     * @return amountOut Amount of quoteToken received for baseAmount of baseToken\\n     */\\n    function _fetchTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint256 _amountIn\\n    ) internal view returns (uint256 amountOut) {\\n        // make sure the max period we use is reasonable\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod, _amountIn);\\n    }\\n\\n    /**\\n     * @notice get twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price scaled by 1e18\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint256 _amountIn\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consult(_pool, _period);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, toUint128(_amountIn), _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap.\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: The current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // index + 1 % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n\\n    /**\\n     * @notice Cast a uint256 to a uint128, revert on overflow\\n     * @param y The uint256 to be downcasted\\n     * @return z The downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y);\\n    }\\n}\\n\"\n        },\n        \"contracts/import/Uni.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"contracts/test/VaultTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _squeethPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 squeethAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _squeethPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n        },\n        \"contracts/mocks/MockWSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWSqueeth is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSqueeth\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockErc20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/core/WSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n/// @notice this is the ERC20 contract for long position of Squeeth\\n/// @dev this contract implements IWPowerPerp interface, makes it controllable by Controller.\\n/// @dev decimals of squeeth is chosen as 14.\\ncontract WSqueeth is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSQTH\\\") {}\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * override decimals with 14.\\n     */\\n    function decimals() public pure override returns (uint8) {\\n        return 14;\\n    }\\n\\n    function init(address _controller) external initializer {\\n        controller = _controller;\\n    }\\n\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockVaultNFTManager.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract MockVaultNFTManager is ERC721Upgradeable {\\n    uint256 public nextId = 1;\\n\\n    function mintNFT(address _recipient) external returns (uint256 tokenId) {\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function burnNFT(uint256 _tokenId) external {\\n        _burn(_tokenId);\\n    }\\n}\\n\"\n        },\n        \"contracts/core/VaultManagerNFT.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract VaultNFTManager is ERC721Upgradeable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller);\\n        _;\\n    }\\n\\n    function init(address _controller) public initializer {\\n        // init nft\\n        __ERC721_init(\\\"Short Opyn Squeeth Position\\\", \\\"sSqueeth\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * mint new NFT, create a new vault struct\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n}\\n\"\n        }\n    },\n    \"settings\": {\n        \"optimizer\": {\n            \"enabled\": true,\n            \"runs\": 2000\n        },\n        \"outputSelection\": {\n            \"*\": {\n                \"*\": [\n                    \"abi\",\n                    \"evm.bytecode\",\n                    \"evm.deployedBytecode\",\n                    \"evm.methodIdentifiers\",\n                    \"metadata\",\n                    \"devdoc\",\n                    \"userdoc\",\n                    \"storageLayout\",\n                    \"evm.gasEstimates\"\n                ],\n                \"\": [\"ast\"]\n            }\n        },\n        \"metadata\": {\n            \"useLiteralContent\": true\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/solcInputs/65b5636a064484e3748f101fc0e531a8.json",
    "content": "{\n    \"language\": \"Solidity\",\n    \"sources\": {\n        \"contracts/core/Controller.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract Controller is Initializable, Ownable {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    bool public isShutDown = false;\\n\\n    address public weth;\\n    address public dai;\\n    address public ethDaiPool;\\n\\n    /// @dev address of the powerPerp/weth pool\\n    address public powerPerpPool;\\n\\n    address public uniswapPositionManager;\\n\\n    uint256 public shutDownEthPriceSnapshot;\\n    uint256 public normalizationFactor;\\n    uint256 public lastFundingUpdateTimestamp;\\n\\n    bool public isWethToken0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IVaultManagerNFT public vaultNFT;\\n    IWPowerPerp public wPowerPerp;\\n    IOracle public oracle;\\n\\n    /// Events\\n    event OpenVault(uint256 vaultId);\\n    event CloseVault(uint256 vaultId);\\n    event DepositCollateral(uint256 vaultId, uint128 amount, uint128 collateralId);\\n    event DepositUniNftCollateral(uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(uint256 vaultId, uint256 amount, uint128 collateralId);\\n    event WithdrawUniNftCollateral(uint256 vaultId, uint256 tokenId);\\n    event MintShort(uint256 amount, uint256 vaultId);\\n    event BurnShort(uint256 amount, uint256 vaultId);\\n    event UpdateOperator(uint256 vaultId, address operator);\\n    event Liquidate(uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"shutdown\\\");\\n        _;\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * init controller with squeeth and short NFT address\\n     */\\n    function init(\\n        address _oracle,\\n        address _vaultNFT,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _dai,\\n        address _ethDaiPool,\\n        address _powerPerpPool,\\n        address _uniPositionManager\\n    ) public initializer {\\n        require(_oracle != address(0), \\\"Invalid oracle address\\\");\\n        require(_vaultNFT != address(0), \\\"Invalid vaultNFT address\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid power perp address\\\");\\n        require(_ethDaiPool != address(0), \\\"Invalid eth:dai pool address\\\");\\n        require(_powerPerpPool != address(0), \\\"Invalid powerperp:eth pool address\\\");\\n\\n        oracle = IOracle(_oracle);\\n        vaultNFT = IVaultManagerNFT(_vaultNFT);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n\\n        ethDaiPool = _ethDaiPool;\\n        powerPerpPool = _powerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n\\n        weth = _weth;\\n        dai = _dai;\\n\\n        normalizationFactor = 1e18;\\n        lastFundingUpdateTimestamp = block.timestamp;\\n\\n        isWethToken0 = weth < _wPowerPerp;\\n    }\\n\\n    /**\\n     * put down collateral and mint squeeth.\\n     * This mints an amount of rSqueeth.\\n     */\\n    function mint(\\n        uint256 _vaultId,\\n        uint128 _mintAmount,\\n        uint256 _nftTokenId\\n    ) external payable notShutdown returns (uint256, uint256 _wSqueethMinted) {\\n        _applyFunding();\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_nftTokenId != 0) _depositUniNFT(msg.sender, _vaultId, _nftTokenId);\\n        if (_mintAmount > 0) {\\n            _wSqueethMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n        _checkVault(_vaultId);\\n        return (_vaultId, _wSqueethMinted);\\n    }\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notShutdown {\\n        _applyFunding();\\n        _addEthCollateral(_vaultId, msg.value);\\n    }\\n\\n    /**\\n     * Deposit Uni NFT as collateral\\n     */\\n    function depositUniNFT(uint256 _vaultId, uint256 _tokenId) external notShutdown {\\n        _applyFunding();\\n        _depositUniNFT(msg.sender, _vaultId, _tokenId);\\n    }\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable notShutdown {\\n        _applyFunding();\\n        _withdrawCollateral(msg.sender, _vaultId, _amount);\\n        _checkVault(_vaultId);\\n    }\\n\\n    /**\\n     * Withdraw Uni NFT from a vault\\n     */\\n    function withdrawUniNFT(uint256 _vaultId) external notShutdown {\\n        _applyFunding();\\n        _withdrawUniNFT(msg.sender, _vaultId);\\n        _checkVault(_vaultId);\\n    }\\n\\n    /**\\n     * burn squueth and remove collateral from a vault.\\n     * This burns an amount of wSqueeth.\\n     */\\n    function burn(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external notShutdown {\\n        _applyFunding();\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        _checkVault(_vaultId);\\n    }\\n\\n    /**\\n     * @notice if a vault is unsafe, but has a UNI NFT in it, user can call saveVault to burn the NFT to\\n     * @notice pay back some debt.\\n     * @notice the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId the vault you want to save\\n     */\\n    function saveVault(uint256 _vaultId) external notShutdown {\\n        _applyFunding();\\n        VaultLib.Vault storage vault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(vault), \\\"Vault is safe\\\");\\n\\n        (, uint256 wPowerPerpExcess) = _saveVault(vault, false);\\n\\n        if (wPowerPerpExcess > 0) {\\n            wPowerPerp.transfer(vaultNFT.ownerOf(_vaultId), wPowerPerpExcess);\\n        }\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (powerPerp burned) * (index price) * 110% in collateral\\n     * @param _vaultId the vault you want to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual you want to repay.\\n     * @return amount of wSqueeth repaid.\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notShutdown returns (uint256) {\\n        _applyFunding();\\n\\n        VaultLib.Vault storage vault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(vault), \\\"Can not liquidate safe vault\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        (uint256 bounty, uint256 wPowerPerpExcess) = _saveVault(vault, true);\\n\\n        // transfer extra wPowerPerp to the vault owner\\n        if (wPowerPerpExcess > 0) {\\n            wPowerPerp.transfer(vaultNFT.ownerOf(_vaultId), wPowerPerpExcess);\\n        }\\n\\n        // if vault is safe after saving, pay bounty and return early.\\n        if (_isVaultSafe(vault)) {\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators are only getting reward from liquidation.\\n        vault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it.\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(vault, _maxDebtAmount, msg.sender);\\n\\n        emit Liquidate(_vaultId, debtAmount, collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now.\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, address(oracle), ethDaiPool, weth, dai);\\n    }\\n\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                address(oracle),\\n                powerPerpPool,\\n                ethDaiPool,\\n                weth,\\n                dai,\\n                address(wPowerPerp),\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * Authorize an address to modify the vault. Can be revoke by setting address to 0.\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(_vaultId, _operator);\\n    }\\n\\n    /**\\n     * shutdown the system and enable redeeming long and short\\n     */\\n    function shutDown() external onlyOwner {\\n        require(!isShutDown, \\\"shutdown\\\");\\n        isShutDown = true;\\n        shutDownEthPriceSnapshot = oracle.getTwapSafe(ethDaiPool, weth, dai, 600);\\n    }\\n\\n    /**\\n     * @dev redeem wPowerPerp for its index value when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external {\\n        require(isShutDown, \\\"!shutdown\\\");\\n        wPowerPerp.burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(\\n            _wPerpAmount,\\n            shutDownEthPriceSnapshot,\\n            normalizationFactor\\n        );\\n        payable(msg.sender).sendValue(longValue);\\n    }\\n\\n    /**\\n     * @dev redeem additional collateral from the vault when the system is shutdown\\n     * @param _vaultId vauld id\\n     */\\n    function redeemShort(uint256 _vaultId) external {\\n        require(isShutDown, \\\"!shutdown\\\");\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            vaults[_vaultId].shortAmount,\\n            shutDownEthPriceSnapshot,\\n            normalizationFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = vaults[_vaultId].collateralAmount.sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it.\\n        vaults[_vaultId].shortAmount = 0;\\n        vaults[_vaultId].collateralAmount = 0;\\n\\n        // todo: handle uni nft collateral\\n\\n        payable(msg.sender).sendValue(excess);\\n    }\\n\\n    /**\\n     * Update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * a function to add eth into a contract, in case it got insolvent and have ensufficient eth to pay out.\\n     */\\n    function donate() external payable {}\\n\\n    /**\\n     * fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"Cannot receive eth\\\");\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return vaultNFT.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    /**\\n     * create a new vault and bind it with a new NFT id.\\n     */\\n    function _openVault(address _recipient) internal returns (uint256 vaultId) {\\n        vaultId = vaultNFT.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(vaultId);\\n    }\\n\\n    function _depositUniNFT(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _tokenId\\n    ) internal {\\n        _checkUniNFT(_tokenId);\\n        vaults[_vaultId].addUniNftCollateral(_tokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(_account, address(this), _tokenId);\\n        emit DepositUniNftCollateral(_vaultId, _tokenId);\\n    }\\n\\n    /**\\n     * add collateral to a vault\\n     */\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        vaults[_vaultId].addEthCollateral(uint128(_amount));\\n        emit DepositCollateral(_vaultId, uint128(_amount), 0);\\n    }\\n\\n    /**\\n     * withdraw uni nft\\n     */\\n    function _withdrawUniNFT(address _account, uint256 _vaultId) internal {\\n        uint256 tokenId = vaults[_vaultId].removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniNftCollateral(_vaultId, tokenId);\\n    }\\n\\n    /**\\n     * remove collateral from the vault\\n     */\\n    function _withdrawCollateral(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n        vaults[_vaultId].removeEthCollateral(_amount);\\n        payable(_account).sendValue(_amount);\\n        emit WithdrawCollateral(_vaultId, _amount, 0);\\n    }\\n\\n    /**\\n     * mint wsqueeth (ERC20) to an account\\n     */\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _squeethAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n\\n        amountToMint = _squeethAmount.mul(1e18).div(normalizationFactor);\\n        vaults[_vaultId].addShort(amountToMint);\\n        wPowerPerp.mint(_account, amountToMint);\\n\\n        emit MintShort(amountToMint, _vaultId);\\n    }\\n\\n    /**\\n     * burn wsqueeth (ERC20) from an account.\\n     */\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        vaults[_vaultId].removeShort(_amount);\\n        wPowerPerp.burn(_account, _amount);\\n\\n        emit BurnShort(_amount, _vaultId);\\n    }\\n\\n    /**\\n     * @dev liquidate a vault, pay the liquidator\\n     * @param _vault the vault storage\\n     * @param _maxDebtAmount max debt amount liquidator is willing to repay\\n     * @param _liquidator address which will receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault storage _vault,\\n        uint256 _maxDebtAmount,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        uint256 maxLiquidationAmount = _vault.shortAmount.div(2);\\n\\n        uint256 debtAmount = _maxDebtAmount > maxLiquidationAmount ? maxLiquidationAmount : _maxDebtAmount;\\n\\n        uint256 collateralToPay = Power2Base._getCollateralByRepayAmount(\\n            debtAmount,\\n            address(oracle),\\n            ethDaiPool,\\n            weth,\\n            dai,\\n            normalizationFactor\\n        );\\n\\n        // 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        // if collateralToPay is higher than the total collateral in the vault\\n        // the system only pays out the amount the vault has, which may not be profitable\\n        uint256 collateralInVault = _vault.collateralAmount;\\n        if (collateralToPay > collateralInVault) collateralToPay = collateralInVault;\\n\\n        wPowerPerp.burn(_liquidator, debtAmount);\\n        _vault.removeShort(debtAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        // pay the liquidator\\n        payable(_liquidator).sendValue(collateralToPay);\\n\\n        return (debtAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice this function will redeem the NFT in a vault\\n     * @notice and reduce debt in the target vault if there's a nft in the vault\\n     * @dev this function will be executed before liquidation if there's a NFT in the vault.\\n     * @dev when it's called by liquidate(), it pays out a small bounty to the liquidator.\\n     * @param _vault the vault storage we're saving\\n     * @param _isLiquidation whether we're paying to the recipient the 2% discount or not.\\n     * @return bounty amount of bounty paid for liquidator\\n     * @return excess amount of wPowerPerp should be transfer to the vault owner\\n     */\\n    function _saveVault(VaultLib.Vault storage _vault, bool _isLiquidation) internal returns (uint256, uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return (0, 0);\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniNFT(nftId);\\n\\n        // change weth back to eth\\n        IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        // the bounty is 2% on top of total value withdrawn from the NFT.\\n        uint256 bounty;\\n        if (_isLiquidation) {\\n            uint256 totalValue = Power2Base\\n                ._getCollateralByRepayAmount(\\n                    withdrawnWPowerPerpAmount,\\n                    address(oracle),\\n                    ethDaiPool,\\n                    weth,\\n                    dai,\\n                    normalizationFactor\\n                )\\n                .add(withdrawnEthAmount);\\n\\n            bounty = totalValue.mul(2).div(100);\\n        }\\n\\n        _vault.removeUniNftCollateral();\\n        // todo: batch SSTORE\\n        _vault.addEthCollateral(withdrawnEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        // burn min of (shortAmount, withdrawnWPowerPerpAmount) from the vault.\\n        uint256 cacheShortAmount = _vault.shortAmount;\\n        uint256 excess;\\n        if (withdrawnWPowerPerpAmount > cacheShortAmount) {\\n            excess = withdrawnWPowerPerpAmount.sub(cacheShortAmount);\\n            withdrawnWPowerPerpAmount = cacheShortAmount;\\n        }\\n        _vault.removeShort(withdrawnWPowerPerpAmount);\\n        wPowerPerp.burn(address(this), withdrawnWPowerPerpAmount);\\n\\n        return (bounty, excess);\\n    }\\n\\n    /**\\n     * @dev redeem a uni v3 nft and get back wPerp and eth.\\n     */\\n    function _redeemUniNFT(uint256 _nftId) internal returns (uint256 wethAmount, uint256 wPowerPerpAmount) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _nftId);\\n\\n        // prepare parameters to withdraw liquidity from Uniswap V3 Position Manager.\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _nftId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        // the decreaseLiquidity function returns the amount collectable by the owner.\\n        (uint256 amount0, uint256 amount1) = positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw weth and wPowerPerp from Uniswap V3.\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _nftId,\\n            recipient: address(this),\\n            amount0Max: uint128(amount0),\\n            amount1Max: uint128(amount1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        bool cacheIsWethToken0 = isWethToken0; // cache storage variable\\n        wethAmount = cacheIsWethToken0 ? collectedToken0 : collectedToken1;\\n        wPowerPerpAmount = cacheIsWethToken0 ? collectedToken1 : collectedToken0;\\n    }\\n\\n    /// @notice Update the normalized factor as a way to pay funding.\\n    /// @dev funding is calculated as mark - index.\\n    function _applyFunding() internal {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return;\\n\\n        normalizationFactor = _getNewNormalizationFactor();\\n        lastFundingUpdateTimestamp = block.timestamp;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp.\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = uint32(block.timestamp - lastFundingUpdateTimestamp);\\n\\n        // make sure we use the same period for mark and index, and this period won't cause revert.\\n        uint32 fairPeriod = _getFairPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor  from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            fairPeriod,\\n            address(oracle),\\n            powerPerpPool,\\n            ethDaiPool,\\n            weth,\\n            dai,\\n            address(wPowerPerp),\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(fairPeriod, address(oracle), ethDaiPool, weth, dai);\\n        uint256 rFunding = (uint256(1e18).mul(uint256(period))).div(secInDay);\\n\\n        // mul by 1e36 to keep newNormalizationFactor in 18 decimals\\n        // uint256 newNormalizationFactor = (mark * 1e36) / (((1e18 + rFunding) * mark - index * rFunding));\\n        uint256 newNormalizationFactor = (mark.mul(1e36)).div(\\n            ((uint256(1e18).add(rFunding)).mul(mark).sub(index.mul(rFunding)))\\n        );\\n\\n        return cacheNormFactor.mul(newNormalizationFactor).div(1e18);\\n    }\\n\\n    /**\\n     * check that the specified tokenId is a valid squeeth/weth lp token.\\n     */\\n    function _checkUniNFT(uint256 _tokenId) internal view {\\n        (, , address token0, address token1, , , , , , , , ) = INonfungiblePositionManager(uniswapPositionManager)\\n            .positions(_tokenId);\\n        // only check token0 and token1, ignore fee.\\n        // If there are multiple wsqueeth/eth pools with different fee rate, we accept LP tokens from all of them.\\n        address wsqueethAddr = address(wPowerPerp); // cache storage variable\\n        address wethAddr = weth; // cache storage variable\\n        require(\\n            (token0 == wsqueethAddr && token1 == wethAddr) || (token1 == wsqueethAddr && token0 == wethAddr),\\n            \\\"Invalid nft\\\"\\n        );\\n    }\\n\\n    /**\\n     * @dev check that the vault is solvent and has enough collateral.\\n     */\\n    function _checkVault(uint256 _vaultId) internal view {\\n        if (_vaultId == 0) return;\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n\\n        require(_isVaultSafe(vault), \\\"Invalid state\\\");\\n    }\\n\\n    function _isVaultSafe(VaultLib.Vault memory _vault) internal view returns (bool) {\\n        uint256 ethDaiPrice = oracle.getTwapSafe(ethDaiPool, weth, dai, 300);\\n        int24 perpPoolTick = oracle.getTimeWeightedAverageTickSafe(powerPerpPool, 300);\\n        return\\n            VaultLib.isProperlyCollateralized(\\n                _vault,\\n                uniswapPositionManager,\\n                normalizationFactor,\\n                ethDaiPrice,\\n                perpPoolTick,\\n                isWethToken0\\n            );\\n    }\\n\\n    function _getFairPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxSafePeriod = _getMaxSafePeriod();\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n\\n    /**\\n     * return the smaller of the max periods of 2 pools\\n     */\\n    function _getMaxSafePeriod() internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = oracle.getMaxPeriod(ethDaiPool);\\n        uint32 maxPeriodPool2 = oracle.getMaxPeriod(powerPerpPool);\\n        return maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n    }\\n}\\n\"\n        },\n        \"hardhat/console.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >= 0.4.22 <0.9.0;\\n\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction _sendLogPayload(bytes memory payload) private view {\\n\\t\\tuint256 payloadLength = payload.length;\\n\\t\\taddress consoleAddress = CONSOLE_ADDRESS;\\n\\t\\tassembly {\\n\\t\\t\\tlet payloadStart := add(payload, 32)\\n\\t\\t\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n\\t\\t}\\n\\t}\\n\\n\\tfunction log() internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t}\\n\\n\\tfunction logInt(int p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n}\\n\"\n        },\n        \"contracts/interfaces/IWPowerPerp.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n        },\n        \"contracts/interfaces/IVaultManagerNFT.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IVaultManagerNFT is IERC721 {\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n        },\n        \"contracts/interfaces/IOracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n        },\n        \"contracts/interfaces/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./IERC721Upgradeable.sol\\\";\\nimport \\\"./IERC721MetadataUpgradeable.sol\\\";\\nimport \\\"./IERC721EnumerableUpgradeable.sol\\\";\\nimport \\\"./IERC721ReceiverUpgradeable.sol\\\";\\nimport \\\"../../introspection/ERC165Upgradeable.sol\\\";\\nimport \\\"../../math/SafeMathUpgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableSetUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableMapUpgradeable.sol\\\";\\nimport \\\"../../utils/StringsUpgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721EnumerableUpgradeable {\\n    using SafeMathUpgradeable for uint256;\\n    using AddressUpgradeable for address;\\n    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;\\n    using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;\\n    using StringsUpgradeable for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSetUpgradeable.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMapUpgradeable.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {\\n        __Context_init_unchained();\\n        __ERC165_init_unchained();\\n        __ERC721_init_unchained(name_, symbol_);\\n    }\\n\\n    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721Upgradeable.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721Upgradeable.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721Upgradeable.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721ReceiverUpgradeable(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n    uint256[41] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/access/Ownable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/math/SafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Address.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/VaultLib.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\\\";\\n\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    /** \\n     collateral is always eth, \\n     while we can also add a Uniswap V3 NFT in to the vault to reduce collateral amount.\\n    */\\n    struct Vault {\\n        address operator;\\n        // address NFTCollateralAddress; // the uni v3 pool address, may not need this if we only support ETH / SQUEETH;\\n        uint256 NftCollateralId; // the uni v3 pool NFT id\\n        uint256 collateralAmount;\\n        uint256 shortAmount;\\n    }\\n\\n    function addEthCollateral(Vault storage _vault, uint256 _amount) internal {\\n        _vault.collateralAmount = _vault.collateralAmount.add(_amount);\\n    }\\n\\n    function addUniNftCollateral(Vault storage _vault, uint256 _tokenId) internal {\\n        require(_vault.NftCollateralId == 0, \\\"Vault already had nft\\\");\\n        require(_tokenId != 0, \\\"invalid id\\\");\\n        _vault.NftCollateralId = _tokenId;\\n    }\\n\\n    function removeEthCollateral(Vault storage _vault, uint256 _amount) internal {\\n        _vault.collateralAmount = _vault.collateralAmount.sub(_amount);\\n    }\\n\\n    function removeUniNftCollateral(Vault storage _vault) internal returns (uint256 tokenId) {\\n        require(_vault.NftCollateralId != 0, \\\"Vault has no NFT\\\");\\n        tokenId = _vault.NftCollateralId;\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    function addShort(Vault storage _vault, uint256 _amount) internal {\\n        _vault.shortAmount = _vault.shortAmount.add(_amount);\\n    }\\n\\n    function removeShort(Vault storage _vault, uint256 _amount) internal {\\n        _vault.shortAmount = _vault.shortAmount.sub(_amount);\\n    }\\n\\n    /// @dev see if a vault is properly collateralized\\n    /// @param _vault the vault we want to check\\n    /// @param _positionManager address of the uni v3 position manager\\n    /// @param _normalizationFactor current _normalizationFactor\\n    /// @param _ethDaiPrice current eth price scaled by 1e18\\n    /// @param _wsqueethPoolTick current price tick for wsqueeth pool\\n    /// @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n    /// @return true if the vault is above water.\\n    function isProperlyCollateralized(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool) {\\n        if (_vault.shortAmount == 0) return true;\\n        return\\n            _isProperlyCollateralized(\\n                _vault,\\n                _positionManager,\\n                _normalizationFactor,\\n                _ethDaiPrice,\\n                _wsqueethPoolTick,\\n                _isWethToken0\\n            );\\n    }\\n\\n    /// @dev see if a vault is properly collateralized\\n    /// @param _vault the vault we want to check\\n    /// @param _positionManager address of the uni v3 position manager\\n    /// @param _normalizationFactor current _normalizationFactor\\n    /// @param _ethDaiPrice current eth price scaled by 1e18\\n    /// @param _wsqueethPoolTick current price tick for wsqueeth pool\\n    /// @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n    /// @return true if the vault is above water.\\n    function _isProperlyCollateralized(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool) {\\n        uint256 totalCollateral = _vault.collateralAmount;\\n        if (_vault.NftCollateralId != 0) {\\n            // if user deposit univ3 nft as collateral, see how much eth / squeeth the LP token has.\\n            (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n                _positionManager,\\n                _vault.NftCollateralId,\\n                _wsqueethPoolTick,\\n                _isWethToken0\\n            );\\n            // convert squeeth amount from NFT as equivalent amount of collateral.\\n            uint256 equivalentCollateral = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\n            // add ETH value from NFT as collateral.\\n            totalCollateral = totalCollateral.add(equivalentCollateral).add(nftEthAmount);\\n        }\\n        uint256 debtValueInETH = _vault.shortAmount.mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\n        return totalCollateral.mul(2) >= debtValueInETH.mul(3);\\n    }\\n\\n    /// @notice get how much eth / squeeth the LP position is worth.\\n    /// @param _positionManager address of the uni v3 position manager\\n    /// @param _tokenId lp token id\\n    /// @param _wsqueethPoolTick current price tick\\n    /// @param _isWethToken0 whether weth is token0 in the pool\\n    /// @return ethAmount the eth amount thie LP token is worth\\n    /// @return squeethAmount the squeeth amount this LP token is worth\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 squeethAmount) {\\n        (int24 tickLower, int24 tickUpper, uint128 liquidity) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wsqueethPoolTick,\\n            liquidity\\n        );\\n        return (_isWethToken0 ? amount0 : amount1, _isWethToken0 ? amount1 : amount0);\\n    }\\n\\n    /**\\n     * @notice get the LP info and tick bond of the LP position.\\n     * @param _positionManager address of the uni v3 position manager\\n     * @param _tokenId LP token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (, , , , , int24 tickLower, int24 tickUpper, uint128 liquidity, , , , ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity);\\n    }\\n\\n    /**\\n     * @notice get how much token0 / token1 a LP position is worth.\\n     * @param _tickLower address of the uni v3 position manager\\n     * @param _tickUpper LP token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 this LP token is worth\\n     * @return amount1 the amount of token1 this LP token is worth\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from squeethPool\\n        uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(_tick);\\n\\n        // the following line is copied from the _modifyPosition function implemented by Uniswap core.\\n        // we use the same logic to determine how much token0, token1 equals to given \\\"liquidity\\\"\\n        // https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/UniswapV3Pool.sol#L306\\n\\n        // use these 2 functions directly, cuz liquidity is always positive\\n        // getAmount0Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L209\\n        // getAmount1Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L225\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(_tickLower),\\n                TickMath.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/Power2Base.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {OracleLibrary} from \\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    /**\\n     * @dev return the index of the power perp in DAI, scaled by 18 decimals\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = _getTwap(_oracle, _ethDaiPool, _weth, _dai, _period);\\n        return ethDaiPrice.mul(ethDaiPrice).div(1e18);\\n    }\\n\\n    /**\\n     * @dev return the mark price of power perp in DAI, scaled by 18 decimals\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _squeethEthPool,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai,\\n        address _wsqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = _getTwap(_oracle, _ethDaiPool, _weth, _dai, _period);\\n        uint256 squeethEthPrice = _getTwap(_oracle, _squeethEthPool, address(_wsqueeth), _weth, _period);\\n\\n        return squeethEthPrice.mul(ethDaiPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @dev get fair collateral amount to pay out to a liquidator repaying _debtAmount debt\\n     * @dev the actual amount liquidator can get should have a x% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @return\\n     */\\n    function _getCollateralByRepayAmount(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _ethDaiPool,\\n        address _weth,\\n        address _dai,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethDaiPrice = IOracle(_oracle).getTwapSafe(_ethDaiPool, _weth, _dai, 600);\\n        return _debtAmount.mul(_normalizationFactor).mul(ethDaiPrice).div(1e36);\\n    }\\n\\n    /**\\n     * @dev request twap from our oracle.\\n     * @return price scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        uint256 twap = IOracle(_oracle).getTwap(_pool, _base, _quote, _period);\\n        require(twap != 0, \\\"WAP WAP WAP\\\");\\n\\n        return twap;\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _ethSettlementPrice eth price used for settlement. scaled with 1e18\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _ethSettlementPrice,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_ethSettlementPrice).div(1e36);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n            \"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\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function _getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN 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 initializer {\\n        __Context_init_unchained();\\n    }\\n\\n    function __Context_init_unchained() internal initializer {\\n    }\\n    function _msgSender() internal view virtual returns (address payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n    uint256[50] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165Upgradeable.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721MetadataUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721EnumerableUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721EnumerableUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721ReceiverUpgradeable {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165Upgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    function __ERC165_init() internal initializer {\\n        __ERC165_init_unchained();\\n    }\\n\\n    function __ERC165_init_unchained() internal initializer {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n    uint256[49] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMathUpgradeable {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary 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    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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 EnumerableSetUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Set type with\\n    // bytes32 values.\\n    // The Set implementation uses private functions, and user-facing\\n    // implementations (such as AddressSet) are just wrappers around the\\n    // underlying Set.\\n    // This means that we can only create new EnumerableSets for types that fit\\n    // in bytes32.\\n\\n    struct Set {\\n        // Storage of set values\\n        bytes32[] _values;\\n\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableMapUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMapUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary StringsUpgradeable {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !AddressUpgradeable.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/IERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165Upgradeable {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Context.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity >=0.5.0;\\n\\nimport './LowGasSafeMath.sol';\\nimport './SafeCast.sol';\\n\\nimport './FullMath.sol';\\nimport './UnsafeMath.sol';\\nimport './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 LowGasSafeMath for uint256;\\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            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            return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96).add(amount)));\\n        } else {\\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    /// @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                (\\n                    amount <= type(uint160).max\\n                        ? (amount << FixedPoint96.RESOLUTION) / liquidity\\n                        : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)\\n                );\\n\\n            return uint256(sqrtPX96).add(quotient).toUint160();\\n        } else {\\n            uint256 quotient =\\n                (\\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            return uint160(sqrtPX96 - quotient);\\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        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @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        return\\n            liquidity < 0\\n                ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\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        return\\n            liquidity < 0\\n                ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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        },\n        \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0 <0.8.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Oracle library\\n/// @notice Provides functions to integrate with V3 pool oracle\\nlibrary OracleLibrary {\\n    /// @notice Fetches time-weighted average tick using Uniswap V3 oracle\\n    /// @param pool Address of Uniswap V3 pool that we want to observe\\n    /// @param period Number of seconds in the past to start calculating time-weighted average\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - period) to block.timestamp\\n    function consult(address pool, uint32 period) internal view returns (int24 timeWeightedAverageTick) {\\n        require(period != 0, 'BP');\\n\\n        uint32[] memory secondAgos = new uint32[](2);\\n        secondAgos[0] = period;\\n        secondAgos[1] = 0;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / period);\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % period != 0)) timeWeightedAverageTick--;\\n    }\\n\\n    /// @notice Given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick Tick value used to calculate the quote\\n    /// @param baseAmount Amount of token to be converted\\n    /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/test/OracleTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester {\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwapSafe(_pool, _base, _quote, period);\\n  }\\n}\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Strings.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"contracts/periphery/ShortHelper.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\ncontract ShortHelper {\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWPowerPerp public immutable wsqueeth;\\n    IWETH9 public immutable weth;\\n    IVaultManagerNFT public immutable vaultNFT;\\n\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n\\n        IWPowerPerp _wsqueeth = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wsqueeth.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        vaultNFT = IVaultManagerNFT(_controller.vaultNFT());\\n        weth = _weth;\\n        controller = _controller;\\n        wsqueeth = _wsqueeth;\\n    }\\n\\n    /**\\n     * mint squeeth, trade with uniswap and send back premium in eth.\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint128 _shortSqueethAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable {\\n        (uint256 vaultId, uint256 wsqueethAmount) = controller.mint{value: msg.value}(\\n            _vaultId,\\n            _shortSqueethAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wsqueethAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this) && _exactInputParams.tokenOut == address(weth)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) vaultNFT.transferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * buy back some squeeth and close the position.\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _removeShortAmount,\\n        uint128 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable {\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get squeeth in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burn(_vaultId, _removeShortAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value - amountIn);\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"contracts/interfaces/IController.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IController {\\n    function vaultNFT() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    /**\\n     * put down collateral and mint squeeth.\\n     */\\n    function mint(\\n        uint256 _vaultId,\\n        uint128 _mintAmount,\\n        uint256 _nftId\\n    ) external payable returns (uint256 vaultId, uint256 _wSqueethMinted);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    /**\\n     * burn squueth and remove collateral from a vault.\\n     */\\n    function burn(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n            \"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\"\n        },\n        \"contracts/mocks/MockUniPositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress._getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/core/Oracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {OracleLibrary} from \\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\";\\n\\ncontract Oracle {\\n    /**\\n     * @notice get twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwap(_pool, _base, _quote, _period, uint256(1e18));\\n    }\\n\\n    /**\\n     * @notice get twap from the uniswap pool, never revert\\n     * @dev if period is larger than the max period stored by the pool, default to the max period.\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price scaled by 1e18\\n     */\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwapSafe(_pool, _base, _quote, _period, uint256(1e18));\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap.\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consult(_pool, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap from the uniswap pool, never revert\\n     * @dev if period is larger than the max period stored by the pool, default to the max period.\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _amountIn Amount of token to be converted\\n     * @return amountOut Amount of quoteToken received for baseAmount of baseToken\\n     */\\n    function _fetchTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint256 _amountIn\\n    ) internal view returns (uint256 amountOut) {\\n        // make sure the max period we use is reasonable\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod, _amountIn);\\n    }\\n\\n    /**\\n     * @notice get twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/dai price, eth is base token\\n     * @param _quote quote currency. to get eth/dai price, dai is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price scaled by 1e18\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint256 _amountIn\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consult(_pool, _period);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, toUint128(_amountIn), _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap.\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: The current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // index + 1 % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n\\n    /**\\n     * @notice Cast a uint256 to a uint128, revert on overflow\\n     * @param y The uint256 to be downcasted\\n     * @return z The downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y);\\n    }\\n}\\n\"\n        },\n        \"contracts/import/Uni.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"contracts/test/VaultTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _squeethPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 squeethAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _squeethPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n        },\n        \"contracts/mocks/MockWSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWSqueeth is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSqueeth\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockErc20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/core/WSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n/// @notice this is the ERC20 contract for long position of Squeeth\\n/// @dev this contract implements IWPowerPerp interface, makes it controllable by Controller.\\n/// @dev decimals of squeeth is chosen as 14.\\ncontract WSqueeth is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSqueeth\\\") {}\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * override decimals with 14.\\n     */\\n    function decimals() public pure override returns (uint8) {\\n        return 14;\\n    }\\n\\n    function init(address _controller) external initializer {\\n        controller = _controller;\\n    }\\n\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockVaultNFTManager.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract MockVaultNFTManager is ERC721Upgradeable {\\n    uint256 public nextId = 1;\\n\\n    function mintNFT(address _recipient) external returns (uint256 tokenId) {\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function burnNFT(uint256 _tokenId) external {\\n        _burn(_tokenId);\\n    }\\n}\\n\"\n        },\n        \"contracts/core/VaultManagerNFT.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract VaultNFTManager is ERC721Upgradeable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller);\\n        _;\\n    }\\n\\n    function init(address _controller) public initializer {\\n        // init nft\\n        __ERC721_init(\\\"Short Opyn Squeeth Position\\\", \\\"sSqueeth\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * mint new NFT, create a new vault struct\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n}\\n\"\n        }\n    },\n    \"settings\": {\n        \"optimizer\": {\n            \"enabled\": true,\n            \"runs\": 2000\n        },\n        \"outputSelection\": {\n            \"*\": {\n                \"*\": [\n                    \"abi\",\n                    \"evm.bytecode\",\n                    \"evm.deployedBytecode\",\n                    \"evm.methodIdentifiers\",\n                    \"metadata\",\n                    \"devdoc\",\n                    \"userdoc\",\n                    \"storageLayout\",\n                    \"evm.gasEstimates\"\n                ],\n                \"\": [\"ast\"]\n            }\n        },\n        \"metadata\": {\n            \"useLiteralContent\": true\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/rinkebyArbitrum/solcInputs/7ff94f89a93cd7aa904196251e75bdb3.json",
    "content": "{\n    \"language\": \"Solidity\",\n    \"sources\": {\n        \"contracts/core/Controller.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\nimport {IWSqueeth} from \\\"../interfaces/IWSqueeth.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract Controller is Initializable, Ownable {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    bool public isShutDown = false;\\n\\n    address public weth;\\n    address public dai;\\n    address public ethDaiPool;\\n    address public wSqueethEthPool;\\n    address public uniswapPositionManager;\\n\\n    uint256 public shutDownEthPriceSnapshot;\\n    uint256 public normalizationFactor;\\n    uint256 public lastFundingUpdateTimestamp;\\n\\n    bool public isWethToken0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IVaultManagerNFT public vaultNFT;\\n    IWSqueeth public wsqueeth;\\n    IOracle public oracle;\\n\\n    /// Events\\n    event OpenVault(uint256 vaultId);\\n    event CloseVault(uint256 vaultId);\\n    event DepositCollateral(uint256 vaultId, uint128 amount, uint128 collateralId);\\n    event DepositUniNftCollateral(uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(uint256 vaultId, uint256 amount, uint128 collateralId);\\n    event WithdrawUniNftCollateral(uint256 vaultId, uint256 tokenId);\\n    event MintShort(uint256 amount, uint256 vaultId);\\n    event BurnShort(uint256 amount, uint256 vaultId);\\n    event UpdateOperator(uint256 vaultId, address operator);\\n    event Liquidate(uint256 vaultId, uint256 debtAmount, uint256 collateralToSell);\\n    event NormalizationFactorUpdated(uint256 oldNormFactor, uint256 newNormFactor, uint256 timestamp);\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"shutdown\\\");\\n        _;\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * init controller with squeeth and short NFT address\\n     */\\n    function init(\\n        address _oracle,\\n        address _vaultNFT,\\n        address _squeeth,\\n        address _weth,\\n        address _dai,\\n        address _ethDaiPool,\\n        address _wSqueethEthPool,\\n        address _uniPositionManager\\n    ) public initializer {\\n        require(_oracle != address(0), \\\"Invalid oracle address\\\");\\n        require(_vaultNFT != address(0), \\\"Invalid vaultNFT address\\\");\\n        require(_squeeth != address(0), \\\"Invalid squeeth address\\\");\\n        require(_ethDaiPool != address(0), \\\"Invalid eth:dai pool address\\\");\\n        require(_wSqueethEthPool != address(0), \\\"Invalid wsqueeth:eth pool address\\\");\\n\\n        oracle = IOracle(_oracle);\\n        vaultNFT = IVaultManagerNFT(_vaultNFT);\\n        wsqueeth = IWSqueeth(_squeeth);\\n\\n        ethDaiPool = _ethDaiPool;\\n        wSqueethEthPool = _wSqueethEthPool;\\n        uniswapPositionManager = _uniPositionManager;\\n\\n        weth = _weth;\\n        dai = _dai;\\n\\n        normalizationFactor = 1e18;\\n        lastFundingUpdateTimestamp = block.timestamp;\\n\\n        isWethToken0 = weth < _squeeth;\\n    }\\n\\n    /**\\n     * put down collateral and mint squeeth.\\n     * This mints an amount of rSqueeth.\\n     */\\n    function mint(\\n        uint256 _vaultId,\\n        uint128 _mintAmount,\\n        uint256 _nftTokenId\\n    ) external payable notShutdown returns (uint256, uint256 _wSqueethMinted) {\\n        _applyFunding();\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_nftTokenId != 0) _depositUniNFT(msg.sender, _vaultId, _nftTokenId);\\n        if (_mintAmount > 0) {\\n            _wSqueethMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n        _checkVault(_vaultId);\\n        return (_vaultId, _wSqueethMinted);\\n    }\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notShutdown {\\n        _applyFunding();\\n        _addEthCollateral(_vaultId, msg.value);\\n    }\\n\\n    /**\\n     * Deposit Uni NFT as collateral\\n     */\\n    function depositUniNFT(uint256 _vaultId, uint256 _tokenId) external notShutdown {\\n        _applyFunding();\\n        _depositUniNFT(msg.sender, _vaultId, _tokenId);\\n    }\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable notShutdown {\\n        _applyFunding();\\n        _withdrawCollateral(msg.sender, _vaultId, _amount);\\n        _checkVault(_vaultId);\\n    }\\n\\n    /**\\n     * Withdraw Uni NFT from a vault\\n     */\\n    function withdrawUniNFT(uint256 _vaultId) external notShutdown {\\n        _applyFunding();\\n        _withdrawUniNFT(msg.sender, _vaultId);\\n        _checkVault(_vaultId);\\n    }\\n\\n    /**\\n     * burn squueth and remove collateral from a vault.\\n     * This burns an amount of wSqueeth.\\n     */\\n    function burn(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external notShutdown {\\n        _applyFunding();\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        _checkVault(_vaultId);\\n    }\\n\\n    function liquidate(uint256 _vaultId, uint256 _debtAmount) external notShutdown {\\n        _applyFunding();\\n\\n        VaultLib.Vault storage vault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(vault), \\\"Can not liquidate safe vault\\\");\\n\\n        require(_debtAmount <= vault.shortAmount.div(2), \\\"Can not repay more than 50% of vault debt\\\");\\n\\n        uint256 collateralPriceUSD = oracle.getTwapSafe(ethDaiPool, weth, dai, 600);\\n        uint256 collateralToSell = _debtAmount.mul(normalizationFactor).mul(collateralPriceUSD).div(1e36);\\n        collateralToSell = collateralToSell.add(collateralToSell.div(10));\\n\\n        wsqueeth.burn(msg.sender, _debtAmount);\\n        vault.removeShort(_debtAmount);\\n        vault.removeEthCollateral(collateralToSell);\\n        payable(msg.sender).sendValue(collateralToSell);\\n\\n        emit Liquidate(_vaultId, _debtAmount, collateralToSell);\\n    }\\n\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return _getIndex(_period);\\n    }\\n\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return _getDenormalizedMark(_period);\\n    }\\n\\n    /**\\n     * Authorize an address to modify the vault. Can be revoke by setting address to 0.\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(_vaultId, _operator);\\n    }\\n\\n    /**\\n     * shutdown the system and enable redeeming long and short\\n     */\\n    function shutDown() external onlyOwner {\\n        require(!isShutDown, \\\"shutdown\\\");\\n        isShutDown = true;\\n        shutDownEthPriceSnapshot = oracle.getTwapSafe(ethDaiPool, weth, dai, 600);\\n    }\\n\\n    function redeemLong(uint256 _wsqueethAmount) external {\\n        require(isShutDown, \\\"!shutdown\\\");\\n        wsqueeth.burn(msg.sender, _wsqueethAmount);\\n        // convert wSqueeth amount to real short position with normalizationFactor\\n        uint256 longValue = _wsqueethAmount.mul(normalizationFactor).mul(shutDownEthPriceSnapshot).div(1e36);\\n        payable(msg.sender).sendValue(longValue);\\n    }\\n\\n    function redeemShort(uint256 _vaultId) external {\\n        require(isShutDown, \\\"!shutdown\\\");\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"not allowed\\\");\\n\\n        uint256 _shortSqueethAmount = vaults[_vaultId].shortAmount;\\n        uint256 debt = _shortSqueethAmount.mul(shutDownEthPriceSnapshot).mul(normalizationFactor).div(1e36);\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = vaults[_vaultId].collateralAmount.sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it.\\n        vaults[_vaultId].shortAmount = 0;\\n        vaults[_vaultId].collateralAmount = 0;\\n\\n        // todo: handle uni nft collateral\\n\\n        payable(msg.sender).sendValue(excess);\\n    }\\n\\n    /**\\n     * Update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * a function to add eth into a contract, in case it got insolvent and have ensufficient eth to pay out.\\n     */\\n    function donate() external payable {}\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return vaultNFT.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    /**\\n     * create a new vault and bind it with a new NFT id.\\n     */\\n    function _openVault(address _recipient) internal returns (uint256 vaultId) {\\n        vaultId = vaultNFT.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(vaultId);\\n    }\\n\\n    function _depositUniNFT(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _tokenId\\n    ) internal {\\n        _checkUniNFT(_tokenId);\\n        vaults[_vaultId].addUniNftCollateral(_tokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(_account, address(this), _tokenId);\\n        emit DepositUniNftCollateral(_vaultId, _tokenId);\\n    }\\n\\n    /**\\n     * add collateral to a vault\\n     */\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        vaults[_vaultId].addEthCollateral(uint128(_amount));\\n        emit DepositCollateral(_vaultId, uint128(_amount), 0);\\n    }\\n\\n    /**\\n     * withdraw uni nft\\n     */\\n    function _withdrawUniNFT(address _account, uint256 _vaultId) internal {\\n        uint256 tokenId = vaults[_vaultId].removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).transferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniNftCollateral(_vaultId, tokenId);\\n    }\\n\\n    /**\\n     * remove collateral from the vault\\n     */\\n    function _withdrawCollateral(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n        vaults[_vaultId].removeEthCollateral(_amount);\\n        payable(_account).sendValue(_amount);\\n        emit WithdrawCollateral(_vaultId, _amount, 0);\\n    }\\n\\n    /**\\n     * mint wsqueeth (ERC20) to an account\\n     */\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _squeethAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"not allowed\\\");\\n\\n        amountToMint = _squeethAmount.mul(1e18).div(normalizationFactor);\\n        vaults[_vaultId].addShort(amountToMint);\\n        wsqueeth.mint(_account, amountToMint);\\n\\n        emit MintShort(amountToMint, _vaultId);\\n    }\\n\\n    /**\\n     * burn wsqueeth (ERC20) from an account.\\n     */\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        vaults[_vaultId].removeShort(_amount);\\n        wsqueeth.burn(_account, _amount);\\n\\n        emit BurnShort(_amount, _vaultId);\\n    }\\n\\n    /**\\n     * Update the normalized factor as a way to pay funding.\\n     */\\n    function _applyFunding() internal {\\n        uint32 period = uint32(block.timestamp - lastFundingUpdateTimestamp);\\n\\n        // make sure we use the same period for mark and index, and this period won't cause revert.\\n        uint32 fairPeriod = _getFairPeriodForOracle(period);\\n\\n        uint256 mark = _getDenormalizedMark(fairPeriod);\\n        uint256 index = _getIndex(fairPeriod);\\n        uint256 rFunding = (uint256(1e18).mul(uint256(period))).div(secInDay);\\n\\n        // mul by 1e36 to keep newNormalizationFactor in 18 decimals\\n        // uint256 newNormalizationFactor = (mark * 1e36) / (((1e18 + rFunding) * mark - index * rFunding));\\n        uint256 newNormalizationFactor = (mark.mul(1e36)).div(\\n            ((uint256(1e18).add(rFunding)).mul(mark).sub(index.mul(rFunding)))\\n        );\\n\\n        uint256 oldNormalizationFactor = normalizationFactor; // for event\\n        normalizationFactor = normalizationFactor.mul(newNormalizationFactor).div(1e18);\\n        lastFundingUpdateTimestamp = block.timestamp;\\n\\n        emit NormalizationFactorUpdated(oldNormalizationFactor, normalizationFactor, block.timestamp);\\n    }\\n\\n    /**\\n     * check that the specified tokenId is a valid squeeth/weth lp token.\\n     */\\n    function _checkUniNFT(uint256 _tokenId) internal view {\\n        (, , address token0, address token1, , , , , , , , ) = INonfungiblePositionManager(uniswapPositionManager)\\n            .positions(_tokenId);\\n        // only check token0 and token1, ignore fee.\\n        // If there are multiple wsqueeth/eth pools with different fee rate, we accept LP tokens from all of them.\\n        address wsqueethAddr = address(wsqueeth); // cache storage variable\\n        address wethAddr = weth; // cache storage variable\\n        require(\\n            (token0 == wsqueethAddr && token1 == wethAddr) || (token1 == wsqueethAddr && token0 == wethAddr),\\n            \\\"Invalid nft\\\"\\n        );\\n    }\\n\\n    /**\\n     * @dev check that the vault is solvent and has enough collateral.\\n     */\\n    function _checkVault(uint256 _vaultId) internal view {\\n        if (_vaultId == 0) return;\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n\\n        require(_isVaultSafe(vault), \\\"Invalid state\\\");\\n    }\\n\\n    function _isVaultSafe(VaultLib.Vault memory _vault) internal view returns (bool) {\\n        uint256 ethDaiPrice = oracle.getTwapSafe(ethDaiPool, weth, dai, 300);\\n        int24 squeethPoolTick = oracle.getTimeWeightedAverageTickSafe(wSqueethEthPool, 300);\\n        return\\n            VaultLib.isProperlyCollateralized(\\n                _vault,\\n                uniswapPositionManager,\\n                normalizationFactor,\\n                ethDaiPrice,\\n                squeethPoolTick,\\n                isWethToken0\\n            );\\n    }\\n\\n    function _getIndex(uint32 _period) internal view returns (uint256) {\\n        uint256 ethDaiPrice = _getTwap(ethDaiPool, weth, dai, _period);\\n        return ethDaiPrice.mul(ethDaiPrice).div(1e18);\\n    }\\n\\n    function _getDenormalizedMark(uint32 _period) public view returns (uint256) {\\n        uint256 ethDaiPrice = _getTwap(ethDaiPool, weth, dai, _period);\\n        uint256 squeethEthPrice = _getTwap(wSqueethEthPool, address(wsqueeth), weth, _period);\\n\\n        return squeethEthPrice.mul(ethDaiPrice).div(normalizationFactor);\\n    }\\n\\n    function _getFairPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxSafePeriod = _getMaxSafePeriod();\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n\\n    /**\\n     * return the smaller of the max periods of 2 pools\\n     */\\n    function _getMaxSafePeriod() internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = oracle.getMaxPeriod(ethDaiPool);\\n        uint32 maxPeriodPool2 = oracle.getMaxPeriod(wSqueethEthPool);\\n        return maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n    }\\n\\n    function _getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        uint256 twap = oracle.getTwap(_pool, _base, _quote, _period);\\n        require(twap != 0, \\\"WAP WAP WAP\\\");\\n\\n        return twap;\\n    }\\n}\\n\"\n        },\n        \"hardhat/console.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >= 0.4.22 <0.9.0;\\n\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction _sendLogPayload(bytes memory payload) private view {\\n\\t\\tuint256 payloadLength = payload.length;\\n\\t\\taddress consoleAddress = CONSOLE_ADDRESS;\\n\\t\\tassembly {\\n\\t\\t\\tlet payloadStart := add(payload, 32)\\n\\t\\t\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n\\t\\t}\\n\\t}\\n\\n\\tfunction log() internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t}\\n\\n\\tfunction logInt(int p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n}\\n\"\n        },\n        \"contracts/interfaces/IWSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWSqueeth is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n        },\n        \"contracts/interfaces/IVaultManagerNFT.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IVaultManagerNFT is IERC721 {\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n        },\n        \"contracts/interfaces/IOracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"./IERC721Upgradeable.sol\\\";\\nimport \\\"./IERC721MetadataUpgradeable.sol\\\";\\nimport \\\"./IERC721EnumerableUpgradeable.sol\\\";\\nimport \\\"./IERC721ReceiverUpgradeable.sol\\\";\\nimport \\\"../../introspection/ERC165Upgradeable.sol\\\";\\nimport \\\"../../math/SafeMathUpgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableSetUpgradeable.sol\\\";\\nimport \\\"../../utils/EnumerableMapUpgradeable.sol\\\";\\nimport \\\"../../utils/StringsUpgradeable.sol\\\";\\nimport \\\"../../proxy/Initializable.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable, IERC721EnumerableUpgradeable {\\n    using SafeMathUpgradeable for uint256;\\n    using AddressUpgradeable for address;\\n    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.UintSet;\\n    using EnumerableMapUpgradeable for EnumerableMapUpgradeable.UintToAddressMap;\\n    using StringsUpgradeable for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSetUpgradeable.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMapUpgradeable.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {\\n        __Context_init_unchained();\\n        __ERC165_init_unchained();\\n        __ERC721_init_unchained(name_, symbol_);\\n    }\\n\\n    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721Upgradeable.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721Upgradeable.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721Upgradeable.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721Upgradeable.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721ReceiverUpgradeable(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n    uint256[41] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/access/Ownable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/math/SafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Address.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/libs/VaultLib.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\\\";\\n\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    /** \\n     collateral is always eth, \\n     while we can also add a Uniswap V3 NFT in to the vault to reduce collateral amount.\\n    */\\n    struct Vault {\\n        address operator;\\n        // address NFTCollateralAddress; // the uni v3 pool address, may not need this if we only support ETH / SQUEETH;\\n        uint256 NftCollateralId; // the uni v3 pool NFT id\\n        uint256 collateralAmount;\\n        uint256 shortAmount;\\n    }\\n\\n    function addEthCollateral(Vault storage _vault, uint256 _amount) internal {\\n        _vault.collateralAmount = _vault.collateralAmount.add(_amount);\\n    }\\n\\n    function addUniNftCollateral(Vault storage _vault, uint256 _tokenId) internal {\\n        require(_vault.NftCollateralId == 0, \\\"Vault already had nft\\\");\\n        require(_tokenId != 0, \\\"invalid id\\\");\\n        _vault.NftCollateralId = _tokenId;\\n    }\\n\\n    function removeEthCollateral(Vault storage _vault, uint256 _amount) internal {\\n        _vault.collateralAmount = _vault.collateralAmount.sub(_amount);\\n    }\\n\\n    function removeUniNftCollateral(Vault storage _vault) internal returns (uint256 tokenId) {\\n        require(_vault.NftCollateralId != 0, \\\"Vault has no NFT\\\");\\n        tokenId = _vault.NftCollateralId;\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    function addShort(Vault storage _vault, uint256 _amount) internal {\\n        _vault.shortAmount = _vault.shortAmount.add(_amount);\\n    }\\n\\n    function removeShort(Vault storage _vault, uint256 _amount) internal {\\n        _vault.shortAmount = _vault.shortAmount.sub(_amount);\\n    }\\n\\n    /// @dev see if a vault is properly collateralized\\n    /// @param _vault the vault we want to check\\n    /// @param _positionManager address of the uni v3 position manager\\n    /// @param _normalizationFactor current _normalizationFactor\\n    /// @param _ethDaiPrice current eth price scaled by 1e18\\n    /// @param _wsqueethPoolTick current price tick for wsqueeth pool\\n    /// @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n    /// @return true if the vault is above water.\\n    function isProperlyCollateralized(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool) {\\n        if (_vault.shortAmount == 0) return true;\\n        return\\n            _isProperlyCollateralized(\\n                _vault,\\n                _positionManager,\\n                _normalizationFactor,\\n                _ethDaiPrice,\\n                _wsqueethPoolTick,\\n                _isWethToken0\\n            );\\n    }\\n\\n    /// @dev see if a vault is properly collateralized\\n    /// @param _vault the vault we want to check\\n    /// @param _positionManager address of the uni v3 position manager\\n    /// @param _normalizationFactor current _normalizationFactor\\n    /// @param _ethDaiPrice current eth price scaled by 1e18\\n    /// @param _wsqueethPoolTick current price tick for wsqueeth pool\\n    /// @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n    /// @return true if the vault is above water.\\n    function _isProperlyCollateralized(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethDaiPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool) {\\n        uint256 totalCollateral = _vault.collateralAmount;\\n        if (_vault.NftCollateralId != 0) {\\n            // if user deposit univ3 nft as collateral, see how much eth / squeeth the LP token has.\\n            (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n                _positionManager,\\n                _vault.NftCollateralId,\\n                _wsqueethPoolTick,\\n                _isWethToken0\\n            );\\n            // convert squeeth amount from NFT as equivalent amount of collateral.\\n            uint256 equivalentCollateral = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\n            // add ETH value from NFT as collateral.\\n            totalCollateral = totalCollateral.add(equivalentCollateral).add(nftEthAmount);\\n        }\\n        uint256 debtValueInETH = _vault.shortAmount.mul(_normalizationFactor).mul(_ethDaiPrice).div(1e36);\\n        return totalCollateral.mul(2) >= debtValueInETH.mul(3);\\n    }\\n\\n    /// @notice get how much eth / squeeth the LP position is worth.\\n    /// @param _positionManager address of the uni v3 position manager\\n    /// @param _tokenId lp token id\\n    /// @param _wsqueethPoolTick current price tick\\n    /// @param _isWethToken0 whether weth is token0 in the pool\\n    /// @return ethAmount the eth amount thie LP token is worth\\n    /// @return squeethAmount the squeeth amount this LP token is worth\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 squeethAmount) {\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(_positionManager, _tokenId, _wsqueethPoolTick);\\n        return (_isWethToken0 ? amount0 : amount1, _isWethToken0 ? amount1 : amount0);\\n    }\\n\\n    /// @notice get how much token0 / token1 a LP position is worth.\\n    /// @param _positionManager address of the uni v3 position manager\\n    /// @param _tokenId LP token id\\n    /// @param _tick current price tick used for calculation\\n    /// @return amount0 the amount of token0 this LP token is worth\\n    /// @return amount1 the amount of token1 this LP token is worth\\n    function _getToken0Token1Balances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _tick\\n    ) internal view returns (uint256 amount0, uint256 amount1) {\\n        // get the LP info and tick bond of the LP position.\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (, , , , , int24 tickLower, int24 tickUpper, uint128 liquidity, , , , ) = positionManager.positions(_tokenId);\\n\\n        // get the current price and tick from squeethPool\\n        uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(_tick);\\n\\n        // the following line is copied from the _modifyPosition function implemented by Uniswap core.\\n        // we use the same logic to determine how much token0, token1 equals to given \\\"liquidity\\\"\\n        // https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/UniswapV3Pool.sol#L306\\n\\n        // use these 2 functions directly, cuz liquidity is always positive\\n        // getAmount0Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L209\\n        // getAmount1Delta: https://github.com/Uniswap/uniswap-v3-core/blob/b2c5555d696428c40c4b236069b3528b2317f3c1/contracts/libraries/SqrtPriceMath.sol#L225\\n\\n        if (_tick < tickLower) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                true\\n            );\\n        } else if (_tick < tickUpper) {\\n            amount0 = SqrtPriceMath.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtPriceX96,\\n                liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMath.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n            \"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\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function _getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN 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 initializer {\\n        __Context_init_unchained();\\n    }\\n\\n    function __Context_init_unchained() internal initializer {\\n    }\\n    function _msgSender() internal view virtual returns (address payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n    uint256[50] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165Upgradeable.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721MetadataUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721EnumerableUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721EnumerableUpgradeable is IERC721Upgradeable {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721ReceiverUpgradeable {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/ERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165Upgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    function __ERC165_init() internal initializer {\\n        __ERC165_init_unchained();\\n    }\\n\\n    function __ERC165_init_unchained() internal initializer {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n    uint256[49] private __gap;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMathUpgradeable {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary 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    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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 EnumerableSetUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Set type with\\n    // bytes32 values.\\n    // The Set implementation uses private functions, and user-facing\\n    // implementations (such as AddressSet) are just wrappers around the\\n    // underlying Set.\\n    // This means that we can only create new EnumerableSets for types that fit\\n    // in bytes32.\\n\\n    struct Set {\\n        // Storage of set values\\n        bytes32[] _values;\\n\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts-upgradeable/utils/EnumerableMapUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMapUpgradeable {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary StringsUpgradeable {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !AddressUpgradeable.isContract(address(this));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts-upgradeable/introspection/IERC165Upgradeable.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165Upgradeable {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Context.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity >=0.5.0;\\n\\nimport './LowGasSafeMath.sol';\\nimport './SafeCast.sol';\\n\\nimport './FullMath.sol';\\nimport './UnsafeMath.sol';\\nimport './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 LowGasSafeMath for uint256;\\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            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            return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96).add(amount)));\\n        } else {\\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    /// @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                (\\n                    amount <= type(uint160).max\\n                        ? (amount << FixedPoint96.RESOLUTION) / liquidity\\n                        : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)\\n                );\\n\\n            return uint256(sqrtPX96).add(quotient).toUint160();\\n        } else {\\n            uint256 quotient =\\n                (\\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            return uint160(sqrtPX96 - quotient);\\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        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @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        return\\n            liquidity < 0\\n                ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\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        return\\n            liquidity < 0\\n                ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256()\\n                : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256();\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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        },\n        \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n            \"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\"\n        },\n        \"contracts/test/VaultTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _squeethPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 squeethAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _squeethPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n            \"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\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress._getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n        },\n        \"contracts/import/Uni.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n        },\n        \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n            \"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\"\n        },\n        \"contracts/periphery/ShortHelper.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IWSqueeth} from \\\"../interfaces/IWSqueeth.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IVaultManagerNFT} from \\\"../interfaces/IVaultManagerNFT.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\ncontract ShortHelper {\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWSqueeth public immutable wsqueeth;\\n    IWETH9 public immutable weth;\\n    IVaultManagerNFT public immutable vaultNFT;\\n\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n\\n        IWSqueeth _wsqueeth = IWSqueeth(_controller.wsqueeth());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wsqueeth.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        vaultNFT = IVaultManagerNFT(_controller.vaultNFT());\\n        weth = _weth;\\n        controller = _controller;\\n        wsqueeth = _wsqueeth;\\n    }\\n\\n    /**\\n     * mint squeeth, trade with uniswap and send back premium in eth.\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint128 _shortSqueethAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable {\\n        (uint256 vaultId, uint256 wsqueethAmount) = controller.mint{value: msg.value}(\\n            _vaultId,\\n            _shortSqueethAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wsqueethAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this) && _exactInputParams.tokenOut == address(weth)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) vaultNFT.transferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * buy back some squeeth and close the position.\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _removeShortAmount,\\n        uint128 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable {\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get squeeth in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burn(_vaultId, _removeShortAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value - amountIn);\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n}\\n\"\n        },\n        \"contracts/interfaces/IWETH9.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n        },\n        \"contracts/interfaces/IController.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IController {\\n    function vaultNFT() external view returns (address);\\n\\n    function wsqueeth() external view returns (address);\\n\\n    /**\\n     * put down collateral and mint squeeth.\\n     */\\n    function mint(\\n        uint256 _vaultId,\\n        uint128 _mintAmount,\\n        uint256 _nftId\\n    ) external payable returns (uint256 vaultId, uint256 _wSqueethMinted);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    /**\\n     * burn squueth and remove collateral from a vault.\\n     */\\n    function burn(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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        },\n        \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/utils/Strings.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n        },\n        \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n        },\n        \"contracts/mocks/MockWSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWSqueeth is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSqueeth\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockErc20.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/core/WSqueeth.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\ncontract WSqueeth is ERC20, Initializable {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Squeeth\\\", \\\"WSqueeth\\\") {}\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * override decimals with 14.\\n     */\\n    function decimals() public pure override returns (uint8) {\\n        return 14;\\n    }\\n\\n    function init(address _controller) external initializer {\\n        controller = _controller;\\n    }\\n\\n    function mint(address _account, uint256 _amount) external onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockUniPositionManager.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity =0.7.6;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n}\\n\"\n        },\n        \"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\": {\n            \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0 <0.8.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Oracle library\\n/// @notice Provides functions to integrate with V3 pool oracle\\nlibrary OracleLibrary {\\n    /// @notice Fetches time-weighted average tick using Uniswap V3 oracle\\n    /// @param pool Address of Uniswap V3 pool that we want to observe\\n    /// @param period Number of seconds in the past to start calculating time-weighted average\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - period) to block.timestamp\\n    function consult(address pool, uint32 period) internal view returns (int24 timeWeightedAverageTick) {\\n        require(period != 0, 'BP');\\n\\n        uint32[] memory secondAgos = new uint32[](2);\\n        secondAgos[0] = period;\\n        secondAgos[1] = 0;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / period);\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % period != 0)) timeWeightedAverageTick--;\\n    }\\n\\n    /// @notice Given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick Tick value used to calculate the quote\\n    /// @param baseAmount Amount of token to be converted\\n    /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n        },\n        \"contracts/core/Oracle.sol\": {\n            \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\nimport {OracleLibrary} from \\\"@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol\\\";\\n\\ncontract Oracle {\\n    using OracleLibrary for address;\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwap(_pool, _base, _quote, _period, uint256(1e18));\\n    }\\n\\n    function getTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) external view returns (uint256) {\\n        return _fetchTwapSafe(_pool, _base, _quote, _period, uint256(1e18));\\n    }\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /// @notice get time weighed average tick, not converted to price\\n    /// @dev this function will not revert\\n    /// @param _pool address of the pool\\n    /// @param _period period in second that we want to calculate average on\\n    /// @return timeWeightedAverageTick the time weighted average tick\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consult(_pool, requestPeriod);\\n    }\\n\\n    /**\\n     * request TWAP from uni v3 pool\\n     * if the period requested is too long, capped at max period we can go back\\n     */\\n    function _fetchTwapSafe(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _twapPeriod,\\n        uint256 _amountIn\\n    ) internal view returns (uint256 amountOut) {\\n        // make sure the max period we use is reasonable\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _twapPeriod > maxPeriod ? maxPeriod : _twapPeriod;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod, _amountIn);\\n    }\\n\\n    /**\\n     * request TWAP from a uni v3 pool\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _twapPeriod,\\n        uint256 _amountIn\\n    ) internal view returns (uint256 amountOut) {\\n        int24 twapTick = OracleLibrary.consult(_pool, _twapPeriod);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, toUint128(_amountIn), _base, _quote);\\n    }\\n\\n    /**\\n     * get the max number of period we can use to request twap for a pool\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: The current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // index + 1 % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n\\n    /// @notice Cast a uint256 to a uint128, revert on overflow\\n    /// @param y The uint256 to be downcasted\\n    /// @return z The downcasted integer, now type uint128\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y);\\n    }\\n}\\n\"\n        },\n        \"contracts/mocks/MockVaultNFTManager.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract MockVaultNFTManager is ERC721Upgradeable {\\n    uint256 public nextId = 1;\\n\\n    function mintNFT(address _recipient) external returns (uint256 tokenId) {\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function burnNFT(uint256 _tokenId) external {\\n        _burn(_tokenId);\\n    }\\n}\\n\"\n        },\n        \"contracts/core/VaultManagerNFT.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC721Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\\\";\\n\\ncontract VaultNFTManager is ERC721Upgradeable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller);\\n        _;\\n    }\\n\\n    function init(address _controller) public initializer {\\n        // init nft\\n        __ERC721_init(\\\"Short Opyn Squeeth Position\\\", \\\"sSqueeth\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * mint new NFT, create a new vault struct\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _mint(_recipient, (tokenId = nextId++));\\n    }\\n}\\n\"\n        },\n        \"contracts/test/OracleTester.sol\": {\n            \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester {\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwapSafe(_pool, _base, _quote, period);\\n  }\\n}\"\n        }\n    },\n    \"settings\": {\n        \"optimizer\": {\n            \"enabled\": true,\n            \"runs\": 2000\n        },\n        \"outputSelection\": {\n            \"*\": {\n                \"*\": [\n                    \"abi\",\n                    \"evm.bytecode\",\n                    \"evm.deployedBytecode\",\n                    \"evm.methodIdentifiers\",\n                    \"metadata\",\n                    \"devdoc\",\n                    \"userdoc\",\n                    \"storageLayout\",\n                    \"evm.gasEstimates\"\n                ],\n                \"\": [\"ast\"]\n            }\n        },\n        \"metadata\": {\n            \"useLiteralContent\": true\n        }\n    }\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/.chainId",
    "content": "3"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/ABDKMath64x64.json",
    "content": "{\n  \"address\": \"0xc3eEC23787Ea5F9310332B7970C3570B6dc933a4\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"x\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"y\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"divu\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"x\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"name\": \"exp_2\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"x\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"name\": \"log_2\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int128\",\n          \"name\": \"\",\n          \"type\": \"int128\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x5045dc8552400278136b22d71148a577d0e361fe802b758580d21486a8bf6f07\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xf668606B896389066a39B132741763e1ca6d76a2\",\n    \"contractAddress\": \"0xc3eEC23787Ea5F9310332B7970C3570B6dc933a4\",\n    \"transactionIndex\": 8,\n    \"gasUsed\": \"941465\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0xad5b97dee70e8a8d2595be1d5f1d3aef86222b61909e783896534b4f48230856\",\n    \"transactionHash\": \"0x5045dc8552400278136b22d71148a577d0e361fe802b758580d21486a8bf6f07\",\n    \"logs\": [],\n    \"blockNumber\": 11808044,\n    \"cumulativeGasUsed\": \"2834278\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"5f450d03d2b8109eaf06de68c57d8c2b\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"x\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"y\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"divu\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"int128\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"x\\\",\\\"type\\\":\\\"int128\\\"}],\\\"name\\\":\\\"exp_2\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"int128\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"x\\\",\\\"type\\\":\\\"int128\\\"}],\\\"name\\\":\\\"log_2\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"int128\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"divu(uint256,uint256)\\\":{\\\"params\\\":{\\\"x\\\":\\\"unsigned 256-bit integer number\\\",\\\"y\\\":\\\"unsigned 256-bit integer number\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"signed 64.64-bit fixed point number\\\"}},\\\"exp_2(int128)\\\":{\\\"params\\\":{\\\"x\\\":\\\"signed 64.64-bit fixed point number\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"signed 64.64-bit fixed point number\\\"}},\\\"log_2(int128)\\\":{\\\"params\\\":{\\\"x\\\":\\\"signed 64.64-bit fixed point number\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"signed 64.64-bit fixed point number\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"divu(uint256,uint256)\\\":{\\\"notice\\\":\\\"Calculate x / y rounding towards zero, where x and y are unsigned 256-bit integer numbers.  Revert on overflow or when y is zero.\\\"},\\\"exp_2(int128)\\\":{\\\"notice\\\":\\\"Calculate binary exponent of x.  Revert on overflow.\\\"},\\\"log_2(int128)\\\":{\\\"notice\\\":\\\"Calculate binary logarithm of x.  Revert if x <= 0.\\\"}},\\\"notice\\\":\\\"Smart contract library of mathematical functions operating with signed 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is basically a simple fraction whose numerator is signed 128-bit integer and denominator is 2^64.  As long as denominator is always the same, there is no need to store it, thus in Solidity signed 64.64-bit fixed point numbers are represented by int128 type holding only the numerator. Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4 Changes - some function visibility switched to public, solidity version set to 0.7.x Changes (cont) - revert strings added solidity version set to ^0.7.0\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/libs/ABDKMath64x64.sol\\\":\\\"ABDKMath64x64\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"contracts/libs/ABDKMath64x64.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: BSD-4-Clause\\\\n/*\\\\n * ABDK Math 64.64 Smart Contract Library.  Copyright \\\\u00a9 2019 by ABDK Consulting.\\\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\\\n * Copyright (c) 2019, ABDK Consulting\\\\n *\\\\n * All rights reserved.\\\\n *\\\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\\\n *\\\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\\\n */\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * Smart contract library of mathematical functions operating with signed\\\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\\\n * represented by int128 type holding only the numerator.\\\\n *\\\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\\\n * Changes (cont) - revert strings added\\\\n * solidity version set to ^0.7.0\\\\n */\\\\nlibrary ABDKMath64x64 {\\\\n    /*\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * -2^127\\\\n     */\\\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\\\n\\\\n    /*\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * 2^127-1\\\\n     */\\\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @param y signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\\\n        int256 result = (int256(x) * y) >> 64;\\\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\\\\\"MUL-OVUF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64 fixed point number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 256-bit integer number\\\\n     */\\\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\\\n        if (y == 0) return 0;\\\\n\\\\n        require(x >= 0, \\\\\\\"MULU-X0\\\\\\\");\\\\n\\\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\\\n        uint256 hi = uint256(x) * (y >> 128);\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"MULU-OF1\\\\\\\");\\\\n        hi <<= 64;\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\\\\\"MULU-OF2\\\\\\\");\\\\n        return hi + lo;\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\\\n        require(y != 0, \\\\\\\"DIVU-INF\\\\\\\");\\\\n        uint128 result = divuu(x, y);\\\\n        require(result <= uint128(MAX_64x64), \\\\\\\"DIVU-OF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function log_2(int128 x) public pure returns (int128) {\\\\n        require(x > 0, \\\\\\\"LOG_2-X0\\\\\\\");\\\\n\\\\n        int256 msb = 0;\\\\n        int256 xc = x;\\\\n        if (xc >= 0x10000000000000000) {\\\\n            xc >>= 64;\\\\n            msb += 64;\\\\n        }\\\\n        if (xc >= 0x100000000) {\\\\n            xc >>= 32;\\\\n            msb += 32;\\\\n        }\\\\n        if (xc >= 0x10000) {\\\\n            xc >>= 16;\\\\n            msb += 16;\\\\n        }\\\\n        if (xc >= 0x100) {\\\\n            xc >>= 8;\\\\n            msb += 8;\\\\n        }\\\\n        if (xc >= 0x10) {\\\\n            xc >>= 4;\\\\n            msb += 4;\\\\n        }\\\\n        if (xc >= 0x4) {\\\\n            xc >>= 2;\\\\n            msb += 2;\\\\n        }\\\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n        int256 result = (msb - 64) << 64;\\\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\\\n            ux *= ux;\\\\n            uint256 b = ux >> 255;\\\\n            ux >>= 127 + b;\\\\n            result += bit * int256(b);\\\\n        }\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary exponent of x.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function exp_2(int128 x) public pure returns (int128) {\\\\n        require(x < 0x400000000000000000, \\\\\\\"EXP_2-OF\\\\\\\"); // Overflow\\\\n\\\\n        if (x < -0x400000000000000000) return 0; // Underflow\\\\n\\\\n        uint256 result = 0x80000000000000000000000000000000;\\\\n\\\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\\\n\\\\n        result >>= uint256(63 - (x >> 64));\\\\n        require(result <= uint256(MAX_64x64));\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 64.64-bit fixed point number\\\\n     */\\\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\\\n        require(y != 0);\\\\n\\\\n        uint256 result;\\\\n\\\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\\\n        else {\\\\n            uint256 msb = 192;\\\\n            uint256 xc = x >> 192;\\\\n            if (xc >= 0x100000000) {\\\\n                xc >>= 32;\\\\n                msb += 32;\\\\n            }\\\\n            if (xc >= 0x10000) {\\\\n                xc >>= 16;\\\\n                msb += 16;\\\\n            }\\\\n            if (xc >= 0x100) {\\\\n                xc >>= 8;\\\\n                msb += 8;\\\\n            }\\\\n            if (xc >= 0x10) {\\\\n                xc >>= 4;\\\\n                msb += 4;\\\\n            }\\\\n            if (xc >= 0x4) {\\\\n                xc >>= 2;\\\\n                msb += 2;\\\\n            }\\\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF1\\\\\\\");\\\\n\\\\n            uint256 hi = result * (y >> 128);\\\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\\\n\\\\n            uint256 xh = x >> 192;\\\\n            uint256 xl = x << 64;\\\\n\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n            lo = hi << 128;\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n\\\\n            assert(xh == hi >> 128);\\\\n\\\\n            result += xl / y;\\\\n        }\\\\n\\\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF2\\\\\\\");\\\\n        return uint128(result);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x56efa7c16e4fffb37ad80af15bd042d9f92532a4553d6b12915e3fa21609ad66\\\",\\\"license\\\":\\\"BSD-4-Clause\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x611035610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80632cbbdee514610050578063fc193cf214610087578063fc505d37146100a7575b600080fd5b6100706004803603602081101561006657600080fd5b5035600f0b6100ca565b60408051600f9290920b8252519081900360200190f35b6100706004803603602081101561009d57600080fd5b5035600f0b6101f8565b610070600480360360408110156100bd57600080fd5b5080359060200135610d19565b60008082600f0b13610123576040805162461bcd60e51b815260206004820152600860248201527f4c4f475f322d5830000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000600f83900b680100000000000000008112610142576040918201911d5b6401000000008112610156576020918201911d5b620100008112610168576010918201911d5b6101008112610179576008918201911d5b60108112610189576004918201911d5b60048112610199576002918201911d5b600281126101a8576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b60008113156101eb5790800260ff81901c8281029390930192607f011c9060011d6101c5565b509093505050505b919050565b60006840000000000000000082600f0b1261025a576040805162461bcd60e51b815260206004820152600860248201527f4558505f322d4f46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b683fffffffffffffffff1982600f0b1215610277575060006101f3565b6f8000000000000000000000000000000060006780000000000000008416600f0b13156102b55770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b60008367400000000000000016600f0b13156102e2577001306fe0a31b7152de8d5a46305c85edec0260801c5b60008367200000000000000016600f0b131561030f577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b60008367100000000000000016600f0b131561033c5770010b5586cf9890f6298b92b71842a983630260801c5b60008367080000000000000016600f0b1315610369577001059b0d31585743ae7c548eb68ca417fd0260801c5b60008367040000000000000016600f0b131561039657700102c9a3e778060ee6f7caca4f7a29bde80260801c5b60008367020000000000000016600f0b13156103c35770010163da9fb33356d84a66ae336dcdfa3f0260801c5b60008367010000000000000016600f0b13156103f057700100b1afa5abcbed6129ab13ec11dc95430260801c5b600083668000000000000016600f0b131561041c5770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600083664000000000000016600f0b1315610448577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600083662000000000000016600f0b131561047457700100162f3904051fa128bca9c55c31e5df0260801c5b600083661000000000000016600f0b13156104a0577001000b175effdc76ba38e31671ca9397250260801c5b600083660800000000000016600f0b13156104cc57700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600083660400000000000016600f0b13156104f85770010002c5cc37da9491d0985c348c68e7b30260801c5b600083660200000000000016600f0b1315610524577001000162e525ee054754457d59952920260260801c5b600083660100000000000016600f0b13156105505770010000b17255775c040618bf4a4ade83fc0260801c5b6000836580000000000016600f0b131561057b577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6000836540000000000016600f0b13156105a657700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6000836520000000000016600f0b13156105d15770010000162e43f4f831060e02d839a9d16d0260801c5b6000836510000000000016600f0b13156105fc57700100000b1721bcfc99d9f890ea069117630260801c5b6000836508000000000016600f0b13156106275770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6000836504000000000016600f0b1315610652577001000002c5c863b73f016468f6bac5ca2b0260801c5b6000836502000000000016600f0b131561067d57700100000162e430e5a18f6119e3c02282a50260801c5b6000836501000000000016600f0b13156106a8577001000000b1721835514b86e6d96efd1bfe0260801c5b60008364800000000016600f0b13156106d257700100000058b90c0b48c6be5df846c5b2ef0260801c5b60008364400000000016600f0b13156106fc5770010000002c5c8601cc6b9e94213c72737a0260801c5b60008364200000000016600f0b1315610726577001000000162e42fff037df38aa2b219f060260801c5b60008364100000000016600f0b13156107505770010000000b17217fba9c739aa5819f44f90260801c5b60008364080000000016600f0b131561077a577001000000058b90bfcdee5acd3c1cedc8230260801c5b60008364040000000016600f0b13156107a457700100000002c5c85fe31f35a6a30da1be500260801c5b60008364020000000016600f0b13156107ce5770010000000162e42ff0999ce3541b9fffcf0260801c5b60008364010000000016600f0b13156107f857700100000000b17217f80f4ef5aadda455540260801c5b600083638000000016600f0b13156108215770010000000058b90bfbf8479bd5a81b51ad0260801c5b600083634000000016600f0b131561084a577001000000002c5c85fdf84bd62ae30a74cc0260801c5b600083632000000016600f0b131561087357700100000000162e42fefb2fed257559bdaa0260801c5b600083631000000016600f0b131561089c577001000000000b17217f7d5a7716bba4a9ae0260801c5b600083630800000016600f0b13156108c557700100000000058b90bfbe9ddbac5e109cce0260801c5b600083630400000016600f0b13156108ee5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600083630200000016600f0b1315610917577001000000000162e42fefa494f1478fde050260801c5b600083630100000016600f0b13156109405770010000000000b17217f7d20cf927c8e94c0260801c5b6000836280000016600f0b1315610968577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6000836240000016600f0b131561099057700100000000002c5c85fdf477b662b269450260801c5b6000836220000016600f0b13156109b85770010000000000162e42fefa3ae53369388c0260801c5b6000836210000016600f0b13156109e057700100000000000b17217f7d1d351a389d400260801c5b6000836208000016600f0b1315610a085770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6000836204000016600f0b1315610a30577001000000000002c5c85fdf4741bea6e77e0260801c5b6000836202000016600f0b1315610a5857700100000000000162e42fefa39fe95583c20260801c5b6000836201000016600f0b1315610a80577001000000000000b17217f7d1cfb72b45e10260801c5b60008361800016600f0b1315610aa757700100000000000058b90bfbe8e7cc35c3f00260801c5b60008361400016600f0b1315610ace5770010000000000002c5c85fdf473e242ea380260801c5b60008361200016600f0b1315610af5577001000000000000162e42fefa39f02b772c0260801c5b60008361100016600f0b1315610b1c5770010000000000000b17217f7d1cf7d83c1a0260801c5b60008361080016600f0b1315610b43577001000000000000058b90bfbe8e7bdcbe2e0260801c5b60008361040016600f0b1315610b6a57700100000000000002c5c85fdf473dea871f0260801c5b60008361020016600f0b1315610b915770010000000000000162e42fefa39ef44d910260801c5b60008361010016600f0b1315610bb857700100000000000000b17217f7d1cf79e9490260801c5b600083608016600f0b1315610bde5770010000000000000058b90bfbe8e7bce5440260801c5b600083604016600f0b1315610c04577001000000000000002c5c85fdf473de6eca0260801c5b600083602016600f0b1315610c2a57700100000000000000162e42fefa39ef366f0260801c5b600083601016600f0b1315610c50577001000000000000000b17217f7d1cf79afa0260801c5b600083600816600f0b1315610c7657700100000000000000058b90bfbe8e7bcd6d0260801c5b600083600416600f0b1315610c9c5770010000000000000002c5c85fdf473de6b20260801c5b600083600216600f0b1315610cc2577001000000000000000162e42fefa39ef3580260801c5b600083600116600f0b1315610ce85770010000000000000000b17217f7d1cf79ab0260801c5b600f83810b60401d603f03900b1c6f7fffffffffffffffffffffffffffffff811115610d1357600080fd5b92915050565b600081610d6d576040805162461bcd60e51b815260206004820152600860248201527f444956552d494e46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000610d798484610df9565b90506f7fffffffffffffffffffffffffffffff6fffffffffffffffffffffffffffffffff82161115610df2576040805162461bcd60e51b815260206004820152600760248201527f444956552d4f4600000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b9392505050565b600081610e0557600080fd5b600077ffffffffffffffffffffffffffffffffffffffffffffffff8411610e3b5782604085901b81610e3357fe5b049050610f9a565b60c084811c6401000000008110610e54576020918201911c5b620100008110610e66576010918201911c5b6101008110610e77576008918201911c5b60108110610e87576004918201911c5b60048110610e97576002918201911c5b60028110610ea6576001820191505b60bf820360018603901c6001018260ff0387901b81610ec157fe5b0492506fffffffffffffffffffffffffffffffff831115610f29576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46310000000000000000000000000000000000000000000000604482015290519081900360640190fd5b608085901c83026fffffffffffffffffffffffffffffffff8616840260c088901c604089901b82811015610f5e576001820391505b608084901b92900382811015610f75576001820391505b829003608084901c8214610f8557fe5b888181610f8e57fe5b04870196505050505050505b6fffffffffffffffffffffffffffffffff811115610df2576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46320000000000000000000000000000000000000000000000604482015290519081900360640190fdfea264697066735822122040574cb227dea1d1a5db4fb4ab0552095e5133a47a8b45993e447ebd0471743a64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c80632cbbdee514610050578063fc193cf214610087578063fc505d37146100a7575b600080fd5b6100706004803603602081101561006657600080fd5b5035600f0b6100ca565b60408051600f9290920b8252519081900360200190f35b6100706004803603602081101561009d57600080fd5b5035600f0b6101f8565b610070600480360360408110156100bd57600080fd5b5080359060200135610d19565b60008082600f0b13610123576040805162461bcd60e51b815260206004820152600860248201527f4c4f475f322d5830000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000600f83900b680100000000000000008112610142576040918201911d5b6401000000008112610156576020918201911d5b620100008112610168576010918201911d5b6101008112610179576008918201911d5b60108112610189576004918201911d5b60048112610199576002918201911d5b600281126101a8576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b60008113156101eb5790800260ff81901c8281029390930192607f011c9060011d6101c5565b509093505050505b919050565b60006840000000000000000082600f0b1261025a576040805162461bcd60e51b815260206004820152600860248201527f4558505f322d4f46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b683fffffffffffffffff1982600f0b1215610277575060006101f3565b6f8000000000000000000000000000000060006780000000000000008416600f0b13156102b55770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b60008367400000000000000016600f0b13156102e2577001306fe0a31b7152de8d5a46305c85edec0260801c5b60008367200000000000000016600f0b131561030f577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b60008367100000000000000016600f0b131561033c5770010b5586cf9890f6298b92b71842a983630260801c5b60008367080000000000000016600f0b1315610369577001059b0d31585743ae7c548eb68ca417fd0260801c5b60008367040000000000000016600f0b131561039657700102c9a3e778060ee6f7caca4f7a29bde80260801c5b60008367020000000000000016600f0b13156103c35770010163da9fb33356d84a66ae336dcdfa3f0260801c5b60008367010000000000000016600f0b13156103f057700100b1afa5abcbed6129ab13ec11dc95430260801c5b600083668000000000000016600f0b131561041c5770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600083664000000000000016600f0b1315610448577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600083662000000000000016600f0b131561047457700100162f3904051fa128bca9c55c31e5df0260801c5b600083661000000000000016600f0b13156104a0577001000b175effdc76ba38e31671ca9397250260801c5b600083660800000000000016600f0b13156104cc57700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600083660400000000000016600f0b13156104f85770010002c5cc37da9491d0985c348c68e7b30260801c5b600083660200000000000016600f0b1315610524577001000162e525ee054754457d59952920260260801c5b600083660100000000000016600f0b13156105505770010000b17255775c040618bf4a4ade83fc0260801c5b6000836580000000000016600f0b131561057b577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6000836540000000000016600f0b13156105a657700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6000836520000000000016600f0b13156105d15770010000162e43f4f831060e02d839a9d16d0260801c5b6000836510000000000016600f0b13156105fc57700100000b1721bcfc99d9f890ea069117630260801c5b6000836508000000000016600f0b13156106275770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6000836504000000000016600f0b1315610652577001000002c5c863b73f016468f6bac5ca2b0260801c5b6000836502000000000016600f0b131561067d57700100000162e430e5a18f6119e3c02282a50260801c5b6000836501000000000016600f0b13156106a8577001000000b1721835514b86e6d96efd1bfe0260801c5b60008364800000000016600f0b13156106d257700100000058b90c0b48c6be5df846c5b2ef0260801c5b60008364400000000016600f0b13156106fc5770010000002c5c8601cc6b9e94213c72737a0260801c5b60008364200000000016600f0b1315610726577001000000162e42fff037df38aa2b219f060260801c5b60008364100000000016600f0b13156107505770010000000b17217fba9c739aa5819f44f90260801c5b60008364080000000016600f0b131561077a577001000000058b90bfcdee5acd3c1cedc8230260801c5b60008364040000000016600f0b13156107a457700100000002c5c85fe31f35a6a30da1be500260801c5b60008364020000000016600f0b13156107ce5770010000000162e42ff0999ce3541b9fffcf0260801c5b60008364010000000016600f0b13156107f857700100000000b17217f80f4ef5aadda455540260801c5b600083638000000016600f0b13156108215770010000000058b90bfbf8479bd5a81b51ad0260801c5b600083634000000016600f0b131561084a577001000000002c5c85fdf84bd62ae30a74cc0260801c5b600083632000000016600f0b131561087357700100000000162e42fefb2fed257559bdaa0260801c5b600083631000000016600f0b131561089c577001000000000b17217f7d5a7716bba4a9ae0260801c5b600083630800000016600f0b13156108c557700100000000058b90bfbe9ddbac5e109cce0260801c5b600083630400000016600f0b13156108ee5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600083630200000016600f0b1315610917577001000000000162e42fefa494f1478fde050260801c5b600083630100000016600f0b13156109405770010000000000b17217f7d20cf927c8e94c0260801c5b6000836280000016600f0b1315610968577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6000836240000016600f0b131561099057700100000000002c5c85fdf477b662b269450260801c5b6000836220000016600f0b13156109b85770010000000000162e42fefa3ae53369388c0260801c5b6000836210000016600f0b13156109e057700100000000000b17217f7d1d351a389d400260801c5b6000836208000016600f0b1315610a085770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6000836204000016600f0b1315610a30577001000000000002c5c85fdf4741bea6e77e0260801c5b6000836202000016600f0b1315610a5857700100000000000162e42fefa39fe95583c20260801c5b6000836201000016600f0b1315610a80577001000000000000b17217f7d1cfb72b45e10260801c5b60008361800016600f0b1315610aa757700100000000000058b90bfbe8e7cc35c3f00260801c5b60008361400016600f0b1315610ace5770010000000000002c5c85fdf473e242ea380260801c5b60008361200016600f0b1315610af5577001000000000000162e42fefa39f02b772c0260801c5b60008361100016600f0b1315610b1c5770010000000000000b17217f7d1cf7d83c1a0260801c5b60008361080016600f0b1315610b43577001000000000000058b90bfbe8e7bdcbe2e0260801c5b60008361040016600f0b1315610b6a57700100000000000002c5c85fdf473dea871f0260801c5b60008361020016600f0b1315610b915770010000000000000162e42fefa39ef44d910260801c5b60008361010016600f0b1315610bb857700100000000000000b17217f7d1cf79e9490260801c5b600083608016600f0b1315610bde5770010000000000000058b90bfbe8e7bce5440260801c5b600083604016600f0b1315610c04577001000000000000002c5c85fdf473de6eca0260801c5b600083602016600f0b1315610c2a57700100000000000000162e42fefa39ef366f0260801c5b600083601016600f0b1315610c50577001000000000000000b17217f7d1cf79afa0260801c5b600083600816600f0b1315610c7657700100000000000000058b90bfbe8e7bcd6d0260801c5b600083600416600f0b1315610c9c5770010000000000000002c5c85fdf473de6b20260801c5b600083600216600f0b1315610cc2577001000000000000000162e42fefa39ef3580260801c5b600083600116600f0b1315610ce85770010000000000000000b17217f7d1cf79ab0260801c5b600f83810b60401d603f03900b1c6f7fffffffffffffffffffffffffffffff811115610d1357600080fd5b92915050565b600081610d6d576040805162461bcd60e51b815260206004820152600860248201527f444956552d494e46000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000610d798484610df9565b90506f7fffffffffffffffffffffffffffffff6fffffffffffffffffffffffffffffffff82161115610df2576040805162461bcd60e51b815260206004820152600760248201527f444956552d4f4600000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b9392505050565b600081610e0557600080fd5b600077ffffffffffffffffffffffffffffffffffffffffffffffff8411610e3b5782604085901b81610e3357fe5b049050610f9a565b60c084811c6401000000008110610e54576020918201911c5b620100008110610e66576010918201911c5b6101008110610e77576008918201911c5b60108110610e87576004918201911c5b60048110610e97576002918201911c5b60028110610ea6576001820191505b60bf820360018603901c6001018260ff0387901b81610ec157fe5b0492506fffffffffffffffffffffffffffffffff831115610f29576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46310000000000000000000000000000000000000000000000604482015290519081900360640190fd5b608085901c83026fffffffffffffffffffffffffffffffff8616840260c088901c604089901b82811015610f5e576001820391505b608084901b92900382811015610f75576001820391505b829003608084901c8214610f8557fe5b888181610f8e57fe5b04870196505050505050505b6fffffffffffffffffffffffffffffffff811115610df2576040805162461bcd60e51b815260206004820152600960248201527f44495655552d4f46320000000000000000000000000000000000000000000000604482015290519081900360640190fdfea264697066735822122040574cb227dea1d1a5db4fb4ab0552095e5133a47a8b45993e447ebd0471743a64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"divu(uint256,uint256)\": {\n        \"params\": {\n          \"x\": \"unsigned 256-bit integer number\",\n          \"y\": \"unsigned 256-bit integer number\"\n        },\n        \"returns\": {\n          \"_0\": \"signed 64.64-bit fixed point number\"\n        }\n      },\n      \"exp_2(int128)\": {\n        \"params\": {\n          \"x\": \"signed 64.64-bit fixed point number\"\n        },\n        \"returns\": {\n          \"_0\": \"signed 64.64-bit fixed point number\"\n        }\n      },\n      \"log_2(int128)\": {\n        \"params\": {\n          \"x\": \"signed 64.64-bit fixed point number\"\n        },\n        \"returns\": {\n          \"_0\": \"signed 64.64-bit fixed point number\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"divu(uint256,uint256)\": {\n        \"notice\": \"Calculate x / y rounding towards zero, where x and y are unsigned 256-bit integer numbers.  Revert on overflow or when y is zero.\"\n      },\n      \"exp_2(int128)\": {\n        \"notice\": \"Calculate binary exponent of x.  Revert on overflow.\"\n      },\n      \"log_2(int128)\": {\n        \"notice\": \"Calculate binary logarithm of x.  Revert if x <= 0.\"\n      }\n    },\n    \"notice\": \"Smart contract library of mathematical functions operating with signed 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is basically a simple fraction whose numerator is signed 128-bit integer and denominator is 2^64.  As long as denominator is always the same, there is no need to store it, thus in Solidity signed 64.64-bit fixed point numbers are represented by int128 type holding only the numerator. Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4 Changes - some function visibility switched to public, solidity version set to 0.7.x Changes (cont) - revert strings added solidity version set to ^0.7.0\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/Controller.json",
    "content": "{\n  \"address\": \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_oracle\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_shortPowerPerp\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wPowerPerp\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_weth\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_quoteCurrency\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_ethQuoteCurrencyPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wPowerPerpPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniPositionManager\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_feeTier\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"BurnShort\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"DepositCollateral\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"DepositUniPositionToken\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"oldFee\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newFee\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FeeRateUpdated\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"oldFeeRecipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"newFeeRecipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"FeeRecipientUpdated\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"liquidator\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"debtAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"collateralPaid\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Liquidate\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"MintShort\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"oldNormFactor\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newNormFactor\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"lastModificationTimestamp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"timestamp\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"NormalizationFactorUpdated\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"OpenVault\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"pausesLeft\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Paused\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"payoutAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"RedeemLong\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vauldId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"collateralAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"RedeemShort\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethRedeemed\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpRedeemed\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpBurned\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wPowerPerpExcess\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"bounty\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ReduceDebt\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"indexForSettlement\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Shutdown\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"unpauser\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"UnPaused\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"UpdateOperator\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawCollateral\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawUniPositionToken\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"FUNDING_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"TWAP_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"applyFunding\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_powerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_withdrawAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burnPowerPerpAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_withdrawAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burnWPowerPerpAmount\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"deposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniTokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"depositUniPositionToken\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"donate\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"ethQuoteCurrencyPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"feeRate\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"feeRecipient\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"feeTier\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getDenormalizedMark\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getDenormalizedMarkForFunding\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getExpectedNormalizationFactor\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getUnscaledIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"indexForSettlement\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isShutDown\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isSystemPaused\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"isVaultSafe\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"lastFundingUpdateTimestamp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"\",\n          \"type\": \"uint128\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"lastPauseTime\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxDebtAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"liquidate\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_powerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniTokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"mintPowerPerpAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniTokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"mintWPowerPerpAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"normalizationFactor\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"\",\n          \"type\": \"uint128\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onERC721Received\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"oracle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"pause\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"pausesLeft\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"quoteCurrency\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPerpAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"redeemLong\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"redeemShort\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"reduceDebt\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"reduceDebtShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_newFeeRate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setFeeRate\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_newFeeRecipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"setFeeRecipient\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"shortPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"shutDown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"unPauseAnyone\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"unPauseOwner\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_operator\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"updateOperator\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"vaults\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"NftCollateralId\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint96\",\n          \"name\": \"collateralAmount\",\n          \"type\": \"uint96\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"shortAmount\",\n          \"type\": \"uint128\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerpPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdrawUniPositionToken\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0xd7239d1c0630f843371e61300dc37949d55bbbe683424ac39c30706aa3c87b46\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xf668606B896389066a39B132741763e1ca6d76a2\",\n    \"contractAddress\": \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n    \"transactionIndex\": 16,\n    \"gasUsed\": \"5402942\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000001000000018000000000000000000000000000020000000000000000000800000000100000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000020000000000001000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x6bbfab489066d100c3aa7d31980b64d5ada03dfdc391a5fcbd3a19235e381aab\",\n    \"transactionHash\": \"0xd7239d1c0630f843371e61300dc37949d55bbbe683424ac39c30706aa3c87b46\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 16,\n        \"blockNumber\": 11808049,\n        \"transactionHash\": \"0xd7239d1c0630f843371e61300dc37949d55bbbe683424ac39c30706aa3c87b46\",\n        \"address\": \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n        \"topics\": [\n          \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x000000000000000000000000f668606b896389066a39b132741763e1ca6d76a2\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 17,\n        \"blockHash\": \"0x6bbfab489066d100c3aa7d31980b64d5ada03dfdc391a5fcbd3a19235e381aab\"\n      }\n    ],\n    \"blockNumber\": 11808049,\n    \"cumulativeGasUsed\": \"6757006\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0xBD9F4bE886653177D22fA9c79FD0DFc41407fC89\",\n    \"0x49721ED2d693F3653BC1216b8E330fA53CFC80eD\",\n    \"0xa4222f78d23593e82Aa74742d25D06720DCa4ab7\",\n    \"0xc778417e063141139fce010982780140aa0cd5ab\",\n    \"0x27415c30d8c87437becbd4f98474f26e712047f4\",\n    \"0x8356AbC730a218c24446C2c85708F373f354F0D8\",\n    \"0x921c384F79de1BAe96d6f33E3E5b8d0B2B34cb68\",\n    \"0x8c7C1F786dA4DEe7d4bB49697A9B0C0c8Fb328e0\",\n    3000\n  ],\n  \"solcInputHash\": \"5f450d03d2b8109eaf06de68c57d8c2b\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_oracle\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_shortPowerPerp\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wPowerPerp\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_weth\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_quoteCurrency\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_ethQuoteCurrencyPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniPositionManager\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_feeTier\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"BurnShort\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"DepositCollateral\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"DepositUniPositionToken\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"oldFee\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newFee\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FeeRateUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"oldFeeRecipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newFeeRecipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"FeeRecipientUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"liquidator\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"debtAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralPaid\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Liquidate\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"MintShort\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"oldNormFactor\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newNormFactor\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"lastModificationTimestamp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"timestamp\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"NormalizationFactorUpdated\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"OpenVault\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"pausesLeft\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Paused\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"payoutAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"RedeemLong\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vauldId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"RedeemShort\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethRedeemed\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpRedeemed\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpBurned\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpExcess\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bounty\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ReduceDebt\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"indexForSettlement\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Shutdown\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"unpauser\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"UnPaused\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"UpdateOperator\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawCollateral\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawUniPositionToken\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"FUNDING_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"TWAP_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"applyFunding\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burnPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burnWPowerPerpAmount\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"deposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"depositUniPositionToken\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"donate\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"ethQuoteCurrencyPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"feeRate\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"feeRecipient\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"feeTier\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getDenormalizedMark\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getDenormalizedMarkForFunding\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getExpectedNormalizationFactor\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getUnscaledIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"indexForSettlement\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isShutDown\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isSystemPaused\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"isVaultSafe\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"lastFundingUpdateTimestamp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"lastPauseTime\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxDebtAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"liquidate\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mintPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniTokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mintWPowerPerpAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"normalizationFactor\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onERC721Received\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"oracle\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"pause\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"pausesLeft\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"quoteCurrency\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"redeemLong\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"redeemShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"reduceDebt\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"reduceDebtShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_newFeeRate\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setFeeRate\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_newFeeRecipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"setFeeRecipient\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"shortPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"shutDown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"unPauseAnyone\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"unPauseOwner\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"updateOperator\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"vaults\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"NftCollateralId\\\",\\\"type\\\":\\\"uint32\\\"},{\\\"internalType\\\":\\\"uint96\\\",\\\"name\\\":\\\"collateralAmount\\\",\\\"type\\\":\\\"uint96\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"shortAmount\\\",\\\"type\\\":\\\"uint128\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdrawUniPositionToken\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"burnPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_powerPerpAmount\\\":\\\"amount of powerPerp to burn\\\",\\\"_vaultId\\\":\\\"id of the vault\\\",\\\"_withdrawAmount\\\":\\\"amount of eth to withdraw\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"amount of wPowerPerp burned\\\"}},\\\"burnWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to burn\\\",\\\"_withdrawAmount\\\":\\\"amount of eth to withdraw\\\"}},\\\"constructor\\\":{\\\"params\\\":{\\\"_ethQuoteCurrencyPool\\\":\\\"uniswap v3 pool for weth / quoteCurrency\\\",\\\"_oracle\\\":\\\"oracle address\\\",\\\"_quoteCurrency\\\":\\\"quoteCurrency address\\\",\\\"_shortPowerPerp\\\":\\\"ERC721 token address representing the short position\\\",\\\"_uniPositionManager\\\":\\\"uniswap v3 position manager address\\\",\\\"_wPowerPerp\\\":\\\"ERC20 token address representing the long position\\\",\\\"_wPowerPerpPool\\\":\\\"uniswap v3 pool for wPowerPerp / weth\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"deposit(uint256)\\\":{\\\"details\\\":\\\"deposit collateral into a vault\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"depositUniPositionToken(uint256,uint256)\\\":{\\\"params\\\":{\\\"_uniTokenId\\\":\\\"uniswap position token id\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"getDenormalizedMark(uint32)\\\":{\\\"params\\\":{\\\"_period\\\":\\\"period of time for the twap in seconds\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"mark price denominated in $USD, scaled by 1e18\\\"}},\\\"getDenormalizedMarkForFunding(uint32)\\\":{\\\"details\\\":\\\"this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\\",\\\"params\\\":{\\\"_period\\\":\\\"period which you want to calculate twap with\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"mark price denominated in $USD, scaled by 1e18\\\"}},\\\"getExpectedNormalizationFactor()\\\":{\\\"details\\\":\\\"can be used for on-chain and off-chain calculations\\\"},\\\"getIndex(uint32)\\\":{\\\"details\\\":\\\"the index price is scaled down by INDEX_SCALE in the associated PowerXBase librarythis is the index price used when calculating funding and for collateralization\\\",\\\"params\\\":{\\\"_period\\\":\\\"period which you want to calculate twap with\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"index price denominated in $USD, scaled by 1e18\\\"}},\\\"getUnscaledIndex(uint32)\\\":{\\\"details\\\":\\\"this is the mark that would be be used for future funding after a new normalization factor is applied\\\",\\\"params\\\":{\\\"_period\\\":\\\"period which you want to calculate twap with\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"index price denominated in $USD, scaled by 1e18\\\"}},\\\"isVaultSafe(uint256)\\\":{\\\"details\\\":\\\"return if the vault is properly collateralized\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"true if the vault is properly collateralized\\\"}},\\\"liquidate(uint256,uint256)\\\":{\\\"details\\\":\\\"liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateralnormally can only liquidate 50% of a vault's debtif a vault is under dust limit after a liquidation can fully liquidatewill attempt to reduceDebt first, and can earn a bounty if sucessful\\\",\\\"params\\\":{\\\"_maxDebtAmount\\\":\\\"max amount of wPowerPerpetual to repay\\\",\\\"_vaultId\\\":\\\"vault to liquidate\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"amount of wPowerPerp repaid\\\"}},\\\"mintPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_powerPerpAmount\\\":\\\"amount of powerPerp to mint\\\",\\\"_uniTokenId\\\":\\\"uniswap v3 position token id (additional collateral)\\\",\\\"_vaultId\\\":\\\"vault to mint wPowerPerp in\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"vaultId\\\",\\\"_1\\\":\\\"amount of wPowerPerp minted\\\"}},\\\"mintWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_uniTokenId\\\":\\\"uniswap v3 position token id (additional collateral)\\\",\\\"_vaultId\\\":\\\"vault to mint wPowerPerp in\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to mint\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"vaultId\\\"}},\\\"onERC721Received(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"accept erc721 from safeTransferFrom and safeMint after callback\\\",\\\"returns\\\":{\\\"_0\\\":\\\"returns received selector\\\"}},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"pause()\\\":{\\\"details\\\":\\\"can only be called for 365 days since the contract was launched or 4 times\\\"},\\\"redeemLong(uint256)\\\":{\\\"params\\\":{\\\"_wPerpAmount\\\":\\\"amount of wPowerPerp to burn\\\"}},\\\"redeemShort(uint256)\\\":{\\\"details\\\":\\\"short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"vault id\\\"}},\\\"reduceDebt(uint256)\\\":{\\\"details\\\":\\\"the caller won't get any bounty. this is expected to be used by vault owner\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"target vault\\\"}},\\\"reduceDebtShutdown(uint256)\\\":{\\\"details\\\":\\\"the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\\",\\\"params\\\":{\\\"_vaultId\\\":\\\"vault containing uniswap v3 position to liquidate\\\"}},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"setFeeRate(uint256)\\\":{\\\"details\\\":\\\"this function cannot be called if the feeRecipient is still un-set\\\",\\\"params\\\":{\\\"_newFeeRate\\\":\\\"new fee rate in basis points. can't be higher than 1%\\\"}},\\\"setFeeRecipient(address)\\\":{\\\"details\\\":\\\"this should be a contract handling insurance\\\",\\\"params\\\":{\\\"_newFeeRecipient\\\":\\\"new fee recipient\\\"}},\\\"shutDown()\\\":{\\\"details\\\":\\\"this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\\"},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"unPauseAnyone()\\\":{\\\"details\\\":\\\"anyone can unpause the contract after 24 hours\\\"},\\\"unPauseOwner()\\\":{\\\"details\\\":\\\"owner can unpause at any time\\\"},\\\"updateOperator(uint256,address)\\\":{\\\"details\\\":\\\"can be revoke by setting address to 0\\\",\\\"params\\\":{\\\"_operator\\\":\\\"new operator address\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"withdraw(uint256,uint256)\\\":{\\\"params\\\":{\\\"_amount\\\":\\\"amount of eth to withdraw\\\",\\\"_vaultId\\\":\\\"id of the vault\\\"}},\\\"withdrawUniPositionToken(uint256)\\\":{\\\"params\\\":{\\\"_vaultId\\\":\\\"id of the vault\\\"}}},\\\"stateVariables\\\":{\\\"ONE\\\":{\\\"details\\\":\\\"basic unit used for calculation\\\"},\\\"PAUSE_TIME_LIMIT\\\":{\\\"details\\\":\\\"system can only be paused for 182 days from deployment\\\"},\\\"feeRate\\\":{\\\"details\\\":\\\"fee rate in basis point. feeRate of 1 = 0.01%\\\"},\\\"indexForSettlement\\\":{\\\"details\\\":\\\"the settlement price for each wPowerPerp for settlement\\\"},\\\"vaults\\\":{\\\"details\\\":\\\"vault data storage\\\"},\\\"wPowerPerpPool\\\":{\\\"details\\\":\\\"address of the powerPerp/weth pool\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"events\\\":{\\\"OpenVault(address,uint256)\\\":{\\\"notice\\\":\\\"Events\\\"}},\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"applyFunding()\\\":{\\\"notice\\\":\\\"update the normalization factor as a way to pay funding\\\"},\\\"burnPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"burn powerPerp and remove collateral from a vault\\\"},\\\"burnWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"burn wPowerPerp and remove collateral from a vault\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"constructor\\\"},\\\"depositUniPositionToken(uint256,uint256)\\\":{\\\"notice\\\":\\\"deposit uniswap position token into a vault to increase collateral ratio\\\"},\\\"donate()\\\":{\\\"notice\\\":\\\"add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\\"},\\\"getDenormalizedMark(uint32)\\\":{\\\"notice\\\":\\\"get the expected mark price of powerPerp after funding has been applied\\\"},\\\"getDenormalizedMarkForFunding(uint32)\\\":{\\\"notice\\\":\\\"get the mark price of powerPerp before funding has been applied\\\"},\\\"getExpectedNormalizationFactor()\\\":{\\\"notice\\\":\\\"returns the expected normalization factor, if the funding is paid right now\\\"},\\\"getIndex(uint32)\\\":{\\\"notice\\\":\\\"get the index price of the powerPerp, scaled down\\\"},\\\"getUnscaledIndex(uint32)\\\":{\\\"notice\\\":\\\"the unscaled index of the power perp in USD, scaled by 18 decimals\\\"},\\\"liquidate(uint256,uint256)\\\":{\\\"notice\\\":\\\"if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\\"},\\\"mintPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\\"},\\\"mintWPowerPerpAmount(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"deposit collateral and mint wPowerPerp\\\"},\\\"pause()\\\":{\\\"notice\\\":\\\"pause the system for up to 24 hours after which any one can unpause\\\"},\\\"redeemLong(uint256)\\\":{\\\"notice\\\":\\\"redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\\"},\\\"redeemShort(uint256)\\\":{\\\"notice\\\":\\\"redeem short position when the system is shutdown\\\"},\\\"reduceDebt(uint256)\\\":{\\\"notice\\\":\\\"withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\\"},\\\"reduceDebtShutdown(uint256)\\\":{\\\"notice\\\":\\\"after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by forceif a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\\"},\\\"setFeeRate(uint256)\\\":{\\\"notice\\\":\\\"set the fee rate when user mints\\\"},\\\"setFeeRecipient(address)\\\":{\\\"notice\\\":\\\"set the recipient who will receive the fee\\\"},\\\"shutDown()\\\":{\\\"notice\\\":\\\"shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactorshort positions can be redeemed for vault collateral minus value of debtpause (if not paused) and then immediately shutdown the system, can be called when paused already\\\"},\\\"unPauseAnyone()\\\":{\\\"notice\\\":\\\"unpause the contract\\\"},\\\"unPauseOwner()\\\":{\\\"notice\\\":\\\"unpause the contract\\\"},\\\"updateOperator(uint256,address)\\\":{\\\"notice\\\":\\\"authorize an address to modify the vault\\\"},\\\"withdraw(uint256,uint256)\\\":{\\\"notice\\\":\\\"withdraw collateral from a vault\\\"},\\\"withdrawUniPositionToken(uint256)\\\":{\\\"notice\\\":\\\"withdraw uniswap v3 position token from a vault\\\"}},\\\"notice\\\":\\\"Error C0: Paused C1: Not paused C2: Shutdown C3: Not shutdown C4: Invalid oracle address C5: Invalid shortPowerPerp address C6: Invalid wPowerPerp address C7: Invalid weth address C8: Invalid quote currency address C9: Invalid eth:quoteCurrency pool address C10: Invalid wPowerPerp:eth pool address C11: Invalid Uniswap position manager C12: Can not liquidate safe vault C13: Invalid address C14: Set fee recipient first C15: Fee too high C16: Paused too many times C17: Pause time limit exceeded C18: Not enough paused time has passed C19: Cannot receive eth C20: Not allowed C21: Need full liquidation C22: Dust vault left C23: Invalid nft C24: Invalid state C25: 0 liquidity Uniswap position token C26: Wrong fee tier for NFT deposit\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/Controller.sol\\\":\\\"Controller\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/core/Controller.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IERC721Receiver} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\\\\\";\\\\n\\\\n//contract\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\nimport {ReentrancyGuard} from \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ABDKMath64x64} from \\\\\\\"../libs/ABDKMath64x64.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"../libs/Uint256Casting.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\n\\\\n/**\\\\n *\\\\n * Error\\\\n * C0: Paused\\\\n * C1: Not paused\\\\n * C2: Shutdown\\\\n * C3: Not shutdown\\\\n * C4: Invalid oracle address\\\\n * C5: Invalid shortPowerPerp address\\\\n * C6: Invalid wPowerPerp address\\\\n * C7: Invalid weth address\\\\n * C8: Invalid quote currency address\\\\n * C9: Invalid eth:quoteCurrency pool address\\\\n * C10: Invalid wPowerPerp:eth pool address\\\\n * C11: Invalid Uniswap position manager\\\\n * C12: Can not liquidate safe vault\\\\n * C13: Invalid address\\\\n * C14: Set fee recipient first\\\\n * C15: Fee too high\\\\n * C16: Paused too many times\\\\n * C17: Pause time limit exceeded\\\\n * C18: Not enough paused time has passed\\\\n * C19: Cannot receive eth\\\\n * C20: Not allowed\\\\n * C21: Need full liquidation\\\\n * C22: Dust vault left\\\\n * C23: Invalid nft\\\\n * C24: Invalid state\\\\n * C25: 0 liquidity Uniswap position token\\\\n * C26: Wrong fee tier for NFT deposit\\\\n */\\\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n    using ABDKMath64x64 for int128;\\\\n    using VaultLib for VaultLib.Vault;\\\\n    using Address for address payable;\\\\n\\\\n    uint256 internal constant MIN_COLLATERAL = 6.9 ether;\\\\n    /// @dev system can only be paused for 182 days from deployment\\\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\\\n\\\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\\\n    uint24 public immutable feeTier;\\\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\\\n\\\\n    //80% of index\\\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\\\n    //140% of index\\\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\\\n    // 10%\\\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\\\n    // 2%\\\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\\\n\\\\n    /// @dev basic unit used for calculation\\\\n    uint256 private constant ONE = 1e18;\\\\n\\\\n    address public immutable weth;\\\\n    address public immutable quoteCurrency;\\\\n    address public immutable ethQuoteCurrencyPool;\\\\n    /// @dev address of the powerPerp/weth pool\\\\n    address public immutable wPowerPerpPool;\\\\n    address internal immutable uniswapPositionManager;\\\\n    address public immutable shortPowerPerp;\\\\n    address public immutable wPowerPerp;\\\\n    address public immutable oracle;\\\\n    address public feeRecipient;\\\\n\\\\n    uint256 internal immutable deployTimestamp;\\\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\\\n    uint256 public feeRate;\\\\n    /// @dev the settlement price for each wPowerPerp for settlement\\\\n    uint256 public indexForSettlement;\\\\n\\\\n    uint256 public pausesLeft = 4;\\\\n    uint256 public lastPauseTime;\\\\n\\\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\\\n    uint128 public normalizationFactor;\\\\n    uint128 public lastFundingUpdateTimestamp;\\\\n\\\\n    bool internal immutable isWethToken0;\\\\n    bool public isShutDown;\\\\n    bool public isSystemPaused;\\\\n\\\\n    /// @dev vault data storage\\\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\\\n\\\\n    /// Events\\\\n    event OpenVault(address sender, uint256 vaultId);\\\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\\\n    event ReduceDebt(\\\\n        address sender,\\\\n        uint256 vaultId,\\\\n        uint256 ethRedeemed,\\\\n        uint256 wPowerPerpRedeemed,\\\\n        uint256 wPowerPerpBurned,\\\\n        uint256 wPowerPerpExcess,\\\\n        uint256 bounty\\\\n    );\\\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\\\n    event NormalizationFactorUpdated(\\\\n        uint256 oldNormFactor,\\\\n        uint256 newNormFactor,\\\\n        uint256 lastModificationTimestamp,\\\\n        uint256 timestamp\\\\n    );\\\\n    event Paused(uint256 pausesLeft);\\\\n    event UnPaused(address unpauser);\\\\n    event Shutdown(uint256 indexForSettlement);\\\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\\\n\\\\n    modifier notPaused() {\\\\n        require(!isSystemPaused, \\\\\\\"C0\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier isPaused() {\\\\n        require(isSystemPaused, \\\\\\\"C1\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier notShutdown() {\\\\n        require(!isShutDown, \\\\\\\"C2\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier isShutdown() {\\\\n        require(isShutDown, \\\\\\\"C3\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice constructor\\\\n     * @param _oracle oracle address\\\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\\\n     * @param _wPowerPerp ERC20 token address representing the long position\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\\\n     * @param _uniPositionManager uniswap v3 position manager address\\\\n     */\\\\n    constructor(\\\\n        address _oracle,\\\\n        address _shortPowerPerp,\\\\n        address _wPowerPerp,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _wPowerPerpPool,\\\\n        address _uniPositionManager,\\\\n        uint24 _feeTier\\\\n    ) {\\\\n        require(_oracle != address(0), \\\\\\\"C4\\\\\\\");\\\\n        require(_shortPowerPerp != address(0), \\\\\\\"C5\\\\\\\");\\\\n        require(_wPowerPerp != address(0), \\\\\\\"C6\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"C7\\\\\\\");\\\\n        require(_quoteCurrency != address(0), \\\\\\\"C8\\\\\\\");\\\\n        require(_ethQuoteCurrencyPool != address(0), \\\\\\\"C9\\\\\\\");\\\\n        require(_wPowerPerpPool != address(0), \\\\\\\"C10\\\\\\\");\\\\n        require(_uniPositionManager != address(0), \\\\\\\"C11\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        shortPowerPerp = _shortPowerPerp;\\\\n        wPowerPerp = _wPowerPerp;\\\\n        weth = _weth;\\\\n        quoteCurrency = _quoteCurrency;\\\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\\\n        wPowerPerpPool = _wPowerPerpPool;\\\\n        uniswapPositionManager = _uniPositionManager;\\\\n        feeTier = _feeTier;\\\\n        isWethToken0 = _weth < _wPowerPerp;\\\\n\\\\n        normalizationFactor = 1e18;\\\\n        deployTimestamp = block.timestamp;\\\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * ======================\\\\n     * | External Functions |\\\\n     * ======================\\\\n     */\\\\n\\\\n    /**\\\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\\\n     * @dev can be used for on-chain and off-chain calculations\\\\n     */\\\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\\\n        return _getNewNormalizationFactor();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index price of the powerPerp, scaled down\\\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\\\n     * @dev this is the index price used when calculating funding and for collateralization\\\\n     * @param _period period which you want to calculate twap with\\\\n     * @return index price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getIndex(uint32 _period) external view returns (uint256) {\\\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\\\n     * @param _period period which you want to calculate twap with\\\\n     * @return index price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\\\n     * @param _period period of time for the twap in seconds\\\\n     * @return mark price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\\\n        return\\\\n            Power2Base._getDenormalizedMark(\\\\n                _period,\\\\n                oracle,\\\\n                wPowerPerpPool,\\\\n                ethQuoteCurrencyPool,\\\\n                weth,\\\\n                quoteCurrency,\\\\n                wPowerPerp,\\\\n                _getNewNormalizationFactor()\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the mark price of powerPerp before funding has been applied\\\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\\\n     * @param _period period which you want to calculate twap with\\\\n     * @return mark price denominated in $USD, scaled by 1e18\\\\n     */\\\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\\\n        return\\\\n            Power2Base._getDenormalizedMark(\\\\n                _period,\\\\n                oracle,\\\\n                wPowerPerpPool,\\\\n                ethQuoteCurrencyPool,\\\\n                weth,\\\\n                quoteCurrency,\\\\n                wPowerPerp,\\\\n                normalizationFactor\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev return if the vault is properly collateralized\\\\n     * @param _vaultId id of the vault\\\\n     * @return true if the vault is properly collateralized\\\\n     */\\\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\\\n     * @param _vaultId vault to mint wPowerPerp in\\\\n     * @param _powerPerpAmount amount of powerPerp to mint\\\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\\\n     * @return vaultId\\\\n     * @return amount of wPowerPerp minted\\\\n     */\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit collateral and mint wPowerPerp\\\\n     * @param _vaultId vault to mint wPowerPerp in\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\\\n     * @return vaultId\\\\n     */\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable notPaused nonReentrant returns (uint256) {\\\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev deposit collateral into a vault\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\\\n     * @param _vaultId id of the vault\\\\n     * @param _uniTokenId uniswap position token id\\\\n     */\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw collateral from a vault\\\\n     * @param _vaultId id of the vault\\\\n     * @param _amount amount of eth to withdraw\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n        payable(msg.sender).sendValue(_amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw uniswap v3 position token from a vault\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp and remove collateral from a vault\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\\\n     * @param _withdrawAmount amount of eth to withdraw\\\\n     */\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn powerPerp and remove collateral from a vault\\\\n     * @param _vaultId id of the vault\\\\n     * @param _powerPerpAmount amount of powerPerp to burn\\\\n     * @param _withdrawAmount amount of eth to withdraw\\\\n     * @return amount of wPowerPerp burned\\\\n     */\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external notPaused nonReentrant returns (uint256) {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\\\n     */\\\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\\\n     * @param _vaultId target vault\\\\n     */\\\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\\\n     * @dev normally can only liquidate 50% of a vault's debt\\\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\\\n     * @param _vaultId vault to liquidate\\\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\\\n     * @return amount of wPowerPerp repaid\\\\n     */\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n\\\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\\\\\"C12\\\\\\\");\\\\n\\\\n        // try to save target vault before liquidation by reducing debt\\\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\\\n\\\\n        // if vault is safe after saving, pay bounty and return early\\\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\\\n            _writeVault(_vaultId, cachedVault);\\\\n            payable(msg.sender).sendValue(bounty);\\\\n            return 0;\\\\n        }\\\\n\\\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\\\n        cachedVault.addEthCollateral(bounty);\\\\n\\\\n        // if the vault is still not safe after saving, liquidate it\\\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\\\n            cachedVault,\\\\n            _maxDebtAmount,\\\\n            cachedNormFactor,\\\\n            msg.sender\\\\n        );\\\\n\\\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\\\n\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        // pay the liquidator\\\\n        payable(msg.sender).sendValue(collateralPaid);\\\\n\\\\n        return debtAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice authorize an address to modify the vault\\\\n     * @dev can be revoke by setting address to 0\\\\n     * @param _vaultId id of the vault\\\\n     * @param _operator new operator address\\\\n     */\\\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\\\n        require(\\\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\\\n            \\\\\\\"C20\\\\\\\"\\\\n        );\\\\n        vaults[_vaultId].operator = _operator;\\\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set the recipient who will receive the fee\\\\n     * @dev this should be a contract handling insurance\\\\n     * @param _newFeeRecipient new fee recipient\\\\n     */\\\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\\\n        require(_newFeeRecipient != address(0), \\\\\\\"C13\\\\\\\");\\\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\\\n        feeRecipient = _newFeeRecipient;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set the fee rate when user mints\\\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\\\n     */\\\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\\\n        require(feeRecipient != address(0), \\\\\\\"C14\\\\\\\");\\\\n        require(_newFeeRate <= 100, \\\\\\\"C15\\\\\\\");\\\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\\\n        feeRate = _newFeeRate;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\\\n     */\\\\n    function shutDown() external onlyOwner notShutdown {\\\\n        isSystemPaused = true;\\\\n        isShutDown = true;\\\\n        indexForSettlement = Power2Base._getScaledTwap(\\\\n            oracle,\\\\n            ethQuoteCurrencyPool,\\\\n            weth,\\\\n            quoteCurrency,\\\\n            TWAP_PERIOD,\\\\n            false\\\\n        );\\\\n        emit Shutdown(indexForSettlement);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\\\n     */\\\\n    function pause() external onlyOwner notShutdown notPaused {\\\\n        require(pausesLeft > 0, \\\\\\\"C16\\\\\\\");\\\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\\\\\"C17\\\\\\\");\\\\n        isSystemPaused = true;\\\\n        pausesLeft -= 1;\\\\n        lastPauseTime = block.timestamp;\\\\n\\\\n        emit Paused(pausesLeft);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice unpause the contract\\\\n     * @dev anyone can unpause the contract after 24 hours\\\\n     */\\\\n    function unPauseAnyone() external isPaused notShutdown {\\\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\\\\\"C18\\\\\\\");\\\\n        isSystemPaused = false;\\\\n        emit UnPaused(msg.sender);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice unpause the contract\\\\n     * @dev owner can unpause at any time\\\\n     */\\\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\\\n        isSystemPaused = false;\\\\n        emit UnPaused(msg.sender);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\\\n     */\\\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\\\n\\\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\\\n        payable(msg.sender).sendValue(longValue);\\\\n\\\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice redeem short position when the system is shutdown\\\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\\\n     * @param _vaultId vault id\\\\n     */\\\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\\\n        _checkCanModifyVault(_vaultId, msg.sender);\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        uint256 cachedNormFactor = normalizationFactor;\\\\n\\\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\\\n\\\\n        uint256 debt = Power2Base._getLongSettlementValue(\\\\n            cachedVault.shortAmount,\\\\n            indexForSettlement,\\\\n            cachedNormFactor\\\\n        );\\\\n        // if the debt is more than collateral, this line will revert\\\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\\\n\\\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\\\n        cachedVault.shortAmount = 0;\\\\n        cachedVault.collateralAmount = 0;\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        payable(msg.sender).sendValue(excess);\\\\n\\\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice update the normalization factor as a way to pay funding\\\\n     */\\\\n    function applyFunding() external notPaused {\\\\n        _applyFunding();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\\\n     */\\\\n    function donate() external payable isShutdown {}\\\\n\\\\n    /**\\\\n     * @notice fallback function to accept eth\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth, \\\\\\\"C19\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\\\n     * @return returns received selector\\\\n     */\\\\n    function onERC721Received(\\\\n        address,\\\\n        address,\\\\n        uint256,\\\\n        bytes memory\\\\n    ) public virtual override returns (bytes4) {\\\\n        return this.onERC721Received.selector;\\\\n    }\\\\n\\\\n    /*\\\\n     * ======================\\\\n     * | Internal Functions |\\\\n     * ======================\\\\n     */\\\\n\\\\n    /**\\\\n     * @notice check if an address can modify a vault\\\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\\\n     * @param _account the address to check if can modify the vault\\\\n     */\\\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\\\n        require(\\\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\\\n            \\\\\\\"C20\\\\\\\"\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\\\n     * @param _account account to receive wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _mintAmount amount to mint\\\\n     * @param _depositAmount amount of eth as collateral\\\\n     * @param _uniTokenId id of uniswap v3 position token\\\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\\\n     * @return the minted wPowerPerp amount\\\\n     */\\\\n    function _openDepositMint(\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _mintAmount,\\\\n        uint256 _depositAmount,\\\\n        uint256 _uniTokenId,\\\\n        bool _isWAmount\\\\n    ) internal returns (uint256, uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        uint256 depositAmountWithFee = _depositAmount;\\\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\\\n        uint256 feeAmount;\\\\n        VaultLib.Vault memory cachedVault;\\\\n\\\\n        // load vault or create new a new one\\\\n        if (_vaultId == 0) {\\\\n            (_vaultId, cachedVault) = _openVault(_account);\\\\n        } else {\\\\n            // make sure we're not accessing an unexistent vault.\\\\n            _checkCanModifyVault(_vaultId, msg.sender);\\\\n            cachedVault = vaults[_vaultId];\\\\n        }\\\\n\\\\n        if (wPowerPerpAmount > 0) {\\\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\\\n        }\\\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\\\n\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        // pay insurance fee\\\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\\\n\\\\n        return (_vaultId, wPowerPerpAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\\\n     * @param _account who should receive collateral\\\\n     * @param _vaultId id of the vault\\\\n     * @param _burnAmount amount of wPowerPerp to burn\\\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\\\n     * @return total burned wPowerPower amount\\\\n     */\\\\n    function _burnAndWithdraw(\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _burnAmount,\\\\n        uint256 _withdrawAmount,\\\\n        bool _isWAmount\\\\n    ) internal returns (uint256) {\\\\n        uint256 cachedNormFactor = _applyFunding();\\\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\\\n\\\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\\\n        _checkVault(cachedVault, cachedNormFactor);\\\\n        _writeVault(_vaultId, cachedVault);\\\\n\\\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\\\n\\\\n        return wBurnAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice open a new vault\\\\n     * @dev create a new vault and bind it with a new short vault id\\\\n     * @param _recipient owner of new vault\\\\n     * @return id of the new vault\\\\n     * @return new in-memory vault\\\\n     */\\\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\\\n\\\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\\\n            NftCollateralId: 0,\\\\n            collateralAmount: 0,\\\\n            shortAmount: 0,\\\\n            operator: address(0)\\\\n        });\\\\n        emit OpenVault(msg.sender, vaultId);\\\\n        return (vaultId, vault);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit uniswap v3 position token into a vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account account to transfer the uniswap v3 position from\\\\n     * @param _vaultId id of the vault\\\\n     * @param _uniTokenId uniswap position token id\\\\n     */\\\\n    function _depositUniPositionToken(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _uniTokenId\\\\n    ) internal {\\\\n        //get tokens for uniswap NFT\\\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\\\n            uniswapPositionManager\\\\n        ).positions(_uniTokenId);\\\\n\\\\n        // require that liquidity is above 0\\\\n        require(liquidity > 0, \\\\\\\"C25\\\\\\\");\\\\n        // accept NFTs from only the wPowerPerp pool\\\\n        require(fee == feeTier, \\\\\\\"C26\\\\\\\");\\\\n        // check token0 and token1\\\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\\\\\"C23\\\\\\\");\\\\n\\\\n        _vault.addUniNftCollateral(_uniTokenId);\\\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral into a vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update.\\\\n     * @param _vaultId id of the vault\\\\n     * @param _amount amount of eth adding to the vault\\\\n     */\\\\n    function _addEthCollateral(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _vaultId,\\\\n        uint256 _amount\\\\n    ) internal {\\\\n        _vault.addEthCollateral(_amount);\\\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap v3 position token from the vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account where to send the uni position token to\\\\n     * @param _vaultId id of the vault\\\\n     */\\\\n    function _withdrawUniPositionToken(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId\\\\n    ) internal {\\\\n        uint256 tokenId = _vault.NftCollateralId;\\\\n        _vault.removeUniNftCollateral();\\\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from the vault\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _vaultId id of the vault\\\\n     * @param _amount amount of eth to withdraw\\\\n     */\\\\n    function _withdrawCollateral(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _vaultId,\\\\n        uint256 _amount\\\\n    ) internal {\\\\n        _vault.removeEthCollateral(_amount);\\\\n\\\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp (ERC20) to an account\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account account to receive wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\\\n     */\\\\n    function _mintWPowerPerp(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount\\\\n    ) internal {\\\\n        _vault.addShort(_wPowerPerpAmount);\\\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\\\n\\\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp (ERC20) from an account\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _account account burning the wPowerPerp\\\\n     * @param _vaultId id of the vault\\\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\\\n     */\\\\n    function _burnWPowerPerp(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _account,\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount\\\\n    ) internal {\\\\n        _vault.removeShort(_wPowerPerpAmount);\\\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\\\n\\\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice liquidate a vault, pay the liquidator\\\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @param _liquidator liquidator address to receive eth\\\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\\\n     * @return collateralToPay amount of collateral paid to liquidator\\\\n     */\\\\n    function _liquidate(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _maxWPowerPerpAmount,\\\\n        uint256 _normalizationFactor,\\\\n        address _liquidator\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\\\n            _maxWPowerPerpAmount,\\\\n            uint256(_vault.shortAmount),\\\\n            uint256(_vault.collateralAmount)\\\\n        );\\\\n\\\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\\\\\"C21\\\\\\\");\\\\n\\\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\\\n        _vault.removeShort(liquidateAmount);\\\\n        _vault.removeEthCollateral(collateralToPay);\\\\n\\\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        require(!isDust, \\\\\\\"C22\\\\\\\");\\\\n\\\\n        return (liquidateAmount, collateralToPay);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\\\n     * @dev will update the vault memory in-place\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _owner account to send any excess\\\\n     * @param _vaultId id of the vault to reduce debt on\\\\n     * @param _payBounty true if paying caller 2% bounty\\\\n     * @return bounty amount of bounty paid for liquidator\\\\n     */\\\\n    function _reduceDebt(\\\\n        VaultLib.Vault memory _vault,\\\\n        address _owner,\\\\n        uint256 _vaultId,\\\\n        bool _payBounty\\\\n    ) internal returns (uint256) {\\\\n        uint256 nftId = _vault.NftCollateralId;\\\\n        if (nftId == 0) return 0;\\\\n\\\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\\\n\\\\n        // change weth back to eth\\\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\\\n\\\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\\\n            _vault,\\\\n            withdrawnEthAmount,\\\\n            withdrawnWPowerPerpAmount,\\\\n            _payBounty\\\\n        );\\\\n\\\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\\\n\\\\n        emit ReduceDebt(\\\\n            msg.sender,\\\\n            _vaultId,\\\\n            withdrawnEthAmount,\\\\n            withdrawnWPowerPerpAmount,\\\\n            burnAmount,\\\\n            excess,\\\\n            bounty\\\\n        );\\\\n\\\\n        return bounty;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice pay fee recipient\\\\n     * @dev pay in eth from either the vault or the deposit amount\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\\\n     */\\\\n    function _getFee(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _depositAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 cachedFeeRate = feeRate;\\\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\\\n        uint256 depositAmountAfterFee;\\\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\\\n            _wPowerPerpAmount,\\\\n            oracle,\\\\n            wPowerPerpPool,\\\\n            wPowerPerp,\\\\n            weth\\\\n        );\\\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\\\n\\\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\\\n        if (_depositAmount > feeAmount) {\\\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\\\n            // if not, adjust the vault to pay from the vault collateral\\\\n        } else {\\\\n            _vault.removeEthCollateral(feeAmount);\\\\n            depositAmountAfterFee = _depositAmount;\\\\n        }\\\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\\\n        return (feeAmount, depositAmountAfterFee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice write vault to storage\\\\n     * @dev writes to vaults mapping\\\\n     */\\\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\\\n        vaults[_vaultId] = _vault;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\\\n     * @param _uniTokenId uniswap v3 position token id\\\\n     * @return wethAmount amount of weth withdrawn from uniswap\\\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\\\n     */\\\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\\\n\\\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\\\n\\\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\\\n            .DecreaseLiquidityParams({\\\\n                tokenId: _uniTokenId,\\\\n                liquidity: liquidity,\\\\n                amount0Min: 0,\\\\n                amount1Min: 0,\\\\n                deadline: block.timestamp\\\\n            });\\\\n\\\\n        positionManager.decreaseLiquidity(decreaseParams);\\\\n\\\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\\\n            tokenId: _uniTokenId,\\\\n            recipient: address(this),\\\\n            amount0Max: uint128(-1),\\\\n            amount1Max: uint128(-1)\\\\n        });\\\\n\\\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\\\n\\\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice update the normalization factor as a way to pay in-kind funding\\\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\\\n     * @return new normalization factor\\\\n     **/\\\\n    function _applyFunding() internal returns (uint256) {\\\\n        // only update the norm factor once per block\\\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\\\n\\\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\\\n\\\\n        emit NormalizationFactorUpdated(\\\\n            normalizationFactor,\\\\n            newNormalizationFactor,\\\\n            lastFundingUpdateTimestamp,\\\\n            block.timestamp\\\\n        );\\\\n\\\\n        // the following will be batch into 1 SSTORE because of type uint128\\\\n        normalizationFactor = newNormalizationFactor.toUint128();\\\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\\\n\\\\n        return newNormalizationFactor;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate new normalization factor base on the current timestamp\\\\n     * @return new normalization factor if funding happens in the current block\\\\n     */\\\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\\\n\\\\n        if (period == 0) {\\\\n            return normalizationFactor;\\\\n        }\\\\n\\\\n        // make sure we use the same period for mark and index\\\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\\\n\\\\n        // avoid reading normalizationFactor from storage multiple times\\\\n        uint256 cacheNormFactor = normalizationFactor;\\\\n\\\\n        uint256 mark = Power2Base._getDenormalizedMark(\\\\n            periodForOracle,\\\\n            oracle,\\\\n            wPowerPerpPool,\\\\n            ethQuoteCurrencyPool,\\\\n            weth,\\\\n            quoteCurrency,\\\\n            wPowerPerp,\\\\n            cacheNormFactor\\\\n        );\\\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\\\n\\\\n        //the fraction of the funding period. used to compound the funding rate\\\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\\\n\\\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\\\n        if (mark < lowerBound) {\\\\n            mark = lowerBound;\\\\n        } else {\\\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\\\n            if (mark > upperBound) mark = upperBound;\\\\n        }\\\\n\\\\n        // normFactor(new) = multiplier * normFactor(old)\\\\n        // multiplier = (index/mark)^rFunding\\\\n        // x^r = n^(log_n(x) * r)\\\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\\\n\\\\n        int128 base = ABDKMath64x64.divu(index, mark);\\\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\\\n        int128 multiplier = logTerm.exp_2();\\\\n        return multiplier.mulu(cacheNormFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if vault has enough collateral and is not a dust vault\\\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _normalizationFactor normalization factor\\\\n     */\\\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        require(isSafe, \\\\\\\"C24\\\\\\\");\\\\n        require(!isDust, \\\\\\\"C22\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check that the vault has enough collateral\\\\n     * @param _vault in-memory vault\\\\n     * @param _normalizationFactor normalization factor\\\\n     * @return true if the vault is properly collateralized\\\\n     */\\\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\\\n        return isSafe;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\\\n     * @param _vault the Vault memory to update\\\\n     * @param _normalizationFactor normalization factor\\\\n     * @return true if the vault is safe\\\\n     * @return true if the vault is a dust vault\\\\n     */\\\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\\\n        internal\\\\n        view\\\\n        returns (bool, bool)\\\\n    {\\\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\\\n            oracle,\\\\n            ethQuoteCurrencyPool,\\\\n            weth,\\\\n            quoteCurrency,\\\\n            TWAP_PERIOD,\\\\n            true // do not call more than maximum period so it does not revert\\\\n        );\\\\n        return\\\\n            VaultLib.getVaultStatus(\\\\n                _vault,\\\\n                uniswapPositionManager,\\\\n                _normalizationFactor,\\\\n                scaledEthPrice,\\\\n                MIN_COLLATERAL,\\\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\\\n                isWethToken0\\\\n            );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\\\n     * @dev this function will update the vault memory in-place\\\\n     * @return burnAmount amount of wPowerPerp that should be burned\\\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\\\n     * @return bounty amount of bounty should be paid out to caller\\\\n     */\\\\n    function _getReduceDebtResultInVault(\\\\n        VaultLib.Vault memory _vault,\\\\n        uint256 nftEthAmount,\\\\n        uint256 nftWPowerperpAmount,\\\\n        bool _payBounty\\\\n    )\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            uint256,\\\\n            uint256,\\\\n            uint256\\\\n        )\\\\n    {\\\\n        uint256 bounty;\\\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\\\n\\\\n        uint256 burnAmount = nftWPowerperpAmount;\\\\n        uint256 wPowerPerpExcess;\\\\n\\\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\\\n            burnAmount = _vault.shortAmount;\\\\n        }\\\\n\\\\n        _vault.removeShort(burnAmount);\\\\n        _vault.removeUniNftCollateral();\\\\n        _vault.addEthCollateral(nftEthAmount);\\\\n        _vault.removeEthCollateral(bounty);\\\\n\\\\n        return (burnAmount, wPowerPerpExcess, bounty);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\\\n     * @dev bounty is 2% of the total value of the position token\\\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\\\n     */\\\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\\\n        return\\\\n            Power2Base\\\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\\\n                .add(_ethWithdrawn)\\\\n                .mul(REDUCE_DEBT_BOUNTY)\\\\n                .div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\\\\\"dust vault\\\\\\\"\\\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\\\n     * @param _vaultShortAmount the amount of short in the vault\\\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\\\n     */\\\\n    function _getLiquidationResult(\\\\n        uint256 _maxWPowerPerpAmount,\\\\n        uint256 _vaultShortAmount,\\\\n        uint256 _vaultCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        // try limiting liquidation amount to half of the vault debt\\\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\\\n            _maxWPowerPerpAmount,\\\\n            _vaultShortAmount.div(2)\\\\n        );\\\\n\\\\n        if (_vaultCollateralAmount > collateralToPay) {\\\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\\\n                // calculate the new liquidation amount and collateral again based on the new limit\\\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\\\n                    _maxWPowerPerpAmount,\\\\n                    _vaultShortAmount\\\\n                );\\\\n            }\\\\n        }\\\\n\\\\n        // check if final collateral to pay is greater than vault amount.\\\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\\\n        if (collateralToPay > _vaultCollateralAmount) {\\\\n            // force liquidator to pay full debt amount\\\\n            finalLiquidateAmount = _vaultShortAmount;\\\\n            collateralToPay = _vaultCollateralAmount;\\\\n        }\\\\n\\\\n        return (finalLiquidateAmount, collateralToPay);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\\\n     * @return collateralToPay total collateral the liquidator will get\\\\n     */\\\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\\\n        internal\\\\n        view\\\\n        returns (uint256, uint256)\\\\n    {\\\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\\\n            ? _maxLiquidatableWAmount\\\\n            : _maxInputWAmount;\\\\n\\\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\\\n            finalWAmountToLiquidate,\\\\n            oracle,\\\\n            wPowerPerpPool,\\\\n            wPowerPerp,\\\\n            weth\\\\n        );\\\\n\\\\n        // add 10% bonus for liquidators\\\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\\\n\\\\n        return (finalWAmountToLiquidate, collateralToPay);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\\\n     * @param _period max period that we intend to use\\\\n     * @return fair period not greator than _period to be used for both pools.\\\\n     */\\\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\\\n\\\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf10380c226b48c8be2aba71df6915ddfe04f2fdf6a6612643816ee351a72bc42\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8a9a4512f1fc29b14dcf97ca149f263f28de43191a3ee31336f2389e3f2f5f8e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/ABDKMath64x64.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: BSD-4-Clause\\\\n/*\\\\n * ABDK Math 64.64 Smart Contract Library.  Copyright \\\\u00a9 2019 by ABDK Consulting.\\\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\\\n * Copyright (c) 2019, ABDK Consulting\\\\n *\\\\n * All rights reserved.\\\\n *\\\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\\\n *\\\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\\\n */\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * Smart contract library of mathematical functions operating with signed\\\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\\\n * represented by int128 type holding only the numerator.\\\\n *\\\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\\\n * Changes (cont) - revert strings added\\\\n * solidity version set to ^0.7.0\\\\n */\\\\nlibrary ABDKMath64x64 {\\\\n    /*\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * Minimum value signed 64.64-bit fixed point number may have.\\\\n     * -2^127\\\\n     */\\\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\\\n\\\\n    /*\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * Maximum value signed 64.64-bit fixed point number may have.\\\\n     * 2^127-1\\\\n     */\\\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @param y signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\\\n        int256 result = (int256(x) * y) >> 64;\\\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\\\\\"MUL-OVUF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64 fixed point number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 256-bit integer number\\\\n     */\\\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\\\n        if (y == 0) return 0;\\\\n\\\\n        require(x >= 0, \\\\\\\"MULU-X0\\\\\\\");\\\\n\\\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\\\n        uint256 hi = uint256(x) * (y >> 128);\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"MULU-OF1\\\\\\\");\\\\n        hi <<= 64;\\\\n\\\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\\\\\"MULU-OF2\\\\\\\");\\\\n        return hi + lo;\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\\\n        require(y != 0, \\\\\\\"DIVU-INF\\\\\\\");\\\\n        uint128 result = divuu(x, y);\\\\n        require(result <= uint128(MAX_64x64), \\\\\\\"DIVU-OF\\\\\\\");\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function log_2(int128 x) public pure returns (int128) {\\\\n        require(x > 0, \\\\\\\"LOG_2-X0\\\\\\\");\\\\n\\\\n        int256 msb = 0;\\\\n        int256 xc = x;\\\\n        if (xc >= 0x10000000000000000) {\\\\n            xc >>= 64;\\\\n            msb += 64;\\\\n        }\\\\n        if (xc >= 0x100000000) {\\\\n            xc >>= 32;\\\\n            msb += 32;\\\\n        }\\\\n        if (xc >= 0x10000) {\\\\n            xc >>= 16;\\\\n            msb += 16;\\\\n        }\\\\n        if (xc >= 0x100) {\\\\n            xc >>= 8;\\\\n            msb += 8;\\\\n        }\\\\n        if (xc >= 0x10) {\\\\n            xc >>= 4;\\\\n            msb += 4;\\\\n        }\\\\n        if (xc >= 0x4) {\\\\n            xc >>= 2;\\\\n            msb += 2;\\\\n        }\\\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n        int256 result = (msb - 64) << 64;\\\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\\\n            ux *= ux;\\\\n            uint256 b = ux >> 255;\\\\n            ux >>= 127 + b;\\\\n            result += bit * int256(b);\\\\n        }\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate binary exponent of x.  Revert on overflow.\\\\n     *\\\\n     * @param x signed 64.64-bit fixed point number\\\\n     * @return signed 64.64-bit fixed point number\\\\n     */\\\\n    function exp_2(int128 x) public pure returns (int128) {\\\\n        require(x < 0x400000000000000000, \\\\\\\"EXP_2-OF\\\\\\\"); // Overflow\\\\n\\\\n        if (x < -0x400000000000000000) return 0; // Underflow\\\\n\\\\n        uint256 result = 0x80000000000000000000000000000000;\\\\n\\\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\\\n\\\\n        result >>= uint256(63 - (x >> 64));\\\\n        require(result <= uint256(MAX_64x64));\\\\n\\\\n        return int128(result);\\\\n    }\\\\n\\\\n    /**\\\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\\\n     * integer numbers.  Revert on overflow or when y is zero.\\\\n     *\\\\n     * @param x unsigned 256-bit integer number\\\\n     * @param y unsigned 256-bit integer number\\\\n     * @return unsigned 64.64-bit fixed point number\\\\n     */\\\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\\\n        require(y != 0);\\\\n\\\\n        uint256 result;\\\\n\\\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\\\n        else {\\\\n            uint256 msb = 192;\\\\n            uint256 xc = x >> 192;\\\\n            if (xc >= 0x100000000) {\\\\n                xc >>= 32;\\\\n                msb += 32;\\\\n            }\\\\n            if (xc >= 0x10000) {\\\\n                xc >>= 16;\\\\n                msb += 16;\\\\n            }\\\\n            if (xc >= 0x100) {\\\\n                xc >>= 8;\\\\n                msb += 8;\\\\n            }\\\\n            if (xc >= 0x10) {\\\\n                xc >>= 4;\\\\n                msb += 4;\\\\n            }\\\\n            if (xc >= 0x4) {\\\\n                xc >>= 2;\\\\n                msb += 2;\\\\n            }\\\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\\\n\\\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF1\\\\\\\");\\\\n\\\\n            uint256 hi = result * (y >> 128);\\\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\\\n\\\\n            uint256 xh = x >> 192;\\\\n            uint256 xl = x << 64;\\\\n\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n            lo = hi << 128;\\\\n            if (xl < lo) xh -= 1;\\\\n            xl -= lo; // We rely on overflow behavior here\\\\n\\\\n            assert(xh == hi >> 128);\\\\n\\\\n            result += xl / y;\\\\n        }\\\\n\\\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\\\\\"DIVUU-OF2\\\\\\\");\\\\n        return uint128(result);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x56efa7c16e4fffb37ad80af15bd042d9f92532a4553d6b12915e3fa21609ad66\\\",\\\"license\\\":\\\"BSD-4-Clause\\\"},\\\"contracts/libs/Power2Base.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary Power2Base {\\\\n    using SafeMath for uint256;\\\\n\\\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\\\n    uint256 private constant INDEX_SCALE = 1e4;\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    /**\\\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getUnscaledIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\\\n     */\\\\n    function _getDenormalizedMark(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _wSqueeth,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\\\n\\\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _weth weth address\\\\n     * @return returns value of debt in ETH\\\\n     */\\\\n    function _getDebtValueInEth(\\\\n        uint256 _debtAmount,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _wSqueeth,\\\\n        address _weth\\\\n    ) internal view returns (uint256) {\\\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle\\\\n     * @dev this will revert if period is > max period for the pool\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        // period reaching this point should be check, otherwise might revert\\\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\\\n     * @param _indexPriceForSettlement index price for settlement\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return amount in wei that should be paid to the token holder\\\\n     */\\\\n    function _getLongSettlementValue(\\\\n        uint256 _wsqueethAmount,\\\\n        uint256 _indexPriceForSettlement,\\\\n        uint256 _normalizationFactor\\\\n    ) internal pure returns (uint256) {\\\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1938180c41ec0ee817b841df605b199e15ffbbe94700b640d031b4e4665a89af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x939175a827c8e9d8d09ee55957e8127a6a55bf42d6a0b3e48b0b59c895aa85af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101e060405260046005553480156200001757600080fd5b5060405162006630380380620066308339810160408190526200003a916200032c565b600062000046620002c4565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600180556001600160a01b038916620000c65760405162461bcd60e51b8152600401620000bd9062000462565b60405180910390fd5b6001600160a01b038816620000ef5760405162461bcd60e51b8152600401620000bd90620004b6565b6001600160a01b038716620001185760405162461bcd60e51b8152600401620000bd90620003f0565b6001600160a01b038616620001415760405162461bcd60e51b8152600401620000bd9062000446565b6001600160a01b0385166200016a5760405162461bcd60e51b8152600401620000bd906200049a565b6001600160a01b038416620001935760405162461bcd60e51b8152600401620000bd906200047e565b6001600160a01b038316620001bc5760405162461bcd60e51b8152600401620000bd906200040c565b6001600160a01b038216620001e55760405162461bcd60e51b8152600401620000bd9062000429565b6001600160601b031960608a811b82166101805289811b82166101405288811b82166101605287811b821660a05286811b821660c05285811b821660e05284811b82166101005283901b16610120526001600160e81b031960e882901b166080526001600160a01b038781169087161060f81b6101c052600780546001600160801b031916670de0b6b3a7640000179055426101a081905262000297906200274f620002c8602090811b91909117901c565b600780546001600160801b03928316600160801b02921691909117905550620004d2975050505050505050565b3390565b806001600160801b03811681146200030f576040805162461bcd60e51b815260206004820152600560248201526409e8c6264760db1b604482015290519081900360640190fd5b919050565b80516001600160a01b03811681146200030f57600080fd5b60008060008060008060008060006101208a8c0312156200034b578485fd5b620003568a62000314565b98506200036660208b0162000314565b97506200037660408b0162000314565b96506200038660608b0162000314565b95506200039660808b0162000314565b9450620003a660a08b0162000314565b9350620003b660c08b0162000314565b9250620003c660e08b0162000314565b91506101008a015162ffffff81168114620003df578182fd5b809150509295985092959850929598565b602080825260029082015261219b60f11b604082015260600190565b60208082526003908201526204331360ec1b604082015260600190565b60208082526003908201526243313160e81b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526002908201526110cd60f21b604082015260600190565b602080825260029082015261433960f01b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b602080825260029082015261433560f01b604082015260600190565b60805160e81c60a05160601c60c05160601c60e05160601c6101005160601c6101205160601c6101405160601c6101605160601c6101805160601c6101a0516101c05160f81c615f2f620007016000398061465452806148f55250806115bc525080610af15280610bc95280610d3a52806113f9528061173c528061243c5280612ac65280612b9a5280613e765280614050528061411052806144d452806145945280614cd35280614d7e525080610ddf528061141d5280611b9952806124e15280612b6b52806135da52806136525280613897528061393f5280613b125280613eb85280613f6b52806144125280614d155280614dc0525080611a795280611d9f5280611de05280611ff352806121a6528061270f5280612f395280613d6452508061339352806134bb52806136ff52806145685280614769525080610d5b5280611d7b528061245d5280612ae75280613e97528061413f52806145c35280614cf45280614d9f525080610b125280610bea5280610d7c528061109e528061175d528061247e5280612b085280612bbb528061407f52806144f5525080610b545280610c2c5280610dbe52806114b1528061179f52806124c05280612b4a5280612bfd52806145375250806103535280610b335280610c0b5280610d9d5280610ebc528061177e528061249f5280612b295280612bdc5280613616528061368e52806137fa5280613ed952806145165280614d365280614de15250806113c152806135915250615f2f6000f3fe6080604052600436106103435760003560e01c80638456cb59116101b0578063b707ab99116100ec578063e74b981b11610095578063f2fde38b1161006f578063f2fde38b146108d0578063f90c3f27146108f0578063fbfc6bc014610905578063ff947525146109255761039b565b8063e74b981b14610888578063ed88c68e146108a8578063ee3189ff146108b05761039b565b8063d296d1f1116100c6578063d296d1f11461083e578063d52725841461085e578063de4a427a146108735761039b565b8063b707ab99146107e9578063c65a391d146107fe578063c9e77ee81461081e5761039b565b806391b8d34a116101595780639d4c9442116101335780639d4c944214610781578063a847e67414610796578063ac6cd5ef146107b6578063b6b55f25146107d65761039b565b806391b8d34a1461072c578063978bbdb91461074c57806397efa942146107615761039b565b80638cd21d7c1161018a5780638cd21d7c146106e25780638da5cb5b1461070257806391b4ded9146107175761039b565b80638456cb591461067d5780638632cb03146106925780638c64ea4a146106b25761039b565b806345596e2e1161027f57806372f5d98a116102285780637dc0d1d0116102025780637dc0d1d0146106295780637f07b1301461063e5780638146b09f1461065357806382564bca146106685761039b565b806372f5d98a146105c35780637691c4ac146105e55780637ca25184146106075761039b565b806363b38ae41161025957806363b38ae414610579578063713d517f1461058e578063715018a6146105ae5761039b565b806345596e2e1461052257806346904840146105425780634be2822c146105575761039b565b806324f5f531116102ec5780633fc8cef3116102c65780633fc8cef3146104ab5780634394318d146104cd578063441a3e70146104ed5780634468c0221461050d5761039b565b806324f5f53114610463578063377a19361461047857806339467918146104985761039b565b806315aded831161031d57806315aded83146104005780631bf7bf6c1461042d578063200f4b8d1461044e5761039b565b806307633669146103a057806310b9e583146103b5578063150b7a02146103ca5761039b565b3661039b57336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103995760405162461bcd60e51b815260040161039090615cc9565b60405180910390fd5b005b600080fd5b3480156103ac57600080fd5b5061039961093a565b3480156103c157600080fd5b50610399610a3d565b3480156103d657600080fd5b506103ea6103e5366004615662565b610bb0565b6040516103f79190615ad9565b60405180910390f35b34801561040c57600080fd5b5061042061041b36600461584f565b610bc1565b6040516103f79190615df3565b61044061043b366004615824565b610c58565b6040516103f7929190615dfc565b34801561045a57600080fd5b50610399610cef565b34801561046f57600080fd5b50610420610d22565b34801561048457600080fd5b5061042061049336600461584f565b610d32565b6104206104a6366004615824565b610e22565b3480156104b757600080fd5b506104c0610eba565b6040516103f79190615961565b3480156104d957600080fd5b506104206104e8366004615824565b610ede565b3480156104f957600080fd5b506103996105083660046157e0565b610f78565b34801561051957600080fd5b506104c061109c565b34801561052e57600080fd5b5061039961053d366004615781565b6110c0565b34801561054e57600080fd5b506104c06111bd565b34801561056357600080fd5b5061056c6111cc565b6040516103f79190615da5565b34801561058557600080fd5b506104206111e2565b34801561059a57600080fd5b506103996105a9366004615781565b6111e8565b3480156105ba57600080fd5b50610399611301565b3480156105cf57600080fd5b506105d86113bf565b6040516103f79190615de3565b3480156105f157600080fd5b506105fa6113e3565b6040516103f79190615ace565b34801561061357600080fd5b5061061c6113f1565b6040516103f79190615e0a565b34801561063557600080fd5b506104c06113f7565b34801561064a57600080fd5b506104c061141b565b34801561065f57600080fd5b5061039961143f565b34801561067457600080fd5b506104c06114af565b34801561068957600080fd5b506103996114d3565b34801561069e57600080fd5b506103996106ad366004615824565b61165c565b3480156106be57600080fd5b506106d26106cd366004615781565b6116e7565b6040516103f79493929190615a90565b3480156106ee57600080fd5b506104206106fd36600461584f565b611734565b34801561070e57600080fd5b506104c06117c3565b34801561072357600080fd5b506104206117d2565b34801561073857600080fd5b506103996107473660046157e0565b6117d8565b34801561075857600080fd5b506104206118d1565b34801561076d57600080fd5b5061039961077c366004615781565b6118d7565b34801561078d57600080fd5b506104c0611a77565b3480156107a257600080fd5b506105fa6107b1366004615781565b611a9b565b3480156107c257600080fd5b506103996107d1366004615781565b611b15565b6103996107e4366004615781565b611c6f565b3480156107f557600080fd5b506104c0611d79565b34801561080a57600080fd5b506103996108193660046157b1565b611d9d565b34801561082a57600080fd5b50610399610839366004615781565b611efb565b34801561084a57600080fd5b506104206108593660046157e0565b61208d565b34801561086a57600080fd5b5061056c6122f8565b34801561087f57600080fd5b50610420612307565b34801561089457600080fd5b506103996108a336600461562a565b61230d565b610399612410565b3480156108bc57600080fd5b506104206108cb36600461584f565b612434565b3480156108dc57600080fd5b506103996108eb36600461562a565b61250d565b3480156108fc57600080fd5b50610420612621565b34801561091157600080fd5b50610399610920366004615781565b612628565b34801561093157600080fd5b506105fa612746565b6109426127ad565b6001600160a01b03166109536117c3565b6001600160a01b0316146109ae576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600854610100900460ff166109d55760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156109f85760405162461bcd60e51b815260040161039090615b53565b6008805461ff00191690556040517fff2b959f2bcdb44c7ecb4b16dae055431019d7350607125cfc2b74a06632c90e90610a33903390615961565b60405180910390a1565b610a456127ad565b6001600160a01b0316610a566117c3565b6001600160a01b031614610ab1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff1615610ad45760405162461bcd60e51b815260040161039090615b53565b6008805460ff1961ff001990911661010017166001179055610b7d7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460006127b1565b60048190556040517f574214b195bf5273a95bb4498e35cf1fde0ce327c727a95ec2ab359f7ba4e11a91610a3391615df3565b630a85bd0160e11b5b949350505050565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006127de565b90505b919050565b6008546000908190610100900460ff1615610c855760405162461bcd60e51b815260040161039090615c39565b60026001541415610ccb576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610cdf33868634876000612819565b6001805590969095509350505050565b600854610100900460ff1615610d175760405162461bcd60e51b815260040161039090615c39565b610d1f61296a565b50565b6000610d2c612a58565b90505b90565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000600760009054906101000a90046001600160801b03166001600160801b0316612ee9565b600854600090610100900460ff1615610e4d5760405162461bcd60e51b815260040161039090615c39565b60026001541415610e93576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001819055506000610eac33868634876001612819565b506001805595945050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854600090610100900460ff1615610f095760405162461bcd60e51b815260040161039090615c39565b60026001541415610f4f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610f5e8433612f2d565b610f6c338585856000613021565b60018055949350505050565b600854610100900460ff1615610fa05760405162461bcd60e51b815260040161039090615c39565b60026001541415610fe6576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610ff58233612f2d565b6000610fff61296a565b600084815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915061107481858561310f565b61107e8183613159565b61108884826131ab565b611092338461327e565b5050600180555050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6110c86127ad565b6001600160a01b03166110d96117c3565b6001600160a01b031614611134576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6002546001600160a01b031661115c5760405162461bcd60e51b815260040161039090615afc565b606481111561117d5760405162461bcd60e51b815260040161039090615c55565b7f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957600354826040516111b0929190615dfc565b60405180910390a1600355565b6002546001600160a01b031681565b600754600160801b90046001600160801b031681565b60055481565b600854610100900460ff16156112105760405162461bcd60e51b815260040161039090615c39565b60026001541415611256576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556112658133612f2d565b600061126f61296a565b600083815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506112e4813385613368565b6112ee8183613159565b6112f883826131ab565b50506001805550565b6113096127ad565b6001600160a01b031661131a6117c3565b6001600160a01b031614611375576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff1681565b6101a481565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff166114665760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156114895760405162461bcd60e51b815260040161039090615b53565b600654620151800142116109f85760405162461bcd60e51b815260040161039090615be3565b7f000000000000000000000000000000000000000000000000000000000000000081565b6114db6127ad565b6001600160a01b03166114ec6117c3565b6001600160a01b031614611547576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff161561156a5760405162461bcd60e51b815260040161039090615b53565b600854610100900460ff16156115925760405162461bcd60e51b815260040161039090615c39565b6000600554116115b45760405162461bcd60e51b815260040161039090615b6f565b60006115e0427f000000000000000000000000000000000000000000000000000000000000000061343f565b905062eff10081106116045760405162461bcd60e51b815260040161039090615ce6565b6008805461ff001916610100179055600580546000190190819055426006556040517f32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e9161165191615df3565b60405180910390a150565b600854610100900460ff16156116845760405162461bcd60e51b815260040161039090615c39565b600260015414156116ca576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556116d98333612f2d565b611092338484846001613021565b600960205260009081526040902080546001909101546001600160a01b03821691600160a01b900463ffffffff16906001600160601b03811690600160601b90046001600160801b031684565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b6000546001600160a01b031690565b60065481565b600854610100900460ff16156118005760405162461bcd60e51b815260040161039090615c39565b60026001541415611846576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556118558233612f2d565b61185d61296a565b50600082815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201526112ee813385856134b3565b60035481565b60085460ff166118f95760405162461bcd60e51b815260040161039090615d03565b6002600154141561193f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b600260015561194e8133612f2d565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b03908116606083015260075491929116906119cc908390339086906137af565b5060006119e983606001516001600160801b0316600454846139fa565b90506000611a0d8285604001516001600160601b031661343f90919063ffffffff16565b60006060860181905260408601529050611a2785856131ab565b611a31338261327e565b7f7dff8cdaec6a8d4d1ad32d3c947ed0f0281c3d6456621ef928defae96ec6cddb338683604051611a64939291906159d5565b60405180910390a1505060018055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b0316606082015281611b09612a58565b9050610bb98282613a23565b60085460ff16611b375760405162461bcd60e51b815260040161039090615d03565b60026001541415611b7d576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90611bd09033908590600401615999565b600060405180830381600087803b158015611bea57600080fd5b505af1158015611bfe573d6000803e3d6000fd5b505060045460075460009350611c2092508491906001600160801b03166139fa565b9050611c2c338261327e565b7f2131ef4f2f82ca75fe7d2e646ebfa45b6be25e53510c829629c76b641500ec67338383604051611c5f939291906159d5565b60405180910390a1505060018055565b600854610100900460ff1615611c975760405162461bcd60e51b815260040161039090615c39565b60026001541415611cdd576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611cec8133612f2d565b611cf461296a565b50600081815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b03166060820152611d67818334613a39565b611d7182826131ab565b505060018055565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331480611e7857506040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611e1d908690600401615df3565b60206040518083038186803b158015611e3557600080fd5b505afa158015611e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6d9190615646565b6001600160a01b0316145b611e945760405162461bcd60e51b815260040161039090615b19565b6000828152600960205260409081902080546001600160a01b0319166001600160a01b038416179055517f3137fc9cd2e33c34f86e29c24d81f3c75b0bce639d3c4ed0d31eeff1160a7ff590611eef903390859085906159b2565b60405180910390a15050565b600854610100900460ff1615611f235760405162461bcd60e51b815260040161039090615c39565b60026001541415611f69576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611f788133612f2d565b600081815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093526001909101546001600160601b03811682850152600160601b90046001600160801b0316606082015291516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60206040518083038186803b15801561204257600080fd5b505afa158015612056573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207a9190615646565b8460006137af565b50611d7182826131ab565b600854600090610100900460ff16156120b85760405162461bcd60e51b815260040161039090615c39565b600260015414156120fe576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155600061210d61296a565b600085815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506121818183613a23565b1561219e5760405162461bcd60e51b815260040161039090615c72565b6000612248827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e896040518263ffffffff1660e01b81526004016121f09190615df3565b60206040518083038186803b15801561220857600080fd5b505afa15801561221c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122409190615646565b8860016137af565b90506122548284613a23565b156122795761226386836131ab565b61226d338261327e565b600093505050506122ee565b6122838282613a76565b60008061229284888733613aac565b915091507f158ba9ab7bbbd08eeffa4753bad41f4d450e24831d293427308badf3eadd8c76338984846040516122cb94939291906159f6565b60405180910390a16122dd88856131ab565b6122e7338261327e565b5093505050505b6001805592915050565b6007546001600160801b031681565b60045481565b6123156127ad565b6001600160a01b03166123266117c3565b6001600160a01b031614612381576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166123a75760405162461bcd60e51b815260040161039090615b8c565b6002546040517faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d3916123e6916001600160a01b03909116908490615a57565b60405180910390a1600280546001600160a01b0319166001600160a01b0392909216919091179055565b60085460ff166124325760405162461bcd60e51b815260040161039090615d03565b565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612508612a58565b612ee9565b6125156127ad565b6001600160a01b03166125266117c3565b6001600160a01b031614612581576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166125c65760405162461bcd60e51b8152600401808060200182810382526026815260200180615e796026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6217124081565b60085460ff1661264a5760405162461bcd60e51b815260040161039090615d03565b60026001541415612690576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001908155600082815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093529301546001600160601b03811684840152600160601b90046001600160801b0316606084015290516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60085460ff1681565b806001600160801b0381168114610c53576040805162461bcd60e51b815260206004820152600560248201527f4f46313238000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b3390565b6000806127c2888888888888613bd3565b90506127d081612710613c79565b9150505b9695505050505050565b6000806127f0868686868b6000613bd3565b905061280e670de0b6b3a76400006128088380613ce0565b90613c79565b979650505050505050565b600080600061282661296a565b90508560008561284b57612846836128088b670de0b6b3a7640000613ce0565b61284d565b885b905060006128596155bc565b8b612871576128678d613d40565b909c5090506128e4565b61287b8c33612f2d565b5060008b815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201525b8215612905576128f581848c613e53565b94509150612905818e8e86613f4a565b891561291657612916818d86613a39565b881561292857612928818e8e8c6134b3565b6129328186613159565b61293c8c826131ab565b811561295857600254612958906001600160a01b03168361327e565b50999b909a5098505050505050505050565b6007546000906001600160801b03600160801b9091041642141561299a57506007546001600160801b0316610d2f565b60006129a4612a58565b6007546040519192507f339e53729b0447795ff69e70a74fed98fc7fef6fe94b7521099b32f0f8de4822916129f3916001600160801b03808216928692600160801b9004909116904290615db9565b60405180910390a1612a048161274f565b600780546fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055612a364261274f565b600780546001600160801b03928316600160801b029216919091179055905090565b6007546000908190612a8490612a7f904290600160801b90046001600160801b031661343f565b614007565b905063ffffffff8116612aa45750506007546001600160801b0316610d2f565b6000612aaf8261404b565b6007549091506001600160801b03166000612b90837f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000089612ee9565b90506000612c21847f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b9050600073c3eEC23787Ea5F9310332B7970C3570B6dc933a463fc505d3787621712406040518363ffffffff1660e01b8152600401612c61929190615e1b565b60206040518083038186803b158015612c7957600080fd5b505af4158015612c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb19190615746565b90506000612cd3670de0b6b3a764000061280885670b1a2bc2ec500000613ce0565b905080841015612ce557809350612d15565b6000612d05670de0b6b3a76400006128088667136dcc951d8c0000613ce0565b905080851115612d13578094505b505b60405163fc505d3760e01b815260009073c3eEC23787Ea5F9310332B7970C3570B6dc933a49063fc505d3790612d519087908990600401615dfc565b60206040518083038186803b158015612d6957600080fd5b505af4158015612d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da19190615746565b90506000612e398473c3eEC23787Ea5F9310332B7970C3570B6dc933a4632cbbdee5856040518263ffffffff1660e01b8152600401612de09190615aee565b60206040518083038186803b158015612df857600080fd5b505af4158015612e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e309190615746565b600f0b9061420f565b604051637e0c9e7960e11b815290915060009073c3eEC23787Ea5F9310332B7970C3570B6dc933a49063fc193cf290612e7a90600f86900b90600401615aee565b60206040518083038186803b158015612e9257600080fd5b505af4158015612ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eca9190615746565b9050612eda600f82900b896142a0565b9a505050505050505050505090565b600080612efb898888888e60006127b1565b90506000612f0e8a8a878a8f6000613bd3565b9050612f1e846128088385613ce0565b9b9a5050505050505050505050565b806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e846040518263ffffffff1660e01b8152600401612f839190615df3565b60206040518083038186803b158015612f9b57600080fd5b505afa158015612faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd39190615646565b6001600160a01b0316148061300157506000828152600960205260409020546001600160a01b038281169116145b61301d5760405162461bcd60e51b815260040161039090615b19565b5050565b60008061302c61296a565b90506000836130505761304b8261280888670de0b6b3a7640000613ce0565b613052565b855b600088815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915081156130ce576130ce818a8a856143f1565b85156130df576130df81898861310f565b6130e98184613159565b6130f388826131ab565b851561310357613103338761327e565b50979650505050505050565b61311983826144ae565b7f627a692d5a03ab34732c0d2aa319f3ecdebdc4528f383eabcb25441dc0a70cfb33838360405161314c939291906159d5565b60405180910390a1505050565b60008061316684846144ca565b91509150816131875760405162461bcd60e51b815260040161039090615c8f565b80156131a55760405162461bcd60e51b815260040161039090615cac565b50505050565b600091825260096020908152604092839020825181549284015163ffffffff16600160a01b027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff6001600160a01b039092166001600160a01b0319909416939093171691909117815591810151600190920180546060909201516001600160801b0316600160601b027fffffffff00000000000000000000000000000000ffffffffffffffffffffffff6001600160601b039094166bffffffffffffffffffffffff199093169290921792909216179055565b804710156132d3576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d806000811461331e576040519150601f19603f3d011682016040523d82523d6000602084013e613323565b606091505b50509050806133635760405162461bcd60e51b815260040180806020018281038252603a815260200180615e9f603a913960400191505060405180910390fd5b505050565b602083015163ffffffff1661337c84614684565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906133cc90309087908690600401615975565b600060405180830381600087803b1580156133e657600080fd5b505af11580156133fa573d6000803e3d6000fd5b505050507fe59f38fa1264fc25c9f0185eee136eaf810d90b8e7293b342e4037c68720177a338383604051613431939291906159d5565b60405180910390a150505050565b600082821115613496576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000806127f0868686868b60006127b1565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166399fbab88866040518263ffffffff1660e01b81526004016135059190615df3565b6101806040518083038186803b15801561351e57600080fd5b505afa158015613532573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135569190615887565b505050509750505095509550955050506000816001600160801b03161161358f5760405162461bcd60e51b815260040161039090615bc6565b7f000000000000000000000000000000000000000000000000000000000000000062ffffff168262ffffff16146135d85760405162461bcd60e51b815260040161039090615b36565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614801561364a57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b806136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161480156136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b6136de5760405162461bcd60e51b815260040161039090615ba9565b6136e888866146cf565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613738908a9030908a90600401615975565b600060405180830381600087803b15801561375257600080fd5b505af1158015613766573d6000803e3d6000fd5b505050507f3917c2f26ce18614e3aedd1289da672ef6563c5c295f49e9b1697ae0ad31556233878760405161379d939291906159d5565b60405180910390a15050505050505050565b602084015160009063ffffffff16806137cc576000915050610bb9565b6000806137d883614764565b9092509050811561386257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061382f908590600401615df3565b600060405180830381600087803b15801561384957600080fd5b505af115801561385d573d6000803e3d6000fd5b505050505b60008060006138738b86868b614931565b9194509250905081156139225760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906138ce908d908690600401615999565b602060405180830381600087803b1580156138e857600080fd5b505af11580156138fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139209190615726565b505b82156139a957604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906139769030908790600401615999565b600060405180830381600087803b15801561399057600080fd5b505af11580156139a4573d6000803e3d6000fd5b505050505b7ffd0ae2fd36bd955810ae42615bc5ff277c0d0dfcb930f06c9f1777c0ef0752e3338a87878787876040516139e49796959493929190615a1c565b60405180910390a19a9950505050505050505050565b6000610bb96ec097ce7bc90715b34b9f100000000061280885613a1d8887613ce0565b90613ce0565b600080613a3084846144ca565b50949350505050565b613a438382613a76565b7f3ca13b7aab12bad7472691fe558faa6b25e99099824a0070a88bd5aa84be610f33838360405161314c939291906159d5565b6040820151613a9790613a92906001600160601b0316836149c7565b614a21565b6001600160601b031660409092019190915250565b600080600080613ad78789606001516001600160801b03168a604001516001600160601b0316614a68565b9150915081871015613afb5760405162461bcd60e51b815260040161039090615c00565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90613b499088908690600401615999565b600060405180830381600087803b158015613b6357600080fd5b505af1158015613b77573d6000803e3d6000fd5b50505050613b8e8289614ad090919063ffffffff16565b613b9888826144ae565b6000613ba489886144ca565b9150508015613bc55760405162461bcd60e51b815260040161039090615cac565b509097909650945050505050565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b158015613c4257600080fd5b505afa158015613c56573d6000803e3d6000fd5b505050506040513d6020811015613c6c57600080fd5b5051979650505050505050565b6000808211613ccf576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613cd857fe5b049392505050565b600082613cef5750600061349b565b82820282848281613cfc57fe5b0414613d395760405162461bcd60e51b8152600401808060200182810382526021815260200180615ed96021913960400191505060405180910390fd5b9392505050565b6000613d4a6155bc565b6040516354ba0f2760e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906354ba0f2790613d99908790600401615961565b602060405180830381600087803b158015613db357600080fd5b505af1158015613dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613deb9190615799565b6040805160808101825260008082526020820181905281830181905260608201529051919250907f25ff1e0131762176a9084e92880f880f39d6d0e62134607f37e631efe1bad87190613e419033908590615999565b60405180910390a19092509050915091565b600354600090819080613e6d576000849250925050613f42565b600080613efd877f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b90506000613f116127106128088487613ce0565b905080871115613f2c57613f25878261343f565b9250613f3a565b613f3689826144ae565b8692505b945090925050505b935093915050565b613f548482614b32565b6040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990613fa29086908590600401615999565b600060405180830381600087803b158015613fbc57600080fd5b505af1158015613fd0573d6000803e3d6000fd5b505050507fb19fa182730a088464dad0e9e0badeb470d0d8d937d854f5caf15c6ad1992c36338284604051613431939291906159d5565b8063ffffffff81168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a3199960e11b604482015290519081900360640190fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b81526004016140ba9190615961565b60206040518083038186803b1580156140d257600080fd5b505afa1580156140e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410a919061586b565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040161417a9190615961565b60206040518083038186803b15801561419257600080fd5b505afa1580156141a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141ca919061586b565b905060008163ffffffff168363ffffffff16116141e757826141e9565b815b90508063ffffffff168563ffffffff16116142045784614206565b805b95945050505050565b6000600f83810b9083900b0260401d6f7fffffffffffffffffffffffffffffff19811280159061424f57506f7fffffffffffffffffffffffffffffff8113155b613d39576040805162461bcd60e51b815260206004820152600860248201527f4d554c2d4f565546000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000816142af5750600061349b565b600083600f0b1215614308576040805162461bcd60e51b815260206004820152600760248201527f4d554c552d583000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600f83900b6001600160801b038316810260401c90608084901c0277ffffffffffffffffffffffffffffffffffffffffffffffff811115614390576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4631000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60401b81198111156143e9576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4632000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b019392505050565b6143fb8482614ad0565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906144499086908590600401615999565b600060405180830381600087803b15801561446357600080fd5b505af1158015614477573d6000803e3d6000fd5b505050507fea19ffc45b48de6d95594aacff7214dd24595fdb0c60e98c8f0b269058c2f792338284604051613431939291906159d5565b6040820151613a9790613a92906001600160601b03168361343f565b60008060006145607f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460016127b1565b9050614678857f00000000000000000000000000000000000000000000000000000000000000008684675fc1b971363200007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634a0a96eb7f00000000000000000000000000000000000000000000000000000000000000006101a46040518363ffffffff1660e01b8152600401614602929190615a71565b60206040518083038186803b15801561461a57600080fd5b505afa15801561462e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146529190615767565b7f0000000000000000000000000000000000000000000000000000000000000000614b4e565b92509250509250929050565b602081015163ffffffff166146c5576040805162461bcd60e51b81526020600482015260026024820152612b1960f11b604482015290519081900360640190fd5b6000602090910152565b602082015163ffffffff1615614711576040805162461bcd60e51b8152602060048201526002602482015261563160f01b604482015290519081900360640190fd5b80614749576040805162461bcd60e51b815260206004820152600360248201526243323360e81b604482015290519081900360640190fd5b61475281614007565b63ffffffff1660209092019190915250565b6000807f0000000000000000000000000000000000000000000000000000000000000000816147938286614bf2565b50506040805160a0810182528981526001600160801b0383166020820152600081830181905260608201524260808201529051630624e65f60e11b815291945092506001600160a01b0385169150630c49ccbe906147f5908490600401615d62565b6040805180830381600087803b15801561480e57600080fd5b505af1158015614822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148469190615801565b5050604080516080810182528781523060208201526001600160801b038183018190526060820152905163fc6f786560e01b815260009081906001600160a01b0387169063fc6f78659061489e908690600401615d1f565b6040805180830381600087803b1580156148b757600080fd5b505af11580156148cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148ef9190615801565b915091507f000000000000000000000000000000000000000000000000000000000000000061491f578082614922565b81815b97509750505050505050915091565b600080600080841561494a576149478787614cb0565b90505b606088015186906000906001600160801b03168211156149905760608a015161497d9089906001600160801b031661343f565b905089606001516001600160801b031691505b61499a8a83614ad0565b6149a38a614684565b6149ad8a8a613a76565b6149b78a846144ae565b9099909850909650945050505050565b600082820183811015613d39576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b806001600160601b0381168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a31c9b60e11b604482015290519081900360640190fd5b6000808080614a8187614a7c886002613c79565b614d60565b9150915080851115614ab657675fc1b97136320000614aa0868361343f565b1015614ab657614ab08787614d60565b90925090505b84811115614ac45750849050835b90969095509350505050565b6060820151614af190614aec906001600160801b03168361343f565b61274f565b6001600160801b031660609092019190915250565b600080614b1a868686866101a46000613bd3565b905061280e670de0b6b3a76400006128088984613ce0565b6060820151614af190614aec906001600160801b0316836149c7565b60008088606001516001600160801b031660001415614b735750600190506000614be6565b6000614bac6ec097ce7bc90715b34b9f100000000061280889613a1d8c8f606001516001600160801b0316613ce090919063ffffffff16565b90506000614bbe8b8b8b8b8a8a614e3c565b90508681106000614bd0846003613ce0565b614bdb846002613ce0565b101595509093505050505b97509795505050505050565b6000806000806000808790506000806000806000856001600160a01b03166399fbab888d6040518263ffffffff1660e01b8152600401808281526020019150506101806040518083038186803b158015614c4b57600080fd5b505afa158015614c5f573d6000803e3d6000fd5b505050506040513d610180811015614c7657600080fd5b5060a081015160c082015160e083015161014084015161016090940151929e50909c509a5090985096505050505050509295509295909350565b6000613d39670de0b6b3a764000061280866470de4df820000613a1d87614d5a887f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b906149c7565b6000806000838511614d725784614d74565b835b90506000614e05827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b9050614e2f614e28670de0b6b3a76400006128088467016345785d8a0000613ce0565b82906149c7565b9196919550909350505050565b6000866020015163ffffffff1660001415614e65575060408601516001600160601b03166127d4565b600080614e7e888a6020015163ffffffff168787614ed3565b90925090506000614ea66ec097ce7bc90715b34b9f100000000061280889613a1d868d613ce0565b60408b0151909150614ec5906001600160601b0316614d5a85846149c7565b9a9950505050505050505050565b6000806000806000806000614ee88b8b614bf2565b94509450945094509450600080614f0187878d88614f54565b9150915089614f2757826001600160801b03168101846001600160801b03168301614f40565b836001600160801b03168201836001600160801b031682015b985098505050505050505094509492505050565b600080600073Aca2c805A88f80D7857773E4b80dE580Dc7ef4Ea63986cfba3866040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b158015614fab57600080fd5b505af4158015614fbf573d6000803e3d6000fd5b505050506040513d6020811015614fd557600080fd5b50519050600287810b9086900b12156151985773786a197a14C5dBD1B10acb3a997F6d0E81b447ea632c32d4b673Aca2c805A88f80D7857773E4b80dE580Dc7ef4Ea63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561505457600080fd5b505af4158015615068573d6000803e3d6000fd5b505050506040513d602081101561507e57600080fd5b50516040805163986cfba360e01b815260028b900b6004820152905173Aca2c805A88f80D7857773E4b80dE580Dc7ef4Ea9163986cfba3916024808301926020929190829003018186803b1580156150d557600080fd5b505af41580156150e9573d6000803e3d6000fd5b505050506040513d60208110156150ff57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561516557600080fd5b505af4158015615179573d6000803e3d6000fd5b505050506040513d602081101561518f57600080fd5b505192506155b2565b8560020b8560020b12156154065773786a197a14C5dBD1B10acb3a997F6d0E81b447ea632c32d4b68273Aca2c805A88f80D7857773E4b80dE580Dc7ef4Ea63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561521357600080fd5b505af4158015615227573d6000803e3d6000fd5b505050506040513d602081101561523d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156152a357600080fd5b505af41580156152b7573d6000803e3d6000fd5b505050506040513d60208110156152cd57600080fd5b50516040805163986cfba360e01b815260028a900b6004820152905191945073786a197a14C5dBD1B10acb3a997F6d0E81b447ea916348a0c5bd9173Aca2c805A88f80D7857773E4b80dE580Dc7ef4Ea9163986cfba391602480820192602092909190829003018186803b15801561534457600080fd5b505af4158015615358573d6000803e3d6000fd5b505050506040513d602081101561536e57600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b03928316600482015291851660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156153d357600080fd5b505af41580156153e7573d6000803e3d6000fd5b505050506040513d60208110156153fd57600080fd5b505191506155b2565b73786a197a14C5dBD1B10acb3a997F6d0E81b447ea6348a0c5bd73Aca2c805A88f80D7857773E4b80dE580Dc7ef4Ea63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561547257600080fd5b505af4158015615486573d6000803e3d6000fd5b505050506040513d602081101561549c57600080fd5b50516040805163986cfba360e01b815260028b900b6004820152905173Aca2c805A88f80D7857773E4b80dE580Dc7ef4Ea9163986cfba3916024808301926020929190829003018186803b1580156154f357600080fd5b505af4158015615507573d6000803e3d6000fd5b505050506040513d602081101561551d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561558357600080fd5b505af4158015615597573d6000803e3d6000fd5b505050506040513d60208110156155ad57600080fd5b505191505b5094509492505050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b8051610c5381615e31565b8051600281900b8114610c5357600080fd5b80516001600160801b0381168114610c5357600080fd5b805162ffffff81168114610c5357600080fd5b60006020828403121561563b578081fd5b8135613d3981615e31565b600060208284031215615657578081fd5b8151613d3981615e31565b60008060008060808587031215615677578283fd5b843561568281615e31565b935060208581013561569381615e31565b935060408601359250606086013567ffffffffffffffff808211156156b6578384fd5b818801915088601f8301126156c9578384fd5b8135818111156156d557fe5b604051601f8201601f19168101850183811182821017156156f257fe5b60405281815283820185018b1015615708578586fd5b81858501868301379081019093019390935250939692955090935050565b600060208284031215615737578081fd5b81518015158114613d39578182fd5b600060208284031215615757578081fd5b815180600f0b8114613d39578182fd5b600060208284031215615778578081fd5b613d39826155ee565b600060208284031215615792578081fd5b5035919050565b6000602082840312156157aa578081fd5b5051919050565b600080604083850312156157c3578182fd5b8235915060208301356157d581615e31565b809150509250929050565b600080604083850312156157f2578182fd5b50508035926020909101359150565b60008060408385031215615813578182fd5b505080516020909101519092909150565b600080600060608486031215615838578283fd5b505081359360208301359350604090920135919050565b600060208284031215615860578081fd5b8135613d3981615e46565b60006020828403121561587c578081fd5b8151613d3981615e46565b6000806000806000806000806000806000806101808d8f0312156158a957898afd5b8c516001600160601b03811681146158bf578a8bfd5b9b506158cd60208e016155e3565b9a506158db60408e016155e3565b99506158e960608e016155e3565b98506158f760808e01615617565b975061590560a08e016155ee565b965061591360c08e016155ee565b955061592160e08e01615600565b94506101008d015193506101208d015192506159406101408e01615600565b915061594f6101608e01615600565b90509295989b509295989b509295989b565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b03979097168752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0392909216825263ffffffff16602082015260400190565b6001600160a01b0394909416845263ffffffff9290921660208401526001600160601b031660408301526001600160801b0316606082015260800190565b901515815260200190565b6001600160e01b031991909116815260200190565b600f9190910b815260200190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b602080825260029082015261043360f41b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b602080825260029082015261433360f01b604082015260600190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b6001600160801b0391909116815260200190565b6001600160801b039485168152602081019390935292166040820152606081019190915260800190565b62ffffff91909116815260200190565b90815260200190565b918252602082015260400190565b63ffffffff91909116815260200190565b63ffffffff929092168252602082015260400190565b6001600160a01b0381168114610d1f57600080fd5b63ffffffff81168114610d1f57600080fdfe5265656e7472616e637947756172643a207265656e7472616e742063616c6c004f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212201ca81e10125d74fc4d8a6f7c39e0648cc26a50a8c5deec6ca4fb49cb3041e74964736f6c63430007060033\",\n  \"deployedBytecode\": \"0x6080604052600436106103435760003560e01c80638456cb59116101b0578063b707ab99116100ec578063e74b981b11610095578063f2fde38b1161006f578063f2fde38b146108d0578063f90c3f27146108f0578063fbfc6bc014610905578063ff947525146109255761039b565b8063e74b981b14610888578063ed88c68e146108a8578063ee3189ff146108b05761039b565b8063d296d1f1116100c6578063d296d1f11461083e578063d52725841461085e578063de4a427a146108735761039b565b8063b707ab99146107e9578063c65a391d146107fe578063c9e77ee81461081e5761039b565b806391b8d34a116101595780639d4c9442116101335780639d4c944214610781578063a847e67414610796578063ac6cd5ef146107b6578063b6b55f25146107d65761039b565b806391b8d34a1461072c578063978bbdb91461074c57806397efa942146107615761039b565b80638cd21d7c1161018a5780638cd21d7c146106e25780638da5cb5b1461070257806391b4ded9146107175761039b565b80638456cb591461067d5780638632cb03146106925780638c64ea4a146106b25761039b565b806345596e2e1161027f57806372f5d98a116102285780637dc0d1d0116102025780637dc0d1d0146106295780637f07b1301461063e5780638146b09f1461065357806382564bca146106685761039b565b806372f5d98a146105c35780637691c4ac146105e55780637ca25184146106075761039b565b806363b38ae41161025957806363b38ae414610579578063713d517f1461058e578063715018a6146105ae5761039b565b806345596e2e1461052257806346904840146105425780634be2822c146105575761039b565b806324f5f531116102ec5780633fc8cef3116102c65780633fc8cef3146104ab5780634394318d146104cd578063441a3e70146104ed5780634468c0221461050d5761039b565b806324f5f53114610463578063377a19361461047857806339467918146104985761039b565b806315aded831161031d57806315aded83146104005780631bf7bf6c1461042d578063200f4b8d1461044e5761039b565b806307633669146103a057806310b9e583146103b5578063150b7a02146103ca5761039b565b3661039b57336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103995760405162461bcd60e51b815260040161039090615cc9565b60405180910390fd5b005b600080fd5b3480156103ac57600080fd5b5061039961093a565b3480156103c157600080fd5b50610399610a3d565b3480156103d657600080fd5b506103ea6103e5366004615662565b610bb0565b6040516103f79190615ad9565b60405180910390f35b34801561040c57600080fd5b5061042061041b36600461584f565b610bc1565b6040516103f79190615df3565b61044061043b366004615824565b610c58565b6040516103f7929190615dfc565b34801561045a57600080fd5b50610399610cef565b34801561046f57600080fd5b50610420610d22565b34801561048457600080fd5b5061042061049336600461584f565b610d32565b6104206104a6366004615824565b610e22565b3480156104b757600080fd5b506104c0610eba565b6040516103f79190615961565b3480156104d957600080fd5b506104206104e8366004615824565b610ede565b3480156104f957600080fd5b506103996105083660046157e0565b610f78565b34801561051957600080fd5b506104c061109c565b34801561052e57600080fd5b5061039961053d366004615781565b6110c0565b34801561054e57600080fd5b506104c06111bd565b34801561056357600080fd5b5061056c6111cc565b6040516103f79190615da5565b34801561058557600080fd5b506104206111e2565b34801561059a57600080fd5b506103996105a9366004615781565b6111e8565b3480156105ba57600080fd5b50610399611301565b3480156105cf57600080fd5b506105d86113bf565b6040516103f79190615de3565b3480156105f157600080fd5b506105fa6113e3565b6040516103f79190615ace565b34801561061357600080fd5b5061061c6113f1565b6040516103f79190615e0a565b34801561063557600080fd5b506104c06113f7565b34801561064a57600080fd5b506104c061141b565b34801561065f57600080fd5b5061039961143f565b34801561067457600080fd5b506104c06114af565b34801561068957600080fd5b506103996114d3565b34801561069e57600080fd5b506103996106ad366004615824565b61165c565b3480156106be57600080fd5b506106d26106cd366004615781565b6116e7565b6040516103f79493929190615a90565b3480156106ee57600080fd5b506104206106fd36600461584f565b611734565b34801561070e57600080fd5b506104c06117c3565b34801561072357600080fd5b506104206117d2565b34801561073857600080fd5b506103996107473660046157e0565b6117d8565b34801561075857600080fd5b506104206118d1565b34801561076d57600080fd5b5061039961077c366004615781565b6118d7565b34801561078d57600080fd5b506104c0611a77565b3480156107a257600080fd5b506105fa6107b1366004615781565b611a9b565b3480156107c257600080fd5b506103996107d1366004615781565b611b15565b6103996107e4366004615781565b611c6f565b3480156107f557600080fd5b506104c0611d79565b34801561080a57600080fd5b506103996108193660046157b1565b611d9d565b34801561082a57600080fd5b50610399610839366004615781565b611efb565b34801561084a57600080fd5b506104206108593660046157e0565b61208d565b34801561086a57600080fd5b5061056c6122f8565b34801561087f57600080fd5b50610420612307565b34801561089457600080fd5b506103996108a336600461562a565b61230d565b610399612410565b3480156108bc57600080fd5b506104206108cb36600461584f565b612434565b3480156108dc57600080fd5b506103996108eb36600461562a565b61250d565b3480156108fc57600080fd5b50610420612621565b34801561091157600080fd5b50610399610920366004615781565b612628565b34801561093157600080fd5b506105fa612746565b6109426127ad565b6001600160a01b03166109536117c3565b6001600160a01b0316146109ae576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600854610100900460ff166109d55760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156109f85760405162461bcd60e51b815260040161039090615b53565b6008805461ff00191690556040517fff2b959f2bcdb44c7ecb4b16dae055431019d7350607125cfc2b74a06632c90e90610a33903390615961565b60405180910390a1565b610a456127ad565b6001600160a01b0316610a566117c3565b6001600160a01b031614610ab1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff1615610ad45760405162461bcd60e51b815260040161039090615b53565b6008805460ff1961ff001990911661010017166001179055610b7d7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460006127b1565b60048190556040517f574214b195bf5273a95bb4498e35cf1fde0ce327c727a95ec2ab359f7ba4e11a91610a3391615df3565b630a85bd0160e11b5b949350505050565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006127de565b90505b919050565b6008546000908190610100900460ff1615610c855760405162461bcd60e51b815260040161039090615c39565b60026001541415610ccb576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610cdf33868634876000612819565b6001805590969095509350505050565b600854610100900460ff1615610d175760405162461bcd60e51b815260040161039090615c39565b610d1f61296a565b50565b6000610d2c612a58565b90505b90565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000600760009054906101000a90046001600160801b03166001600160801b0316612ee9565b600854600090610100900460ff1615610e4d5760405162461bcd60e51b815260040161039090615c39565b60026001541415610e93576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001819055506000610eac33868634876001612819565b506001805595945050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854600090610100900460ff1615610f095760405162461bcd60e51b815260040161039090615c39565b60026001541415610f4f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610f5e8433612f2d565b610f6c338585856000613021565b60018055949350505050565b600854610100900460ff1615610fa05760405162461bcd60e51b815260040161039090615c39565b60026001541415610fe6576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155610ff58233612f2d565b6000610fff61296a565b600084815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915061107481858561310f565b61107e8183613159565b61108884826131ab565b611092338461327e565b5050600180555050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6110c86127ad565b6001600160a01b03166110d96117c3565b6001600160a01b031614611134576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6002546001600160a01b031661115c5760405162461bcd60e51b815260040161039090615afc565b606481111561117d5760405162461bcd60e51b815260040161039090615c55565b7f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957600354826040516111b0929190615dfc565b60405180910390a1600355565b6002546001600160a01b031681565b600754600160801b90046001600160801b031681565b60055481565b600854610100900460ff16156112105760405162461bcd60e51b815260040161039090615c39565b60026001541415611256576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556112658133612f2d565b600061126f61296a565b600083815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506112e4813385613368565b6112ee8183613159565b6112f883826131ab565b50506001805550565b6113096127ad565b6001600160a01b031661131a6117c3565b6001600160a01b031614611375576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff1681565b6101a481565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600854610100900460ff166114665760405162461bcd60e51b815260040161039090615c1d565b60085460ff16156114895760405162461bcd60e51b815260040161039090615b53565b600654620151800142116109f85760405162461bcd60e51b815260040161039090615be3565b7f000000000000000000000000000000000000000000000000000000000000000081565b6114db6127ad565b6001600160a01b03166114ec6117c3565b6001600160a01b031614611547576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60085460ff161561156a5760405162461bcd60e51b815260040161039090615b53565b600854610100900460ff16156115925760405162461bcd60e51b815260040161039090615c39565b6000600554116115b45760405162461bcd60e51b815260040161039090615b6f565b60006115e0427f000000000000000000000000000000000000000000000000000000000000000061343f565b905062eff10081106116045760405162461bcd60e51b815260040161039090615ce6565b6008805461ff001916610100179055600580546000190190819055426006556040517f32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e9161165191615df3565b60405180910390a150565b600854610100900460ff16156116845760405162461bcd60e51b815260040161039090615c39565b600260015414156116ca576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556116d98333612f2d565b611092338484846001613021565b600960205260009081526040902080546001909101546001600160a01b03821691600160a01b900463ffffffff16906001600160601b03811690600160601b90046001600160801b031684565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b6000546001600160a01b031690565b60065481565b600854610100900460ff16156118005760405162461bcd60e51b815260040161039090615c39565b60026001541415611846576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001556118558233612f2d565b61185d61296a565b50600082815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201526112ee813385856134b3565b60035481565b60085460ff166118f95760405162461bcd60e51b815260040161039090615d03565b6002600154141561193f576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b600260015561194e8133612f2d565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b03908116606083015260075491929116906119cc908390339086906137af565b5060006119e983606001516001600160801b0316600454846139fa565b90506000611a0d8285604001516001600160601b031661343f90919063ffffffff16565b60006060860181905260408601529050611a2785856131ab565b611a31338261327e565b7f7dff8cdaec6a8d4d1ad32d3c947ed0f0281c3d6456621ef928defae96ec6cddb338683604051611a64939291906159d5565b60405180910390a1505060018055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000818152600960209081526040808320815160808101835281546001600160a01b0381168252600160a01b900463ffffffff1693810193909352600101546001600160601b03811691830191909152600160601b90046001600160801b0316606082015281611b09612a58565b9050610bb98282613a23565b60085460ff16611b375760405162461bcd60e51b815260040161039090615d03565b60026001541415611b7d576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90611bd09033908590600401615999565b600060405180830381600087803b158015611bea57600080fd5b505af1158015611bfe573d6000803e3d6000fd5b505060045460075460009350611c2092508491906001600160801b03166139fa565b9050611c2c338261327e565b7f2131ef4f2f82ca75fe7d2e646ebfa45b6be25e53510c829629c76b641500ec67338383604051611c5f939291906159d5565b60405180910390a1505060018055565b600854610100900460ff1615611c975760405162461bcd60e51b815260040161039090615c39565b60026001541415611cdd576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611cec8133612f2d565b611cf461296a565b50600081815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b03166060820152611d67818334613a39565b611d7182826131ab565b505060018055565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331480611e7857506040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611e1d908690600401615df3565b60206040518083038186803b158015611e3557600080fd5b505afa158015611e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6d9190615646565b6001600160a01b0316145b611e945760405162461bcd60e51b815260040161039090615b19565b6000828152600960205260409081902080546001600160a01b0319166001600160a01b038416179055517f3137fc9cd2e33c34f86e29c24d81f3c75b0bce639d3c4ed0d31eeff1160a7ff590611eef903390859085906159b2565b60405180910390a15050565b600854610100900460ff1615611f235760405162461bcd60e51b815260040161039090615c39565b60026001541415611f69576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155611f788133612f2d565b600081815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093526001909101546001600160601b03811682850152600160601b90046001600160801b0316606082015291516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60206040518083038186803b15801561204257600080fd5b505afa158015612056573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207a9190615646565b8460006137af565b50611d7182826131ab565b600854600090610100900460ff16156120b85760405162461bcd60e51b815260040161039090615c39565b600260015414156120fe576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b6002600155600061210d61296a565b600085815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201529091506121818183613a23565b1561219e5760405162461bcd60e51b815260040161039090615c72565b6000612248827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e896040518263ffffffff1660e01b81526004016121f09190615df3565b60206040518083038186803b15801561220857600080fd5b505afa15801561221c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122409190615646565b8860016137af565b90506122548284613a23565b156122795761226386836131ab565b61226d338261327e565b600093505050506122ee565b6122838282613a76565b60008061229284888733613aac565b915091507f158ba9ab7bbbd08eeffa4753bad41f4d450e24831d293427308badf3eadd8c76338984846040516122cb94939291906159f6565b60405180910390a16122dd88856131ab565b6122e7338261327e565b5093505050505b6001805592915050565b6007546001600160801b031681565b60045481565b6123156127ad565b6001600160a01b03166123266117c3565b6001600160a01b031614612381576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166123a75760405162461bcd60e51b815260040161039090615b8c565b6002546040517faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d3916123e6916001600160a01b03909116908490615a57565b60405180910390a1600280546001600160a01b0319166001600160a01b0392909216919091179055565b60085460ff166124325760405162461bcd60e51b815260040161039090615d03565b565b6000610c50827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612508612a58565b612ee9565b6125156127ad565b6001600160a01b03166125266117c3565b6001600160a01b031614612581576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166125c65760405162461bcd60e51b8152600401808060200182810382526026815260200180615e796026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6217124081565b60085460ff1661264a5760405162461bcd60e51b815260040161039090615d03565b60026001541415612690576040805162461bcd60e51b815260206004820152601f6024820152600080516020615e59833981519152604482015290519081900360640190fd5b60026001908155600082815260096020908152604091829020825160808101845281546001600160a01b038082168352600160a01b90910463ffffffff16938201939093529301546001600160601b03811684840152600160601b90046001600160801b0316606084015290516331a9108f60e11b81526120829183917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e9061202a908790600401615df3565b60085460ff1681565b806001600160801b0381168114610c53576040805162461bcd60e51b815260206004820152600560248201527f4f46313238000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b3390565b6000806127c2888888888888613bd3565b90506127d081612710613c79565b9150505b9695505050505050565b6000806127f0868686868b6000613bd3565b905061280e670de0b6b3a76400006128088380613ce0565b90613c79565b979650505050505050565b600080600061282661296a565b90508560008561284b57612846836128088b670de0b6b3a7640000613ce0565b61284d565b885b905060006128596155bc565b8b612871576128678d613d40565b909c5090506128e4565b61287b8c33612f2d565b5060008b815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b031660608201525b8215612905576128f581848c613e53565b94509150612905818e8e86613f4a565b891561291657612916818d86613a39565b881561292857612928818e8e8c6134b3565b6129328186613159565b61293c8c826131ab565b811561295857600254612958906001600160a01b03168361327e565b50999b909a5098505050505050505050565b6007546000906001600160801b03600160801b9091041642141561299a57506007546001600160801b0316610d2f565b60006129a4612a58565b6007546040519192507f339e53729b0447795ff69e70a74fed98fc7fef6fe94b7521099b32f0f8de4822916129f3916001600160801b03808216928692600160801b9004909116904290615db9565b60405180910390a1612a048161274f565b600780546fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055612a364261274f565b600780546001600160801b03928316600160801b029216919091179055905090565b6007546000908190612a8490612a7f904290600160801b90046001600160801b031661343f565b614007565b905063ffffffff8116612aa45750506007546001600160801b0316610d2f565b6000612aaf8261404b565b6007549091506001600160801b03166000612b90837f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000089612ee9565b90506000612c21847f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006134a1565b9050600073__$f98cbc68e241c61b30349ba6b91a975736$__63fc505d3787621712406040518363ffffffff1660e01b8152600401612c61929190615e1b565b60206040518083038186803b158015612c7957600080fd5b505af4158015612c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb19190615746565b90506000612cd3670de0b6b3a764000061280885670b1a2bc2ec500000613ce0565b905080841015612ce557809350612d15565b6000612d05670de0b6b3a76400006128088667136dcc951d8c0000613ce0565b905080851115612d13578094505b505b60405163fc505d3760e01b815260009073__$f98cbc68e241c61b30349ba6b91a975736$__9063fc505d3790612d519087908990600401615dfc565b60206040518083038186803b158015612d6957600080fd5b505af4158015612d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da19190615746565b90506000612e398473__$f98cbc68e241c61b30349ba6b91a975736$__632cbbdee5856040518263ffffffff1660e01b8152600401612de09190615aee565b60206040518083038186803b158015612df857600080fd5b505af4158015612e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e309190615746565b600f0b9061420f565b604051637e0c9e7960e11b815290915060009073__$f98cbc68e241c61b30349ba6b91a975736$__9063fc193cf290612e7a90600f86900b90600401615aee565b60206040518083038186803b158015612e9257600080fd5b505af4158015612ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eca9190615746565b9050612eda600f82900b896142a0565b9a505050505050505050505090565b600080612efb898888888e60006127b1565b90506000612f0e8a8a878a8f6000613bd3565b9050612f1e846128088385613ce0565b9b9a5050505050505050505050565b806001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e846040518263ffffffff1660e01b8152600401612f839190615df3565b60206040518083038186803b158015612f9b57600080fd5b505afa158015612faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd39190615646565b6001600160a01b0316148061300157506000828152600960205260409020546001600160a01b038281169116145b61301d5760405162461bcd60e51b815260040161039090615b19565b5050565b60008061302c61296a565b90506000836130505761304b8261280888670de0b6b3a7640000613ce0565b613052565b855b600088815260096020908152604091829020825160808101845281546001600160a01b0381168252600160a01b900463ffffffff1692810192909252600101546001600160601b03811692820192909252600160601b9091046001600160801b0316606082015290915081156130ce576130ce818a8a856143f1565b85156130df576130df81898861310f565b6130e98184613159565b6130f388826131ab565b851561310357613103338761327e565b50979650505050505050565b61311983826144ae565b7f627a692d5a03ab34732c0d2aa319f3ecdebdc4528f383eabcb25441dc0a70cfb33838360405161314c939291906159d5565b60405180910390a1505050565b60008061316684846144ca565b91509150816131875760405162461bcd60e51b815260040161039090615c8f565b80156131a55760405162461bcd60e51b815260040161039090615cac565b50505050565b600091825260096020908152604092839020825181549284015163ffffffff16600160a01b027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff6001600160a01b039092166001600160a01b0319909416939093171691909117815591810151600190920180546060909201516001600160801b0316600160601b027fffffffff00000000000000000000000000000000ffffffffffffffffffffffff6001600160601b039094166bffffffffffffffffffffffff199093169290921792909216179055565b804710156132d3576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d806000811461331e576040519150601f19603f3d011682016040523d82523d6000602084013e613323565b606091505b50509050806133635760405162461bcd60e51b815260040180806020018281038252603a815260200180615e9f603a913960400191505060405180910390fd5b505050565b602083015163ffffffff1661337c84614684565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906133cc90309087908690600401615975565b600060405180830381600087803b1580156133e657600080fd5b505af11580156133fa573d6000803e3d6000fd5b505050507fe59f38fa1264fc25c9f0185eee136eaf810d90b8e7293b342e4037c68720177a338383604051613431939291906159d5565b60405180910390a150505050565b600082821115613496576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000806127f0868686868b60006127b1565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166399fbab88866040518263ffffffff1660e01b81526004016135059190615df3565b6101806040518083038186803b15801561351e57600080fd5b505afa158015613532573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135569190615887565b505050509750505095509550955050506000816001600160801b03161161358f5760405162461bcd60e51b815260040161039090615bc6565b7f000000000000000000000000000000000000000000000000000000000000000062ffffff168262ffffff16146135d85760405162461bcd60e51b815260040161039090615b36565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614801561364a57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b806136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161480156136c257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b6136de5760405162461bcd60e51b815260040161039090615ba9565b6136e888866146cf565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613738908a9030908a90600401615975565b600060405180830381600087803b15801561375257600080fd5b505af1158015613766573d6000803e3d6000fd5b505050507f3917c2f26ce18614e3aedd1289da672ef6563c5c295f49e9b1697ae0ad31556233878760405161379d939291906159d5565b60405180910390a15050505050505050565b602084015160009063ffffffff16806137cc576000915050610bb9565b6000806137d883614764565b9092509050811561386257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061382f908590600401615df3565b600060405180830381600087803b15801561384957600080fd5b505af115801561385d573d6000803e3d6000fd5b505050505b60008060006138738b86868b614931565b9194509250905081156139225760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906138ce908d908690600401615999565b602060405180830381600087803b1580156138e857600080fd5b505af11580156138fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139209190615726565b505b82156139a957604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906139769030908790600401615999565b600060405180830381600087803b15801561399057600080fd5b505af11580156139a4573d6000803e3d6000fd5b505050505b7ffd0ae2fd36bd955810ae42615bc5ff277c0d0dfcb930f06c9f1777c0ef0752e3338a87878787876040516139e49796959493929190615a1c565b60405180910390a19a9950505050505050505050565b6000610bb96ec097ce7bc90715b34b9f100000000061280885613a1d8887613ce0565b90613ce0565b600080613a3084846144ca565b50949350505050565b613a438382613a76565b7f3ca13b7aab12bad7472691fe558faa6b25e99099824a0070a88bd5aa84be610f33838360405161314c939291906159d5565b6040820151613a9790613a92906001600160601b0316836149c7565b614a21565b6001600160601b031660409092019190915250565b600080600080613ad78789606001516001600160801b03168a604001516001600160601b0316614a68565b9150915081871015613afb5760405162461bcd60e51b815260040161039090615c00565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90613b499088908690600401615999565b600060405180830381600087803b158015613b6357600080fd5b505af1158015613b77573d6000803e3d6000fd5b50505050613b8e8289614ad090919063ffffffff16565b613b9888826144ae565b6000613ba489886144ca565b9150508015613bc55760405162461bcd60e51b815260040161039090615cac565b509097909650945050505050565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b158015613c4257600080fd5b505afa158015613c56573d6000803e3d6000fd5b505050506040513d6020811015613c6c57600080fd5b5051979650505050505050565b6000808211613ccf576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613cd857fe5b049392505050565b600082613cef5750600061349b565b82820282848281613cfc57fe5b0414613d395760405162461bcd60e51b8152600401808060200182810382526021815260200180615ed96021913960400191505060405180910390fd5b9392505050565b6000613d4a6155bc565b6040516354ba0f2760e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906354ba0f2790613d99908790600401615961565b602060405180830381600087803b158015613db357600080fd5b505af1158015613dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613deb9190615799565b6040805160808101825260008082526020820181905281830181905260608201529051919250907f25ff1e0131762176a9084e92880f880f39d6d0e62134607f37e631efe1bad87190613e419033908590615999565b60405180910390a19092509050915091565b600354600090819080613e6d576000849250925050613f42565b600080613efd877f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b90506000613f116127106128088487613ce0565b905080871115613f2c57613f25878261343f565b9250613f3a565b613f3689826144ae565b8692505b945090925050505b935093915050565b613f548482614b32565b6040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990613fa29086908590600401615999565b600060405180830381600087803b158015613fbc57600080fd5b505af1158015613fd0573d6000803e3d6000fd5b505050507fb19fa182730a088464dad0e9e0badeb470d0d8d937d854f5caf15c6ad1992c36338284604051613431939291906159d5565b8063ffffffff81168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a3199960e11b604482015290519081900360640190fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b81526004016140ba9190615961565b60206040518083038186803b1580156140d257600080fd5b505afa1580156140e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410a919061586b565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663de5a6e227f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040161417a9190615961565b60206040518083038186803b15801561419257600080fd5b505afa1580156141a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141ca919061586b565b905060008163ffffffff168363ffffffff16116141e757826141e9565b815b90508063ffffffff168563ffffffff16116142045784614206565b805b95945050505050565b6000600f83810b9083900b0260401d6f7fffffffffffffffffffffffffffffff19811280159061424f57506f7fffffffffffffffffffffffffffffff8113155b613d39576040805162461bcd60e51b815260206004820152600860248201527f4d554c2d4f565546000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000816142af5750600061349b565b600083600f0b1215614308576040805162461bcd60e51b815260206004820152600760248201527f4d554c552d583000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600f83900b6001600160801b038316810260401c90608084901c0277ffffffffffffffffffffffffffffffffffffffffffffffff811115614390576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4631000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60401b81198111156143e9576040805162461bcd60e51b815260206004820152600860248201527f4d554c552d4f4632000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b019392505050565b6143fb8482614ad0565b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906144499086908590600401615999565b600060405180830381600087803b15801561446357600080fd5b505af1158015614477573d6000803e3d6000fd5b505050507fea19ffc45b48de6d95594aacff7214dd24595fdb0c60e98c8f0b269058c2f792338284604051613431939291906159d5565b6040820151613a9790613a92906001600160601b03168361343f565b60008060006145607f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460016127b1565b9050614678857f00000000000000000000000000000000000000000000000000000000000000008684675fc1b971363200007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634a0a96eb7f00000000000000000000000000000000000000000000000000000000000000006101a46040518363ffffffff1660e01b8152600401614602929190615a71565b60206040518083038186803b15801561461a57600080fd5b505afa15801561462e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146529190615767565b7f0000000000000000000000000000000000000000000000000000000000000000614b4e565b92509250509250929050565b602081015163ffffffff166146c5576040805162461bcd60e51b81526020600482015260026024820152612b1960f11b604482015290519081900360640190fd5b6000602090910152565b602082015163ffffffff1615614711576040805162461bcd60e51b8152602060048201526002602482015261563160f01b604482015290519081900360640190fd5b80614749576040805162461bcd60e51b815260206004820152600360248201526243323360e81b604482015290519081900360640190fd5b61475281614007565b63ffffffff1660209092019190915250565b6000807f0000000000000000000000000000000000000000000000000000000000000000816147938286614bf2565b50506040805160a0810182528981526001600160801b0383166020820152600081830181905260608201524260808201529051630624e65f60e11b815291945092506001600160a01b0385169150630c49ccbe906147f5908490600401615d62565b6040805180830381600087803b15801561480e57600080fd5b505af1158015614822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148469190615801565b5050604080516080810182528781523060208201526001600160801b038183018190526060820152905163fc6f786560e01b815260009081906001600160a01b0387169063fc6f78659061489e908690600401615d1f565b6040805180830381600087803b1580156148b757600080fd5b505af11580156148cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148ef9190615801565b915091507f000000000000000000000000000000000000000000000000000000000000000061491f578082614922565b81815b97509750505050505050915091565b600080600080841561494a576149478787614cb0565b90505b606088015186906000906001600160801b03168211156149905760608a015161497d9089906001600160801b031661343f565b905089606001516001600160801b031691505b61499a8a83614ad0565b6149a38a614684565b6149ad8a8a613a76565b6149b78a846144ae565b9099909850909650945050505050565b600082820183811015613d39576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b806001600160601b0381168114610c53576040805162461bcd60e51b8152602060048083019190915260248201526327a31c9b60e11b604482015290519081900360640190fd5b6000808080614a8187614a7c886002613c79565b614d60565b9150915080851115614ab657675fc1b97136320000614aa0868361343f565b1015614ab657614ab08787614d60565b90925090505b84811115614ac45750849050835b90969095509350505050565b6060820151614af190614aec906001600160801b03168361343f565b61274f565b6001600160801b031660609092019190915250565b600080614b1a868686866101a46000613bd3565b905061280e670de0b6b3a76400006128088984613ce0565b6060820151614af190614aec906001600160801b0316836149c7565b60008088606001516001600160801b031660001415614b735750600190506000614be6565b6000614bac6ec097ce7bc90715b34b9f100000000061280889613a1d8c8f606001516001600160801b0316613ce090919063ffffffff16565b90506000614bbe8b8b8b8b8a8a614e3c565b90508681106000614bd0846003613ce0565b614bdb846002613ce0565b101595509093505050505b97509795505050505050565b6000806000806000808790506000806000806000856001600160a01b03166399fbab888d6040518263ffffffff1660e01b8152600401808281526020019150506101806040518083038186803b158015614c4b57600080fd5b505afa158015614c5f573d6000803e3d6000fd5b505050506040513d610180811015614c7657600080fd5b5060a081015160c082015160e083015161014084015161016090940151929e50909c509a5090985096505050505050509295509295909350565b6000613d39670de0b6b3a764000061280866470de4df820000613a1d87614d5a887f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b906149c7565b6000806000838511614d725784614d74565b835b90506000614e05827f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614b06565b9050614e2f614e28670de0b6b3a76400006128088467016345785d8a0000613ce0565b82906149c7565b9196919550909350505050565b6000866020015163ffffffff1660001415614e65575060408601516001600160601b03166127d4565b600080614e7e888a6020015163ffffffff168787614ed3565b90925090506000614ea66ec097ce7bc90715b34b9f100000000061280889613a1d868d613ce0565b60408b0151909150614ec5906001600160601b0316614d5a85846149c7565b9a9950505050505050505050565b6000806000806000806000614ee88b8b614bf2565b94509450945094509450600080614f0187878d88614f54565b9150915089614f2757826001600160801b03168101846001600160801b03168301614f40565b836001600160801b03168201836001600160801b031682015b985098505050505050505094509492505050565b600080600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba3866040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b158015614fab57600080fd5b505af4158015614fbf573d6000803e3d6000fd5b505050506040513d6020811015614fd557600080fd5b50519050600287810b9086900b12156151985773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b673__$d199f155f9376dc21890c162698c9ef049$__63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561505457600080fd5b505af4158015615068573d6000803e3d6000fd5b505050506040513d602081101561507e57600080fd5b50516040805163986cfba360e01b815260028b900b6004820152905173__$d199f155f9376dc21890c162698c9ef049$__9163986cfba3916024808301926020929190829003018186803b1580156150d557600080fd5b505af41580156150e9573d6000803e3d6000fd5b505050506040513d60208110156150ff57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561516557600080fd5b505af4158015615179573d6000803e3d6000fd5b505050506040513d602081101561518f57600080fd5b505192506155b2565b8560020b8560020b12156154065773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b68273__$d199f155f9376dc21890c162698c9ef049$__63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561521357600080fd5b505af4158015615227573d6000803e3d6000fd5b505050506040513d602081101561523d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156152a357600080fd5b505af41580156152b7573d6000803e3d6000fd5b505050506040513d60208110156152cd57600080fd5b50516040805163986cfba360e01b815260028a900b6004820152905191945073__$a98c5df505b68ab2f483703658c95acb30$__916348a0c5bd9173__$d199f155f9376dc21890c162698c9ef049$__9163986cfba391602480820192602092909190829003018186803b15801561534457600080fd5b505af4158015615358573d6000803e3d6000fd5b505050506040513d602081101561536e57600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b03928316600482015291851660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b1580156153d357600080fd5b505af41580156153e7573d6000803e3d6000fd5b505050506040513d60208110156153fd57600080fd5b505191506155b2565b73__$a98c5df505b68ab2f483703658c95acb30$__6348a0c5bd73__$d199f155f9376dc21890c162698c9ef049$__63986cfba38a6040518263ffffffff1660e01b8152600401808260020b815260200191505060206040518083038186803b15801561547257600080fd5b505af4158015615486573d6000803e3d6000fd5b505050506040513d602081101561549c57600080fd5b50516040805163986cfba360e01b815260028b900b6004820152905173__$d199f155f9376dc21890c162698c9ef049$__9163986cfba3916024808301926020929190829003018186803b1580156154f357600080fd5b505af4158015615507573d6000803e3d6000fd5b505050506040513d602081101561551d57600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526001600160801b038816604483015260016064830152516084808301926020929190829003018186803b15801561558357600080fd5b505af4158015615597573d6000803e3d6000fd5b505050506040513d60208110156155ad57600080fd5b505191505b5094509492505050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b8051610c5381615e31565b8051600281900b8114610c5357600080fd5b80516001600160801b0381168114610c5357600080fd5b805162ffffff81168114610c5357600080fd5b60006020828403121561563b578081fd5b8135613d3981615e31565b600060208284031215615657578081fd5b8151613d3981615e31565b60008060008060808587031215615677578283fd5b843561568281615e31565b935060208581013561569381615e31565b935060408601359250606086013567ffffffffffffffff808211156156b6578384fd5b818801915088601f8301126156c9578384fd5b8135818111156156d557fe5b604051601f8201601f19168101850183811182821017156156f257fe5b60405281815283820185018b1015615708578586fd5b81858501868301379081019093019390935250939692955090935050565b600060208284031215615737578081fd5b81518015158114613d39578182fd5b600060208284031215615757578081fd5b815180600f0b8114613d39578182fd5b600060208284031215615778578081fd5b613d39826155ee565b600060208284031215615792578081fd5b5035919050565b6000602082840312156157aa578081fd5b5051919050565b600080604083850312156157c3578182fd5b8235915060208301356157d581615e31565b809150509250929050565b600080604083850312156157f2578182fd5b50508035926020909101359150565b60008060408385031215615813578182fd5b505080516020909101519092909150565b600080600060608486031215615838578283fd5b505081359360208301359350604090920135919050565b600060208284031215615860578081fd5b8135613d3981615e46565b60006020828403121561587c578081fd5b8151613d3981615e46565b6000806000806000806000806000806000806101808d8f0312156158a957898afd5b8c516001600160601b03811681146158bf578a8bfd5b9b506158cd60208e016155e3565b9a506158db60408e016155e3565b99506158e960608e016155e3565b98506158f760808e01615617565b975061590560a08e016155ee565b965061591360c08e016155ee565b955061592160e08e01615600565b94506101008d015193506101208d015192506159406101408e01615600565b915061594f6101608e01615600565b90509295989b509295989b509295989b565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b03979097168752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0392909216825263ffffffff16602082015260400190565b6001600160a01b0394909416845263ffffffff9290921660208401526001600160601b031660408301526001600160801b0316606082015260800190565b901515815260200190565b6001600160e01b031991909116815260200190565b600f9190910b815260200190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b602080825260029082015261043360f41b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b602080825260029082015261433360f01b604082015260600190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b6001600160801b0391909116815260200190565b6001600160801b039485168152602081019390935292166040820152606081019190915260800190565b62ffffff91909116815260200190565b90815260200190565b918252602082015260400190565b63ffffffff91909116815260200190565b63ffffffff929092168252602082015260400190565b6001600160a01b0381168114610d1f57600080fd5b63ffffffff81168114610d1f57600080fdfe5265656e7472616e637947756172643a207265656e7472616e742063616c6c004f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212201ca81e10125d74fc4d8a6f7c39e0648cc26a50a8c5deec6ca4fb49cb3041e74964736f6c63430007060033\",\n  \"libraries\": {\n    \"ABDKMath64x64\": \"0xc3eEC23787Ea5F9310332B7970C3570B6dc933a4\",\n    \"SqrtPriceMathPartial\": \"0x786a197a14C5dBD1B10acb3a997F6d0E81b447ea\",\n    \"TickMathExternal\": \"0xAca2c805A88f80D7857773E4b80dE580Dc7ef4Ea\"\n  },\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"burnPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_powerPerpAmount\": \"amount of powerPerp to burn\",\n          \"_vaultId\": \"id of the vault\",\n          \"_withdrawAmount\": \"amount of eth to withdraw\"\n        },\n        \"returns\": {\n          \"_0\": \"amount of wPowerPerp burned\"\n        }\n      },\n      \"burnWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_vaultId\": \"id of the vault\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to burn\",\n          \"_withdrawAmount\": \"amount of eth to withdraw\"\n        }\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_ethQuoteCurrencyPool\": \"uniswap v3 pool for weth / quoteCurrency\",\n          \"_oracle\": \"oracle address\",\n          \"_quoteCurrency\": \"quoteCurrency address\",\n          \"_shortPowerPerp\": \"ERC721 token address representing the short position\",\n          \"_uniPositionManager\": \"uniswap v3 position manager address\",\n          \"_wPowerPerp\": \"ERC20 token address representing the long position\",\n          \"_wPowerPerpPool\": \"uniswap v3 pool for wPowerPerp / weth\",\n          \"_weth\": \"weth address\"\n        }\n      },\n      \"deposit(uint256)\": {\n        \"details\": \"deposit collateral into a vault\",\n        \"params\": {\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"depositUniPositionToken(uint256,uint256)\": {\n        \"params\": {\n          \"_uniTokenId\": \"uniswap position token id\",\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"getDenormalizedMark(uint32)\": {\n        \"params\": {\n          \"_period\": \"period of time for the twap in seconds\"\n        },\n        \"returns\": {\n          \"_0\": \"mark price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"getDenormalizedMarkForFunding(uint32)\": {\n        \"details\": \"this is the mark that would be used to calculate a new normalization factor if funding was calculated now\",\n        \"params\": {\n          \"_period\": \"period which you want to calculate twap with\"\n        },\n        \"returns\": {\n          \"_0\": \"mark price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"getExpectedNormalizationFactor()\": {\n        \"details\": \"can be used for on-chain and off-chain calculations\"\n      },\n      \"getIndex(uint32)\": {\n        \"details\": \"the index price is scaled down by INDEX_SCALE in the associated PowerXBase librarythis is the index price used when calculating funding and for collateralization\",\n        \"params\": {\n          \"_period\": \"period which you want to calculate twap with\"\n        },\n        \"returns\": {\n          \"_0\": \"index price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"getUnscaledIndex(uint32)\": {\n        \"details\": \"this is the mark that would be be used for future funding after a new normalization factor is applied\",\n        \"params\": {\n          \"_period\": \"period which you want to calculate twap with\"\n        },\n        \"returns\": {\n          \"_0\": \"index price denominated in $USD, scaled by 1e18\"\n        }\n      },\n      \"isVaultSafe(uint256)\": {\n        \"details\": \"return if the vault is properly collateralized\",\n        \"params\": {\n          \"_vaultId\": \"id of the vault\"\n        },\n        \"returns\": {\n          \"_0\": \"true if the vault is properly collateralized\"\n        }\n      },\n      \"liquidate(uint256,uint256)\": {\n        \"details\": \"liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateralnormally can only liquidate 50% of a vault's debtif a vault is under dust limit after a liquidation can fully liquidatewill attempt to reduceDebt first, and can earn a bounty if sucessful\",\n        \"params\": {\n          \"_maxDebtAmount\": \"max amount of wPowerPerpetual to repay\",\n          \"_vaultId\": \"vault to liquidate\"\n        },\n        \"returns\": {\n          \"_0\": \"amount of wPowerPerp repaid\"\n        }\n      },\n      \"mintPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_powerPerpAmount\": \"amount of powerPerp to mint\",\n          \"_uniTokenId\": \"uniswap v3 position token id (additional collateral)\",\n          \"_vaultId\": \"vault to mint wPowerPerp in\"\n        },\n        \"returns\": {\n          \"_0\": \"vaultId\",\n          \"_1\": \"amount of wPowerPerp minted\"\n        }\n      },\n      \"mintWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_uniTokenId\": \"uniswap v3 position token id (additional collateral)\",\n          \"_vaultId\": \"vault to mint wPowerPerp in\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to mint\"\n        },\n        \"returns\": {\n          \"_0\": \"vaultId\"\n        }\n      },\n      \"onERC721Received(address,address,uint256,bytes)\": {\n        \"details\": \"accept erc721 from safeTransferFrom and safeMint after callback\",\n        \"returns\": {\n          \"_0\": \"returns received selector\"\n        }\n      },\n      \"owner()\": {\n        \"details\": \"Returns the address of the current owner.\"\n      },\n      \"pause()\": {\n        \"details\": \"can only be called for 365 days since the contract was launched or 4 times\"\n      },\n      \"redeemLong(uint256)\": {\n        \"params\": {\n          \"_wPerpAmount\": \"amount of wPowerPerp to burn\"\n        }\n      },\n      \"redeemShort(uint256)\": {\n        \"details\": \"short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\",\n        \"params\": {\n          \"_vaultId\": \"vault id\"\n        }\n      },\n      \"reduceDebt(uint256)\": {\n        \"details\": \"the caller won't get any bounty. this is expected to be used by vault owner\",\n        \"params\": {\n          \"_vaultId\": \"target vault\"\n        }\n      },\n      \"reduceDebtShutdown(uint256)\": {\n        \"details\": \"the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\",\n        \"params\": {\n          \"_vaultId\": \"vault containing uniswap v3 position to liquidate\"\n        }\n      },\n      \"renounceOwnership()\": {\n        \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n      },\n      \"setFeeRate(uint256)\": {\n        \"details\": \"this function cannot be called if the feeRecipient is still un-set\",\n        \"params\": {\n          \"_newFeeRate\": \"new fee rate in basis points. can't be higher than 1%\"\n        }\n      },\n      \"setFeeRecipient(address)\": {\n        \"details\": \"this should be a contract handling insurance\",\n        \"params\": {\n          \"_newFeeRecipient\": \"new fee recipient\"\n        }\n      },\n      \"shutDown()\": {\n        \"details\": \"this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\"\n      },\n      \"transferOwnership(address)\": {\n        \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n      },\n      \"unPauseAnyone()\": {\n        \"details\": \"anyone can unpause the contract after 24 hours\"\n      },\n      \"unPauseOwner()\": {\n        \"details\": \"owner can unpause at any time\"\n      },\n      \"updateOperator(uint256,address)\": {\n        \"details\": \"can be revoke by setting address to 0\",\n        \"params\": {\n          \"_operator\": \"new operator address\",\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"withdraw(uint256,uint256)\": {\n        \"params\": {\n          \"_amount\": \"amount of eth to withdraw\",\n          \"_vaultId\": \"id of the vault\"\n        }\n      },\n      \"withdrawUniPositionToken(uint256)\": {\n        \"params\": {\n          \"_vaultId\": \"id of the vault\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"ONE\": {\n        \"details\": \"basic unit used for calculation\"\n      },\n      \"PAUSE_TIME_LIMIT\": {\n        \"details\": \"system can only be paused for 182 days from deployment\"\n      },\n      \"feeRate\": {\n        \"details\": \"fee rate in basis point. feeRate of 1 = 0.01%\"\n      },\n      \"indexForSettlement\": {\n        \"details\": \"the settlement price for each wPowerPerp for settlement\"\n      },\n      \"vaults\": {\n        \"details\": \"vault data storage\"\n      },\n      \"wPowerPerpPool\": {\n        \"details\": \"address of the powerPerp/weth pool\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"events\": {\n      \"OpenVault(address,uint256)\": {\n        \"notice\": \"Events\"\n      }\n    },\n    \"kind\": \"user\",\n    \"methods\": {\n      \"applyFunding()\": {\n        \"notice\": \"update the normalization factor as a way to pay funding\"\n      },\n      \"burnPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"burn powerPerp and remove collateral from a vault\"\n      },\n      \"burnWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"burn wPowerPerp and remove collateral from a vault\"\n      },\n      \"constructor\": {\n        \"notice\": \"constructor\"\n      },\n      \"depositUniPositionToken(uint256,uint256)\": {\n        \"notice\": \"deposit uniswap position token into a vault to increase collateral ratio\"\n      },\n      \"donate()\": {\n        \"notice\": \"add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\"\n      },\n      \"getDenormalizedMark(uint32)\": {\n        \"notice\": \"get the expected mark price of powerPerp after funding has been applied\"\n      },\n      \"getDenormalizedMarkForFunding(uint32)\": {\n        \"notice\": \"get the mark price of powerPerp before funding has been applied\"\n      },\n      \"getExpectedNormalizationFactor()\": {\n        \"notice\": \"returns the expected normalization factor, if the funding is paid right now\"\n      },\n      \"getIndex(uint32)\": {\n        \"notice\": \"get the index price of the powerPerp, scaled down\"\n      },\n      \"getUnscaledIndex(uint32)\": {\n        \"notice\": \"the unscaled index of the power perp in USD, scaled by 18 decimals\"\n      },\n      \"liquidate(uint256,uint256)\": {\n        \"notice\": \"if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\"\n      },\n      \"mintPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\"\n      },\n      \"mintWPowerPerpAmount(uint256,uint256,uint256)\": {\n        \"notice\": \"deposit collateral and mint wPowerPerp\"\n      },\n      \"pause()\": {\n        \"notice\": \"pause the system for up to 24 hours after which any one can unpause\"\n      },\n      \"redeemLong(uint256)\": {\n        \"notice\": \"redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\"\n      },\n      \"redeemShort(uint256)\": {\n        \"notice\": \"redeem short position when the system is shutdown\"\n      },\n      \"reduceDebt(uint256)\": {\n        \"notice\": \"withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\"\n      },\n      \"reduceDebtShutdown(uint256)\": {\n        \"notice\": \"after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by forceif a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\"\n      },\n      \"setFeeRate(uint256)\": {\n        \"notice\": \"set the fee rate when user mints\"\n      },\n      \"setFeeRecipient(address)\": {\n        \"notice\": \"set the recipient who will receive the fee\"\n      },\n      \"shutDown()\": {\n        \"notice\": \"shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactorshort positions can be redeemed for vault collateral minus value of debtpause (if not paused) and then immediately shutdown the system, can be called when paused already\"\n      },\n      \"unPauseAnyone()\": {\n        \"notice\": \"unpause the contract\"\n      },\n      \"unPauseOwner()\": {\n        \"notice\": \"unpause the contract\"\n      },\n      \"updateOperator(uint256,address)\": {\n        \"notice\": \"authorize an address to modify the vault\"\n      },\n      \"withdraw(uint256,uint256)\": {\n        \"notice\": \"withdraw collateral from a vault\"\n      },\n      \"withdrawUniPositionToken(uint256)\": {\n        \"notice\": \"withdraw uniswap v3 position token from a vault\"\n      }\n    },\n    \"notice\": \"Error C0: Paused C1: Not paused C2: Shutdown C3: Not shutdown C4: Invalid oracle address C5: Invalid shortPowerPerp address C6: Invalid wPowerPerp address C7: Invalid weth address C8: Invalid quote currency address C9: Invalid eth:quoteCurrency pool address C10: Invalid wPowerPerp:eth pool address C11: Invalid Uniswap position manager C12: Can not liquidate safe vault C13: Invalid address C14: Set fee recipient first C15: Fee too high C16: Paused too many times C17: Pause time limit exceeded C18: Not enough paused time has passed C19: Cannot receive eth C20: Not allowed C21: Need full liquidation C22: Dust vault left C23: Invalid nft C24: Invalid state C25: 0 liquidity Uniswap position token C26: Wrong fee tier for NFT deposit\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 7,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"_owner\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 3698,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7240,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"feeRecipient\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 7245,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"feeRate\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7248,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"indexForSettlement\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7251,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"pausesLeft\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7253,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"lastPauseTime\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7255,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"normalizationFactor\",\n        \"offset\": 0,\n        \"slot\": \"7\",\n        \"type\": \"t_uint128\"\n      },\n      {\n        \"astId\": 7257,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"lastFundingUpdateTimestamp\",\n        \"offset\": 16,\n        \"slot\": \"7\",\n        \"type\": \"t_uint128\"\n      },\n      {\n        \"astId\": 7261,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"isShutDown\",\n        \"offset\": 0,\n        \"slot\": \"8\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 7263,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"isSystemPaused\",\n        \"offset\": 1,\n        \"slot\": \"8\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 7268,\n        \"contract\": \"contracts/core/Controller.sol:Controller\",\n        \"label\": \"vaults\",\n        \"offset\": 0,\n        \"slot\": \"9\",\n        \"type\": \"t_mapping(t_uint256,t_struct(Vault)13791_storage)\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_mapping(t_uint256,t_struct(Vault)13791_storage)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => struct VaultLib.Vault)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_struct(Vault)13791_storage\"\n      },\n      \"t_struct(Vault)13791_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct VaultLib.Vault\",\n        \"members\": [\n          {\n            \"astId\": 13784,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"operator\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_address\"\n          },\n          {\n            \"astId\": 13786,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"NftCollateralId\",\n            \"offset\": 20,\n            \"slot\": \"0\",\n            \"type\": \"t_uint32\"\n          },\n          {\n            \"astId\": 13788,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"collateralAmount\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_uint96\"\n          },\n          {\n            \"astId\": 13790,\n            \"contract\": \"contracts/core/Controller.sol:Controller\",\n            \"label\": \"shortAmount\",\n            \"offset\": 12,\n            \"slot\": \"1\",\n            \"type\": \"t_uint128\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_uint128\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint128\",\n        \"numberOfBytes\": \"16\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint32\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint32\",\n        \"numberOfBytes\": \"4\"\n      },\n      \"t_uint96\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint96\",\n        \"numberOfBytes\": \"12\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/ControllerHelper.json",
    "content": "{\n  \"address\": \"0x7e9C5490e91F93529c6480B46a59D738F6bcEa43\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controller\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_nonfungiblePositionManager\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniswapFactory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_exec\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_euler\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_dToken\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"burnExactRemoved\",\n              \"type\": \"bool\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.CloseShortWithUserNftParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"closeShortWithUserNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"dToken\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"euler\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"exec\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToFlashloan\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"burnExactRemoved\",\n              \"type\": \"bool\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashloanCloseVaultLpNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmount\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToFlashloan\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToLp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashloanWMintLpDepositNft\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToMint\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToSell\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"minToReceive\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashSellLongWMintParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashswapSellLongWMint\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBurn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountToBuy\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToWithdraw\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"maxToPay\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.FlashswapWBurnBuyLongParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"flashswapWBurnBuyLong\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"encodedData\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onDeferredLiquidityCheck\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onERC721Received\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_collateralToFlashloan\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"enum ControllerHelperDataType.RebalanceVaultNftType\",\n              \"name\": \"rebalanceLpInVaultType\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"bytes\",\n              \"name\": \"data\",\n              \"type\": \"bytes\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.RebalanceLpInVaultParams[]\",\n          \"name\": \"_params\",\n          \"type\": \"tuple[]\"\n        }\n      ],\n      \"name\": \"rebalanceLpInVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmountDesired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wethAmountDesired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0DesiredMin\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1DesiredMin\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.RebalanceLpWithoutVaultParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"rebalanceLpWithoutVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"liquidityPercentage\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"limitPriceEthPerPowerPerp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"poolFee\",\n              \"type\": \"uint24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.ReduceLiquidityAndSellParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"reduceLiquidityAndSell\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"token\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"wPowerPerpPool\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"vaultId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"wPowerPerpAmount\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToDeposit\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"collateralToLp\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"lowerTick\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"upperTick\",\n              \"type\": \"int24\"\n            }\n          ],\n          \"internalType\": \"struct ControllerHelperDataType.MintAndLpParams\",\n          \"name\": \"_params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"wMintLp\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0xb334d66cf5c548b4fb2f9474d6a698114c8bfacb173b31a6436fccebcd427481\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0x7e9C5490e91F93529c6480B46a59D738F6bcEa43\",\n    \"transactionIndex\": 1,\n    \"gasUsed\": \"5438748\",\n    \"logsBloom\": \"0x00040000000000000000000000020000000404004000000000000000000000000800000000000000000000000020000000000000000000000000000000200000040000000000000000000800002000000000000000000000000000000000000002000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000020000000000000000000000000000208010200820000000000000000000000000002000000000000000000020000000\",\n    \"blockHash\": \"0x318a18c5183eee828e55917726fac62680fa3cb2a3c61abd3248e6ed25badc2e\",\n    \"transactionHash\": \"0xb334d66cf5c548b4fb2f9474d6a698114c8bfacb173b31a6436fccebcd427481\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 1,\n        \"blockNumber\": 12347841,\n        \"transactionHash\": \"0xb334d66cf5c548b4fb2f9474d6a698114c8bfacb173b31a6436fccebcd427481\",\n        \"address\": \"0xa4222f78d23593e82Aa74742d25D06720DCa4ab7\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x0000000000000000000000007e9c5490e91f93529c6480b46a59d738f6bcea43\",\n          \"0x0000000000000000000000008c7c1f786da4dee7d4bb49697a9b0c0c8fb328e0\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 0,\n        \"blockHash\": \"0x318a18c5183eee828e55917726fac62680fa3cb2a3c61abd3248e6ed25badc2e\"\n      },\n      {\n        \"transactionIndex\": 1,\n        \"blockNumber\": 12347841,\n        \"transactionHash\": \"0xb334d66cf5c548b4fb2f9474d6a698114c8bfacb173b31a6436fccebcd427481\",\n        \"address\": \"0xc778417E063141139Fce010982780140Aa0cD5Ab\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x0000000000000000000000007e9c5490e91f93529c6480b46a59d738f6bcea43\",\n          \"0x0000000000000000000000008c7c1f786da4dee7d4bb49697a9b0c0c8fb328e0\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 1,\n        \"blockHash\": \"0x318a18c5183eee828e55917726fac62680fa3cb2a3c61abd3248e6ed25badc2e\"\n      },\n      {\n        \"transactionIndex\": 1,\n        \"blockNumber\": 12347841,\n        \"transactionHash\": \"0xb334d66cf5c548b4fb2f9474d6a698114c8bfacb173b31a6436fccebcd427481\",\n        \"address\": \"0x8c7C1F786dA4DEe7d4bB49697A9B0C0c8Fb328e0\",\n        \"topics\": [\n          \"0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31\",\n          \"0x0000000000000000000000007e9c5490e91f93529c6480b46a59d738f6bcea43\",\n          \"0x00000000000000000000000059f0c781a6ec387f09c40faa22b7477a2950d209\"\n        ],\n        \"data\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n        \"logIndex\": 2,\n        \"blockHash\": \"0x318a18c5183eee828e55917726fac62680fa3cb2a3c61abd3248e6ed25badc2e\"\n      }\n    ],\n    \"blockNumber\": 12347841,\n    \"cumulativeGasUsed\": \"5459748\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n    \"0x8c7C1F786dA4DEe7d4bB49697A9B0C0c8Fb328e0\",\n    \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n    \"0xF7B8611008Ed073Ef348FE130671688BBb20409d\",\n    \"0xfC3DD73e918b931be7DEfd0cc616508391bcc001\",\n    \"0x682b4c36a6D4749Ced8C3abF47AefDFC57A17754\"\n  ],\n  \"solcInputHash\": \"fc32ed9e00a9017e491333926bef5473\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controller\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_nonfungiblePositionManager\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniswapFactory\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_exec\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_euler\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_dToken\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidityPercentage\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBurn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"burnExactRemoved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.CloseShortWithUserNftParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"closeShortWithUserNft\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"dToken\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"euler\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"exec\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"factory\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidityPercentage\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBurn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToFlashloan\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"burnExactRemoved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashloanCloseVaultLpNftParam\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashloanCloseVaultLpNft\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToFlashloan\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToLp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"upperTick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashloanWMintLpDepositNftParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashloanWMintLpDepositNft\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToMint\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToSell\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minToReceive\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashSellLongWMintParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashswapSellLongWMint\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBurn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountToBuy\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"maxToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.FlashswapWBurnBuyLongParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"flashswapWBurnBuyLong\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"encodedData\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onDeferredLiquidityCheck\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onERC721Received\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_collateralToFlashloan\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"enum ControllerHelperDataType.RebalanceVaultNftType\\\",\\\"name\\\":\\\"rebalanceLpInVaultType\\\",\\\"type\\\":\\\"uint8\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.RebalanceLpInVaultParams[]\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple[]\\\"}],\\\"name\\\":\\\"rebalanceLpInVault\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmountDesired\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wethAmountDesired\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0DesiredMin\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1DesiredMin\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"upperTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.RebalanceLpWithoutVaultParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"rebalanceLpWithoutVault\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"liquidityPercentage\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"limitPriceEthPerPowerPerp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.ReduceLiquidityAndSellParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"reduceLiquidityAndSell\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"token\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount0Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount1Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"uniswapV3SwapCallback\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"collateralToLp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1Min\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"upperTick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"internalType\\\":\\\"struct ControllerHelperDataType.MintAndLpParams\\\",\\\"name\\\":\\\"_params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"wMintLp\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\\\":{\\\"details\\\":\\\"user should approve this contract for Uni NFT transfer\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.CloseShortWithUserNftParams struct\\\"}},\\\"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"details\\\":\\\"sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\\"}},\\\"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"details\\\":\\\"flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.FlashSellLongWMintParams struct\\\"}},\\\"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"details\\\":\\\"this function\\\",\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\\"}},\\\"onERC721Received(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"accept erc721 from safeTransferFrom and safeMint after callback\\\",\\\"returns\\\":{\\\"_0\\\":\\\"returns received selector\\\"}},\\\"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\\\":{\\\"params\\\":{\\\"_collateralToFlashloan\\\":\\\"collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\\",\\\"_params\\\":\\\"array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\\",\\\"_vaultId\\\":\\\"vault ID\\\"}},\\\"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\\\":{\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\\"}},\\\"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\\\":{\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\\"}},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"params\\\":{\\\"_data\\\":\\\"callback data encoded as SwapCallbackData struct\\\",\\\"amount0Delta\\\":\\\"amount of token0\\\",\\\"amount1Delta\\\":\\\"amount of token1\\\"}},\\\"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"params\\\":{\\\"_params\\\":\\\"ControllerHelperDataType.MintAndLpParams struct\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\\\":{\\\"notice\\\":\\\"close short position with user Uniswap v3 LP NFT\\\"},\\\"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"notice\\\":\\\"FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\\"},\\\"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"notice\\\":\\\"sell long wPowerPerp and flashswap mint short position\\\"},\\\"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\\\":{\\\"notice\\\":\\\"flash close position and buy long squeeth\\\"},\\\"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\\\":{\\\"notice\\\":\\\"Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\\"},\\\"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\\\":{\\\"notice\\\":\\\"Rebalance LP nft through trading\\\"},\\\"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\\\":{\\\"notice\\\":\\\"sell all LP wPowerPerp amounts to WETH and send back to user\\\"},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"notice\\\":\\\"uniswap swap callback function for flashswap\\\"},\\\"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\\\":{\\\"notice\\\":\\\"mint WPowerPerp and LP into Uniswap v3 pool\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/periphery/ControllerHelper.sol\\\":\\\"ControllerHelper\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#flash\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\\\ninterface IUniswapV3FlashCallback {\\\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\\\n    function uniswapV3FlashCallback(\\\\n        uint256 fee0,\\\\n        uint256 fee1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x151ba1777392771025f0fca946c95fbc16ec4b5eff05e1f236115b99bd574de2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Safe casting methods\\\\n/// @notice Contains methods for safely casting between types\\\\nlibrary SafeCast {\\\\n    /// @notice Cast a uint256 to a uint160, revert on overflow\\\\n    /// @param y The uint256 to be downcasted\\\\n    /// @return z The downcasted integer, now type uint160\\\\n    function toUint160(uint256 y) internal pure returns (uint160 z) {\\\\n        require((z = uint160(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a int256 to a int128, revert on overflow or underflow\\\\n    /// @param y The int256 to be downcasted\\\\n    /// @return z The downcasted integer, now type int128\\\\n    function toInt128(int256 y) internal pure returns (int128 z) {\\\\n        require((z = int128(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a uint256 to a int256, revert on overflow\\\\n    /// @param y The uint256 to be casted\\\\n    /// @return z The casted integer, now type int256\\\\n    function toInt256(uint256 y) internal pure returns (int256 z) {\\\\n        require(y < 2**255);\\\\n        z = int256(y);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n/*\\\\n * @title Solidity Bytes Arrays Utils\\\\n * @author Gon\\\\u00e7alo S\\\\u00e1 <goncalo.sa@consensys.net>\\\\n *\\\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\\\n */\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nlibrary BytesLib {\\\\n    function slice(\\\\n        bytes memory _bytes,\\\\n        uint256 _start,\\\\n        uint256 _length\\\\n    ) internal pure returns (bytes memory) {\\\\n        require(_length + 31 >= _length, 'slice_overflow');\\\\n        require(_start + _length >= _start, 'slice_overflow');\\\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\\\n\\\\n        bytes memory tempBytes;\\\\n\\\\n        assembly {\\\\n            switch iszero(_length)\\\\n                case 0 {\\\\n                    // Get a location of some free memory and store it in tempBytes as\\\\n                    // Solidity does for memory variables.\\\\n                    tempBytes := mload(0x40)\\\\n\\\\n                    // The first word of the slice result is potentially a partial\\\\n                    // word read from the original array. To read it, we calculate\\\\n                    // the length of that partial word and start copying that many\\\\n                    // bytes into the array. The first word we copy will start with\\\\n                    // data we don't care about, but the last `lengthmod` bytes will\\\\n                    // land at the beginning of the contents of the new array. When\\\\n                    // we're done copying, we overwrite the full first word with\\\\n                    // the actual length of the slice.\\\\n                    let lengthmod := and(_length, 31)\\\\n\\\\n                    // The multiplication in the next line is necessary\\\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\\\n                    // the following copy loop was copying the origin's length\\\\n                    // and then ending prematurely not copying everything it should.\\\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\\\n                    let end := add(mc, _length)\\\\n\\\\n                    for {\\\\n                        // The multiplication in the next line has the same exact purpose\\\\n                        // as the one above.\\\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\\\n                    } lt(mc, end) {\\\\n                        mc := add(mc, 0x20)\\\\n                        cc := add(cc, 0x20)\\\\n                    } {\\\\n                        mstore(mc, mload(cc))\\\\n                    }\\\\n\\\\n                    mstore(tempBytes, _length)\\\\n\\\\n                    //update free-memory pointer\\\\n                    //allocating the array padded to 32 bytes like the compiler does now\\\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\\\n                }\\\\n                //if we want a zero-length slice let's just return a zero-length array\\\\n                default {\\\\n                    tempBytes := mload(0x40)\\\\n                    //zero out the 32 bytes slice we are about to return\\\\n                    //we need to do it because Solidity does not garbage collect\\\\n                    mstore(tempBytes, 0)\\\\n\\\\n                    mstore(0x40, add(tempBytes, 0x20))\\\\n                }\\\\n        }\\\\n\\\\n        return tempBytes;\\\\n    }\\\\n\\\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\\\n        address tempAddress;\\\\n\\\\n        assembly {\\\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\\\n        }\\\\n\\\\n        return tempAddress;\\\\n    }\\\\n\\\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\\\n        uint24 tempUint;\\\\n\\\\n        assembly {\\\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\\\n        }\\\\n\\\\n        return tempUint;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport './PoolAddress.sol';\\\\n\\\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\\\nlibrary CallbackValidation {\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param tokenA The contract address of either token0 or token1\\\\n    /// @param tokenB The contract address of the other token\\\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(\\\\n        address factory,\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool pool) {\\\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param poolKey The identifying key of the V3 pool\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\\\n        internal\\\\n        view\\\\n        returns (IUniswapV3Pool pool)\\\\n    {\\\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\\\n        require(msg.sender == address(pool));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.6.0;\\\\n\\\\nimport './BytesLib.sol';\\\\n\\\\n/// @title Functions for manipulating path data for multihop swaps\\\\nlibrary Path {\\\\n    using BytesLib for bytes;\\\\n\\\\n    /// @dev The length of the bytes encoded address\\\\n    uint256 private constant ADDR_SIZE = 20;\\\\n    /// @dev The length of the bytes encoded fee\\\\n    uint256 private constant FEE_SIZE = 3;\\\\n\\\\n    /// @dev The offset of a single token address and pool fee\\\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\\\n    /// @dev The offset of an encoded pool key\\\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\\\n\\\\n    /// @notice Returns true iff the path contains two or more pools\\\\n    /// @param path The encoded swap path\\\\n    /// @return True if path contains two or more pools, otherwise false\\\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\\\n    }\\\\n\\\\n    /// @notice Returns the number of pools in the path\\\\n    /// @param path The encoded swap path\\\\n    /// @return The number of pools in the path\\\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Decodes the first pool in path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return tokenA The first token of the given pool\\\\n    /// @return tokenB The second token of the given pool\\\\n    /// @return fee The fee level of the pool\\\\n    function decodeFirstPool(bytes memory path)\\\\n        internal\\\\n        pure\\\\n        returns (\\\\n            address tokenA,\\\\n            address tokenB,\\\\n            uint24 fee\\\\n        )\\\\n    {\\\\n        tokenA = path.toAddress(0);\\\\n        fee = path.toUint24(ADDR_SIZE);\\\\n        tokenB = path.toAddress(NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Gets the segment corresponding to the first pool in the path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return The segment containing all data necessary to target the first pool in the path\\\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(0, POP_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\\\n    /// @param path The swap path\\\\n    /// @return The remaining token + fee elements in the path\\\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IERC20Detailed.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// uniswap Library only works under 0.7.6\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IERC20Detailed is IERC20 {\\\\n    function decimals() external view returns (uint8);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcd59a0158d0711810c499904b9d37a71fdb34d1c4403f3cb67ca47de5e88bf7b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/ControllerHelper.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IERC721Receiver} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\\\\\";\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {UniswapControllerHelper} from \\\\\\\"./UniswapControllerHelper.sol\\\\\\\";\\\\nimport {EulerControllerHelper} from \\\\\\\"./EulerControllerHelper.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ControllerHelperDataType} from \\\\\\\"./lib/ControllerHelperDataType.sol\\\\\\\";\\\\nimport {ControllerHelperUtil} from \\\\\\\"./lib/ControllerHelperUtil.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    bool private immutable isWethToken0;\\\\n    address private immutable controller;\\\\n    address private immutable shortPowerPerp;\\\\n    address private immutable wPowerPerp;\\\\n    address private immutable weth;\\\\n    address private immutable nonfungiblePositionManager;\\\\n\\\\n    constructor(\\\\n        address _controller,\\\\n        address _nonfungiblePositionManager,\\\\n        address _uniswapFactory,\\\\n        address _exec,\\\\n        address _euler,\\\\n        address _dToken\\\\n    )\\\\n        UniswapControllerHelper(_uniswapFactory)\\\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\\\n    {\\\\n        controller = _controller;\\\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\\\n        wPowerPerp = IController(_controller).wPowerPerp();\\\\n        weth = IController(_controller).weth();\\\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\\\n\\\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\\\n\\\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\\\n\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\\\n     * @return returns received selector\\\\n     */\\\\n    function onERC721Received(\\\\n        address,\\\\n        address,\\\\n        uint256,\\\\n        bytes memory\\\\n    ) public virtual override returns (bytes4) {\\\\n        return this.onERC721Received.selector;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {}\\\\n\\\\n    /**\\\\n     * @notice flash close position and buy long squeeth\\\\n     * @dev this function\\\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\\\n     */\\\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        _checkAccess(_params.vaultId);\\\\n\\\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\\\n\\\\n        wrapInternal(msg.value);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            _params.poolFee,\\\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\\\n            _params.maxToPay,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\\\n            abi.encode(_params)\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sell long wPowerPerp and flashswap mint short position\\\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\\\n     */\\\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        if (_params.vaultId != 0) {\\\\n            _checkAccess(_params.vaultId);\\\\n        }\\\\n\\\\n        wrapInternal(msg.value);\\\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\\\n        // flashswap and mint short position\\\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            _params.poolFee,\\\\n            totalAmountIn,\\\\n            _params.minToReceive,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\\\n            abi.encode(_params)\\\\n        );\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice close short position with user Uniswap v3 LP NFT\\\\n     * @dev user should approve this contract for Uni NFT transfer\\\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\\\n     */\\\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        _checkAccess(_params.vaultId);\\\\n\\\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\\\n            msg.sender,\\\\n            address(this),\\\\n            _params.tokenId\\\\n        );\\\\n\\\\n        wrapInternal(msg.value);\\\\n\\\\n        // close LP position\\\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n            nonfungiblePositionManager,\\\\n            ControllerHelperDataType.CloseUniLpParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: _params.liquidity,\\\\n                liquidityPercentage: _params.liquidityPercentage,\\\\n                amount0Min: _params.amount0Min,\\\\n                amount1Min: _params.amount1Min\\\\n            }),\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\\\n        ControllerHelperUtil.checkClosedLp(\\\\n            msg.sender,\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            0,\\\\n            _params.tokenId,\\\\n            _params.liquidityPercentage\\\\n        );\\\\n        // burn vault debt using amounts withdrawn from LP position\\\\n        _closeShortWithAmountsFromLp(\\\\n            _params.vaultId,\\\\n            wPowerPerpAmountInLp,\\\\n            _params.wPowerPerpAmountToBurn,\\\\n            _params.collateralToWithdraw,\\\\n            _params.limitPriceEthPerPowerPerp,\\\\n            _params.poolFee,\\\\n            _params.burnExactRemoved\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        _checkAccess(_params.vaultId);\\\\n\\\\n        wrapInternal(msg.value);\\\\n        _flashLoan(\\\\n            weth,\\\\n            _params.collateralToFlashloan,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\\\n            abi.encode(_params)\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\\\n     */\\\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\\\n        if (_params.vaultId != 0) {\\\\n            _checkAccess(_params.vaultId);\\\\n        }\\\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\\\n\\\\n        wrapInternal(msg.value);\\\\n\\\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            _params,\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        // if openeded new vault, transfer vault NFT to user\\\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\\\n     */\\\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        if (_params.vaultId != 0) {\\\\n            _checkAccess(_params.vaultId);\\\\n        }\\\\n\\\\n        wrapInternal(msg.value);\\\\n        _flashLoan(\\\\n            weth,\\\\n            _params.collateralToFlashloan,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\\\n            abi.encode(_params)\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\\\n     */\\\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\\\n            msg.sender,\\\\n            address(this),\\\\n            _params.tokenId\\\\n        );\\\\n\\\\n        // close LP NFT and get Weth and WPowerPerp amounts\\\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n            nonfungiblePositionManager,\\\\n            ControllerHelperDataType.CloseUniLpParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: _params.liquidity,\\\\n                liquidityPercentage: _params.liquidityPercentage,\\\\n                amount0Min: uint128(_params.amount0Min),\\\\n                amount1Min: uint128(_params.amount1Min)\\\\n            }),\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        ControllerHelperUtil.checkClosedLp(\\\\n            msg.sender,\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            0,\\\\n            _params.tokenId,\\\\n            _params.liquidityPercentage\\\\n        );\\\\n\\\\n        if (wPowerPerpAmountInLp > 0) {\\\\n            _exactInFlashSwap(\\\\n                wPowerPerp,\\\\n                weth,\\\\n                _params.poolFee,\\\\n                wPowerPerpAmountInLp,\\\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\\\n                \\\\\\\"\\\\\\\"\\\\n            );\\\\n        }\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice Rebalance LP nft through trading\\\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\\\n     */\\\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\\\n        external\\\\n        payable\\\\n    {\\\\n        wrapInternal(msg.value);\\\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\\\n            msg.sender,\\\\n            address(this),\\\\n            _params.tokenId\\\\n        );\\\\n        // close LP NFT and get Weth and WPowerPerp amounts\\\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n            nonfungiblePositionManager,\\\\n            ControllerHelperDataType.CloseUniLpParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: _params.liquidity,\\\\n                liquidityPercentage: 1e18,\\\\n                amount0Min: uint128(_params.amount0Min),\\\\n                amount1Min: uint128(_params.amount1Min)\\\\n            }),\\\\n            isWethToken0\\\\n        );\\\\n\\\\n        ControllerHelperUtil.checkClosedLp(\\\\n            msg.sender,\\\\n            controller,\\\\n            nonfungiblePositionManager,\\\\n            0,\\\\n            _params.tokenId,\\\\n            1e18\\\\n        );\\\\n\\\\n        uint256 wethAmountDesired;\\\\n        uint256 wPowerPerpAmountDesired;\\\\n\\\\n        if (isWethToken0) {\\\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\\\n                _params.wPowerPerpPool,\\\\n                _params.wethAmountDesired,\\\\n                _params.wPowerPerpAmountDesired,\\\\n                _params.lowerTick,\\\\n                _params.upperTick,\\\\n                isWethToken0\\\\n            );\\\\n        } else {\\\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\\\n                _params.wPowerPerpPool,\\\\n                _params.wethAmountDesired,\\\\n                _params.wPowerPerpAmountDesired,\\\\n                _params.lowerTick,\\\\n                _params.upperTick,\\\\n                isWethToken0\\\\n            );\\\\n        }\\\\n\\\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\\\n            _exactOutFlashSwap(\\\\n                weth,\\\\n                wPowerPerp,\\\\n                _params.poolFee,\\\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\\\n                \\\\\\\"\\\\\\\"\\\\n            );\\\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\\\n            _exactInFlashSwap(\\\\n                wPowerPerp,\\\\n                weth,\\\\n                _params.poolFee,\\\\n                wPowerPerpExcess,\\\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\\\n                \\\\\\\"\\\\\\\"\\\\n            );\\\\n        }\\\\n\\\\n        // mint new position\\\\n        ControllerHelperUtil.lpWPowerPerpPool(\\\\n            nonfungiblePositionManager,\\\\n            _params.wPowerPerpPool,\\\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\\\n                recipient: msg.sender,\\\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\\\n                amount0Min: _params.amount0DesiredMin,\\\\n                amount1Min: _params.amount1DesiredMin,\\\\n                lowerTick: _params.lowerTick,\\\\n                upperTick: _params.upperTick\\\\n            })\\\\n        );\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\\\n     * @param _vaultId vault ID\\\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\\\n     */\\\\n    function rebalanceLpInVault(\\\\n        uint256 _vaultId,\\\\n        uint256 _collateralToFlashloan,\\\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\\\n    ) external payable {\\\\n        // check ownership\\\\n        _checkAccess(_vaultId);\\\\n\\\\n        wrapInternal(msg.value);\\\\n        _flashLoan(\\\\n            weth,\\\\n            _collateralToFlashloan,\\\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\\\n            abi.encode(_vaultId, _params)\\\\n        );\\\\n\\\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\\\n\\\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice checks if the msg.sender is the owener of the vault\\\\n     * @param _vaultId vault ID\\\\n     */\\\\n    function _checkAccess(uint256 _vaultId) internal view {\\\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice gets the shortAmount that has been minted from a vault\\\\n     * @param _vaultId vault ID\\\\n     * @return short amount from vault\\\\n     */\\\\n\\\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\\\n\\\\n        return vault.shortAmount;\\\\n    }\\\\n\\\\n    function _flashCallback(\\\\n        address _initiator,\\\\n        address, /*_asset*/\\\\n        uint256 _amount,\\\\n        uint8 _callSource,\\\\n        bytes memory _calldata\\\\n    ) internal override {\\\\n        if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\\\n        ) {\\\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\\\n                _calldata,\\\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\\\n            );\\\\n\\\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\\\n                controller,\\\\n                nonfungiblePositionManager,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                ControllerHelperDataType.MintAndLpParams({\\\\n                    recipient: address(this),\\\\n                    wPowerPerpPool: data.wPowerPerpPool,\\\\n                    vaultId: data.vaultId,\\\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\\\n                    collateralToDeposit: data.collateralToDeposit,\\\\n                    collateralToLp: data.collateralToLp,\\\\n                    amount0Min: data.amount0Min,\\\\n                    amount1Min: data.amount1Min,\\\\n                    lowerTick: data.lowerTick,\\\\n                    upperTick: data.upperTick\\\\n                }),\\\\n                isWethToken0\\\\n            );\\\\n\\\\n            // deposit Uni NFT token in vault\\\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                vaultId,\\\\n                0,\\\\n                _amount.add(data.collateralToWithdraw)\\\\n            );\\\\n\\\\n            // if openeded new vault, transfer vault NFT to user\\\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\\\n        ) {\\\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\\\n                _calldata,\\\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\\\n            );\\\\n\\\\n            IWETH9(weth).withdraw(_amount);\\\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\\\n\\\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\\\n\\\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\\\n                nonfungiblePositionManager,\\\\n                ControllerHelperDataType.CloseUniLpParams({\\\\n                    tokenId: data.tokenId,\\\\n                    liquidity: data.liquidity,\\\\n                    liquidityPercentage: data.liquidityPercentage,\\\\n                    amount0Min: data.amount0Min,\\\\n                    amount1Min: data.amount1Min\\\\n                }),\\\\n                isWethToken0\\\\n            );\\\\n\\\\n            ControllerHelperUtil.checkClosedLp(\\\\n                _initiator,\\\\n                controller,\\\\n                nonfungiblePositionManager,\\\\n                data.vaultId,\\\\n                data.tokenId,\\\\n                data.liquidityPercentage\\\\n            );\\\\n\\\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\\\n            _closeShortWithAmountsFromLp(\\\\n                data.vaultId,\\\\n                wPowerPerpAmountInLp,\\\\n                data.wPowerPerpAmountToBurn,\\\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\\\n                data.limitPriceEthPerPowerPerp,\\\\n                data.poolFee,\\\\n                data.burnExactRemoved\\\\n            );\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\\\n        ) {\\\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\\\n                _calldata,\\\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\\\n            );\\\\n\\\\n            // deposit collateral into vault and withdraw LP NFT\\\\n            IWETH9(weth).withdraw(_amount);\\\\n            IController(controller).deposit{value: _amount}(vaultId);\\\\n            IController(controller).withdrawUniPositionToken(vaultId);\\\\n            for (uint256 i; i < data.length; i++) {\\\\n                if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\\\n                ) {\\\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\\\n                    );\\\\n\\\\n                    ControllerHelperUtil.increaseLpLiquidity(\\\\n                        controller,\\\\n                        nonfungiblePositionManager,\\\\n                        wPowerPerp,\\\\n                        increaseLiquidityParam.wPowerPerpPool,\\\\n                        vaultId,\\\\n                        increaseLiquidityParam,\\\\n                        isWethToken0\\\\n                    );\\\\n\\\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\\\n                ) {\\\\n                    // decrease liquidity in LP\\\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\\\n                    );\\\\n\\\\n                    ControllerHelperUtil.closeUniLp(\\\\n                        nonfungiblePositionManager,\\\\n                        ControllerHelperDataType.CloseUniLpParams({\\\\n                            tokenId: decreaseLiquidityParam.tokenId,\\\\n                            liquidity: decreaseLiquidityParam.liquidity,\\\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\\\n                        }),\\\\n                        isWethToken0\\\\n                    );\\\\n\\\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\\\n                    ControllerHelperUtil.checkClosedLp(\\\\n                        _initiator,\\\\n                        controller,\\\\n                        nonfungiblePositionManager,\\\\n                        vaultId,\\\\n                        decreaseLiquidityParam.tokenId,\\\\n                        decreaseLiquidityParam.liquidityPercentage\\\\n                    );\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\\\n                ) {\\\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\\\n                    );\\\\n\\\\n                    // make sure not to fail\\\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\\\n\\\\n                    ControllerHelperUtil.mintDepositInVault(\\\\n                        controller,\\\\n                        weth,\\\\n                        vaultId,\\\\n                        depositIntoVaultParams.wPowerPerpToMint,\\\\n                        depositIntoVaultParams.collateralToDeposit\\\\n                    );\\\\n                } else if (\\\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\\\n                ) {\\\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\\\n                    );\\\\n\\\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\\\n\\\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\\\n                            controller,\\\\n                            weth,\\\\n                            vaultId,\\\\n                            currentBalance,\\\\n                            withdrawFromVaultParams.collateralToWithdraw\\\\n                        );\\\\n                    } else {\\\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\\\n                            controller,\\\\n                            weth,\\\\n                            vaultId,\\\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\\\n                            withdrawFromVaultParams.collateralToWithdraw\\\\n                        );\\\\n                    }\\\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.MintAndLpParams)\\\\n                    );\\\\n\\\\n                    uint256 tokenId;\\\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\\\n                        controller,\\\\n                        nonfungiblePositionManager,\\\\n                        wPowerPerp,\\\\n                        weth,\\\\n                        mintAndLpParams,\\\\n                        isWethToken0\\\\n                    );\\\\n                    // deposit Uni NFT token in vault\\\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\\\n                ) {\\\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.GeneralSwapParams)\\\\n                    );\\\\n\\\\n                    require(\\\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\\\n                    );\\\\n\\\\n                    _exactInFlashSwap(\\\\n                        swapParams.tokenIn,\\\\n                        swapParams.tokenOut,\\\\n                        swapParams.poolFee,\\\\n                        swapParams.amountIn,\\\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\\\n                        \\\\\\\"\\\\\\\"\\\\n                    );\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\\\n                ) {\\\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.CollectFeesParams)\\\\n                    );\\\\n\\\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\\\n                        .CollectParams({\\\\n                            tokenId: collectFeesParams.tokenId,\\\\n                            recipient: address(this),\\\\n                            amount0Max: collectFeesParams.amount0Max,\\\\n                            amount1Max: collectFeesParams.amount0Max\\\\n                        });\\\\n\\\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\\\n                } else if (\\\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\\\n                ) {\\\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\\\n                        data[i].data,\\\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\\\n                    );\\\\n\\\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\\\n                }\\\\n            }\\\\n\\\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _swapCallback(\\\\n        address _caller,\\\\n        address _tokenIn,\\\\n        address _pool,\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\\\n        ) {\\\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\\\n                _callData,\\\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\\\n            );\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                data.vaultId,\\\\n                data.wPowerPerpAmountToBurn,\\\\n                data.collateralToWithdraw\\\\n            );\\\\n\\\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\\\n        ) {\\\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\\\n                _callData,\\\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\\\n            );\\\\n\\\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\\\n                    controller,\\\\n                    weth,\\\\n                    data.vaultId,\\\\n                    data.wPowerPerpAmountToMint,\\\\n                    data.collateralToDeposit\\\\n                );\\\\n\\\\n                // this is a newly open vault, transfer to the user\\\\n                if (data.vaultId == 0)\\\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\\\n            }\\\\n\\\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\\\n        ) {\\\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\\\n        ) {\\\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\\\n        ) {\\\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\\\n                _callData,\\\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\\\n            );\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                data.vaultId,\\\\n                data.wPowerPerpAmountToBurn,\\\\n                data.collateralToWithdraw\\\\n            );\\\\n\\\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\\\n        } else if (\\\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\\\n        ) {\\\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice wrap ETH to WETH\\\\n     * @param _amount amount to wrap\\\\n     */\\\\n    function wrapInternal(uint256 _amount) internal {\\\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\\\n    }\\\\n\\\\n    function _closeShortWithAmountsFromLp(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _wPowerPerpAmountToBurn,\\\\n        uint256 _collateralToWithdraw,\\\\n        uint256 _limitPriceEthPerPowerPerp,\\\\n        uint24 _poolFee,\\\\n        bool burnExactRemoved\\\\n    ) private {\\\\n        if (burnExactRemoved) {\\\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\\\n\\\\n            ControllerHelperUtil.burnWithdrawFromVault(\\\\n                controller,\\\\n                weth,\\\\n                _vaultId,\\\\n                _wPowerPerpAmount,\\\\n                _collateralToWithdraw\\\\n            );\\\\n        } else {\\\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\\\n                // swap needed wPowerPerp amount to close short position\\\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\\\n\\\\n                _exactOutFlashSwap(\\\\n                    weth,\\\\n                    wPowerPerp,\\\\n                    _poolFee,\\\\n                    wPowerPerpDeficit,\\\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\\\n                );\\\\n            } else {\\\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\\\n                ControllerHelperUtil.burnWithdrawFromVault(\\\\n                    controller,\\\\n                    weth,\\\\n                    _vaultId,\\\\n                    _wPowerPerpAmountToBurn,\\\\n                    _collateralToWithdraw\\\\n                );\\\\n\\\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\\\n                if (wPowerPerpExcess > 0) {\\\\n                    _exactInFlashSwap(\\\\n                        wPowerPerp,\\\\n                        weth,\\\\n                        _poolFee,\\\\n                        wPowerPerpExcess,\\\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\\\n                        \\\\\\\"\\\\\\\"\\\\n                    );\\\\n                }\\\\n            }\\\\n        }\\\\n\\\\n        // wrap ETH to WETH\\\\n        wrapInternal(address(this).balance);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe9649979188ed6661ec0511b25ef05748ae61abd4ffc1f716ca7e89b7faf333e\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/EulerControllerHelper.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: agpl-3.0\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IERC20Detailed} from \\\\\\\"../interfaces/IERC20Detailed.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\\\ninterface IDeferredLiquidityCheck {\\\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\\\n}\\\\n\\\\ninterface IExec {\\\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\\\n}\\\\n\\\\ninterface IEulerDToken {\\\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\\\n\\\\n    function repay(uint256 subAccountId, uint256 amount) external;\\\\n}\\\\n\\\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\\\n    using SafeMath for uint256;\\\\n\\\\n    address public immutable exec;\\\\n    address public immutable euler;\\\\n    address public immutable token;\\\\n    address public immutable dToken;\\\\n\\\\n    struct FlashloanCallbackData {\\\\n        address caller;\\\\n        address assetToBorrow;\\\\n        uint256 amountToBorrow;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    constructor(\\\\n        address _exec,\\\\n        address _euler,\\\\n        address _token,\\\\n        address _dToken\\\\n    ) {\\\\n        exec = _exec;\\\\n        euler = _euler;\\\\n        token = _token;\\\\n        dToken = _dToken;\\\\n    }\\\\n\\\\n    function _flashCallback(\\\\n        address _initiator,\\\\n        address _asset,\\\\n        uint256 _amount,\\\\n        uint8 _callSource,\\\\n        bytes memory _calldata\\\\n    ) internal virtual {}\\\\n\\\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\\\n        // sanity checks\\\\n        require(msg.sender == euler);\\\\n\\\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\\\n\\\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\\\n\\\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\\\n\\\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\\\n    }\\\\n\\\\n    /**\\\\n     */\\\\n    function _flashLoan(\\\\n        address _asset,\\\\n        uint256 _amount,\\\\n        uint8 _callSource,\\\\n        bytes memory _data\\\\n    ) internal {\\\\n        // Disable the liquidity check for \\\\\\\"this\\\\\\\" and call-back into onDeferredLiquidityCheck:\\\\n        IExec(exec).deferLiquidityCheck(\\\\n            address(this),\\\\n            abi.encode(\\\\n                FlashloanCallbackData({\\\\n                    caller: msg.sender,\\\\n                    assetToBorrow: _asset,\\\\n                    amountToBorrow: _amount,\\\\n                    callSource: _callSource,\\\\n                    callData: _data\\\\n                })\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6a7f3fef2c2eca5a4851e75c632eff2e7c28b4b244ad9fb0bbe2247efe1b395c\\\",\\\"license\\\":\\\"agpl-3.0\\\"},\\\"contracts/periphery/UniswapControllerHelper.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\\\\\";\\\\n\\\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\\\n    using Path for bytes;\\\\n    using SafeCast for uint256;\\\\n    using LowGasSafeMath for uint256;\\\\n    using LowGasSafeMath for int256;\\\\n\\\\n    /// @dev Uniswap factory address\\\\n    address public immutable factory;\\\\n\\\\n    struct SwapCallbackData {\\\\n        bytes path;\\\\n        address caller;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev constructor\\\\n     * @param _factory uniswap factory address\\\\n     */\\\\n    constructor(address _factory) {\\\\n        require(_factory != address(0));\\\\n        factory = _factory;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap swap callback function for flashswap\\\\n     * @param amount0Delta amount of token0\\\\n     * @param amount1Delta amount of token1\\\\n     * @param _data callback data encoded as SwapCallbackData struct\\\\n     */\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata _data\\\\n    ) external override {\\\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\\\n\\\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //ensure that callback comes from uniswap pool\\\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\\\n\\\\n        //determine the amount that needs to be repaid as part of the flashswap\\\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\\\n\\\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountIn amount to sell\\\\n     * @param _amountOutMinimum minimum amount to receive\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call\\\\n     */\\\\n    function _exactInFlashSwap(\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        uint24 _fee,\\\\n        uint256 _amountIn,\\\\n        uint256 _amountOutMinimum,\\\\n        uint8 _callSource,\\\\n        bytes memory _data\\\\n    ) internal returns (uint256) {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountOut = _exactInputInternal(\\\\n            _amountIn,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({\\\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\\\n                caller: msg.sender,\\\\n                callSource: _callSource,\\\\n                callData: _data\\\\n            })\\\\n        );\\\\n\\\\n        //slippage limit check\\\\n        require(amountOut >= _amountOutMinimum);\\\\n\\\\n        return amountOut;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountOut exact amount to receive\\\\n     * @param _amountInMaximum maximum amount to sell\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call\\\\n     */\\\\n    function _exactOutFlashSwap(\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        uint24 _fee,\\\\n        uint256 _amountOut,\\\\n        uint256 _amountInMaximum,\\\\n        uint8 _callSource,\\\\n        bytes memory _data\\\\n    ) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountIn = _exactOutputInternal(\\\\n            _amountOut,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({\\\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\\\n                caller: msg.sender,\\\\n                callSource: _callSource,\\\\n                callData: _data\\\\n            })\\\\n        );\\\\n\\\\n        //slippage limit check\\\\n        require(amountIn <= _amountInMaximum);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice function to be called by uniswap callback.\\\\n     * @dev this function should be overridden by the child contract\\\\n     * param _caller initial strategy function caller\\\\n     * param _tokenIn token address sold\\\\n     * param _tokenOut token address bought\\\\n     * param _fee pool fee\\\\n     * param _amountToPay amount to pay for the pool second token\\\\n     * param _callData arbitrary data assigned with the flashswap call\\\\n     * param _callSource function call source\\\\n     */\\\\n    function _swapCallback(\\\\n        address _caller,\\\\n        address _tokenIn,\\\\n        address _pool,\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal virtual {}\\\\n\\\\n    /**\\\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\\\n     * @param _amountIn amount of token to pay\\\\n     * @param _recipient recipient for receive\\\\n     * @param _sqrtPriceLimitX96 price limit\\\\n     * @return amount of token bought (amountOut)\\\\n     */\\\\n    function _exactInputInternal(\\\\n        uint256 _amountIn,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\\\n            _recipient,\\\\n            zeroForOne,\\\\n            _amountIn.toInt256(),\\\\n            _sqrtPriceLimitX96 == 0\\\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                : _sqrtPriceLimitX96,\\\\n            abi.encode(data)\\\\n        );\\\\n\\\\n        //determine the amountOut based on which token has a lower address\\\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\\\n     * @param _amountOut amount of token to receive\\\\n     * @param _recipient recipient for receive\\\\n     * @param _sqrtPriceLimitX96 price limit\\\\n     * @return amount of token sold (amountIn)\\\\n     */\\\\n    function _exactOutputInternal(\\\\n        uint256 _amountOut,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\\\n            _recipient,\\\\n            zeroForOne,\\\\n            -_amountOut.toInt256(),\\\\n            _sqrtPriceLimitX96 == 0\\\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                : _sqrtPriceLimitX96,\\\\n            abi.encode(data)\\\\n        );\\\\n\\\\n        //determine the amountIn and amountOut based on which token has a lower address\\\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\\\n        // it's technically possible to not receive the full output amount,\\\\n        // so if no price limit has been specified, require this possibility away\\\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\\\n\\\\n        return amountIn;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice returns the uniswap pool for the given token pair and fee\\\\n     * @dev the pool contract may or may not exist\\\\n     * @param tokenA address of first token\\\\n     * @param tokenB address of second token\\\\n     * @param fee fee tier for pool\\\\n     */\\\\n    function _getPool(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (address) {\\\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x91b5e0a2bc1ce71c0c614f89c6304c2d9ea5052120bdc88f0cf62f694afd284e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/lib/ControllerHelperDataType.sol\\\":{\\\"content\\\":\\\"pragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperDataType {\\\\n    using SafeMath for uint256;\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum CALLBACK_SOURCE {\\\\n        FLASH_W_MINT,\\\\n        FLASH_W_BURN,\\\\n        FLASH_SELL_LONG_W_MINT,\\\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\\\n        GENERAL_SWAP\\\\n    }\\\\n\\\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\\\n    enum RebalanceVaultNftType {\\\\n        IncreaseLpLiquidity,\\\\n        DecreaseLpLiquidity,\\\\n        DepositIntoVault,\\\\n        WithdrawFromVault,\\\\n        MintNewLp,\\\\n        generalSwap,\\\\n        CollectFees, \\\\n        DepositExistingNft\\\\n    }\\\\n    \\\\n    /// @dev params for flashswapWBurnBuyLong()\\\\n    struct FlashswapWBurnBuyLongParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\\\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev params for flashswapSellLongWMint()\\\\n    struct FlashSellLongWMintParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\\\n    struct SwapExactoutEthWPowerPerpData {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\\\n    }\\\\n\\\\n    /// @dev params for CloseShortWithUserNft()\\\\n    struct CloseShortWithUserNftParams {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity;  // liquidity amount in LP \\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;      // uniswap pool fee\\\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for wMintLp()\\\\n    struct MintAndLpParams {\\\\n        address recipient;  // recipient address\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 collateralToLp; // collateral amount to LP\\\\n        uint256 amount0Min; // minimum amount to LP of asset0\\\\n        uint256 amount1Min; // minimum amount to LP of asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for flashloanWMintDepositNft()\\\\n    struct FlashloanWMintLpDepositNftParams {\\\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\\\n        uint256 vaultId; // vault ID (could be zero)\\\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\\\n        uint256 amount0Min; // minimum amount of token0 to LP\\\\n        uint256 amount1Min; // minimum amount of token1 to LP\\\\n        int24 lowerTick; // range lower tick to LP in\\\\n        int24 upperTick; // range upper tick to LP in\\\\n    }\\\\n\\\\n    /// @dev params for flashloanCloseVaultLpNft()\\\\n    struct FlashloanCloseVaultLpNftParam {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity; // amount of liquidity in LP position\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for _closeUniLp() \\\\n    struct CloseUniLpParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\\\n    }\\\\n\\\\n    /// @dev params for sellAll()\\\\n    struct ReduceLiquidityAndSellParams {\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpWithoutVault()\\\\n    struct RebalanceLpWithoutVaultParams {\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\\\n        uint256 wethAmountDesired;  // WETH amount to LP\\\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\\\n    struct LpWPowerPerpPoolParams {\\\\n        address recipient;  // recipient address\\\\n        uint256 amount0Desired; // amount desired to LP for asset0\\\\n        uint256 amount1Desired; // amount desired to LP for asset1\\\\n        uint256 amount0Min; // amount min to LP for asset0\\\\n        uint256 amount1Min; // amount min to LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpInVault()\\\\n    struct RebalanceLpInVaultParams {\\\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\\\n        bytes data;\\\\n    }\\\\n\\\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\\\n    struct IncreaseLpLiquidityParams {\\\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 wethAmountToLp; // WETH amount to LP\\\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for decrease liquidity in LP position\\\\n    struct DecreaseLpLiquidityParams {  \\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for minting into vault\\\\n    struct DepositIntoVaultParams {\\\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\\\n    }\\\\n\\\\n    /// @dev struct for withdrawing from vault\\\\n    struct withdrawFromVaultParams {  \\\\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\\\n    }\\\\n\\\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\\\n    struct GeneralSwapParams {\\\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\\\n        uint256 amountIn; // amount to swap in\\\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\\\n    struct CollectFeesParams {\\\\n        uint256 tokenId;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\\\n    struct DepositExistingNftParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x04a47d47c3e0a1ec4e834f9aa466960200084fbdee47f0f513990b2c4708b02a\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/ControllerHelperUtil.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ControllerHelperDataType} from \\\\\\\"./ControllerHelperDataType.sol\\\\\\\";\\\\nimport {LiquidityAmounts} from \\\\\\\"./LiquidityAmounts.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"../../libs/TickMathExternal.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperUtil {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /**\\\\n     * @notice fully or partially close Uni v3 LP\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return withdrawn wPowerPerp and WETH amounts\\\\n     */\\\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\\\n            .DecreaseLiquidityParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\\\n                amount0Min: _params.amount0Min,\\\\n                amount1Min: _params.amount1Min,\\\\n                deadline: block.timestamp\\\\n            });\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\\\n\\\\n        uint256 wethAmount;\\\\n        uint256 _wPowerPerpAmount;\\\\n        (_isWethToken0)\\\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n                INonfungiblePositionManager.CollectParams({\\\\n                    tokenId: _params.tokenId,\\\\n                    recipient: address(this),\\\\n                    amount0Max: type(uint128).max,\\\\n                    amount1Max: type(uint128).max\\\\n                })\\\\n            )\\\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n            INonfungiblePositionManager.CollectParams({\\\\n                tokenId: _params.tokenId,\\\\n                recipient: address(this),\\\\n                amount0Max: type(uint128).max,\\\\n                amount1Max: type(uint128).max\\\\n            })\\\\n        );\\\\n\\\\n        return (_wPowerPerpAmount, wethAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\\\n     * @param _collateralToLp amount of ETH collateral to LP\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\\\n     * @param _lowerTick LP position lower tick\\\\n     * @param _upperTick LP position upper tick\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return exact amount0 and amount1 to be LPed\\\\n     */\\\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\\\n        uint256 amount0Desired; \\\\n        uint256 amount1Desired;\\\\n\\\\n        {\\\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\\\n        }\\\\n        \\\\n        return (amount0Desired, amount1Desired);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\\\n     * @param _controller wPowerPerp controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return _vaultId and tokenId\\\\n     */\\\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\\\n\\\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\\\n                \\\\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\\\n                _mintAndLpParams.vaultId,\\\\n                amountToMint,\\\\n                0\\\\n            );\\\\n        }\\\\n        // LP amount0Desired and amount1Desired in Uni v3\\\\n        uint256 uniTokenId = lpWPowerPerpPool(\\\\n            _nonfungiblePositionManager,\\\\n            _mintAndLpParams.wPowerPerpPool,\\\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\\\n                recipient: _mintAndLpParams.recipient,\\\\n                amount0Desired: amount0Desired,\\\\n                amount1Desired: amount1Desired,\\\\n                amount0Min: _mintAndLpParams.amount0Min,\\\\n                amount1Min: _mintAndLpParams.amount1Min,\\\\n                lowerTick: _mintAndLpParams.lowerTick,\\\\n                upperTick: _mintAndLpParams.upperTick\\\\n            })\\\\n        );\\\\n        return (_vaultId, uniTokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice increase liquidityin Uni v3 position\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault Id\\\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     */\\\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\\\n            (\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                int24 tickLower,\\\\n                int24 tickUpper,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                \\\\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\\\n\\\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n\\\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\\\n                    _vaultId,\\\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\\\n                    0\\\\n                );\\\\n            }\\\\n        }\\\\n\\\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\\\n            tokenId: _increaseLiquidityParam.tokenId,\\\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\\\n            deadline: block.timestamp\\\\n        });\\\\n\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp in vault\\\\n     * @param _controller controller address\\\\n     * @param _weth WETH address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\\\n     * @param _collateralToDeposit amount of collateral to deposit\\\\n     */\\\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\\\n\\\\n        uint256 vaultId = _vaultId;\\\\n        if (_wPowerPerpToMint > 0) {\\\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\\\n                _vaultId,\\\\n                _wPowerPerpToMint,\\\\n                0\\\\n            );\\\\n        } else {\\\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\\\n        }\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\\\n     * @param _controller controller address\\\\n     * @param _weth weth address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     */\\\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\\\n        IController(_controller).burnWPowerPerpAmount(\\\\n            _vaultId,\\\\n            _wPowerPerpToBurn,\\\\n            _collateralToWithdraw\\\\n        );\\\\n\\\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice LP into Uniswap V3 pool\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\\\n     */\\\\n    function lpWPowerPerpPool(\\\\n        address _nonfungiblePositionManager,\\\\n        address _wPowerPerpPool,\\\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\\\n    ) public returns (uint256) {\\\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\\\n            tickLower: int24(_params.lowerTick),\\\\n            tickUpper: int24(_params.upperTick),\\\\n            amount0Desired: _params.amount0Desired,\\\\n            amount1Desired: _params.amount1Desired,\\\\n            amount0Min: _params.amount0Min,\\\\n            amount1Min: _params.amount1Min,\\\\n            recipient: _params.recipient,\\\\n            deadline: block.timestamp\\\\n        });\\\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\\\n            mintParams\\\\n        );\\\\n        return tokenId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\\\n     * @param _user user address\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault ID\\\\n     * @param _tokenId Uni LP NFT id\\\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\\\n     */\\\\n    function checkClosedLp(\\\\n        address _user,\\\\n        address _controller,\\\\n        address _nonfungiblePositionManager,\\\\n        uint256 _vaultId,\\\\n        uint256 _tokenId,\\\\n        uint256 _liquidityPercentage\\\\n    ) public {\\\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\\\n                address(this),\\\\n                _user,\\\\n                _tokenId\\\\n            );\\\\n        } else {\\\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice send ETH and wPowerPerp\\\\n     * @param _weth WETH address\\\\n     * @param _wPowerPerp wPowerPerp address\\\\n     */\\\\n    function sendBack(address _weth, address _wPowerPerp) public {\\\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n        if (wPowerPerpBalance > 0) {\\\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x51c6185083d747a36ee8543219c0e7a326b866c0bdc113e82956cd4e226f7ba3\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/LiquidityAmounts.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"../../libs/SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\n\\\\n\\\\n/// @title Liquidity amount functions\\\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\\\nlibrary LiquidityAmounts {\\\\n    /// @notice Downcasts uint256 to uint128\\\\n    /// @param x The uint258 to be downcasted\\\\n    /// @return y The passed value, downcasted to uint128\\\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\\\n        require((y = uint128(x)) == x);\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount0 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount0(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount1 The amount1 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount1(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount of token0 being sent in\\\\n    /// @param amount1 The amount of token1 being sent in\\\\n    /// @return liquidity The maximum amount of liquidity received\\\\n    function getLiquidityForAmounts(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\\\n\\\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\\\n        } else {\\\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\\\n        }\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    function getAmount0ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            FullMath.mulDiv(\\\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\\\n                sqrtRatioBX96 - sqrtRatioAX96,\\\\n                sqrtRatioBX96\\\\n            ) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmount1ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n\\\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmountsForLiquidity(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\\\n        } else {\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        }\\\\n    }\\\\n\\\\n    function getAmountsFromLiquidity(        \\\\n        uint160 sqrtRatioX96,\\\\n        int24 currentTick,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (currentTick < tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else if (currentTick < tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtRatioX96,\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                sqrtRatioX96,\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            }\\\\n    \\\\n    }\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb4b0f464529a43f3ca7a9d6afc5976902c0a004649bdf3239ca77469d26b7cf2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101e06040523480156200001257600080fd5b5060405162006a3e38038062006a3e833981016040819052620000359162000679565b8282876001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200007157600080fd5b505afa15801562000086573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ac919062000655565b83876001600160a01b038116620000c257600080fd5b6001600160601b0319606091821b811660805294811b851660a05292831b841660c05290821b831660e052811b82166101005287901b166101405260408051634ea64a2160e11b815290516001600160a01b03881691639d4c9442916004808301926020929190829003018186803b1580156200013e57600080fd5b505afa15801562000153573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000179919062000655565b6001600160a01b0316610160816001600160a01b031660601b81525050856001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b158015620001d057600080fd5b505afa158015620001e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200020b919062000655565b6001600160a01b0316610180816001600160a01b031660601b81525050856001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200026257600080fd5b505afa15801562000277573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029d919062000655565b6001600160601b0319606091821b81166101a0529086901b166101c052604080516307f07b1360e41b815290516001600160a01b03881691637f07b130916004808301926020929190829003018186803b158015620002fb57600080fd5b505afa15801562000310573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000336919062000655565b6001600160a01b0316866001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200037957600080fd5b505afa1580156200038e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003b4919062000655565b6001600160a01b031610151561012081151560f81b81525050856001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b1580156200040757600080fd5b505afa1580156200041c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000442919062000655565b6001600160a01b031663095ea7b3866000196040518363ffffffff1660e01b81526004016200047392919062000736565b602060405180830381600087803b1580156200048e57600080fd5b505af1158015620004a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c99190620006f9565b50856001600160a01b0316633fc8cef36040518163ffffffff1660e01b815260040160206040518083038186803b1580156200050457600080fd5b505afa15801562000519573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200053f919062000655565b6001600160a01b031663095ea7b3866000196040518363ffffffff1660e01b81526004016200057092919062000736565b602060405180830381600087803b1580156200058b57600080fd5b505af1158015620005a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005c69190620006f9565b5060405163a22cb46560e01b81526001600160a01b0386169063a22cb46590620005f89089906001906004016200071b565b600060405180830381600087803b1580156200061357600080fd5b505af115801562000628573d6000803e3d6000fd5b505050505050505050506200074f565b80516001600160a01b03811681146200065057600080fd5b919050565b60006020828403121562000667578081fd5b620006728262000638565b9392505050565b60008060008060008060c0878903121562000692578182fd5b6200069d8762000638565b9550620006ad6020880162000638565b9450620006bd6040880162000638565b9350620006cd6060880162000638565b9250620006dd6080880162000638565b9150620006ed60a0880162000638565b90509295509295509295565b6000602082840312156200070b578081fd5b8151801515811462000672578182fd5b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6101205160f81c6101405160601c6101605160601c6101805160601c6101a05160601c6101c05160601c615fe162000a5d600039806102f452806103dc52806104cd52806108aa5280610b315280610cca5280610efc5280610f8652806110f1528061183f52806118d55280611a4152806120bc52806125eb528061274a5280612a5f5280612bff5280612d5552806132cb528061367e52508061074952806108275280610a385280610acf5280610bef5280610d0e5280610e67528061118252806111fc528061125e52806112c4528061136652806113d3528061177a5280611c0552806120fe52806122f5528061246852806128405280612e0b5280612f13528061310852806131d0528061330d528061349b528061355b528061384d528061392552806139a45280613a6a5280613b0b5280613c405280613cad5280613df5528061404e528061411d52508061076a52806108065280610a5a5280610c115280610cec5280610e895280611161528061121e52806112e652806113f452806116ae528061175952806120dd5280612a815280612ff352806132ec52806134db528061351b52806139c55280613aea5280613f165280613f86525080610dcc5280611e7252806123a25280613e915250806104ab5280610ca852806110cf5280611a1f528061209b528061224f52806122d452806124e65280612565528061272852806128bc528061293b5280612a3d5280612b145280612d335280612ef152806130e652806131ae52806132aa52806133da5280613789528061382b52806139035280613a485280613c1e5280613dd352806140fb52806144985250806103ff528061053d52806105b852806106a852806108f252806109245280610d32528061100d528061195e52806121a4528061265b5280612aa85280612c6d528061332f5250806114b052806116195280611aea525080611bdb52508061146c52806115695280611b0e5250806117d85280611f145250806117fc5280611b7752806147505250615fe16000f3fe6080604052600436106101125760003560e01c8063a15db5c5116100a5578063d8fa26f011610074578063db661b7111610059578063db661b711461027a578063fa461e331461028f578063fc0c546a146102af57610119565b8063d8fa26f014610252578063d9d7858a1461026557610119565b8063a15db5c5146101e8578063bc638a7914610208578063c1c0e9c41461021b578063c45a01551461023d57610119565b80633ca8402b116100e15780633ca8402b1461018f5780634fc5864f146101af57806383b17e4d146101c2578063923247ae146101d557610119565b8063150b7a021461011e57806315d23b04146101545780632ef1f08214610169578063334cc3651461017c57610119565b3661011957005b600080fd5b34801561012a57600080fd5b5061013e610139366004614aaf565b6102c4565b60405161014b9190615b22565b60405180910390f35b6101676101623660046151a6565b6102d4565b005b610167610177366004615506565b610ab8565b61016761018a3660046150fe565b610c39565b34801561019b57600080fd5b506101676101aa3660046151b8565b610ee5565b6101676101bd366004614ea3565b611246565b6101676101d0366004614c3e565b611341565b6101676101e3366004614db7565b61139d565b3480156101f457600080fd5b50610167610203366004614b51565b611461565b610167610216366004614db7565b61167d565b34801561022757600080fd5b506102306117d6565b60405161014b91906156ad565b34801561024957600080fd5b506102306117fa565b610167610260366004614c3e565b61181e565b34801561027157600080fd5b50610230611ae8565b34801561028657600080fd5b50610230611b0c565b34801561029b57600080fd5b506101676102aa366004614bc3565b611b30565b3480156102bb57600080fd5b50610230611bd9565b630a85bd0160e11b949350505050565b6102dd34611bfd565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061033190339030906020870135906004016156c1565b600060405180830381600087803b15801561034b57600080fd5b505af115801561035f573d6000803e3d6000fd5b50506040805160a08101825260208086013582528583013590820152670de0b6b3a7640000818301526001600160801b0361010086013581166060830152610120860135166080820152905163760a3f2b60e11b815260009350737a29594866CF3383555b8e051C80142e86d1058C925063ec147e5691610427917f000000000000000000000000000000000000000000000000000000000000000091907f000000000000000000000000000000000000000000000000000000000000000090600401615a6c565b604080518083038186803b15801561043e57600080fd5b505af4158015610452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104769190614ba0565b50604051630725e4e160e31b8152909150737a29594866CF3383555b8e051C80142e86d1058C9063392f2708906105089033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a013590670de0b6b3a7640000906004016156e5565b60006040518083038186803b15801561052057600080fd5b505af4158015610534573d6000803e3d6000fd5b505050506000807f00000000000000000000000000000000000000000000000000000000000000001561065157737a29594866CF3383555b8e051C80142e86d1058C63b573fa8b6105886020870187614a77565b608087013560608801356105a46101608a016101408b01614b84565b6105b66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016105f896959493929190615ae7565b604080518083038186803b15801561060f57600080fd5b505af4158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190614ba0565b909250905061073c565b737a29594866CF3383555b8e051C80142e86d1058C63b573fa8b6106786020870187614a77565b608087013560608801356106946101608a016101408b01614b84565b6106a66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016106e896959493929190615ae7565b604080518083038186803b1580156106ff57600080fd5b505af4158015610713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107379190614ba0565b925090505b828111156107eb576107e67f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061079b6101a0880161018089016153db565b6107a58588611c61565b6107cf670de0b6b3a76400006107c96107be898c611c61565b60e08d013590611cc3565b90611d23565b600460405180602001604052806000815250611d8a565b61088e565b8281101561088e5760006107ff8483611c61565b905061088b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006108586101a089016101808a016153db565b84610873670de0b6b3a76400006107c960e08d013584611cc3565b60035b60405180602001604052806000815250611dee565b50505b737a29594866CF3383555b8e051C80142e86d1058C63aee2533b7f00000000000000000000000000000000000000000000000000000000000000006108d66020880188614a77565b6040518060e00160405280336001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000061091b578661091d565b875b81526020017f000000000000000000000000000000000000000000000000000000000000000061094d578761094f565b865b815260a08a0135602082015260c08a0135604082015260600161097a6101608b016101408c01614b84565b60020b81526020016109946101808b016101608c01614b84565b60020b8152506040518463ffffffff1660e01b81526004016109b89392919061596c565b60206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0891906153f7565b506040516328bb252f60e11b8152737a29594866CF3383555b8e051C80142e86d1058C906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610a9a57600080fd5b505af4158015610aae573d6000803e3d6000fd5b5050505050505050565b610ac184611e61565b610aca34611bfd565b610b1a7f0000000000000000000000000000000000000000000000000000000000000000846008878686604051602001610b0693929190615dc6565b604051602081830303815290604052611f12565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190610b669030906004016156ad565b60206040518083038186803b158015610b7e57600080fd5b505afa158015610b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb691906153f7565b15610bc057600080fd5b6040516328bb252f60e11b8152737a29594866CF3383555b8e051C80142e86d1058C906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b604081013515610c5057610c508160400135611e61565b610c62608082013560a0830135611fe8565b3414610c6d57600080fd5b610c7634611bfd565b6040516308e6940f60e41b8152600090737a29594866CF3383555b8e051C80142e86d1058C90638e6940f090610d5a907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009089907f000000000000000000000000000000000000000000000000000000000000000090600401615738565b604080518083038186803b158015610d7157600080fd5b505af4158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190614ba0565b5090506040820135610e3857604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610e05903090339086906004016156c1565b600060405180830381600087803b158015610e1f57600080fd5b505af1158015610e33573d6000803e3d6000fd5b505050505b6040516328bb252f60e11b8152737a29594866CF3383555b8e051C80142e86d1058C906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610ec957600080fd5b505af4158015610edd573d6000803e3d6000fd5b505050505050565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610f3690339030908635906004016156c1565b600060405180830381600087803b158015610f5057600080fd5b505af1158015610f64573d6000803e3d6000fd5b505050506000737a29594866CF3383555b8e051C80142e86d1058C63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a00160405280866000013581526020018660200135815260200186604001358152602001866060016020810190610fe191906153bf565b6001600160801b03168152602001610fff60a08801608089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161104a93929190615a6c565b604080518083038186803b15801561106157600080fd5b505af4158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190614ba0565b5060408051630725e4e160e31b8152919250737a29594866CF3383555b8e051C80142e86d1058C9163392f2708916111239133917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000916000918a35918b0135906004016156e5565b60006040518083038186803b15801561113b57600080fd5b505af415801561114f573d6000803e3d6000fd5b505050506000811115610e38576111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006111b160e0860160c087016153db565b84610873670de0b6b3a76400006107c960a08a013584611cc3565b506040516328bb252f60e11b8152737a29594866CF3383555b8e051C80142e86d1058C906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b6112508135611e61565b61125934611bfd565b6112957f000000000000000000000000000000000000000000000000000000000000000060a0830135600784604051602001610b069190615c01565b6040516328bb252f60e11b8152737a29594866CF3383555b8e051C80142e86d1058C906351764a5e9061130e907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b15801561132657600080fd5b505af415801561133a573d6000803e3d6000fd5b5050505050565b602081013515611358576113588160200135611e61565b61136134611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000006080830135600684604051602001610b069190615cca565b6113a78135611e61565b6113b5606082013534611fe8565b816080013511156113c557600080fd5b6113ce34611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061142360c0850160a086016153db565b61143560208601356040870135611fe8565b608086013560018760405160200161144d9190615ba0565b604051602081830303815290604052611d8a565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461149657600080fd5b6000818060200190518101906114ac9190614ded565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ecbcdab600083604001516040518363ffffffff1660e01b8152600401611501929190615b4f565b600060405180830381600087803b15801561151b57600080fd5b505af115801561152f573d6000803e3d6000fd5b5050505061155481600001518260200151836040015184606001518560800151612042565b80602001516001600160a01b031663095ea7b37f000000000000000000000000000000000000000000000000000000000000000083604001516040518363ffffffff1660e01b81526004016115aa929190615ace565b602060405180830381600087803b1580156115c457600080fd5b505af11580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614b35565b50604080820151905163d8aed14560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163d8aed1459161164f91600091600401615b4f565b600060405180830381600087803b15801561166957600080fd5b505af1158015610edd573d6000803e3d6000fd5b80351561168e5761168e8135611e61565b61169734611bfd565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906116eb90339030906060870135906004016156c1565b602060405180830381600087803b15801561170557600080fd5b505af1158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190614b35565b50600061175260208301356060840135611fe8565b90506111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006117a960c0860160a087016153db565b8460808701356002886040516020016117c29190615ba0565b604051602081830303815290604052611dee565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6118288135611e61565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061187c90339030906020870135906004016156c1565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050506118b734611bfd565b6000737a29594866CF3383555b8e051C80142e86d1058C63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200135815260200186604001358152602001866060013581526020018660e001602081019061193091906153bf565b6001600160801b03168152602001611950610120880161010089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161199b93929190615a6c565b604080518083038186803b1580156119b257600080fd5b505af41580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614ba0565b50604051630725e4e160e31b8152909150737a29594866CF3383555b8e051C80142e86d1058C9063392f270890611a789033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a01359060608b0135906004016156e5565b60006040518083038186803b158015611a9057600080fd5b505af4158015611aa4573d6000803e3d6000fd5b50610e389250508335905082608085013560a086013560c0870135611ad161014089016101208a016153db565b611ae36101608a016101408b01614b19565b6138b5565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000841380611b3f5750600083135b611b4857600080fd5b6000611b56828401846151c9565b90506000806000611b6a8460000151613b58565b9250925092506000611b9e7f0000000000000000000000000000000000000000000000000000000000000000858585613b89565b90506000808a13611baf5788611bb1565b895b9050611bcd86602001518684848a606001518b60400151613ba8565b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8015611c5e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166957600080fd5b50565b600082821115611cb8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600082611cd257506000611cbd565b82820282848281611cdf57fe5b0414611d1c5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f8b6021913960400191505060405180910390fd5b9392505050565b6000808211611d79576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611d8257fe5b049392505050565b6000611ddf8530600060405180608001604052808c8c8f604051602001611db393929190615644565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526141e7565b905083811115610aae57600080fd5b600080611e448630600060405180608001604052808e8d8f604051602001611e1893929190615644565b60408051601f1981840301815291815290825233602083015260ff8b1690820152606001889052614354565b905084811015611e5357600080fd5b90505b979650505050505050565b6040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611eaf908590600401615dbd565b60206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190614a93565b6001600160a01b031614611c5e57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060a00160405280336001600160a01b03168152602001886001600160a01b031681526020018781526020018660ff16815260200185815250604051602001611f8e9190615bae565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611fba929190615a4a565b600060405180830381600087803b158015611fd457600080fd5b505af1158015610aae573d6000803e3d6000fd5b600082820183811015611d1c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60068260ff16600981111561205357fe5b600981111561205e57fe5b14156124165760008180602001905181019061207a9190614f6c565b9050600080737a29594866CF3383555b8e051C80142e86d1058C638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000604051806101400160405280306001600160a01b031681526020018a600001516001600160a01b031681526020018a6020015181526020018a6040015181526020018a6060015181526020018a60a0015181526020018a60e0015181526020018a610100015181526020018a610120015160020b81526020018a610140015160020b8152507f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016121e496959493929190615818565b604080518083038186803b1580156121fb57600080fd5b505af415801561220f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122339190614ba0565b6040516348dc69a560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906122869085908590600401615b4f565b600060405180830381600087803b1580156122a057600080fd5b505af11580156122b4573d6000803e3d6000fd5b50505050737a29594866CF3383555b8e051C80142e86d1058C6363410a867f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085600061232e8960c001518d611fe890919063ffffffff16565b6040518663ffffffff1660e01b815260040161234e9594939291906159df565b60006040518083038186803b15801561236657600080fd5b505af415801561237a573d6000803e3d6000fd5b5050505082602001516000141561240e57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906123db9030908c9087906004016156c1565b600060405180830381600087803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050505b50505061133a565b60078260ff16600981111561242757fe5b600981111561243257fe5b14156127eb5760008180602001905181019061244e9190614eb5565b604051632e1a7d4d60e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061249d908790600401615dbd565b600060405180830381600087803b1580156124b757600080fd5b505af11580156124cb573d6000803e3d6000fd5b5050825160405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063b6b55f259250879161251d91600401615dbd565b6000604051808303818588803b15801561253657600080fd5b505af115801561254a573d6000803e3d6000fd5b5050835160405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016945063713d517f935061259b9250600401615dbd565b600060405180830381600087803b1580156125b557600080fd5b505af11580156125c9573d6000803e3d6000fd5b505050506000737a29594866CF3383555b8e051C80142e86d1058C63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200151815260200186604001518152602001866060015181526020018661010001516001600160801b031681526020018661012001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161269893929190615a6c565b604080518083038186803b1580156126af57600080fd5b505af41580156126c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e79190614ba0565b50825160208401516060850151604051630725e4e160e31b8152939450737a29594866CF3383555b8e051C80142e86d1058C9363392f270893612775938d937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000939291906004016156e5565b60006040518083038186803b15801561278d57600080fd5b505af41580156127a1573d6000803e3d6000fd5b505050506127e482600001518284608001516127ce8660a001518760c00151611fe890919063ffffffff16565b8660e001518761014001518861016001516138b5565b505061133a565b60088260ff1660098111156127fc57fe5b600981111561280757fe5b141561133a5760008082806020019051810190612824919061540f565b604051632e1a7d4d60e01b815291935091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612875908890600401615dbd565b600060405180830381600087803b15801561288f57600080fd5b505af11580156128a3573d6000803e3d6000fd5b505060405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063b6b55f25915087906128f5908690600401615dbd565b6000604051808303818588803b15801561290e57600080fd5b505af1158015612922573d6000803e3d6000fd5b505060405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063713d517f925061297391508590600401615dbd565b600060405180830381600087803b15801561298d57600080fd5b505af11580156129a1573d6000803e3d6000fd5b5050505060005b81518110156137fb5760008282815181106129bf57fe5b60200260200101516000015160078111156129d657fe5b1415612b895760008282815181106129ea57fe5b602002602001015160200151806020019051810190612a09919061507c565b8051604051637a04dbd760e01b8152919250737a29594866CF3383555b8e051C80142e86d1058C91637a04dbd791612ad0917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091908b9089907f0000000000000000000000000000000000000000000000000000000000000000906004016158d4565b60006040518083038186803b158015612ae857600080fd5b505af4158015612afc573d6000803e3d6000fd5b5050505060208101516040516348dc69a560e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916391b8d34a91612b51918891600401615b4f565b600060405180830381600087803b158015612b6b57600080fd5b505af1158015612b7f573d6000803e3d6000fd5b50505050506137f3565b6001828281518110612b9757fe5b6020026020010151600001516007811115612bae57fe5b1415612dad576000828281518110612bc257fe5b602002602001015160200151806020019051810190612be19190614cbc565b9050737a29594866CF3383555b8e051C80142e86d1058C63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a0016040528085600001518152602001856020015181526020018560400151815260200185606001516001600160801b0316815260200185608001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401612caa93929190615a6c565b604080518083038186803b158015612cc157600080fd5b505af4158015612cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf99190614ba0565b505080516040808301519051630725e4e160e31b8152737a29594866CF3383555b8e051C80142e86d1058C9263392f270892612d81928e927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c9291906004016156e5565b60006040518083038186803b158015612d9957600080fd5b505af4158015612b7f573d6000803e3d6000fd5b6002828281518110612dbb57fe5b6020026020010151600001516007811115612dd257fe5b1415612f95576000828281518110612de657fe5b602002602001015160200151806020019051810190612e059190614d6f565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612e5591906156ad565b60206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906153f7565b90508160200151811015612ebb57602082018190525b81516020830151604051639f70f9e560e01b8152737a29594866CF3383555b8e051C80142e86d1058C92639f70f9e592612f3d927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60206040518083038186803b158015612f5557600080fd5b505af4158015612f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8d91906153f7565b5050506137f3565b6003828281518110612fa357fe5b6020026020010151600001516007811115612fba57fe5b1415613232576000828281518110612fce57fe5b602002602001015160200151806020019051810190612fed9190615370565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161303d91906156ad565b60206040518083038186803b15801561305557600080fd5b505afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d91906153f7565b905081604001511561316b5760006130a486614493565b9050818110156130b2578091505b60208301516040516331a0854360e11b8152737a29594866CF3383555b8e051C80142e86d1058C916363410a8691613135917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918c918991906004016159df565b60006040518083038186803b15801561314d57600080fd5b505af4158015613161573d6000803e3d6000fd5b505050505061322b565b8151811015613178578082525b815160208301516040516331a0854360e11b8152737a29594866CF3383555b8e051C80142e86d1058C926363410a86926131fa927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60006040518083038186803b15801561321257600080fd5b505af4158015613226573d6000803e3d6000fd5b505050505b50506137f3565b600482828151811061324057fe5b602002602001015160000151600781111561325757fe5b141561343f57600082828151811061326b57fe5b60200260200101516020015180602001905181019061328a9190615110565b90506000737a29594866CF3383555b8e051C80142e86d1058C638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000877f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b815260040161336f96959493929190615818565b604080518083038186803b15801561338657600080fd5b505af415801561339a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133be9190614ba0565b6040516348dc69a560e11b815291965091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906134119088908590600401615b4f565b600060405180830381600087803b15801561342b57600080fd5b505af1158015613226573d6000803e3d6000fd5b600582828151811061344d57fe5b602002602001015160000151600781111561346457fe5b14156135e157600082828151811061347857fe5b6020026020010151602001518060200190518101906134979190615007565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561351357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b8061359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b61359c57600080fd5b61322b81600001518260200151836080015184604001516135da670de0b6b3a76400006107c988604001518960600151611cc390919063ffffffff16565b6009610876565b60068282815181106135ef57fe5b602002602001015160000151600781111561360657fe5b141561371557600082828151811061361a57fe5b6020026020010151602001518060200190518101906136399190614c5a565b604080516080810182528251815230602080830191909152830180516001600160801b03908116838501529051166060820152905163fc6f786560e01b8152919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fc6f7865906136bb908490600401615b5d565b6040805180830381600087803b1580156136d457600080fd5b505af11580156136e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370c9190614ba0565b505050506137f3565b600782828151811061372357fe5b602002602001015160000151600781111561373a57fe5b14156137f357600082828151811061374e57fe5b60200260200101516020015180602001905181019061376d9190614d34565b80516040516348dc69a560e11b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916391b8d34a916137bf91889190600401615b4f565b600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b50505050505b6001016129a8565b506040516331a0854360e11b8152737a29594866CF3383555b8e051C80142e86d1058C906363410a869061387c907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009087906000908c906004016159df565b60006040518083038186803b15801561389457600080fd5b505af41580156138a8573d6000803e3d6000fd5b5050505050505050505050565b80156139895760006138c688614493565b9050868110156138d4578096505b6040516331a0854360e11b8152737a29594866CF3383555b8e051C80142e86d1058C906363410a8690613953907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908d908d908c906004016159df565b60006040518083038186803b15801561396b57600080fd5b505af415801561397f573d6000803e3d6000fd5b5050505050613b46565b84861015613a1957600061399d8688611c61565b9050613a137f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085846139fc670de0b6b3a76400006107c98b84611cc3565b60058e8d8d60405160200161144d93929190615697565b50613b46565b6040516331a0854360e11b8152737a29594866CF3383555b8e051C80142e86d1058C906363410a8690613a98907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c908b908b906004016159df565b60006040518083038186803b158015613ab057600080fd5b505af4158015613ac4573d6000803e3d6000fd5b505050506000613add8688611c6190919063ffffffff16565b90508015613b4457613b427f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008584610873670de0b6b3a76400006107c98b84611cc3565b505b505b613b4f47611bfd565b50505050505050565b60008080613b668482614548565b9250613b73846014614614565b9050613b80846017614548565b91509193909250565b6000613b9f85613b9a8686866146d0565b614726565b95945050505050565b60018160ff166009811115613bb957fe5b6009811115613bc457fe5b1415613d3f57600082806020019051810190613be09190614dd2565b8051602082015160608301516040516331a0854360e11b8152939450737a29594866CF3383555b8e051C80142e86d1058C936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60006040518083038186803b158015613c8057600080fd5b505af4158015613c94573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb9150613ce69088908890600401615ace565b602060405180830381600087803b158015613d0057600080fd5b505af1158015613d14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d389190614b35565b5050610edd565b60028160ff166009811115613d5057fe5b6009811115613d5b57fe5b1415613f4d57600082806020019051810190613d779190614dd2565b9050600081602001511180613d90575060008160400151115b15613eff57805160208201516040808401519051639f70f9e560e01b8152600093737a29594866CF3383555b8e051C80142e86d1058C93639f70f9e593613e21937f0000000000000000000000000000000000000000000000000000000000000000937f000000000000000000000000000000000000000000000000000000000000000093909290916004016159df565b60206040518083038186803b158015613e3957600080fd5b505af4158015613e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7191906153f7565b8251909150613efd57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613eca9030908c9086906004016156c1565b600060405180830381600087803b158015613ee457600080fd5b505af1158015613ef8573d6000803e3d6000fd5b505050505b505b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ce69088908890600401615ace565b60038160ff166009811115613f5e57fe5b6009811115613f6957fe5b14156140155760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b602060405180830381600087803b158015613fd757600080fd5b505af1158015613feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400f9190614b35565b50610edd565b60048160ff16600981111561402657fe5b600981111561403157fe5b14156140855760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b60058160ff16600981111561409657fe5b60098111156140a157fe5b1415614145576000828060200190518101906140bd9190615287565b8051602082015160408084015190516331a0854360e11b8152939450737a29594866CF3383555b8e051C80142e86d1058C936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60098160ff16600981111561415657fe5b600981111561416157fe5b1415610edd5760405163a9059cbb60e01b81526001600160a01b0386169063a9059cbb906141959087908790600401615ace565b602060405180830381600087803b1580156141af57600080fd5b505af11580156141c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4f9190614b35565b6000806000806141fa8560000151613b58565b919450925090506001600160a01b038084169083161060008061421e858786614749565b6001600160a01b031663128acb088b856142378f614787565b6000036001600160a01b038e161561424f578d614275565b8761426e5773fffd8963efd1fc6a506488495d951d5263988d25614275565b6401000276a45b8d6040516020016142869190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142b5959493929190615a10565b6040805180830381600087803b1580156142ce57600080fd5b505af11580156142e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143069190614ba0565b915091506000808461431c578284600003614322565b83836000035b915091508a6001600160a01b031660001415614344578c811461434457600080fd5b509b9a5050505050505050505050565b6000806000806143678560000151613b58565b919450925090506001600160a01b038083169084161060008061438b868686614749565b6001600160a01b031663128acb088b856143a48f614787565b6001600160a01b038e16156143b9578d6143df565b876143d85773fffd8963efd1fc6a506488495d951d5263988d256143df565b6401000276a45b8d6040516020016143f09190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161441f959493929190615a10565b6040805180830381600087803b15801561443857600080fd5b505af115801561444c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144709190614ba0565b915091508261447f5781614481565b805b6000039b9a5050505050505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c64ea4a846040518263ffffffff1660e01b81526004016144e29190615dbd565b60806040518083038186803b1580156144fa57600080fd5b505afa15801561450e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453291906152dc565b606001516001600160801b03169150505b919050565b6000818260140110156145a2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b81601401835110156145fb576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b60008182600301101561466e576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156146c7576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6146d8614899565b826001600160a01b0316846001600160a01b031611156146f6579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614732838361479d565b9050336001600160a01b03821614611cbd57600080fd5b600061477f7f000000000000000000000000000000000000000000000000000000000000000061477a8686866146d0565b61479d565b949350505050565b6000600160ff1b821061479957600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b0316106147c557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561454381615f16565b805161454381615f16565b803561454381615f2b565b805161454381615f2b565b600082601f8301126148f5578081fd5b813561490861490382615ec4565b615ea0565b81815284602083860101111561491c578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614946578081fd5b815161495461490382615ec4565b818152846020838601011115614968578283fd5b61477f826020830160208701615ee6565b803561454381615f46565b805161454381615f46565b600061016082840312156149a1578081fd5b50919050565b600060c082840312156149a1578081fd5b600060c082840312156149c9578081fd5b60405160c0810181811067ffffffffffffffff821117156149e657fe5b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151614a2881615f6a565b60a0919091015292915050565b803561454381615f55565b805161454381615f55565b803561454381615f6a565b805161454381615f6a565b803561454381615f7b565b805161454381615f7b565b600060208284031215614a88578081fd5b8135611d1c81615f16565b600060208284031215614aa4578081fd5b8151611d1c81615f16565b60008060008060808587031215614ac4578283fd5b8435614acf81615f16565b93506020850135614adf81615f16565b925060408501359150606085013567ffffffffffffffff811115614b01578182fd5b614b0d878288016148e5565b91505092959194509250565b600060208284031215614b2a578081fd5b8135611d1c81615f2b565b600060208284031215614b46578081fd5b8151611d1c81615f2b565b600060208284031215614b62578081fd5b813567ffffffffffffffff811115614b78578182fd5b61477f848285016148e5565b600060208284031215614b95578081fd5b8135611d1c81615f46565b60008060408385031215614bb2578182fd5b505080516020909101519092909150565b60008060008060608587031215614bd8578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614bfd578384fd5b818701915087601f830112614c10578384fd5b813581811115614c1e578485fd5b886020828501011115614c2f578485fd5b95989497505060200194505050565b60006101608284031215614c50578081fd5b611d1c838361498f565b600060608284031215614c6b578081fd5b6040516060810181811067ffffffffffffffff82111715614c8857fe5b604052825181526020830151614c9d81615f55565b60208201526040830151614cb081615f55565b60408201529392505050565b600060a08284031215614ccd578081fd5b60405160a0810181811067ffffffffffffffff82111715614cea57fe5b80604052508251815260208301516020820152604083015160408201526060830151614d1581615f55565b60608201526080830151614d2881615f55565b60808201529392505050565b600060208284031215614d45578081fd5b6040516020810181811067ffffffffffffffff82111715614d6257fe5b6040529151825250919050565b600060408284031215614d80578081fd5b6040516040810181811067ffffffffffffffff82111715614d9d57fe5b604052825181526020928301519281019290925250919050565b600060c08284031215614dc8578081fd5b611d1c83836149a7565b600060c08284031215614de3578081fd5b611d1c83836149b8565b600060208284031215614dfe578081fd5b815167ffffffffffffffff80821115614e15578283fd5b9083019060a08286031215614e28578283fd5b60405160a081018181108382111715614e3d57fe5b604052614e49836148c4565b8152614e57602084016148c4565b602082015260408301516040820152614e7260608401614a6c565b6060820152608083015182811115614e88578485fd5b614e9487828601614936565b60808301525095945050505050565b600061018082840312156149a1578081fd5b6000610180808385031215614ec8578182fd5b614ed181615ea0565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100614f2b818501614a40565b90820152610120614f3d848201614a40565b90820152610140614f4f848201614a56565b90820152610160614f618482016148da565b908201529392505050565b6000610160808385031215614f7f578182fd5b614f8881615ea0565b9050614f93836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120614ff5818501614984565b90820152610140614f61848201614984565b600060a08284031215615018578081fd5b60405160a0810181811067ffffffffffffffff8211171561503557fe5b604052825161504381615f16565b8152602083015161505381615f16565b8060208301525060408301516040820152606083015160608201526080830151614d2881615f6a565b600060e0828403121561508d578081fd5b60405160e0810181811067ffffffffffffffff821117156150aa57fe5b6040526150b6836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600061014082840312156149a1578081fd5b6000610140808385031215615123578182fd5b61512c81615ea0565b9050615137836148c4565b8152615145602084016148c4565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100615194818501614984565b90820152610120614f61848201614984565b60006101a082840312156149a1578081fd5b600060e082840312156149a1578081fd5b6000602082840312156151da578081fd5b813567ffffffffffffffff808211156151f1578283fd5b9083019060808286031215615204578283fd5b60405160808101818110838211171561521957fe5b60405282358281111561522a578485fd5b615236878286016148e5565b825250615245602084016148b9565b602082015261525660408401614a61565b604082015260608301358281111561526c578485fd5b615278878286016148e5565b60608301525095945050505050565b600060608284031215615298578081fd5b6040516060810181811067ffffffffffffffff821117156152b557fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000608082840312156152ed578081fd5b6040516080810181811067ffffffffffffffff8211171561530a57fe5b604052825161531881615f16565b8152602083015163ffffffff81168114615330578283fd5b602082015260408301516bffffffffffffffffffffffff81168114615353578283fd5b604082015261536460608401614a40565b60608201529392505050565b600060608284031215615381578081fd5b6040516060810181811067ffffffffffffffff8211171561539e57fe5b806040525082518152602083015160208201526040830151614cb081615f2b565b6000602082840312156153d0578081fd5b8135611d1c81615f55565b6000602082840312156153ec578081fd5b8135611d1c81615f6a565b600060208284031215615408578081fd5b5051919050565b60008060408385031215615421578182fd5b8251915060208084015167ffffffffffffffff80821115615440578384fd5b818601915086601f830112615453578384fd5b81518181111561545f57fe5b61546c8485830201615ea0565b81815284810190848601875b848110156154f557815187016040818e03601f1901121561549757898afd5b6040516040810181811089821117156154ac57fe5b604052818a01516154bc81615f39565b81526040820151888111156154cf578b8cfd5b6154dd8f8c83860101614936565b828c0152508552509287019290870190600101615478565b50979a909950975050505050505050565b6000806000806060858703121561551b578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615540578384fd5b818701915087601f830112615553578384fd5b813581811115615561578485fd5b8860208083028501011115614c2f578485fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526155c9816020860160208601615ee6565b601f01601f19169290920160200192915050565b60020b9052565b803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a081013561561e81615f6a565b62ffffff811660a0840152505050565b6001600160801b03169052565b62ffffff169052565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286811660208301528581166040830152841660608201526101e0810161577660808301615771866148b9565b615574565b615782602085016148b9565b61578f60a0840182615574565b50604084013560c0830152606084013560e083015261010060808501358184015261012060a08601358185015260c086013561014085015260e08601356101608501526157dd828701614979565b91506157ed6101808501836155dd565b6157f8818701614979565b9150506158096101a08401826155dd565b50611e566101c0830184615581565b6001600160a01b038781168252868116602083015285811660408301528416606082015282516101e0820190615852906080840190615574565b602084015161586460a0840182615574565b50604084015160c0830152606084015160e08301526080840151610100818185015260a08601519150610120828186015260c087015161014086015260e08701516101608601528187015192506158bf6101808601846155dd565b860151915061580990506101a08401826155dd565b60006101a0820190506001600160a01b03808a1683528089166020840152808816604084015280871660608401528560808401528085511660a084015250602084015160c0830152604084015160e08301526060840151610100830152608084015161012083015260a084015161014083015260c0840151610160830152615960610180830184615581565b98975050505050505050565b6000610120820190506001600160a01b0380861683528085166020840152808451166040840152506020830151606083015260408301516080830152606083015160a0830152608083015160c083015260a083015160020b60e083015260c083015160020b610100830152949350505050565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152611e5660a08301846155b1565b60006001600160a01b03841682526040602083015261477f60408301846155b1565b600060e0820190506001600160a01b038516825283516020830152602084015160408301526040840151606083015260608401516001600160801b0380821660808501528060808701511660a0850152505082151560c0830152949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396909616865260208601949094526040850192909252600290810b60608501520b6080830152151560a082015260c00190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b918252602082015260400190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b60c08101611cbd82846155e4565b6000602082526001600160a01b03808451166020840152806020850151166040840152506040830151606083015260ff6060840151166080830152608083015160a08084015261477f60c08401826155b1565b600061018082019050823582526020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100615c62818501614a35565b615c6e8285018261562e565b5050610120615c7e818501614a35565b615c8a8285018261562e565b5050610140615c9a818501614a4b565b615ca68285018261563b565b5050610160615cb68185016148cf565b615cc282850182615581565b505092915050565b6101608101615cdc82615771856148b9565b6020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100808401358184015250610120615d3c818501614979565b615d48828501826155dd565b5050610140615d58818501614979565b615cc2828501826155dd565b600060208252825160806020840152615d8060a08401826155b1565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f19848303016080850152613b9f82826155b1565b90815260200190565b6000604080830186845260208281860152818683526060860190506060828802870101925087855b88811015615e9157878503605f190183528135368b9003603e19018112615e13578788fd5b8a018035615e2081615f39565b60088110615e2a57fe5b86528085013536829003601e19018112615e42578889fd5b8101803567ffffffffffffffff811115615e5a57898afd5b803603831315615e6857898afd5b8887890152615e7c89890182898501615587565b97505050928401925090830190600101615dee565b50929998505050505050505050565b60405181810167ffffffffffffffff81118282101715615ebc57fe5b604052919050565b600067ffffffffffffffff821115615ed857fe5b50601f01601f191660200190565b60005b83811015615f01578181015183820152602001615ee9565b83811115615f10576000848401525b50505050565b6001600160a01b0381168114611c5e57600080fd5b8015158114611c5e57600080fd5b60088110611c5e57600080fd5b8060020b8114611c5e57600080fd5b6001600160801b0381168114611c5e57600080fd5b62ffffff81168114611c5e57600080fd5b60ff81168114611c5e57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220564c27264bc33c078d9c75afb2f26fb0c092712e686cacc101aaeee9df569b6e64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x6080604052600436106101125760003560e01c8063a15db5c5116100a5578063d8fa26f011610074578063db661b7111610059578063db661b711461027a578063fa461e331461028f578063fc0c546a146102af57610119565b8063d8fa26f014610252578063d9d7858a1461026557610119565b8063a15db5c5146101e8578063bc638a7914610208578063c1c0e9c41461021b578063c45a01551461023d57610119565b80633ca8402b116100e15780633ca8402b1461018f5780634fc5864f146101af57806383b17e4d146101c2578063923247ae146101d557610119565b8063150b7a021461011e57806315d23b04146101545780632ef1f08214610169578063334cc3651461017c57610119565b3661011957005b600080fd5b34801561012a57600080fd5b5061013e610139366004614aaf565b6102c4565b60405161014b9190615b22565b60405180910390f35b6101676101623660046151a6565b6102d4565b005b610167610177366004615506565b610ab8565b61016761018a3660046150fe565b610c39565b34801561019b57600080fd5b506101676101aa3660046151b8565b610ee5565b6101676101bd366004614ea3565b611246565b6101676101d0366004614c3e565b611341565b6101676101e3366004614db7565b61139d565b3480156101f457600080fd5b50610167610203366004614b51565b611461565b610167610216366004614db7565b61167d565b34801561022757600080fd5b506102306117d6565b60405161014b91906156ad565b34801561024957600080fd5b506102306117fa565b610167610260366004614c3e565b61181e565b34801561027157600080fd5b50610230611ae8565b34801561028657600080fd5b50610230611b0c565b34801561029b57600080fd5b506101676102aa366004614bc3565b611b30565b3480156102bb57600080fd5b50610230611bd9565b630a85bd0160e11b949350505050565b6102dd34611bfd565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061033190339030906020870135906004016156c1565b600060405180830381600087803b15801561034b57600080fd5b505af115801561035f573d6000803e3d6000fd5b50506040805160a08101825260208086013582528583013590820152670de0b6b3a7640000818301526001600160801b0361010086013581166060830152610120860135166080820152905163760a3f2b60e11b81526000935073__$561e80098325da493156966792c25e3551$__925063ec147e5691610427917f000000000000000000000000000000000000000000000000000000000000000091907f000000000000000000000000000000000000000000000000000000000000000090600401615a6c565b604080518083038186803b15801561043e57600080fd5b505af4158015610452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104769190614ba0565b50604051630725e4e160e31b815290915073__$561e80098325da493156966792c25e3551$__9063392f2708906105089033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a013590670de0b6b3a7640000906004016156e5565b60006040518083038186803b15801561052057600080fd5b505af4158015610534573d6000803e3d6000fd5b505050506000807f0000000000000000000000000000000000000000000000000000000000000000156106515773__$561e80098325da493156966792c25e3551$__63b573fa8b6105886020870187614a77565b608087013560608801356105a46101608a016101408b01614b84565b6105b66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016105f896959493929190615ae7565b604080518083038186803b15801561060f57600080fd5b505af4158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190614ba0565b909250905061073c565b73__$561e80098325da493156966792c25e3551$__63b573fa8b6106786020870187614a77565b608087013560608801356106946101608a016101408b01614b84565b6106a66101808b016101608c01614b84565b7f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016106e896959493929190615ae7565b604080518083038186803b1580156106ff57600080fd5b505af4158015610713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107379190614ba0565b925090505b828111156107eb576107e67f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061079b6101a0880161018089016153db565b6107a58588611c61565b6107cf670de0b6b3a76400006107c96107be898c611c61565b60e08d013590611cc3565b90611d23565b600460405180602001604052806000815250611d8a565b61088e565b8281101561088e5760006107ff8483611c61565b905061088b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006108586101a089016101808a016153db565b84610873670de0b6b3a76400006107c960e08d013584611cc3565b60035b60405180602001604052806000815250611dee565b50505b73__$561e80098325da493156966792c25e3551$__63aee2533b7f00000000000000000000000000000000000000000000000000000000000000006108d66020880188614a77565b6040518060e00160405280336001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000061091b578661091d565b875b81526020017f000000000000000000000000000000000000000000000000000000000000000061094d578761094f565b865b815260a08a0135602082015260c08a0135604082015260600161097a6101608b016101408c01614b84565b60020b81526020016109946101808b016101608c01614b84565b60020b8152506040518463ffffffff1660e01b81526004016109b89392919061596c565b60206040518083038186803b1580156109d057600080fd5b505af41580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0891906153f7565b506040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610a9a57600080fd5b505af4158015610aae573d6000803e3d6000fd5b5050505050505050565b610ac184611e61565b610aca34611bfd565b610b1a7f0000000000000000000000000000000000000000000000000000000000000000846008878686604051602001610b0693929190615dc6565b604051602081830303815290604052611f12565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190610b669030906004016156ad565b60206040518083038186803b158015610b7e57600080fd5b505afa158015610b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb691906153f7565b15610bc057600080fd5b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610a82907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b604081013515610c5057610c508160400135611e61565b610c62608082013560a0830135611fe8565b3414610c6d57600080fd5b610c7634611bfd565b6040516308e6940f60e41b815260009073__$561e80098325da493156966792c25e3551$__90638e6940f090610d5a907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009089907f000000000000000000000000000000000000000000000000000000000000000090600401615738565b604080518083038186803b158015610d7157600080fd5b505af4158015610d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da99190614ba0565b5090506040820135610e3857604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610e05903090339086906004016156c1565b600060405180830381600087803b158015610e1f57600080fd5b505af1158015610e33573d6000803e3d6000fd5b505050505b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b158015610ec957600080fd5b505af4158015610edd573d6000803e3d6000fd5b505050505050565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610f3690339030908635906004016156c1565b600060405180830381600087803b158015610f5057600080fd5b505af1158015610f64573d6000803e3d6000fd5b50505050600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a00160405280866000013581526020018660200135815260200186604001358152602001866060016020810190610fe191906153bf565b6001600160801b03168152602001610fff60a08801608089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161104a93929190615a6c565b604080518083038186803b15801561106157600080fd5b505af4158015611075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110999190614ba0565b5060408051630725e4e160e31b815291925073__$561e80098325da493156966792c25e3551$__9163392f2708916111239133917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000916000918a35918b0135906004016156e5565b60006040518083038186803b15801561113b57600080fd5b505af415801561114f573d6000803e3d6000fd5b505050506000811115610e38576111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006111b160e0860160c087016153db565b84610873670de0b6b3a76400006107c960a08a013584611cc3565b506040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e90610eb1907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b6112508135611e61565b61125934611bfd565b6112957f000000000000000000000000000000000000000000000000000000000000000060a0830135600784604051602001610b069190615c01565b6040516328bb252f60e11b815273__$561e80098325da493156966792c25e3551$__906351764a5e9061130e907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060040161571e565b60006040518083038186803b15801561132657600080fd5b505af415801561133a573d6000803e3d6000fd5b5050505050565b602081013515611358576113588160200135611e61565b61136134611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000006080830135600684604051602001610b069190615cca565b6113a78135611e61565b6113b5606082013534611fe8565b816080013511156113c557600080fd5b6113ce34611bfd565b6112957f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061142360c0850160a086016153db565b61143560208601356040870135611fe8565b608086013560018760405160200161144d9190615ba0565b604051602081830303815290604052611d8a565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461149657600080fd5b6000818060200190518101906114ac9190614ded565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630ecbcdab600083604001516040518363ffffffff1660e01b8152600401611501929190615b4f565b600060405180830381600087803b15801561151b57600080fd5b505af115801561152f573d6000803e3d6000fd5b5050505061155481600001518260200151836040015184606001518560800151612042565b80602001516001600160a01b031663095ea7b37f000000000000000000000000000000000000000000000000000000000000000083604001516040518363ffffffff1660e01b81526004016115aa929190615ace565b602060405180830381600087803b1580156115c457600080fd5b505af11580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614b35565b50604080820151905163d8aed14560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163d8aed1459161164f91600091600401615b4f565b600060405180830381600087803b15801561166957600080fd5b505af1158015610edd573d6000803e3d6000fd5b80351561168e5761168e8135611e61565b61169734611bfd565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906116eb90339030906060870135906004016156c1565b602060405180830381600087803b15801561170557600080fd5b505af1158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190614b35565b50600061175260208301356060840135611fe8565b90506111cc7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006117a960c0860160a087016153db565b8460808701356002886040516020016117c29190615ba0565b604051602081830303815290604052611dee565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6118288135611e61565b604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e9061187c90339030906020870135906004016156c1565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050506118b734611bfd565b600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200135815260200186604001358152602001866060013581526020018660e001602081019061193091906153bf565b6001600160801b03168152602001611950610120880161010089016153bf565b6001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161199b93929190615a6c565b604080518083038186803b1580156119b257600080fd5b505af41580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea9190614ba0565b50604051630725e4e160e31b815290915073__$561e80098325da493156966792c25e3551$__9063392f270890611a789033907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009060208a01359060608b0135906004016156e5565b60006040518083038186803b158015611a9057600080fd5b505af4158015611aa4573d6000803e3d6000fd5b50610e389250508335905082608085013560a086013560c0870135611ad161014089016101208a016153db565b611ae36101608a016101408b01614b19565b6138b5565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000841380611b3f5750600083135b611b4857600080fd5b6000611b56828401846151c9565b90506000806000611b6a8460000151613b58565b9250925092506000611b9e7f0000000000000000000000000000000000000000000000000000000000000000858585613b89565b90506000808a13611baf5788611bb1565b895b9050611bcd86602001518684848a606001518b60400151613ba8565b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b8015611c5e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166957600080fd5b50565b600082821115611cb8576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b600082611cd257506000611cbd565b82820282848281611cdf57fe5b0414611d1c5760405162461bcd60e51b8152600401808060200182810382526021815260200180615f8b6021913960400191505060405180910390fd5b9392505050565b6000808211611d79576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611d8257fe5b049392505050565b6000611ddf8530600060405180608001604052808c8c8f604051602001611db393929190615644565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526141e7565b905083811115610aae57600080fd5b600080611e448630600060405180608001604052808e8d8f604051602001611e1893929190615644565b60408051601f1981840301815291815290825233602083015260ff8b1690820152606001889052614354565b905084811015611e5357600080fd5b90505b979650505050505050565b6040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90611eaf908590600401615dbd565b60206040518083038186803b158015611ec757600080fd5b505afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190614a93565b6001600160a01b031614611c5e57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060a00160405280336001600160a01b03168152602001886001600160a01b031681526020018781526020018660ff16815260200185815250604051602001611f8e9190615bae565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611fba929190615a4a565b600060405180830381600087803b158015611fd457600080fd5b505af1158015610aae573d6000803e3d6000fd5b600082820183811015611d1c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60068260ff16600981111561205357fe5b600981111561205e57fe5b14156124165760008180602001905181019061207a9190614f6c565b905060008073__$561e80098325da493156966792c25e3551$__638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000604051806101400160405280306001600160a01b031681526020018a600001516001600160a01b031681526020018a6020015181526020018a6040015181526020018a6060015181526020018a60a0015181526020018a60e0015181526020018a610100015181526020018a610120015160020b81526020018a610140015160020b8152507f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b81526004016121e496959493929190615818565b604080518083038186803b1580156121fb57600080fd5b505af415801561220f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122339190614ba0565b6040516348dc69a560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906122869085908590600401615b4f565b600060405180830381600087803b1580156122a057600080fd5b505af11580156122b4573d6000803e3d6000fd5b5050505073__$561e80098325da493156966792c25e3551$__6363410a867f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085600061232e8960c001518d611fe890919063ffffffff16565b6040518663ffffffff1660e01b815260040161234e9594939291906159df565b60006040518083038186803b15801561236657600080fd5b505af415801561237a573d6000803e3d6000fd5b5050505082602001516000141561240e57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e906123db9030908c9087906004016156c1565b600060405180830381600087803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050505b50505061133a565b60078260ff16600981111561242757fe5b600981111561243257fe5b14156127eb5760008180602001905181019061244e9190614eb5565b604051632e1a7d4d60e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9061249d908790600401615dbd565b600060405180830381600087803b1580156124b757600080fd5b505af11580156124cb573d6000803e3d6000fd5b5050825160405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063b6b55f259250879161251d91600401615dbd565b6000604051808303818588803b15801561253657600080fd5b505af115801561254a573d6000803e3d6000fd5b5050835160405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016945063713d517f935061259b9250600401615dbd565b600060405180830381600087803b1580156125b557600080fd5b505af11580156125c9573d6000803e3d6000fd5b50505050600073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a001604052808660200151815260200186604001518152602001866060015181526020018661010001516001600160801b031681526020018661012001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161269893929190615a6c565b604080518083038186803b1580156126af57600080fd5b505af41580156126c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e79190614ba0565b50825160208401516060850151604051630725e4e160e31b815293945073__$561e80098325da493156966792c25e3551$__9363392f270893612775938d937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000939291906004016156e5565b60006040518083038186803b15801561278d57600080fd5b505af41580156127a1573d6000803e3d6000fd5b505050506127e482600001518284608001516127ce8660a001518760c00151611fe890919063ffffffff16565b8660e001518761014001518861016001516138b5565b505061133a565b60088260ff1660098111156127fc57fe5b600981111561280757fe5b141561133a5760008082806020019051810190612824919061540f565b604051632e1a7d4d60e01b815291935091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612875908890600401615dbd565b600060405180830381600087803b15801561288f57600080fd5b505af11580156128a3573d6000803e3d6000fd5b505060405163b6b55f2560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063b6b55f25915087906128f5908690600401615dbd565b6000604051808303818588803b15801561290e57600080fd5b505af1158015612922573d6000803e3d6000fd5b505060405163713d517f60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063713d517f925061297391508590600401615dbd565b600060405180830381600087803b15801561298d57600080fd5b505af11580156129a1573d6000803e3d6000fd5b5050505060005b81518110156137fb5760008282815181106129bf57fe5b60200260200101516000015160078111156129d657fe5b1415612b895760008282815181106129ea57fe5b602002602001015160200151806020019051810190612a09919061507c565b8051604051637a04dbd760e01b815291925073__$561e80098325da493156966792c25e3551$__91637a04dbd791612ad0917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091908b9089907f0000000000000000000000000000000000000000000000000000000000000000906004016158d4565b60006040518083038186803b158015612ae857600080fd5b505af4158015612afc573d6000803e3d6000fd5b5050505060208101516040516348dc69a560e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916391b8d34a91612b51918891600401615b4f565b600060405180830381600087803b158015612b6b57600080fd5b505af1158015612b7f573d6000803e3d6000fd5b50505050506137f3565b6001828281518110612b9757fe5b6020026020010151600001516007811115612bae57fe5b1415612dad576000828281518110612bc257fe5b602002602001015160200151806020019051810190612be19190614cbc565b905073__$561e80098325da493156966792c25e3551$__63ec147e567f00000000000000000000000000000000000000000000000000000000000000006040518060a0016040528085600001518152602001856020015181526020018560400151815260200185606001516001600160801b0316815260200185608001516001600160801b03168152507f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401612caa93929190615a6c565b604080518083038186803b158015612cc157600080fd5b505af4158015612cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf99190614ba0565b505080516040808301519051630725e4e160e31b815273__$561e80098325da493156966792c25e3551$__9263392f270892612d81928e927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c9291906004016156e5565b60006040518083038186803b158015612d9957600080fd5b505af4158015612b7f573d6000803e3d6000fd5b6002828281518110612dbb57fe5b6020026020010151600001516007811115612dd257fe5b1415612f95576000828281518110612de657fe5b602002602001015160200151806020019051810190612e059190614d6f565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612e5591906156ad565b60206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906153f7565b90508160200151811015612ebb57602082018190525b81516020830151604051639f70f9e560e01b815273__$561e80098325da493156966792c25e3551$__92639f70f9e592612f3d927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60206040518083038186803b158015612f5557600080fd5b505af4158015612f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f8d91906153f7565b5050506137f3565b6003828281518110612fa357fe5b6020026020010151600001516007811115612fba57fe5b1415613232576000828281518110612fce57fe5b602002602001015160200151806020019051810190612fed9190615370565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161303d91906156ad565b60206040518083038186803b15801561305557600080fd5b505afa158015613069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061308d91906153f7565b905081604001511561316b5760006130a486614493565b9050818110156130b2578091505b60208301516040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__916363410a8691613135917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918c918991906004016159df565b60006040518083038186803b15801561314d57600080fd5b505af4158015613161573d6000803e3d6000fd5b505050505061322b565b8151811015613178578082525b815160208301516040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__926363410a86926131fa927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000928c926004016159df565b60006040518083038186803b15801561321257600080fd5b505af4158015613226573d6000803e3d6000fd5b505050505b50506137f3565b600482828151811061324057fe5b602002602001015160000151600781111561325757fe5b141561343f57600082828151811061326b57fe5b60200260200101516020015180602001905181019061328a9190615110565b9050600073__$561e80098325da493156966792c25e3551$__638e6940f07f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000877f00000000000000000000000000000000000000000000000000000000000000006040518763ffffffff1660e01b815260040161336f96959493929190615818565b604080518083038186803b15801561338657600080fd5b505af415801561339a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133be9190614ba0565b6040516348dc69a560e11b815291965091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391b8d34a906134119088908590600401615b4f565b600060405180830381600087803b15801561342b57600080fd5b505af1158015613226573d6000803e3d6000fd5b600582828151811061344d57fe5b602002602001015160000151600781111561346457fe5b14156135e157600082828151811061347857fe5b6020026020010151602001518060200190518101906134979190615007565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561351357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b8061359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b031614801561359357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b61359c57600080fd5b61322b81600001518260200151836080015184604001516135da670de0b6b3a76400006107c988604001518960600151611cc390919063ffffffff16565b6009610876565b60068282815181106135ef57fe5b602002602001015160000151600781111561360657fe5b141561371557600082828151811061361a57fe5b6020026020010151602001518060200190518101906136399190614c5a565b604080516080810182528251815230602080830191909152830180516001600160801b03908116838501529051166060820152905163fc6f786560e01b8152919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fc6f7865906136bb908490600401615b5d565b6040805180830381600087803b1580156136d457600080fd5b505af11580156136e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370c9190614ba0565b505050506137f3565b600782828151811061372357fe5b602002602001015160000151600781111561373a57fe5b14156137f357600082828151811061374e57fe5b60200260200101516020015180602001905181019061376d9190614d34565b80516040516348dc69a560e11b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916391b8d34a916137bf91889190600401615b4f565b600060405180830381600087803b1580156137d957600080fd5b505af11580156137ed573d6000803e3d6000fd5b50505050505b6001016129a8565b506040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a869061387c907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009087906000908c906004016159df565b60006040518083038186803b15801561389457600080fd5b505af41580156138a8573d6000803e3d6000fd5b5050505050505050505050565b80156139895760006138c688614493565b9050868110156138d4578096505b6040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a8690613953907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908d908d908c906004016159df565b60006040518083038186803b15801561396b57600080fd5b505af415801561397f573d6000803e3d6000fd5b5050505050613b46565b84861015613a1957600061399d8688611c61565b9050613a137f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000085846139fc670de0b6b3a76400006107c98b84611cc3565b60058e8d8d60405160200161144d93929190615697565b50613b46565b6040516331a0854360e11b815273__$561e80098325da493156966792c25e3551$__906363410a8690613a98907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c908b908b906004016159df565b60006040518083038186803b158015613ab057600080fd5b505af4158015613ac4573d6000803e3d6000fd5b505050506000613add8688611c6190919063ffffffff16565b90508015613b4457613b427f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008584610873670de0b6b3a76400006107c98b84611cc3565b505b505b613b4f47611bfd565b50505050505050565b60008080613b668482614548565b9250613b73846014614614565b9050613b80846017614548565b91509193909250565b6000613b9f85613b9a8686866146d0565b614726565b95945050505050565b60018160ff166009811115613bb957fe5b6009811115613bc457fe5b1415613d3f57600082806020019051810190613be09190614dd2565b8051602082015160608301516040516331a0854360e11b815293945073__$561e80098325da493156966792c25e3551$__936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60006040518083038186803b158015613c8057600080fd5b505af4158015613c94573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb9150613ce69088908890600401615ace565b602060405180830381600087803b158015613d0057600080fd5b505af1158015613d14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d389190614b35565b5050610edd565b60028160ff166009811115613d5057fe5b6009811115613d5b57fe5b1415613f4d57600082806020019051810190613d779190614dd2565b9050600081602001511180613d90575060008160400151115b15613eff57805160208201516040808401519051639f70f9e560e01b815260009373__$561e80098325da493156966792c25e3551$__93639f70f9e593613e21937f0000000000000000000000000000000000000000000000000000000000000000937f000000000000000000000000000000000000000000000000000000000000000093909290916004016159df565b60206040518083038186803b158015613e3957600080fd5b505af4158015613e4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7191906153f7565b8251909150613efd57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90613eca9030908c9086906004016156c1565b600060405180830381600087803b158015613ee457600080fd5b505af1158015613ef8573d6000803e3d6000fd5b505050505b505b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613ce69088908890600401615ace565b60038160ff166009811115613f5e57fe5b6009811115613f6957fe5b14156140155760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b602060405180830381600087803b158015613fd757600080fd5b505af1158015613feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400f9190614b35565b50610edd565b60048160ff16600981111561402657fe5b600981111561403157fe5b14156140855760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613fbd9087908790600401615ace565b60058160ff16600981111561409657fe5b60098111156140a157fe5b1415614145576000828060200190518101906140bd9190615287565b8051602082015160408084015190516331a0854360e11b815293945073__$561e80098325da493156966792c25e3551$__936363410a8693613c68937f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000936004016159df565b60098160ff16600981111561415657fe5b600981111561416157fe5b1415610edd5760405163a9059cbb60e01b81526001600160a01b0386169063a9059cbb906141959087908790600401615ace565b602060405180830381600087803b1580156141af57600080fd5b505af11580156141c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4f9190614b35565b6000806000806141fa8560000151613b58565b919450925090506001600160a01b038084169083161060008061421e858786614749565b6001600160a01b031663128acb088b856142378f614787565b6000036001600160a01b038e161561424f578d614275565b8761426e5773fffd8963efd1fc6a506488495d951d5263988d25614275565b6401000276a45b8d6040516020016142869190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016142b5959493929190615a10565b6040805180830381600087803b1580156142ce57600080fd5b505af11580156142e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143069190614ba0565b915091506000808461431c578284600003614322565b83836000035b915091508a6001600160a01b031660001415614344578c811461434457600080fd5b509b9a5050505050505050505050565b6000806000806143678560000151613b58565b919450925090506001600160a01b038083169084161060008061438b868686614749565b6001600160a01b031663128acb088b856143a48f614787565b6001600160a01b038e16156143b9578d6143df565b876143d85773fffd8963efd1fc6a506488495d951d5263988d256143df565b6401000276a45b8d6040516020016143f09190615d64565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161441f959493929190615a10565b6040805180830381600087803b15801561443857600080fd5b505af115801561444c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144709190614ba0565b915091508261447f5781614481565b805b6000039b9a5050505050505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c64ea4a846040518263ffffffff1660e01b81526004016144e29190615dbd565b60806040518083038186803b1580156144fa57600080fd5b505afa15801561450e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453291906152dc565b606001516001600160801b03169150505b919050565b6000818260140110156145a2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b81601401835110156145fb576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b60008182600301101561466e576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156146c7576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6146d8614899565b826001600160a01b0316846001600160a01b031611156146f6579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000614732838361479d565b9050336001600160a01b03821614611cbd57600080fd5b600061477f7f000000000000000000000000000000000000000000000000000000000000000061477a8686866146d0565b61479d565b949350505050565b6000600160ff1b821061479957600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b0316106147c557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561454381615f16565b805161454381615f16565b803561454381615f2b565b805161454381615f2b565b600082601f8301126148f5578081fd5b813561490861490382615ec4565b615ea0565b81815284602083860101111561491c578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614946578081fd5b815161495461490382615ec4565b818152846020838601011115614968578283fd5b61477f826020830160208701615ee6565b803561454381615f46565b805161454381615f46565b600061016082840312156149a1578081fd5b50919050565b600060c082840312156149a1578081fd5b600060c082840312156149c9578081fd5b60405160c0810181811067ffffffffffffffff821117156149e657fe5b8060405250809150825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a0830151614a2881615f6a565b60a0919091015292915050565b803561454381615f55565b805161454381615f55565b803561454381615f6a565b805161454381615f6a565b803561454381615f7b565b805161454381615f7b565b600060208284031215614a88578081fd5b8135611d1c81615f16565b600060208284031215614aa4578081fd5b8151611d1c81615f16565b60008060008060808587031215614ac4578283fd5b8435614acf81615f16565b93506020850135614adf81615f16565b925060408501359150606085013567ffffffffffffffff811115614b01578182fd5b614b0d878288016148e5565b91505092959194509250565b600060208284031215614b2a578081fd5b8135611d1c81615f2b565b600060208284031215614b46578081fd5b8151611d1c81615f2b565b600060208284031215614b62578081fd5b813567ffffffffffffffff811115614b78578182fd5b61477f848285016148e5565b600060208284031215614b95578081fd5b8135611d1c81615f46565b60008060408385031215614bb2578182fd5b505080516020909101519092909150565b60008060008060608587031215614bd8578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614bfd578384fd5b818701915087601f830112614c10578384fd5b813581811115614c1e578485fd5b886020828501011115614c2f578485fd5b95989497505060200194505050565b60006101608284031215614c50578081fd5b611d1c838361498f565b600060608284031215614c6b578081fd5b6040516060810181811067ffffffffffffffff82111715614c8857fe5b604052825181526020830151614c9d81615f55565b60208201526040830151614cb081615f55565b60408201529392505050565b600060a08284031215614ccd578081fd5b60405160a0810181811067ffffffffffffffff82111715614cea57fe5b80604052508251815260208301516020820152604083015160408201526060830151614d1581615f55565b60608201526080830151614d2881615f55565b60808201529392505050565b600060208284031215614d45578081fd5b6040516020810181811067ffffffffffffffff82111715614d6257fe5b6040529151825250919050565b600060408284031215614d80578081fd5b6040516040810181811067ffffffffffffffff82111715614d9d57fe5b604052825181526020928301519281019290925250919050565b600060c08284031215614dc8578081fd5b611d1c83836149a7565b600060c08284031215614de3578081fd5b611d1c83836149b8565b600060208284031215614dfe578081fd5b815167ffffffffffffffff80821115614e15578283fd5b9083019060a08286031215614e28578283fd5b60405160a081018181108382111715614e3d57fe5b604052614e49836148c4565b8152614e57602084016148c4565b602082015260408301516040820152614e7260608401614a6c565b6060820152608083015182811115614e88578485fd5b614e9487828601614936565b60808301525095945050505050565b600061018082840312156149a1578081fd5b6000610180808385031215614ec8578182fd5b614ed181615ea0565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100614f2b818501614a40565b90820152610120614f3d848201614a40565b90820152610140614f4f848201614a56565b90820152610160614f618482016148da565b908201529392505050565b6000610160808385031215614f7f578182fd5b614f8881615ea0565b9050614f93836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120614ff5818501614984565b90820152610140614f61848201614984565b600060a08284031215615018578081fd5b60405160a0810181811067ffffffffffffffff8211171561503557fe5b604052825161504381615f16565b8152602083015161505381615f16565b8060208301525060408301516040820152606083015160608201526080830151614d2881615f6a565b600060e0828403121561508d578081fd5b60405160e0810181811067ffffffffffffffff821117156150aa57fe5b6040526150b6836148c4565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c08201528091505092915050565b600061014082840312156149a1578081fd5b6000610140808385031215615123578182fd5b61512c81615ea0565b9050615137836148c4565b8152615145602084016148c4565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e0820152610100615194818501614984565b90820152610120614f61848201614984565b60006101a082840312156149a1578081fd5b600060e082840312156149a1578081fd5b6000602082840312156151da578081fd5b813567ffffffffffffffff808211156151f1578283fd5b9083019060808286031215615204578283fd5b60405160808101818110838211171561521957fe5b60405282358281111561522a578485fd5b615236878286016148e5565b825250615245602084016148b9565b602082015261525660408401614a61565b604082015260608301358281111561526c578485fd5b615278878286016148e5565b60608301525095945050505050565b600060608284031215615298578081fd5b6040516060810181811067ffffffffffffffff821117156152b557fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000608082840312156152ed578081fd5b6040516080810181811067ffffffffffffffff8211171561530a57fe5b604052825161531881615f16565b8152602083015163ffffffff81168114615330578283fd5b602082015260408301516bffffffffffffffffffffffff81168114615353578283fd5b604082015261536460608401614a40565b60608201529392505050565b600060608284031215615381578081fd5b6040516060810181811067ffffffffffffffff8211171561539e57fe5b806040525082518152602083015160208201526040830151614cb081615f2b565b6000602082840312156153d0578081fd5b8135611d1c81615f55565b6000602082840312156153ec578081fd5b8135611d1c81615f6a565b600060208284031215615408578081fd5b5051919050565b60008060408385031215615421578182fd5b8251915060208084015167ffffffffffffffff80821115615440578384fd5b818601915086601f830112615453578384fd5b81518181111561545f57fe5b61546c8485830201615ea0565b81815284810190848601875b848110156154f557815187016040818e03601f1901121561549757898afd5b6040516040810181811089821117156154ac57fe5b604052818a01516154bc81615f39565b81526040820151888111156154cf578b8cfd5b6154dd8f8c83860101614936565b828c0152508552509287019290870190600101615478565b50979a909950975050505050505050565b6000806000806060858703121561551b578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615540578384fd5b818701915087601f830112615553578384fd5b813581811115615561578485fd5b8860208083028501011115614c2f578485fd5b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526155c9816020860160208601615ee6565b601f01601f19169290920160200192915050565b60020b9052565b803582526020810135602083015260408101356040830152606081013560608301526080810135608083015260a081013561561e81615f6a565b62ffffff811660a0840152505050565b6001600160801b03169052565b62ffffff169052565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b9283526020830191909152604082015260600190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286811660208301528581166040830152841660608201526101e0810161577660808301615771866148b9565b615574565b615782602085016148b9565b61578f60a0840182615574565b50604084013560c0830152606084013560e083015261010060808501358184015261012060a08601358185015260c086013561014085015260e08601356101608501526157dd828701614979565b91506157ed6101808501836155dd565b6157f8818701614979565b9150506158096101a08401826155dd565b50611e566101c0830184615581565b6001600160a01b038781168252868116602083015285811660408301528416606082015282516101e0820190615852906080840190615574565b602084015161586460a0840182615574565b50604084015160c0830152606084015160e08301526080840151610100818185015260a08601519150610120828186015260c087015161014086015260e08701516101608601528187015192506158bf6101808601846155dd565b860151915061580990506101a08401826155dd565b60006101a0820190506001600160a01b03808a1683528089166020840152808816604084015280871660608401528560808401528085511660a084015250602084015160c0830152604084015160e08301526060840151610100830152608084015161012083015260a084015161014083015260c0840151610160830152615960610180830184615581565b98975050505050505050565b6000610120820190506001600160a01b0380861683528085166020840152808451166040840152506020830151606083015260408301516080830152606083015160a0830152608083015160c083015260a083015160020b60e083015260c083015160020b610100830152949350505050565b6001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a06080830152611e5660a08301846155b1565b60006001600160a01b03841682526040602083015261477f60408301846155b1565b600060e0820190506001600160a01b038516825283516020830152602084015160408301526040840151606083015260608401516001600160801b0380821660808501528060808701511660a0850152505082151560c0830152949350505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396909616865260208601949094526040850192909252600290810b60608501520b6080830152151560a082015260c00190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b918252602082015260400190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b60c08101611cbd82846155e4565b6000602082526001600160a01b03808451166020840152806020850151166040840152506040830151606083015260ff6060840151166080830152608083015160a08084015261477f60c08401826155b1565b600061018082019050823582526020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100615c62818501614a35565b615c6e8285018261562e565b5050610120615c7e818501614a35565b615c8a8285018261562e565b5050610140615c9a818501614a4b565b615ca68285018261563b565b5050610160615cb68185016148cf565b615cc282850182615581565b505092915050565b6101608101615cdc82615771856148b9565b6020830135602083015260408301356040830152606083013560608301526080830135608083015260a083013560a083015260c083013560c083015260e083013560e0830152610100808401358184015250610120615d3c818501614979565b615d48828501826155dd565b5050610140615d58818501614979565b615cc2828501826155dd565b600060208252825160806020840152615d8060a08401826155b1565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f19848303016080850152613b9f82826155b1565b90815260200190565b6000604080830186845260208281860152818683526060860190506060828802870101925087855b88811015615e9157878503605f190183528135368b9003603e19018112615e13578788fd5b8a018035615e2081615f39565b60088110615e2a57fe5b86528085013536829003601e19018112615e42578889fd5b8101803567ffffffffffffffff811115615e5a57898afd5b803603831315615e6857898afd5b8887890152615e7c89890182898501615587565b97505050928401925090830190600101615dee565b50929998505050505050505050565b60405181810167ffffffffffffffff81118282101715615ebc57fe5b604052919050565b600067ffffffffffffffff821115615ed857fe5b50601f01601f191660200190565b60005b83811015615f01578181015183820152602001615ee9565b83811115615f10576000848401525b50505050565b6001600160a01b0381168114611c5e57600080fd5b8015158114611c5e57600080fd5b60088110611c5e57600080fd5b8060020b8114611c5e57600080fd5b6001600160801b0381168114611c5e57600080fd5b62ffffff81168114611c5e57600080fd5b60ff81168114611c5e57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220564c27264bc33c078d9c75afb2f26fb0c092712e686cacc101aaeee9df569b6e64736f6c63430007060033\",\n  \"libraries\": {\n    \"ControllerHelperUtil\": \"0x7a29594866CF3383555b8e051C80142e86d1058C\"\n  },\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\": {\n        \"details\": \"user should approve this contract for Uni NFT transfer\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.CloseShortWithUserNftParams struct\"\n        }\n      },\n      \"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"details\": \"sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\"\n        }\n      },\n      \"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"details\": \"flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.FlashSellLongWMintParams struct\"\n        }\n      },\n      \"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"details\": \"this function\",\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\"\n        }\n      },\n      \"onERC721Received(address,address,uint256,bytes)\": {\n        \"details\": \"accept erc721 from safeTransferFrom and safeMint after callback\",\n        \"returns\": {\n          \"_0\": \"returns received selector\"\n        }\n      },\n      \"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\": {\n        \"params\": {\n          \"_collateralToFlashloan\": \"collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\",\n          \"_params\": \"array of ControllerHelperDataType.RebalanceLpInVaultParams structs\",\n          \"_vaultId\": \"vault ID\"\n        }\n      },\n      \"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\": {\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\"\n        }\n      },\n      \"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\": {\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.ReduceLiquidityAndSellParams struct\"\n        }\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"params\": {\n          \"_data\": \"callback data encoded as SwapCallbackData struct\",\n          \"amount0Delta\": \"amount of token0\",\n          \"amount1Delta\": \"amount of token1\"\n        }\n      },\n      \"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"params\": {\n          \"_params\": \"ControllerHelperDataType.MintAndLpParams struct\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"closeShortWithUserNft((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint128,uint128,uint24,bool))\": {\n        \"notice\": \"close short position with user Uniswap v3 LP NFT\"\n      },\n      \"flashloanWMintLpDepositNft((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"notice\": \"FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\"\n      },\n      \"flashswapSellLongWMint((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"notice\": \"sell long wPowerPerp and flashswap mint short position\"\n      },\n      \"flashswapWBurnBuyLong((uint256,uint256,uint256,uint256,uint256,uint24))\": {\n        \"notice\": \"flash close position and buy long squeeth\"\n      },\n      \"rebalanceLpInVault(uint256,uint256,(uint8,bytes)[])\": {\n        \"notice\": \"Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\"\n      },\n      \"rebalanceLpWithoutVault((address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24,uint24))\": {\n        \"notice\": \"Rebalance LP nft through trading\"\n      },\n      \"reduceLiquidityAndSell((uint256,uint256,uint256,uint128,uint128,uint256,uint24))\": {\n        \"notice\": \"sell all LP wPowerPerp amounts to WETH and send back to user\"\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"notice\": \"uniswap swap callback function for flashswap\"\n      },\n      \"wMintLp((address,address,uint256,uint256,uint256,uint256,uint256,uint256,int24,int24))\": {\n        \"notice\": \"mint WPowerPerp and LP into Uniswap v3 pool\"\n      }\n    },\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/ControllerHelperUtil.json",
    "content": "{\n  \"address\": \"0x7a29594866CF3383555b8e051C80142e86d1058C\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wPowerPerpPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_collateralToLp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"_lowerTick\",\n          \"type\": \"int24\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"_upperTick\",\n          \"type\": \"int24\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_isWethToken0\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getAmountsToLp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x3632295f5be02b04f26e81a63f926a317f12bd7c3413c2e4a75e0f73966d3288\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0x7a29594866CF3383555b8e051C80142e86d1058C\",\n    \"transactionIndex\": 2,\n    \"gasUsed\": \"2335019\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x5b0259a9e9b44aa88b2b8d531716880bd513e6ddef57918f173087814ecb73e7\",\n    \"transactionHash\": \"0x3632295f5be02b04f26e81a63f926a317f12bd7c3413c2e4a75e0f73966d3288\",\n    \"logs\": [],\n    \"blockNumber\": 12344832,\n    \"cumulativeGasUsed\": \"2424233\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"fc32ed9e00a9017e491333926bef5473\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wPowerPerpPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_collateralToLp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"_lowerTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"_upperTick\\\",\\\"type\\\":\\\"int24\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_isWethToken0\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getAmountsToLp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_collateralToWithdraw\\\":\\\"amount of collateral to withdraw\\\",\\\"_controller\\\":\\\"controller address\\\",\\\"_vaultId\\\":\\\"vault Id\\\",\\\"_wPowerPerpToBurn\\\":\\\"amount of wPowerPerp to burn\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"checkClosedLp(address,address,address,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\",\\\"_liquidityPercentage\\\":\\\"percentage of liquidity that was closed from total amount\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_tokenId\\\":\\\"Uni LP NFT id\\\",\\\"_user\\\":\\\"user address\\\",\\\"_vaultId\\\":\\\"vault ID\\\"}},\\\"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\\\":{\\\"params\\\":{\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_params\\\":\\\"ControllerHelperDataType.CloseUniLpParams struct \\\"},\\\"returns\\\":{\\\"_0\\\":\\\"withdrawn wPowerPerp and WETH amounts\\\"}},\\\"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\\\":{\\\"params\\\":{\\\"_collateralToLp\\\":\\\"amount of ETH collateral to LP\\\",\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_lowerTick\\\":\\\"LP position lower tick\\\",\\\"_upperTick\\\":\\\"LP position upper tick\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to LP\\\",\\\"_wPowerPerpPool\\\":\\\"wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"exact amount0 and amount1 to be LPed\\\"}},\\\"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\",\\\"_increaseLiquidityParam\\\":\\\"ControllerHelperDataType.IncreaseLpLiquidityParams struct\\\",\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_vaultId\\\":\\\"vault Id\\\"}},\\\"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\\\":{\\\"params\\\":{\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\",\\\"_params\\\":\\\"ControllerHelperDataType.LpWPowerPerpPoolParams struct\\\",\\\"_wPowerPerpPool\\\":\\\"wPowerpPerp pool address in Uni v3\\\"}},\\\"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"wPowerPerp controller address\\\",\\\"_isWethToken0\\\":\\\"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\",\\\"_mintAndLpParams\\\":\\\"ControllerHelperDataType.MintAndLpParams struct\\\",\\\"_nonfungiblePositionManager\\\":\\\"Uni NonFungiblePositionManager address\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"_vaultId and tokenId\\\"}},\\\"mintDepositInVault(address,address,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_collateralToDeposit\\\":\\\"amount of collateral to deposit\\\",\\\"_controller\\\":\\\"controller address\\\",\\\"_vaultId\\\":\\\"vault Id\\\",\\\"_wPowerPerpToMint\\\":\\\"amount of wPowerPerp to mint\\\",\\\"_weth\\\":\\\"WETH address\\\"}},\\\"sendBack(address,address)\\\":{\\\"params\\\":{\\\"_wPowerPerp\\\":\\\"wPowerPerp address\\\",\\\"_weth\\\":\\\"WETH address\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"burn wPowerPerp or just withdraw collateral from vault (or both)\\\"},\\\"checkClosedLp(address,address,address,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\\"},\\\"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\\\":{\\\"notice\\\":\\\"fully or partially close Uni v3 LP\\\"},\\\"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\\\":{\\\"notice\\\":\\\"get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\\"},\\\"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\\\":{\\\"notice\\\":\\\"increase liquidityin Uni v3 position\\\"},\\\"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\\\":{\\\"notice\\\":\\\"LP into Uniswap V3 pool\\\"},\\\"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\\\":{\\\"notice\\\":\\\"minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\\"},\\\"mintDepositInVault(address,address,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"mint wPowerPerp in vault\\\"},\\\"sendBack(address,address)\\\":{\\\"notice\\\":\\\"send ETH and wPowerPerp\\\"}},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/periphery/lib/ControllerHelperUtil.sol\\\":\\\"ControllerHelperUtil\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/lib/ControllerHelperDataType.sol\\\":{\\\"content\\\":\\\"pragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperDataType {\\\\n    using SafeMath for uint256;\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum CALLBACK_SOURCE {\\\\n        FLASH_W_MINT,\\\\n        FLASH_W_BURN,\\\\n        FLASH_SELL_LONG_W_MINT,\\\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\\\n        GENERAL_SWAP\\\\n    }\\\\n\\\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\\\n    enum RebalanceVaultNftType {\\\\n        IncreaseLpLiquidity,\\\\n        DecreaseLpLiquidity,\\\\n        DepositIntoVault,\\\\n        WithdrawFromVault,\\\\n        MintNewLp,\\\\n        generalSwap,\\\\n        CollectFees, \\\\n        DepositExistingNft\\\\n    }\\\\n    \\\\n    /// @dev params for flashswapWBurnBuyLong()\\\\n    struct FlashswapWBurnBuyLongParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\\\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev params for flashswapSellLongWMint()\\\\n    struct FlashSellLongWMintParams {\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n    }\\\\n\\\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\\\n    struct SwapExactoutEthWPowerPerpData {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\\\n    }\\\\n\\\\n    /// @dev params for CloseShortWithUserNft()\\\\n    struct CloseShortWithUserNftParams {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity;  // liquidity amount in LP \\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;      // uniswap pool fee\\\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for wMintLp()\\\\n    struct MintAndLpParams {\\\\n        address recipient;  // recipient address\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 vaultId;    // vault ID\\\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 collateralToLp; // collateral amount to LP\\\\n        uint256 amount0Min; // minimum amount to LP of asset0\\\\n        uint256 amount1Min; // minimum amount to LP of asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for flashloanWMintDepositNft()\\\\n    struct FlashloanWMintLpDepositNftParams {\\\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\\\n        uint256 vaultId; // vault ID (could be zero)\\\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\\\n        uint256 amount0Min; // minimum amount of token0 to LP\\\\n        uint256 amount1Min; // minimum amount of token1 to LP\\\\n        int24 lowerTick; // range lower tick to LP in\\\\n        int24 upperTick; // range upper tick to LP in\\\\n    }\\\\n\\\\n    /// @dev params for flashloanCloseVaultLpNft()\\\\n    struct FlashloanCloseVaultLpNftParam {\\\\n        uint256 vaultId; // vault ID\\\\n        uint256 tokenId; // Uni NFT token ID\\\\n        uint256 liquidity; // amount of liquidity in LP position\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint24 poolFee;     // uniswap pool fee\\\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\\\n    }\\\\n\\\\n    /// @dev params for _closeUniLp() \\\\n    struct CloseUniLpParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\\\n    }\\\\n\\\\n    /// @dev params for sellAll()\\\\n    struct ReduceLiquidityAndSellParams {\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpWithoutVault()\\\\n    struct RebalanceLpWithoutVaultParams {\\\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\\\n        uint256 tokenId;    // Uni token ID\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\\\n        uint256 wethAmountDesired;  // WETH amount to LP\\\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\\\n    struct LpWPowerPerpPoolParams {\\\\n        address recipient;  // recipient address\\\\n        uint256 amount0Desired; // amount desired to LP for asset0\\\\n        uint256 amount1Desired; // amount desired to LP for asset1\\\\n        uint256 amount0Min; // amount min to LP for asset0\\\\n        uint256 amount1Min; // amount min to LP for asset1\\\\n        int24 lowerTick;    // LP lower tick\\\\n        int24 upperTick;    // LP upper tick\\\\n    }\\\\n\\\\n    /// @dev params for rebalanceLpInVault()\\\\n    struct RebalanceLpInVaultParams {\\\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\\\n        bytes data;\\\\n    }\\\\n\\\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\\\n    struct IncreaseLpLiquidityParams {\\\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\\\n        uint256 wethAmountToLp; // WETH amount to LP\\\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for decrease liquidity in LP position\\\\n    struct DecreaseLpLiquidityParams {  \\\\n        uint256 tokenId;    // Uni v3 NFT token id\\\\n        uint256 liquidity;  // LP liquidity amount\\\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\\\n    }\\\\n\\\\n    /// @dev struct for minting into vault\\\\n    struct DepositIntoVaultParams {\\\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\\\n    }\\\\n\\\\n    /// @dev struct for withdrawing from vault\\\\n    struct withdrawFromVaultParams {  \\\\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\\\n    }\\\\n\\\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\\\n    struct GeneralSwapParams {\\\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\\\n        uint256 amountIn; // amount to swap in\\\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\\\n    }\\\\n\\\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\\\n    struct CollectFeesParams {\\\\n        uint256 tokenId;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\\\n    struct DepositExistingNftParams {\\\\n        uint256 tokenId;    // Uni v3 NFT id\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x04a47d47c3e0a1ec4e834f9aa466960200084fbdee47f0f513990b2c4708b02a\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/ControllerHelperUtil.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ControllerHelperDataType} from \\\\\\\"./ControllerHelperDataType.sol\\\\\\\";\\\\nimport {LiquidityAmounts} from \\\\\\\"./LiquidityAmounts.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"../../libs/TickMathExternal.sol\\\\\\\";\\\\n\\\\nlibrary ControllerHelperUtil {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /**\\\\n     * @notice fully or partially close Uni v3 LP\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return withdrawn wPowerPerp and WETH amounts\\\\n     */\\\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\\\n            .DecreaseLiquidityParams({\\\\n                tokenId: _params.tokenId,\\\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\\\n                amount0Min: _params.amount0Min,\\\\n                amount1Min: _params.amount1Min,\\\\n                deadline: block.timestamp\\\\n            });\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\\\n\\\\n        uint256 wethAmount;\\\\n        uint256 _wPowerPerpAmount;\\\\n        (_isWethToken0)\\\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n                INonfungiblePositionManager.CollectParams({\\\\n                    tokenId: _params.tokenId,\\\\n                    recipient: address(this),\\\\n                    amount0Max: type(uint128).max,\\\\n                    amount1Max: type(uint128).max\\\\n                })\\\\n            )\\\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\\\n            INonfungiblePositionManager.CollectParams({\\\\n                tokenId: _params.tokenId,\\\\n                recipient: address(this),\\\\n                amount0Max: type(uint128).max,\\\\n                amount1Max: type(uint128).max\\\\n            })\\\\n        );\\\\n\\\\n        return (_wPowerPerpAmount, wethAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\\\n     * @param _collateralToLp amount of ETH collateral to LP\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\\\n     * @param _lowerTick LP position lower tick\\\\n     * @param _upperTick LP position upper tick\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return exact amount0 and amount1 to be LPed\\\\n     */\\\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\\\n        uint256 amount0Desired; \\\\n        uint256 amount1Desired;\\\\n\\\\n        {\\\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\\\n        }\\\\n        \\\\n        return (amount0Desired, amount1Desired);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\\\n     * @param _controller wPowerPerp controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     * @return _vaultId and tokenId\\\\n     */\\\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\\\n\\\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\\\n                \\\\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\\\n                _mintAndLpParams.vaultId,\\\\n                amountToMint,\\\\n                0\\\\n            );\\\\n        }\\\\n        // LP amount0Desired and amount1Desired in Uni v3\\\\n        uint256 uniTokenId = lpWPowerPerpPool(\\\\n            _nonfungiblePositionManager,\\\\n            _mintAndLpParams.wPowerPerpPool,\\\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\\\n                recipient: _mintAndLpParams.recipient,\\\\n                amount0Desired: amount0Desired,\\\\n                amount1Desired: amount1Desired,\\\\n                amount0Min: _mintAndLpParams.amount0Min,\\\\n                amount1Min: _mintAndLpParams.amount1Min,\\\\n                lowerTick: _mintAndLpParams.lowerTick,\\\\n                upperTick: _mintAndLpParams.upperTick\\\\n            })\\\\n        );\\\\n        return (_vaultId, uniTokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice increase liquidityin Uni v3 position\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault Id\\\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\\\n     */\\\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\\\n            (\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                int24 tickLower,\\\\n                int24 tickUpper,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                ,\\\\n                \\\\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\\\n\\\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n\\\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\\\n                    _vaultId,\\\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\\\n                    0\\\\n                );\\\\n            }\\\\n        }\\\\n\\\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\\\n            tokenId: _increaseLiquidityParam.tokenId,\\\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\\\n            deadline: block.timestamp\\\\n        });\\\\n\\\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp in vault\\\\n     * @param _controller controller address\\\\n     * @param _weth WETH address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\\\n     * @param _collateralToDeposit amount of collateral to deposit\\\\n     */\\\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\\\n\\\\n        uint256 vaultId = _vaultId;\\\\n        if (_wPowerPerpToMint > 0) {\\\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\\\n                _vaultId,\\\\n                _wPowerPerpToMint,\\\\n                0\\\\n            );\\\\n        } else {\\\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\\\n        }\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\\\n     * @param _controller controller address\\\\n     * @param _weth weth address\\\\n     * @param _vaultId vault Id\\\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     */\\\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\\\n        IController(_controller).burnWPowerPerpAmount(\\\\n            _vaultId,\\\\n            _wPowerPerpToBurn,\\\\n            _collateralToWithdraw\\\\n        );\\\\n\\\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice LP into Uniswap V3 pool\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\\\n     */\\\\n    function lpWPowerPerpPool(\\\\n        address _nonfungiblePositionManager,\\\\n        address _wPowerPerpPool,\\\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\\\n    ) public returns (uint256) {\\\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\\\n            tickLower: int24(_params.lowerTick),\\\\n            tickUpper: int24(_params.upperTick),\\\\n            amount0Desired: _params.amount0Desired,\\\\n            amount1Desired: _params.amount1Desired,\\\\n            amount0Min: _params.amount0Min,\\\\n            amount1Min: _params.amount1Min,\\\\n            recipient: _params.recipient,\\\\n            deadline: block.timestamp\\\\n        });\\\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\\\n            mintParams\\\\n        );\\\\n        return tokenId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\\\n     * @param _user user address\\\\n     * @param _controller controller address\\\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\\\n     * @param _vaultId vault ID\\\\n     * @param _tokenId Uni LP NFT id\\\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\\\n     */\\\\n    function checkClosedLp(\\\\n        address _user,\\\\n        address _controller,\\\\n        address _nonfungiblePositionManager,\\\\n        uint256 _vaultId,\\\\n        uint256 _tokenId,\\\\n        uint256 _liquidityPercentage\\\\n    ) public {\\\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\\\n                address(this),\\\\n                _user,\\\\n                _tokenId\\\\n            );\\\\n        } else {\\\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice send ETH and wPowerPerp\\\\n     * @param _weth WETH address\\\\n     * @param _wPowerPerp wPowerPerp address\\\\n     */\\\\n    function sendBack(address _weth, address _wPowerPerp) public {\\\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\\\n        if (wPowerPerpBalance > 0) {\\\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x51c6185083d747a36ee8543219c0e7a326b866c0bdc113e82956cd4e226f7ba3\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/periphery/lib/LiquidityAmounts.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"../../libs/SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\n\\\\n\\\\n/// @title Liquidity amount functions\\\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\\\nlibrary LiquidityAmounts {\\\\n    /// @notice Downcasts uint256 to uint128\\\\n    /// @param x The uint258 to be downcasted\\\\n    /// @return y The passed value, downcasted to uint128\\\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\\\n        require((y = uint128(x)) == x);\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount0 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount0(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount1 The amount1 being sent in\\\\n    /// @return liquidity The amount of returned liquidity\\\\n    function getLiquidityForAmount1(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\\\n    }\\\\n\\\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param amount0 The amount of token0 being sent in\\\\n    /// @param amount1 The amount of token1 being sent in\\\\n    /// @return liquidity The maximum amount of liquidity received\\\\n    function getLiquidityForAmounts(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    ) internal pure returns (uint128 liquidity) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\\\n\\\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\\\n        } else {\\\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\\\n        }\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    function getAmount0ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            FullMath.mulDiv(\\\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\\\n                sqrtRatioBX96 - sqrtRatioAX96,\\\\n                sqrtRatioBX96\\\\n            ) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmount1ForLiquidity(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n\\\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\\\n    /// pool prices and the prices at the tick boundaries\\\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\\\n    /// @param liquidity The liquidity being valued\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function getAmountsForLiquidity(\\\\n        uint160 sqrtRatioX96,\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\\\n        } else {\\\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\\\n        }\\\\n    }\\\\n\\\\n    function getAmountsFromLiquidity(        \\\\n        uint160 sqrtRatioX96,\\\\n        int24 currentTick,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        if (currentTick < tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else if (currentTick < tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtRatioX96,\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                sqrtRatioX96,\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMath.getSqrtRatioAtTick(tickLower),\\\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\\\n                liquidity,\\\\n                false\\\\n            );\\\\n            }\\\\n    \\\\n    }\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb4b0f464529a43f3ca7a9d6afc5976902c0a004649bdf3239ca77469d26b7cf2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x61294e610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100ad5760003560e01c80638e6940f011610080578063aee2533b11610065578063aee2533b14610198578063b573fa8b146101b8578063ec147e56146101cb576100ad565b80638e6940f0146101345780639f70f9e51461016b576100ad565b8063392f2708146100b257806351764a5e146100d457806363410a86146100f45780637a04dbd714610114575b600080fd5b8180156100be57600080fd5b506100d26100cd366004612153565b6101eb565b005b8180156100e057600080fd5b506100d26100ef366004611f91565b6102d4565b81801561010057600080fd5b506100d261010f366004612282565b6104c1565b81801561012057600080fd5b506100d261012f366004612056565b61056e565b81801561014057600080fd5b5061015461014f366004611fc9565b610865565b60405161016292919061284f565b60405180910390f35b81801561017757600080fd5b5061018b610186366004612282565b610b78565b6040516101629190612846565b8180156101a457600080fd5b5061018b6101b33660046121b7565b610cdf565b6101546101c636600461237c565b610f52565b8180156101d757600080fd5b506101546101e63660046122d2565b6111bd565b8215806101ff575080670de0b6b3a7640000145b1561026b57604051632142170760e11b81526001600160a01b038516906342842e0e906102349030908a90879060040161269c565b600060405180830381600087803b15801561024e57600080fd5b505af1158015610262573d6000803e3d6000fd5b505050506102cc565b6040516348dc69a560e11b81526001600160a01b038616906391b8d34a90610299908690869060040161284f565b600060405180830381600087803b1580156102b357600080fd5b505af11580156102c7573d6000803e3d6000fd5b505050505b505050505050565b6040516370a0823160e01b81526001600160a01b03831690632e1a7d4d9082906370a082319061030890309060040161266f565b60206040518083038186803b15801561032057600080fd5b505afa158015610334573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035891906124fb565b6040518263ffffffff1660e01b81526004016103749190612846565b600060405180830381600087803b15801561038e57600080fd5b505af11580156103a2573d6000803e3d6000fd5b506103b39250339150479050611424565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906103e290309060040161266f565b60206040518083038186803b1580156103fa57600080fd5b505afa15801561040e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043291906124fb565b905080156104bc5760405163a9059cbb60e01b81526001600160a01b0383169063a9059cbb906104689033908590600401612683565b602060405180830381600087803b15801561048257600080fd5b505af1158015610496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ba91906123dd565b505b505050565b604051638632cb0360e01b81526001600160a01b03861690638632cb03906104f19086908690869060040161285d565b600060405180830381600087803b15801561050b57600080fd5b505af115801561051f573d6000803e3d6000fd5b50505050600081111561056757836001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156102b357600080fd5b5050505050565b60408201511561077557600080876001600160a01b03166399fbab8885602001516040518263ffffffff1660e01b81526004016105ab9190612846565b6101806040518083038186803b1580156105c457600080fd5b505afa1580156105d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fc9190612573565b5050505050965096505050505050600080610623888760800151886040015187878a610f52565b9150915084610633578181610636565b80825b6080880152604080880191909152516370a0823160e01b81526000906001600160a01b038b16906370a082319061067190309060040161266f565b60206040518083038186803b15801561068957600080fd5b505afa15801561069d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c191906124fb565b9050866040015181101561076f578b6001600160a01b0316633946791888606001518a6106fb858c6040015161150990919063ffffffff16565b60006040518563ffffffff1660e01b815260040161071b9392919061285d565b6020604051808303818588803b15801561073457600080fd5b505af1158015610748573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061076d91906124fb565b505b50505050505b60006040518060c00160405280846020015181526020018361079b5784604001516107a1565b84608001515b8152602001836107b55784608001516107bb565b84604001515b81526020018460a0015181526020018460c001518152602001428152509050866001600160a01b031663219f5d17826040518263ffffffff1660e01b81526004016108069190612754565b606060405180830381600087803b15801561082057600080fd5b505af1158015610834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108589190612415565b5050505050505050505050565b600080846001600160a01b0316632e1a7d4d85608001356040518263ffffffff1660e01b81526004016108989190612846565b600060405180830381600087803b1580156108b257600080fd5b505af11580156108c6573d6000803e3d6000fd5b505050506000806109178660200160208101906108e39190611f59565b60a088013560608901356108ff6101208b016101008c016123f9565b6109116101408c016101208d016123f9565b8a610f52565b9092509050604086013560008661092e5783610930565b825b9050808a6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161095f919061266f565b60206040518083038186803b15801561097757600080fd5b505afa15801561098b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109af91906124fb565b1015610acd576040516370a0823160e01b8152610a3c906001600160a01b038c16906370a08231906109e590309060040161266f565b60206040518083038186803b1580156109fd57600080fd5b505afa158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3591906124fb565b8290611509565b90508b6001600160a01b0316633946791889608001358a604001358460006040518563ffffffff1660e01b8152600401610a789392919061285d565b6020604051808303818588803b158015610a9157600080fd5b505af1158015610aa5573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610aca91906124fb565b91505b6000610b648c610ae360408c0160208d01611f59565b6040805160e0810190915280610afc60208f018f611f59565b6001600160a01b031681526020018981526020018881526020018d60c0013581526020018d60e0013581526020018d610100016020810190610b3e91906123f9565b60020b81526020018d610120016020810190610b5a91906123f9565b60020b9052610cdf565b929d929c50919a5050505050505050505050565b60008115610bdf57604051632e1a7d4d60e01b81526001600160a01b03861690632e1a7d4d90610bac908590600401612846565b600060405180830381600087803b158015610bc657600080fd5b505af1158015610bda573d6000803e3d6000fd5b505050505b838315610c7257604051630728cf2360e31b81526001600160a01b038816906339467918908590610c19908990899060009060040161285d565b6020604051808303818588803b158015610c3257600080fd5b505af1158015610c46573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610c6b91906124fb565b9050610cd3565b60405163b6b55f2560e01b81526001600160a01b0388169063b6b55f25908590610ca0908990600401612846565b6000604051808303818588803b158015610cb957600080fd5b505af1158015610ccd573d6000803e3d6000fd5b50505050505b90505b95945050505050565b600080604051806101600160405280856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d2757600080fd5b505afa158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f9190611f75565b6001600160a01b03168152602001856001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610da657600080fd5b505afa158015610dba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dde9190611f75565b6001600160a01b03168152602001856001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610e2557600080fd5b505afa158015610e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5d91906124e1565b62ffffff1681526020018460a0015160020b81526020018460c0015160020b81526020018460200151815260200184604001518152602001846060015181526020018460800151815260200184600001516001600160a01b031681526020014281525090506000856001600160a01b03166388316456836040518263ffffffff1660e01b8152600401610ef09190612798565b608060405180830381600087803b158015610f0a57600080fd5b505af1158015610f1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f429190612513565b50919450505050505b9392505050565b60008060008060008a6001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610f9357600080fd5b505afa158015610fa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcb919061244b565b50505050509150506000730772382Dd7D99adb5218d31fAdfE1c68c847733563986cfba3836040518263ffffffff1660e01b815260040161100c91906126c0565b60206040518083038186803b15801561102457600080fd5b505af4158015611038573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105c9190611f75565b90506000730772382Dd7D99adb5218d31fAdfE1c68c847733563986cfba38b6040518263ffffffff1660e01b815260040161109791906126c0565b60206040518083038186803b1580156110af57600080fd5b505af41580156110c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e79190611f75565b90506000730772382Dd7D99adb5218d31fAdfE1c68c847733563986cfba38b6040518263ffffffff1660e01b815260040161112291906126c0565b60206040518083038186803b15801561113a57600080fd5b505af415801561114e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111729190611f75565b905088611180578b8d611183565b8c8c5b909650945060006111978484848a8a61156b565b90506111a684868e8e85611623565b909950975050505050505050965096945050505050565b60008060006040518060a0016040528086600001518152602001611204670de0b6b3a76400006111fe89604001518a6020015161196490919063ffffffff16565b906119bd565b6001600160801b0316815260200186606001516001600160801b0316815260200186608001516001600160801b03168152602001428152509050856001600160a01b0316630c49ccbe826040518263ffffffff1660e01b815260040161126a9190612711565b6040805180830381600087803b15801561128357600080fd5b505af1158015611297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bb9190612550565b5050600080856113705760408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f78659161131691906004016126ce565b6040805180830381600087803b15801561132f57600080fd5b505af1158015611343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113679190612550565b92509050611418565b60408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f7865916113c191906004016126ce565b6040805180830381600087803b1580156113da57600080fd5b505af11580156113ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114129190612550565b90925090505b97909650945050505050565b80471015611479576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146114c4576040519150601f19603f3d011682016040523d82523d6000602084013e6114c9565b606091505b50509050806104bc5760405162461bcd60e51b815260040180806020018281038252603a8152602001806128be603a913960400191505060405180910390fd5b600082821115611560576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000836001600160a01b0316856001600160a01b0316111561158b579293925b846001600160a01b0316866001600160a01b0316116115b6576115af858585611a24565b9050610cd6565b836001600160a01b0316866001600160a01b031610156116185760006115dd878686611a24565b905060006115ec878986611a90565b9050806001600160801b0316826001600160801b03161061160d578061160f565b815b92505050610cd6565b610cd3858584611a90565b6000808460020b8660020b12156116fc5773565483126A5fC6004455F4e11014C442A61D740c632c32d4b661165787611ade565b61166087611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b1580156116c957600080fd5b505af41580156116dd573d6000803e3d6000fd5b505050506040513d60208110156116f357600080fd5b5051915061195a565b8360020b8660020b12156118965773565483126A5fC6004455F4e11014C442A61D740c632c32d4b68861172e87611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561179757600080fd5b505af41580156117ab573d6000803e3d6000fd5b505050506040513d60208110156117c157600080fd5b5051915073565483126A5fC6004455F4e11014C442A61D740c6348a0c5bd6117e887611ade565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039283166004820152918b1660248301526001600160801b038716604483015260006064830152516084808301926020929190829003018186803b15801561186357600080fd5b505af4158015611877573d6000803e3d6000fd5b505050506040513d602081101561188d57600080fd5b5051905061195a565b73565483126A5fC6004455F4e11014C442A61D740c6348a0c5bd6118b987611ade565b6118c287611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561192b57600080fd5b505af415801561193f573d6000803e3d6000fd5b505050506040513d602081101561195557600080fd5b505190505b9550959350505050565b60008261197357506000611565565b8282028284828161198057fe5b0414610f4b5760405162461bcd60e51b81526004018080602001828103825260218152602001806128f86021913960400191505060405180910390fd5b6000808211611a13576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611a1c57fe5b049392505050565b6000826001600160a01b0316846001600160a01b03161115611a44579192915b6000611a70856001600160a01b0316856001600160a01b03166c01000000000000000000000000611e1d565b9050610cd6611a8b84838888036001600160a01b0316611e1d565b611ecc565b6000826001600160a01b0316846001600160a01b03161115611ab0579192915b611ad6611a8b836c010000000000000000000000008787036001600160a01b0316611e1d565b949350505050565b60008060008360020b12611af5578260020b611afd565b8260020b6000035b9050620d89e8811115611b3b576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216611b5c57700100000000000000000000000000000000611b6e565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615611ba2576ffff97272373d413259a46990580e213a0260801c5b6004821615611bc1576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615611be0576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615611bff576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615611c1e576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615611c3d576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615611c5c576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615611c7c576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615611c9c576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615611cbc576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615611cdc576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615611cfc576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615611d1c576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615611d3c576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615611d5c576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615611d7d576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615611d9d576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615611dbc576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615611dd9576b048a170391f7dc42444e8fa20260801c5b60008460020b1315611df4578060001981611df057fe5b0490505b640100000000810615611e08576001611e0b565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080611e535760008411611e4857600080fd5b508290049050610f4b565b808411611e5f57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b806001600160801b0381168114611ee257600080fd5b919050565b8035611ee281612873565b8051611ee281612873565b8035611ee28161288b565b8035611ee281612899565b8051611ee281612899565b8035611ee2816128a8565b8051611ee2816128a8565b805161ffff81168114611ee257600080fd5b805162ffffff81168114611ee257600080fd5b600060208284031215611f6a578081fd5b8135610f4b81612873565b600060208284031215611f86578081fd5b8151610f4b81612873565b60008060408385031215611fa3578081fd5b8235611fae81612873565b91506020830135611fbe81612873565b809150509250929050565b6000806000806000808688036101e0811215611fe3578283fd5b8735611fee81612873565b96506020880135611ffe81612873565b9550604088013561200e81612873565b9450606088013561201e81612873565b9350610140607f1982011215612032578283fd5b506080870191506101c08701356120488161288b565b809150509295509295509295565b60008060008060008060008789036101a0811215612072578182fd5b883561207d81612873565b9750602089013561208d81612873565b9650604089013561209d81612873565b955060608901356120ad81612873565b94506080890135935060e0609f19820112156120c7578182fd5b5060405160e0810181811067ffffffffffffffff821117156120e557fe5b6040526120f460a08a01611ee7565b815260c089810135602083015260e08a013560408301526101008a013560608301526101208a013560808301526101408a013560a08301526101608a01359082015291506121456101808901611efd565b905092959891949750929550565b60008060008060008060c0878903121561216b578384fd5b863561217681612873565b9550602087013561218681612873565b9450604087013561219681612873565b959894975094956060810135955060808101359460a0909101359350915050565b60008060008385036101208112156121cd578182fd5b84356121d881612873565b935060208501356121e881612873565b925060e0603f19820112156121fb578182fd5b5060405160e0810181811067ffffffffffffffff8211171561221957fe5b806040525061222a60408601611ee7565b8152606085013560208201526080850135604082015260a0850135606082015260c0850135608082015261226060e08601611f08565b60a08201526122726101008601611f08565b60c0820152809150509250925092565b600080600080600060a08688031215612299578283fd5b85356122a481612873565b945060208601356122b481612873565b94979496505050506040830135926060810135926080909101359150565b600080600083850360e08112156122e7578182fd5b84356122f281612873565b935060a0601f1982011215612305578182fd5b5060405160a0810181811067ffffffffffffffff8211171561232357fe5b806040525060208501358152604085013560208201526060850135604082015261234f60808601611f1e565b606082015261236060a08601611f1e565b6080820152915061237360c08501611efd565b90509250925092565b60008060008060008060c08789031215612394578384fd5b863561239f81612873565b9550602087013594506040870135935060608701356123bd81612899565b925060808701356123cd81612899565b915060a08701356120488161288b565b6000602082840312156123ee578081fd5b8151610f4b8161288b565b60006020828403121561240a578081fd5b8135610f4b81612899565b600080600060608486031215612429578081fd5b8351612434816128a8565b602085015160409095015190969495509392505050565b600080600080600080600060e0888a031215612465578081fd5b875161247081612873565b602089015190975061248181612899565b955061248f60408901611f34565b945061249d60608901611f34565b93506124ab60808901611f34565b925060a088015160ff811681146124c0578182fd5b60c08901519092506124d18161288b565b8091505092959891949750929550565b6000602082840312156124f2578081fd5b610f4b82611f46565b60006020828403121561250c578081fd5b5051919050565b60008060008060808587031215612528578182fd5b84519350602085015161253a816128a8565b6040860151606090960151949790965092505050565b60008060408385031215612562578182fd5b505080516020909101519092909150565b6000806000806000806000806000806000806101808d8f031215612595578586fd5b8c516bffffffffffffffffffffffff811681146125b0578687fd5b9b506125be60208e01611ef2565b9a506125cc60408e01611ef2565b99506125da60608e01611ef2565b98506125e860808e01611f46565b97506125f660a08e01611f13565b965061260460c08e01611f13565b955061261260e08e01611f29565b94506101008d015193506101208d015192506126316101408e01611f29565b91506126406101608e01611f29565b90509295989b509295989b509295989b565b6001600160a01b03169052565b60020b9052565b62ffffff169052565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60029190910b815260200190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6000610160820190506127ac828451612652565b60208301516127be6020840182612652565b5060408301516127d16040840182612666565b5060608301516127e4606084018261265f565b5060808301516127f7608084018261265f565b5060a083015160a083015260c083015160c083015260e083015160e08301526101008084015181840152506101208084015161283582850182612652565b505061014092830151919092015290565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b6001600160a01b038116811461288857600080fd5b50565b801515811461288857600080fd5b8060020b811461288857600080fd5b6001600160801b038116811461288857600080fdfe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220cfb89b72f5833964391283454a5a095d88e171c58035cad9299687278c762ec164736f6c63430007060033\",\n  \"deployedBytecode\": \"0x73000000000000000000000000000000000000000030146080604052600436106100ad5760003560e01c80638e6940f011610080578063aee2533b11610065578063aee2533b14610198578063b573fa8b146101b8578063ec147e56146101cb576100ad565b80638e6940f0146101345780639f70f9e51461016b576100ad565b8063392f2708146100b257806351764a5e146100d457806363410a86146100f45780637a04dbd714610114575b600080fd5b8180156100be57600080fd5b506100d26100cd366004612153565b6101eb565b005b8180156100e057600080fd5b506100d26100ef366004611f91565b6102d4565b81801561010057600080fd5b506100d261010f366004612282565b6104c1565b81801561012057600080fd5b506100d261012f366004612056565b61056e565b81801561014057600080fd5b5061015461014f366004611fc9565b610865565b60405161016292919061284f565b60405180910390f35b81801561017757600080fd5b5061018b610186366004612282565b610b78565b6040516101629190612846565b8180156101a457600080fd5b5061018b6101b33660046121b7565b610cdf565b6101546101c636600461237c565b610f52565b8180156101d757600080fd5b506101546101e63660046122d2565b6111bd565b8215806101ff575080670de0b6b3a7640000145b1561026b57604051632142170760e11b81526001600160a01b038516906342842e0e906102349030908a90879060040161269c565b600060405180830381600087803b15801561024e57600080fd5b505af1158015610262573d6000803e3d6000fd5b505050506102cc565b6040516348dc69a560e11b81526001600160a01b038616906391b8d34a90610299908690869060040161284f565b600060405180830381600087803b1580156102b357600080fd5b505af11580156102c7573d6000803e3d6000fd5b505050505b505050505050565b6040516370a0823160e01b81526001600160a01b03831690632e1a7d4d9082906370a082319061030890309060040161266f565b60206040518083038186803b15801561032057600080fd5b505afa158015610334573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035891906124fb565b6040518263ffffffff1660e01b81526004016103749190612846565b600060405180830381600087803b15801561038e57600080fd5b505af11580156103a2573d6000803e3d6000fd5b506103b39250339150479050611424565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906103e290309060040161266f565b60206040518083038186803b1580156103fa57600080fd5b505afa15801561040e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043291906124fb565b905080156104bc5760405163a9059cbb60e01b81526001600160a01b0383169063a9059cbb906104689033908590600401612683565b602060405180830381600087803b15801561048257600080fd5b505af1158015610496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ba91906123dd565b505b505050565b604051638632cb0360e01b81526001600160a01b03861690638632cb03906104f19086908690869060040161285d565b600060405180830381600087803b15801561050b57600080fd5b505af115801561051f573d6000803e3d6000fd5b50505050600081111561056757836001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156102b357600080fd5b5050505050565b60408201511561077557600080876001600160a01b03166399fbab8885602001516040518263ffffffff1660e01b81526004016105ab9190612846565b6101806040518083038186803b1580156105c457600080fd5b505afa1580156105d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fc9190612573565b5050505050965096505050505050600080610623888760800151886040015187878a610f52565b9150915084610633578181610636565b80825b6080880152604080880191909152516370a0823160e01b81526000906001600160a01b038b16906370a082319061067190309060040161266f565b60206040518083038186803b15801561068957600080fd5b505afa15801561069d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c191906124fb565b9050866040015181101561076f578b6001600160a01b0316633946791888606001518a6106fb858c6040015161150990919063ffffffff16565b60006040518563ffffffff1660e01b815260040161071b9392919061285d565b6020604051808303818588803b15801561073457600080fd5b505af1158015610748573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061076d91906124fb565b505b50505050505b60006040518060c00160405280846020015181526020018361079b5784604001516107a1565b84608001515b8152602001836107b55784608001516107bb565b84604001515b81526020018460a0015181526020018460c001518152602001428152509050866001600160a01b031663219f5d17826040518263ffffffff1660e01b81526004016108069190612754565b606060405180830381600087803b15801561082057600080fd5b505af1158015610834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108589190612415565b5050505050505050505050565b600080846001600160a01b0316632e1a7d4d85608001356040518263ffffffff1660e01b81526004016108989190612846565b600060405180830381600087803b1580156108b257600080fd5b505af11580156108c6573d6000803e3d6000fd5b505050506000806109178660200160208101906108e39190611f59565b60a088013560608901356108ff6101208b016101008c016123f9565b6109116101408c016101208d016123f9565b8a610f52565b9092509050604086013560008661092e5783610930565b825b9050808a6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161095f919061266f565b60206040518083038186803b15801561097757600080fd5b505afa15801561098b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109af91906124fb565b1015610acd576040516370a0823160e01b8152610a3c906001600160a01b038c16906370a08231906109e590309060040161266f565b60206040518083038186803b1580156109fd57600080fd5b505afa158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3591906124fb565b8290611509565b90508b6001600160a01b0316633946791889608001358a604001358460006040518563ffffffff1660e01b8152600401610a789392919061285d565b6020604051808303818588803b158015610a9157600080fd5b505af1158015610aa5573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610aca91906124fb565b91505b6000610b648c610ae360408c0160208d01611f59565b6040805160e0810190915280610afc60208f018f611f59565b6001600160a01b031681526020018981526020018881526020018d60c0013581526020018d60e0013581526020018d610100016020810190610b3e91906123f9565b60020b81526020018d610120016020810190610b5a91906123f9565b60020b9052610cdf565b929d929c50919a5050505050505050505050565b60008115610bdf57604051632e1a7d4d60e01b81526001600160a01b03861690632e1a7d4d90610bac908590600401612846565b600060405180830381600087803b158015610bc657600080fd5b505af1158015610bda573d6000803e3d6000fd5b505050505b838315610c7257604051630728cf2360e31b81526001600160a01b038816906339467918908590610c19908990899060009060040161285d565b6020604051808303818588803b158015610c3257600080fd5b505af1158015610c46573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610c6b91906124fb565b9050610cd3565b60405163b6b55f2560e01b81526001600160a01b0388169063b6b55f25908590610ca0908990600401612846565b6000604051808303818588803b158015610cb957600080fd5b505af1158015610ccd573d6000803e3d6000fd5b50505050505b90505b95945050505050565b600080604051806101600160405280856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d2757600080fd5b505afa158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f9190611f75565b6001600160a01b03168152602001856001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610da657600080fd5b505afa158015610dba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dde9190611f75565b6001600160a01b03168152602001856001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610e2557600080fd5b505afa158015610e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5d91906124e1565b62ffffff1681526020018460a0015160020b81526020018460c0015160020b81526020018460200151815260200184604001518152602001846060015181526020018460800151815260200184600001516001600160a01b031681526020014281525090506000856001600160a01b03166388316456836040518263ffffffff1660e01b8152600401610ef09190612798565b608060405180830381600087803b158015610f0a57600080fd5b505af1158015610f1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f429190612513565b50919450505050505b9392505050565b60008060008060008a6001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610f9357600080fd5b505afa158015610fa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcb919061244b565b5050505050915050600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba3836040518263ffffffff1660e01b815260040161100c91906126c0565b60206040518083038186803b15801561102457600080fd5b505af4158015611038573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105c9190611f75565b9050600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba38b6040518263ffffffff1660e01b815260040161109791906126c0565b60206040518083038186803b1580156110af57600080fd5b505af41580156110c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e79190611f75565b9050600073__$d199f155f9376dc21890c162698c9ef049$__63986cfba38b6040518263ffffffff1660e01b815260040161112291906126c0565b60206040518083038186803b15801561113a57600080fd5b505af415801561114e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111729190611f75565b905088611180578b8d611183565b8c8c5b909650945060006111978484848a8a61156b565b90506111a684868e8e85611623565b909950975050505050505050965096945050505050565b60008060006040518060a0016040528086600001518152602001611204670de0b6b3a76400006111fe89604001518a6020015161196490919063ffffffff16565b906119bd565b6001600160801b0316815260200186606001516001600160801b0316815260200186608001516001600160801b03168152602001428152509050856001600160a01b0316630c49ccbe826040518263ffffffff1660e01b815260040161126a9190612711565b6040805180830381600087803b15801561128357600080fd5b505af1158015611297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bb9190612550565b5050600080856113705760408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f78659161131691906004016126ce565b6040805180830381600087803b15801561132f57600080fd5b505af1158015611343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113679190612550565b92509050611418565b60408051608081018252885181523060208201526001600160801b038183018190526060820152905163fc6f786560e01b81526001600160a01b038a169163fc6f7865916113c191906004016126ce565b6040805180830381600087803b1580156113da57600080fd5b505af11580156113ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114129190612550565b90925090505b97909650945050505050565b80471015611479576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146114c4576040519150601f19603f3d011682016040523d82523d6000602084013e6114c9565b606091505b50509050806104bc5760405162461bcd60e51b815260040180806020018281038252603a8152602001806128be603a913960400191505060405180910390fd5b600082821115611560576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000836001600160a01b0316856001600160a01b0316111561158b579293925b846001600160a01b0316866001600160a01b0316116115b6576115af858585611a24565b9050610cd6565b836001600160a01b0316866001600160a01b031610156116185760006115dd878686611a24565b905060006115ec878986611a90565b9050806001600160801b0316826001600160801b03161061160d578061160f565b815b92505050610cd6565b610cd3858584611a90565b6000808460020b8660020b12156116fc5773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b661165787611ade565b61166087611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b1580156116c957600080fd5b505af41580156116dd573d6000803e3d6000fd5b505050506040513d60208110156116f357600080fd5b5051915061195a565b8360020b8660020b12156118965773__$a98c5df505b68ab2f483703658c95acb30$__632c32d4b68861172e87611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561179757600080fd5b505af41580156117ab573d6000803e3d6000fd5b505050506040513d60208110156117c157600080fd5b5051915073__$a98c5df505b68ab2f483703658c95acb30$__6348a0c5bd6117e887611ade565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039283166004820152918b1660248301526001600160801b038716604483015260006064830152516084808301926020929190829003018186803b15801561186357600080fd5b505af4158015611877573d6000803e3d6000fd5b505050506040513d602081101561188d57600080fd5b5051905061195a565b73__$a98c5df505b68ab2f483703658c95acb30$__6348a0c5bd6118b987611ade565b6118c287611ade565b8660006040518563ffffffff1660e01b815260040180856001600160a01b03168152602001846001600160a01b03168152602001836001600160801b03168152602001821515815260200194505050505060206040518083038186803b15801561192b57600080fd5b505af415801561193f573d6000803e3d6000fd5b505050506040513d602081101561195557600080fd5b505190505b9550959350505050565b60008261197357506000611565565b8282028284828161198057fe5b0414610f4b5760405162461bcd60e51b81526004018080602001828103825260218152602001806128f86021913960400191505060405180910390fd5b6000808211611a13576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611a1c57fe5b049392505050565b6000826001600160a01b0316846001600160a01b03161115611a44579192915b6000611a70856001600160a01b0316856001600160a01b03166c01000000000000000000000000611e1d565b9050610cd6611a8b84838888036001600160a01b0316611e1d565b611ecc565b6000826001600160a01b0316846001600160a01b03161115611ab0579192915b611ad6611a8b836c010000000000000000000000008787036001600160a01b0316611e1d565b949350505050565b60008060008360020b12611af5578260020b611afd565b8260020b6000035b9050620d89e8811115611b3b576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216611b5c57700100000000000000000000000000000000611b6e565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615611ba2576ffff97272373d413259a46990580e213a0260801c5b6004821615611bc1576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615611be0576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615611bff576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615611c1e576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615611c3d576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615611c5c576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615611c7c576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615611c9c576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615611cbc576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615611cdc576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615611cfc576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615611d1c576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615611d3c576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615611d5c576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615611d7d576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615611d9d576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615611dbc576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615611dd9576b048a170391f7dc42444e8fa20260801c5b60008460020b1315611df4578060001981611df057fe5b0490505b640100000000810615611e08576001611e0b565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080611e535760008411611e4857600080fd5b508290049050610f4b565b808411611e5f57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b806001600160801b0381168114611ee257600080fd5b919050565b8035611ee281612873565b8051611ee281612873565b8035611ee28161288b565b8035611ee281612899565b8051611ee281612899565b8035611ee2816128a8565b8051611ee2816128a8565b805161ffff81168114611ee257600080fd5b805162ffffff81168114611ee257600080fd5b600060208284031215611f6a578081fd5b8135610f4b81612873565b600060208284031215611f86578081fd5b8151610f4b81612873565b60008060408385031215611fa3578081fd5b8235611fae81612873565b91506020830135611fbe81612873565b809150509250929050565b6000806000806000808688036101e0811215611fe3578283fd5b8735611fee81612873565b96506020880135611ffe81612873565b9550604088013561200e81612873565b9450606088013561201e81612873565b9350610140607f1982011215612032578283fd5b506080870191506101c08701356120488161288b565b809150509295509295509295565b60008060008060008060008789036101a0811215612072578182fd5b883561207d81612873565b9750602089013561208d81612873565b9650604089013561209d81612873565b955060608901356120ad81612873565b94506080890135935060e0609f19820112156120c7578182fd5b5060405160e0810181811067ffffffffffffffff821117156120e557fe5b6040526120f460a08a01611ee7565b815260c089810135602083015260e08a013560408301526101008a013560608301526101208a013560808301526101408a013560a08301526101608a01359082015291506121456101808901611efd565b905092959891949750929550565b60008060008060008060c0878903121561216b578384fd5b863561217681612873565b9550602087013561218681612873565b9450604087013561219681612873565b959894975094956060810135955060808101359460a0909101359350915050565b60008060008385036101208112156121cd578182fd5b84356121d881612873565b935060208501356121e881612873565b925060e0603f19820112156121fb578182fd5b5060405160e0810181811067ffffffffffffffff8211171561221957fe5b806040525061222a60408601611ee7565b8152606085013560208201526080850135604082015260a0850135606082015260c0850135608082015261226060e08601611f08565b60a08201526122726101008601611f08565b60c0820152809150509250925092565b600080600080600060a08688031215612299578283fd5b85356122a481612873565b945060208601356122b481612873565b94979496505050506040830135926060810135926080909101359150565b600080600083850360e08112156122e7578182fd5b84356122f281612873565b935060a0601f1982011215612305578182fd5b5060405160a0810181811067ffffffffffffffff8211171561232357fe5b806040525060208501358152604085013560208201526060850135604082015261234f60808601611f1e565b606082015261236060a08601611f1e565b6080820152915061237360c08501611efd565b90509250925092565b60008060008060008060c08789031215612394578384fd5b863561239f81612873565b9550602087013594506040870135935060608701356123bd81612899565b925060808701356123cd81612899565b915060a08701356120488161288b565b6000602082840312156123ee578081fd5b8151610f4b8161288b565b60006020828403121561240a578081fd5b8135610f4b81612899565b600080600060608486031215612429578081fd5b8351612434816128a8565b602085015160409095015190969495509392505050565b600080600080600080600060e0888a031215612465578081fd5b875161247081612873565b602089015190975061248181612899565b955061248f60408901611f34565b945061249d60608901611f34565b93506124ab60808901611f34565b925060a088015160ff811681146124c0578182fd5b60c08901519092506124d18161288b565b8091505092959891949750929550565b6000602082840312156124f2578081fd5b610f4b82611f46565b60006020828403121561250c578081fd5b5051919050565b60008060008060808587031215612528578182fd5b84519350602085015161253a816128a8565b6040860151606090960151949790965092505050565b60008060408385031215612562578182fd5b505080516020909101519092909150565b6000806000806000806000806000806000806101808d8f031215612595578586fd5b8c516bffffffffffffffffffffffff811681146125b0578687fd5b9b506125be60208e01611ef2565b9a506125cc60408e01611ef2565b99506125da60608e01611ef2565b98506125e860808e01611f46565b97506125f660a08e01611f13565b965061260460c08e01611f13565b955061261260e08e01611f29565b94506101008d015193506101208d015192506126316101408e01611f29565b91506126406101608e01611f29565b90509295989b509295989b509295989b565b6001600160a01b03169052565b60020b9052565b62ffffff169052565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60029190910b815260200190565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b600060a082019050825182526001600160801b03602084015116602083015260408301516040830152606083015160608301526080830151608083015292915050565b600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6000610160820190506127ac828451612652565b60208301516127be6020840182612652565b5060408301516127d16040840182612666565b5060608301516127e4606084018261265f565b5060808301516127f7608084018261265f565b5060a083015160a083015260c083015160c083015260e083015160e08301526101008084015181840152506101208084015161283582850182612652565b505061014092830151919092015290565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b6001600160a01b038116811461288857600080fd5b50565b801515811461288857600080fd5b8060020b811461288857600080fd5b6001600160801b038116811461288857600080fdfe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220cfb89b72f5833964391283454a5a095d88e171c58035cad9299687278c762ec164736f6c63430007060033\",\n  \"libraries\": {\n    \"TickMathExternal\": \"0x0772382Dd7D99adb5218d31fAdfE1c68c8477335\",\n    \"SqrtPriceMathPartial\": \"0x565483126A5fC6004455F4e11014C442A61D740c\"\n  },\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_collateralToWithdraw\": \"amount of collateral to withdraw\",\n          \"_controller\": \"controller address\",\n          \"_vaultId\": \"vault Id\",\n          \"_wPowerPerpToBurn\": \"amount of wPowerPerp to burn\",\n          \"_weth\": \"weth address\"\n        }\n      },\n      \"checkClosedLp(address,address,address,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_controller\": \"controller address\",\n          \"_liquidityPercentage\": \"percentage of liquidity that was closed from total amount\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_tokenId\": \"Uni LP NFT id\",\n          \"_user\": \"user address\",\n          \"_vaultId\": \"vault ID\"\n        }\n      },\n      \"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\": {\n        \"params\": {\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_params\": \"ControllerHelperDataType.CloseUniLpParams struct \"\n        },\n        \"returns\": {\n          \"_0\": \"withdrawn wPowerPerp and WETH amounts\"\n        }\n      },\n      \"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\": {\n        \"params\": {\n          \"_collateralToLp\": \"amount of ETH collateral to LP\",\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_lowerTick\": \"LP position lower tick\",\n          \"_upperTick\": \"LP position upper tick\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to LP\",\n          \"_wPowerPerpPool\": \"wPowerPerp Uni v3 pool (oSQTH/ETH pool)\"\n        },\n        \"returns\": {\n          \"_0\": \"exact amount0 and amount1 to be LPed\"\n        }\n      },\n      \"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\": {\n        \"params\": {\n          \"_controller\": \"controller address\",\n          \"_increaseLiquidityParam\": \"ControllerHelperDataType.IncreaseLpLiquidityParams struct\",\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_vaultId\": \"vault Id\"\n        }\n      },\n      \"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\": {\n        \"params\": {\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\",\n          \"_params\": \"ControllerHelperDataType.LpWPowerPerpPoolParams struct\",\n          \"_wPowerPerpPool\": \"wPowerpPerp pool address in Uni v3\"\n        }\n      },\n      \"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\": {\n        \"params\": {\n          \"_controller\": \"wPowerPerp controller address\",\n          \"_isWethToken0\": \"bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\",\n          \"_mintAndLpParams\": \"ControllerHelperDataType.MintAndLpParams struct\",\n          \"_nonfungiblePositionManager\": \"Uni NonFungiblePositionManager address\"\n        },\n        \"returns\": {\n          \"_0\": \"_vaultId and tokenId\"\n        }\n      },\n      \"mintDepositInVault(address,address,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_collateralToDeposit\": \"amount of collateral to deposit\",\n          \"_controller\": \"controller address\",\n          \"_vaultId\": \"vault Id\",\n          \"_wPowerPerpToMint\": \"amount of wPowerPerp to mint\",\n          \"_weth\": \"WETH address\"\n        }\n      },\n      \"sendBack(address,address)\": {\n        \"params\": {\n          \"_wPowerPerp\": \"wPowerPerp address\",\n          \"_weth\": \"WETH address\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"burnWithdrawFromVault(address,address,uint256,uint256,uint256)\": {\n        \"notice\": \"burn wPowerPerp or just withdraw collateral from vault (or both)\"\n      },\n      \"checkClosedLp(address,address,address,uint256,uint256,uint256)\": {\n        \"notice\": \"transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\"\n      },\n      \"closeUniLp(address,ControllerHelperDataType.CloseUniLpParams,bool)\": {\n        \"notice\": \"fully or partially close Uni v3 LP\"\n      },\n      \"getAmountsToLp(address,uint256,uint256,int24,int24,bool)\": {\n        \"notice\": \"get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\"\n      },\n      \"increaseLpLiquidity(address,address,address,address,uint256,ControllerHelperDataType.IncreaseLpLiquidityParams,bool)\": {\n        \"notice\": \"increase liquidityin Uni v3 position\"\n      },\n      \"lpWPowerPerpPool(address,address,ControllerHelperDataType.LpWPowerPerpPoolParams)\": {\n        \"notice\": \"LP into Uniswap V3 pool\"\n      },\n      \"mintAndLp(address,address,address,address,ControllerHelperDataType.MintAndLpParams,bool)\": {\n        \"notice\": \"minth amount of wPowerPerp and LP in weth/wPowerPerp pool\"\n      },\n      \"mintDepositInVault(address,address,uint256,uint256,uint256)\": {\n        \"notice\": \"mint wPowerPerp in vault\"\n      },\n      \"sendBack(address,address)\": {\n        \"notice\": \"send ETH and wPowerPerp\"\n      }\n    },\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/CrabMigration.json",
    "content": "{\n  \"address\": \"0xD0fb9d47B5F65d76C6bDf1b9E43a4A2345080B2f\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address payable\",\n          \"name\": \"_crabV1\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_weth\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_eulerExec\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_dToken\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_eulerMainnet\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"user\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ClaimAndWithdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"user\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ClaimV2Shares\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"user\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabV1Amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"DepositV1Shares\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"user\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabV1Amount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabV2Amount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excessEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashMigrate\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"user\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabV1Amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawV1Shares\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_strategyCap\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"batchMigrate\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amountToWithdraw\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxEthToPay\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"claimAndWithdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"claimV2Shares\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"crabV1\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address payable\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"crabV2\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address payable\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"depositV1Shares\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"euler\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_v1Shares\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToFlashDeposit\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToBorrow\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_withdrawMaxEthToPay\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashMigrateAndWithdrawFromV1toV2\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_v1Shares\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToFlashDeposit\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashMigrateFromV1toV2\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_v1Shares\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"flashMigrationDetails\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isMigrated\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"encodedData\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onDeferredLiquidityCheck\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address payable\",\n          \"name\": \"_crabV2\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"setCrabV2\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"sharesDeposited\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdrawV1Shares\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0xccb538f212acc0f9d1408e4e066a2a6d0ae9b6c928bc2c0cc287d8cbc2eec06f\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0xD0fb9d47B5F65d76C6bDf1b9E43a4A2345080B2f\",\n    \"transactionIndex\": 5,\n    \"gasUsed\": \"3091563\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000004000000000800000000000000000000040000000000000000000000000080000000000000000000010200000040008000000000000000000000000000001000000000002000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000020000000000000000000000a00000000000000001000000000000000000000000000000000000000000000000000000040000000000000000000200000020000010000000000200000000000000000000002004000000000000000000000000\",\n    \"blockHash\": \"0xb10db58506a0657b4f8de1b7ce15646ee40a97ae2f812cbe628effaa6c14ce66\",\n    \"transactionHash\": \"0xccb538f212acc0f9d1408e4e066a2a6d0ae9b6c928bc2c0cc287d8cbc2eec06f\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 5,\n        \"blockNumber\": 12581444,\n        \"transactionHash\": \"0xccb538f212acc0f9d1408e4e066a2a6d0ae9b6c928bc2c0cc287d8cbc2eec06f\",\n        \"address\": \"0xD0fb9d47B5F65d76C6bDf1b9E43a4A2345080B2f\",\n        \"topics\": [\n          \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000005599b4eaddd319e2f462b27fc8378b0bfad309ca\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 20,\n        \"blockHash\": \"0xb10db58506a0657b4f8de1b7ce15646ee40a97ae2f812cbe628effaa6c14ce66\"\n      },\n      {\n        \"transactionIndex\": 5,\n        \"blockNumber\": 12581444,\n        \"transactionHash\": \"0xccb538f212acc0f9d1408e4e066a2a6d0ae9b6c928bc2c0cc287d8cbc2eec06f\",\n        \"address\": \"0xc778417E063141139Fce010982780140Aa0cD5Ab\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x000000000000000000000000d0fb9d47b5f65d76c6bdf1b9e43a4a2345080b2f\",\n          \"0x000000000000000000000000fc3dd73e918b931be7defd0cc616508391bcc001\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 21,\n        \"blockHash\": \"0xb10db58506a0657b4f8de1b7ce15646ee40a97ae2f812cbe628effaa6c14ce66\"\n      }\n    ],\n    \"blockNumber\": 12581444,\n    \"cumulativeGasUsed\": \"3985199\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0xbffBD99cFD9d77c49595dFe8eB531715906ca4Cf\",\n    \"0xc778417e063141139fce010982780140aa0cd5ab\",\n    \"0xF7B8611008Ed073Ef348FE130671688BBb20409d\",\n    \"0x682b4c36a6D4749Ced8C3abF47AefDFC57A17754\",\n    \"0xfC3DD73e918b931be7DEfd0cc616508391bcc001\"\n  ],\n  \"solcInputHash\": \"30afee76cfee2d4cc1c12451e0258499\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address payable\\\",\\\"name\\\":\\\"_crabV1\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_weth\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_eulerExec\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_dToken\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_eulerMainnet\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"user\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ClaimAndWithdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"user\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ClaimV2Shares\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"user\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabV1Amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"DepositV1Shares\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"user\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabV1Amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabV2Amount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excessEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashMigrate\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"user\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabV1Amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawV1Shares\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_strategyCap\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"batchMigrate\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amountToWithdraw\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxEthToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"claimAndWithdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"claimV2Shares\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"crabV1\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address payable\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"crabV2\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address payable\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"depositV1Shares\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"euler\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_v1Shares\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToFlashDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToBorrow\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawMaxEthToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashMigrateAndWithdrawFromV1toV2\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_v1Shares\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToFlashDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashMigrateFromV1toV2\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_v1Shares\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"flashMigrationDetails\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isMigrated\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"encodedData\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onDeferredLiquidityCheck\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address payable\\\",\\\"name\\\":\\\"_crabV2\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"setCrabV2\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"sharesDeposited\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdrawV1Shares\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"author\\\":\\\"Opyn team\\\",\\\"details\\\":\\\"CrabMigration contract\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"batchMigrate(uint256)\\\":{\\\"params\\\":{\\\"_strategyCap\\\":\\\"strategy cap in ETH\\\"}},\\\"claimAndWithdraw(uint256,uint256,uint24)\\\":{\\\"params\\\":{\\\"_amountToWithdraw\\\":\\\"V2 shares to claim\\\",\\\"_maxEthToPay\\\":\\\"maximum ETH to pay to buy back the owed wSqueeth debt\\\",\\\"_poolFee\\\":\\\"Uniswap pool fee for flash withdraw\\\"}},\\\"constructor\\\":{\\\"params\\\":{\\\"_crabV1\\\":\\\"address of crab V1\\\",\\\"_dToken\\\":\\\"address of euler liability token\\\",\\\"_eulerExec\\\":\\\"address of euler exec contract\\\",\\\"_eulerMainnet\\\":\\\"address of euler deployment on mainnet\\\",\\\"_weth\\\":\\\"address of weth\\\"}},\\\"depositV1Shares(uint256)\\\":{\\\"params\\\":{\\\"_amount\\\":\\\"amount of crabV1 shares to deposit\\\"}},\\\"flashMigrateAndWithdrawFromV1toV2(uint256,uint256,uint256,uint256,uint24)\\\":{\\\"params\\\":{\\\"_ethToBorrow\\\":\\\"amount to flash loan to deposit in crab v2\\\",\\\"_ethToFlashDeposit\\\":\\\"flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\\",\\\"_poolFee\\\":\\\"uniswap pool fee for the optional flash deposit into crab v2\\\",\\\"_v1Shares\\\":\\\"V1 shares to migrate\\\",\\\"_withdrawMaxEthToPay\\\":\\\"maximum ETH to pay to buy back the owed wSqueeth debt\\\"}},\\\"flashMigrateFromV1toV2(uint256,uint256,uint24)\\\":{\\\"params\\\":{\\\"_ethToFlashDeposit\\\":\\\"flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\\",\\\"_poolFee\\\":\\\"uniswap pool fee for flash deposit\\\",\\\"_v1Shares\\\":\\\"V1 shares to migrate\\\"}},\\\"flashMigrationDetails(uint256)\\\":{\\\"params\\\":{\\\"_v1Shares\\\":\\\"amount of crab V1 shares\\\"}},\\\"onDeferredLiquidityCheck(bytes)\\\":{\\\"params\\\":{\\\"encodedData\\\":\\\"callback data\\\"}},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"setCrabV2(address)\\\":{\\\"params\\\":{\\\"_crabV2\\\":\\\"address of crab V2\\\"}},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"withdrawV1Shares(uint256)\\\":{\\\"params\\\":{\\\"_amount\\\":\\\"amount of V1 shares to withdraw\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"batchMigrate(uint256)\\\":{\\\"notice\\\":\\\"the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes the V2 contract at the same collateral ratio as the V1 contract\\\"},\\\"claimAndWithdraw(uint256,uint256,uint24)\\\":{\\\"notice\\\":\\\"claim crab V2 shares and flash withdraw from crab V2\\\"},\\\"claimV2Shares()\\\":{\\\"notice\\\":\\\"claim crab V2 shares\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"migration constructor\\\"},\\\"depositV1Shares(uint256)\\\":{\\\"notice\\\":\\\"deposit crab V1 shares in the pool for migration\\\"},\\\"flashMigrateAndWithdrawFromV1toV2(uint256,uint256,uint256,uint256,uint24)\\\":{\\\"notice\\\":\\\"used to migrate from crab V1 to crab V2 when CR1 < CR2\\\"},\\\"flashMigrateFromV1toV2(uint256,uint256,uint24)\\\":{\\\"notice\\\":\\\"used to migrate from crab V1 to crab V2 when CR1 >= CR2\\\"},\\\"flashMigrationDetails(uint256)\\\":{\\\"notice\\\":\\\"view details of flash migration for specified amount of V1 shares\\\"},\\\"onDeferredLiquidityCheck(bytes)\\\":{\\\"notice\\\":\\\"Euler callback function\\\"},\\\"setCrabV2(address)\\\":{\\\"notice\\\":\\\"set the crabV2 address\\\"},\\\"withdrawV1Shares(uint256)\\\":{\\\"notice\\\":\\\"withdraw crab V1 shares in the pool before migration\\\"}},\\\"notice\\\":\\\"Contract for Migrating from Crab V1 to Crab V2\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/strategy/CrabMigration.sol\\\":\\\"CrabMigration\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\\\n *\\\\n * These functions can be used to verify that a message was signed by the holder\\\\n * of the private keys of a given address.\\\\n */\\\\nlibrary ECDSA {\\\\n    /**\\\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\\\n     * `signature`. This address can then be used for verification purposes.\\\\n     *\\\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\\\n     * this function rejects them by requiring the `s` value to be in the lower\\\\n     * half order, and the `v` value to be either 27 or 28.\\\\n     *\\\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\\\n     * verification to be secure: it is possible to craft signatures that\\\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\\\n     * this is by receiving a hash of the original message (which may otherwise\\\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\\\n     */\\\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\\\n        // Check the signature length\\\\n        if (signature.length != 65) {\\\\n            revert(\\\\\\\"ECDSA: invalid signature length\\\\\\\");\\\\n        }\\\\n\\\\n        // Divide the signature in r, s and v variables\\\\n        bytes32 r;\\\\n        bytes32 s;\\\\n        uint8 v;\\\\n\\\\n        // ecrecover takes the signature parameters, and the only way to get them\\\\n        // currently is to use assembly.\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly {\\\\n            r := mload(add(signature, 0x20))\\\\n            s := mload(add(signature, 0x40))\\\\n            v := byte(0, mload(add(signature, 0x60)))\\\\n        }\\\\n\\\\n        return recover(hash, v, r, s);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\\\n     * `r` and `s` signature fields separately.\\\\n     */\\\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\\\n        // the valid range for s in (281): 0 < s < secp256k1n \\\\u00f7 2 + 1, and for v in (282): v \\\\u2208 {27, 28}. Most\\\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\\\n        //\\\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\\\n        // these malleable signatures as well.\\\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\\\\\"ECDSA: invalid signature 's' value\\\\\\\");\\\\n        require(v == 27 || v == 28, \\\\\\\"ECDSA: invalid signature 'v' value\\\\\\\");\\\\n\\\\n        // If the signature is valid (and not malleable), return the signer address\\\\n        address signer = ecrecover(hash, v, r, s);\\\\n        require(signer != address(0), \\\\\\\"ECDSA: invalid signature\\\\\\\");\\\\n\\\\n        return signer;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\\\n     * replicates the behavior of the\\\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\\\n     * JSON-RPC method.\\\\n     *\\\\n     * See {recover}.\\\\n     */\\\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\\\n        // 32 is the length in bytes of hash,\\\\n        // enforced by the type signature above\\\\n        return keccak256(abi.encodePacked(\\\\\\\"\\\\\\\\x19Ethereum Signed Message:\\\\\\\\n32\\\\\\\", hash));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc80ce3fcc5e444a2c5bdb902fe4d4f4ecba04e9b416425697d00ae95c1955f82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/drafts/EIP712.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <0.8.0;\\\\n\\\\n/**\\\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\\\n *\\\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\\\n *\\\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\\\n * ({_hashTypedDataV4}).\\\\n *\\\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\\\n *\\\\n * NOTE: This contract implements the version of the encoding known as \\\\\\\"v4\\\\\\\", as implemented by the JSON RPC method\\\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\\\n *\\\\n * _Available since v3.4._\\\\n */\\\\nabstract contract EIP712 {\\\\n    /* solhint-disable var-name-mixedcase */\\\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\\\n    // invalidate the cached domain separator if the chain id changes.\\\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\\\n    uint256 private immutable _CACHED_CHAIN_ID;\\\\n\\\\n    bytes32 private immutable _HASHED_NAME;\\\\n    bytes32 private immutable _HASHED_VERSION;\\\\n    bytes32 private immutable _TYPE_HASH;\\\\n    /* solhint-enable var-name-mixedcase */\\\\n\\\\n    /**\\\\n     * @dev Initializes the domain separator and parameter caches.\\\\n     *\\\\n     * The meaning of `name` and `version` is specified in\\\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\\\n     *\\\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\\\n     * - `version`: the current major version of the signing domain.\\\\n     *\\\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\\\n     * contract upgrade].\\\\n     */\\\\n    constructor(string memory name, string memory version) {\\\\n        bytes32 hashedName = keccak256(bytes(name));\\\\n        bytes32 hashedVersion = keccak256(bytes(version));\\\\n        bytes32 typeHash = keccak256(\\\\\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\\\\\");\\\\n        _HASHED_NAME = hashedName;\\\\n        _HASHED_VERSION = hashedVersion;\\\\n        _CACHED_CHAIN_ID = _getChainId();\\\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\\\n        _TYPE_HASH = typeHash;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the domain separator for the current chain.\\\\n     */\\\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\\\n            return _CACHED_DOMAIN_SEPARATOR;\\\\n        } else {\\\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\\\n        }\\\\n    }\\\\n\\\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\\\n        return keccak256(\\\\n            abi.encode(\\\\n                typeHash,\\\\n                name,\\\\n                version,\\\\n                _getChainId(),\\\\n                address(this)\\\\n            )\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\\\n     *\\\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\\\n     *\\\\n     * ```solidity\\\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\\\n     *     keccak256(\\\\\\\"Mail(address to,string contents)\\\\\\\"),\\\\n     *     mailTo,\\\\n     *     keccak256(bytes(mailContents))\\\\n     * )));\\\\n     * address signer = ECDSA.recover(digest, signature);\\\\n     * ```\\\\n     */\\\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\\\n        return keccak256(abi.encodePacked(\\\\\\\"\\\\\\\\x19\\\\\\\\x01\\\\\\\", _domainSeparatorV4(), structHash));\\\\n    }\\\\n\\\\n    function _getChainId() private view returns (uint256 chainId) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly {\\\\n            chainId := chainid()\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4bc5cda2bfee483ff10334881c9ea5cc4df7faa7b18a5a4b8f02fc51cf8adca\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 SafeMath for uint256;\\\\n    using Address for address;\\\\n\\\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\\\n    }\\\\n\\\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\\\n    }\\\\n\\\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\\\\\"SafeERC20: decreased allowance below zero\\\\\\\");\\\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\\\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) { // Return data is optional\\\\n            // solhint-disable-next-line max-line-length\\\\n            require(abi.decode(returndata, (bool)), \\\\\\\"SafeERC20: ERC20 operation did not succeed\\\\\\\");\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc77dd6233a82c7c6e3dc49da8f3456baa00ecd3ea4dfa9222002a9aebf155dcd\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Safe casting methods\\\\n/// @notice Contains methods for safely casting between types\\\\nlibrary SafeCast {\\\\n    /// @notice Cast a uint256 to a uint160, revert on overflow\\\\n    /// @param y The uint256 to be downcasted\\\\n    /// @return z The downcasted integer, now type uint160\\\\n    function toUint160(uint256 y) internal pure returns (uint160 z) {\\\\n        require((z = uint160(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a int256 to a int128, revert on overflow or underflow\\\\n    /// @param y The int256 to be downcasted\\\\n    /// @return z The downcasted integer, now type int128\\\\n    function toInt128(int256 y) internal pure returns (int128 z) {\\\\n        require((z = int128(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a uint256 to a int256, revert on overflow\\\\n    /// @param y The uint256 to be casted\\\\n    /// @return z The casted integer, now type int256\\\\n    function toInt256(uint256 y) internal pure returns (int256 z) {\\\\n        require(y < 2**255);\\\\n        z = int256(y);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n/*\\\\n * @title Solidity Bytes Arrays Utils\\\\n * @author Gon\\\\u00e7alo S\\\\u00e1 <goncalo.sa@consensys.net>\\\\n *\\\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\\\n */\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nlibrary BytesLib {\\\\n    function slice(\\\\n        bytes memory _bytes,\\\\n        uint256 _start,\\\\n        uint256 _length\\\\n    ) internal pure returns (bytes memory) {\\\\n        require(_length + 31 >= _length, 'slice_overflow');\\\\n        require(_start + _length >= _start, 'slice_overflow');\\\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\\\n\\\\n        bytes memory tempBytes;\\\\n\\\\n        assembly {\\\\n            switch iszero(_length)\\\\n                case 0 {\\\\n                    // Get a location of some free memory and store it in tempBytes as\\\\n                    // Solidity does for memory variables.\\\\n                    tempBytes := mload(0x40)\\\\n\\\\n                    // The first word of the slice result is potentially a partial\\\\n                    // word read from the original array. To read it, we calculate\\\\n                    // the length of that partial word and start copying that many\\\\n                    // bytes into the array. The first word we copy will start with\\\\n                    // data we don't care about, but the last `lengthmod` bytes will\\\\n                    // land at the beginning of the contents of the new array. When\\\\n                    // we're done copying, we overwrite the full first word with\\\\n                    // the actual length of the slice.\\\\n                    let lengthmod := and(_length, 31)\\\\n\\\\n                    // The multiplication in the next line is necessary\\\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\\\n                    // the following copy loop was copying the origin's length\\\\n                    // and then ending prematurely not copying everything it should.\\\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\\\n                    let end := add(mc, _length)\\\\n\\\\n                    for {\\\\n                        // The multiplication in the next line has the same exact purpose\\\\n                        // as the one above.\\\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\\\n                    } lt(mc, end) {\\\\n                        mc := add(mc, 0x20)\\\\n                        cc := add(cc, 0x20)\\\\n                    } {\\\\n                        mstore(mc, mload(cc))\\\\n                    }\\\\n\\\\n                    mstore(tempBytes, _length)\\\\n\\\\n                    //update free-memory pointer\\\\n                    //allocating the array padded to 32 bytes like the compiler does now\\\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\\\n                }\\\\n                //if we want a zero-length slice let's just return a zero-length array\\\\n                default {\\\\n                    tempBytes := mload(0x40)\\\\n                    //zero out the 32 bytes slice we are about to return\\\\n                    //we need to do it because Solidity does not garbage collect\\\\n                    mstore(tempBytes, 0)\\\\n\\\\n                    mstore(0x40, add(tempBytes, 0x20))\\\\n                }\\\\n        }\\\\n\\\\n        return tempBytes;\\\\n    }\\\\n\\\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\\\n        address tempAddress;\\\\n\\\\n        assembly {\\\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\\\n        }\\\\n\\\\n        return tempAddress;\\\\n    }\\\\n\\\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\\\n        uint24 tempUint;\\\\n\\\\n        assembly {\\\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\\\n        }\\\\n\\\\n        return tempUint;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport './PoolAddress.sol';\\\\n\\\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\\\nlibrary CallbackValidation {\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param tokenA The contract address of either token0 or token1\\\\n    /// @param tokenB The contract address of the other token\\\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(\\\\n        address factory,\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool pool) {\\\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param poolKey The identifying key of the V3 pool\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\\\n        internal\\\\n        view\\\\n        returns (IUniswapV3Pool pool)\\\\n    {\\\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\\\n        require(msg.sender == address(pool));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.6.0;\\\\n\\\\nimport './BytesLib.sol';\\\\n\\\\n/// @title Functions for manipulating path data for multihop swaps\\\\nlibrary Path {\\\\n    using BytesLib for bytes;\\\\n\\\\n    /// @dev The length of the bytes encoded address\\\\n    uint256 private constant ADDR_SIZE = 20;\\\\n    /// @dev The length of the bytes encoded fee\\\\n    uint256 private constant FEE_SIZE = 3;\\\\n\\\\n    /// @dev The offset of a single token address and pool fee\\\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\\\n    /// @dev The offset of an encoded pool key\\\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\\\n\\\\n    /// @notice Returns true iff the path contains two or more pools\\\\n    /// @param path The encoded swap path\\\\n    /// @return True if path contains two or more pools, otherwise false\\\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\\\n    }\\\\n\\\\n    /// @notice Returns the number of pools in the path\\\\n    /// @param path The encoded swap path\\\\n    /// @return The number of pools in the path\\\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Decodes the first pool in path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return tokenA The first token of the given pool\\\\n    /// @return tokenB The second token of the given pool\\\\n    /// @return fee The fee level of the pool\\\\n    function decodeFirstPool(bytes memory path)\\\\n        internal\\\\n        pure\\\\n        returns (\\\\n            address tokenA,\\\\n            address tokenB,\\\\n            uint24 fee\\\\n        )\\\\n    {\\\\n        tokenA = path.toAddress(0);\\\\n        fee = path.toUint24(ADDR_SIZE);\\\\n        tokenB = path.toAddress(NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Gets the segment corresponding to the first pool in the path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return The segment containing all data necessary to target the first pool in the path\\\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(0, POP_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\\\n    /// @param path The swap path\\\\n    /// @return The remaining token + fee elements in the path\\\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/external/WETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\\\n\\\\ncontract WETH9 {\\\\n    string public name = \\\\\\\"Wrapped Ether\\\\\\\";\\\\n    string public symbol = \\\\\\\"WETH\\\\\\\";\\\\n    uint8 public decimals = 18;\\\\n\\\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\\\n    event Deposit(address indexed dst, uint256 wad);\\\\n    event Withdrawal(address indexed src, uint256 wad);\\\\n\\\\n    mapping(address => uint256) public balanceOf;\\\\n    mapping(address => mapping(address => uint256)) public allowance;\\\\n\\\\n    function deposit() public payable {\\\\n        balanceOf[msg.sender] += msg.value;\\\\n        emit Deposit(msg.sender, msg.value);\\\\n    }\\\\n\\\\n    function withdraw(uint256 wad) public {\\\\n        require(balanceOf[msg.sender] >= wad);\\\\n        balanceOf[msg.sender] -= wad;\\\\n        payable(msg.sender).transfer(wad);\\\\n        emit Withdrawal(msg.sender, wad);\\\\n    }\\\\n\\\\n    function totalSupply() public view returns (uint256) {\\\\n        return address(this).balance;\\\\n    }\\\\n\\\\n    function approve(address guy, uint256 wad) public returns (bool) {\\\\n        allowance[msg.sender][guy] = wad;\\\\n        emit Approval(msg.sender, guy, wad);\\\\n        return true;\\\\n    }\\\\n\\\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\\\n        return transferFrom(msg.sender, dst, wad);\\\\n    }\\\\n\\\\n    function transferFrom(\\\\n        address src,\\\\n        address dst,\\\\n        uint256 wad\\\\n    ) public returns (bool) {\\\\n        require(balanceOf[src] >= wad);\\\\n\\\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\\\n            require(allowance[src][msg.sender] >= wad);\\\\n            allowance[src][msg.sender] -= wad;\\\\n        }\\\\n\\\\n        balanceOf[src] -= wad;\\\\n        balanceOf[dst] += wad;\\\\n\\\\n        emit Transfer(src, dst, wad);\\\\n\\\\n        return true;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1624ad07a54d1a85df74a1ec4dc0e5d47d42165bfd71cf1dbc9fc51de3e6d8de\\\",\\\"license\\\":\\\"GPL-3.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IEuler.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\ninterface IEulerExec {\\\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\\\n}\\\\n\\\\ninterface IDToken {\\\\n    function underlyingAsset() external view returns (address);\\\\n\\\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\\\n\\\\n    function repay(uint256 subAccountId, uint256 amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x81fd5d15724c747dad6b8f2a01b893a59b4db6c02ce2ecb92b50dfd96c4046c8\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/Power2Base.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary Power2Base {\\\\n    using SafeMath for uint256;\\\\n\\\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\\\n    uint256 private constant INDEX_SCALE = 1e4;\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    /**\\\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getUnscaledIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\\\n     */\\\\n    function _getDenormalizedMark(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _wSqueeth,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\\\n\\\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _weth weth address\\\\n     * @return returns value of debt in ETH\\\\n     */\\\\n    function _getDebtValueInEth(\\\\n        uint256 _debtAmount,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _wSqueeth,\\\\n        address _weth\\\\n    ) internal view returns (uint256) {\\\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle\\\\n     * @dev this will revert if period is > max period for the pool\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        // period reaching this point should be check, otherwise might revert\\\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\\\n     * @param _indexPriceForSettlement index price for settlement\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return amount in wei that should be paid to the token holder\\\\n     */\\\\n    function _getLongSettlementValue(\\\\n        uint256 _wsqueethAmount,\\\\n        uint256 _indexPriceForSettlement,\\\\n        uint256 _normalizationFactor\\\\n    ) internal pure returns (uint256) {\\\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1938180c41ec0ee817b841df605b199e15ffbbe94700b640d031b4e4665a89af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/CrabMigration.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\nimport {SafeERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\\\\\";\\\\nimport {IEulerExec, IDToken} from \\\\\\\"../interfaces/IEuler.sol\\\\\\\";\\\\nimport {WETH9} from \\\\\\\"../external/WETH9.sol\\\\\\\";\\\\n\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {CrabStrategyV2} from \\\\\\\"./CrabStrategyV2.sol\\\\\\\";\\\\nimport {CrabStrategy} from \\\\\\\"./CrabStrategy.sol\\\\\\\";\\\\nimport {StrategyMath} from \\\\\\\"./base/StrategyMath.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Migration Error Codes:\\\\n * M1: Migration already happened\\\\n * M2: Migration has not yet happened\\\\n * M3: msg.sender is not Euler Mainnet Contract\\\\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\\\\n * M5: Can't withdraw more than you own\\\\n * M6: Not enough ETH to repay the loan\\\\n * M7: Invalid crabV2 address\\\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\\\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\\\n * M10: Wrong migration function, use flashMigrateFromV1toV2\\\\n * M11: crabV2 address not yet set\\\\n */\\\\n\\\\n/**\\\\n * @dev CrabMigration contract\\\\n * @notice Contract for Migrating from Crab V1 to Crab V2\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabMigration is Ownable {\\\\n    using SafeERC20 for IERC20;\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    mapping(address => uint256) public sharesDeposited;\\\\n    bool public isMigrated;\\\\n\\\\n    address payable public crabV1;\\\\n    address payable public crabV2;\\\\n    address public immutable euler;\\\\n    address public immutable weth;\\\\n\\\\n    address immutable EULER_MAINNET;\\\\n    address immutable dToken;\\\\n    address immutable wPowerPerp;\\\\n\\\\n    struct FlashloanCallbackData {\\\\n        address caller;\\\\n        uint256 amountToBorrow;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    struct BatchMigrate {\\\\n        uint256 strategyCap;\\\\n    }\\\\n\\\\n    struct FlashMigrateV1toV2 {\\\\n        uint256 v1oSqthToPay;\\\\n        uint256 ethToFlashDeposit;\\\\n        uint256 crabV1ToWithdraw;\\\\n        uint24 poolFee;\\\\n    }\\\\n\\\\n    struct FlashMigrateAndBuyV1toV2 {\\\\n        uint256 v1oSqthToPay;\\\\n        uint256 ethToFlashDeposit;\\\\n        uint256 withdrawMaxEthToPay;\\\\n        uint256 crabV1ToWithdraw;\\\\n        uint24 poolFeeFlashDeposit;\\\\n    }\\\\n\\\\n    enum FLASH_SOURCE {\\\\n        BATCH_MIGRATE,\\\\n        FLASH_MIGRATE_V1_TO_V2,\\\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\\\n    }\\\\n\\\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\\\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\\\\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\\\\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\\\\n\\\\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\\\\n\\\\n    modifier beforeMigration() {\\\\n        require(!isMigrated, \\\\\\\"M1\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier afterMigration() {\\\\n        require(isMigrated, \\\\\\\"M2\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier afterInitialized() {\\\\n        require(crabV2 != address(0), \\\\\\\"M11\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice migration constructor\\\\n     * @param _crabV1 address of crab V1\\\\n     * @param _weth address of weth\\\\n     * @param _eulerExec address of euler exec contract\\\\n     * @param _dToken address of euler liability token\\\\n     * @param _eulerMainnet address of euler deployment on mainnet\\\\n     */\\\\n    constructor(\\\\n        address payable _crabV1,\\\\n        address _weth,\\\\n        address _eulerExec,\\\\n        address _dToken,\\\\n        address _eulerMainnet\\\\n    ) {\\\\n        require(_eulerExec != address(0), \\\\\\\"invalid _eulerExec address\\\\\\\");\\\\n        require(_dToken != address(0), \\\\\\\"invalid _dToken address\\\\\\\");\\\\n        require(_eulerMainnet != address(0), \\\\\\\"invalid _eulerMainnet address\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"invalid _weth address\\\\\\\");\\\\n        require(_crabV1 != address(0), \\\\\\\"invalid _crabv1 address\\\\\\\");\\\\n        require(IDToken(_dToken).underlyingAsset() == _weth, \\\\\\\"dToken underlying asset should be weth\\\\\\\");\\\\n\\\\n        crabV1 = _crabV1;\\\\n        euler = _eulerExec;\\\\n        EULER_MAINNET = _eulerMainnet;\\\\n        weth = _weth;\\\\n        dToken = _dToken;\\\\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\\\\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set the crabV2 address\\\\n     * @param _crabV2 address of crab V2\\\\n     */\\\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\\\n        require(_crabV2 != address(0), \\\\\\\"M7\\\\\\\");\\\\n        crabV2 = _crabV2;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit crab V1 shares in the pool for migration\\\\n     * @param _amount amount of crabV1 shares to deposit\\\\n     */\\\\n    function depositV1Shares(uint256 _amount) external beforeMigration {\\\\n        sharesDeposited[msg.sender] += _amount;\\\\n\\\\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\\\\n\\\\n        emit DepositV1Shares(msg.sender, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw crab V1 shares in the pool before migration\\\\n     * @param _amount amount of V1 shares to withdraw\\\\n     */\\\\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\\\\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\\\\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\\\\n\\\\n        emit WithdrawV1Shares(msg.sender, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\\\\n     * the V2 contract at the same collateral ratio as the V1 contract\\\\n     * @param _strategyCap strategy cap in ETH\\\\n     */\\\\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\\\\n        // 1. update isMigrated\\\\n        isMigrated = true;\\\\n\\\\n        // 2. flash floan eth from euler eq to amt\\\\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\\\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\\\\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\\\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\\\n        IEulerExec(euler).deferLiquidityCheck(\\\\n            address(this),\\\\n            abi.encode(\\\\n                FlashloanCallbackData({\\\\n                    caller: msg.sender,\\\\n                    amountToBorrow: amountEthToBorrow,\\\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\\\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\\\\n                })\\\\n            )\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice Euler callback function\\\\n     * @param encodedData callback data\\\\n     */\\\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\\\n        require(msg.sender == EULER_MAINNET, \\\\\\\"M3\\\\\\\");\\\\n\\\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\\\n\\\\n        // 1. borrow weth\\\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\\\n        WETH9(weth).withdraw(data.amountToBorrow);\\\\n\\\\n        // 2. callback\\\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\\\n\\\\n        // 3. repay the weth\\\\n        WETH9(weth).deposit{value: data.amountToBorrow}();\\\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice callback function for flash actions\\\\n     * @param _initiator address of original function caller\\\\n     * @param _amount  amount to pay back for flashswap\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     * @param _calldata arbitrary data attached to callback\\\\n\\\\n     */\\\\n    function _flashCallback(\\\\n        address _initiator,\\\\n        uint256 _amount,\\\\n        uint8 _callSource,\\\\n        bytes memory _calldata\\\\n    ) internal {\\\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\\\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\\\\n\\\\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\\\n\\\\n            // 2. mint osqth in crab V2\\\\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\\\\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\\\\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\\\\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\\\\n                wSqueethToMint,\\\\n                crabV1Balance,\\\\n                timeAtLastHedge,\\\\n                priceAtLastHedge,\\\\n                data.strategyCap\\\\n            );\\\\n\\\\n            // 3. call withdraw from crab V1\\\\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\\\\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\\\n\\\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\\\n\\\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\\\n\\\\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\\\\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\\\\n\\\\n            // flash deposit remaining ETH, otherwise refund\\\\n            // if CR1 = CR2 ethToFlashDeposit should be 0\\\\n            if (data.ethToFlashDeposit > 0) {\\\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\\\n                    data.ethToFlashDeposit,\\\\n                    data.poolFee\\\\n                );\\\\n            }\\\\n\\\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\\\n            // send back V2 tokens to the user\\\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\\\n\\\\n            uint256 excessEth = address(this).balance;\\\\n\\\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\\\n\\\\n            // send back excess ETH\\\\n            if (excessEth > _amount) {\\\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\\\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\\\\n\\\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\\\n\\\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\\\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\\\\n\\\\n            // find crab amount for contract's sqth balance\\\\n            // remaining crab can be withdrawn using flash withdraw\\\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\\\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\\\n\\\\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\\\\n\\\\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\\\n            require(address(this).balance >= _amount, \\\\\\\"M6\\\\\\\");\\\\n\\\\n            if (data.ethToFlashDeposit > 0) {\\\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\\\n                    data.ethToFlashDeposit,\\\\n                    data.poolFeeFlashDeposit\\\\n                );\\\\n            }\\\\n\\\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\\\n\\\\n            // send V2 tokens to the user\\\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\\\n\\\\n            uint256 excessEth = address(this).balance;\\\\n\\\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\\\n\\\\n            // send back the excess ETH\\\\n            if (excessEth > _amount) {\\\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\\\n            }\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice claim crab V2 shares\\\\n     */\\\\n    function claimV2Shares() external afterMigration {\\\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\\\n        sharesDeposited[msg.sender] = 0;\\\\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\\\\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice claim crab V2 shares and flash withdraw from crab V2\\\\n     * @param _amountToWithdraw V2 shares to claim\\\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\\\n     * @param _poolFee Uniswap pool fee for flash withdraw\\\\n     */\\\\n    function claimAndWithdraw(\\\\n        uint256 _amountToWithdraw,\\\\n        uint256 _maxEthToPay,\\\\n        uint24 _poolFee\\\\n    ) external afterMigration {\\\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\\\n        require(_amountToWithdraw <= amountV1Deposited, \\\\\\\"M5\\\\\\\");\\\\n\\\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\\\\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\\\\n\\\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\\\n\\\\n        // send eth to user\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice view details of flash migration for specified amount of V1 shares\\\\n     * @param _v1Shares amount of crab V1 shares\\\\n     */\\\\n    function flashMigrationDetails(uint256 _v1Shares)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            bool,\\\\n            uint256,\\\\n            uint256,\\\\n            uint256\\\\n        )\\\\n    {\\\\n        return _flashMigrationDetails(_v1Shares);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\\\\n     * @param _v1Shares V1 shares to migrate\\\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\\\n     * @param _poolFee uniswap pool fee for flash deposit\\\\n     */\\\\n    function flashMigrateFromV1toV2(\\\\n        uint256 _v1Shares,\\\\n        uint256 _ethToFlashDeposit,\\\\n        uint24 _poolFee\\\\n    ) external afterMigration {\\\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\\\n\\\\n        require(isFlashOnlyMigrate, \\\\\\\"M9\\\\\\\");\\\\n\\\\n        IEulerExec(euler).deferLiquidityCheck(\\\\n            address(this),\\\\n            abi.encode(\\\\n                FlashloanCallbackData({\\\\n                    caller: msg.sender,\\\\n                    amountToBorrow: ethNeededForV2,\\\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\\\n                    callData: abi.encode(\\\\n                        FlashMigrateV1toV2({\\\\n                            v1oSqthToPay: v1oSqthToPay,\\\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\\\n                            crabV1ToWithdraw: _v1Shares,\\\\n                            poolFee: _poolFee\\\\n                        })\\\\n                    )\\\\n                })\\\\n            )\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\\\\n     * @param _v1Shares V1 shares to migrate\\\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\\\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\\\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\\\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\\\\n     */\\\\n    function flashMigrateAndWithdrawFromV1toV2(\\\\n        uint256 _v1Shares,\\\\n        uint256 _ethToFlashDeposit,\\\\n        uint256 _ethToBorrow,\\\\n        uint256 _withdrawMaxEthToPay,\\\\n        uint24 _poolFee\\\\n    ) external afterMigration {\\\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\\\n\\\\n        require(!isFlashOnlyMigrate, \\\\\\\"M10\\\\\\\");\\\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\\\\\"M8\\\\\\\");\\\\n\\\\n        IEulerExec(euler).deferLiquidityCheck(\\\\n            address(this),\\\\n            abi.encode(\\\\n                FlashloanCallbackData({\\\\n                    caller: msg.sender,\\\\n                    amountToBorrow: _ethToBorrow,\\\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\\\n                    callData: abi.encode(\\\\n                        FlashMigrateAndBuyV1toV2({\\\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\\\n                            v1oSqthToPay: v1oSqthToPay,\\\\n                            crabV1ToWithdraw: _v1Shares,\\\\n                            poolFeeFlashDeposit: _poolFee\\\\n                        })\\\\n                    )\\\\n                })\\\\n            )\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get migration details for given amount of V1 shares\\\\n     * @param _v1Shares amount of crab V1 shares\\\\n     */\\\\n    function _flashMigrationDetails(uint256 _v1Shares)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            bool,\\\\n            uint256,\\\\n            uint256,\\\\n            uint256\\\\n        )\\\\n    {\\\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\\\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\\\\n\\\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\\\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\\\\n\\\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \\\\\\\"M4\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x276e3812b302205f2e657a443f808d978eeb593a0b52cf2b326eda3df2210bd3\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/CrabStrategy.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {StrategyBase} from \\\\\\\"./base/StrategyBase.sol\\\\\\\";\\\\nimport {StrategyFlashSwap} from \\\\\\\"./base/StrategyFlashSwap.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./base/StrategyMath.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev CrabStrategy contract\\\\n * @notice Contract for Crab strategy\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\\\n    uint256 public strategyCap;\\\\n\\\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\\\n    /// @dev twap period to use for hedge calculations\\\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum FLASH_SOURCE {\\\\n        FLASH_DEPOSIT,\\\\n        FLASH_WITHDRAW,\\\\n        FLASH_HEDGE_SELL,\\\\n        FLASH_HEDGE_BUY\\\\n    }\\\\n\\\\n    /// @dev ETH:WSqueeth uniswap pool\\\\n    address public immutable ethWSqueethPool;\\\\n    /// @dev strategy uniswap oracle\\\\n    address public immutable oracle;\\\\n    address public immutable ethQuoteCurrencyPool;\\\\n    address public immutable quoteCurrency;\\\\n\\\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\\\n    uint256 public deltaHedgeThreshold = 1e15;\\\\n    /// @dev time difference to trigger a hedge (seconds)\\\\n    uint256 public hedgeTimeThreshold;\\\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\\\n    uint256 public hedgePriceThreshold;\\\\n    /// @dev hedge auction duration (seconds)\\\\n    uint256 public auctionTime;\\\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\\\n    uint256 public minPriceMultiplier;\\\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\\\n    uint256 public maxPriceMultiplier;\\\\n\\\\n    /// @dev timestamp when last hedge executed\\\\n    uint256 public timeAtLastHedge;\\\\n    /// @dev WSqueeth/Eth price when last hedge executed\\\\n    uint256 public priceAtLastHedge;\\\\n\\\\n    /// @dev set to true when redeemShortShutdown has been called\\\\n    bool private hasRedeemedInShutdown;\\\\n\\\\n    struct FlashDepositData {\\\\n        uint256 totalDeposit;\\\\n    }\\\\n\\\\n    struct FlashWithdrawData {\\\\n        uint256 crabAmount;\\\\n    }\\\\n\\\\n    struct FlashHedgeData {\\\\n        uint256 wSqueethAmount;\\\\n        uint256 ethProceeds;\\\\n        uint256 minWSqueeth;\\\\n        uint256 minEth;\\\\n    }\\\\n\\\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\\\n    event TimeHedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        uint256 hedgeTimestamp,\\\\n        uint256 auctionTriggerTimestamp,\\\\n        uint256 minWSqueeth,\\\\n        uint256 minEth\\\\n    );\\\\n    event PriceHedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        uint256 hedgeTimestamp,\\\\n        uint256 auctionTriggerTimestamp,\\\\n        uint256 minWSqueeth,\\\\n        uint256 minEth\\\\n    );\\\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\\\n    event Hedge(\\\\n        address indexed hedger,\\\\n        bool auctionType,\\\\n        uint256 hedgerPrice,\\\\n        uint256 auctionPrice,\\\\n        uint256 wSqueethHedgeTargetAmount,\\\\n        uint256 ethHedgetargetAmount\\\\n    );\\\\n    event HedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        bool auctionType,\\\\n        uint256 auctionPrice,\\\\n        uint256 wSqueethHedgeTargetAmount,\\\\n        uint256 ethHedgetargetAmount\\\\n    );\\\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\\\n    event SetStrategyCap(uint256 newCapAmount);\\\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\\\n    event SetAuctionTime(uint256 newAuctionTime);\\\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\\\n\\\\n    /**\\\\n     * @notice strategy constructor\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _wSqueethController power token controller address\\\\n     * @param _oracle oracle address\\\\n     * @param _weth weth address\\\\n     * @param _uniswapFactory uniswap factory address\\\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\\\n     * @param _auctionTime auction duration (seconds)\\\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\\\n     */\\\\n    constructor(\\\\n        address _wSqueethController,\\\\n        address _oracle,\\\\n        address _weth,\\\\n        address _uniswapFactory,\\\\n        address _ethWSqueethPool,\\\\n        uint256 _hedgeTimeThreshold,\\\\n        uint256 _hedgePriceThreshold,\\\\n        uint256 _auctionTime,\\\\n        uint256 _minPriceMultiplier,\\\\n        uint256 _maxPriceMultiplier\\\\n    ) StrategyBase(_wSqueethController, _weth, \\\\\\\"Crab Strategy\\\\\\\", \\\\\\\"Crab\\\\\\\") StrategyFlashSwap(_uniswapFactory) {\\\\n        require(_oracle != address(0), \\\\\\\"invalid oracle address\\\\\\\");\\\\n        require(_ethWSqueethPool != address(0), \\\\\\\"invalid ETH:WSqueeth address\\\\\\\");\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"invalid hedge time threshold\\\\\\\");\\\\n        require(_hedgePriceThreshold > 0, \\\\\\\"invalid hedge price threshold\\\\\\\");\\\\n        require(_auctionTime > 0, \\\\\\\"invalid auction time\\\\\\\");\\\\n        require(_minPriceMultiplier < 1e18, \\\\\\\"min price multiplier too high\\\\\\\");\\\\n        require(_minPriceMultiplier > 0, \\\\\\\"invalid min price multiplier\\\\\\\");\\\\n        require(_maxPriceMultiplier > 1e18, \\\\\\\"max price multiplier too low\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        ethWSqueethPool = _ethWSqueethPool;\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n        auctionTime = _auctionTime;\\\\n        minPriceMultiplier = _minPriceMultiplier;\\\\n        maxPriceMultiplier = _maxPriceMultiplier;\\\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\\\\\"Cannot receive eth\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the strategy cap in ETH collateral terms\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\\\n        strategyCap = _capAmount;\\\\n\\\\n        emit SetStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to redeem the net value of a vault post shutdown\\\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\\\n     */\\\\n    function redeemShortShutdown() external {\\\\n        hasRedeemedInShutdown = true;\\\\n        powerTokenController.redeemShort(vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\\n     */\\\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\\\n            _ethToDeposit,\\\\n            cachedStrategyDebt,\\\\n            cachedStrategyCollateral\\\\n        );\\\\n\\\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\\\n            // store hedge data as strategy is delta neutral at this point\\\\n            // only execute this upon first deposit\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\\\n                ethWSqueethPool,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                hedgingTwapPeriod,\\\\n                true\\\\n            );\\\\n            timeAtLastHedge = block.timestamp;\\\\n            priceAtLastHedge = wSqueethEthPrice;\\\\n        }\\\\n\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n            wSqueethToMint,\\\\n            _ethToDeposit.sub(msg.value),\\\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\\\n            abi.encodePacked(_ethToDeposit)\\\\n        );\\\\n\\\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\\n     * @param _crabAmount strategy token amount to burn\\\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\\\n     */\\\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n            exactWSqueethNeeded,\\\\n            _maxEthToPay,\\\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\\\n            abi.encodePacked(_crabAmount)\\\\n        );\\\\n\\\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit ETH into strategy\\\\n     * @dev provide ETH, return wSqueeth and strategy token\\\\n     */\\\\n    function deposit() external payable nonReentrant {\\\\n        uint256 amount = msg.value;\\\\n\\\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\\\n\\\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\\\n\\\\n        // send back ETH collateral\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n\\\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\\\n        require(powerTokenController.isShutDown(), \\\\\\\"Squeeth contracts not shut down\\\\\\\");\\\\n        require(hasRedeemedInShutdown, \\\\\\\"Crab must redeemShortShutdown\\\\\\\");\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\\\n        _burn(msg.sender, _crabAmount);\\\\n\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\\\n     * @dev between uniswap execution price and the price of the hedging auction\\\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\\\n     */\\\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\\\n\\\\n        require(isTimeHedgeAllowed, \\\\\\\"Time hedging is not allowed\\\\\\\");\\\\n\\\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\\\n\\\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\\\n     * @dev between uniswap execution price and the price of the hedging auction\\\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\\\n     */\\\\n    function priceHedgeOnUniswap(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _minWSqueeth,\\\\n        uint256 _minEth\\\\n    ) external payable {\\\\n        require(_isPriceHedge(_auctionTriggerTime), \\\\\\\"Price hedging not allowed\\\\\\\");\\\\n\\\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\\\n\\\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy hedging based on time threshold\\\\n     * @dev need to attach msg.value if buying WSqueeth\\\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\\\n     */\\\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\\\n\\\\n        require(isTimeHedgeAllowed, \\\\\\\"Time hedging is not allowed\\\\\\\");\\\\n\\\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\\\n\\\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy hedging based on price threshold\\\\n     * @dev need to attach msg.value if buying WSqueeth\\\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\\\n     */\\\\n    function priceHedge(\\\\n        uint256 _auctionTriggerTime,\\\\n        bool _isStrategySellingWSqueeth,\\\\n        uint256 _limitPrice\\\\n    ) external payable nonReentrant {\\\\n        require(_isPriceHedge(_auctionTriggerTime), \\\\\\\"Price hedging not allowed\\\\\\\");\\\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\\\n\\\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\\\n        return _isPriceHedge(_auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\\\n     * @return auctionTriggertime auction trigger timestamp\\\\n     */\\\\n    function checkTimeHedge() external view returns (bool, uint256) {\\\\n        return _isTimeHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\\\n     * @param _crabAmount strategy token amount\\\\n     * @return wSqueeth amount\\\\n     */\\\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\\\n        return _getDebtFromStrategyAmount(_crabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\\\n     */\\\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\\\n\\\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\\\n     */\\\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\\\n        require(_hedgingTwapPeriod >= 180, \\\\\\\"twap period is too short\\\\\\\");\\\\n\\\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\\\n\\\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\\\n     */\\\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"invalid hedge time threshold\\\\\\\");\\\\n\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n\\\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\\\n     */\\\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\\\n        require(_hedgePriceThreshold > 0, \\\\\\\"invalid hedge price threshold\\\\\\\");\\\\n\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n\\\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\\\n     * @param _auctionTime the length of the hedge auction in seconds\\\\n     */\\\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\\\n        require(_auctionTime > 0, \\\\\\\"invalid auction time\\\\\\\");\\\\n\\\\n        auctionTime = _auctionTime;\\\\n\\\\n        emit SetAuctionTime(_auctionTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\\\n     */\\\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\\\n        require(_minPriceMultiplier < 1e18, \\\\\\\"min price multiplier too high\\\\\\\");\\\\n\\\\n        minPriceMultiplier = _minPriceMultiplier;\\\\n\\\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\\\n     */\\\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\\\n        require(_maxPriceMultiplier > 1e18, \\\\\\\"max price multiplier too low\\\\\\\");\\\\n\\\\n        maxPriceMultiplier = _maxPriceMultiplier;\\\\n\\\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get current auction details\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\\\n     */\\\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            bool,\\\\n            uint256,\\\\n            uint256,\\\\n            uint256,\\\\n            bool\\\\n        )\\\\n    {\\\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            hedgingTwapPeriod,\\\\n            true\\\\n        );\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\\\n            strategyDebt,\\\\n            ethDelta,\\\\n            auctionWSqueethEthPrice,\\\\n            feeAdjustment\\\\n        );\\\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\\\n\\\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a user deposit puts the strategy above the cap\\\\n     * @dev reverts if a deposit amount puts strategy over the cap\\\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\\\n     * @param _depositAmount the user deposit amount in ETH\\\\n     * @param _strategyCollateral the updated strategy collateral\\\\n     */\\\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\\\\\"Deposit exceeds strategy cap\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _strategyFlash(\\\\n        address _caller,\\\\n        address, /*_tokenIn*/\\\\n        address, /*_tokenOut*/\\\\n        uint24, /*_fee*/\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n\\\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\\\n            //will revert if data.totalDeposit is > eth balance in contract\\\\n            _deposit(_caller, data.totalDeposit, true);\\\\n\\\\n            //repay the flash swap\\\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\\\n\\\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\\\n\\\\n            //return excess eth to the user that was not needed for slippage\\\\n            if (address(this).balance > 0) {\\\\n                payable(_caller).sendValue(address(this).balance);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\\\n\\\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\\\n            uint256 ethToWithdraw = _withdraw(\\\\n                _caller,\\\\n                data.crabAmount,\\\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\\\n                true\\\\n            );\\\\n\\\\n            //use some amount of withdrawn ETH to repay flash swap\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\\\n\\\\n            //excess ETH not used to repay flash swap is transferred to the user\\\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\\\n\\\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\\\n\\\\n            if (proceeds > 0) {\\\\n                payable(_caller).sendValue(proceeds);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\\\n            //strategy is selling wSqueeth for ETH\\\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\\\n\\\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\\\n\\\\n            //minimum profit check for hedger\\\\n            require(wSqueethProfit >= data.minWSqueeth, \\\\\\\"profit is less than min wSqueeth\\\\\\\");\\\\n\\\\n            //repay flash swap and transfer profit to hedger\\\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\\\n            //strategy is buying wSqueeth for ETH\\\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\\\n\\\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\\\n\\\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\\\n\\\\n            //minimum profit check for hedger\\\\n            require(ethProfit >= data.minEth, \\\\\\\"profit is less than min ETH\\\\\\\");\\\\n\\\\n            //repay flash swap and transfer profit to hedger\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\\\n            payable(_caller).sendValue(ethProfit);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit into strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _depositor depositor address\\\\n     * @param _amount amount of ETH collateral to deposit\\\\n     * @param _isFlashDeposit true if called by flashDeposit\\\\n     * @return wSqueethToMint minted amount of WSqueeth\\\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\\\n     */\\\\n    function _deposit(\\\\n        address _depositor,\\\\n        uint256 _amount,\\\\n        bool _isFlashDeposit\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_amount, strategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\\\n\\\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\\\n\\\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\\\n            // store hedge data as strategy is delta neutral at this point\\\\n            // only execute this upon first deposit\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\\\n                ethWSqueethPool,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                hedgingTwapPeriod,\\\\n                true\\\\n            );\\\\n            timeAtLastHedge = block.timestamp;\\\\n            priceAtLastHedge = wSqueethEthPrice;\\\\n        }\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\\\n\\\\n        return (wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\\\n     * @return ETH amount to withdraw\\\\n     */\\\\n    function _withdraw(\\\\n        address _from,\\\\n        uint256 _crabAmount,\\\\n        uint256 _wSqueethAmount,\\\\n        bool _isFlashWithdraw\\\\n    ) internal returns (uint256) {\\\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\\\n\\\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\\\n        _burn(_from, _crabAmount);\\\\n\\\\n        return ethToWithdraw;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\\\n     */\\\\n    function _hedge(\\\\n        uint256 _auctionTriggerTime,\\\\n        bool _isStrategySellingWSqueeth,\\\\n        uint256 _limitPrice\\\\n    ) internal {\\\\n        (\\\\n            bool isSellingAuction,\\\\n            uint256 wSqueethToAuction,\\\\n            uint256 ethProceeds,\\\\n            uint256 auctionWSqueethEthPrice\\\\n        ) = _startAuction(_auctionTriggerTime);\\\\n\\\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\\\\\"wrong auction type\\\\\\\");\\\\n\\\\n        if (isSellingAuction) {\\\\n            // Receiving ETH and paying wSqueeth\\\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\\\\\"Auction price > max price\\\\\\\");\\\\n            require(msg.value >= ethProceeds, \\\\\\\"Low ETH amount received\\\\\\\");\\\\n\\\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\\\n        } else {\\\\n            require(msg.value == 0, \\\\\\\"ETH attached for buy auction\\\\\\\");\\\\n            // Receiving wSqueeth and paying ETH\\\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\\\\\"Auction price < min price\\\\\\\");\\\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\\\n        }\\\\n\\\\n        emit Hedge(\\\\n            msg.sender,\\\\n            _isStrategySellingWSqueeth,\\\\n            _limitPrice,\\\\n            auctionWSqueethEthPrice,\\\\n            wSqueethToAuction,\\\\n            ethProceeds\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute arb between auction price and uniswap price\\\\n     * @param _auctionTriggerTime auction starting time\\\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\\\n     */\\\\n    function _hedgeOnUniswap(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _minWSqueeth,\\\\n        uint256 _minEth\\\\n    ) internal {\\\\n        (\\\\n            bool isSellingAuction,\\\\n            uint256 wSqueethToAuction,\\\\n            uint256 ethProceeds,\\\\n            uint256 auctionWSqueethEthPrice\\\\n        ) = _startAuction(_auctionTriggerTime);\\\\n\\\\n        if (isSellingAuction) {\\\\n            _exactOutFlashSwap(\\\\n                wPowerPerp,\\\\n                weth,\\\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n                ethProceeds,\\\\n                wSqueethToAuction,\\\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\\\n            );\\\\n        } else {\\\\n            _exactOutFlashSwap(\\\\n                weth,\\\\n                wPowerPerp,\\\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n                wSqueethToAuction,\\\\n                ethProceeds,\\\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\\\n            );\\\\n        }\\\\n\\\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute sell auction based on the parameters calculated\\\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\\\n     * @param _buyer buyer address\\\\n     * @param _buyerAmount buyer ETH amount sent\\\\n     * @param _wSqueethToSell wSqueeth amount to sell\\\\n     * @param _ethToBuy ETH amount to buy\\\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\\\n     */\\\\n    function _executeSellAuction(\\\\n        address _buyer,\\\\n        uint256 _buyerAmount,\\\\n        uint256 _wSqueethToSell,\\\\n        uint256 _ethToBuy,\\\\n        bool _isHedgingOnUniswap\\\\n    ) internal {\\\\n        if (_isHedgingOnUniswap) {\\\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\\\n        } else {\\\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\\\n\\\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\\\n\\\\n            if (remainingEth > 0) {\\\\n                payable(_buyer).sendValue(remainingEth);\\\\n            }\\\\n        }\\\\n\\\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute buy auction based on the parameters calculated\\\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\\\n     * @param _seller seller address\\\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\\\n     * @param _ethToSell ETH amount to sell\\\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\\\n     */\\\\n    function _executeBuyAuction(\\\\n        address _seller,\\\\n        uint256 _wSqueethToBuy,\\\\n        uint256 _ethToSell,\\\\n        bool _isHedgingOnUniswap\\\\n    ) internal {\\\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\\\n\\\\n        if (!_isHedgingOnUniswap) {\\\\n            payable(_seller).sendValue(_ethToSell);\\\\n        }\\\\n\\\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\\\n     * @param _auctionTriggerTime auction starting time\\\\n     * @return auction type\\\\n     * @return WSqueeth amount to sell or buy\\\\n     * @return ETH to sell/buy\\\\n     * @return auction WSqueeth/ETH price\\\\n     */\\\\n    function _startAuction(uint256 _auctionTriggerTime)\\\\n        internal\\\\n        returns (\\\\n            bool,\\\\n            uint256,\\\\n            uint256,\\\\n            uint256\\\\n        )\\\\n    {\\\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            hedgingTwapPeriod,\\\\n            true\\\\n        );\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\\\n            strategyDebt,\\\\n            ethDelta,\\\\n            auctionWSqueethEthPrice,\\\\n            feeAdjustment\\\\n        );\\\\n\\\\n        require(isSellingAuction == isStillSellingAuction, \\\\\\\"auction direction changed\\\\\\\");\\\\n\\\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\\\n\\\\n        timeAtLastHedge = block.timestamp;\\\\n        priceAtLastHedge = currentWSqueethPrice;\\\\n\\\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sync strategy debt and collateral amount from vault\\\\n     * @return synced debt amount\\\\n     * @return synced collateral amount\\\\n     */\\\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\\\n\\\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\\\n     * @return the fee adjustment factor\\\\n     */\\\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\\\n            oracle,\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            POWER_PERP_PERIOD,\\\\n            false\\\\n        );\\\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\\\n     * @param _depositedAmount amount of deposited WETH\\\\n     * @param _strategyDebtAmount amount of strategy debt\\\\n     * @param _strategyCollateralAmount collateral amount in strategy\\\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\\\n     */\\\\n    function _calcWsqueethToMintAndFee(\\\\n        uint256 _depositedAmount,\\\\n        uint256 _strategyDebtAmount,\\\\n        uint256 _strategyCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 wSqueethToMint;\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n\\\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\\\n            require(totalSupply() == 0, \\\\\\\"Crab contracts shut down\\\\\\\");\\\\n\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\\\n                ethWSqueethPool,\\\\n                wPowerPerp,\\\\n                weth,\\\\n                hedgingTwapPeriod,\\\\n                true\\\\n            );\\\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\\\n        } else {\\\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\\\n            );\\\\n        }\\\\n\\\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\\\n\\\\n        return (wSqueethToMint, fee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if time hedging is allowed\\\\n     * @return auction trigger timestamp\\\\n     */\\\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\\\n\\\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\\\n            secondsToPriceHedgeTrigger\\\\n        );\\\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\\\n\\\\n        return priceThreshold >= hedgePriceThreshold;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\\\n     * @return auction price\\\\n     */\\\\n    function _getAuctionPrice(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _wSqueethEthPrice,\\\\n        bool _isSellingAuction\\\\n    ) internal view returns (uint256) {\\\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\\\n            ? 1e18\\\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\\\n\\\\n        uint256 priceMultiplier;\\\\n        if (_isSellingAuction) {\\\\n            priceMultiplier = maxPriceMultiplier.sub(\\\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\\\n            );\\\\n        } else {\\\\n            priceMultiplier = minPriceMultiplier.add(\\\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\\\n            );\\\\n        }\\\\n\\\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\\\n     * @param _debt strategy debt\\\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\\\n     */\\\\n    function _checkAuctionType(\\\\n        uint256 _debt,\\\\n        uint256 _ethDelta,\\\\n        uint256 _wSqueethEthPrice,\\\\n        uint256 _feeAdjustment\\\\n    ) internal view returns (bool, uint256) {\\\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\\\n\\\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\\\n            wSqueethDelta,\\\\n            _ethDelta,\\\\n            _wSqueethEthPrice,\\\\n            _feeAdjustment\\\\n        );\\\\n\\\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\\\\\"strategy is delta neutral\\\\\\\");\\\\n\\\\n        return (isSellingAuction, targetHedge);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate amount of strategy token to mint for depositor\\\\n     * @param _amount amount of ETH deposited\\\\n     * @param _strategyCollateralAmount amount of strategy collateral\\\\n     * @param _crabTotalSupply total supply of strategy token\\\\n     * @return amount of strategy token to mint\\\\n     */\\\\n    function _calcSharesToMint(\\\\n        uint256 _amount,\\\\n        uint256 _strategyCollateralAmount,\\\\n        uint256 _crabTotalSupply\\\\n    ) internal pure returns (uint256) {\\\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\\\n\\\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\\\n\\\\n        return _amount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\\\n     * @param _crabAmount strategy token amount\\\\n     * @param _totalSupply strategy total supply\\\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\\\n     */\\\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\\\n        return _crabAmount.wdiv(_totalSupply);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\\\n     * @param _crabRatio crab ratio\\\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\\\n     * @return amount of ETH allowed to withdraw\\\\n     */\\\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine target hedge and auction type (selling/buying auction)\\\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\\\n     * @param _wSqueethDelta WSqueeth delta\\\\n     * @param _ethDelta ETH delta\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\\\n     * @return target hedge in wSqueeth\\\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\\\n     */\\\\n    function _getTargetHedgeAndAuctionType(\\\\n        uint256 _wSqueethDelta,\\\\n        uint256 _ethDelta,\\\\n        uint256 _wSqueethEthPrice,\\\\n        uint256 _feeAdjustment\\\\n    ) internal pure returns (uint256, bool) {\\\\n        return\\\\n            (_wSqueethDelta > _ethDelta)\\\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86a9d034ce1d510b05c23a0e2d42865823c676e17685494bde6c954504062366\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/CrabStrategyV2.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {StrategyBase} from \\\\\\\"./base/StrategyBase.sol\\\\\\\";\\\\nimport {StrategyFlashSwap} from \\\\\\\"./base/StrategyFlashSwap.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\nimport {EIP712} from \\\\\\\"@openzeppelin/contracts/drafts/EIP712.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./base/StrategyMath.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\nimport {ECDSA} from \\\\\\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Crab V2 Error Codes:\\\\n * C1: Caller is not timelock\\\\n * C2: Contract not yet initialized\\\\n * C3: Invalid oracle address\\\\n * C4: Invalid timelock address\\\\n * C5: Invalid ETH:WSqueeth address\\\\n * C6: Invalid crabMigration address\\\\n * C7: Invalid hedge time threshold\\\\n * C8: Invalid hedge price threshold\\\\n * C9: Cannot receive ETH\\\\n * C10: Caller not Crab Migration contract\\\\n * C11: Crab V2 already initialized\\\\n * C12: Squeeth contracts not shut down\\\\n * C13: Crab must redeemShortShutdown\\\\n * C14: Twap period is too short\\\\n * C15: Price tolerance is too high\\\\n * C16: Deposit exceeds strategy cap\\\\n * C17: Clearing Price should be below bid price\\\\n * C18: Clearing Price should be above offer price\\\\n * C19: Invalid offer signature\\\\n * C20: Order has expired\\\\n * C21: Manager Price should be greater than 0\\\\n * C22: Not a valid Time or Price hedge\\\\n * C23: Orders must take the opposite side of the hedge\\\\n * C24: All orders must be either buying or selling\\\\n * C25: Orders are not arranged properly\\\\n * C26: Crab contracts shut down\\\\n *  C27: Nonce already used.\\\\n */\\\\n\\\\n/**\\\\n * @dev CrabStrategyV2 contract\\\\n * @notice Contract for Crab strategy\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\\\n    uint256 public strategyCap;\\\\n\\\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\\\n\\\\n    /// @dev basic unit used for calculation\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    // @dev OTC price must be within this distance of the uniswap twap price\\\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\\\n\\\\n    // @dev OTC price tolerance cannot exceed 20%\\\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\\\n\\\\n    /// @dev twap period to use for hedge calculations\\\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\\\n    /// @dev true if CrabV2 was initialized\\\\n    bool public isInitialized;\\\\n\\\\n    /// @dev typehash for signed orders\\\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\\\n        keccak256(\\\\n            \\\\\\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\\\\\"\\\\n        );\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum FLASH_SOURCE {\\\\n        FLASH_DEPOSIT,\\\\n        FLASH_WITHDRAW\\\\n    }\\\\n\\\\n    /// @dev ETH:wSqueeth uniswap pool\\\\n    address public immutable ethWSqueethPool;\\\\n    /// @dev strategy uniswap oracle\\\\n    address public immutable oracle;\\\\n    address public immutable timelock;\\\\n    address public immutable crabMigration;\\\\n\\\\n    /// @dev time difference to trigger a hedge (seconds)\\\\n    uint256 public hedgeTimeThreshold;\\\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\\\n    uint256 public hedgePriceThreshold;\\\\n\\\\n    /// @dev timestamp when last hedge executed\\\\n    uint256 public timeAtLastHedge;\\\\n    /// @dev wSqueeth/Eth price when last hedge executed\\\\n    uint256 public priceAtLastHedge;\\\\n\\\\n    /// @dev set to true when redeemShortShutdown has been called\\\\n    bool private hasRedeemedInShutdown;\\\\n\\\\n    /// @dev store the used flag for a nonce for each address\\\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\\\n\\\\n    struct FlashDepositData {\\\\n        uint256 totalDeposit;\\\\n    }\\\\n\\\\n    struct FlashWithdrawData {\\\\n        uint256 crabAmount;\\\\n    }\\\\n\\\\n    struct Order {\\\\n        uint256 bidId;\\\\n        address trader;\\\\n        uint256 quantity;\\\\n        uint256 price;\\\\n        bool isBuying;\\\\n        uint256 expiry;\\\\n        uint256 nonce;\\\\n        uint8 v;\\\\n        bytes32 r;\\\\n        bytes32 s;\\\\n    }\\\\n\\\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\\\n    event HedgeOTCSingle(\\\\n        address trader,\\\\n        uint256 bidId,\\\\n        uint256 quantity,\\\\n        uint256 price,\\\\n        bool isBuying,\\\\n        uint256 clearingPrice\\\\n    );\\\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\\\n    event SetStrategyCap(uint256 newCapAmount);\\\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\\\n\\\\n    modifier onlyTimelock() {\\\\n        require(msg.sender == timelock, \\\\\\\"C1\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier afterInitialization() {\\\\n        require(isInitialized, \\\\\\\"C2\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy constructor\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _wSqueethController power token controller address\\\\n     * @param _oracle oracle address\\\\n     * @param _weth weth address\\\\n     * @param _uniswapFactory uniswap factory address\\\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\\\n     * @param _timelock timelock contract address\\\\n     * @param _crabMigration crab migration contract address\\\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\\\n     */\\\\n    constructor(\\\\n        address _wSqueethController,\\\\n        address _oracle,\\\\n        address _weth,\\\\n        address _uniswapFactory,\\\\n        address _ethWSqueethPool,\\\\n        address _timelock,\\\\n        address _crabMigration,\\\\n        uint256 _hedgeTimeThreshold,\\\\n        uint256 _hedgePriceThreshold\\\\n    )\\\\n        StrategyBase(_wSqueethController, _weth, \\\\\\\"Crab Strategy v2\\\\\\\", \\\\\\\"Crabv2\\\\\\\")\\\\n        StrategyFlashSwap(_uniswapFactory)\\\\n        EIP712(\\\\\\\"CrabOTC\\\\\\\", \\\\\\\"2\\\\\\\")\\\\n    {\\\\n        require(_oracle != address(0), \\\\\\\"C3\\\\\\\");\\\\n        require(_timelock != address(0), \\\\\\\"C4\\\\\\\");\\\\n        require(_ethWSqueethPool != address(0), \\\\\\\"C5\\\\\\\");\\\\n        require(_crabMigration != address(0), \\\\\\\"C6\\\\\\\");\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"C7\\\\\\\");\\\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\\\\\"C8\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        ethWSqueethPool = _ethWSqueethPool;\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n        timelock = _timelock;\\\\n        crabMigration = _crabMigration;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\\\\\"C9\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice initializes the collateral ratio after the first migration\\\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\\\n     * @param _crabSharesToMint crab shares to mint\\\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\\\n     * @param _strategyCap strategy cap for crab V2\\\\n     */\\\\n    function initialize(\\\\n        uint256 _wSqueethToMint,\\\\n        uint256 _crabSharesToMint,\\\\n        uint256 _timeAtLastHedge,\\\\n        uint256 _priceAtLastHedge,\\\\n        uint256 _strategyCap\\\\n    ) external payable {\\\\n        require(msg.sender == crabMigration, \\\\\\\"C10\\\\\\\");\\\\n        require(!isInitialized, \\\\\\\"C11\\\\\\\");\\\\n\\\\n        _setStrategyCap(_strategyCap);\\\\n\\\\n        uint256 amount = msg.value;\\\\n\\\\n        _checkStrategyCap(amount, 0);\\\\n\\\\n        // store hedge data from crab V1\\\\n        timeAtLastHedge = _timeAtLastHedge;\\\\n        priceAtLastHedge = _priceAtLastHedge;\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\\\n\\\\n        isInitialized = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice transfer vault NFT to new contract\\\\n     * @dev strategy cap is set to 0 to avoid future deposits\\\\n     * @param _newStrategy new strategy contract address\\\\n     */\\\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\\\n        _setStrategyCap(0);\\\\n\\\\n        emit VaultTransferred(_newStrategy, vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the strategy cap in ETH collateral terms\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\\\n        _setStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set strategy cap amount\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function _setStrategyCap(uint256 _capAmount) internal {\\\\n        strategyCap = _capAmount;\\\\n        emit SetStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to redeem the net value of a vault post shutdown\\\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\\\n     */\\\\n    function redeemShortShutdown() external afterInitialization {\\\\n        hasRedeemedInShutdown = true;\\\\n        powerTokenController.redeemShort(vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\\n     * @param _poolFee Uniswap pool fee\\\\n     */\\\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\\\n            _ethToDeposit,\\\\n            cachedStrategyDebt,\\\\n            cachedStrategyCollateral\\\\n        );\\\\n\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            _poolFee,\\\\n            wSqueethToMint,\\\\n            _ethToDeposit.sub(msg.value),\\\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\\\n            abi.encodePacked(_ethToDeposit)\\\\n        );\\\\n\\\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\\n     * @param _crabAmount strategy token amount to burn\\\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\\\n     * @param _poolFee Uniswap pool fee\\\\n\\\\n     */\\\\n    function flashWithdraw(\\\\n        uint256 _crabAmount,\\\\n        uint256 _maxEthToPay,\\\\n        uint24 _poolFee\\\\n    ) external nonReentrant {\\\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            _poolFee,\\\\n            exactWSqueethNeeded,\\\\n            _maxEthToPay,\\\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\\\n            abi.encodePacked(_crabAmount)\\\\n        );\\\\n\\\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit ETH into strategy\\\\n     * @dev provide ETH, return wSqueeth and strategy token\\\\n     */\\\\n    function deposit() external payable nonReentrant {\\\\n        uint256 amount = msg.value;\\\\n\\\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\\\n\\\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\\\n\\\\n        // send back ETH collateral\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n\\\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\\\n        require(powerTokenController.isShutDown(), \\\\\\\"C12\\\\\\\");\\\\n        require(hasRedeemedInShutdown, \\\\\\\"C13\\\\\\\");\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\\\n        _burn(msg.sender, _crabAmount);\\\\n\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set nonce to true\\\\n     * @param _nonce the number to be set true\\\\n     */\\\\n    function setNonceTrue(uint256 _nonce) external {\\\\n        nonces[msg.sender][_nonce] = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\\\n     * @param _crabAmount strategy token amount\\\\n     * @return wSqueeth amount\\\\n     */\\\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\\\n        return _getDebtFromStrategyAmount(_crabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\\\n     */\\\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\\\n        require(_hedgingTwapPeriod >= 180, \\\\\\\"C14\\\\\\\");\\\\n\\\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\\\n\\\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\\\n     */\\\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"C7\\\\\\\");\\\\n\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n\\\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\\\n     */\\\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\\\\\"C8\\\\\\\");\\\\n\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n\\\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\\\n     */\\\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\\\n        // Tolerance cannot be more than 20%\\\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\\\\\"C15\\\\\\\");\\\\n\\\\n        otcPriceTolerance = _otcPriceTolerance;\\\\n\\\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a user deposit puts the strategy above the cap\\\\n     * @dev reverts if a deposit amount puts strategy over the cap\\\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\\\n     * @param _depositAmount the user deposit amount in ETH\\\\n     * @param _strategyCollateral the updated strategy collateral\\\\n     */\\\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\\\\\"C16\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _strategyFlash(\\\\n        address _caller,\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        uint24 _fee,\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n\\\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\\\n            // will revert if data.totalDeposit is > eth balance in contract\\\\n            _deposit(_caller, data.totalDeposit, true);\\\\n\\\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\\\n\\\\n            // repay the flash swap\\\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\\\n\\\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\\\n\\\\n            // return excess eth to the user that was not needed for slippage\\\\n            if (address(this).balance > 0) {\\\\n                payable(_caller).sendValue(address(this).balance);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\\\n\\\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\\\n            uint256 ethToWithdraw = _withdraw(\\\\n                _caller,\\\\n                data.crabAmount,\\\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\\\n                true\\\\n            );\\\\n\\\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\\\n\\\\n            // use some amount of withdrawn ETH to repay flash swap\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\\\n\\\\n            // excess ETH not used to repay flash swap is transferred to the user\\\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\\\n\\\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\\\n\\\\n            if (proceeds > 0) {\\\\n                payable(_caller).sendValue(proceeds);\\\\n            }\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit into strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _depositor depositor address\\\\n     * @param _amount amount of ETH collateral to deposit\\\\n     * @param _isFlashDeposit true if called by flashDeposit\\\\n     * @return wSqueethToMint minted amount of WSqueeth\\\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\\\n     */\\\\n    function _deposit(\\\\n        address _depositor,\\\\n        uint256 _amount,\\\\n        bool _isFlashDeposit\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_amount, strategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\\\n\\\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\\\n\\\\n        return (wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\\\n     * @return ETH amount to withdraw\\\\n     */\\\\n    function _withdraw(\\\\n        address _from,\\\\n        uint256 _crabAmount,\\\\n        uint256 _wSqueethAmount,\\\\n        bool _isFlashWithdraw\\\\n    ) internal returns (uint256) {\\\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\\\n\\\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\\\n        _burn(_from, _crabAmount);\\\\n\\\\n        return ethToWithdraw;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev set nonce flag of the trader to true\\\\n     * @param _trader address of the signer\\\\n     * @param _nonce number that is to be traded only once\\\\n     */\\\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\\\n        require(!nonces[_trader][_nonce], \\\\\\\"C27\\\\\\\");\\\\n        nonces[_trader][_nonce] = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev view function to get the domain seperator used in signing\\\\n     */\\\\n    // solhint-disable-next-line func-name-mixedcase\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\\\n        return _domainSeparatorV4();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev check the signer and swap tokens in the order\\\\n     * @param _remainingAmount quantity the manager wants to trade\\\\n     * @param _clearingPrice the price at which all orders are traded\\\\n     * @param _order a signed order to swap tokens\\\\n     */\\\\n    function _execOrder(\\\\n        uint256 _remainingAmount,\\\\n        uint256 _clearingPrice,\\\\n        Order memory _order\\\\n    ) internal {\\\\n        // check that order beats clearing price\\\\n        if (_order.isBuying) {\\\\n            require(_clearingPrice <= _order.price, \\\\\\\"C17\\\\\\\");\\\\n        } else {\\\\n            require(_clearingPrice >= _order.price, \\\\\\\"C18\\\\\\\");\\\\n        }\\\\n\\\\n        _useNonce(_order.trader, _order.nonce);\\\\n        bytes32 structHash = keccak256(\\\\n            abi.encode(\\\\n                _CRAB_BALANCE_TYPEHASH,\\\\n                _order.bidId,\\\\n                _order.trader,\\\\n                _order.quantity,\\\\n                _order.price,\\\\n                _order.isBuying,\\\\n                _order.expiry,\\\\n                _order.nonce\\\\n            )\\\\n        );\\\\n\\\\n        bytes32 hash = _hashTypedDataV4(structHash);\\\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\\\n        require(offerSigner == _order.trader, \\\\\\\"C19\\\\\\\");\\\\n        require(_order.expiry >= block.timestamp, \\\\\\\"C20\\\\\\\");\\\\n\\\\n        // adjust quantity for partial fills\\\\n        if (_remainingAmount < _order.quantity) {\\\\n            _order.quantity = _remainingAmount;\\\\n        }\\\\n        // weth clearing price for the order\\\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\\\n\\\\n        if (_order.isBuying) {\\\\n            // trader sends weth and receives oSQTH\\\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\\\n            IWETH9(weth).withdraw(wethAmount);\\\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\\\n        } else {\\\\n            // trader sends oSQTH and receives weth\\\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\\\n            // wrap it\\\\n            IWETH9(weth).deposit{value: wethAmount}();\\\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\\\n        }\\\\n\\\\n        emit HedgeOTCSingle(\\\\n            _order.trader, // market maker\\\\n            _order.bidId,\\\\n            _order.quantity, // order oSQTH quantity\\\\n            _order.price, // order price\\\\n            _order.isBuying, // order direction\\\\n            _clearingPrice // executed price for order\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev hedge function to reduce delta using an array of signed orders\\\\n     * @param _totalQuantity quantity the manager wants to trade\\\\n     * @param _clearingPrice clearing price in weth\\\\n     * @param _isHedgeBuying direction of hedge trade\\\\n     * @param _orders an array of signed order to swap tokens\\\\n     */\\\\n    function hedgeOTC(\\\\n        uint256 _totalQuantity,\\\\n        uint256 _clearingPrice,\\\\n        bool _isHedgeBuying,\\\\n        Order[] memory _orders\\\\n    ) external onlyOwner afterInitialization {\\\\n        require(_clearingPrice > 0, \\\\\\\"C21\\\\\\\");\\\\n        require(_isTimeHedge() || _isPriceHedge(), \\\\\\\"C22\\\\\\\");\\\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\\\n\\\\n        timeAtLastHedge = block.timestamp;\\\\n        priceAtLastHedge = _clearingPrice;\\\\n\\\\n        uint256 remainingAmount = _totalQuantity;\\\\n        uint256 prevPrice = _orders[0].price;\\\\n        uint256 currentPrice = _orders[0].price;\\\\n        bool isOrderBuying = _orders[0].isBuying;\\\\n        require(_isHedgeBuying != isOrderBuying, \\\\\\\"C23\\\\\\\");\\\\n\\\\n        // iterate through order array and execute if valid\\\\n        for (uint256 i; i < _orders.length; ++i) {\\\\n            currentPrice = _orders[i].price;\\\\n            require(_orders[i].isBuying == isOrderBuying, \\\\\\\"C24\\\\\\\");\\\\n            if (_isHedgeBuying) {\\\\n                require(currentPrice >= prevPrice, \\\\\\\"C25\\\\\\\");\\\\n            } else {\\\\n                require(currentPrice <= prevPrice, \\\\\\\"C25\\\\\\\");\\\\n            }\\\\n            prevPrice = currentPrice;\\\\n\\\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\\\n\\\\n            if (remainingAmount > _orders[i].quantity) {\\\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\\\n            } else {\\\\n                break;\\\\n            }\\\\n        }\\\\n\\\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\\\n     * @param _price clearing price provided by manager\\\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\\\n     */\\\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\\\n        // Get twap\\\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\\\n\\\\n        if (_isHedgeBuying) {\\\\n            require(\\\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\\\n                \\\\\\\"Price too high relative to Uniswap twap.\\\\\\\"\\\\n            );\\\\n        } else {\\\\n            require(\\\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\\\n                \\\\\\\"Price too low relative to Uniswap twap.\\\\\\\"\\\\n            );\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sync strategy debt and collateral amount from vault\\\\n     * @return synced debt amount\\\\n     * @return synced collateral amount\\\\n     */\\\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\\\n\\\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\\\n     * @return the fee adjustment factor\\\\n     */\\\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\\\n            oracle,\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            POWER_PERP_PERIOD,\\\\n            false\\\\n        );\\\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\\\n     * @param _depositedAmount amount of deposited WETH\\\\n     * @param _strategyDebtAmount amount of strategy debt\\\\n     * @param _strategyCollateralAmount collateral amount in strategy\\\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\\\n     */\\\\n    function _calcWsqueethToMintAndFee(\\\\n        uint256 _depositedAmount,\\\\n        uint256 _strategyDebtAmount,\\\\n        uint256 _strategyCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 wSqueethToMint;\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\\\n        require(!isShutdown, \\\\\\\"C26\\\\\\\");\\\\n\\\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\\\n        );\\\\n\\\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\\\n\\\\n        return (wSqueethToMint, fee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if time hedging is allowed\\\\n     */\\\\n    function _isTimeHedge() internal view returns (bool) {\\\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function _isPriceHedge() internal view returns (bool) {\\\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\\\n\\\\n        return priceThreshold >= hedgePriceThreshold;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkPriceHedge() external view returns (bool) {\\\\n        return _isPriceHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkTimeHedge() external view returns (bool) {\\\\n        return _isTimeHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate amount of strategy token to mint for depositor\\\\n     * @param _amount amount of ETH deposited\\\\n     * @param _strategyCollateralAmount amount of strategy collateral\\\\n     * @param _crabTotalSupply total supply of strategy token\\\\n     * @return amount of strategy token to mint\\\\n     */\\\\n    function _calcSharesToMint(\\\\n        uint256 _amount,\\\\n        uint256 _strategyCollateralAmount,\\\\n        uint256 _crabTotalSupply\\\\n    ) internal pure returns (uint256) {\\\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\\\n\\\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\\\n\\\\n        return _amount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\\\n     * @param _crabAmount strategy token amount\\\\n     * @param _totalSupply strategy total supply\\\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\\\n     */\\\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\\\n        return _crabAmount.wdiv(_totalSupply);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\\\n     * @param _crabRatio crab ratio\\\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\\\n     * @return amount of ETH allowed to withdraw\\\\n     */\\\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8b1900ce7c5c79e38af489819462339a27d677e2bb8626f7aa6f784409cbf3fa\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyBase.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./StrategyMath.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../../libs/VaultLib.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev StrategyBase contract\\\\n * @notice base contract for PowerToken strategy\\\\n * @author opyn team\\\\n */\\\\ncontract StrategyBase is ERC20 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev power token controller\\\\n    IController public powerTokenController;\\\\n\\\\n    /// @dev WETH token\\\\n    address public immutable weth;\\\\n    address public immutable wPowerPerp;\\\\n\\\\n    /// @dev power token strategy vault ID\\\\n    uint256 public immutable vaultId;\\\\n\\\\n    /**\\\\n     * @notice constructor for StrategyBase\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _powerTokenController power token controller address\\\\n     * @param _weth weth token address\\\\n     * @param _name token name for strategy ERC20 token\\\\n     * @param _symbol token symbol for strategy ERC20 token\\\\n     */\\\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\\\n        require(_powerTokenController != address(0), \\\\\\\"invalid controller address\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"invalid weth address\\\\\\\");\\\\n\\\\n        weth = _weth;\\\\n        powerTokenController = IController(_powerTokenController);\\\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\\\n    }\\\\n    /**\\\\n     * @notice get power token strategy vault ID \\\\n     * @return vault ID\\\\n     */\\\\n    function getStrategyVaultId() external view returns (uint256) {\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n    */\\\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\\\n        return _getVaultDetails();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint WPowerPerp and deposit collateral\\\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\\\n     * @param _to receiver address\\\\n     * @param _wAmount amount of WPowerPerp to mint\\\\n     * @param _collateral amount of collateral to deposit\\\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\\\n     */\\\\n    function _mintWPowerPerp(\\\\n        address _to,\\\\n        uint256 _wAmount,\\\\n        uint256 _collateral,\\\\n        bool _keepWsqueeth\\\\n    ) internal {\\\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\\\n\\\\n        if (!_keepWsqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn WPowerPerp and withdraw collateral\\\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\\\n     * @param _from WPowerPerp holder address\\\\n     * @param _amount amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\\\n     */\\\\n    function _burnWPowerPerp(\\\\n        address _from,\\\\n        uint256 _amount,\\\\n        uint256 _collateralToWithdraw,\\\\n        bool _isOwnedWSqueeth\\\\n    ) internal {\\\\n        if (!_isOwnedWSqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\\\n        }\\\\n\\\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint strategy token\\\\n     * @param _to recepient address\\\\n     * @param _amount token amount\\\\n     */\\\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\\\n        _mint(_to, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get strategy debt amount for a specific strategy token amount\\\\n     * @param _strategyAmount strategy amount\\\\n     * @return debt amount\\\\n     */\\\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n     */\\\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\\\n\\\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\\\n    }\\\\n}\\\\n\\\\n\\\",\\\"keccak256\\\":\\\"0xa18ad4c34899e27bdf048a866834e05dda91ee8ff904fac23587dddf69a5d675\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyFlashSwap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\\\n\\\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\\\n    using Path for bytes;\\\\n    using SafeCast for uint256;\\\\n    using LowGasSafeMath for uint256;\\\\n    using LowGasSafeMath for int256;\\\\n\\\\n    /// @dev Uniswap factory address\\\\n    address public immutable factory;\\\\n\\\\n    struct SwapCallbackData {\\\\n        bytes path;\\\\n        address caller;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev constructor\\\\n     * @param _factory uniswap factory address\\\\n     */\\\\n    constructor(\\\\n        address _factory\\\\n    ) {\\\\n        require(_factory != address(0), \\\\\\\"invalid factory address\\\\\\\");\\\\n        factory = _factory;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap swap callback function for flashes\\\\n     * @param amount0Delta amount of token0\\\\n     * @param amount1Delta amount of token1\\\\n     * @param _data callback data encoded as SwapCallbackData struct\\\\n     */\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata _data\\\\n    ) external override {\\\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\\\n\\\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //ensure that callback comes from uniswap pool\\\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\\\n\\\\n        //determine the amount that needs to be repaid as part of the flashswap\\\\n        uint256 amountToPay =\\\\n            amount0Delta > 0\\\\n                ?  uint256(amount0Delta)\\\\n                :  uint256(amount1Delta);\\\\n        \\\\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountIn amount to sell\\\\n     * @param _amountOutMinimum minimum amount to receive\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountOut = _exactInputInternal(\\\\n            _amountIn,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n       \\\\n        //slippage limit check\\\\n        require(amountOut >= _amountOutMinimum, \\\\\\\"amount out less than min\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountOut exact amount to receive\\\\n     * @param _amountInMaximum maximum amount to sell\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountIn = _exactOutputInternal(\\\\n            _amountOut,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n        \\\\n        //slippage limit check\\\\n        require(amountIn <= _amountInMaximum, \\\\\\\"amount in greater than max\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice function to be called by uniswap callback. \\\\n     * @dev this function should be overridden by the child contract\\\\n     * param _caller initial strategy function caller\\\\n     * param _tokenIn token address sold\\\\n     * param _tokenOut token address bought\\\\n     * param _fee pool fee\\\\n     * param _amountToPay amount to pay for the pool second token\\\\n     * param _callData arbitrary data assigned with the flashswap call \\\\n     * param _callSource function call source\\\\n     */\\\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\\\n    \\\\n    /** \\\\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\\\n    * @param _amountIn amount of token to pay\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token bought (amountOut)\\\\n    */\\\\n    function _exactInputInternal(\\\\n        uint256 _amountIn,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n       \\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0, int256 amount1) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                _amountIn.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n        \\\\n        //determine the amountOut based on which token has a lower address\\\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\\\n    * @param _amountOut amount of token to receive\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token sold (amountIn)\\\\n    */\\\\n    function _exactOutputInternal(\\\\n        uint256 _amountOut,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n        \\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0Delta, int256 amount1Delta) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                -_amountOut.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n\\\\n        //determine the amountIn and amountOut based on which token has a lower address\\\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\\\n        // it's technically possible to not receive the full output amount,\\\\n        // so if no price limit has been specified, require this possibility away\\\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\\\n\\\\n        return amountIn;\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice returns the uniswap pool for the given token pair and fee\\\\n    * @dev the pool contract may or may not exist\\\\n    * @param tokenA address of first token \\\\n    * @param tokenB address of second token \\\\n    * @param fee fee tier for pool\\\\n    */\\\\n    function _getPool(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool) {\\\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x91b49caf229fd114fbb589e73056772cf15a0adaba0a6f5eca4dff9cd12b9575\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/base/StrategyMath.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: AGPL-3.0-only\\\\n\\\\n/// math.sol -- mixin for inline numerical wizardry\\\\n\\\\n// This program is free software: you can redistribute it and/or modify\\\\n// it under the terms of the GNU General Public License as published by\\\\n// the Free Software Foundation, either version 3 of the License, or\\\\n// (at your option) any later version.\\\\n\\\\n// This program is distributed in the hope that it will be useful,\\\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\\\n// GNU General Public License for more details.\\\\n\\\\n// You should have received a copy of the GNU General Public License\\\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\\\n\\\\npragma solidity >0.4.13;\\\\n\\\\n\\\\n/**\\\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\\\n * @dev change contract to library, added div() function\\\\n */\\\\nlibrary StrategyMath {\\\\n    function add(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x + y) >= x, \\\\\\\"ds-math-add-overflow\\\\\\\");\\\\n    }\\\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x - y) <= x, \\\\\\\"ds-math-sub-underflow\\\\\\\");\\\\n    }\\\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\\\n        require(y == 0 || (z = x * y) / y == x, \\\\\\\"ds-math-mul-overflow\\\\\\\");\\\\n    }\\\\n\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    function min(uint x, uint y) internal pure returns (uint z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function max(uint x, uint y) internal pure returns (uint z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n    function imin(int x, int y) internal pure returns (int z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function imax(int x, int y) internal pure returns (int z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n\\\\n    uint constant WAD = 10 ** 18;\\\\n    uint constant RAY = 10 ** 27;\\\\n\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), WAD / 2) / WAD;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), RAY / 2) / RAY;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, WAD), y / 2) / y;\\\\n    }\\\\n    //rounds to zero if x*y < RAY / 2\\\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, RAY), y / 2) / y;\\\\n    }\\\\n\\\\n    // Ceil A to a multiple m\\\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(sub(add(a, m), 1), m), m);\\\\n    }\\\\n\\\\n    // Floor A to a multiple m\\\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(a, m), m);\\\\n    }\\\\n\\\\n    // This famous algorithm is called \\\\\\\"exponentiation by squaring\\\\\\\"\\\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\\\n    //\\\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\\\n    //\\\\n    // These facts are why it works:\\\\n    //\\\\n    //  If n is even, then x^n = (x^2)^(n/2).\\\\n    //  If n is odd,  then x^n = x * x^(n-1),\\\\n    //   and applying the equation for even x gives\\\\n    //    x^n = x * (x^2)^((n-1) / 2).\\\\n    //\\\\n    //  Also, EVM division is flooring and\\\\n    //    floor[(n-1) / 2] = floor[n / 2].\\\\n    //\\\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\\\n        z = n % 2 != 0 ? x : RAY;\\\\n\\\\n        for (n /= 2; n != 0; n /= 2) {\\\\n            x = rmul(x, x);\\\\n\\\\n            if (n % 2 != 0) {\\\\n                z = rmul(z, x);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0xfec6fa07fbbb639f94321d6503f5363286776cf831215017ce28aae67295613b\\\",\\\"license\\\":\\\"AGPL-3.0-only\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101206040523480156200001257600080fd5b5060405162003b3e38038062003b3e8339810160408190526200003591620003a3565b60006200004162000379565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b038316620000bd5760405162461bcd60e51b8152600401620000b49062000511565b60405180910390fd5b6001600160a01b038216620000e65760405162461bcd60e51b8152600401620000b49062000494565b6001600160a01b0381166200010f5760405162461bcd60e51b8152600401620000b4906200045d565b6001600160a01b038416620001385760405162461bcd60e51b8152600401620000b4906200057f565b6001600160a01b038516620001615760405162461bcd60e51b8152600401620000b49062000548565b836001600160a01b0316826001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b158015620001a557600080fd5b505afa158015620001ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001e091906200037d565b6001600160a01b031614620002095760405162461bcd60e51b8152600401620000b490620004cb565b600280546001600160a01b03808816610100908102610100600160a81b031990931692909217928390556001600160601b0319606087811b821660805285811b821660c05288811b821660a05286901b1660e052604080516307f07b1360e41b81529051929093041691637f07b130916004808301926020929190829003018186803b1580156200029957600080fd5b505afa158015620002ae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002d491906200037d565b60601b6001600160601b0319166101005260405163095ea7b360e01b81526001600160a01b0385169063095ea7b390620003179084906000199060040162000444565b602060405180830381600087803b1580156200033257600080fd5b505af115801562000347573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200036d919062000422565b505050505050620005cf565b3390565b6000602082840312156200038f578081fd5b81516200039c81620005b6565b9392505050565b600080600080600060a08688031215620003bb578081fd5b8551620003c881620005b6565b6020870151909550620003db81620005b6565b6040870151909450620003ee81620005b6565b60608701519093506200040181620005b6565b60808701519092506200041481620005b6565b809150509295509295909350565b60006020828403121562000434578081fd5b815180151581146200039c578182fd5b6001600160a01b03929092168252602082015260400190565b6020808252601d908201527f696e76616c6964205f65756c65724d61696e6e65742061646472657373000000604082015260600190565b60208082526017908201527f696e76616c6964205f64546f6b656e2061646472657373000000000000000000604082015260600190565b60208082526026908201527f64546f6b656e20756e6465726c79696e672061737365742073686f756c6420626040820152650ca40eecae8d60d31b606082015260800190565b6020808252601a908201527f696e76616c6964205f65756c6572457865632061646472657373000000000000604082015260600190565b60208082526017908201527f696e76616c6964205f6372616276312061646472657373000000000000000000604082015260600190565b60208082526015908201527f696e76616c6964205f7765746820616464726573730000000000000000000000604082015260600190565b6001600160a01b0381168114620005cc57600080fd5b50565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6134e46200065a60003980611c175280611ef052806121945280612572528061261652806129b1525080610d915280610f29525080610d1f52508061015852806105575280610e155280610e995250806105eb52806108665280610be5528061139552506134e46000f3fe6080604052600436106101485760003560e01c8063a15db5c5116100c0578063cb9d1ab811610074578063db661b7111610059578063db661b71146103d2578063f2fde38b146103e7578063fe7dd6e414610407576101cf565b8063cb9d1ab814610392578063d2cebf9b146103b2576101cf565b8063bab89ea3116100a5578063bab89ea31461032d578063bbac0aca14610342578063bbca7f1e14610362576101cf565b8063a15db5c5146102eb578063b06faf621461030b576101cf565b8063715018a6116101175780638da5cb5b116100fc5780638da5cb5b146102965780638e953732146102ab578063a13d7b33146102cb576101cf565b8063715018a61461026c5780637fa8c37014610281576101cf565b8063139d3799146101d45780631d4dab2c146101f45780633fc8cef31461022a578063581e74781461024c576101cf565b366101cf57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610193575060025461010090046001600160a01b031633145b806101a857506003546001600160a01b031633145b6101cd5760405162461bcd60e51b81526004016101c490613230565b60405180910390fd5b005b600080fd5b3480156101e057600080fd5b506101cd6101ef366004612ff6565b61041c565b34801561020057600080fd5b5061021461020f366004612d22565b610543565b6040516102219190613343565b60405180910390f35b34801561023657600080fd5b5061023f610555565b60405161022191906130a6565b34801561025857600080fd5b506101cd610267366004612ff6565b610579565b34801561027857600080fd5b506101cd6106dc565b34801561028d57600080fd5b5061023f6107a7565b3480156102a257600080fd5b5061023f6107bb565b3480156102b757600080fd5b506101cd6102c636600461302e565b6107ca565b3480156102d757600080fd5b506101cd6102e6366004612fc6565b61095e565b3480156102f757600080fd5b506101cd610306366004612d9c565b610cec565b34801561031757600080fd5b50610320610f97565b6040516102219190613119565b34801561033957600080fd5b506101cd610fa0565b34801561034e57600080fd5b506101cd61035d366004612d22565b61109f565b34801561036e57600080fd5b5061038261037d366004612fc6565b611168565b6040516102219493929190613124565b34801561039e57600080fd5b506101cd6103ad366004612fc6565b611186565b3480156103be57600080fd5b506101cd6103cd366004612fc6565b611282565b3480156103de57600080fd5b5061023f611393565b3480156103f357600080fd5b506101cd610402366004612d22565b6113b7565b34801561041357600080fd5b5061023f6114d8565b60025460ff1661043e5760405162461bcd60e51b81526004016101c49061324c565b336000908152600160205260409020548084111561046e5760405162461bcd60e51b81526004016101c49061316b565b61047881856114e7565b3360009081526001602052604090819020919091556003549051630b52b7ff60e41b81526001600160a01b039091169063b52b7ff0906104c09087908790879060040161335f565b600060405180830381600087803b1580156104da57600080fd5b505af11580156104ee573d6000803e3d6000fd5b50505050336001600160a01b03167f38d6d922c6452f3aaf90ad851ed15eb4c5c613c745d0531cf4337c07de651bab8560405161052b9190613343565b60405180910390a261053d3347611545565b50505050565b60016020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60025460ff1661059b5760405162461bcd60e51b81526004016101c49061324c565b60008060006105a98661162f565b50925092509250826105cd5760405162461bcd60e51b81526004016101c4906131bf565b60408051608081018252338152602081018490526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916389b7b7a69130918101600160ff16815260200160405180608001604052808781526020018b81526020018c81526020018a62ffffff1681525060405160200161065691906132ce565b60408051601f1981840301815291815291525161067691906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016106a29291906130de565b600060405180830381600087803b1580156106bc57600080fd5b505af11580156106d0573d6000803e3d6000fd5b50505050505050505050565b6106e46118d3565b6001600160a01b03166106f56107bb565b6001600160a01b031614610750576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b60025461010090046001600160a01b031681565b6000546001600160a01b031690565b60025460ff166107ec5760405162461bcd60e51b81526004016101c49061324c565b6000806107f88761162f565b509250509150811561081c5760405162461bcd60e51b81526004016101c4906131f7565b60008511801561082c5750600084115b6108485760405162461bcd60e51b81526004016101c490613187565b60408051608081018252338152602081018790526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916389b7b7a69130918101600260ff1681526020016040518060a001604052808781526020018c81526020018a81526020018d81526020018962ffffff168152506040516020016108d7919061328f565b60408051601f198184030181529181529152516108f791906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016109239291906130de565b600060405180830381600087803b15801561093d57600080fd5b505af1158015610951573d6000803e3d6000fd5b5050505050505050505050565b6109666118d3565b6001600160a01b03166109776107bb565b6001600160a01b0316146109d2576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6003546001600160a01b03166109fa5760405162461bcd60e51b81526004016101c490613268565b60025460ff1615610a1d5760405162461bcd60e51b81526004016101c490613214565b6002805460ff1916600117908190556040516370a0823160e01b81526000916001600160a01b0361010090910416906370a0823190610a609030906004016130a6565b60206040518083038186803b158015610a7857600080fd5b505afa158015610a8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab09190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b0257600080fd5b505afa158015610b16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3a9190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b158015610b8c57600080fd5b505afa158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc49190612d3e565b50925060009150610be19050610bda85856118d7565b8390611908565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060800160405280336001600160a01b0316815260200185815260200160006002811115610c4057fe5b60ff16815260200160405180602001604052808b815250604051602001610c679190613285565b60408051601f19818403018152918152915251610c8791906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610cb39291906130de565b600060405180830381600087803b158015610ccd57600080fd5b505af1158015610ce1573d6000803e3d6000fd5b505050505050505050565b6003546001600160a01b0316610d145760405162461bcd60e51b81526004016101c490613268565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d5c5760405162461bcd60e51b81526004016101c4906131a3565b600081806020019051810190610d729190612f1f565b6020810151604051630ecbcdab60e01b81529192506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691630ecbcdab91610dc89160009190600401613141565b600060405180830381600087803b158015610de257600080fd5b505af1158015610df6573d6000803e3d6000fd5b5050506020820151604051632e1a7d4d60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250632e1a7d4d91610e4991600401613343565b600060405180830381600087803b158015610e6357600080fd5b505af1158015610e77573d6000803e3d6000fd5b50505050610e978160000151826020015183604001518460600151611930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db082602001516040518263ffffffff1660e01b81526004016000604051808303818588803b158015610ef657600080fd5b505af1158015610f0a573d6000803e3d6000fd5b505050602083015160405163d8aed14560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063d8aed1459250610f6191600091600401613141565b600060405180830381600087803b158015610f7b57600080fd5b505af1158015610f8f573d6000803e3d6000fd5b505050505050565b60025460ff1681565b60025460ff16610fc25760405162461bcd60e51b81526004016101c49061324c565b336000818152600160205260408082208054929055600354905163a9059cbb60e01b815291926001600160a01b039091169163a9059cbb91611008918590600401613100565b602060405180830381600087803b15801561102257600080fd5b505af1158015611036573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105a9190612d7c565b50336001600160a01b03167f0adef25f8a7a2d6f3fb9761ba0c96c9752b6d985abd47e23b7fa3095ba8e4701826040516110949190613343565b60405180910390a250565b6110a76118d3565b6001600160a01b03166110b86107bb565b6001600160a01b031614611113576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166111395760405162461bcd60e51b81526004016101c4906131db565b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000806000806111778561162f565b93509350935093509193509193565b60025460ff16156111a95760405162461bcd60e51b81526004016101c490613214565b336000818152600160205260409081902080548401905560025490516323b872dd60e01b81526101009091046001600160a01b0316916323b872dd916111f69190309086906004016130ba565b602060405180830381600087803b15801561121057600080fd5b505af1158015611224573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112489190612d7c565b50336001600160a01b03167fcbfc37edaa5ac30951b21b47b70bbb70dd1e015fa918da25d516798c6a2622e8826040516110949190613343565b60025460ff16156112a55760405162461bcd60e51b81526004016101c490613214565b336000908152600160205260409020546112bf90826114e7565b336000818152600160205260409081902092909255600254915163a9059cbb60e01b81526101009092046001600160a01b03169163a9059cbb91611307918590600401613100565b602060405180830381600087803b15801561132157600080fd5b505af1158015611335573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113599190612d7c565b50336001600160a01b03167ffdef8f0daac171c9b3f7896ae8991c11b88b64b1b76b574d8189dcd0357e5f6e826040516110949190613343565b7f000000000000000000000000000000000000000000000000000000000000000081565b6113bf6118d3565b6001600160a01b03166113d06107bb565b6001600160a01b03161461142b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166114705760405162461bcd60e51b815260040180806020018281038252602681526020018061344f6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6003546001600160a01b031681565b8082038281111561153f576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b92915050565b8047101561159a576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146115e5576040519150601f19603f3d011682016040523d82523d6000602084013e6115ea565b606091505b505090508061162a5760405162461bcd60e51b815260040180806020018281038252603a815260200180613475603a913960400191505060405180910390fd5b505050565b600080600080600080600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561168657600080fd5b505afa15801561169a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116be9190612d3e565b935093505050600080600360009054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561171557600080fd5b505afa158015611729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174d9190612d3e565b93509350505060006117ee600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156117a657600080fd5b505afa1580156117ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117de9190612fde565b6117e8868d611908565b906118d7565b90506000633b9aca006118158161180f86611809878a611908565b90612b43565b90612b5f565b8161181c57fe5b04905060006118bb876118b5600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561187657600080fd5b505afa15801561188a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ae9190612fde565b8f906118d7565b90611908565b808311159d929c50929a509198509650505050505050565b3390565b6000816118f96118ef85670de0b6b3a7640000612b8e565b6002855b04612bfa565b8161190057fe5b049392505050565b6000670de0b6b3a76400006118f96119208585612b8e565b6002670de0b6b3a76400006118f3565b60008260ff16600281111561194157fe5b600281111561194c57fe5b1415611d1f576000818060200190518101906119689190612e10565b6002546040516370a0823160e01b81529192506000916101009091046001600160a01b0316906370a08231906119a29030906004016130a6565b60206040518083038186803b1580156119ba57600080fd5b505afa1580156119ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f29190612fde565b60025460405163f73e19c360e01b81529192506000916101009091046001600160a01b03169063f73e19c390611a2c908590600401613343565b60206040518083038186803b158015611a4457600080fd5b505afa158015611a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7c9190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166367b8c3456040518163ffffffff1660e01b815260040160206040518083038186803b158015611ace57600080fd5b505afa158015611ae2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b069190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166363bbc4b66040518163ffffffff1660e01b815260040160206040518083038186803b158015611b5857600080fd5b505afa158015611b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b909190612fde565b6003548651604051631b9756c160e31b81529293506001600160a01b039091169163dcbab608918b91611bce9188918a918991899190600401613390565b6000604051808303818588803b158015611be757600080fd5b505af1158015611bfb573d6000803e3d6000fd5b505060025460405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116955063095ea7b39450611c5c93506101009092049091169060001990600401613100565b602060405180830381600087803b158015611c7657600080fd5b505af1158015611c8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cae9190612d7c565b50600254604051632e1a7d4d60e01b81526101009091046001600160a01b031690632e1a7d4d90611ce3908790600401613343565b600060405180830381600087803b158015611cfd57600080fd5b505af1158015611d11573d6000803e3d6000fd5b50505050505050505061053d565b60018260ff166002811115611d3057fe5b6002811115611d3b57fe5b1415612317576003546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611d729030906004016130a6565b60206040518083038186803b158015611d8a57600080fd5b505afa158015611d9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc29190612fde565b9050600082806020019051810190611dda9190612eba565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e2c57600080fd5b505af1158015611e40573d6000803e3d6000fd5b505060025460408581015190516323b872dd60e01b81526101009092046001600160a01b031694506323b872dd9350611e8192508a913091906004016130ba565b602060405180830381600087803b158015611e9b57600080fd5b505af1158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190612d7c565b50600254815160405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169363095ea7b393611f2f936101009092049092169190600401613100565b602060405180830381600087803b158015611f4957600080fd5b505af1158015611f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f819190612d7c565b506002546040828101519051632e1a7d4d60e01b81526101009092046001600160a01b031691632e1a7d4d91611fb991600401613343565b600060405180830381600087803b158015611fd357600080fd5b505af1158015611fe7573d6000803e3d6000fd5b5050505060208101511561206a576003546001600160a01b031663fc5b73ff61201047886114e7565b836020015184606001516040518463ffffffff1660e01b815260040161203792919061334c565b6000604051808303818588803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b50505050505b6003546040516370a0823160e01b81526000916120f79185916001600160a01b0316906370a08231906120a19030906004016130a6565b60206040518083038186803b1580156120b957600080fd5b505afa1580156120cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f19190612fde565b906114e7565b60035460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb9061212a908a908590600401613100565b602060405180830381600087803b15801561214457600080fd5b505af1158015612158573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217c9190612d7c565b506040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90899083906370a08231906121d39030906004016130a6565b60206040518083038186803b1580156121eb57600080fd5b505afa1580156121ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122239190612fde565b6040518363ffffffff1660e01b8152600401612240929190613100565b602060405180830381600087803b15801561225a57600080fd5b505af115801561226e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122929190612d7c565b50604082015147906001600160a01b038916907fa1b94934d9119aa101df2e94f736d2cff64c4d7db8706c9b5bb1ffa265842f8990846122d2858c6114e7565b6040516122e19392919061337a565b60405180910390a28681111561230e5761230e6122fe82896114e7565b6001600160a01b038a1690611545565b5050505061053d565b60028260ff16600281111561232857fe5b600281111561233357fe5b141561053d576003546040516370a0823160e01b81526000916001600160a01b0316906370a082319061236a9030906004016130a6565b60206040518083038186803b15801561238257600080fd5b505afa158015612396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ba9190612fde565b90506000828060200190518101906123d29190612e4b565b90506000600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561242457600080fd5b505afa158015612438573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245c9190612d3e565b60025460608701516040516323b872dd60e01b81529296506101009091046001600160a01b031694506323b872dd935061249e92508b913091906004016130ba565b602060405180830381600087803b1580156124b857600080fd5b505af11580156124cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f09190612d7c565b50600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b15801561254157600080fd5b505af1158015612555573d6000803e3d6000fd5b50506040516370a0823160e01b8152600093506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692506370a0823191506125a99030906004016130a6565b60206040518083038186803b1580156125c157600080fd5b505afa1580156125d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f99190612fde565b60025460405163095ea7b360e01b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263095ea7b3926126549261010090910416908590600401613100565b602060405180830381600087803b15801561266e57600080fd5b505af1158015612682573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126a69190612d7c565b50600061273d83611809600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126fe57600080fd5b505afa158015612712573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127369190612fde565b8590611908565b90506000633b9aca006127508382612c52565b8161275757fe5b600254604051632e1a7d4d60e01b815292909104925061010090046001600160a01b031690632e1a7d4d90612790908490600401613343565b600060405180830381600087803b1580156127aa57600080fd5b505af11580156127be573d6000803e3d6000fd5b505060025460608801516101009091046001600160a01b031692506323ccafd991506127ea90846114e7565b87604001516040518363ffffffff1660e01b815260040161280c929190613141565b600060405180830381600087803b15801561282657600080fd5b505af115801561283a573d6000803e3d6000fd5b505050508847101561285e5760405162461bcd60e51b81526004016101c49061314f565b6020850151156128dd576003546001600160a01b031663fc5b73ff612883478c6114e7565b876020015188608001516040518463ffffffff1660e01b81526004016128aa92919061334c565b6000604051808303818588803b1580156128c357600080fd5b505af11580156128d7573d6000803e3d6000fd5b50505050505b6003546040516370a0823160e01b81526000916129149189916001600160a01b0316906370a08231906120a19030906004016130a6565b60035460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb90612947908e908590600401613100565b602060405180830381600087803b15801561296157600080fd5b505af1158015612975573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129999190612d7c565b506040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb908d9083906370a08231906129f09030906004016130a6565b60206040518083038186803b158015612a0857600080fd5b505afa158015612a1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a409190612fde565b6040518363ffffffff1660e01b8152600401612a5d929190613100565b602060405180830381600087803b158015612a7757600080fd5b505af1158015612a8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aaf9190612d7c565b5060004790508b6001600160a01b03167fa1b94934d9119aa101df2e94f736d2cff64c4d7db8706c9b5bb1ffa265842f89886060015184612af98f866114e790919063ffffffff16565b604051612b089392919061337a565b60405180910390a28a811115612b3557612b35612b25828d6114e7565b6001600160a01b038e1690611545565b505050505050505050505050565b6000816118f96118ef856b033b2e3c9fd0803ce8000000612b8e565b6000612b87612b81612b7b612b748686612bfa565b60016114e7565b84612c5d565b83612b8e565b9392505050565b6000811580612ba957505080820282828281612ba657fe5b04145b61153f576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b8082018281101561153f576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000612b87612b8184845b6000808211612cb3576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161190057fe5b600082601f830112612ccc578081fd5b8151612cdf612cda826133d7565b6133b3565b818152846020838601011115612cf3578283fd5b612d048260208301602087016133f9565b949350505050565b805160ff81168114612d1d57600080fd5b919050565b600060208284031215612d33578081fd5b8135612b8781613425565b60008060008060808587031215612d53578283fd5b8451612d5e81613425565b60208601516040870151606090970151919890975090945092505050565b600060208284031215612d8d578081fd5b81518015158114612b87578182fd5b600060208284031215612dad578081fd5b813567ffffffffffffffff811115612dc3578182fd5b8201601f81018413612dd3578182fd5b8035612de1612cda826133d7565b818152856020838501011115612df5578384fd5b81602084016020830137908101602001929092525092915050565b600060208284031215612e21578081fd5b6040516020810181811067ffffffffffffffff82111715612e3e57fe5b6040529151825250919050565b600060a08284031215612e5c578081fd5b60405160a0810181811067ffffffffffffffff82111715612e7957fe5b8060405250825181526020830151602082015260408301516040820152606083015160608201526080830151612eae8161343d565b60808201529392505050565b600060808284031215612ecb578081fd5b6040516080810181811067ffffffffffffffff82111715612ee857fe5b80604052508251815260208301516020820152604083015160408201526060830151612f138161343d565b60608201529392505050565b600060208284031215612f30578081fd5b815167ffffffffffffffff80821115612f47578283fd5b9083019060808286031215612f5a578283fd5b604051608081018181108382111715612f6f57fe5b6040528251612f7d81613425565b815260208381015190820152612f9560408401612d0c565b6040820152606083015182811115612fab578485fd5b612fb787828601612cbc565b60608301525095945050505050565b600060208284031215612fd7578081fd5b5035919050565b600060208284031215612fef578081fd5b5051919050565b60008060006060848603121561300a578081fd5b833592506020840135915060408401356130238161343d565b809150509250925092565b600080600080600060a08688031215613045578283fd5b85359450602086013593506040860135925060608601359150608086013561306c8161343d565b809150509295509295909350565b600081518084526130928160208601602086016133f9565b601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b038416825260406020830152612d04604083018461307a565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b931515845260208401929092526040830152606082015260800190565b918252602082015260400190565b602080825260029082015261269b60f11b604082015260600190565b6020808252600290820152614d3560f01b604082015260600190565b60208082526002908201526109a760f31b604082015260600190565b6020808252600290820152614d3360f01b604082015260600190565b6020808252600290820152614d3960f01b604082015260600190565b6020808252600290820152614d3760f01b604082015260600190565b60208082526003908201526204d31360ec1b604082015260600190565b6020808252600290820152614d3160f01b604082015260600190565b602080825260029082015261134d60f21b604082015260600190565b602080825260029082015261269960f11b604082015260600190565b6020808252600390820152624d313160e81b604082015260600190565b9051815260200190565b600060a0820190508251825260208301516020830152604083015160408301526060830151606083015262ffffff608084015116608083015292915050565b81518152602080830151908201526040808301519082015260609182015162ffffff169181019190915260800190565b6000602082526001600160a01b0383511660208301526020830151604083015260ff60408401511660608301526060830151608080840152612d0460a084018261307a565b90815260200190565b91825262ffffff16602082015260400190565b928352602083019190915262ffffff16604082015260600190565b9283526020830191909152604082015260600190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff811182821017156133cf57fe5b604052919050565b600067ffffffffffffffff8211156133eb57fe5b50601f01601f191660200190565b60005b838110156134145781810151838201526020016133fc565b8381111561053d5750506000910152565b6001600160a01b038116811461343a57600080fd5b50565b62ffffff8116811461343a57600080fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a26469706673582212207966a8d1a64f3eebd4cdd5a263bc2934c3f304d935a1b2eaf5f4667b66aa9f7a64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x6080604052600436106101485760003560e01c8063a15db5c5116100c0578063cb9d1ab811610074578063db661b7111610059578063db661b71146103d2578063f2fde38b146103e7578063fe7dd6e414610407576101cf565b8063cb9d1ab814610392578063d2cebf9b146103b2576101cf565b8063bab89ea3116100a5578063bab89ea31461032d578063bbac0aca14610342578063bbca7f1e14610362576101cf565b8063a15db5c5146102eb578063b06faf621461030b576101cf565b8063715018a6116101175780638da5cb5b116100fc5780638da5cb5b146102965780638e953732146102ab578063a13d7b33146102cb576101cf565b8063715018a61461026c5780637fa8c37014610281576101cf565b8063139d3799146101d45780631d4dab2c146101f45780633fc8cef31461022a578063581e74781461024c576101cf565b366101cf57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610193575060025461010090046001600160a01b031633145b806101a857506003546001600160a01b031633145b6101cd5760405162461bcd60e51b81526004016101c490613230565b60405180910390fd5b005b600080fd5b3480156101e057600080fd5b506101cd6101ef366004612ff6565b61041c565b34801561020057600080fd5b5061021461020f366004612d22565b610543565b6040516102219190613343565b60405180910390f35b34801561023657600080fd5b5061023f610555565b60405161022191906130a6565b34801561025857600080fd5b506101cd610267366004612ff6565b610579565b34801561027857600080fd5b506101cd6106dc565b34801561028d57600080fd5b5061023f6107a7565b3480156102a257600080fd5b5061023f6107bb565b3480156102b757600080fd5b506101cd6102c636600461302e565b6107ca565b3480156102d757600080fd5b506101cd6102e6366004612fc6565b61095e565b3480156102f757600080fd5b506101cd610306366004612d9c565b610cec565b34801561031757600080fd5b50610320610f97565b6040516102219190613119565b34801561033957600080fd5b506101cd610fa0565b34801561034e57600080fd5b506101cd61035d366004612d22565b61109f565b34801561036e57600080fd5b5061038261037d366004612fc6565b611168565b6040516102219493929190613124565b34801561039e57600080fd5b506101cd6103ad366004612fc6565b611186565b3480156103be57600080fd5b506101cd6103cd366004612fc6565b611282565b3480156103de57600080fd5b5061023f611393565b3480156103f357600080fd5b506101cd610402366004612d22565b6113b7565b34801561041357600080fd5b5061023f6114d8565b60025460ff1661043e5760405162461bcd60e51b81526004016101c49061324c565b336000908152600160205260409020548084111561046e5760405162461bcd60e51b81526004016101c49061316b565b61047881856114e7565b3360009081526001602052604090819020919091556003549051630b52b7ff60e41b81526001600160a01b039091169063b52b7ff0906104c09087908790879060040161335f565b600060405180830381600087803b1580156104da57600080fd5b505af11580156104ee573d6000803e3d6000fd5b50505050336001600160a01b03167f38d6d922c6452f3aaf90ad851ed15eb4c5c613c745d0531cf4337c07de651bab8560405161052b9190613343565b60405180910390a261053d3347611545565b50505050565b60016020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60025460ff1661059b5760405162461bcd60e51b81526004016101c49061324c565b60008060006105a98661162f565b50925092509250826105cd5760405162461bcd60e51b81526004016101c4906131bf565b60408051608081018252338152602081018490526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916389b7b7a69130918101600160ff16815260200160405180608001604052808781526020018b81526020018c81526020018a62ffffff1681525060405160200161065691906132ce565b60408051601f1981840301815291815291525161067691906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016106a29291906130de565b600060405180830381600087803b1580156106bc57600080fd5b505af11580156106d0573d6000803e3d6000fd5b50505050505050505050565b6106e46118d3565b6001600160a01b03166106f56107bb565b6001600160a01b031614610750576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b60025461010090046001600160a01b031681565b6000546001600160a01b031690565b60025460ff166107ec5760405162461bcd60e51b81526004016101c49061324c565b6000806107f88761162f565b509250509150811561081c5760405162461bcd60e51b81526004016101c4906131f7565b60008511801561082c5750600084115b6108485760405162461bcd60e51b81526004016101c490613187565b60408051608081018252338152602081018790526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916389b7b7a69130918101600260ff1681526020016040518060a001604052808781526020018c81526020018a81526020018d81526020018962ffffff168152506040516020016108d7919061328f565b60408051601f198184030181529181529152516108f791906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016109239291906130de565b600060405180830381600087803b15801561093d57600080fd5b505af1158015610951573d6000803e3d6000fd5b5050505050505050505050565b6109666118d3565b6001600160a01b03166109776107bb565b6001600160a01b0316146109d2576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6003546001600160a01b03166109fa5760405162461bcd60e51b81526004016101c490613268565b60025460ff1615610a1d5760405162461bcd60e51b81526004016101c490613214565b6002805460ff1916600117908190556040516370a0823160e01b81526000916001600160a01b0361010090910416906370a0823190610a609030906004016130a6565b60206040518083038186803b158015610a7857600080fd5b505afa158015610a8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab09190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b0257600080fd5b505afa158015610b16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3a9190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b158015610b8c57600080fd5b505afa158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc49190612d3e565b50925060009150610be19050610bda85856118d7565b8390611908565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389b7b7a6306040518060800160405280336001600160a01b0316815260200185815260200160006002811115610c4057fe5b60ff16815260200160405180602001604052808b815250604051602001610c679190613285565b60408051601f19818403018152918152915251610c8791906020016132fe565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610cb39291906130de565b600060405180830381600087803b158015610ccd57600080fd5b505af1158015610ce1573d6000803e3d6000fd5b505050505050505050565b6003546001600160a01b0316610d145760405162461bcd60e51b81526004016101c490613268565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d5c5760405162461bcd60e51b81526004016101c4906131a3565b600081806020019051810190610d729190612f1f565b6020810151604051630ecbcdab60e01b81529192506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691630ecbcdab91610dc89160009190600401613141565b600060405180830381600087803b158015610de257600080fd5b505af1158015610df6573d6000803e3d6000fd5b5050506020820151604051632e1a7d4d60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250632e1a7d4d91610e4991600401613343565b600060405180830381600087803b158015610e6357600080fd5b505af1158015610e77573d6000803e3d6000fd5b50505050610e978160000151826020015183604001518460600151611930565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db082602001516040518263ffffffff1660e01b81526004016000604051808303818588803b158015610ef657600080fd5b505af1158015610f0a573d6000803e3d6000fd5b505050602083015160405163d8aed14560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063d8aed1459250610f6191600091600401613141565b600060405180830381600087803b158015610f7b57600080fd5b505af1158015610f8f573d6000803e3d6000fd5b505050505050565b60025460ff1681565b60025460ff16610fc25760405162461bcd60e51b81526004016101c49061324c565b336000818152600160205260408082208054929055600354905163a9059cbb60e01b815291926001600160a01b039091169163a9059cbb91611008918590600401613100565b602060405180830381600087803b15801561102257600080fd5b505af1158015611036573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105a9190612d7c565b50336001600160a01b03167f0adef25f8a7a2d6f3fb9761ba0c96c9752b6d985abd47e23b7fa3095ba8e4701826040516110949190613343565b60405180910390a250565b6110a76118d3565b6001600160a01b03166110b86107bb565b6001600160a01b031614611113576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166111395760405162461bcd60e51b81526004016101c4906131db565b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000806000806111778561162f565b93509350935093509193509193565b60025460ff16156111a95760405162461bcd60e51b81526004016101c490613214565b336000818152600160205260409081902080548401905560025490516323b872dd60e01b81526101009091046001600160a01b0316916323b872dd916111f69190309086906004016130ba565b602060405180830381600087803b15801561121057600080fd5b505af1158015611224573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112489190612d7c565b50336001600160a01b03167fcbfc37edaa5ac30951b21b47b70bbb70dd1e015fa918da25d516798c6a2622e8826040516110949190613343565b60025460ff16156112a55760405162461bcd60e51b81526004016101c490613214565b336000908152600160205260409020546112bf90826114e7565b336000818152600160205260409081902092909255600254915163a9059cbb60e01b81526101009092046001600160a01b03169163a9059cbb91611307918590600401613100565b602060405180830381600087803b15801561132157600080fd5b505af1158015611335573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113599190612d7c565b50336001600160a01b03167ffdef8f0daac171c9b3f7896ae8991c11b88b64b1b76b574d8189dcd0357e5f6e826040516110949190613343565b7f000000000000000000000000000000000000000000000000000000000000000081565b6113bf6118d3565b6001600160a01b03166113d06107bb565b6001600160a01b03161461142b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166114705760405162461bcd60e51b815260040180806020018281038252602681526020018061344f6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6003546001600160a01b031681565b8082038281111561153f576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b92915050565b8047101561159a576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146115e5576040519150601f19603f3d011682016040523d82523d6000602084013e6115ea565b606091505b505090508061162a5760405162461bcd60e51b815260040180806020018281038252603a815260200180613475603a913960400191505060405180910390fd5b505050565b600080600080600080600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561168657600080fd5b505afa15801561169a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116be9190612d3e565b935093505050600080600360009054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561171557600080fd5b505afa158015611729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174d9190612d3e565b93509350505060006117ee600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156117a657600080fd5b505afa1580156117ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117de9190612fde565b6117e8868d611908565b906118d7565b90506000633b9aca006118158161180f86611809878a611908565b90612b43565b90612b5f565b8161181c57fe5b04905060006118bb876118b5600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561187657600080fd5b505afa15801561188a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ae9190612fde565b8f906118d7565b90611908565b808311159d929c50929a509198509650505050505050565b3390565b6000816118f96118ef85670de0b6b3a7640000612b8e565b6002855b04612bfa565b8161190057fe5b049392505050565b6000670de0b6b3a76400006118f96119208585612b8e565b6002670de0b6b3a76400006118f3565b60008260ff16600281111561194157fe5b600281111561194c57fe5b1415611d1f576000818060200190518101906119689190612e10565b6002546040516370a0823160e01b81529192506000916101009091046001600160a01b0316906370a08231906119a29030906004016130a6565b60206040518083038186803b1580156119ba57600080fd5b505afa1580156119ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f29190612fde565b60025460405163f73e19c360e01b81529192506000916101009091046001600160a01b03169063f73e19c390611a2c908590600401613343565b60206040518083038186803b158015611a4457600080fd5b505afa158015611a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7c9190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166367b8c3456040518163ffffffff1660e01b815260040160206040518083038186803b158015611ace57600080fd5b505afa158015611ae2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b069190612fde565b90506000600260019054906101000a90046001600160a01b03166001600160a01b03166363bbc4b66040518163ffffffff1660e01b815260040160206040518083038186803b158015611b5857600080fd5b505afa158015611b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b909190612fde565b6003548651604051631b9756c160e31b81529293506001600160a01b039091169163dcbab608918b91611bce9188918a918991899190600401613390565b6000604051808303818588803b158015611be757600080fd5b505af1158015611bfb573d6000803e3d6000fd5b505060025460405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116955063095ea7b39450611c5c93506101009092049091169060001990600401613100565b602060405180830381600087803b158015611c7657600080fd5b505af1158015611c8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cae9190612d7c565b50600254604051632e1a7d4d60e01b81526101009091046001600160a01b031690632e1a7d4d90611ce3908790600401613343565b600060405180830381600087803b158015611cfd57600080fd5b505af1158015611d11573d6000803e3d6000fd5b50505050505050505061053d565b60018260ff166002811115611d3057fe5b6002811115611d3b57fe5b1415612317576003546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611d729030906004016130a6565b60206040518083038186803b158015611d8a57600080fd5b505afa158015611d9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc29190612fde565b9050600082806020019051810190611dda9190612eba565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e2c57600080fd5b505af1158015611e40573d6000803e3d6000fd5b505060025460408581015190516323b872dd60e01b81526101009092046001600160a01b031694506323b872dd9350611e8192508a913091906004016130ba565b602060405180830381600087803b158015611e9b57600080fd5b505af1158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190612d7c565b50600254815160405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169363095ea7b393611f2f936101009092049092169190600401613100565b602060405180830381600087803b158015611f4957600080fd5b505af1158015611f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f819190612d7c565b506002546040828101519051632e1a7d4d60e01b81526101009092046001600160a01b031691632e1a7d4d91611fb991600401613343565b600060405180830381600087803b158015611fd357600080fd5b505af1158015611fe7573d6000803e3d6000fd5b5050505060208101511561206a576003546001600160a01b031663fc5b73ff61201047886114e7565b836020015184606001516040518463ffffffff1660e01b815260040161203792919061334c565b6000604051808303818588803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b50505050505b6003546040516370a0823160e01b81526000916120f79185916001600160a01b0316906370a08231906120a19030906004016130a6565b60206040518083038186803b1580156120b957600080fd5b505afa1580156120cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f19190612fde565b906114e7565b60035460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb9061212a908a908590600401613100565b602060405180830381600087803b15801561214457600080fd5b505af1158015612158573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217c9190612d7c565b506040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90899083906370a08231906121d39030906004016130a6565b60206040518083038186803b1580156121eb57600080fd5b505afa1580156121ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122239190612fde565b6040518363ffffffff1660e01b8152600401612240929190613100565b602060405180830381600087803b15801561225a57600080fd5b505af115801561226e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122929190612d7c565b50604082015147906001600160a01b038916907fa1b94934d9119aa101df2e94f736d2cff64c4d7db8706c9b5bb1ffa265842f8990846122d2858c6114e7565b6040516122e19392919061337a565b60405180910390a28681111561230e5761230e6122fe82896114e7565b6001600160a01b038a1690611545565b5050505061053d565b60028260ff16600281111561232857fe5b600281111561233357fe5b141561053d576003546040516370a0823160e01b81526000916001600160a01b0316906370a082319061236a9030906004016130a6565b60206040518083038186803b15801561238257600080fd5b505afa158015612396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ba9190612fde565b90506000828060200190518101906123d29190612e4b565b90506000600260019054906101000a90046001600160a01b03166001600160a01b031663533092ef6040518163ffffffff1660e01b815260040160806040518083038186803b15801561242457600080fd5b505afa158015612438573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245c9190612d3e565b60025460608701516040516323b872dd60e01b81529296506101009091046001600160a01b031694506323b872dd935061249e92508b913091906004016130ba565b602060405180830381600087803b1580156124b857600080fd5b505af11580156124cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f09190612d7c565b50600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b15801561254157600080fd5b505af1158015612555573d6000803e3d6000fd5b50506040516370a0823160e01b8152600093506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692506370a0823191506125a99030906004016130a6565b60206040518083038186803b1580156125c157600080fd5b505afa1580156125d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f99190612fde565b60025460405163095ea7b360e01b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263095ea7b3926126549261010090910416908590600401613100565b602060405180830381600087803b15801561266e57600080fd5b505af1158015612682573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126a69190612d7c565b50600061273d83611809600260019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126fe57600080fd5b505afa158015612712573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127369190612fde565b8590611908565b90506000633b9aca006127508382612c52565b8161275757fe5b600254604051632e1a7d4d60e01b815292909104925061010090046001600160a01b031690632e1a7d4d90612790908490600401613343565b600060405180830381600087803b1580156127aa57600080fd5b505af11580156127be573d6000803e3d6000fd5b505060025460608801516101009091046001600160a01b031692506323ccafd991506127ea90846114e7565b87604001516040518363ffffffff1660e01b815260040161280c929190613141565b600060405180830381600087803b15801561282657600080fd5b505af115801561283a573d6000803e3d6000fd5b505050508847101561285e5760405162461bcd60e51b81526004016101c49061314f565b6020850151156128dd576003546001600160a01b031663fc5b73ff612883478c6114e7565b876020015188608001516040518463ffffffff1660e01b81526004016128aa92919061334c565b6000604051808303818588803b1580156128c357600080fd5b505af11580156128d7573d6000803e3d6000fd5b50505050505b6003546040516370a0823160e01b81526000916129149189916001600160a01b0316906370a08231906120a19030906004016130a6565b60035460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb90612947908e908590600401613100565b602060405180830381600087803b15801561296157600080fd5b505af1158015612975573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129999190612d7c565b506040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb908d9083906370a08231906129f09030906004016130a6565b60206040518083038186803b158015612a0857600080fd5b505afa158015612a1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a409190612fde565b6040518363ffffffff1660e01b8152600401612a5d929190613100565b602060405180830381600087803b158015612a7757600080fd5b505af1158015612a8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aaf9190612d7c565b5060004790508b6001600160a01b03167fa1b94934d9119aa101df2e94f736d2cff64c4d7db8706c9b5bb1ffa265842f89886060015184612af98f866114e790919063ffffffff16565b604051612b089392919061337a565b60405180910390a28a811115612b3557612b35612b25828d6114e7565b6001600160a01b038e1690611545565b505050505050505050505050565b6000816118f96118ef856b033b2e3c9fd0803ce8000000612b8e565b6000612b87612b81612b7b612b748686612bfa565b60016114e7565b84612c5d565b83612b8e565b9392505050565b6000811580612ba957505080820282828281612ba657fe5b04145b61153f576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b8082018281101561153f576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000612b87612b8184845b6000808211612cb3576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161190057fe5b600082601f830112612ccc578081fd5b8151612cdf612cda826133d7565b6133b3565b818152846020838601011115612cf3578283fd5b612d048260208301602087016133f9565b949350505050565b805160ff81168114612d1d57600080fd5b919050565b600060208284031215612d33578081fd5b8135612b8781613425565b60008060008060808587031215612d53578283fd5b8451612d5e81613425565b60208601516040870151606090970151919890975090945092505050565b600060208284031215612d8d578081fd5b81518015158114612b87578182fd5b600060208284031215612dad578081fd5b813567ffffffffffffffff811115612dc3578182fd5b8201601f81018413612dd3578182fd5b8035612de1612cda826133d7565b818152856020838501011115612df5578384fd5b81602084016020830137908101602001929092525092915050565b600060208284031215612e21578081fd5b6040516020810181811067ffffffffffffffff82111715612e3e57fe5b6040529151825250919050565b600060a08284031215612e5c578081fd5b60405160a0810181811067ffffffffffffffff82111715612e7957fe5b8060405250825181526020830151602082015260408301516040820152606083015160608201526080830151612eae8161343d565b60808201529392505050565b600060808284031215612ecb578081fd5b6040516080810181811067ffffffffffffffff82111715612ee857fe5b80604052508251815260208301516020820152604083015160408201526060830151612f138161343d565b60608201529392505050565b600060208284031215612f30578081fd5b815167ffffffffffffffff80821115612f47578283fd5b9083019060808286031215612f5a578283fd5b604051608081018181108382111715612f6f57fe5b6040528251612f7d81613425565b815260208381015190820152612f9560408401612d0c565b6040820152606083015182811115612fab578485fd5b612fb787828601612cbc565b60608301525095945050505050565b600060208284031215612fd7578081fd5b5035919050565b600060208284031215612fef578081fd5b5051919050565b60008060006060848603121561300a578081fd5b833592506020840135915060408401356130238161343d565b809150509250925092565b600080600080600060a08688031215613045578283fd5b85359450602086013593506040860135925060608601359150608086013561306c8161343d565b809150509295509295909350565b600081518084526130928160208601602086016133f9565b601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b038416825260406020830152612d04604083018461307a565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b931515845260208401929092526040830152606082015260800190565b918252602082015260400190565b602080825260029082015261269b60f11b604082015260600190565b6020808252600290820152614d3560f01b604082015260600190565b60208082526002908201526109a760f31b604082015260600190565b6020808252600290820152614d3360f01b604082015260600190565b6020808252600290820152614d3960f01b604082015260600190565b6020808252600290820152614d3760f01b604082015260600190565b60208082526003908201526204d31360ec1b604082015260600190565b6020808252600290820152614d3160f01b604082015260600190565b602080825260029082015261134d60f21b604082015260600190565b602080825260029082015261269960f11b604082015260600190565b6020808252600390820152624d313160e81b604082015260600190565b9051815260200190565b600060a0820190508251825260208301516020830152604083015160408301526060830151606083015262ffffff608084015116608083015292915050565b81518152602080830151908201526040808301519082015260609182015162ffffff169181019190915260800190565b6000602082526001600160a01b0383511660208301526020830151604083015260ff60408401511660608301526060830151608080840152612d0460a084018261307a565b90815260200190565b91825262ffffff16602082015260400190565b928352602083019190915262ffffff16604082015260600190565b9283526020830191909152604082015260600190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff811182821017156133cf57fe5b604052919050565b600067ffffffffffffffff8211156133eb57fe5b50601f01601f191660200190565b60005b838110156134145781810151838201526020016133fc565b8381111561053d5750506000910152565b6001600160a01b038116811461343a57600080fd5b50565b62ffffff8116811461343a57600080fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a26469706673582212207966a8d1a64f3eebd4cdd5a263bc2934c3f304d935a1b2eaf5f4667b66aa9f7a64736f6c63430007060033\",\n  \"devdoc\": {\n    \"author\": \"Opyn team\",\n    \"details\": \"CrabMigration contract\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"batchMigrate(uint256)\": {\n        \"params\": {\n          \"_strategyCap\": \"strategy cap in ETH\"\n        }\n      },\n      \"claimAndWithdraw(uint256,uint256,uint24)\": {\n        \"params\": {\n          \"_amountToWithdraw\": \"V2 shares to claim\",\n          \"_maxEthToPay\": \"maximum ETH to pay to buy back the owed wSqueeth debt\",\n          \"_poolFee\": \"Uniswap pool fee for flash withdraw\"\n        }\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_crabV1\": \"address of crab V1\",\n          \"_dToken\": \"address of euler liability token\",\n          \"_eulerExec\": \"address of euler exec contract\",\n          \"_eulerMainnet\": \"address of euler deployment on mainnet\",\n          \"_weth\": \"address of weth\"\n        }\n      },\n      \"depositV1Shares(uint256)\": {\n        \"params\": {\n          \"_amount\": \"amount of crabV1 shares to deposit\"\n        }\n      },\n      \"flashMigrateAndWithdrawFromV1toV2(uint256,uint256,uint256,uint256,uint24)\": {\n        \"params\": {\n          \"_ethToBorrow\": \"amount to flash loan to deposit in crab v2\",\n          \"_ethToFlashDeposit\": \"flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\",\n          \"_poolFee\": \"uniswap pool fee for the optional flash deposit into crab v2\",\n          \"_v1Shares\": \"V1 shares to migrate\",\n          \"_withdrawMaxEthToPay\": \"maximum ETH to pay to buy back the owed wSqueeth debt\"\n        }\n      },\n      \"flashMigrateFromV1toV2(uint256,uint256,uint24)\": {\n        \"params\": {\n          \"_ethToFlashDeposit\": \"flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\",\n          \"_poolFee\": \"uniswap pool fee for flash deposit\",\n          \"_v1Shares\": \"V1 shares to migrate\"\n        }\n      },\n      \"flashMigrationDetails(uint256)\": {\n        \"params\": {\n          \"_v1Shares\": \"amount of crab V1 shares\"\n        }\n      },\n      \"onDeferredLiquidityCheck(bytes)\": {\n        \"params\": {\n          \"encodedData\": \"callback data\"\n        }\n      },\n      \"owner()\": {\n        \"details\": \"Returns the address of the current owner.\"\n      },\n      \"renounceOwnership()\": {\n        \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n      },\n      \"setCrabV2(address)\": {\n        \"params\": {\n          \"_crabV2\": \"address of crab V2\"\n        }\n      },\n      \"transferOwnership(address)\": {\n        \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n      },\n      \"withdrawV1Shares(uint256)\": {\n        \"params\": {\n          \"_amount\": \"amount of V1 shares to withdraw\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"batchMigrate(uint256)\": {\n        \"notice\": \"the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes the V2 contract at the same collateral ratio as the V1 contract\"\n      },\n      \"claimAndWithdraw(uint256,uint256,uint24)\": {\n        \"notice\": \"claim crab V2 shares and flash withdraw from crab V2\"\n      },\n      \"claimV2Shares()\": {\n        \"notice\": \"claim crab V2 shares\"\n      },\n      \"constructor\": {\n        \"notice\": \"migration constructor\"\n      },\n      \"depositV1Shares(uint256)\": {\n        \"notice\": \"deposit crab V1 shares in the pool for migration\"\n      },\n      \"flashMigrateAndWithdrawFromV1toV2(uint256,uint256,uint256,uint256,uint24)\": {\n        \"notice\": \"used to migrate from crab V1 to crab V2 when CR1 < CR2\"\n      },\n      \"flashMigrateFromV1toV2(uint256,uint256,uint24)\": {\n        \"notice\": \"used to migrate from crab V1 to crab V2 when CR1 >= CR2\"\n      },\n      \"flashMigrationDetails(uint256)\": {\n        \"notice\": \"view details of flash migration for specified amount of V1 shares\"\n      },\n      \"onDeferredLiquidityCheck(bytes)\": {\n        \"notice\": \"Euler callback function\"\n      },\n      \"setCrabV2(address)\": {\n        \"notice\": \"set the crabV2 address\"\n      },\n      \"withdrawV1Shares(uint256)\": {\n        \"notice\": \"withdraw crab V1 shares in the pool before migration\"\n      }\n    },\n    \"notice\": \"Contract for Migrating from Crab V1 to Crab V2\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 7,\n        \"contract\": \"contracts/strategy/CrabMigration.sol:CrabMigration\",\n        \"label\": \"_owner\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 21326,\n        \"contract\": \"contracts/strategy/CrabMigration.sol:CrabMigration\",\n        \"label\": \"sharesDeposited\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 21328,\n        \"contract\": \"contracts/strategy/CrabMigration.sol:CrabMigration\",\n        \"label\": \"isMigrated\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 21330,\n        \"contract\": \"contracts/strategy/CrabMigration.sol:CrabMigration\",\n        \"label\": \"crabV1\",\n        \"offset\": 1,\n        \"slot\": \"2\",\n        \"type\": \"t_address_payable\"\n      },\n      {\n        \"astId\": 21332,\n        \"contract\": \"contracts/strategy/CrabMigration.sol:CrabMigration\",\n        \"label\": \"crabV2\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_address_payable\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_address_payable\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address payable\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/CrabStrategyDeployment.json",
    "content": "{\n  \"address\": \"0x0637A9184cf4DD294F8AfA3963DeAC2Dfadfb00F\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wSqueethController\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_oracle\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_weth\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniswapFactory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_ethWSqueethPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgePriceThreshold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_auctionTime\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minPriceMultiplier\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxPriceMultiplier\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"lpAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Deposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"seller\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethBought\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethSold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isHedgingOnUniswap\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"ExecuteBuyAuction\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"buyer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethSold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethBought\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isHedgingOnUniswap\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"ExecuteSellAuction\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"depositedAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tradedAmountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDeposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDepositCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdrawCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"auctionType\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"hedgerPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethHedgeTargetAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethHedgetargetAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Hedge\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"auctionType\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethHedgeTargetAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethHedgetargetAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"HedgeOnUniswap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"auctionType\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"hedgerPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionTriggerTimestamp\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"PriceHedge\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"hedgeTimestamp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionTriggerTimestamp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"minWSqueeth\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"minEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"PriceHedgeOnUniswap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newCapAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"oldCapAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetStrategyCap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"auctionType\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"hedgerPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionTriggerTimestamp\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"TimeHedge\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"hedger\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"hedgeTimestamp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"auctionTriggerTimestamp\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"minWSqueeth\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"minEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"TimeHedgeOnUniswap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Withdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawShutdown\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"DELTA_HEDGE_THRESHOLD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"POWER_PERP_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"TWAP_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"auctionStartTime\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"auctionTime\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_auctionTriggerTime\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"canExecuteAuction\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_auctionTriggerTime\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"checkPriceHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"checkTimeHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"subtractedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"decreaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"deposit\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"ethQuoteCurrencyPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"ethWSqueethPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToDeposit\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"flashDeposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxEthToPay\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"flashWithdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getStrategyVaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getVaultDetails\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getWsqueethFromCrabAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hasRedeemedInShutdown\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgePriceThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgeTimeThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"addedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"increaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"maxPriceMultiplier\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"minPriceMultiplier\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"oracle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"powerTokenController\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IController\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"priceAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_auctionTriggerTime\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_isStrategySellingWSqueeth\",\n          \"type\": \"bool\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_limitPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"priceHedge\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_auctionTriggerTime\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minWSqueeth\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"priceHedgeOnUniswap\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"quoteCurrency\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"redeemShortShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_capAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setStrategyCap\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"strategyCap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"timeAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_isStrategySellingWSqueeth\",\n          \"type\": \"bool\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_limitPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"timeHedge\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minWSqueeth\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_minEth\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"timeHedgeOnUniswap\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"vaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdrawShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x298774ab1bb90692e8f42ee98ac456d52b296fa826086de84166d7ede4b4d31b\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0x0637A9184cf4DD294F8AfA3963DeAC2Dfadfb00F\",\n    \"transactionIndex\": 9,\n    \"gasUsed\": \"5541563\",\n    \"logsBloom\": \"0x00004000000008000000000000000000000002000000000000800000000000000000000000000202000000020080000100080000000000000000000100000001000000001000000000000008000000000021000000010000000000000000000000000000020240000000010000000800000000000000000020000010000000400000000000100000000000000004000000000000000000000000000000000000000000000000000000000000800000004000000000000000000000000000000000000002000000020000000000000000040000000000000000000000000020200000000001000000000800000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x008ded828e5107aedf0644079f72bfff4d0e6237e3979dc3b8e92440811eb452\",\n    \"transactionHash\": \"0x298774ab1bb90692e8f42ee98ac456d52b296fa826086de84166d7ede4b4d31b\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 9,\n        \"blockNumber\": 11841072,\n        \"transactionHash\": \"0x298774ab1bb90692e8f42ee98ac456d52b296fa826086de84166d7ede4b4d31b\",\n        \"address\": \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n        \"topics\": [\n          \"0x339e53729b0447795ff69e70a74fed98fc7fef6fe94b7521099b32f0f8de4822\"\n        ],\n        \"data\": \"0x0000000000000000000000000000000000000000000000000d892ac4e52accbc0000000000000000000000000000000000000000000000000d88faf22ae47f3f0000000000000000000000000000000000000000000000000000000061e7cedc0000000000000000000000000000000000000000000000000000000061e7d1e4\",\n        \"logIndex\": 8,\n        \"blockHash\": \"0x008ded828e5107aedf0644079f72bfff4d0e6237e3979dc3b8e92440811eb452\"\n      },\n      {\n        \"transactionIndex\": 9,\n        \"blockNumber\": 11841072,\n        \"transactionHash\": \"0x298774ab1bb90692e8f42ee98ac456d52b296fa826086de84166d7ede4b4d31b\",\n        \"address\": \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n        \"topics\": [\n          \"0x3137fc9cd2e33c34f86e29c24d81f3c75b0bce639d3c4ed0d31eeff1160a7ff5\"\n        ],\n        \"data\": \"0x00000000000000000000000049721ed2d693f3653bc1216b8e330fa53cfc80ed000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000\",\n        \"logIndex\": 9,\n        \"blockHash\": \"0x008ded828e5107aedf0644079f72bfff4d0e6237e3979dc3b8e92440811eb452\"\n      },\n      {\n        \"transactionIndex\": 9,\n        \"blockNumber\": 11841072,\n        \"transactionHash\": \"0x298774ab1bb90692e8f42ee98ac456d52b296fa826086de84166d7ede4b4d31b\",\n        \"address\": \"0x49721ED2d693F3653BC1216b8E330fA53CFC80eD\",\n        \"topics\": [\n          \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000000637a9184cf4dd294f8afa3963deac2dfadfb00f\",\n          \"0x000000000000000000000000000000000000000000000000000000000000000c\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 10,\n        \"blockHash\": \"0x008ded828e5107aedf0644079f72bfff4d0e6237e3979dc3b8e92440811eb452\"\n      },\n      {\n        \"transactionIndex\": 9,\n        \"blockNumber\": 11841072,\n        \"transactionHash\": \"0x298774ab1bb90692e8f42ee98ac456d52b296fa826086de84166d7ede4b4d31b\",\n        \"address\": \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n        \"topics\": [\n          \"0x25ff1e0131762176a9084e92880f880f39d6d0e62134607f37e631efe1bad871\"\n        ],\n        \"data\": \"0x0000000000000000000000000637a9184cf4dd294f8afa3963deac2dfadfb00f000000000000000000000000000000000000000000000000000000000000000c\",\n        \"logIndex\": 11,\n        \"blockHash\": \"0x008ded828e5107aedf0644079f72bfff4d0e6237e3979dc3b8e92440811eb452\"\n      },\n      {\n        \"transactionIndex\": 9,\n        \"blockNumber\": 11841072,\n        \"transactionHash\": \"0x298774ab1bb90692e8f42ee98ac456d52b296fa826086de84166d7ede4b4d31b\",\n        \"address\": \"0x0637A9184cf4DD294F8AfA3963DeAC2Dfadfb00F\",\n        \"topics\": [\n          \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000005599b4eaddd319e2f462b27fc8378b0bfad309ca\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 12,\n        \"blockHash\": \"0x008ded828e5107aedf0644079f72bfff4d0e6237e3979dc3b8e92440811eb452\"\n      }\n    ],\n    \"blockNumber\": 11841072,\n    \"cumulativeGasUsed\": \"5901159\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n    \"0xBD9F4bE886653177D22fA9c79FD0DFc41407fC89\",\n    \"0xc778417e063141139fce010982780140aa0cd5ab\",\n    \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n    \"0x921c384F79de1BAe96d6f33E3E5b8d0B2B34cb68\",\n    86400,\n    \"10000000000000000\",\n    3600,\n    \"950000000000000000\",\n    \"1050000000000000000\"\n  ],\n  \"solcInputHash\": \"35c7170ef16c72e51fcfcf56e6ebe3eb\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wSqueethController\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_oracle\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_weth\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniswapFactory\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_ethWSqueethPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_auctionTime\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minPriceMultiplier\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxPriceMultiplier\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"lpAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Deposit\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"seller\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethBought\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethSold\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isHedgingOnUniswap\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"ExecuteBuyAuction\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"buyer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethSold\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethBought\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isHedgingOnUniswap\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"ExecuteSellAuction\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"depositedAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tradedAmountOut\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDeposit\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"flashswapDebt\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excess\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDepositCallback\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"flashswapDebt\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excess\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdrawCallback\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"auctionType\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"hedgerPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethHedgeTargetAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethHedgetargetAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Hedge\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"auctionType\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethHedgeTargetAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethHedgetargetAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"HedgeOnUniswap\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"auctionType\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"hedgerPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionTriggerTimestamp\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"PriceHedge\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"hedgeTimestamp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionTriggerTimestamp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minWSqueeth\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"PriceHedgeOnUniswap\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newCapAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"oldCapAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetStrategyCap\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"auctionType\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"hedgerPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionTriggerTimestamp\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"TimeHedge\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"hedger\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"hedgeTimestamp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"auctionTriggerTimestamp\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minWSqueeth\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"TimeHedgeOnUniswap\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethWithdrawn\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Withdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethWithdrawn\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawShutdown\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"DELTA_HEDGE_THRESHOLD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"POWER_PERP_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"TWAP_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"auctionStartTime\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"auctionTime\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_auctionTriggerTime\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"canExecuteAuction\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_auctionTriggerTime\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"checkPriceHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"checkTimeHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"subtractedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"decreaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"deposit\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"ethQuoteCurrencyPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"ethWSqueethPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"factory\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToDeposit\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"flashDeposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxEthToPay\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"flashWithdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getStrategyVaultId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getVaultDetails\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"getWsqueethFromCrabAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hasRedeemedInShutdown\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgePriceThreshold\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgeTimeThreshold\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"addedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"increaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"maxPriceMultiplier\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"minPriceMultiplier\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"oracle\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"powerTokenController\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IController\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"priceAtLastHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_auctionTriggerTime\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_isStrategySellingWSqueeth\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_limitPrice\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"priceHedge\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_auctionTriggerTime\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minWSqueeth\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"priceHedgeOnUniswap\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"quoteCurrency\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"redeemShortShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_capAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setStrategyCap\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"strategyCap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"timeAtLastHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_isStrategySellingWSqueeth\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_limitPrice\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"timeHedge\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minWSqueeth\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_minEth\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"timeHedgeOnUniswap\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount0Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount1Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"uniswapV3SwapCallback\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"vaultId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdrawShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"author\\\":\\\"Opyn team\\\",\\\"details\\\":\\\"CrabStrategy contract\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"allowance(address,address)\\\":{\\\"details\\\":\\\"See {IERC20-allowance}.\\\"},\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC20-balanceOf}.\\\"},\\\"checkPriceHedge(uint256)\\\":{\\\"params\\\":{\\\"_auctionTriggerTime\\\":\\\"alleged timestamp where auction was triggered\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"true if hedging is allowed\\\"}},\\\"checkTimeHedge()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"isTimeHedgeAllowed true if hedging is allowed\\\",\\\"_1\\\":\\\"auctionTriggertime auction trigger timestamp\\\"}},\\\"constructor\\\":{\\\"details\\\":\\\"this will open a vault in the power token contract and store the vault ID\\\",\\\"params\\\":{\\\"_auctionTime\\\":\\\"auction duration (seconds)\\\",\\\"_ethWSqueethPool\\\":\\\"eth:wSqueeth uniswap pool address\\\",\\\"_hedgePriceThreshold\\\":\\\"hedge price threshold (0.1*1e18 = 10%)\\\",\\\"_hedgeTimeThreshold\\\":\\\"hedge time threshold (seconds)\\\",\\\"_maxPriceMultiplier\\\":\\\"maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\\",\\\"_minPriceMultiplier\\\":\\\"minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\\",\\\"_oracle\\\":\\\"oracle address\\\",\\\"_uniswapFactory\\\":\\\"uniswap factory address\\\",\\\"_wSqueethController\\\":\\\"power token controller address\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"decimals()\\\":{\\\"details\\\":\\\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\\\"},\\\"decreaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\\\"},\\\"deposit()\\\":{\\\"details\\\":\\\"provide ETH, return wSqueeth and strategy token\\\",\\\"returns\\\":{\\\"_0\\\":\\\"wSqueethToMint minted amount of wSqueeth\\\",\\\"_1\\\":\\\"depositorCrabAmount minted amount of strategy token\\\"}},\\\"flashDeposit(uint256)\\\":{\\\"details\\\":\\\"this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth_ethToDeposit must be less than msg.value plus the proceeds from the flash swapthe difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\",\\\"params\\\":{\\\"_ethToDeposit\\\":\\\"total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\"}},\\\"flashWithdraw(uint256,uint256)\\\":{\\\"details\\\":\\\"this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\",\\\"params\\\":{\\\"_crabAmount\\\":\\\"strategy token amount to burn\\\",\\\"_maxEthToPay\\\":\\\"maximum ETH to pay to buy back the owed wSqueeth debt\\\"}},\\\"getStrategyVaultId()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"vault ID\\\"}},\\\"getVaultDetails()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"operator\\\",\\\"_1\\\":\\\"nft collateral id\\\",\\\"_2\\\":\\\"collateral amount\\\",\\\"_3\\\":\\\"short amount\\\"}},\\\"getWsqueethFromCrabAmount(uint256)\\\":{\\\"details\\\":\\\"_crabAmount strategy token amount\\\",\\\"returns\\\":{\\\"_0\\\":\\\"wSqueeth amount\\\"}},\\\"increaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\\\"},\\\"name()\\\":{\\\"details\\\":\\\"Returns the name of the token.\\\"},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"priceHedge(uint256,bool,uint256)\\\":{\\\"details\\\":\\\"need to attach msg.value if buying WSqueeth\\\",\\\"params\\\":{\\\"_auctionTriggerTime\\\":\\\"timestamp where auction started\\\"}},\\\"redeemShortShutdown()\\\":{\\\"details\\\":\\\"needs to be called 1 time before users can exit the strategy using withdrawShutdown\\\"},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"setStrategyCap(uint256)\\\":{\\\"details\\\":\\\"deposits are rejected if it would put the strategy above the cap amountstrategy collateral can be above the cap amount due to hedging activities\\\",\\\"params\\\":{\\\"_capAmount\\\":\\\"the maximum strategy collateral in ETH, checked on deposits\\\"}},\\\"symbol()\\\":{\\\"details\\\":\\\"Returns the symbol of the token, usually a shorter version of the name.\\\"},\\\"timeHedge(bool,uint256)\\\":{\\\"details\\\":\\\"need to attach msg.value if buying WSqueeth\\\",\\\"params\\\":{\\\"_isStrategySellingWSqueeth\\\":\\\"sell or buy auction, true for sell auction\\\",\\\"_limitPrice\\\":\\\"hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\\"}},\\\"timeHedgeOnUniswap(uint256,uint256)\\\":{\\\"params\\\":{\\\"_minEth\\\":\\\"minimum ETH amount of profit if hedge auction is buying WSqueeth\\\",\\\"_minWSqueeth\\\":\\\"minimum WSqueeth amount of profit if hedge auction is selling WSqueeth\\\"}},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC20-totalSupply}.\\\"},\\\"transfer(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\\\"},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"params\\\":{\\\"_data\\\":\\\"callback data encoded as SwapCallbackData struct\\\",\\\"amount0Delta\\\":\\\"amount of token0\\\",\\\"amount1Delta\\\":\\\"amount of token1\\\"}},\\\"withdraw(uint256)\\\":{\\\"details\\\":\\\"provide strategy tokens and wSqueeth, returns eth\\\",\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of strategy token to burn\\\"}},\\\"withdrawShutdown(uint256)\\\":{\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of strategy token to burn\\\"}}},\\\"stateVariables\\\":{\\\"auctionTime\\\":{\\\"details\\\":\\\"hedge auction duration (seconds)\\\"},\\\"ethWSqueethPool\\\":{\\\"details\\\":\\\"ETH:WSqueeth uniswap pool\\\"},\\\"hasRedeemedInShutdown\\\":{\\\"details\\\":\\\"set to true when redeemShortShutdown has been called\\\"},\\\"hedgePriceThreshold\\\":{\\\"details\\\":\\\"price movement to trigger a hedge (0.1*1e18 = 10%)\\\"},\\\"hedgeTimeThreshold\\\":{\\\"details\\\":\\\"time difference to trigger a hedge (seconds)\\\"},\\\"maxPriceMultiplier\\\":{\\\"details\\\":\\\"start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\\"},\\\"minPriceMultiplier\\\":{\\\"details\\\":\\\"start auction price multiplier for hedge buy auction and reserve price for end sell auction (scaled 1e18)\\\"},\\\"oracle\\\":{\\\"details\\\":\\\"strategy uniswap oracle\\\"},\\\"priceAtLastHedge\\\":{\\\"details\\\":\\\"WSqueeth/Eth price when last hedge executed\\\"},\\\"timeAtLastHedge\\\":{\\\"details\\\":\\\"timestamp when last hedge executed\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"checkPriceHedge(uint256)\\\":{\\\"notice\\\":\\\"check if hedging based on price threshold is allowed\\\"},\\\"checkTimeHedge()\\\":{\\\"notice\\\":\\\"check if hedging based on time threshold is allowed\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"strategy constructor\\\"},\\\"deposit()\\\":{\\\"notice\\\":\\\"deposit ETH into strategy\\\"},\\\"flashDeposit(uint256)\\\":{\\\"notice\\\":\\\"flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\"},\\\"flashWithdraw(uint256,uint256)\\\":{\\\"notice\\\":\\\"flash deposit into strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\"},\\\"getStrategyVaultId()\\\":{\\\"notice\\\":\\\"get power token strategy vault ID \\\"},\\\"getVaultDetails()\\\":{\\\"notice\\\":\\\"get the vault composition of the strategy \\\"},\\\"getWsqueethFromCrabAmount(uint256)\\\":{\\\"notice\\\":\\\"get wSqueeth debt amount associated with strategy token amount\\\"},\\\"priceHedge(uint256,bool,uint256)\\\":{\\\"notice\\\":\\\"strategy hedging based on price threshold\\\"},\\\"priceHedgeOnUniswap(uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"hedge startegy based on price threshold with uniswap arbing\\\"},\\\"redeemShortShutdown()\\\":{\\\"notice\\\":\\\"called to redeem the net value of a vault post shutdown\\\"},\\\"setStrategyCap(uint256)\\\":{\\\"notice\\\":\\\"owner can set the strategy cap in ETH collateral terms\\\"},\\\"timeHedge(bool,uint256)\\\":{\\\"notice\\\":\\\"strategy hedging based on time threshold\\\"},\\\"timeHedgeOnUniswap(uint256,uint256)\\\":{\\\"notice\\\":\\\"hedge startegy based on time threshold with uniswap arbing\\\"},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"notice\\\":\\\"uniswap swap callback function for flashes\\\"},\\\"withdraw(uint256)\\\":{\\\"notice\\\":\\\"withdraw WETH from strategy\\\"},\\\"withdrawShutdown(uint256)\\\":{\\\"notice\\\":\\\"called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\"}},\\\"notice\\\":\\\"Contract for Crab strategy\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/strategy/CrabStrategy.sol\\\":\\\"CrabStrategy\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Safe casting methods\\\\n/// @notice Contains methods for safely casting between types\\\\nlibrary SafeCast {\\\\n    /// @notice Cast a uint256 to a uint160, revert on overflow\\\\n    /// @param y The uint256 to be downcasted\\\\n    /// @return z The downcasted integer, now type uint160\\\\n    function toUint160(uint256 y) internal pure returns (uint160 z) {\\\\n        require((z = uint160(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a int256 to a int128, revert on overflow or underflow\\\\n    /// @param y The int256 to be downcasted\\\\n    /// @return z The downcasted integer, now type int128\\\\n    function toInt128(int256 y) internal pure returns (int128 z) {\\\\n        require((z = int128(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a uint256 to a int256, revert on overflow\\\\n    /// @param y The uint256 to be casted\\\\n    /// @return z The casted integer, now type int256\\\\n    function toInt256(uint256 y) internal pure returns (int256 z) {\\\\n        require(y < 2**255);\\\\n        z = int256(y);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n/*\\\\n * @title Solidity Bytes Arrays Utils\\\\n * @author Gon\\\\u00e7alo S\\\\u00e1 <goncalo.sa@consensys.net>\\\\n *\\\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\\\n */\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nlibrary BytesLib {\\\\n    function slice(\\\\n        bytes memory _bytes,\\\\n        uint256 _start,\\\\n        uint256 _length\\\\n    ) internal pure returns (bytes memory) {\\\\n        require(_length + 31 >= _length, 'slice_overflow');\\\\n        require(_start + _length >= _start, 'slice_overflow');\\\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\\\n\\\\n        bytes memory tempBytes;\\\\n\\\\n        assembly {\\\\n            switch iszero(_length)\\\\n                case 0 {\\\\n                    // Get a location of some free memory and store it in tempBytes as\\\\n                    // Solidity does for memory variables.\\\\n                    tempBytes := mload(0x40)\\\\n\\\\n                    // The first word of the slice result is potentially a partial\\\\n                    // word read from the original array. To read it, we calculate\\\\n                    // the length of that partial word and start copying that many\\\\n                    // bytes into the array. The first word we copy will start with\\\\n                    // data we don't care about, but the last `lengthmod` bytes will\\\\n                    // land at the beginning of the contents of the new array. When\\\\n                    // we're done copying, we overwrite the full first word with\\\\n                    // the actual length of the slice.\\\\n                    let lengthmod := and(_length, 31)\\\\n\\\\n                    // The multiplication in the next line is necessary\\\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\\\n                    // the following copy loop was copying the origin's length\\\\n                    // and then ending prematurely not copying everything it should.\\\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\\\n                    let end := add(mc, _length)\\\\n\\\\n                    for {\\\\n                        // The multiplication in the next line has the same exact purpose\\\\n                        // as the one above.\\\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\\\n                    } lt(mc, end) {\\\\n                        mc := add(mc, 0x20)\\\\n                        cc := add(cc, 0x20)\\\\n                    } {\\\\n                        mstore(mc, mload(cc))\\\\n                    }\\\\n\\\\n                    mstore(tempBytes, _length)\\\\n\\\\n                    //update free-memory pointer\\\\n                    //allocating the array padded to 32 bytes like the compiler does now\\\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\\\n                }\\\\n                //if we want a zero-length slice let's just return a zero-length array\\\\n                default {\\\\n                    tempBytes := mload(0x40)\\\\n                    //zero out the 32 bytes slice we are about to return\\\\n                    //we need to do it because Solidity does not garbage collect\\\\n                    mstore(tempBytes, 0)\\\\n\\\\n                    mstore(0x40, add(tempBytes, 0x20))\\\\n                }\\\\n        }\\\\n\\\\n        return tempBytes;\\\\n    }\\\\n\\\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\\\n        address tempAddress;\\\\n\\\\n        assembly {\\\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\\\n        }\\\\n\\\\n        return tempAddress;\\\\n    }\\\\n\\\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\\\n        uint24 tempUint;\\\\n\\\\n        assembly {\\\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\\\n        }\\\\n\\\\n        return tempUint;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport './PoolAddress.sol';\\\\n\\\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\\\nlibrary CallbackValidation {\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param tokenA The contract address of either token0 or token1\\\\n    /// @param tokenB The contract address of the other token\\\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(\\\\n        address factory,\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool pool) {\\\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param poolKey The identifying key of the V3 pool\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\\\n        internal\\\\n        view\\\\n        returns (IUniswapV3Pool pool)\\\\n    {\\\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\\\n        require(msg.sender == address(pool));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.6.0;\\\\n\\\\nimport './BytesLib.sol';\\\\n\\\\n/// @title Functions for manipulating path data for multihop swaps\\\\nlibrary Path {\\\\n    using BytesLib for bytes;\\\\n\\\\n    /// @dev The length of the bytes encoded address\\\\n    uint256 private constant ADDR_SIZE = 20;\\\\n    /// @dev The length of the bytes encoded fee\\\\n    uint256 private constant FEE_SIZE = 3;\\\\n\\\\n    /// @dev The offset of a single token address and pool fee\\\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\\\n    /// @dev The offset of an encoded pool key\\\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\\\n\\\\n    /// @notice Returns true iff the path contains two or more pools\\\\n    /// @param path The encoded swap path\\\\n    /// @return True if path contains two or more pools, otherwise false\\\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\\\n    }\\\\n\\\\n    /// @notice Returns the number of pools in the path\\\\n    /// @param path The encoded swap path\\\\n    /// @return The number of pools in the path\\\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Decodes the first pool in path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return tokenA The first token of the given pool\\\\n    /// @return tokenB The second token of the given pool\\\\n    /// @return fee The fee level of the pool\\\\n    function decodeFirstPool(bytes memory path)\\\\n        internal\\\\n        pure\\\\n        returns (\\\\n            address tokenA,\\\\n            address tokenB,\\\\n            uint24 fee\\\\n        )\\\\n    {\\\\n        tokenA = path.toAddress(0);\\\\n        fee = path.toUint24(ADDR_SIZE);\\\\n        tokenB = path.toAddress(NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Gets the segment corresponding to the first pool in the path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return The segment containing all data necessary to target the first pool in the path\\\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(0, POP_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\\\n    /// @param path The swap path\\\\n    /// @return The remaining token + fee elements in the path\\\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnOnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc5d6230c8bafcaf2ae7260efd68c45ab13e91819ed9e11881b29dc48386e4bc7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8a9a4512f1fc29b14dcf97ca149f263f28de43191a3ee31336f2389e3f2f5f8e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/Power2Base.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary Power2Base {\\\\n    using SafeMath for uint256;\\\\n\\\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\\\n    uint256 private constant INDEX_SCALE = 1e4;\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    /**\\\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getUnscaledIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\\\n     */\\\\n    function _getDenormalizedMark(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _wSqueeth,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\\\n\\\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _weth weth address\\\\n     * @return returns value of debt in ETH\\\\n     */\\\\n    function _getDebtValueInEth(\\\\n        uint256 _debtAmount,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _wSqueeth,\\\\n        address _weth\\\\n    ) internal view returns (uint256) {\\\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle\\\\n     * @dev this will revert if period is > max period for the pool\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        // period reaching this point should be check, otherwise might revert\\\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\\\n     * @param _indexPriceForSettlement index price for settlement\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return amount in wei that should be paid to the token holder\\\\n     */\\\\n    function _getLongSettlementValue(\\\\n        uint256 _wsqueethAmount,\\\\n        uint256 _indexPriceForSettlement,\\\\n        uint256 _normalizationFactor\\\\n    ) internal pure returns (uint256) {\\\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1938180c41ec0ee817b841df605b199e15ffbbe94700b640d031b4e4665a89af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x939175a827c8e9d8d09ee55957e8127a6a55bf42d6a0b3e48b0b59c895aa85af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/CrabStrategy.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {StrategyBase} from \\\\\\\"./base/StrategyBase.sol\\\\\\\";\\\\nimport {StrategyFlashSwap} from \\\\\\\"./base/StrategyFlashSwap.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {StrategyMath} from \\\\\\\"./base/StrategyMath.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev CrabStrategy contract\\\\n * @notice Contract for Crab strategy\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\\\n    // strategy will only allow hedging if collateral to trade is at least 0.1% of the total strategy collateral\\\\n    uint256 public constant DELTA_HEDGE_THRESHOLD = 1e15;\\\\n\\\\n    uint256 public strategyCap;\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum FLASH_SOURCE {\\\\n        FLASH_DEPOSIT,\\\\n        FLASH_WITHDRAW,\\\\n        FLASH_HEDGE_SELL,\\\\n        FLASH_HEDGE_BUY\\\\n    }\\\\n\\\\n    /// @dev ETH:WSqueeth uniswap pool\\\\n    address public immutable ethWSqueethPool;\\\\n    /// @dev strategy uniswap oracle\\\\n    address public immutable oracle;\\\\n    address public immutable ethQuoteCurrencyPool;\\\\n    address public immutable quoteCurrency;\\\\n\\\\n    /// @dev time difference to trigger a hedge (seconds)\\\\n    uint256 public immutable hedgeTimeThreshold;\\\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\\\n    uint256 public immutable hedgePriceThreshold;\\\\n    /// @dev hedge auction duration (seconds)\\\\n    uint256 public immutable auctionTime;\\\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for end sell auction (scaled 1e18)\\\\n    uint256 public immutable minPriceMultiplier;\\\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\\\n    uint256 public immutable maxPriceMultiplier;\\\\n\\\\n    /// @dev timestamp when last hedge executed\\\\n    uint256 public timeAtLastHedge;\\\\n    /// @dev WSqueeth/Eth price when last hedge executed\\\\n    uint256 public priceAtLastHedge;\\\\n    uint256 public auctionStartTime;\\\\n\\\\n    /// @dev set to true when redeemShortShutdown has been called\\\\n    bool public hasRedeemedInShutdown;\\\\n\\\\n    struct FlashDepositData {\\\\n        uint256 totalDeposit;\\\\n    }\\\\n\\\\n    struct FlashWithdrawData {\\\\n        uint256 crabAmount;\\\\n    }\\\\n\\\\n    struct FlashHedgeData {\\\\n        uint256 wSqueethAmount;\\\\n        uint256 ethProceeds;\\\\n        uint256 minWSqueeth;\\\\n        uint256 minEth;\\\\n    }\\\\n\\\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\\\n    event TimeHedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        uint256 hedgeTimestamp,\\\\n        uint256 auctionTriggerTimestamp,\\\\n        uint256 minWSqueeth,\\\\n        uint256 minEth\\\\n    );\\\\n    event PriceHedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        uint256 hedgeTimestamp,\\\\n        uint256 auctionTriggerTimestamp,\\\\n        uint256 minWSqueeth,\\\\n        uint256 minEth\\\\n    );\\\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\\\n    event Hedge(\\\\n        address indexed hedger,\\\\n        bool auctionType,\\\\n        uint256 hedgerPrice,\\\\n        uint256 auctionPrice,\\\\n        uint256 wSqueethHedgeTargetAmount,\\\\n        uint256 ethHedgetargetAmount\\\\n    );\\\\n    event HedgeOnUniswap(\\\\n        address indexed hedger,\\\\n        bool auctionType,\\\\n        uint256 auctionPrice,\\\\n        uint256 wSqueethHedgeTargetAmount,\\\\n        uint256 ethHedgetargetAmount\\\\n    );\\\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\\\n    event SetStrategyCap(uint256 newCapAmount, uint256 oldCapAmount);\\\\n\\\\n    /**\\\\n     * @notice strategy constructor\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _wSqueethController power token controller address\\\\n     * @param _oracle oracle address\\\\n     * @param _weth weth address\\\\n     * @param _uniswapFactory uniswap factory address\\\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\\\n     * @param _auctionTime auction duration (seconds)\\\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\\\n     */\\\\n    constructor(\\\\n        address _wSqueethController,\\\\n        address _oracle,\\\\n        address _weth,\\\\n        address _uniswapFactory,\\\\n        address _ethWSqueethPool,\\\\n        uint256 _hedgeTimeThreshold,\\\\n        uint256 _hedgePriceThreshold,\\\\n        uint256 _auctionTime,\\\\n        uint256 _minPriceMultiplier,\\\\n        uint256 _maxPriceMultiplier\\\\n    ) StrategyBase(_wSqueethController, _weth, \\\\\\\"Crab Strategy\\\\\\\", \\\\\\\"Crab\\\\\\\") StrategyFlashSwap(_uniswapFactory) {\\\\n        require(_oracle != address(0), \\\\\\\"invalid oracle address\\\\\\\");\\\\n        require(_ethWSqueethPool != address(0), \\\\\\\"invalid ETH:WSqueeth address\\\\\\\");\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"invalid hedge time threshold\\\\\\\");\\\\n        require(_hedgePriceThreshold > 0, \\\\\\\"invalid hedge price threshold\\\\\\\");\\\\n        require(_auctionTime > 0, \\\\\\\"invalid auction time\\\\\\\");\\\\n        require(_minPriceMultiplier < 1e18, \\\\\\\"auction min price multiplier too high\\\\\\\");\\\\n        require(_minPriceMultiplier > 0, \\\\\\\"invalid auction min price multiplier\\\\\\\");\\\\n        require(_maxPriceMultiplier > 1e18, \\\\\\\"auction max price multiplier too low\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        ethWSqueethPool = _ethWSqueethPool;\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n        auctionTime = _auctionTime;\\\\n        minPriceMultiplier = _minPriceMultiplier;\\\\n        maxPriceMultiplier = _maxPriceMultiplier;\\\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\\\\\"Cannot receive eth\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the strategy cap in ETH collateral terms\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\\\n        uint256 oldCap = strategyCap;\\\\n        strategyCap = _capAmount;\\\\n\\\\n        emit SetStrategyCap(_capAmount, oldCap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to redeem the net value of a vault post shutdown\\\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\\\n     */\\\\n    function redeemShortShutdown() external {\\\\n        hasRedeemedInShutdown = true;\\\\n        powerTokenController.redeemShort(vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\\n     */\\\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\\\n            _ethToDeposit,\\\\n            cachedStrategyDebt,\\\\n            cachedStrategyCollateral\\\\n        );\\\\n\\\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\\\n            // store hedge data as strategy is delta neutral at this point\\\\n            // only execute this upon first deposit\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\\\n            timeAtLastHedge = block.timestamp;\\\\n            priceAtLastHedge = wSqueethEthPrice;\\\\n        }\\\\n\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n            wSqueethToMint,\\\\n            _ethToDeposit.sub(msg.value),\\\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\\\n            abi.encodePacked(_ethToDeposit)\\\\n        );\\\\n\\\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash deposit into strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\\n     * @param _crabAmount strategy token amount to burn\\\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\\\n     */\\\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n            exactWSqueethNeeded,\\\\n            _maxEthToPay,\\\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\\\n            abi.encodePacked(_crabAmount)\\\\n        );\\\\n\\\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit ETH into strategy\\\\n     * @dev provide ETH, return wSqueeth and strategy token\\\\n     * @return wSqueethToMint minted amount of wSqueeth\\\\n     * @return depositorCrabAmount minted amount of strategy token\\\\n     */\\\\n    function deposit() external payable nonReentrant returns (uint256, uint256) {\\\\n        uint256 amount = msg.value;\\\\n\\\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\\\n\\\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\\\n\\\\n        return (wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdraw(uint256 _crabAmount) external payable nonReentrant {\\\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\\\n\\\\n        // send back ETH collateral\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n\\\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\\\n        require(powerTokenController.isShutDown(), \\\\\\\"Squeeth contracts are not shut down\\\\\\\");\\\\n        require(hasRedeemedInShutdown, \\\\\\\"Strategy has not redeemed vault proceeds\\\\\\\");\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\\\n        _burn(msg.sender, _crabAmount);\\\\n\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\\\n     * @param _minWSqueeth minimum WSqueeth amount of profit if hedge auction is selling WSqueeth\\\\n     * @param _minEth minimum ETH amount of profit if hedge auction is buying WSqueeth\\\\n     */\\\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\\\n\\\\n        require(block.timestamp >= auctionTriggerTime, \\\\\\\"Time hedging is not allowed\\\\\\\");\\\\n\\\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\\\n\\\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\\\n     */\\\\n    function priceHedgeOnUniswap(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _minWSqueeth,\\\\n        uint256 _minEth\\\\n    ) external payable {\\\\n        require(_isPriceHedge(_auctionTriggerTime), \\\\\\\"Price hedging not allowed\\\\\\\");\\\\n\\\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\\\n\\\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy hedging based on time threshold\\\\n     * @dev need to attach msg.value if buying WSqueeth\\\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\\\n     */\\\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\\\n\\\\n        require(isTimeHedgeAllowed, \\\\\\\"Time hedging is not allowed\\\\\\\");\\\\n\\\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\\\n\\\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy hedging based on price threshold\\\\n     * @dev need to attach msg.value if buying WSqueeth\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     */\\\\n    function priceHedge(\\\\n        uint256 _auctionTriggerTime,\\\\n        bool _isStrategySellingWSqueeth,\\\\n        uint256 _limitPrice\\\\n    ) external payable nonReentrant {\\\\n        require(_isPriceHedge(_auctionTriggerTime), \\\\\\\"Price hedging not allowed\\\\\\\");\\\\n\\\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\\\n\\\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @param _auctionTriggerTime alleged timestamp where auction was triggered\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\\\n        return _isPriceHedge(_auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\\\n     * @return auctionTriggertime auction trigger timestamp\\\\n     */\\\\n    function checkTimeHedge() external view returns (bool, uint256) {\\\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\\\n\\\\n        return (isTimeHedgeAllowed, auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\\\n     * @dev _crabAmount strategy token amount\\\\n     * @return wSqueeth amount\\\\n     */\\\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\\\n        return _getDebtFromStrategyAmount(_crabAmount);\\\\n    }\\\\n\\\\n    function canExecuteAuction(uint256 _auctionTriggerTime) external view returns (bool) {\\\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\\\n        (bool isStillSellingAuction, ) = _checkAuctionType(\\\\n            strategyDebt,\\\\n            ethDelta,\\\\n            auctionWSqueethEthPrice,\\\\n            feeAdjustment\\\\n        );\\\\n\\\\n        return isSellingAuction == isStillSellingAuction;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a user deposit puts the strategy above the cap\\\\n     * @dev reverts if a deposit amount puts strategy over the cap\\\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\\\n     * @param _depositAmount the user deposit amount in ETH\\\\n     * @param _strategyCollateral the updated strategy collateral\\\\n     */\\\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\\\\\"Deposit exceeds strategy cap\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _strategyFlash(\\\\n        address _caller,\\\\n        address, /*_tokenIn*/\\\\n        address, /*_tokenOut*/\\\\n        uint24, /*_fee*/\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n\\\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\\\n            //will revert if data.totalDeposit is > eth balance in contract\\\\n            _deposit(_caller, data.totalDeposit, true);\\\\n\\\\n            //repay the flash swap\\\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\\\n\\\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\\\n\\\\n            //return excess eth to the user that was not needed for slippage\\\\n            if (address(this).balance > 0) {\\\\n                payable(_caller).sendValue(address(this).balance);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\\\n\\\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\\\n            uint256 ethToWithdraw = _withdraw(\\\\n                _caller,\\\\n                data.crabAmount,\\\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\\\n                true\\\\n            );\\\\n\\\\n            //use some amount of withdrawn ETH to repay flash swap\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\\\n\\\\n            //excess ETH not used to repay flash swap is transferred to the user\\\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\\\n\\\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\\\n\\\\n            if (proceeds > 0) {\\\\n                payable(_caller).sendValue(proceeds);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\\\n            //strategy is selling wSqueeth for ETH\\\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\\\n\\\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\\\n\\\\n            //minimum profit check for hedger\\\\n            require(wSqueethProfit >= data.minWSqueeth, \\\\\\\"profit is less than min wSqueeth\\\\\\\");\\\\n\\\\n            //repay flash swap and transfer profit to hedger\\\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\\\n            //strategy is buying wSqueeth for ETH\\\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\\\n\\\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\\\n\\\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\\\n\\\\n            //minimum profit check for hedger\\\\n            require(ethProfit >= data.minEth, \\\\\\\"profit is less than min ETH\\\\\\\");\\\\n\\\\n            //repay flash swap and transfer profit to hedger\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\\\n            payable(_caller).sendValue(ethProfit);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit into strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _depositor depositor address\\\\n     * @param _amount amount of ETH collateral to deposit\\\\n     * @param _isFlashDeposit true if called by flashDeposit\\\\n     * @return wSqueethToMint minted amount of WSqueeth\\\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\\\n     */\\\\n    function _deposit(\\\\n        address _depositor,\\\\n        uint256 _amount,\\\\n        bool _isFlashDeposit\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_amount, strategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\\\n\\\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\\\n\\\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\\\n            // store hedge data as strategy is delta neutral at this point\\\\n            // only execute this upon first deposit\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\\\n            timeAtLastHedge = block.timestamp;\\\\n            priceAtLastHedge = wSqueethEthPrice;\\\\n        }\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\\\n\\\\n        return (wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\\\n     * @return ETH amount to withdraw\\\\n     */\\\\n    function _withdraw(\\\\n        address _from,\\\\n        uint256 _crabAmount,\\\\n        uint256 _wSqueethAmount,\\\\n        bool _isFlashWithdraw\\\\n    ) internal returns (uint256) {\\\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\\\n\\\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\\\n        _burn(_from, _crabAmount);\\\\n\\\\n        return ethToWithdraw;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\\\n     */\\\\n    function _hedge(\\\\n        uint256 _auctionTriggerTime,\\\\n        bool _isStrategySellingWSqueeth,\\\\n        uint256 _limitPrice\\\\n    ) internal {\\\\n        (\\\\n            bool isSellingAuction,\\\\n            uint256 wSqueethToAuction,\\\\n            uint256 ethProceeds,\\\\n            uint256 auctionWSqueethEthPrice\\\\n        ) = _startAuction(_auctionTriggerTime);\\\\n\\\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\\\\\"wrong auction type\\\\\\\");\\\\n\\\\n        if (isSellingAuction) {\\\\n            // Receiving ETH and paying wSqueeth\\\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\\\\\"Auction price greater than max accepted price\\\\\\\");\\\\n            require(msg.value >= ethProceeds, \\\\\\\"Low ETH amount received\\\\\\\");\\\\n\\\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\\\n        } else {\\\\n            require(msg.value == 0, \\\\\\\"ETH attached for buy auction\\\\\\\");\\\\n            // Receiving wSqueeth and paying ETH\\\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\\\\\"Auction price greater than min accepted price\\\\\\\");\\\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\\\n        }\\\\n\\\\n        emit Hedge(\\\\n            msg.sender,\\\\n            _isStrategySellingWSqueeth,\\\\n            _limitPrice,\\\\n            auctionWSqueethEthPrice,\\\\n            wSqueethToAuction,\\\\n            ethProceeds\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute arb between auction price and uniswap price\\\\n     * @param _auctionTriggerTime auction starting time\\\\n     */\\\\n    function _hedgeOnUniswap(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _minWSqueeth,\\\\n        uint256 _minEth\\\\n    ) internal {\\\\n        (\\\\n            bool isSellingAuction,\\\\n            uint256 wSqueethToAuction,\\\\n            uint256 ethProceeds,\\\\n            uint256 auctionWSqueethEthPrice\\\\n        ) = _startAuction(_auctionTriggerTime);\\\\n\\\\n        if (isSellingAuction) {\\\\n            _exactOutFlashSwap(\\\\n                wPowerPerp,\\\\n                weth,\\\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n                ethProceeds,\\\\n                wSqueethToAuction,\\\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\\\n            );\\\\n        } else {\\\\n            _exactOutFlashSwap(\\\\n                weth,\\\\n                wPowerPerp,\\\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\\\n                wSqueethToAuction,\\\\n                ethProceeds,\\\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\\\n            );\\\\n        }\\\\n\\\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute sell auction based on the parameters calculated\\\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\\\n     * @param _buyer buyer address\\\\n     * @param _buyerAmount buyer ETH amount sent\\\\n     * @param _wSqueethToSell wSqueeth amount to sell\\\\n     * @param _ethToBuy ETH amount to buy\\\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\\\n     */\\\\n    function _executeSellAuction(\\\\n        address _buyer,\\\\n        uint256 _buyerAmount,\\\\n        uint256 _wSqueethToSell,\\\\n        uint256 _ethToBuy,\\\\n        bool _isHedgingOnUniswap\\\\n    ) internal {\\\\n        if (_isHedgingOnUniswap) {\\\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\\\n        } else {\\\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\\\n\\\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\\\n\\\\n            if (remainingEth > 0) {\\\\n                payable(_buyer).sendValue(remainingEth);\\\\n            }\\\\n        }\\\\n\\\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute buy auction based on the parameters calculated\\\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\\\n     * @param _seller seller address\\\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\\\n     * @param _ethToSell ETH amount to sell\\\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\\\n     */\\\\n    function _executeBuyAuction(\\\\n        address _seller,\\\\n        uint256 _wSqueethToBuy,\\\\n        uint256 _ethToSell,\\\\n        bool _isHedgingOnUniswap\\\\n    ) internal {\\\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\\\n\\\\n        if (!_isHedgingOnUniswap) {\\\\n            payable(_seller).sendValue(_ethToSell);\\\\n        }\\\\n\\\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\\\n     * @param _auctionTriggerTime auction starting time\\\\n     * @return auction type\\\\n     * @return WSqueeth amount to sell or buy\\\\n     * @return ETH to sell/buy\\\\n     * @return auction WSqueeth/ETH price\\\\n     */\\\\n    function _startAuction(uint256 _auctionTriggerTime)\\\\n        internal\\\\n        returns (\\\\n            bool,\\\\n            uint256,\\\\n            uint256,\\\\n            uint256\\\\n        )\\\\n    {\\\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\\\n            strategyDebt,\\\\n            ethDelta,\\\\n            auctionWSqueethEthPrice,\\\\n            feeAdjustment\\\\n        );\\\\n\\\\n        require(isSellingAuction == isStillSellingAuction, \\\\\\\"can not execute hedging trade as auction type changed\\\\\\\");\\\\n\\\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\\\n\\\\n        timeAtLastHedge = block.timestamp;\\\\n        priceAtLastHedge = currentWSqueethPrice;\\\\n\\\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sync strategy debt and collateral amount from vault\\\\n     * @return synced debt amount\\\\n     * @return synced collateral amount\\\\n     */\\\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\\\n\\\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\\\n     * @return the fee adjustment factor\\\\n     */\\\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\\\n            oracle,\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            POWER_PERP_PERIOD,\\\\n            false\\\\n        );\\\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\\\n     * @param _depositedAmount amount of deposited WETH\\\\n     * @param _strategyDebtAmount amount of strategy debt\\\\n     * @param _strategyCollateralAmount collateral amount in strategy\\\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\\\n     */\\\\n    function _calcWsqueethToMintAndFee(\\\\n        uint256 _depositedAmount,\\\\n        uint256 _strategyDebtAmount,\\\\n        uint256 _strategyCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 wSqueethToMint;\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n\\\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\\\n            require(\\\\n                totalSupply() == 0,\\\\n                \\\\\\\"Crab strategy shut down due to full liquidation or shutdown of squeeth contracts\\\\\\\"\\\\n            );\\\\n\\\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\\\n        } else {\\\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\\\n            );\\\\n        }\\\\n\\\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\\\n\\\\n        return (wSqueethToMint, fee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if time hedging is allowed\\\\n     * @return auction trigger timestamp\\\\n     */\\\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\\\n\\\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            secondsToPriceHedgeTrigger + TWAP_PERIOD,\\\\n            secondsToPriceHedgeTrigger\\\\n        );\\\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\\\n\\\\n        return priceThreshold >= hedgePriceThreshold;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\\\n     * @param _auctionTriggerTime timestamp where auction started\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\\\n     * @return auction price\\\\n     */\\\\n    function _getAuctionPrice(\\\\n        uint256 _auctionTriggerTime,\\\\n        uint256 _wSqueethEthPrice,\\\\n        bool _isSellingAuction\\\\n    ) internal view returns (uint256) {\\\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\\\n            ? 1e18\\\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\\\n\\\\n        uint256 priceMultiplier;\\\\n        if (_isSellingAuction) {\\\\n            priceMultiplier = maxPriceMultiplier.sub(\\\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\\\n            );\\\\n        } else {\\\\n            priceMultiplier = minPriceMultiplier.add(\\\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\\\n            );\\\\n        }\\\\n\\\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\\\n     * @param _debt strategy debt\\\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueth\\\\n     */\\\\n    function _checkAuctionType(\\\\n        uint256 _debt,\\\\n        uint256 _ethDelta,\\\\n        uint256 _wSqueethEthPrice,\\\\n        uint256 _feeAdjustment\\\\n    ) internal pure returns (bool, uint256) {\\\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\\\n\\\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\\\n            wSqueethDelta,\\\\n            _ethDelta,\\\\n            _wSqueethEthPrice,\\\\n            _feeAdjustment\\\\n        );\\\\n\\\\n        uint256 collateralRatioToHedge = targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta);\\\\n\\\\n        require(collateralRatioToHedge > DELTA_HEDGE_THRESHOLD, \\\\\\\"strategy is delta neutral\\\\\\\");\\\\n\\\\n        return (isSellingAuction, targetHedge);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate amount of strategy token to mint for depositor\\\\n     * @param _amount amount of ETH deposited\\\\n     * @param _strategyCollateralAmount amount of strategy collateral\\\\n     * @param _crabTotalSupply total supply of strategy token\\\\n     * @return amount of strategy token to mint\\\\n     */\\\\n    function _calcSharesToMint(\\\\n        uint256 _amount,\\\\n        uint256 _strategyCollateralAmount,\\\\n        uint256 _crabTotalSupply\\\\n    ) internal pure returns (uint256) {\\\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\\\n\\\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\\\n\\\\n        return _amount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\\\n     * @param _crabAmount strategy token amount\\\\n     * @param _totalSupply strategy total supply\\\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\\\n     */\\\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\\\n        return _crabAmount.wdiv(_totalSupply);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\\\n     * @param _crabRatio crab ratio\\\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\\\n     * @return amount of ETH allowed to withdraw\\\\n     */\\\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine target hedge and auction type (selling/buying auction)\\\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\\\n     * @param _wSqueethDelta WSqueeth delta\\\\n     * @param _ethDelta ETH delta\\\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\\\n     * @return target hedge in wSqueeth\\\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\\\n     */\\\\n    function _getTargetHedgeAndAuctionType(\\\\n        uint256 _wSqueethDelta,\\\\n        uint256 _ethDelta,\\\\n        uint256 _wSqueethEthPrice,\\\\n        uint256 _feeAdjustment\\\\n    ) internal pure returns (uint256, bool) {\\\\n        return\\\\n            (_wSqueethDelta > _ethDelta)\\\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xefd97834ea1dea979733b2731b5a5779feb6152f42f46e0890b0c184c30c96e9\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/base/StrategyBase.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {StrategyMath} from \\\\\\\"./StrategyMath.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../../libs/VaultLib.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev StrategyBase contract\\\\n * @notice base contract for PowerToken strategy\\\\n * @author opyn team\\\\n */\\\\ncontract StrategyBase is ERC20 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev power token controller\\\\n    IController public powerTokenController;\\\\n\\\\n    /// @dev WETH token\\\\n    address public immutable weth;\\\\n    address public immutable wPowerPerp;\\\\n\\\\n    /// @dev power token strategy vault ID\\\\n    uint256 public immutable vaultId;\\\\n\\\\n    /**\\\\n     * @notice constructor for StrategyBase\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _powerTokenController power token controller address\\\\n     * @param _weth weth token address\\\\n     * @param _name token name for strategy ERC20 token\\\\n     * @param _symbol token symbol for strategy ERC20 token\\\\n     */\\\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\\\n        require(_powerTokenController != address(0), \\\\\\\"invalid power token controller address\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"invalid weth address\\\\\\\");\\\\n\\\\n        weth = _weth;\\\\n        powerTokenController = IController(_powerTokenController);\\\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\\\n    }\\\\n    /**\\\\n     * @notice get power token strategy vault ID \\\\n     * @return vault ID\\\\n     */\\\\n    function getStrategyVaultId() external view returns (uint256) {\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n    */\\\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\\\n        return _getVaultDetails();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint WPowerPerp and deposit collateral\\\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\\\n     * @param _to receiver address\\\\n     * @param _wAmount amount of WPowerPerp to mint\\\\n     * @param _collateral amount of collateral to deposit\\\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\\\n     */\\\\n    function _mintWPowerPerp(\\\\n        address _to,\\\\n        uint256 _wAmount,\\\\n        uint256 _collateral,\\\\n        bool _keepWsqueeth\\\\n    ) internal {\\\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\\\n\\\\n        if (!_keepWsqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn WPowerPerp and withdraw collateral\\\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\\\n     * @param _from WPowerPerp holder address\\\\n     * @param _amount amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\\\n     */\\\\n    function _burnWPowerPerp(\\\\n        address _from,\\\\n        uint256 _amount,\\\\n        uint256 _collateralToWithdraw,\\\\n        bool _isOwnedWSqueeth\\\\n    ) internal {\\\\n        if (!_isOwnedWSqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\\\n        }\\\\n\\\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint strategy token\\\\n     * @param _to recepient address\\\\n     * @param _amount token amount\\\\n     */\\\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\\\n        _mint(_to, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get strategy debt amount for a specific strategy token amount\\\\n     * @param _strategyAmount strategy amount\\\\n     * @return debt amount\\\\n     */\\\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n     */\\\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\\\n\\\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\\\n    }\\\\n}\\\\n\\\\n\\\",\\\"keccak256\\\":\\\"0x7ddcfefd4b947c490edb279eaf5ffa4e6332b47a1df0f7969dce4b6425141f24\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/base/StrategyFlashSwap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\\\n\\\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\\\n    using Path for bytes;\\\\n    using SafeCast for uint256;\\\\n    using LowGasSafeMath for uint256;\\\\n    using LowGasSafeMath for int256;\\\\n\\\\n    /// @dev Uniswap factory address\\\\n    address public immutable factory;\\\\n\\\\n    struct SwapCallbackData {\\\\n        bytes path;\\\\n        address caller;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev constructor\\\\n     * @param _factory uniswap factory address\\\\n     */\\\\n    constructor(\\\\n        address _factory\\\\n    ) {\\\\n        require(_factory != address(0), \\\\\\\"invalid factory address\\\\\\\");\\\\n        factory = _factory;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap swap callback function for flashes\\\\n     * @param amount0Delta amount of token0\\\\n     * @param amount1Delta amount of token1\\\\n     * @param _data callback data encoded as SwapCallbackData struct\\\\n     */\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata _data\\\\n    ) external override {\\\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\\\n\\\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //ensure that callback comes from uniswap pool\\\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\\\n\\\\n        //determine the amount that needs to be repaid as part of the flashswap\\\\n        uint256 amountToPay =\\\\n            amount0Delta > 0\\\\n                ?  uint256(amount0Delta)\\\\n                :  uint256(amount1Delta);\\\\n        \\\\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountIn amount to sell\\\\n     * @param _amountOutMinimum minimum amount to receive\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountOut = _exactInputInternal(\\\\n            _amountIn,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n       \\\\n        //slippage limit check\\\\n        require(amountOut >= _amountOutMinimum, \\\\\\\"amount out less than min\\\\\\\");\\\\n    }\\\\n\\\\n\\\\n    /**\\\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountOut exact amount to receive\\\\n     * @param _amountInMaximum maximum amount to sell\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountIn = _exactOutputInternal(\\\\n            _amountOut,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n        \\\\n        //slippage limit check\\\\n        require(amountIn <= _amountInMaximum, \\\\\\\"amount in greater than max\\\\\\\");\\\\n    }\\\\n\\\\n\\\\n    /**\\\\n     * @notice function to be called by uniswap callback. \\\\n     * @dev this function should be overridden by the child contract\\\\n     * param _caller initial strategy function caller\\\\n     * param _tokenIn token address sold\\\\n     * param _tokenOut token address bought\\\\n     * param _fee pool fee\\\\n     * param _amountToPay amount to pay for the pool second token\\\\n     * param _callData arbitrary data assigned with the flashswap call \\\\n     * param _callSource function call source\\\\n     */\\\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\\\n    \\\\n    /** \\\\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\\\n    * @param _amountIn amount of token to pay\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token bought (amountOut)\\\\n    */\\\\n    function _exactInputInternal(\\\\n        uint256 _amountIn,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n       \\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0, int256 amount1) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                _amountIn.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n        \\\\n        //determine the amountOut based on which token has a lower address\\\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\\\n    * @param _amountOut amount of token to receive\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token sold (amountIn)\\\\n    */\\\\n    function _exactOutputInternal(\\\\n        uint256 _amountOut,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n        \\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0Delta, int256 amount1Delta) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                -_amountOut.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n\\\\n        //determine the amountIn and amountOut based on which token has a lower address\\\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\\\n        // it's technically possible to not receive the full output amount,\\\\n        // so if no price limit has been specified, require this possibility away\\\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\\\n\\\\n        return amountIn;\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice returns the uniswap pool for the given token pair and fee\\\\n    * @dev the pool contract may or may not exist\\\\n    * @param tokenA address of first token \\\\n    * @param tokenB address of second token \\\\n    * @param fee fee tier for pool\\\\n    */\\\\n    function _getPool(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) private view returns (IUniswapV3Pool) {\\\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0eb6d9c8b33ee8c48f9abd106d84fea7b39548a3ce9d77d2f435e0740f914aff\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/base/StrategyMath.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: AGPL-3.0-only\\\\n\\\\n/// math.sol -- mixin for inline numerical wizardry\\\\n\\\\n// This program is free software: you can redistribute it and/or modify\\\\n// it under the terms of the GNU General Public License as published by\\\\n// the Free Software Foundation, either version 3 of the License, or\\\\n// (at your option) any later version.\\\\n\\\\n// This program is distributed in the hope that it will be useful,\\\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\\\n// GNU General Public License for more details.\\\\n\\\\n// You should have received a copy of the GNU General Public License\\\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\\\n\\\\npragma solidity >0.4.13;\\\\n\\\\n\\\\n/**\\\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\\\n * @dev change contract to library, all uint to uint256, added div() function\\\\n */\\\\nlibrary StrategyMath {\\\\n    function add(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x + y) >= x, \\\\\\\"ds-math-add-overflow\\\\\\\");\\\\n    }\\\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x - y) <= x, \\\\\\\"ds-math-sub-underflow\\\\\\\");\\\\n    }\\\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\\\n        require(y == 0 || (z = x * y) / y == x, \\\\\\\"ds-math-mul-overflow\\\\\\\");\\\\n    }\\\\n\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    function min(uint x, uint y) internal pure returns (uint z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function max(uint x, uint y) internal pure returns (uint z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n    function imin(int x, int y) internal pure returns (int z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function imax(int x, int y) internal pure returns (int z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n\\\\n    uint constant WAD = 10 ** 18;\\\\n    uint constant RAY = 10 ** 27;\\\\n\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), WAD / 2) / WAD;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), RAY / 2) / RAY;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, WAD), y / 2) / y;\\\\n    }\\\\n    //rounds to zero if x*y < RAY / 2\\\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, RAY), y / 2) / y;\\\\n    }\\\\n\\\\n    // This famous algorithm is called \\\\\\\"exponentiation by squaring\\\\\\\"\\\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\\\n    //\\\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\\\n    //\\\\n    // These facts are why it works:\\\\n    //\\\\n    //  If n is even, then x^n = (x^2)^(n/2).\\\\n    //  If n is odd,  then x^n = x * x^(n-1),\\\\n    //   and applying the equation for even x gives\\\\n    //    x^n = x * (x^2)^((n-1) / 2).\\\\n    //\\\\n    //  Also, EVM division is flooring and\\\\n    //    floor[(n-1) / 2] = floor[n / 2].\\\\n    //\\\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\\\n        z = n % 2 != 0 ? x : RAY;\\\\n\\\\n        for (n /= 2; n != 0; n /= 2) {\\\\n            x = rmul(x, x);\\\\n\\\\n            if (n % 2 != 0) {\\\\n                z = rmul(z, x);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0x84c9ac7d6dc04da14edb481015a2c76d0a95a1c3cb56834fbc2c91b2019a1c57\\\",\\\"license\\\":\\\"AGPL-3.0-only\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6102206040523480156200001257600080fd5b50604051620066f1380380620066f1833981016040819052620000359162000698565b868a896040518060400160405280600d81526020016c4372616220537472617465677960981b8152506040518060400160405280600481526020016321b930b160e11b8152508181816003908051906020019062000095929190620005ab565b508051620000ab906004906020840190620005ab565b50506005805460ff19166012179055506001600160a01b038416620000ed5760405162461bcd60e51b8152600401620000e49062000768565b60405180910390fd5b6001600160a01b038316620001165760405162461bcd60e51b8152600401620000e4906200098e565b606083901b6001600160601b03191660805260058054610100600160a81b0319166101006001600160a01b0387811682029290921792839055604080516307f07b1360e41b815290519190930490911691637f07b130916004808301926020929190829003018186803b1580156200018d57600080fd5b505afa158015620001a2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c8919062000674565b6001600160601b031960609190911b1660a052600554604051630728cf2360e31b81526101009091046001600160a01b03169063394679189062000216906000908190819060040162000752565b602060405180830381600087803b1580156200023157600080fd5b505af115801562000246573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200026c919062000739565b60c052505050506001600160a01b0381166200029c5760405162461bcd60e51b8152600401620000e49062000912565b60601b6001600160601b03191660e05260016006556000620002bd620005a7565b600780546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b038916620003345760405162461bcd60e51b8152600401620000e49062000853565b6001600160a01b0386166200035d5760405162461bcd60e51b8152600401620000e490620009c5565b60008511620003805760405162461bcd60e51b8152600401620000e4906200081c565b60008411620003a35760405162461bcd60e51b8152600401620000e490620007e5565b60008311620003c65760405162461bcd60e51b8152600401620000e490620007ae565b670de0b6b3a76400008210620003f05760405162461bcd60e51b8152600401620000e49062000949565b60008211620004135760405162461bcd60e51b8152600401620000e4906200088a565b670de0b6b3a764000081116200043d5760405162461bcd60e51b8152600401620000e490620008ce565b6001600160601b031960608a811b82166101205287901b16610100526101808590526101a08490526101c08390526101e082905261020081905260408051632234601160e11b815290516001600160a01b038c1691634468c022916004808301926020929190829003018186803b158015620004b857600080fd5b505afa158015620004cd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004f3919062000674565b6001600160a01b0316610140816001600160a01b031660601b81525050896001600160a01b03166382564bca6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200054a57600080fd5b505afa1580156200055f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000585919062000674565b60601b6001600160601b0319166101605250620009fc98505050505050505050565b3390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620005e357600085556200062e565b82601f10620005fe57805160ff19168380011785556200062e565b828001600101855582156200062e579182015b828111156200062e57825182559160200191906001019062000611565b506200063c92915062000640565b5090565b5b808211156200063c576000815560010162000641565b80516001600160a01b03811681146200066f57600080fd5b919050565b60006020828403121562000686578081fd5b620006918262000657565b9392505050565b6000806000806000806000806000806101408b8d031215620006b8578586fd5b620006c38b62000657565b9950620006d360208c0162000657565b9850620006e360408c0162000657565b9750620006f360608c0162000657565b96506200070360808c0162000657565b955060a08b0151945060c08b0151935060e08b015192506101008b015191506101208b015190509295989b9194979a5092959850565b6000602082840312156200074b578081fd5b5051919050565b9283526020830191909152604082015260600190565b60208082526026908201527f696e76616c696420706f77657220746f6b656e20636f6e74726f6c6c6572206160408201526564647265737360d01b606082015260800190565b60208082526014908201527f696e76616c69642061756374696f6e2074696d65000000000000000000000000604082015260600190565b6020808252601d908201527f696e76616c6964206865646765207072696365207468726573686f6c64000000604082015260600190565b6020808252601c908201527f696e76616c69642068656467652074696d65207468726573686f6c6400000000604082015260600190565b60208082526016908201527f696e76616c6964206f7261636c65206164647265737300000000000000000000604082015260600190565b60208082526024908201527f696e76616c69642061756374696f6e206d696e207072696365206d756c7469706040820152633634b2b960e11b606082015260800190565b60208082526024908201527f61756374696f6e206d6178207072696365206d756c7469706c69657220746f6f604082015263206c6f7760e01b606082015260800190565b60208082526017908201527f696e76616c696420666163746f72792061646472657373000000000000000000604082015260600190565b60208082526025908201527f61756374696f6e206d696e207072696365206d756c7469706c69657220746f6f604082015264040d0d2ced60db1b606082015260800190565b60208082526014908201527f696e76616c696420776574682061646472657373000000000000000000000000604082015260600190565b6020808252601c908201527f696e76616c6964204554483a5753717565657468206164647265737300000000604082015260600190565b60805160601c60a05160601c60c05160e05160601c6101005160601c6101205160601c6101405160601c6101605160601c610180516101a0516101c0516101e05161020051615ad962000c18600039806118fe5280612ffd528061304b52806130825250806110ed528061301e52806130a352806130c9525080610ab55280612f7c5280612fb0525080611c7f5280612b6152508061150a528061198d52806124e8525080611754525080611424525080610b8e528061170c5280611796528061200d5280612a045280612dc652806131d65280614006525080610bbb5280610cce5280610f16528061144852806117c5528061203a5280612a335280612bf05280612ce75280612de7528061320352806134c8528061374952806139f35280613c4f5280614035525080611b565280611e1352806149a05250806111dc52806115345280611a58528061293052806143775280614662525080610bdd5280610c8c5280610ef5528061173052806117e6528061205c5280612a545280612bae5280612cc65280612e085280613225528061349b52806135ee52806139c65280613a87528061405652806142be52806146fe5250806103695280610bff5280610cad5280610ed452806114005280611807528061207e5280612a755280612bcf5280612ca55280612e295280613247528061339752806136935280613719528061388a5280613b995280613c1f52806140775250615ad96000f3fe6080604052600436106103595760003560e01c806370a08231116101bb578063a457c2d7116100f7578063d22dbc5911610095578063f101d92f1161006f578063f101d92f146108d0578063f2fde38b146108e5578063f73e19c314610905578063fa461e3314610925576103cb565b8063d22dbc5914610886578063dd62ed3e1461089b578063eb54f9ec146108bb576103cb565b8063c2451689116100d1578063c245168914610823578063c45a015514610846578063cae740291461085b578063d0e30db014610870576103cb565b8063a457c2d7146107c3578063a9059cbb146107e3578063b0b9346114610803576103cb565b8063832c857f116101645780638ec4b7211161013e5780638ec4b7211461076457806395d89b41146107795780639c1ab1b81461078e578063a319b29f146107ae576103cb565b8063832c857f1461071a57806386e867721461072f5780638da5cb5b1461074f576103cb565b80637dc0d1d0116101955780637dc0d1d0146106db5780637f07b130146106f057806382564bca14610705576103cb565b806370a08231146106a6578063715018a6146106c65780637ca2518414610564576103cb565b80633950935111610295578063533092ef1161023357806366a91b761161020d57806366a91b761461065457806367b8c345146106695780636c1040a91461067e57806370749b4414610693576103cb565b8063533092ef146106075780635e5cdcd71461062c57806363bbc4b61461063f576103cb565b80633dcb0c5d1161026f5780633dcb0c5d146105a65780633fc8cef3146105c85780634468c022146105dd5780634d76e6fc146105f2576103cb565b80633950935114610544578063395ebb69146105645780633d3a62ee14610586576103cb565b806323b872dd116103025780632a340056116102dc5780632a340056146104e55780632e1a7d4d146104fa578063313ce5671461050d57806333194c0a1461052f576103cb565b806323b872dd1461049257806323ccafd9146104b257806325d7707c146104d2576103cb565b8063155f586d11610333578063155f586d1461044857806318160ddd1461046a5780631a5af3421461047f576103cb565b806306fdde03146103d0578063095ea7b3146103fb5780630ca514cd14610428576103cb565b366103cb57336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103a4575060055461010090046001600160a01b031633145b6103c95760405162461bcd60e51b81526004016103c0906155f7565b60405180910390fd5b005b600080fd5b3480156103dc57600080fd5b506103e5610945565b6040516103f29190615366565b60405180910390f35b34801561040757600080fd5b5061041b610416366004614d79565b6109db565b6040516103f291906152f1565b34801561043457600080fd5b506103c961044336600461506a565b6109f9565b34801561045457600080fd5b5061045d610ab3565b6040516103f291906151aa565b34801561047657600080fd5b5061045d610ad7565b6103c961048d36600461506a565b610add565b34801561049e57600080fd5b5061041b6104ad366004614d39565b610ddd565b3480156104be57600080fd5b506103c96104cd3660046150c0565b610e65565b6103c96104e0366004614dc0565b61101b565b3480156104f157600080fd5b5061045d6110eb565b6103c961050836600461506a565b61110f565b34801561051957600080fd5b506105226111d1565b6040516103f291906158cb565b34801561053b57600080fd5b5061045d6111da565b34801561055057600080fd5b5061041b61055f366004614d79565b6111fe565b34801561057057600080fd5b5061057961124c565b6040516103f291906158ba565b34801561059257600080fd5b506103c96105a136600461506a565b611252565b3480156105b257600080fd5b506105bb6113ea565b6040516103f291906151ce565b3480156105d457600080fd5b506105bb6113fe565b3480156105e957600080fd5b506105bb611422565b3480156105fe57600080fd5b506105bb611446565b34801561061357600080fd5b5061061c61146a565b6040516103f294939291906152cb565b6103c961063a3660046150e1565b611486565b34801561064b57600080fd5b5061045d611502565b34801561066057600080fd5b5061045d611508565b34801561067557600080fd5b5061045d61152c565b34801561068a57600080fd5b5061045d611532565b6103c96106a136600461509a565b611556565b3480156106b257600080fd5b5061045d6106c1366004614ce5565b611620565b3480156106d257600080fd5b506103c961163f565b3480156106e757600080fd5b506105bb61170a565b3480156106fc57600080fd5b506105bb61172e565b34801561071157600080fd5b506105bb611752565b34801561072657600080fd5b5061045d611776565b34801561073b57600080fd5b5061041b61074a36600461506a565b611781565b34801561075b57600080fd5b506105bb6118ed565b34801561077057600080fd5b5061045d6118fc565b34801561078557600080fd5b506103e5611920565b34801561079a57600080fd5b506103c96107a93660046150c0565b611981565b3480156107ba57600080fd5b506103c9611a1d565b3480156107cf57600080fd5b5061041b6107de366004614d79565b611ab4565b3480156107ef57600080fd5b5061041b6107fe366004614d79565b611b1c565b34801561080f57600080fd5b5061041b61081e36600461506a565b611b30565b34801561082f57600080fd5b50610838611b3b565b6040516103f29291906152fc565b34801561085257600080fd5b506105bb611b54565b34801561086757600080fd5b5061045d611b78565b610878611b7e565b6040516103f292919061587e565b34801561089257600080fd5b5061041b611c43565b3480156108a757600080fd5b5061045d6108b6366004614d01565b611c4c565b3480156108c757600080fd5b5061045d611c77565b3480156108dc57600080fd5b5061045d611c7d565b3480156108f157600080fd5b506103c9610900366004614ce5565b611ca1565b34801561091157600080fd5b5061045d61092036600461506a565b611dc3565b34801561093157600080fd5b506103c9610940366004614e00565b611dce565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109d15780601f106109a6576101008083540402835291602001916109d1565b820191906000526020600020905b8154815290600101906020018083116109b457829003601f168201915b5050505050905090565b60006109ef6109e8611e74565b8484611e78565b5060015b92915050565b610a01611e74565b6001600160a01b0316610a126118ed565b6001600160a01b031614610a6d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60088054908290556040517f543c6f21ac1fa8a080c6b447bc8f7e6e9e005b757bced81426dedeeb98e3a6b590610aa7908490849061587e565b60405180910390a15050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60025490565b60026006541415610b35576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600080610b45611f64565b91509150610b538382611f7e565b6000610b60848484611fad565b50905082158015610b6f575081155b15610c875760405163cce79bd560e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cce79bd590610c2e907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906101a4906001906004016151e2565b60206040518083038186803b158015610c4657600080fd5b505afa158015610c5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7e9190615082565b42600955600a55505b610d8f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610d2557600080fd5b505afa158015610d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5d9190615047565b84610d688934612177565b60008a604051602001610d7b91906151aa565b6040516020818303038152906040526121cf565b336001600160a01b03167f5d85169ff8329e90f3225f9798e0eba54d00c55d3bbfe201a0d1606febb23a8e8583604051610dca92919061587e565b60405180910390a2505060016006555050565b6000610dea848484612250565b610e5a84610df6611e74565b610e55856040518060600160405280602881526020016159ed602891396001600160a01b038a16600090815260016020526040812090610e34611e74565b6001600160a01b0316815260208101919091526040016000205491906123ab565b611e78565b5060015b9392505050565b60026006541415610ebd576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610ecd83612442565b9050610fce7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610f6d57600080fd5b505afa158015610f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa59190615047565b8486600189604051602001610fba91906151aa565b604051602081830303815290604052612467565b336001600160a01b03167fa13b272c1cf13ba724064d3d4809d9f557aab8da2bb582cba031a2f57e728e9d848360405161100992919061587e565b60405180910390a25050600160065550565b60026006541415611073576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000806110836124de565b91509150816110a45760405162461bcd60e51b81526004016103c0906155c0565b6110af818585612525565b336001600160a01b03167eb3acebad2d25b9626850dd370eadbf46d6a94dd0fab19c061f97e1dd4a9639858584604051610dca9392919061530c565b7f000000000000000000000000000000000000000000000000000000000000000081565b60026006541415611167576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600061117782612442565b905060006111883384846000612655565b905061119433826126a2565b336001600160a01b03167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94848484604051611009939291906158a4565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006109ef61120b611e74565b84610e55856001600061121c611e74565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061278c565b6101a481565b600260065414156112aa576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600681905550600560019054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561130257600080fd5b505af1158015611316573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133a9190614da4565b6113565760405162461bcd60e51b81526004016103c090615546565b600c5460ff166113785760405162461bcd60e51b81526004016103c090615379565b600061138b82611386610ad7565b6127e6565b9050600061139982476127f2565b90506113a533846127fe565b6113af33826126a2565b336001600160a01b03167fe9ab9870b9093d99f8e981919f65ad09b7ae90ff80f1031639af9e0357eb9ed6848360405161100992919061587e565b60055461010090046001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000806114786128fa565b935093509350935090919293565b61148f836129f1565b6114ab5760405162461bcd60e51b81526004016103c09061550f565b6114b6838383612b8c565b336001600160a01b03167ff99cce6ee3154fddfc55959dd136665c7351fe51c0ea58392ca454be8180dcd4428585856040516114f594939291906151b3565b60405180910390a2505050565b600a5481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60095481565b7f000000000000000000000000000000000000000000000000000000000000000090565b600260065414156115ae576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556115bc836129f1565b6115d85760405162461bcd60e51b81526004016103c09061550f565b6115e3838383612525565b336001600160a01b03167fa6806e5672ec1827d23bd4a25f4a41c8d0b055720c40081e3803f6b0a957f7978383866040516110099392919061530c565b6001600160a01b0381166000908152602081905260409020545b919050565b611647611e74565b6001600160a01b03166116586118ed565b6001600160a01b0316146116b3576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6007546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36007805473ffffffffffffffffffffffffffffffffffffffff19169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b66038d7ea4c6800081565b600080600061178e611f64565b9150915060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cce79bd57f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460016040518663ffffffff1660e01b815260040161184b9594939291906151e2565b60206040518083038186803b15801561186357600080fd5b505afa158015611877573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189b9190615082565b905060006118a7612dbe565b905060006118b785858585612efb565b50905060006118c7888584612f77565b905060006118d787878487612efb565b5015159215159290921498975050505050505050565b6007546001600160a01b031690565b7f000000000000000000000000000000000000000000000000000000000000000081565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109d15780601f106109a6576101008083540402835291602001916109d1565b6009546000906119b1907f0000000000000000000000000000000000000000000000000000000000000000613105565b9050804210156119d35760405162461bcd60e51b81526004016103c0906155c0565b6119de818484612b8c565b336001600160a01b03167f6c3a0d23de8295593e3e236062f9103f4a66c6d8de92b9425a2e17ae3baca677428386866040516114f594939291906151b3565b600c8054600160ff19909116179055600554604051634bf7d4a160e11b81526101009091046001600160a01b0316906397efa94290611a80907f0000000000000000000000000000000000000000000000000000000000000000906004016151aa565b600060405180830381600087803b158015611a9a57600080fd5b505af1158015611aae573d6000803e3d6000fd5b50505050565b60006109ef611ac1611e74565b84610e5585604051806060016040528060258152602001615a7f6025913960016000611aeb611e74565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906123ab565b60006109ef611b29611e74565b8484612250565b60006109f3826129f1565b600080600080611b496124de565b909450925050509091565b7f000000000000000000000000000000000000000000000000000000000000000081565b60085481565b60008060026006541415611bd9576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065534600080611bed33848361315d565b91509150336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158383604051611c2c92919061587e565b60405180910390a290935091505060016006559091565b600c5460ff1681565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600b5481565b7f000000000000000000000000000000000000000000000000000000000000000081565b611ca9611e74565b6001600160a01b0316611cba6118ed565b6001600160a01b031614611d15576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611d5a5760405162461bcd60e51b81526004018080602001828103825260268152602001806159456026913960400191505060405180910390fd5b6007546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60006109f382612442565b6000841380611ddd5750600083135b611de657600080fd5b6000611df482840184614ef5565b90506000806000611e0884600001516132f5565b925092509250611e3a7f0000000000000000000000000000000000000000000000000000000000000000848484613326565b506000808913611e4a5787611e4c565b885b9050611e698560200151858585858a606001518b60400151613345565b505050505050505050565b3390565b6001600160a01b038316611ebd5760405162461bcd60e51b8152600401808060200182810382526024815260200180615a5b6024913960400191505060405180910390fd5b6001600160a01b038216611f025760405162461bcd60e51b815260040180806020018281038252602281526020018061596b6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600080600080611f726128fa565b96509450505050509091565b600854611f8b8284613105565b1115611fa95760405162461bcd60e51b81526004016103c09061562e565b5050565b600080600080611fbb612dbe565b905085158015611fc9575084155b1561213257611fd6610ad7565b15611ff35760405162461bcd60e51b81526004016103c09061576b565b60405163cce79bd560e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cce79bd5906120ad907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906101a4906001906004016151e2565b60206040518083038186803b1580156120c557600080fd5b505afa1580156120d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120fd9190615082565b9050600061211382671bc16d674ec80000613ce8565b90506121296121228285613105565b8a90613d21565b9350505061215c565b6121596121496121428884613ce8565b8790613105565b6121538989613ce8565b90613d21565b91505b60006121688383613ce8565b92989297509195505050505050565b808203828111156109f3576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b60006122248530600060405180608001604052808d8c8e6040516020016121f893929190615157565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052613d41565b9050838110156122465760405162461bcd60e51b81526004016103c090615433565b5050505050505050565b6001600160a01b0383166122955760405162461bcd60e51b8152600401808060200182810382526025815260200180615a366025913960400191505060405180910390fd5b6001600160a01b0382166122da5760405162461bcd60e51b81526004018080602001828103825260238152602001806159006023913960400191505060405180910390fd5b6122e5838383612787565b6123228160405180606001604052806026815260200161598d602691396001600160a01b03861660009081526020819052604090205491906123ab565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612351908261278c565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000818484111561243a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156123ff5781810151838201526020016123e7565b50505050905090810190601f16801561242c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008061244d6128fa565b9350505050610e5e61245d610ad7565b6121538386613ce8565b60006124bc8530600060405180608001604052808c8c8f60405160200161249093929190615157565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052613e80565b9050838111156122465760405162461bcd60e51b81526004016103c0906154d8565b60008060006125187f000000000000000000000000000000000000000000000000000000000000000060095461310590919063ffffffff16565b4281111593509150509091565b60008060008061253487613fed565b93509350935093508315158615151461255f5760405162461bcd60e51b81526004016103c0906154a1565b83156125b857848111156125855760405162461bcd60e51b81526004016103c090615665565b813410156125a55760405162461bcd60e51b81526004016103c09061546a565b6125b3333485856000614199565b612603565b34156125d65760405162461bcd60e51b81526004016103c0906156b2565b848110156125f65760405162461bcd60e51b81526004016103c09061571e565b6126033384846000614233565b336001600160a01b03167f878fd3ca52ad322c7535f559ee7c91afc67363073783360ef1b1420589dc61748787848787604051612644959493929190615341565b60405180910390a250505050505050565b600080612660611f64565b915050600061267186611386610ad7565b9050600061267f82846127f2565b905061268d888783886142a2565b61269788886127fe565b979650505050505050565b804710156126f7576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114612742576040519150601f19603f3d011682016040523d82523d6000602084013e612747565b606091505b50509050806127875760405162461bcd60e51b815260040180806020018281038252603a8152602001806159b3603a913960400191505060405180910390fd5b505050565b600082820183811015610e5e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610e5e8383613d21565b6000610e5e8284613ce8565b6001600160a01b0382166128435760405162461bcd60e51b8152600401808060200182810382526021815260200180615a156021913960400191505060405180910390fd5b61284f82600083612787565b61288c81604051806060016040528060228152602001615923602291396001600160a01b03851660009081526020819052604090205491906123ab565b6001600160a01b0383166000908152602081905260409020556002546128b290826143d1565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600554604051634632752560e11b8152600091829182918291829161010090046001600160a01b031690638c64ea4a90612958907f0000000000000000000000000000000000000000000000000000000000000000906004016151aa565b60806040518083038186803b15801561297057600080fd5b505afa158015612984573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a89190614fb3565b805160208201516040830151606090930151919863ffffffff90911697506bffffffffffffffffffffffff90921695506fffffffffffffffffffffffffffffffff169350915050565b6000806129fe4284612177565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634ac78d117f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a48701876040518663ffffffff1660e01b8152600401612aba95949392919061521b565b60206040518083038186803b158015612ad257600080fd5b505afa158015612ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0a9190615082565b90506000612b23600a5483613d2190919063ffffffff16565b90506000670de0b6b3a76400008211612b4d57612b48670de0b6b3a764000083612177565b612b5f565b612b5f82670de0b6b3a7640000612177565b7f000000000000000000000000000000000000000000000000000000000000000011159695505050505050565b600080600080612b9b87613fed565b93509350935093508315612ca057612c9b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015612c4757600080fd5b505afa158015612c5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7f9190615047565b858760025b89898e8e604051602001610fba94939291906151b3565b612d7f565b612d7f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015612d3e57600080fd5b505afa158015612d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d769190615047565b86866003612c84565b336001600160a01b03167f4c1a959210172325f5c6678421c3834b04ae8ce57f7a7c0c0bbfbb62bca37e34858386866040516126449493929190615324565b600080612e527f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a4600061442e565b90506000600560019054906101000a90046001600160a01b03166001600160a01b031663978bbdb96040518163ffffffff1660e01b815260040160206040518083038186803b158015612ea457600080fd5b505afa158015612eb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612edc9190615082565b9050612ef4612710612eee84846144d4565b90614540565b9250505090565b60008080612f1b85612f1589671bc16d674ec80000613ce8565b90613ce8565b9050600080612f2c8389898961459f565b90925090506000612f4189612153858b613ce8565b905066038d7ea4c680008111612f695760405162461bcd60e51b81526004016103c0906157ee565b509890975095505050505050565b6000807f0000000000000000000000000000000000000000000000000000000000000000612fa54287612177565b1015612fde57612fd97f00000000000000000000000000000000000000000000000000000000000000006121534288612177565b612fe8565b670de0b6b3a76400005b905060008315613077576130706130496130427f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612177565b8490613ce8565b7f000000000000000000000000000000000000000000000000000000000000000090612177565b90506130f1565b6130ee6130c76130427f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612177565b7f000000000000000000000000000000000000000000000000000000000000000090613105565b90505b6130fb8582613ce8565b9695505050505050565b808201828110156109f3576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b60008060008061316b611f64565b915091506131798682611f7e565b600080613187888585611fad565b909250905060006131a961319b8a84612177565b856131a4610ad7565b6145e5565b9050841580156131b7575083155b156132cf5760405163cce79bd560e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cce79bd590613276907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906101a4906001906004016151e2565b60206040518083038186803b15801561328e57600080fd5b505afa1580156132a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132c69190615082565b42600955600a55505b6132db8a848b8b614634565b6132e58a8261478e565b9199919850909650505050505050565b600080806133038482614798565b9250613310846014614864565b905061331d846017614798565b91509193909250565b600061333c85613337868686614920565b614976565b95945050505050565b60008160ff16600381111561335657fe5b600381111561336157fe5b14156135a75760008280602001905181019061337d9190614e7b565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906133d49030906004016151ce565b60206040518083038186803b1580156133ec57600080fd5b505afa158015613400573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134249190615082565b6040518263ffffffff1660e01b815260040161344091906151aa565b600060405180830381600087803b15801561345a57600080fd5b505af115801561346e573d6000803e3d6000fd5b50505050613482888260000151600161315d565b505060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906134f2907f00000000000000000000000000000000000000000000000000000000000000009088906004016152b2565b602060405180830381600087803b15801561350c57600080fd5b505af1158015613520573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135449190614da4565b50876001600160a01b03167fc355ebece16d7e85e486911f0cde1074bc4bd3fec251c88cdddc7076d3e99adb854760405161358092919061587e565b60405180910390a247156135a1576135a16001600160a01b038916476126a2565b50613cdf565b60018160ff1660038111156135b857fe5b60038111156135c357fe5b1415613838576000828060200190518101906135df9190614e7b565b9050600061368f8983600001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161363891906151ce565b60206040518083038186803b15801561365057600080fd5b505afa158015613664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136889190615082565b6001612655565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b1580156136ec57600080fd5b505af1158015613700573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925061377391507f00000000000000000000000000000000000000000000000000000000000000009089906004016152b2565b602060405180830381600087803b15801561378d57600080fd5b505af11580156137a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c59190614da4565b5060006137d28287612177565b9050896001600160a01b03167f6f3269a64126ef2a1959892f3d921e81865181e09a7f72f55d3a49550c53b48d878360405161380f92919061587e565b60405180910390a28015613830576138306001600160a01b038b16826126a2565b505050613cdf565b60028160ff16600381111561384957fe5b600381111561385457fe5b1415613b10576000828060200190518101906138709190614e96565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906138c79030906004016151ce565b60206040518083038186803b1580156138df57600080fd5b505afa1580156138f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139179190615082565b6040518263ffffffff1660e01b815260040161393391906151aa565b600060405180830381600087803b15801561394d57600080fd5b505af1158015613961573d6000803e3d6000fd5b505050506020810151815161397a918a91816001614199565b80516000906139899086612177565b905081604001518110156139af5760405162461bcd60e51b81526004016103c0906156e9565b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613a1d907f00000000000000000000000000000000000000000000000000000000000000009089906004016152b2565b602060405180830381600087803b158015613a3757600080fd5b505af1158015613a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a6f9190614da4565b5060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613abe908c9085906004016152b2565b602060405180830381600087803b158015613ad857600080fd5b505af1158015613aec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138309190614da4565b60038160ff166003811115613b2157fe5b6003811115613b2c57fe5b1415613cdf57600082806020019051810190613b489190614e96565b9050613b5f88826000015183602001516001614233565b6020810151600090613b719086612177565b90508160600151811015613b975760405162461bcd60e51b81526004016103c090615589565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b158015613bf257600080fd5b505af1158015613c06573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250613c7991507f00000000000000000000000000000000000000000000000000000000000000009089906004016152b2565b602060405180830381600087803b158015613c9357600080fd5b505af1158015613ca7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ccb9190614da4565b50611e696001600160a01b038a16826126a2565b50505050505050565b6000670de0b6b3a7640000613d12613d0085856144d4565b6002670de0b6b3a76400005b04613105565b81613d1957fe5b049392505050565b600081613d12613d3985670de0b6b3a76400006144d4565b600285613d0c565b600080600080613d5485600001516132f5565b919450925090506001600160a01b0380831690841610600080613d78868686614999565b6001600160a01b031663128acb088b85613d918f6149d7565b6001600160a01b038e1615613da6578d613dcc565b87613dc55773fffd8963efd1fc6a506488495d951d5263988d25613dcc565b6401000276a45b8d604051602001613ddd9190615825565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401613e0c959493929190615278565b6040805180830381600087803b158015613e2557600080fd5b505af1158015613e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e5d9190614ddd565b9150915082613e6c5781613e6e565b805b6000039b9a5050505050505050505050565b600080600080613e9385600001516132f5565b919450925090506001600160a01b0380841690831610600080613eb7858786614999565b6001600160a01b031663128acb088b85613ed08f6149d7565b6000036001600160a01b038e1615613ee8578d613f0e565b87613f075773fffd8963efd1fc6a506488495d951d5263988d25613f0e565b6401000276a45b8d604051602001613f1f9190615825565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401613f4e959493929190615278565b6040805180830381600087803b158015613f6757600080fd5b505af1158015613f7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f9f9190614ddd565b9150915060008084613fb5578284600003613fbb565b83836000035b915091508a6001600160a01b031660001415613fdd578c8114613fdd57600080fd5b509b9a5050505050505050505050565b600080600080600080613ffe611f64565b9150915060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cce79bd57f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460016040518663ffffffff1660e01b81526004016140bb9594939291906151e2565b60206040518083038186803b1580156140d357600080fd5b505afa1580156140e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410b9190615082565b90506000614117612dbe565b9050600061412785858585612efb565b50905060006141378b8584612f77565b905060008061414888888588612efb565b915091508115158415151461416f5760405162461bcd60e51b81526004016103c0906153d6565b600061417b8285613ce8565b42600955600a9790975550929c929b50939950975095505050505050565b80156141b1576141ac8584846001614634565b6141e7565b6141be8584846000614634565b60006141ca8584612177565b905080156141e5576141e56001600160a01b038716826126a2565b505b846001600160a01b03167f2af3664d72ebbec5e92c3a487f09a4ecd9ef50177eced03cc2b05892b5e0c9158484846040516142249392919061588c565b60405180910390a25050505050565b61423f848484846142a2565b80614257576142576001600160a01b038516836126a2565b836001600160a01b03167fc7472bd0a757f40f801e047dd4f4ec901314e95afcbfed844e62af18401e0e6b8484846040516142949392919061588c565b60405180910390a250505050565b8061434b576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906142f790879030908890600401615254565b602060405180830381600087803b15801561431157600080fd5b505af1158015614325573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143499190614da4565b505b600554604051638632cb0360e01b81526101009091046001600160a01b031690638632cb03906143a3907f000000000000000000000000000000000000000000000000000000000000000090879087906004016158a4565b600060405180830381600087803b1580156143bd57600080fd5b505af1158015612246573d6000803e3d6000fd5b600082821115614428576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b15801561449d57600080fd5b505afa1580156144b1573d6000803e3d6000fd5b505050506040513d60208110156144c757600080fd5b5051979650505050505050565b60008115806144ef575050808202828282816144ec57fe5b04145b6109f3576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000808211614596576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613d1957fe5b6000808486116145c7576145c06145b68585613105565b6121538789612177565b60016145d8565b6145d5846121538888612177565b60005b9150915094509492505050565b6000806145fc6145f58587613105565b8690613d21565b9050821561462b57614623614619670de0b6b3a764000083612177565b6121538584613ce8565b915050610e5e565b50929392505050565b600554604051630728cf2360e31b81526101009091046001600160a01b031690633946791890849061468f907f00000000000000000000000000000000000000000000000000000000000000009088906000906004016158a4565b6020604051808303818588803b1580156146a857600080fd5b505af11580156146bc573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906146e19190615082565b5080611aae5760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb9061473590879087906004016152b2565b602060405180830381600087803b15801561474f57600080fd5b505af1158015614763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147879190614da4565b5050505050565b611fa982826149ed565b6000818260140110156147f2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b816014018351101561484b576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b6000818260030110156148be576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b8160030183511015614917576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b614928614bd9565b826001600160a01b0316846001600160a01b03161115614946579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b60006149828383614add565b9050336001600160a01b038216146109f357600080fd5b60006149cf7f00000000000000000000000000000000000000000000000000000000000000006149ca868686614920565b614add565b949350505050565b6000600160ff1b82106149e957600080fd5b5090565b6001600160a01b038216614a48576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b614a5460008383612787565b600254614a61908261278c565b6002556001600160a01b038216600090815260208190526040902054614a87908261278c565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600081602001516001600160a01b031682600001516001600160a01b031610614b0557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561163a816158d9565b600082601f830112614c14578081fd5b813567ffffffffffffffff80821115614c2957fe5b604051601f8301601f191681016020018281118282101715614c4757fe5b604052828152848301602001861015614c5e578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215614c8a578081fd5b6040516020810181811067ffffffffffffffff82111715614ca757fe5b6040529151825250919050565b80516fffffffffffffffffffffffffffffffff8116811461163a57600080fd5b803560ff8116811461163a57600080fd5b600060208284031215614cf6578081fd5b8135610e5e816158d9565b60008060408385031215614d13578081fd5b8235614d1e816158d9565b91506020830135614d2e816158d9565b809150509250929050565b600080600060608486031215614d4d578081fd5b8335614d58816158d9565b92506020840135614d68816158d9565b929592945050506040919091013590565b60008060408385031215614d8b578182fd5b8235614d96816158d9565b946020939093013593505050565b600060208284031215614db5578081fd5b8151610e5e816158f1565b60008060408385031215614dd2578081fd5b8235614d96816158f1565b60008060408385031215614def578182fd5b505080516020909101519092909150565b60008060008060608587031215614e15578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614e3a578384fd5b818701915087601f830112614e4d578384fd5b813581811115614e5b578485fd5b886020828501011115614e6c578485fd5b95989497505060200194505050565b600060208284031215614e8c578081fd5b610e5e8383614c79565b600060808284031215614ea7578081fd5b6040516080810181811067ffffffffffffffff82111715614ec457fe5b8060405250825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b600060208284031215614f06578081fd5b813567ffffffffffffffff80821115614f1d578283fd5b9083019060808286031215614f30578283fd5b604051608081018181108382111715614f4557fe5b604052823582811115614f56578485fd5b614f6287828601614c04565b825250614f7160208401614bf9565b6020820152614f8260408401614cd4565b6040820152606083013582811115614f98578485fd5b614fa487828601614c04565b60608301525095945050505050565b600060808284031215614fc4578081fd5b6040516080810181811067ffffffffffffffff82111715614fe157fe5b6040528251614fef816158d9565b8152602083015163ffffffff81168114615007578283fd5b602082015260408301516bffffffffffffffffffffffff8116811461502a578283fd5b604082015261503b60608401614cb4565b60608201529392505050565b600060208284031215615058578081fd5b815162ffffff81168114610e5e578182fd5b60006020828403121561507b578081fd5b5035919050565b600060208284031215615093578081fd5b5051919050565b6000806000606084860312156150ae578081fd5b833592506020840135614d68816158f1565b600080604083850312156150d2578182fd5b50508035926020909101359150565b6000806000606084860312156150f5578081fd5b505081359360208301359350604090920135919050565b60008151808452815b8181101561513157602081850181015186830182015201615115565b818111156151425782602083870101525b50601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b90815260200190565b93845260208401929092526040830152606082015260800190565b6001600160a01b0391909116815260200190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9283166060830152909116608082015260a00190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a0608083015261269760a083018461510c565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b901515815260200190565b9115158252602082015260400190565b92151583526020830191909152604082015260600190565b931515845260208401929092526040830152606082015260800190565b9415158552602085019390935260408401919091526060830152608082015260a00190565b600060208252610e5e602083018461510c565b60208082526028908201527f537472617465677920686173206e6f742072656465656d6564207661756c742060408201527f70726f6365656473000000000000000000000000000000000000000000000000606082015260800190565b60208082526035908201527f63616e206e6f7420657865637574652068656467696e6720747261646520617360408201527f2061756374696f6e2074797065206368616e6765640000000000000000000000606082015260800190565b60208082526018908201527f616d6f756e74206f7574206c657373207468616e206d696e0000000000000000604082015260600190565b60208082526017908201527f4c6f772045544820616d6f756e74207265636569766564000000000000000000604082015260600190565b60208082526012908201527f77726f6e672061756374696f6e20747970650000000000000000000000000000604082015260600190565b6020808252601a908201527f616d6f756e7420696e2067726561746572207468616e206d6178000000000000604082015260600190565b60208082526019908201527f50726963652068656467696e67206e6f7420616c6c6f77656400000000000000604082015260600190565b60208082526023908201527f5371756565746820636f6e74726163747320617265206e6f742073687574206460408201526237bbb760e91b606082015260800190565b6020808252601b908201527f70726f666974206973206c657373207468616e206d696e204554480000000000604082015260600190565b6020808252601b908201527f54696d652068656467696e67206973206e6f7420616c6c6f7765640000000000604082015260600190565b60208082526012908201527f43616e6e6f742072656365697665206574680000000000000000000000000000604082015260600190565b6020808252601c908201527f4465706f73697420657863656564732073747261746567792063617000000000604082015260600190565b6020808252602d908201527f41756374696f6e2070726963652067726561746572207468616e206d6178206160408201526c6363657074656420707269636560981b606082015260800190565b6020808252601c908201527f45544820617474616368656420666f72206275792061756374696f6e00000000604082015260600190565b6020808252818101527f70726f666974206973206c657373207468616e206d696e207753717565657468604082015260600190565b6020808252602d908201527f41756374696f6e2070726963652067726561746572207468616e206d696e206160408201526c6363657074656420707269636560981b606082015260800190565b60208082526050908201527f43726162207374726174656779207368757420646f776e2064756520746f206660408201527f756c6c206c69717569646174696f6e206f722073687574646f776e206f66207360608201527f71756565746820636f6e74726163747300000000000000000000000000000000608082015260a00190565b60208082526019908201527f73747261746567792069732064656c7461206e65757472616c00000000000000604082015260600190565b60006020825282516080602084015261584160a084018261510c565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f1984830301608085015261333c828261510c565b918252602082015260400190565b92835260208301919091521515604082015260600190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b6001600160a01b03811681146158ee57600080fd5b50565b80151581146158ee57600080fdfe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220b1972285e63bdfb8208cc087c392f5dbbdca1910676c7d3fcc55b9136d1b0e8b64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x6080604052600436106103595760003560e01c806370a08231116101bb578063a457c2d7116100f7578063d22dbc5911610095578063f101d92f1161006f578063f101d92f146108d0578063f2fde38b146108e5578063f73e19c314610905578063fa461e3314610925576103cb565b8063d22dbc5914610886578063dd62ed3e1461089b578063eb54f9ec146108bb576103cb565b8063c2451689116100d1578063c245168914610823578063c45a015514610846578063cae740291461085b578063d0e30db014610870576103cb565b8063a457c2d7146107c3578063a9059cbb146107e3578063b0b9346114610803576103cb565b8063832c857f116101645780638ec4b7211161013e5780638ec4b7211461076457806395d89b41146107795780639c1ab1b81461078e578063a319b29f146107ae576103cb565b8063832c857f1461071a57806386e867721461072f5780638da5cb5b1461074f576103cb565b80637dc0d1d0116101955780637dc0d1d0146106db5780637f07b130146106f057806382564bca14610705576103cb565b806370a08231146106a6578063715018a6146106c65780637ca2518414610564576103cb565b80633950935111610295578063533092ef1161023357806366a91b761161020d57806366a91b761461065457806367b8c345146106695780636c1040a91461067e57806370749b4414610693576103cb565b8063533092ef146106075780635e5cdcd71461062c57806363bbc4b61461063f576103cb565b80633dcb0c5d1161026f5780633dcb0c5d146105a65780633fc8cef3146105c85780634468c022146105dd5780634d76e6fc146105f2576103cb565b80633950935114610544578063395ebb69146105645780633d3a62ee14610586576103cb565b806323b872dd116103025780632a340056116102dc5780632a340056146104e55780632e1a7d4d146104fa578063313ce5671461050d57806333194c0a1461052f576103cb565b806323b872dd1461049257806323ccafd9146104b257806325d7707c146104d2576103cb565b8063155f586d11610333578063155f586d1461044857806318160ddd1461046a5780631a5af3421461047f576103cb565b806306fdde03146103d0578063095ea7b3146103fb5780630ca514cd14610428576103cb565b366103cb57336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103a4575060055461010090046001600160a01b031633145b6103c95760405162461bcd60e51b81526004016103c0906155f7565b60405180910390fd5b005b600080fd5b3480156103dc57600080fd5b506103e5610945565b6040516103f29190615366565b60405180910390f35b34801561040757600080fd5b5061041b610416366004614d79565b6109db565b6040516103f291906152f1565b34801561043457600080fd5b506103c961044336600461506a565b6109f9565b34801561045457600080fd5b5061045d610ab3565b6040516103f291906151aa565b34801561047657600080fd5b5061045d610ad7565b6103c961048d36600461506a565b610add565b34801561049e57600080fd5b5061041b6104ad366004614d39565b610ddd565b3480156104be57600080fd5b506103c96104cd3660046150c0565b610e65565b6103c96104e0366004614dc0565b61101b565b3480156104f157600080fd5b5061045d6110eb565b6103c961050836600461506a565b61110f565b34801561051957600080fd5b506105226111d1565b6040516103f291906158cb565b34801561053b57600080fd5b5061045d6111da565b34801561055057600080fd5b5061041b61055f366004614d79565b6111fe565b34801561057057600080fd5b5061057961124c565b6040516103f291906158ba565b34801561059257600080fd5b506103c96105a136600461506a565b611252565b3480156105b257600080fd5b506105bb6113ea565b6040516103f291906151ce565b3480156105d457600080fd5b506105bb6113fe565b3480156105e957600080fd5b506105bb611422565b3480156105fe57600080fd5b506105bb611446565b34801561061357600080fd5b5061061c61146a565b6040516103f294939291906152cb565b6103c961063a3660046150e1565b611486565b34801561064b57600080fd5b5061045d611502565b34801561066057600080fd5b5061045d611508565b34801561067557600080fd5b5061045d61152c565b34801561068a57600080fd5b5061045d611532565b6103c96106a136600461509a565b611556565b3480156106b257600080fd5b5061045d6106c1366004614ce5565b611620565b3480156106d257600080fd5b506103c961163f565b3480156106e757600080fd5b506105bb61170a565b3480156106fc57600080fd5b506105bb61172e565b34801561071157600080fd5b506105bb611752565b34801561072657600080fd5b5061045d611776565b34801561073b57600080fd5b5061041b61074a36600461506a565b611781565b34801561075b57600080fd5b506105bb6118ed565b34801561077057600080fd5b5061045d6118fc565b34801561078557600080fd5b506103e5611920565b34801561079a57600080fd5b506103c96107a93660046150c0565b611981565b3480156107ba57600080fd5b506103c9611a1d565b3480156107cf57600080fd5b5061041b6107de366004614d79565b611ab4565b3480156107ef57600080fd5b5061041b6107fe366004614d79565b611b1c565b34801561080f57600080fd5b5061041b61081e36600461506a565b611b30565b34801561082f57600080fd5b50610838611b3b565b6040516103f29291906152fc565b34801561085257600080fd5b506105bb611b54565b34801561086757600080fd5b5061045d611b78565b610878611b7e565b6040516103f292919061587e565b34801561089257600080fd5b5061041b611c43565b3480156108a757600080fd5b5061045d6108b6366004614d01565b611c4c565b3480156108c757600080fd5b5061045d611c77565b3480156108dc57600080fd5b5061045d611c7d565b3480156108f157600080fd5b506103c9610900366004614ce5565b611ca1565b34801561091157600080fd5b5061045d61092036600461506a565b611dc3565b34801561093157600080fd5b506103c9610940366004614e00565b611dce565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109d15780601f106109a6576101008083540402835291602001916109d1565b820191906000526020600020905b8154815290600101906020018083116109b457829003601f168201915b5050505050905090565b60006109ef6109e8611e74565b8484611e78565b5060015b92915050565b610a01611e74565b6001600160a01b0316610a126118ed565b6001600160a01b031614610a6d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60088054908290556040517f543c6f21ac1fa8a080c6b447bc8f7e6e9e005b757bced81426dedeeb98e3a6b590610aa7908490849061587e565b60405180910390a15050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60025490565b60026006541415610b35576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600080610b45611f64565b91509150610b538382611f7e565b6000610b60848484611fad565b50905082158015610b6f575081155b15610c875760405163cce79bd560e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cce79bd590610c2e907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906101a4906001906004016151e2565b60206040518083038186803b158015610c4657600080fd5b505afa158015610c5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7e9190615082565b42600955600a55505b610d8f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610d2557600080fd5b505afa158015610d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5d9190615047565b84610d688934612177565b60008a604051602001610d7b91906151aa565b6040516020818303038152906040526121cf565b336001600160a01b03167f5d85169ff8329e90f3225f9798e0eba54d00c55d3bbfe201a0d1606febb23a8e8583604051610dca92919061587e565b60405180910390a2505060016006555050565b6000610dea848484612250565b610e5a84610df6611e74565b610e55856040518060600160405280602881526020016159ed602891396001600160a01b038a16600090815260016020526040812090610e34611e74565b6001600160a01b0316815260208101919091526040016000205491906123ab565b611e78565b5060015b9392505050565b60026006541415610ebd576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610ecd83612442565b9050610fce7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610f6d57600080fd5b505afa158015610f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa59190615047565b8486600189604051602001610fba91906151aa565b604051602081830303815290604052612467565b336001600160a01b03167fa13b272c1cf13ba724064d3d4809d9f557aab8da2bb582cba031a2f57e728e9d848360405161100992919061587e565b60405180910390a25050600160065550565b60026006541415611073576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000806110836124de565b91509150816110a45760405162461bcd60e51b81526004016103c0906155c0565b6110af818585612525565b336001600160a01b03167eb3acebad2d25b9626850dd370eadbf46d6a94dd0fab19c061f97e1dd4a9639858584604051610dca9392919061530c565b7f000000000000000000000000000000000000000000000000000000000000000081565b60026006541415611167576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600061117782612442565b905060006111883384846000612655565b905061119433826126a2565b336001600160a01b03167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94848484604051611009939291906158a4565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006109ef61120b611e74565b84610e55856001600061121c611e74565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061278c565b6101a481565b600260065414156112aa576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600681905550600560019054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561130257600080fd5b505af1158015611316573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133a9190614da4565b6113565760405162461bcd60e51b81526004016103c090615546565b600c5460ff166113785760405162461bcd60e51b81526004016103c090615379565b600061138b82611386610ad7565b6127e6565b9050600061139982476127f2565b90506113a533846127fe565b6113af33826126a2565b336001600160a01b03167fe9ab9870b9093d99f8e981919f65ad09b7ae90ff80f1031639af9e0357eb9ed6848360405161100992919061587e565b60055461010090046001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000806114786128fa565b935093509350935090919293565b61148f836129f1565b6114ab5760405162461bcd60e51b81526004016103c09061550f565b6114b6838383612b8c565b336001600160a01b03167ff99cce6ee3154fddfc55959dd136665c7351fe51c0ea58392ca454be8180dcd4428585856040516114f594939291906151b3565b60405180910390a2505050565b600a5481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60095481565b7f000000000000000000000000000000000000000000000000000000000000000090565b600260065414156115ae576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556115bc836129f1565b6115d85760405162461bcd60e51b81526004016103c09061550f565b6115e3838383612525565b336001600160a01b03167fa6806e5672ec1827d23bd4a25f4a41c8d0b055720c40081e3803f6b0a957f7978383866040516110099392919061530c565b6001600160a01b0381166000908152602081905260409020545b919050565b611647611e74565b6001600160a01b03166116586118ed565b6001600160a01b0316146116b3576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6007546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36007805473ffffffffffffffffffffffffffffffffffffffff19169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b66038d7ea4c6800081565b600080600061178e611f64565b9150915060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cce79bd57f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460016040518663ffffffff1660e01b815260040161184b9594939291906151e2565b60206040518083038186803b15801561186357600080fd5b505afa158015611877573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189b9190615082565b905060006118a7612dbe565b905060006118b785858585612efb565b50905060006118c7888584612f77565b905060006118d787878487612efb565b5015159215159290921498975050505050505050565b6007546001600160a01b031690565b7f000000000000000000000000000000000000000000000000000000000000000081565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109d15780601f106109a6576101008083540402835291602001916109d1565b6009546000906119b1907f0000000000000000000000000000000000000000000000000000000000000000613105565b9050804210156119d35760405162461bcd60e51b81526004016103c0906155c0565b6119de818484612b8c565b336001600160a01b03167f6c3a0d23de8295593e3e236062f9103f4a66c6d8de92b9425a2e17ae3baca677428386866040516114f594939291906151b3565b600c8054600160ff19909116179055600554604051634bf7d4a160e11b81526101009091046001600160a01b0316906397efa94290611a80907f0000000000000000000000000000000000000000000000000000000000000000906004016151aa565b600060405180830381600087803b158015611a9a57600080fd5b505af1158015611aae573d6000803e3d6000fd5b50505050565b60006109ef611ac1611e74565b84610e5585604051806060016040528060258152602001615a7f6025913960016000611aeb611e74565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906123ab565b60006109ef611b29611e74565b8484612250565b60006109f3826129f1565b600080600080611b496124de565b909450925050509091565b7f000000000000000000000000000000000000000000000000000000000000000081565b60085481565b60008060026006541415611bd9576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065534600080611bed33848361315d565b91509150336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158383604051611c2c92919061587e565b60405180910390a290935091505060016006559091565b600c5460ff1681565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600b5481565b7f000000000000000000000000000000000000000000000000000000000000000081565b611ca9611e74565b6001600160a01b0316611cba6118ed565b6001600160a01b031614611d15576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611d5a5760405162461bcd60e51b81526004018080602001828103825260268152602001806159456026913960400191505060405180910390fd5b6007546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60006109f382612442565b6000841380611ddd5750600083135b611de657600080fd5b6000611df482840184614ef5565b90506000806000611e0884600001516132f5565b925092509250611e3a7f0000000000000000000000000000000000000000000000000000000000000000848484613326565b506000808913611e4a5787611e4c565b885b9050611e698560200151858585858a606001518b60400151613345565b505050505050505050565b3390565b6001600160a01b038316611ebd5760405162461bcd60e51b8152600401808060200182810382526024815260200180615a5b6024913960400191505060405180910390fd5b6001600160a01b038216611f025760405162461bcd60e51b815260040180806020018281038252602281526020018061596b6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600080600080611f726128fa565b96509450505050509091565b600854611f8b8284613105565b1115611fa95760405162461bcd60e51b81526004016103c09061562e565b5050565b600080600080611fbb612dbe565b905085158015611fc9575084155b1561213257611fd6610ad7565b15611ff35760405162461bcd60e51b81526004016103c09061576b565b60405163cce79bd560e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cce79bd5906120ad907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906101a4906001906004016151e2565b60206040518083038186803b1580156120c557600080fd5b505afa1580156120d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120fd9190615082565b9050600061211382671bc16d674ec80000613ce8565b90506121296121228285613105565b8a90613d21565b9350505061215c565b6121596121496121428884613ce8565b8790613105565b6121538989613ce8565b90613d21565b91505b60006121688383613ce8565b92989297509195505050505050565b808203828111156109f3576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b60006122248530600060405180608001604052808d8c8e6040516020016121f893929190615157565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052613d41565b9050838110156122465760405162461bcd60e51b81526004016103c090615433565b5050505050505050565b6001600160a01b0383166122955760405162461bcd60e51b8152600401808060200182810382526025815260200180615a366025913960400191505060405180910390fd5b6001600160a01b0382166122da5760405162461bcd60e51b81526004018080602001828103825260238152602001806159006023913960400191505060405180910390fd5b6122e5838383612787565b6123228160405180606001604052806026815260200161598d602691396001600160a01b03861660009081526020819052604090205491906123ab565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612351908261278c565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000818484111561243a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156123ff5781810151838201526020016123e7565b50505050905090810190601f16801561242c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008061244d6128fa565b9350505050610e5e61245d610ad7565b6121538386613ce8565b60006124bc8530600060405180608001604052808c8c8f60405160200161249093929190615157565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052613e80565b9050838111156122465760405162461bcd60e51b81526004016103c0906154d8565b60008060006125187f000000000000000000000000000000000000000000000000000000000000000060095461310590919063ffffffff16565b4281111593509150509091565b60008060008061253487613fed565b93509350935093508315158615151461255f5760405162461bcd60e51b81526004016103c0906154a1565b83156125b857848111156125855760405162461bcd60e51b81526004016103c090615665565b813410156125a55760405162461bcd60e51b81526004016103c09061546a565b6125b3333485856000614199565b612603565b34156125d65760405162461bcd60e51b81526004016103c0906156b2565b848110156125f65760405162461bcd60e51b81526004016103c09061571e565b6126033384846000614233565b336001600160a01b03167f878fd3ca52ad322c7535f559ee7c91afc67363073783360ef1b1420589dc61748787848787604051612644959493929190615341565b60405180910390a250505050505050565b600080612660611f64565b915050600061267186611386610ad7565b9050600061267f82846127f2565b905061268d888783886142a2565b61269788886127fe565b979650505050505050565b804710156126f7576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114612742576040519150601f19603f3d011682016040523d82523d6000602084013e612747565b606091505b50509050806127875760405162461bcd60e51b815260040180806020018281038252603a8152602001806159b3603a913960400191505060405180910390fd5b505050565b600082820183811015610e5e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610e5e8383613d21565b6000610e5e8284613ce8565b6001600160a01b0382166128435760405162461bcd60e51b8152600401808060200182810382526021815260200180615a156021913960400191505060405180910390fd5b61284f82600083612787565b61288c81604051806060016040528060228152602001615923602291396001600160a01b03851660009081526020819052604090205491906123ab565b6001600160a01b0383166000908152602081905260409020556002546128b290826143d1565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600554604051634632752560e11b8152600091829182918291829161010090046001600160a01b031690638c64ea4a90612958907f0000000000000000000000000000000000000000000000000000000000000000906004016151aa565b60806040518083038186803b15801561297057600080fd5b505afa158015612984573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a89190614fb3565b805160208201516040830151606090930151919863ffffffff90911697506bffffffffffffffffffffffff90921695506fffffffffffffffffffffffffffffffff169350915050565b6000806129fe4284612177565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634ac78d117f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a48701876040518663ffffffff1660e01b8152600401612aba95949392919061521b565b60206040518083038186803b158015612ad257600080fd5b505afa158015612ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0a9190615082565b90506000612b23600a5483613d2190919063ffffffff16565b90506000670de0b6b3a76400008211612b4d57612b48670de0b6b3a764000083612177565b612b5f565b612b5f82670de0b6b3a7640000612177565b7f000000000000000000000000000000000000000000000000000000000000000011159695505050505050565b600080600080612b9b87613fed565b93509350935093508315612ca057612c9b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015612c4757600080fd5b505afa158015612c5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7f9190615047565b858760025b89898e8e604051602001610fba94939291906151b3565b612d7f565b612d7f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015612d3e57600080fd5b505afa158015612d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d769190615047565b86866003612c84565b336001600160a01b03167f4c1a959210172325f5c6678421c3834b04ae8ce57f7a7c0c0bbfbb62bca37e34858386866040516126449493929190615324565b600080612e527f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a4600061442e565b90506000600560019054906101000a90046001600160a01b03166001600160a01b031663978bbdb96040518163ffffffff1660e01b815260040160206040518083038186803b158015612ea457600080fd5b505afa158015612eb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612edc9190615082565b9050612ef4612710612eee84846144d4565b90614540565b9250505090565b60008080612f1b85612f1589671bc16d674ec80000613ce8565b90613ce8565b9050600080612f2c8389898961459f565b90925090506000612f4189612153858b613ce8565b905066038d7ea4c680008111612f695760405162461bcd60e51b81526004016103c0906157ee565b509890975095505050505050565b6000807f0000000000000000000000000000000000000000000000000000000000000000612fa54287612177565b1015612fde57612fd97f00000000000000000000000000000000000000000000000000000000000000006121534288612177565b612fe8565b670de0b6b3a76400005b905060008315613077576130706130496130427f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612177565b8490613ce8565b7f000000000000000000000000000000000000000000000000000000000000000090612177565b90506130f1565b6130ee6130c76130427f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612177565b7f000000000000000000000000000000000000000000000000000000000000000090613105565b90505b6130fb8582613ce8565b9695505050505050565b808201828110156109f3576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b60008060008061316b611f64565b915091506131798682611f7e565b600080613187888585611fad565b909250905060006131a961319b8a84612177565b856131a4610ad7565b6145e5565b9050841580156131b7575083155b156132cf5760405163cce79bd560e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cce79bd590613276907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906101a4906001906004016151e2565b60206040518083038186803b15801561328e57600080fd5b505afa1580156132a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132c69190615082565b42600955600a55505b6132db8a848b8b614634565b6132e58a8261478e565b9199919850909650505050505050565b600080806133038482614798565b9250613310846014614864565b905061331d846017614798565b91509193909250565b600061333c85613337868686614920565b614976565b95945050505050565b60008160ff16600381111561335657fe5b600381111561336157fe5b14156135a75760008280602001905181019061337d9190614e7b565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906133d49030906004016151ce565b60206040518083038186803b1580156133ec57600080fd5b505afa158015613400573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134249190615082565b6040518263ffffffff1660e01b815260040161344091906151aa565b600060405180830381600087803b15801561345a57600080fd5b505af115801561346e573d6000803e3d6000fd5b50505050613482888260000151600161315d565b505060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906134f2907f00000000000000000000000000000000000000000000000000000000000000009088906004016152b2565b602060405180830381600087803b15801561350c57600080fd5b505af1158015613520573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135449190614da4565b50876001600160a01b03167fc355ebece16d7e85e486911f0cde1074bc4bd3fec251c88cdddc7076d3e99adb854760405161358092919061587e565b60405180910390a247156135a1576135a16001600160a01b038916476126a2565b50613cdf565b60018160ff1660038111156135b857fe5b60038111156135c357fe5b1415613838576000828060200190518101906135df9190614e7b565b9050600061368f8983600001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161363891906151ce565b60206040518083038186803b15801561365057600080fd5b505afa158015613664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136889190615082565b6001612655565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b1580156136ec57600080fd5b505af1158015613700573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925061377391507f00000000000000000000000000000000000000000000000000000000000000009089906004016152b2565b602060405180830381600087803b15801561378d57600080fd5b505af11580156137a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c59190614da4565b5060006137d28287612177565b9050896001600160a01b03167f6f3269a64126ef2a1959892f3d921e81865181e09a7f72f55d3a49550c53b48d878360405161380f92919061587e565b60405180910390a28015613830576138306001600160a01b038b16826126a2565b505050613cdf565b60028160ff16600381111561384957fe5b600381111561385457fe5b1415613b10576000828060200190518101906138709190614e96565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906138c79030906004016151ce565b60206040518083038186803b1580156138df57600080fd5b505afa1580156138f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139179190615082565b6040518263ffffffff1660e01b815260040161393391906151aa565b600060405180830381600087803b15801561394d57600080fd5b505af1158015613961573d6000803e3d6000fd5b505050506020810151815161397a918a91816001614199565b80516000906139899086612177565b905081604001518110156139af5760405162461bcd60e51b81526004016103c0906156e9565b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613a1d907f00000000000000000000000000000000000000000000000000000000000000009089906004016152b2565b602060405180830381600087803b158015613a3757600080fd5b505af1158015613a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a6f9190614da4565b5060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613abe908c9085906004016152b2565b602060405180830381600087803b158015613ad857600080fd5b505af1158015613aec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138309190614da4565b60038160ff166003811115613b2157fe5b6003811115613b2c57fe5b1415613cdf57600082806020019051810190613b489190614e96565b9050613b5f88826000015183602001516001614233565b6020810151600090613b719086612177565b90508160600151811015613b975760405162461bcd60e51b81526004016103c090615589565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b158015613bf257600080fd5b505af1158015613c06573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250613c7991507f00000000000000000000000000000000000000000000000000000000000000009089906004016152b2565b602060405180830381600087803b158015613c9357600080fd5b505af1158015613ca7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ccb9190614da4565b50611e696001600160a01b038a16826126a2565b50505050505050565b6000670de0b6b3a7640000613d12613d0085856144d4565b6002670de0b6b3a76400005b04613105565b81613d1957fe5b049392505050565b600081613d12613d3985670de0b6b3a76400006144d4565b600285613d0c565b600080600080613d5485600001516132f5565b919450925090506001600160a01b0380831690841610600080613d78868686614999565b6001600160a01b031663128acb088b85613d918f6149d7565b6001600160a01b038e1615613da6578d613dcc565b87613dc55773fffd8963efd1fc6a506488495d951d5263988d25613dcc565b6401000276a45b8d604051602001613ddd9190615825565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401613e0c959493929190615278565b6040805180830381600087803b158015613e2557600080fd5b505af1158015613e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e5d9190614ddd565b9150915082613e6c5781613e6e565b805b6000039b9a5050505050505050505050565b600080600080613e9385600001516132f5565b919450925090506001600160a01b0380841690831610600080613eb7858786614999565b6001600160a01b031663128acb088b85613ed08f6149d7565b6000036001600160a01b038e1615613ee8578d613f0e565b87613f075773fffd8963efd1fc6a506488495d951d5263988d25613f0e565b6401000276a45b8d604051602001613f1f9190615825565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401613f4e959493929190615278565b6040805180830381600087803b158015613f6757600080fd5b505af1158015613f7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f9f9190614ddd565b9150915060008084613fb5578284600003613fbb565b83836000035b915091508a6001600160a01b031660001415613fdd578c8114613fdd57600080fd5b509b9a5050505050505050505050565b600080600080600080613ffe611f64565b9150915060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cce79bd57f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a460016040518663ffffffff1660e01b81526004016140bb9594939291906151e2565b60206040518083038186803b1580156140d357600080fd5b505afa1580156140e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410b9190615082565b90506000614117612dbe565b9050600061412785858585612efb565b50905060006141378b8584612f77565b905060008061414888888588612efb565b915091508115158415151461416f5760405162461bcd60e51b81526004016103c0906153d6565b600061417b8285613ce8565b42600955600a9790975550929c929b50939950975095505050505050565b80156141b1576141ac8584846001614634565b6141e7565b6141be8584846000614634565b60006141ca8584612177565b905080156141e5576141e56001600160a01b038716826126a2565b505b846001600160a01b03167f2af3664d72ebbec5e92c3a487f09a4ecd9ef50177eced03cc2b05892b5e0c9158484846040516142249392919061588c565b60405180910390a25050505050565b61423f848484846142a2565b80614257576142576001600160a01b038516836126a2565b836001600160a01b03167fc7472bd0a757f40f801e047dd4f4ec901314e95afcbfed844e62af18401e0e6b8484846040516142949392919061588c565b60405180910390a250505050565b8061434b576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906142f790879030908890600401615254565b602060405180830381600087803b15801561431157600080fd5b505af1158015614325573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143499190614da4565b505b600554604051638632cb0360e01b81526101009091046001600160a01b031690638632cb03906143a3907f000000000000000000000000000000000000000000000000000000000000000090879087906004016158a4565b600060405180830381600087803b1580156143bd57600080fd5b505af1158015612246573d6000803e3d6000fd5b600082821115614428576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b15801561449d57600080fd5b505afa1580156144b1573d6000803e3d6000fd5b505050506040513d60208110156144c757600080fd5b5051979650505050505050565b60008115806144ef575050808202828282816144ec57fe5b04145b6109f3576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000808211614596576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613d1957fe5b6000808486116145c7576145c06145b68585613105565b6121538789612177565b60016145d8565b6145d5846121538888612177565b60005b9150915094509492505050565b6000806145fc6145f58587613105565b8690613d21565b9050821561462b57614623614619670de0b6b3a764000083612177565b6121538584613ce8565b915050610e5e565b50929392505050565b600554604051630728cf2360e31b81526101009091046001600160a01b031690633946791890849061468f907f00000000000000000000000000000000000000000000000000000000000000009088906000906004016158a4565b6020604051808303818588803b1580156146a857600080fd5b505af11580156146bc573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906146e19190615082565b5080611aae5760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb9061473590879087906004016152b2565b602060405180830381600087803b15801561474f57600080fd5b505af1158015614763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147879190614da4565b5050505050565b611fa982826149ed565b6000818260140110156147f2576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b816014018351101561484b576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b6000818260030110156148be576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b8160030183511015614917576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b614928614bd9565b826001600160a01b0316846001600160a01b03161115614946579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b60006149828383614add565b9050336001600160a01b038216146109f357600080fd5b60006149cf7f00000000000000000000000000000000000000000000000000000000000000006149ca868686614920565b614add565b949350505050565b6000600160ff1b82106149e957600080fd5b5090565b6001600160a01b038216614a48576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b614a5460008383612787565b600254614a61908261278c565b6002556001600160a01b038216600090815260208190526040902054614a87908261278c565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600081602001516001600160a01b031682600001516001600160a01b031610614b0557600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561163a816158d9565b600082601f830112614c14578081fd5b813567ffffffffffffffff80821115614c2957fe5b604051601f8301601f191681016020018281118282101715614c4757fe5b604052828152848301602001861015614c5e578384fd5b82602086016020830137918201602001929092529392505050565b600060208284031215614c8a578081fd5b6040516020810181811067ffffffffffffffff82111715614ca757fe5b6040529151825250919050565b80516fffffffffffffffffffffffffffffffff8116811461163a57600080fd5b803560ff8116811461163a57600080fd5b600060208284031215614cf6578081fd5b8135610e5e816158d9565b60008060408385031215614d13578081fd5b8235614d1e816158d9565b91506020830135614d2e816158d9565b809150509250929050565b600080600060608486031215614d4d578081fd5b8335614d58816158d9565b92506020840135614d68816158d9565b929592945050506040919091013590565b60008060408385031215614d8b578182fd5b8235614d96816158d9565b946020939093013593505050565b600060208284031215614db5578081fd5b8151610e5e816158f1565b60008060408385031215614dd2578081fd5b8235614d96816158f1565b60008060408385031215614def578182fd5b505080516020909101519092909150565b60008060008060608587031215614e15578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614e3a578384fd5b818701915087601f830112614e4d578384fd5b813581811115614e5b578485fd5b886020828501011115614e6c578485fd5b95989497505060200194505050565b600060208284031215614e8c578081fd5b610e5e8383614c79565b600060808284031215614ea7578081fd5b6040516080810181811067ffffffffffffffff82111715614ec457fe5b8060405250825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b600060208284031215614f06578081fd5b813567ffffffffffffffff80821115614f1d578283fd5b9083019060808286031215614f30578283fd5b604051608081018181108382111715614f4557fe5b604052823582811115614f56578485fd5b614f6287828601614c04565b825250614f7160208401614bf9565b6020820152614f8260408401614cd4565b6040820152606083013582811115614f98578485fd5b614fa487828601614c04565b60608301525095945050505050565b600060808284031215614fc4578081fd5b6040516080810181811067ffffffffffffffff82111715614fe157fe5b6040528251614fef816158d9565b8152602083015163ffffffff81168114615007578283fd5b602082015260408301516bffffffffffffffffffffffff8116811461502a578283fd5b604082015261503b60608401614cb4565b60608201529392505050565b600060208284031215615058578081fd5b815162ffffff81168114610e5e578182fd5b60006020828403121561507b578081fd5b5035919050565b600060208284031215615093578081fd5b5051919050565b6000806000606084860312156150ae578081fd5b833592506020840135614d68816158f1565b600080604083850312156150d2578182fd5b50508035926020909101359150565b6000806000606084860312156150f5578081fd5b505081359360208301359350604090920135919050565b60008151808452815b8181101561513157602081850181015186830182015201615115565b818111156151425782602083870101525b50601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b90815260200190565b93845260208401929092526040830152606082015260800190565b6001600160a01b0391909116815260200190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9283166060830152909116608082015260a00190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a0608083015261269760a083018461510c565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b901515815260200190565b9115158252602082015260400190565b92151583526020830191909152604082015260600190565b931515845260208401929092526040830152606082015260800190565b9415158552602085019390935260408401919091526060830152608082015260a00190565b600060208252610e5e602083018461510c565b60208082526028908201527f537472617465677920686173206e6f742072656465656d6564207661756c742060408201527f70726f6365656473000000000000000000000000000000000000000000000000606082015260800190565b60208082526035908201527f63616e206e6f7420657865637574652068656467696e6720747261646520617360408201527f2061756374696f6e2074797065206368616e6765640000000000000000000000606082015260800190565b60208082526018908201527f616d6f756e74206f7574206c657373207468616e206d696e0000000000000000604082015260600190565b60208082526017908201527f4c6f772045544820616d6f756e74207265636569766564000000000000000000604082015260600190565b60208082526012908201527f77726f6e672061756374696f6e20747970650000000000000000000000000000604082015260600190565b6020808252601a908201527f616d6f756e7420696e2067726561746572207468616e206d6178000000000000604082015260600190565b60208082526019908201527f50726963652068656467696e67206e6f7420616c6c6f77656400000000000000604082015260600190565b60208082526023908201527f5371756565746820636f6e74726163747320617265206e6f742073687574206460408201526237bbb760e91b606082015260800190565b6020808252601b908201527f70726f666974206973206c657373207468616e206d696e204554480000000000604082015260600190565b6020808252601b908201527f54696d652068656467696e67206973206e6f7420616c6c6f7765640000000000604082015260600190565b60208082526012908201527f43616e6e6f742072656365697665206574680000000000000000000000000000604082015260600190565b6020808252601c908201527f4465706f73697420657863656564732073747261746567792063617000000000604082015260600190565b6020808252602d908201527f41756374696f6e2070726963652067726561746572207468616e206d6178206160408201526c6363657074656420707269636560981b606082015260800190565b6020808252601c908201527f45544820617474616368656420666f72206275792061756374696f6e00000000604082015260600190565b6020808252818101527f70726f666974206973206c657373207468616e206d696e207753717565657468604082015260600190565b6020808252602d908201527f41756374696f6e2070726963652067726561746572207468616e206d696e206160408201526c6363657074656420707269636560981b606082015260800190565b60208082526050908201527f43726162207374726174656779207368757420646f776e2064756520746f206660408201527f756c6c206c69717569646174696f6e206f722073687574646f776e206f66207360608201527f71756565746820636f6e74726163747300000000000000000000000000000000608082015260a00190565b60208082526019908201527f73747261746567792069732064656c7461206e65757472616c00000000000000604082015260600190565b60006020825282516080602084015261584160a084018261510c565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f1984830301608085015261333c828261510c565b918252602082015260400190565b92835260208301919091521515604082015260600190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b6001600160a01b03811681146158ee57600080fd5b50565b80151581146158ee57600080fdfe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220b1972285e63bdfb8208cc087c392f5dbbdca1910676c7d3fcc55b9136d1b0e8b64736f6c63430007060033\",\n  \"devdoc\": {\n    \"author\": \"Opyn team\",\n    \"details\": \"CrabStrategy contract\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"allowance(address,address)\": {\n        \"details\": \"See {IERC20-allowance}.\"\n      },\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC20-balanceOf}.\"\n      },\n      \"checkPriceHedge(uint256)\": {\n        \"params\": {\n          \"_auctionTriggerTime\": \"alleged timestamp where auction was triggered\"\n        },\n        \"returns\": {\n          \"_0\": \"true if hedging is allowed\"\n        }\n      },\n      \"checkTimeHedge()\": {\n        \"returns\": {\n          \"_0\": \"isTimeHedgeAllowed true if hedging is allowed\",\n          \"_1\": \"auctionTriggertime auction trigger timestamp\"\n        }\n      },\n      \"constructor\": {\n        \"details\": \"this will open a vault in the power token contract and store the vault ID\",\n        \"params\": {\n          \"_auctionTime\": \"auction duration (seconds)\",\n          \"_ethWSqueethPool\": \"eth:wSqueeth uniswap pool address\",\n          \"_hedgePriceThreshold\": \"hedge price threshold (0.1*1e18 = 10%)\",\n          \"_hedgeTimeThreshold\": \"hedge time threshold (seconds)\",\n          \"_maxPriceMultiplier\": \"maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\",\n          \"_minPriceMultiplier\": \"minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\",\n          \"_oracle\": \"oracle address\",\n          \"_uniswapFactory\": \"uniswap factory address\",\n          \"_wSqueethController\": \"power token controller address\",\n          \"_weth\": \"weth address\"\n        }\n      },\n      \"decimals()\": {\n        \"details\": \"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"\n      },\n      \"decreaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"\n      },\n      \"deposit()\": {\n        \"details\": \"provide ETH, return wSqueeth and strategy token\",\n        \"returns\": {\n          \"_0\": \"wSqueethToMint minted amount of wSqueeth\",\n          \"_1\": \"depositorCrabAmount minted amount of strategy token\"\n        }\n      },\n      \"flashDeposit(uint256)\": {\n        \"details\": \"this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth_ethToDeposit must be less than msg.value plus the proceeds from the flash swapthe difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\",\n        \"params\": {\n          \"_ethToDeposit\": \"total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\"\n        }\n      },\n      \"flashWithdraw(uint256,uint256)\": {\n        \"details\": \"this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\",\n        \"params\": {\n          \"_crabAmount\": \"strategy token amount to burn\",\n          \"_maxEthToPay\": \"maximum ETH to pay to buy back the owed wSqueeth debt\"\n        }\n      },\n      \"getStrategyVaultId()\": {\n        \"returns\": {\n          \"_0\": \"vault ID\"\n        }\n      },\n      \"getVaultDetails()\": {\n        \"returns\": {\n          \"_0\": \"operator\",\n          \"_1\": \"nft collateral id\",\n          \"_2\": \"collateral amount\",\n          \"_3\": \"short amount\"\n        }\n      },\n      \"getWsqueethFromCrabAmount(uint256)\": {\n        \"details\": \"_crabAmount strategy token amount\",\n        \"returns\": {\n          \"_0\": \"wSqueeth amount\"\n        }\n      },\n      \"increaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"name()\": {\n        \"details\": \"Returns the name of the token.\"\n      },\n      \"owner()\": {\n        \"details\": \"Returns the address of the current owner.\"\n      },\n      \"priceHedge(uint256,bool,uint256)\": {\n        \"details\": \"need to attach msg.value if buying WSqueeth\",\n        \"params\": {\n          \"_auctionTriggerTime\": \"timestamp where auction started\"\n        }\n      },\n      \"redeemShortShutdown()\": {\n        \"details\": \"needs to be called 1 time before users can exit the strategy using withdrawShutdown\"\n      },\n      \"renounceOwnership()\": {\n        \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n      },\n      \"setStrategyCap(uint256)\": {\n        \"details\": \"deposits are rejected if it would put the strategy above the cap amountstrategy collateral can be above the cap amount due to hedging activities\",\n        \"params\": {\n          \"_capAmount\": \"the maximum strategy collateral in ETH, checked on deposits\"\n        }\n      },\n      \"symbol()\": {\n        \"details\": \"Returns the symbol of the token, usually a shorter version of the name.\"\n      },\n      \"timeHedge(bool,uint256)\": {\n        \"details\": \"need to attach msg.value if buying WSqueeth\",\n        \"params\": {\n          \"_isStrategySellingWSqueeth\": \"sell or buy auction, true for sell auction\",\n          \"_limitPrice\": \"hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\"\n        }\n      },\n      \"timeHedgeOnUniswap(uint256,uint256)\": {\n        \"params\": {\n          \"_minEth\": \"minimum ETH amount of profit if hedge auction is buying WSqueeth\",\n          \"_minWSqueeth\": \"minimum WSqueeth amount of profit if hedge auction is selling WSqueeth\"\n        }\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC20-totalSupply}.\"\n      },\n      \"transfer(address,uint256)\": {\n        \"details\": \"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"\n      },\n      \"transferOwnership(address)\": {\n        \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"params\": {\n          \"_data\": \"callback data encoded as SwapCallbackData struct\",\n          \"amount0Delta\": \"amount of token0\",\n          \"amount1Delta\": \"amount of token1\"\n        }\n      },\n      \"withdraw(uint256)\": {\n        \"details\": \"provide strategy tokens and wSqueeth, returns eth\",\n        \"params\": {\n          \"_crabAmount\": \"amount of strategy token to burn\"\n        }\n      },\n      \"withdrawShutdown(uint256)\": {\n        \"params\": {\n          \"_crabAmount\": \"amount of strategy token to burn\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"auctionTime\": {\n        \"details\": \"hedge auction duration (seconds)\"\n      },\n      \"ethWSqueethPool\": {\n        \"details\": \"ETH:WSqueeth uniswap pool\"\n      },\n      \"hasRedeemedInShutdown\": {\n        \"details\": \"set to true when redeemShortShutdown has been called\"\n      },\n      \"hedgePriceThreshold\": {\n        \"details\": \"price movement to trigger a hedge (0.1*1e18 = 10%)\"\n      },\n      \"hedgeTimeThreshold\": {\n        \"details\": \"time difference to trigger a hedge (seconds)\"\n      },\n      \"maxPriceMultiplier\": {\n        \"details\": \"start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\"\n      },\n      \"minPriceMultiplier\": {\n        \"details\": \"start auction price multiplier for hedge buy auction and reserve price for end sell auction (scaled 1e18)\"\n      },\n      \"oracle\": {\n        \"details\": \"strategy uniswap oracle\"\n      },\n      \"priceAtLastHedge\": {\n        \"details\": \"WSqueeth/Eth price when last hedge executed\"\n      },\n      \"timeAtLastHedge\": {\n        \"details\": \"timestamp when last hedge executed\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"checkPriceHedge(uint256)\": {\n        \"notice\": \"check if hedging based on price threshold is allowed\"\n      },\n      \"checkTimeHedge()\": {\n        \"notice\": \"check if hedging based on time threshold is allowed\"\n      },\n      \"constructor\": {\n        \"notice\": \"strategy constructor\"\n      },\n      \"deposit()\": {\n        \"notice\": \"deposit ETH into strategy\"\n      },\n      \"flashDeposit(uint256)\": {\n        \"notice\": \"flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\"\n      },\n      \"flashWithdraw(uint256,uint256)\": {\n        \"notice\": \"flash deposit into strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\"\n      },\n      \"getStrategyVaultId()\": {\n        \"notice\": \"get power token strategy vault ID \"\n      },\n      \"getVaultDetails()\": {\n        \"notice\": \"get the vault composition of the strategy \"\n      },\n      \"getWsqueethFromCrabAmount(uint256)\": {\n        \"notice\": \"get wSqueeth debt amount associated with strategy token amount\"\n      },\n      \"priceHedge(uint256,bool,uint256)\": {\n        \"notice\": \"strategy hedging based on price threshold\"\n      },\n      \"priceHedgeOnUniswap(uint256,uint256,uint256)\": {\n        \"notice\": \"hedge startegy based on price threshold with uniswap arbing\"\n      },\n      \"redeemShortShutdown()\": {\n        \"notice\": \"called to redeem the net value of a vault post shutdown\"\n      },\n      \"setStrategyCap(uint256)\": {\n        \"notice\": \"owner can set the strategy cap in ETH collateral terms\"\n      },\n      \"timeHedge(bool,uint256)\": {\n        \"notice\": \"strategy hedging based on time threshold\"\n      },\n      \"timeHedgeOnUniswap(uint256,uint256)\": {\n        \"notice\": \"hedge startegy based on time threshold with uniswap arbing\"\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"notice\": \"uniswap swap callback function for flashes\"\n      },\n      \"withdraw(uint256)\": {\n        \"notice\": \"withdraw WETH from strategy\"\n      },\n      \"withdrawShutdown(uint256)\": {\n        \"notice\": \"called to exit a vault if the Squeeth Power Perp contracts are shutdown\"\n      }\n    },\n    \"notice\": \"Contract for Crab strategy\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 616,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_balances\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 622,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_allowances\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n      },\n      {\n        \"astId\": 624,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_totalSupply\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 626,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 628,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 630,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_decimals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint8\"\n      },\n      {\n        \"astId\": 18018,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"powerTokenController\",\n        \"offset\": 1,\n        \"slot\": \"5\",\n        \"type\": \"t_contract(IController)10843\"\n      },\n      {\n        \"astId\": 3698,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"_owner\",\n        \"offset\": 0,\n        \"slot\": \"7\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 15704,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"strategyCap\",\n        \"offset\": 0,\n        \"slot\": \"8\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 15737,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"timeAtLastHedge\",\n        \"offset\": 0,\n        \"slot\": \"9\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 15740,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"priceAtLastHedge\",\n        \"offset\": 0,\n        \"slot\": \"10\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 15742,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"auctionStartTime\",\n        \"offset\": 0,\n        \"slot\": \"11\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 15745,\n        \"contract\": \"contracts/strategy/CrabStrategy.sol:CrabStrategy\",\n        \"label\": \"hasRedeemedInShutdown\",\n        \"offset\": 0,\n        \"slot\": \"12\",\n        \"type\": \"t_bool\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_contract(IController)10843\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"contract IController\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => uint256))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_uint256)\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint8\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint8\",\n        \"numberOfBytes\": \"1\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/CrabStrategyV2.json",
    "content": "{\n  \"address\": \"0xdD1e9c25115e0d6e531d9F9E6ab7dbbEd15158Ce\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wSqueethController\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_oracle\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_weth\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_uniswapFactory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_ethWSqueethPool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_timelock\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_crabMigration\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"lpAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Deposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"depositedAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"tradedAmountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDeposit\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"depositor\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashDepositCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"flashswapDebt\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"excess\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"FlashWithdrawCallback\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"bidId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"quantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"clearingPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"HedgeOTC\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"trader\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"bidId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"quantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"price\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"isBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"clearingPrice\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"HedgeOTCSingle\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"previousOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnershipTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newHedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetHedgePriceThreshold\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newHedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetHedgeTimeThreshold\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint32\",\n          \"name\": \"newHedgingTwapPeriod\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"SetHedgingTwapPeriod\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"otcPriceTolerance\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetOTCPriceTolerance\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"newCapAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"SetStrategyCap\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newStrategy\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"vaultId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"VaultTransferred\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"wSqueethAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Withdraw\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"withdrawer\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"ethWithdrawn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"WithdrawShutdown\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"DOMAIN_SEPARATOR\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"MAX_OTC_PRICE_TOLERANCE\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"POWER_PERP_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"checkPriceHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"checkTimeHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"crabMigration\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"subtractedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"decreaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"deposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"ethWSqueethPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_ethToDeposit\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashDeposit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_maxEthToPay\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"_poolFee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"flashWithdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getStrategyVaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"getVaultDetails\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getWsqueethFromCrabAmount\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_totalQuantity\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_clearingPrice\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_isHedgeBuying\",\n          \"type\": \"bool\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"bidId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"trader\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"quantity\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"price\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"bool\",\n              \"name\": \"isBuying\",\n              \"type\": \"bool\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"expiry\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"nonce\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint8\",\n              \"name\": \"v\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"bytes32\",\n              \"name\": \"r\",\n              \"type\": \"bytes32\"\n            },\n            {\n              \"internalType\": \"bytes32\",\n              \"name\": \"s\",\n              \"type\": \"bytes32\"\n            }\n          ],\n          \"internalType\": \"struct CrabStrategyV2.Order[]\",\n          \"name\": \"_orders\",\n          \"type\": \"tuple[]\"\n        }\n      ],\n      \"name\": \"hedgeOTC\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgePriceThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgeTimeThreshold\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"hedgingTwapPeriod\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"addedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"increaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wSqueethToMint\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabSharesToMint\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_timeAtLastHedge\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_priceAtLastHedge\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_strategyCap\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"initialize\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"isInitialized\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"nonces\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"oracle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"otcPriceTolerance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"powerTokenController\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IController\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"priceAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"redeemShortShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"renounceOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgePriceThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setHedgePriceThreshold\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_hedgeTimeThreshold\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setHedgeTimeThreshold\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_hedgingTwapPeriod\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"setHedgingTwapPeriod\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_nonce\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setNonceTrue\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_otcPriceTolerance\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setOTCPriceTolerance\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_capAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setStrategyCap\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"strategyCap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"timeAtLastHedge\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"timelock\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferOwnership\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_newStrategy\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"transferVault\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"vaultId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdraw\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_crabAmount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"withdrawShutdown\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0xd7fa4444a4e3b33c6551e0ab88476372de0252cd364906028664e0f3c36c7258\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0xdD1e9c25115e0d6e531d9F9E6ab7dbbEd15158Ce\",\n    \"transactionIndex\": 3,\n    \"gasUsed\": \"5451384\",\n    \"logsBloom\": \"0x00004000000008000000000000000000000000000000000000800000000000000000000000000000000000000080000000080000000000000000000100000001000000001008000000000008000000002001000000010000000000000400004000000000020240000000000000000800000000000000000020000010000000400000000000100000000000000000000000000000000000000100000000000000000000000000000000000000800000004000000000800000000000000000000000000002000000020000000000200000040000000000000000000000000020000000040001000000000800000000000000000080000000000000000000000000\",\n    \"blockHash\": \"0xba53e2be562c13af6f4315617b5997d6a46b699535b3c78e06ce75ca3684afeb\",\n    \"transactionHash\": \"0xd7fa4444a4e3b33c6551e0ab88476372de0252cd364906028664e0f3c36c7258\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 3,\n        \"blockNumber\": 12581446,\n        \"transactionHash\": \"0xd7fa4444a4e3b33c6551e0ab88476372de0252cd364906028664e0f3c36c7258\",\n        \"address\": \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n        \"topics\": [\n          \"0x339e53729b0447795ff69e70a74fed98fc7fef6fe94b7521099b32f0f8de4822\"\n        ],\n        \"data\": \"0x00000000000000000000000000000000000000000000000004b264d340f24b8000000000000000000000000000000000000000000000000004b022b07a850ff30000000000000000000000000000000000000000000000000000000062ce0d4c0000000000000000000000000000000000000000000000000000000062ce2e4c\",\n        \"logIndex\": 10,\n        \"blockHash\": \"0xba53e2be562c13af6f4315617b5997d6a46b699535b3c78e06ce75ca3684afeb\"\n      },\n      {\n        \"transactionIndex\": 3,\n        \"blockNumber\": 12581446,\n        \"transactionHash\": \"0xd7fa4444a4e3b33c6551e0ab88476372de0252cd364906028664e0f3c36c7258\",\n        \"address\": \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n        \"topics\": [\n          \"0x3137fc9cd2e33c34f86e29c24d81f3c75b0bce639d3c4ed0d31eeff1160a7ff5\"\n        ],\n        \"data\": \"0x00000000000000000000000049721ed2d693f3653bc1216b8e330fa53cfc80ed00000000000000000000000000000000000000000000000000000000000002d10000000000000000000000000000000000000000000000000000000000000000\",\n        \"logIndex\": 11,\n        \"blockHash\": \"0xba53e2be562c13af6f4315617b5997d6a46b699535b3c78e06ce75ca3684afeb\"\n      },\n      {\n        \"transactionIndex\": 3,\n        \"blockNumber\": 12581446,\n        \"transactionHash\": \"0xd7fa4444a4e3b33c6551e0ab88476372de0252cd364906028664e0f3c36c7258\",\n        \"address\": \"0x49721ED2d693F3653BC1216b8E330fA53CFC80eD\",\n        \"topics\": [\n          \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x000000000000000000000000dd1e9c25115e0d6e531d9f9e6ab7dbbed15158ce\",\n          \"0x00000000000000000000000000000000000000000000000000000000000002d1\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 12,\n        \"blockHash\": \"0xba53e2be562c13af6f4315617b5997d6a46b699535b3c78e06ce75ca3684afeb\"\n      },\n      {\n        \"transactionIndex\": 3,\n        \"blockNumber\": 12581446,\n        \"transactionHash\": \"0xd7fa4444a4e3b33c6551e0ab88476372de0252cd364906028664e0f3c36c7258\",\n        \"address\": \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n        \"topics\": [\n          \"0x25ff1e0131762176a9084e92880f880f39d6d0e62134607f37e631efe1bad871\"\n        ],\n        \"data\": \"0x000000000000000000000000dd1e9c25115e0d6e531d9f9e6ab7dbbed15158ce00000000000000000000000000000000000000000000000000000000000002d1\",\n        \"logIndex\": 13,\n        \"blockHash\": \"0xba53e2be562c13af6f4315617b5997d6a46b699535b3c78e06ce75ca3684afeb\"\n      },\n      {\n        \"transactionIndex\": 3,\n        \"blockNumber\": 12581446,\n        \"transactionHash\": \"0xd7fa4444a4e3b33c6551e0ab88476372de0252cd364906028664e0f3c36c7258\",\n        \"address\": \"0xdD1e9c25115e0d6e531d9F9E6ab7dbbEd15158Ce\",\n        \"topics\": [\n          \"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000005599b4eaddd319e2f462b27fc8378b0bfad309ca\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 14,\n        \"blockHash\": \"0xba53e2be562c13af6f4315617b5997d6a46b699535b3c78e06ce75ca3684afeb\"\n      }\n    ],\n    \"blockNumber\": 12581446,\n    \"cumulativeGasUsed\": \"5782448\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n    \"0xBD9F4bE886653177D22fA9c79FD0DFc41407fC89\",\n    \"0xc778417e063141139fce010982780140aa0cd5ab\",\n    \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n    \"0x921c384F79de1BAe96d6f33E3E5b8d0B2B34cb68\",\n    \"0xF15964458bcA1941dE53fBc004BA7842f4783EC6\",\n    \"0xD0fb9d47B5F65d76C6bDf1b9E43a4A2345080B2f\",\n    3600,\n    \"200000000000000000\"\n  ],\n  \"solcInputHash\": \"30afee76cfee2d4cc1c12451e0258499\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wSqueethController\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_oracle\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_weth\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_uniswapFactory\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_ethWSqueethPool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_timelock\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_crabMigration\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"lpAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Deposit\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"depositedAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tradedAmountOut\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDeposit\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"depositor\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"flashswapDebt\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excess\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashDepositCallback\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"flashswapDebt\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"excess\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"FlashWithdrawCallback\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bidId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"quantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"clearingPrice\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"HedgeOTC\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"trader\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bidId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"quantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"price\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"clearingPrice\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"HedgeOTCSingle\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"previousOwner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"OwnershipTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newHedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetHedgePriceThreshold\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newHedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetHedgeTimeThreshold\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"newHedgingTwapPeriod\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"SetHedgingTwapPeriod\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"otcPriceTolerance\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetOTCPriceTolerance\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newCapAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"SetStrategyCap\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newStrategy\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"vaultId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"VaultTransferred\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"wSqueethAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethWithdrawn\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Withdraw\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"withdrawer\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"ethWithdrawn\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"WithdrawShutdown\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"DOMAIN_SEPARATOR\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"MAX_OTC_PRICE_TOLERANCE\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"POWER_PERP_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"checkPriceHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"checkTimeHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"crabMigration\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"subtractedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"decreaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"deposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"ethWSqueethPool\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"factory\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_ethToDeposit\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashDeposit\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_maxEthToPay\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"_poolFee\\\",\\\"type\\\":\\\"uint24\\\"}],\\\"name\\\":\\\"flashWithdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getStrategyVaultId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"getVaultDetails\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"getWsqueethFromCrabAmount\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_totalQuantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_clearingPrice\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_isHedgeBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"bidId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"trader\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"quantity\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"price\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"isBuying\\\",\\\"type\\\":\\\"bool\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"expiry\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"nonce\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"v\\\",\\\"type\\\":\\\"uint8\\\"},{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"r\\\",\\\"type\\\":\\\"bytes32\\\"},{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"s\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"internalType\\\":\\\"struct CrabStrategyV2.Order[]\\\",\\\"name\\\":\\\"_orders\\\",\\\"type\\\":\\\"tuple[]\\\"}],\\\"name\\\":\\\"hedgeOTC\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgePriceThreshold\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgeTimeThreshold\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"hedgingTwapPeriod\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"addedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"increaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wSqueethToMint\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabSharesToMint\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_timeAtLastHedge\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_priceAtLastHedge\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_strategyCap\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"initialize\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"isInitialized\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"nonces\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"oracle\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"otcPriceTolerance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"owner\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"powerTokenController\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IController\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"priceAtLastHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"redeemShortShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"renounceOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgePriceThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setHedgePriceThreshold\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_hedgeTimeThreshold\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setHedgeTimeThreshold\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_hedgingTwapPeriod\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"setHedgingTwapPeriod\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_nonce\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setNonceTrue\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_otcPriceTolerance\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setOTCPriceTolerance\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_capAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setStrategyCap\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"strategyCap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"timeAtLastHedge\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"timelock\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newOwner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferOwnership\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_newStrategy\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"transferVault\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount0Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"int256\\\",\\\"name\\\":\\\"amount1Delta\\\",\\\"type\\\":\\\"int256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"uniswapV3SwapCallback\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"vaultId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdraw\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_crabAmount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"withdrawShutdown\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"author\\\":\\\"Opyn team\\\",\\\"details\\\":\\\"CrabStrategyV2 contract\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"DOMAIN_SEPARATOR()\\\":{\\\"details\\\":\\\"view function to get the domain seperator used in signing\\\"},\\\"allowance(address,address)\\\":{\\\"details\\\":\\\"See {IERC20-allowance}.\\\"},\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC20-balanceOf}.\\\"},\\\"checkPriceHedge()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"true if hedging is allowed\\\"}},\\\"checkTimeHedge()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"true if hedging is allowed\\\"}},\\\"constructor\\\":{\\\"details\\\":\\\"this will open a vault in the power token contract and store the vault ID\\\",\\\"params\\\":{\\\"_crabMigration\\\":\\\"crab migration contract address\\\",\\\"_ethWSqueethPool\\\":\\\"eth:wSqueeth uniswap pool address\\\",\\\"_hedgePriceThreshold\\\":\\\"hedge price threshold (0.1*1e18 = 10%)\\\",\\\"_hedgeTimeThreshold\\\":\\\"hedge time threshold (seconds)\\\",\\\"_oracle\\\":\\\"oracle address\\\",\\\"_timelock\\\":\\\"timelock contract address\\\",\\\"_uniswapFactory\\\":\\\"uniswap factory address\\\",\\\"_wSqueethController\\\":\\\"power token controller address\\\",\\\"_weth\\\":\\\"weth address\\\"}},\\\"decimals()\\\":{\\\"details\\\":\\\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\\\"},\\\"decreaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\\\"},\\\"deposit()\\\":{\\\"details\\\":\\\"provide ETH, return wSqueeth and strategy token\\\"},\\\"flashDeposit(uint256,uint24)\\\":{\\\"details\\\":\\\"this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth_ethToDeposit must be less than msg.value plus the proceeds from the flash swapthe difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\",\\\"params\\\":{\\\"_ethToDeposit\\\":\\\"total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\",\\\"_poolFee\\\":\\\"Uniswap pool fee\\\"}},\\\"flashWithdraw(uint256,uint256,uint24)\\\":{\\\"details\\\":\\\"this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\",\\\"params\\\":{\\\"_crabAmount\\\":\\\"strategy token amount to burn\\\",\\\"_maxEthToPay\\\":\\\"maximum ETH to pay to buy back the wSqueeth debt\\\",\\\"_poolFee\\\":\\\"Uniswap pool fee\\\"}},\\\"getStrategyVaultId()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"vault ID\\\"}},\\\"getVaultDetails()\\\":{\\\"returns\\\":{\\\"_0\\\":\\\"operator\\\",\\\"_1\\\":\\\"nft collateral id\\\",\\\"_2\\\":\\\"collateral amount\\\",\\\"_3\\\":\\\"short amount\\\"}},\\\"getWsqueethFromCrabAmount(uint256)\\\":{\\\"params\\\":{\\\"_crabAmount\\\":\\\"strategy token amount\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"wSqueeth amount\\\"}},\\\"hedgeOTC(uint256,uint256,bool,(uint256,address,uint256,uint256,bool,uint256,uint256,uint8,bytes32,bytes32)[])\\\":{\\\"details\\\":\\\"hedge function to reduce delta using an array of signed orders\\\",\\\"params\\\":{\\\"_clearingPrice\\\":\\\"clearing price in weth\\\",\\\"_isHedgeBuying\\\":\\\"direction of hedge trade\\\",\\\"_orders\\\":\\\"an array of signed order to swap tokens\\\",\\\"_totalQuantity\\\":\\\"quantity the manager wants to trade\\\"}},\\\"increaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\\\"},\\\"initialize(uint256,uint256,uint256,uint256,uint256)\\\":{\\\"params\\\":{\\\"_crabSharesToMint\\\":\\\"crab shares to mint\\\",\\\"_priceAtLastHedge\\\":\\\"price at last hedge for crab V1\\\",\\\"_strategyCap\\\":\\\"strategy cap for crab V2\\\",\\\"_timeAtLastHedge\\\":\\\"time at last hedge for crab V1\\\",\\\"_wSqueethToMint\\\":\\\"amount of wPowerPerp to mint\\\"}},\\\"name()\\\":{\\\"details\\\":\\\"Returns the name of the token.\\\"},\\\"owner()\\\":{\\\"details\\\":\\\"Returns the address of the current owner.\\\"},\\\"redeemShortShutdown()\\\":{\\\"details\\\":\\\"needs to be called before users can exit strategy using withdrawShutdown\\\"},\\\"renounceOwnership()\\\":{\\\"details\\\":\\\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\\\"},\\\"setHedgePriceThreshold(uint256)\\\":{\\\"params\\\":{\\\"_hedgePriceThreshold\\\":\\\"the hedge price threshold, in percent, scaled by 1e18\\\"}},\\\"setHedgeTimeThreshold(uint256)\\\":{\\\"params\\\":{\\\"_hedgeTimeThreshold\\\":\\\"the hedge time threshold, in seconds\\\"}},\\\"setHedgingTwapPeriod(uint32)\\\":{\\\"params\\\":{\\\"_hedgingTwapPeriod\\\":\\\"the twap period, in seconds\\\"}},\\\"setNonceTrue(uint256)\\\":{\\\"params\\\":{\\\"_nonce\\\":\\\"the number to be set true\\\"}},\\\"setOTCPriceTolerance(uint256)\\\":{\\\"params\\\":{\\\"_otcPriceTolerance\\\":\\\"the OTC price tolerance, in percent, scaled by 1e18\\\"}},\\\"setStrategyCap(uint256)\\\":{\\\"details\\\":\\\"deposits are rejected if it would put the strategy above the cap amountstrategy collateral can be above the cap amount due to hedging activities\\\",\\\"params\\\":{\\\"_capAmount\\\":\\\"the maximum strategy collateral in ETH, checked on deposits\\\"}},\\\"symbol()\\\":{\\\"details\\\":\\\"Returns the symbol of the token, usually a shorter version of the name.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC20-totalSupply}.\\\"},\\\"transfer(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\\\"},\\\"transferOwnership(address)\\\":{\\\"details\\\":\\\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\\\"},\\\"transferVault(address)\\\":{\\\"details\\\":\\\"strategy cap is set to 0 to avoid future deposits\\\",\\\"params\\\":{\\\"_newStrategy\\\":\\\"new strategy contract address\\\"}},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"params\\\":{\\\"_data\\\":\\\"callback data encoded as SwapCallbackData struct\\\",\\\"amount0Delta\\\":\\\"amount of token0\\\",\\\"amount1Delta\\\":\\\"amount of token1\\\"}},\\\"withdraw(uint256)\\\":{\\\"details\\\":\\\"provide strategy tokens and wSqueeth, returns ETH\\\",\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of strategy token to burn\\\"}},\\\"withdrawShutdown(uint256)\\\":{\\\"params\\\":{\\\"_crabAmount\\\":\\\"amount of strategy token to burn\\\"}}},\\\"stateVariables\\\":{\\\"ONE\\\":{\\\"details\\\":\\\"basic unit used for calculation\\\"},\\\"POWER_PERP_PERIOD\\\":{\\\"details\\\":\\\"the TWAP_PERIOD used in the PowerPerp Controller contract\\\"},\\\"_CRAB_BALANCE_TYPEHASH\\\":{\\\"details\\\":\\\"typehash for signed orders\\\"},\\\"ethWSqueethPool\\\":{\\\"details\\\":\\\"ETH:wSqueeth uniswap pool\\\"},\\\"hasRedeemedInShutdown\\\":{\\\"details\\\":\\\"set to true when redeemShortShutdown has been called\\\"},\\\"hedgePriceThreshold\\\":{\\\"details\\\":\\\"price movement to trigger a hedge (0.1*1e18 = 10%)\\\"},\\\"hedgeTimeThreshold\\\":{\\\"details\\\":\\\"time difference to trigger a hedge (seconds)\\\"},\\\"hedgingTwapPeriod\\\":{\\\"details\\\":\\\"twap period to use for hedge calculations\\\"},\\\"isInitialized\\\":{\\\"details\\\":\\\"true if CrabV2 was initialized\\\"},\\\"nonces\\\":{\\\"details\\\":\\\"store the used flag for a nonce for each address\\\"},\\\"oracle\\\":{\\\"details\\\":\\\"strategy uniswap oracle\\\"},\\\"priceAtLastHedge\\\":{\\\"details\\\":\\\"wSqueeth/Eth price when last hedge executed\\\"},\\\"strategyCap\\\":{\\\"details\\\":\\\"the cap in ETH for the strategy, above which deposits will be rejected\\\"},\\\"timeAtLastHedge\\\":{\\\"details\\\":\\\"timestamp when last hedge executed\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"checkPriceHedge()\\\":{\\\"notice\\\":\\\"check if hedging based on price threshold is allowed\\\"},\\\"checkTimeHedge()\\\":{\\\"notice\\\":\\\"check if hedging based on time threshold is allowed\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"strategy constructor\\\"},\\\"deposit()\\\":{\\\"notice\\\":\\\"deposit ETH into strategy\\\"},\\\"flashDeposit(uint256,uint24)\\\":{\\\"notice\\\":\\\"flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\"},\\\"flashWithdraw(uint256,uint256,uint24)\\\":{\\\"notice\\\":\\\"flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\"},\\\"getStrategyVaultId()\\\":{\\\"notice\\\":\\\"get power token strategy vault ID \\\"},\\\"getVaultDetails()\\\":{\\\"notice\\\":\\\"get the vault composition of the strategy \\\"},\\\"getWsqueethFromCrabAmount(uint256)\\\":{\\\"notice\\\":\\\"get wSqueeth debt amount associated with strategy token amount\\\"},\\\"initialize(uint256,uint256,uint256,uint256,uint256)\\\":{\\\"notice\\\":\\\"initializes the collateral ratio after the first migration\\\"},\\\"redeemShortShutdown()\\\":{\\\"notice\\\":\\\"called to redeem the net value of a vault post shutdown\\\"},\\\"setHedgePriceThreshold(uint256)\\\":{\\\"notice\\\":\\\"owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\"},\\\"setHedgeTimeThreshold(uint256)\\\":{\\\"notice\\\":\\\"owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\"},\\\"setHedgingTwapPeriod(uint32)\\\":{\\\"notice\\\":\\\"owner can set the twap period in seconds that is used for calculating twaps for hedging\\\"},\\\"setNonceTrue(uint256)\\\":{\\\"notice\\\":\\\"set nonce to true\\\"},\\\"setOTCPriceTolerance(uint256)\\\":{\\\"notice\\\":\\\"owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\\"},\\\"setStrategyCap(uint256)\\\":{\\\"notice\\\":\\\"owner can set the strategy cap in ETH collateral terms\\\"},\\\"transferVault(address)\\\":{\\\"notice\\\":\\\"transfer vault NFT to new contract\\\"},\\\"uniswapV3SwapCallback(int256,int256,bytes)\\\":{\\\"notice\\\":\\\"uniswap swap callback function for flashes\\\"},\\\"withdraw(uint256)\\\":{\\\"notice\\\":\\\"withdraw WETH from strategy\\\"},\\\"withdrawShutdown(uint256)\\\":{\\\"notice\\\":\\\"called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\"}},\\\"notice\\\":\\\"Contract for Crab strategy\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/strategy/CrabStrategyV2.sol\\\":\\\"CrabStrategyV2\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/access/Ownable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../utils/Context.sol\\\\\\\";\\\\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        address msgSender = _msgSender();\\\\n        _owner = msgSender;\\\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\\\n        _owner = newOwner;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\\\n *\\\\n * These functions can be used to verify that a message was signed by the holder\\\\n * of the private keys of a given address.\\\\n */\\\\nlibrary ECDSA {\\\\n    /**\\\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\\\n     * `signature`. This address can then be used for verification purposes.\\\\n     *\\\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\\\n     * this function rejects them by requiring the `s` value to be in the lower\\\\n     * half order, and the `v` value to be either 27 or 28.\\\\n     *\\\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\\\n     * verification to be secure: it is possible to craft signatures that\\\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\\\n     * this is by receiving a hash of the original message (which may otherwise\\\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\\\n     */\\\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\\\n        // Check the signature length\\\\n        if (signature.length != 65) {\\\\n            revert(\\\\\\\"ECDSA: invalid signature length\\\\\\\");\\\\n        }\\\\n\\\\n        // Divide the signature in r, s and v variables\\\\n        bytes32 r;\\\\n        bytes32 s;\\\\n        uint8 v;\\\\n\\\\n        // ecrecover takes the signature parameters, and the only way to get them\\\\n        // currently is to use assembly.\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly {\\\\n            r := mload(add(signature, 0x20))\\\\n            s := mload(add(signature, 0x40))\\\\n            v := byte(0, mload(add(signature, 0x60)))\\\\n        }\\\\n\\\\n        return recover(hash, v, r, s);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\\\n     * `r` and `s` signature fields separately.\\\\n     */\\\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\\\n        // the valid range for s in (281): 0 < s < secp256k1n \\\\u00f7 2 + 1, and for v in (282): v \\\\u2208 {27, 28}. Most\\\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\\\n        //\\\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\\\n        // these malleable signatures as well.\\\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\\\\\"ECDSA: invalid signature 's' value\\\\\\\");\\\\n        require(v == 27 || v == 28, \\\\\\\"ECDSA: invalid signature 'v' value\\\\\\\");\\\\n\\\\n        // If the signature is valid (and not malleable), return the signer address\\\\n        address signer = ecrecover(hash, v, r, s);\\\\n        require(signer != address(0), \\\\\\\"ECDSA: invalid signature\\\\\\\");\\\\n\\\\n        return signer;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\\\n     * replicates the behavior of the\\\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\\\n     * JSON-RPC method.\\\\n     *\\\\n     * See {recover}.\\\\n     */\\\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\\\n        // 32 is the length in bytes of hash,\\\\n        // enforced by the type signature above\\\\n        return keccak256(abi.encodePacked(\\\\\\\"\\\\\\\\x19Ethereum Signed Message:\\\\\\\\n32\\\\\\\", hash));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc80ce3fcc5e444a2c5bdb902fe4d4f4ecba04e9b416425697d00ae95c1955f82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/drafts/EIP712.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <0.8.0;\\\\n\\\\n/**\\\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\\\n *\\\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\\\n *\\\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\\\n * ({_hashTypedDataV4}).\\\\n *\\\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\\\n *\\\\n * NOTE: This contract implements the version of the encoding known as \\\\\\\"v4\\\\\\\", as implemented by the JSON RPC method\\\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\\\n *\\\\n * _Available since v3.4._\\\\n */\\\\nabstract contract EIP712 {\\\\n    /* solhint-disable var-name-mixedcase */\\\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\\\n    // invalidate the cached domain separator if the chain id changes.\\\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\\\n    uint256 private immutable _CACHED_CHAIN_ID;\\\\n\\\\n    bytes32 private immutable _HASHED_NAME;\\\\n    bytes32 private immutable _HASHED_VERSION;\\\\n    bytes32 private immutable _TYPE_HASH;\\\\n    /* solhint-enable var-name-mixedcase */\\\\n\\\\n    /**\\\\n     * @dev Initializes the domain separator and parameter caches.\\\\n     *\\\\n     * The meaning of `name` and `version` is specified in\\\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\\\n     *\\\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\\\n     * - `version`: the current major version of the signing domain.\\\\n     *\\\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\\\n     * contract upgrade].\\\\n     */\\\\n    constructor(string memory name, string memory version) {\\\\n        bytes32 hashedName = keccak256(bytes(name));\\\\n        bytes32 hashedVersion = keccak256(bytes(version));\\\\n        bytes32 typeHash = keccak256(\\\\\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\\\\\");\\\\n        _HASHED_NAME = hashedName;\\\\n        _HASHED_VERSION = hashedVersion;\\\\n        _CACHED_CHAIN_ID = _getChainId();\\\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\\\n        _TYPE_HASH = typeHash;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the domain separator for the current chain.\\\\n     */\\\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\\\n            return _CACHED_DOMAIN_SEPARATOR;\\\\n        } else {\\\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\\\n        }\\\\n    }\\\\n\\\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\\\n        return keccak256(\\\\n            abi.encode(\\\\n                typeHash,\\\\n                name,\\\\n                version,\\\\n                _getChainId(),\\\\n                address(this)\\\\n            )\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\\\n     *\\\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\\\n     *\\\\n     * ```solidity\\\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\\\n     *     keccak256(\\\\\\\"Mail(address to,string contents)\\\\\\\"),\\\\n     *     mailTo,\\\\n     *     keccak256(bytes(mailContents))\\\\n     * )));\\\\n     * address signer = ECDSA.recover(digest, signature);\\\\n     * ```\\\\n     */\\\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\\\n        return keccak256(abi.encodePacked(\\\\\\\"\\\\\\\\x19\\\\\\\\x01\\\\\\\", _domainSeparatorV4(), structHash));\\\\n    }\\\\n\\\\n    function _getChainId() private view returns (uint256 chainId) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly {\\\\n            chainId := chainid()\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4bc5cda2bfee483ff10334881c9ea5cc4df7faa7b18a5a4b8f02fc51cf8adca\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.0;\\\\n\\\\n/// @title Optimized overflow and underflow safe math operations\\\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\\\nlibrary LowGasSafeMath {\\\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x + y) >= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require((z = x - y) <= x);\\\\n    }\\\\n\\\\n    /// @notice Returns x * y, reverts if overflows\\\\n    /// @param x The multiplicand\\\\n    /// @param y The multiplier\\\\n    /// @return z The product of x and y\\\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        require(x == 0 || (z = x * y) / x == y);\\\\n    }\\\\n\\\\n    /// @notice Returns x + y, reverts if overflows or underflows\\\\n    /// @param x The augend\\\\n    /// @param y The addend\\\\n    /// @return z The sum of x and y\\\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x + y) >= x == (y >= 0));\\\\n    }\\\\n\\\\n    /// @notice Returns x - y, reverts if overflows or underflows\\\\n    /// @param x The minuend\\\\n    /// @param y The subtrahend\\\\n    /// @return z The difference of x and y\\\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\\\n        require((z = x - y) <= x == (y >= 0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x86715eb960f18e01ac94e3bba4614ed51a887fa3c5bd1c43bf80aa98e019cf2d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Safe casting methods\\\\n/// @notice Contains methods for safely casting between types\\\\nlibrary SafeCast {\\\\n    /// @notice Cast a uint256 to a uint160, revert on overflow\\\\n    /// @param y The uint256 to be downcasted\\\\n    /// @return z The downcasted integer, now type uint160\\\\n    function toUint160(uint256 y) internal pure returns (uint160 z) {\\\\n        require((z = uint160(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a int256 to a int128, revert on overflow or underflow\\\\n    /// @param y The int256 to be downcasted\\\\n    /// @return z The downcasted integer, now type int128\\\\n    function toInt128(int256 y) internal pure returns (int128 z) {\\\\n        require((z = int128(y)) == y);\\\\n    }\\\\n\\\\n    /// @notice Cast a uint256 to a int256, revert on overflow\\\\n    /// @param y The uint256 to be casted\\\\n    /// @return z The casted integer, now type int256\\\\n    function toInt256(uint256 y) internal pure returns (int256 z) {\\\\n        require(y < 2**255);\\\\n        z = int256(y);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x4c12bf820c0b011f5490a209960ca34dd8af34660ef9e01de0438393d15e3fd8\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n/*\\\\n * @title Solidity Bytes Arrays Utils\\\\n * @author Gon\\\\u00e7alo S\\\\u00e1 <goncalo.sa@consensys.net>\\\\n *\\\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\\\n */\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\nlibrary BytesLib {\\\\n    function slice(\\\\n        bytes memory _bytes,\\\\n        uint256 _start,\\\\n        uint256 _length\\\\n    ) internal pure returns (bytes memory) {\\\\n        require(_length + 31 >= _length, 'slice_overflow');\\\\n        require(_start + _length >= _start, 'slice_overflow');\\\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\\\n\\\\n        bytes memory tempBytes;\\\\n\\\\n        assembly {\\\\n            switch iszero(_length)\\\\n                case 0 {\\\\n                    // Get a location of some free memory and store it in tempBytes as\\\\n                    // Solidity does for memory variables.\\\\n                    tempBytes := mload(0x40)\\\\n\\\\n                    // The first word of the slice result is potentially a partial\\\\n                    // word read from the original array. To read it, we calculate\\\\n                    // the length of that partial word and start copying that many\\\\n                    // bytes into the array. The first word we copy will start with\\\\n                    // data we don't care about, but the last `lengthmod` bytes will\\\\n                    // land at the beginning of the contents of the new array. When\\\\n                    // we're done copying, we overwrite the full first word with\\\\n                    // the actual length of the slice.\\\\n                    let lengthmod := and(_length, 31)\\\\n\\\\n                    // The multiplication in the next line is necessary\\\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\\\n                    // the following copy loop was copying the origin's length\\\\n                    // and then ending prematurely not copying everything it should.\\\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\\\n                    let end := add(mc, _length)\\\\n\\\\n                    for {\\\\n                        // The multiplication in the next line has the same exact purpose\\\\n                        // as the one above.\\\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\\\n                    } lt(mc, end) {\\\\n                        mc := add(mc, 0x20)\\\\n                        cc := add(cc, 0x20)\\\\n                    } {\\\\n                        mstore(mc, mload(cc))\\\\n                    }\\\\n\\\\n                    mstore(tempBytes, _length)\\\\n\\\\n                    //update free-memory pointer\\\\n                    //allocating the array padded to 32 bytes like the compiler does now\\\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\\\n                }\\\\n                //if we want a zero-length slice let's just return a zero-length array\\\\n                default {\\\\n                    tempBytes := mload(0x40)\\\\n                    //zero out the 32 bytes slice we are about to return\\\\n                    //we need to do it because Solidity does not garbage collect\\\\n                    mstore(tempBytes, 0)\\\\n\\\\n                    mstore(0x40, add(tempBytes, 0x20))\\\\n                }\\\\n        }\\\\n\\\\n        return tempBytes;\\\\n    }\\\\n\\\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\\\n        address tempAddress;\\\\n\\\\n        assembly {\\\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\\\n        }\\\\n\\\\n        return tempAddress;\\\\n    }\\\\n\\\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\\\n        uint24 tempUint;\\\\n\\\\n        assembly {\\\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\\\n        }\\\\n\\\\n        return tempUint;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x68629e5b1a30b6490c6ae721c28117f6f963745462b007da0769758eb67f10d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\\\nimport './PoolAddress.sol';\\\\n\\\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\\\nlibrary CallbackValidation {\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param tokenA The contract address of either token0 or token1\\\\n    /// @param tokenB The contract address of the other token\\\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(\\\\n        address factory,\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool pool) {\\\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\\\n    }\\\\n\\\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\\\n    /// @param factory The contract address of the Uniswap V3 factory\\\\n    /// @param poolKey The identifying key of the V3 pool\\\\n    /// @return pool The V3 pool contract address\\\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\\\n        internal\\\\n        view\\\\n        returns (IUniswapV3Pool pool)\\\\n    {\\\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\\\n        require(msg.sender == address(pool));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x490c80ca7f4a0ee0514041ddec0867e8a52b24febf1670991797af8fed9f3eec\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.6.0;\\\\n\\\\nimport './BytesLib.sol';\\\\n\\\\n/// @title Functions for manipulating path data for multihop swaps\\\\nlibrary Path {\\\\n    using BytesLib for bytes;\\\\n\\\\n    /// @dev The length of the bytes encoded address\\\\n    uint256 private constant ADDR_SIZE = 20;\\\\n    /// @dev The length of the bytes encoded fee\\\\n    uint256 private constant FEE_SIZE = 3;\\\\n\\\\n    /// @dev The offset of a single token address and pool fee\\\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\\\n    /// @dev The offset of an encoded pool key\\\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\\\n\\\\n    /// @notice Returns true iff the path contains two or more pools\\\\n    /// @param path The encoded swap path\\\\n    /// @return True if path contains two or more pools, otherwise false\\\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\\\n    }\\\\n\\\\n    /// @notice Returns the number of pools in the path\\\\n    /// @param path The encoded swap path\\\\n    /// @return The number of pools in the path\\\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Decodes the first pool in path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return tokenA The first token of the given pool\\\\n    /// @return tokenB The second token of the given pool\\\\n    /// @return fee The fee level of the pool\\\\n    function decodeFirstPool(bytes memory path)\\\\n        internal\\\\n        pure\\\\n        returns (\\\\n            address tokenA,\\\\n            address tokenB,\\\\n            uint24 fee\\\\n        )\\\\n    {\\\\n        tokenA = path.toAddress(0);\\\\n        fee = path.toUint24(ADDR_SIZE);\\\\n        tokenB = path.toAddress(NEXT_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Gets the segment corresponding to the first pool in the path\\\\n    /// @param path The bytes encoded swap path\\\\n    /// @return The segment containing all data necessary to target the first pool in the path\\\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(0, POP_OFFSET);\\\\n    }\\\\n\\\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\\\n    /// @param path The swap path\\\\n    /// @return The remaining token + fee elements in the path\\\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb22c562b5175d50dbcc2224325666090d985f052abdcfe275c8dfc884e34de61\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerpPool() external view returns (address);\\\\n\\\\n    function oracle() external view returns (address);\\\\n\\\\n    function weth() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n\\\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\\\n\\\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x63a3299e63c121a847f92b0098e72132890cb0b8183245410eb7d6c765e5eac3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IOracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\ninterface IOracle {\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        uint32 _periodToHistoricPrice\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256);\\\\n\\\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\\\n\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe4ca0166858146d6aa98ec5d76e432c121299757b9eef14c32990d981d6e81ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity 0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x78be70880c9ec22c35cf595377416bb25960936fee1b0fff06e415bda1b5e64b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/Power2Base.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\nlibrary Power2Base {\\\\n    using SafeMath for uint256;\\\\n\\\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\\\n    uint256 private constant INDEX_SCALE = 1e4;\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    /**\\\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @return for squeeth, return ethPrice^2\\\\n     */\\\\n    function _getUnscaledIndex(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\\\n     * @param _weth weth address\\\\n     * @param _quoteCurrency quoteCurrency address\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\\\n     */\\\\n    function _getDenormalizedMark(\\\\n        uint32 _period,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _ethQuoteCurrencyPool,\\\\n        address _weth,\\\\n        address _quoteCurrency,\\\\n        address _wSqueeth,\\\\n        uint256 _normalizationFactor\\\\n    ) internal view returns (uint256) {\\\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\\\n            _oracle,\\\\n            _ethQuoteCurrencyPool,\\\\n            _weth,\\\\n            _quoteCurrency,\\\\n            _period,\\\\n            false\\\\n        );\\\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\\\n\\\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\\\n     * @param _oracle oracle address\\\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\\\n     * @param _wSqueeth wSqueeth address\\\\n     * @param _weth weth address\\\\n     * @return returns value of debt in ETH\\\\n     */\\\\n    function _getDebtValueInEth(\\\\n        uint256 _debtAmount,\\\\n        address _oracle,\\\\n        address _wSqueethEthPool,\\\\n        address _wSqueeth,\\\\n        address _weth\\\\n    ) internal view returns (uint256) {\\\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return twap price scaled down by INDEX_SCALE\\\\n     */\\\\n    function _getScaledTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\\\n        return twap.div(INDEX_SCALE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice request twap from our oracle\\\\n     * @dev this will revert if period is > max period for the pool\\\\n     * @param _oracle oracle address\\\\n     * @param _pool uniswap v3 pool address\\\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\\\n     * @return human readable price. scaled by 1e18\\\\n     */\\\\n    function _getTwap(\\\\n        address _oracle,\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) internal view returns (uint256) {\\\\n        // period reaching this point should be check, otherwise might revert\\\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\\\n     * @param _indexPriceForSettlement index price for settlement\\\\n     * @param _normalizationFactor current normalization factor\\\\n     * @return amount in wei that should be paid to the token holder\\\\n     */\\\\n    function _getLongSettlementValue(\\\\n        uint256 _wsqueethAmount,\\\\n        uint256 _indexPriceForSettlement,\\\\n        uint256 _normalizationFactor\\\\n    ) internal pure returns (uint256) {\\\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1938180c41ec0ee817b841df605b199e15ffbbe94700b640d031b4e4665a89af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x6ec7738f80b383c1258df1a6d86fc0849bb398965003569066d21a4bf2c7c6ee\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/CrabStrategyV2.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IOracle} from \\\\\\\"../interfaces/IOracle.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {StrategyBase} from \\\\\\\"./base/StrategyBase.sol\\\\\\\";\\\\nimport {StrategyFlashSwap} from \\\\\\\"./base/StrategyFlashSwap.sol\\\\\\\";\\\\nimport {Ownable} from \\\\\\\"@openzeppelin/contracts/access/Ownable.sol\\\\\\\";\\\\nimport {EIP712} from \\\\\\\"@openzeppelin/contracts/drafts/EIP712.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./base/StrategyMath.sol\\\\\\\";\\\\nimport {Power2Base} from \\\\\\\"../libs/Power2Base.sol\\\\\\\";\\\\nimport {ECDSA} from \\\\\\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Crab V2 Error Codes:\\\\n * C1: Caller is not timelock\\\\n * C2: Contract not yet initialized\\\\n * C3: Invalid oracle address\\\\n * C4: Invalid timelock address\\\\n * C5: Invalid ETH:WSqueeth address\\\\n * C6: Invalid crabMigration address\\\\n * C7: Invalid hedge time threshold\\\\n * C8: Invalid hedge price threshold\\\\n * C9: Cannot receive ETH\\\\n * C10: Caller not Crab Migration contract\\\\n * C11: Crab V2 already initialized\\\\n * C12: Squeeth contracts not shut down\\\\n * C13: Crab must redeemShortShutdown\\\\n * C14: Twap period is too short\\\\n * C15: Price tolerance is too high\\\\n * C16: Deposit exceeds strategy cap\\\\n * C17: Clearing Price should be below bid price\\\\n * C18: Clearing Price should be above offer price\\\\n * C19: Invalid offer signature\\\\n * C20: Order has expired\\\\n * C21: Manager Price should be greater than 0\\\\n * C22: Not a valid Time or Price hedge\\\\n * C23: Orders must take the opposite side of the hedge\\\\n * C24: All orders must be either buying or selling\\\\n * C25: Orders are not arranged properly\\\\n * C26: Crab contracts shut down\\\\n *  C27: Nonce already used.\\\\n */\\\\n\\\\n/**\\\\n * @dev CrabStrategyV2 contract\\\\n * @notice Contract for Crab strategy\\\\n * @author Opyn team\\\\n */\\\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\\\n    uint256 public strategyCap;\\\\n\\\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\\\n\\\\n    /// @dev basic unit used for calculation\\\\n    uint256 private constant ONE = 1e18;\\\\n    uint256 private constant ONE_ONE = 1e36;\\\\n\\\\n    // @dev OTC price must be within this distance of the uniswap twap price\\\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\\\n\\\\n    // @dev OTC price tolerance cannot exceed 20%\\\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\\\n\\\\n    /// @dev twap period to use for hedge calculations\\\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\\\n    /// @dev true if CrabV2 was initialized\\\\n    bool public isInitialized;\\\\n\\\\n    /// @dev typehash for signed orders\\\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\\\n        keccak256(\\\\n            \\\\\\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\\\\\"\\\\n        );\\\\n\\\\n    /// @dev enum to differentiate between uniswap swap callback function source\\\\n    enum FLASH_SOURCE {\\\\n        FLASH_DEPOSIT,\\\\n        FLASH_WITHDRAW\\\\n    }\\\\n\\\\n    /// @dev ETH:wSqueeth uniswap pool\\\\n    address public immutable ethWSqueethPool;\\\\n    /// @dev strategy uniswap oracle\\\\n    address public immutable oracle;\\\\n    address public immutable timelock;\\\\n    address public immutable crabMigration;\\\\n\\\\n    /// @dev time difference to trigger a hedge (seconds)\\\\n    uint256 public hedgeTimeThreshold;\\\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\\\n    uint256 public hedgePriceThreshold;\\\\n\\\\n    /// @dev timestamp when last hedge executed\\\\n    uint256 public timeAtLastHedge;\\\\n    /// @dev wSqueeth/Eth price when last hedge executed\\\\n    uint256 public priceAtLastHedge;\\\\n\\\\n    /// @dev set to true when redeemShortShutdown has been called\\\\n    bool private hasRedeemedInShutdown;\\\\n\\\\n    /// @dev store the used flag for a nonce for each address\\\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\\\n\\\\n    struct FlashDepositData {\\\\n        uint256 totalDeposit;\\\\n    }\\\\n\\\\n    struct FlashWithdrawData {\\\\n        uint256 crabAmount;\\\\n    }\\\\n\\\\n    struct Order {\\\\n        uint256 bidId;\\\\n        address trader;\\\\n        uint256 quantity;\\\\n        uint256 price;\\\\n        bool isBuying;\\\\n        uint256 expiry;\\\\n        uint256 nonce;\\\\n        uint8 v;\\\\n        bytes32 r;\\\\n        bytes32 s;\\\\n    }\\\\n\\\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\\\n    event HedgeOTCSingle(\\\\n        address trader,\\\\n        uint256 bidId,\\\\n        uint256 quantity,\\\\n        uint256 price,\\\\n        bool isBuying,\\\\n        uint256 clearingPrice\\\\n    );\\\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\\\n    event SetStrategyCap(uint256 newCapAmount);\\\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\\\n\\\\n    modifier onlyTimelock() {\\\\n        require(msg.sender == timelock, \\\\\\\"C1\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    modifier afterInitialization() {\\\\n        require(isInitialized, \\\\\\\"C2\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice strategy constructor\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _wSqueethController power token controller address\\\\n     * @param _oracle oracle address\\\\n     * @param _weth weth address\\\\n     * @param _uniswapFactory uniswap factory address\\\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\\\n     * @param _timelock timelock contract address\\\\n     * @param _crabMigration crab migration contract address\\\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\\\n     */\\\\n    constructor(\\\\n        address _wSqueethController,\\\\n        address _oracle,\\\\n        address _weth,\\\\n        address _uniswapFactory,\\\\n        address _ethWSqueethPool,\\\\n        address _timelock,\\\\n        address _crabMigration,\\\\n        uint256 _hedgeTimeThreshold,\\\\n        uint256 _hedgePriceThreshold\\\\n    )\\\\n        StrategyBase(_wSqueethController, _weth, \\\\\\\"Crab Strategy v2\\\\\\\", \\\\\\\"Crabv2\\\\\\\")\\\\n        StrategyFlashSwap(_uniswapFactory)\\\\n        EIP712(\\\\\\\"CrabOTC\\\\\\\", \\\\\\\"2\\\\\\\")\\\\n    {\\\\n        require(_oracle != address(0), \\\\\\\"C3\\\\\\\");\\\\n        require(_timelock != address(0), \\\\\\\"C4\\\\\\\");\\\\n        require(_ethWSqueethPool != address(0), \\\\\\\"C5\\\\\\\");\\\\n        require(_crabMigration != address(0), \\\\\\\"C6\\\\\\\");\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"C7\\\\\\\");\\\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\\\\\"C8\\\\\\\");\\\\n\\\\n        oracle = _oracle;\\\\n        ethWSqueethPool = _ethWSqueethPool;\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n        timelock = _timelock;\\\\n        crabMigration = _crabMigration;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice receive function to allow ETH transfer to this contract\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\\\\\"C9\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice initializes the collateral ratio after the first migration\\\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\\\n     * @param _crabSharesToMint crab shares to mint\\\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\\\n     * @param _strategyCap strategy cap for crab V2\\\\n     */\\\\n    function initialize(\\\\n        uint256 _wSqueethToMint,\\\\n        uint256 _crabSharesToMint,\\\\n        uint256 _timeAtLastHedge,\\\\n        uint256 _priceAtLastHedge,\\\\n        uint256 _strategyCap\\\\n    ) external payable {\\\\n        require(msg.sender == crabMigration, \\\\\\\"C10\\\\\\\");\\\\n        require(!isInitialized, \\\\\\\"C11\\\\\\\");\\\\n\\\\n        _setStrategyCap(_strategyCap);\\\\n\\\\n        uint256 amount = msg.value;\\\\n\\\\n        _checkStrategyCap(amount, 0);\\\\n\\\\n        // store hedge data from crab V1\\\\n        timeAtLastHedge = _timeAtLastHedge;\\\\n        priceAtLastHedge = _priceAtLastHedge;\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\\\n\\\\n        isInitialized = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice transfer vault NFT to new contract\\\\n     * @dev strategy cap is set to 0 to avoid future deposits\\\\n     * @param _newStrategy new strategy contract address\\\\n     */\\\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\\\n        _setStrategyCap(0);\\\\n\\\\n        emit VaultTransferred(_newStrategy, vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the strategy cap in ETH collateral terms\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\\\n        _setStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set strategy cap amount\\\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\\\n     */\\\\n    function _setStrategyCap(uint256 _capAmount) internal {\\\\n        strategyCap = _capAmount;\\\\n        emit SetStrategyCap(_capAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to redeem the net value of a vault post shutdown\\\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\\\n     */\\\\n    function redeemShortShutdown() external afterInitialization {\\\\n        hasRedeemedInShutdown = true;\\\\n        powerTokenController.redeemShort(vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\\\n     * @param _poolFee Uniswap pool fee\\\\n     */\\\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\\\n            _ethToDeposit,\\\\n            cachedStrategyDebt,\\\\n            cachedStrategyCollateral\\\\n        );\\\\n\\\\n        _exactInFlashSwap(\\\\n            wPowerPerp,\\\\n            weth,\\\\n            _poolFee,\\\\n            wSqueethToMint,\\\\n            _ethToDeposit.sub(msg.value),\\\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\\\n            abi.encodePacked(_ethToDeposit)\\\\n        );\\\\n\\\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\\\n     * @param _crabAmount strategy token amount to burn\\\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\\\n     * @param _poolFee Uniswap pool fee\\\\n\\\\n     */\\\\n    function flashWithdraw(\\\\n        uint256 _crabAmount,\\\\n        uint256 _maxEthToPay,\\\\n        uint24 _poolFee\\\\n    ) external nonReentrant {\\\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\\\n\\\\n        _exactOutFlashSwap(\\\\n            weth,\\\\n            wPowerPerp,\\\\n            _poolFee,\\\\n            exactWSqueethNeeded,\\\\n            _maxEthToPay,\\\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\\\n            abi.encodePacked(_crabAmount)\\\\n        );\\\\n\\\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit ETH into strategy\\\\n     * @dev provide ETH, return wSqueeth and strategy token\\\\n     */\\\\n    function deposit() external payable nonReentrant {\\\\n        uint256 amount = msg.value;\\\\n\\\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\\\n\\\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\\\n\\\\n        // send back ETH collateral\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n\\\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     */\\\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\\\n        require(powerTokenController.isShutDown(), \\\\\\\"C12\\\\\\\");\\\\n        require(hasRedeemedInShutdown, \\\\\\\"C13\\\\\\\");\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\\\n        _burn(msg.sender, _crabAmount);\\\\n\\\\n        payable(msg.sender).sendValue(ethToWithdraw);\\\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice set nonce to true\\\\n     * @param _nonce the number to be set true\\\\n     */\\\\n    function setNonceTrue(uint256 _nonce) external {\\\\n        nonces[msg.sender][_nonce] = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\\\n     * @param _crabAmount strategy token amount\\\\n     * @return wSqueeth amount\\\\n     */\\\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\\\n        return _getDebtFromStrategyAmount(_crabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\\\n     */\\\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\\\n        require(_hedgingTwapPeriod >= 180, \\\\\\\"C14\\\\\\\");\\\\n\\\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\\\n\\\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\\\n     */\\\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\\\n        require(_hedgeTimeThreshold > 0, \\\\\\\"C7\\\\\\\");\\\\n\\\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\\\n\\\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\\\n     */\\\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\\\\\"C8\\\\\\\");\\\\n\\\\n        hedgePriceThreshold = _hedgePriceThreshold;\\\\n\\\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\\\n     */\\\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\\\n        // Tolerance cannot be more than 20%\\\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\\\\\"C15\\\\\\\");\\\\n\\\\n        otcPriceTolerance = _otcPriceTolerance;\\\\n\\\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a user deposit puts the strategy above the cap\\\\n     * @dev reverts if a deposit amount puts strategy over the cap\\\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\\\n     * @param _depositAmount the user deposit amount in ETH\\\\n     * @param _strategyCollateral the updated strategy collateral\\\\n     */\\\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\\\\\"C16\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap flash swap callback function\\\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\\\n     * @param _caller address of original function caller\\\\n     * @param _amountToPay amount to pay back for flashswap\\\\n     * @param _callData arbitrary data attached to callback\\\\n     * @param _callSource identifier for which function triggered callback\\\\n     */\\\\n    function _strategyFlash(\\\\n        address _caller,\\\\n        address _tokenIn,\\\\n        address _tokenOut,\\\\n        uint24 _fee,\\\\n        uint256 _amountToPay,\\\\n        bytes memory _callData,\\\\n        uint8 _callSource\\\\n    ) internal override {\\\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\\\n\\\\n            // convert WETH to ETH as Uniswap uses WETH\\\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\\\n\\\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\\\n            // will revert if data.totalDeposit is > eth balance in contract\\\\n            _deposit(_caller, data.totalDeposit, true);\\\\n\\\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\\\n\\\\n            // repay the flash swap\\\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\\\n\\\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\\\n\\\\n            // return excess eth to the user that was not needed for slippage\\\\n            if (address(this).balance > 0) {\\\\n                payable(_caller).sendValue(address(this).balance);\\\\n            }\\\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\\\n\\\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\\\n            uint256 ethToWithdraw = _withdraw(\\\\n                _caller,\\\\n                data.crabAmount,\\\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\\\n                true\\\\n            );\\\\n\\\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\\\n\\\\n            // use some amount of withdrawn ETH to repay flash swap\\\\n            IWETH9(weth).deposit{value: _amountToPay}();\\\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\\\n\\\\n            // excess ETH not used to repay flash swap is transferred to the user\\\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\\\n\\\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\\\n\\\\n            if (proceeds > 0) {\\\\n                payable(_caller).sendValue(proceeds);\\\\n            }\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice deposit into strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _depositor depositor address\\\\n     * @param _amount amount of ETH collateral to deposit\\\\n     * @param _isFlashDeposit true if called by flashDeposit\\\\n     * @return wSqueethToMint minted amount of WSqueeth\\\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\\\n     */\\\\n    function _deposit(\\\\n        address _depositor,\\\\n        uint256 _amount,\\\\n        bool _isFlashDeposit\\\\n    ) internal returns (uint256, uint256) {\\\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\\\n        _checkStrategyCap(_amount, strategyCollateral);\\\\n\\\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\\\n\\\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\\\n\\\\n        // mint wSqueeth and send it to msg.sender\\\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\\\n        // mint LP to depositor\\\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\\\n\\\\n        return (wSqueethToMint, depositorCrabAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice withdraw WETH from strategy\\\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\\\n     * @param _crabAmount amount of strategy token to burn\\\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\\\n     * @return ETH amount to withdraw\\\\n     */\\\\n    function _withdraw(\\\\n        address _from,\\\\n        uint256 _crabAmount,\\\\n        uint256 _wSqueethAmount,\\\\n        bool _isFlashWithdraw\\\\n    ) internal returns (uint256) {\\\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\\\n\\\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\\\n\\\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\\\n        _burn(_from, _crabAmount);\\\\n\\\\n        return ethToWithdraw;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev set nonce flag of the trader to true\\\\n     * @param _trader address of the signer\\\\n     * @param _nonce number that is to be traded only once\\\\n     */\\\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\\\n        require(!nonces[_trader][_nonce], \\\\\\\"C27\\\\\\\");\\\\n        nonces[_trader][_nonce] = true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev view function to get the domain seperator used in signing\\\\n     */\\\\n    // solhint-disable-next-line func-name-mixedcase\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\\\n        return _domainSeparatorV4();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev check the signer and swap tokens in the order\\\\n     * @param _remainingAmount quantity the manager wants to trade\\\\n     * @param _clearingPrice the price at which all orders are traded\\\\n     * @param _order a signed order to swap tokens\\\\n     */\\\\n    function _execOrder(\\\\n        uint256 _remainingAmount,\\\\n        uint256 _clearingPrice,\\\\n        Order memory _order\\\\n    ) internal {\\\\n        // check that order beats clearing price\\\\n        if (_order.isBuying) {\\\\n            require(_clearingPrice <= _order.price, \\\\\\\"C17\\\\\\\");\\\\n        } else {\\\\n            require(_clearingPrice >= _order.price, \\\\\\\"C18\\\\\\\");\\\\n        }\\\\n\\\\n        _useNonce(_order.trader, _order.nonce);\\\\n        bytes32 structHash = keccak256(\\\\n            abi.encode(\\\\n                _CRAB_BALANCE_TYPEHASH,\\\\n                _order.bidId,\\\\n                _order.trader,\\\\n                _order.quantity,\\\\n                _order.price,\\\\n                _order.isBuying,\\\\n                _order.expiry,\\\\n                _order.nonce\\\\n            )\\\\n        );\\\\n\\\\n        bytes32 hash = _hashTypedDataV4(structHash);\\\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\\\n        require(offerSigner == _order.trader, \\\\\\\"C19\\\\\\\");\\\\n        require(_order.expiry >= block.timestamp, \\\\\\\"C20\\\\\\\");\\\\n\\\\n        // adjust quantity for partial fills\\\\n        if (_remainingAmount < _order.quantity) {\\\\n            _order.quantity = _remainingAmount;\\\\n        }\\\\n        // weth clearing price for the order\\\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\\\n\\\\n        if (_order.isBuying) {\\\\n            // trader sends weth and receives oSQTH\\\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\\\n            IWETH9(weth).withdraw(wethAmount);\\\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\\\n        } else {\\\\n            // trader sends oSQTH and receives weth\\\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\\\n            // wrap it\\\\n            IWETH9(weth).deposit{value: wethAmount}();\\\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\\\n        }\\\\n\\\\n        emit HedgeOTCSingle(\\\\n            _order.trader, // market maker\\\\n            _order.bidId,\\\\n            _order.quantity, // order oSQTH quantity\\\\n            _order.price, // order price\\\\n            _order.isBuying, // order direction\\\\n            _clearingPrice // executed price for order\\\\n        );\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev hedge function to reduce delta using an array of signed orders\\\\n     * @param _totalQuantity quantity the manager wants to trade\\\\n     * @param _clearingPrice clearing price in weth\\\\n     * @param _isHedgeBuying direction of hedge trade\\\\n     * @param _orders an array of signed order to swap tokens\\\\n     */\\\\n    function hedgeOTC(\\\\n        uint256 _totalQuantity,\\\\n        uint256 _clearingPrice,\\\\n        bool _isHedgeBuying,\\\\n        Order[] memory _orders\\\\n    ) external onlyOwner afterInitialization {\\\\n        require(_clearingPrice > 0, \\\\\\\"C21\\\\\\\");\\\\n        require(_isTimeHedge() || _isPriceHedge(), \\\\\\\"C22\\\\\\\");\\\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\\\n\\\\n        timeAtLastHedge = block.timestamp;\\\\n        priceAtLastHedge = _clearingPrice;\\\\n\\\\n        uint256 remainingAmount = _totalQuantity;\\\\n        uint256 prevPrice = _orders[0].price;\\\\n        uint256 currentPrice = _orders[0].price;\\\\n        bool isOrderBuying = _orders[0].isBuying;\\\\n        require(_isHedgeBuying != isOrderBuying, \\\\\\\"C23\\\\\\\");\\\\n\\\\n        // iterate through order array and execute if valid\\\\n        for (uint256 i; i < _orders.length; ++i) {\\\\n            currentPrice = _orders[i].price;\\\\n            require(_orders[i].isBuying == isOrderBuying, \\\\\\\"C24\\\\\\\");\\\\n            if (_isHedgeBuying) {\\\\n                require(currentPrice >= prevPrice, \\\\\\\"C25\\\\\\\");\\\\n            } else {\\\\n                require(currentPrice <= prevPrice, \\\\\\\"C25\\\\\\\");\\\\n            }\\\\n            prevPrice = currentPrice;\\\\n\\\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\\\n\\\\n            if (remainingAmount > _orders[i].quantity) {\\\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\\\n            } else {\\\\n                break;\\\\n            }\\\\n        }\\\\n\\\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\\\n     * @param _price clearing price provided by manager\\\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\\\n     */\\\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\\\n        // Get twap\\\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\\\n\\\\n        if (_isHedgeBuying) {\\\\n            require(\\\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\\\n                \\\\\\\"Price too high relative to Uniswap twap.\\\\\\\"\\\\n            );\\\\n        } else {\\\\n            require(\\\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\\\n                \\\\\\\"Price too low relative to Uniswap twap.\\\\\\\"\\\\n            );\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice sync strategy debt and collateral amount from vault\\\\n     * @return synced debt amount\\\\n     * @return synced collateral amount\\\\n     */\\\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\\\n\\\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\\\n     * @return the fee adjustment factor\\\\n     */\\\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\\\n            oracle,\\\\n            ethWSqueethPool,\\\\n            wPowerPerp,\\\\n            weth,\\\\n            POWER_PERP_PERIOD,\\\\n            false\\\\n        );\\\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\\\n     * @param _depositedAmount amount of deposited WETH\\\\n     * @param _strategyDebtAmount amount of strategy debt\\\\n     * @param _strategyCollateralAmount collateral amount in strategy\\\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\\\n     */\\\\n    function _calcWsqueethToMintAndFee(\\\\n        uint256 _depositedAmount,\\\\n        uint256 _strategyDebtAmount,\\\\n        uint256 _strategyCollateralAmount\\\\n    ) internal view returns (uint256, uint256) {\\\\n        uint256 wSqueethToMint;\\\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\\\n        require(!isShutdown, \\\\\\\"C26\\\\\\\");\\\\n\\\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\\\n        );\\\\n\\\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\\\n\\\\n        return (wSqueethToMint, fee);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if time hedging is allowed\\\\n     */\\\\n    function _isTimeHedge() internal view returns (bool) {\\\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function _isPriceHedge() internal view returns (bool) {\\\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\\\n\\\\n        return priceThreshold >= hedgePriceThreshold;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on price threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkPriceHedge() external view returns (bool) {\\\\n        return _isPriceHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if hedging based on time threshold is allowed\\\\n     * @return true if hedging is allowed\\\\n     */\\\\n    function checkTimeHedge() external view returns (bool) {\\\\n        return _isTimeHedge();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev calculate amount of strategy token to mint for depositor\\\\n     * @param _amount amount of ETH deposited\\\\n     * @param _strategyCollateralAmount amount of strategy collateral\\\\n     * @param _crabTotalSupply total supply of strategy token\\\\n     * @return amount of strategy token to mint\\\\n     */\\\\n    function _calcSharesToMint(\\\\n        uint256 _amount,\\\\n        uint256 _strategyCollateralAmount,\\\\n        uint256 _crabTotalSupply\\\\n    ) internal pure returns (uint256) {\\\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\\\n\\\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\\\n\\\\n        return _amount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\\\n     * @param _crabAmount strategy token amount\\\\n     * @param _totalSupply strategy total supply\\\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\\\n     */\\\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\\\n        return _crabAmount.wdiv(_totalSupply);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\\\n     * @param _crabRatio crab ratio\\\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\\\n     * @return amount of ETH allowed to withdraw\\\\n     */\\\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8b1900ce7c5c79e38af489819462339a27d677e2bb8626f7aa6f784409cbf3fa\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyBase.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-3.0-only\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport {IController} from \\\\\\\"../../interfaces/IController.sol\\\\\\\";\\\\nimport {IWPowerPerp} from \\\\\\\"../../interfaces/IWPowerPerp.sol\\\\\\\";\\\\n\\\\n// contract\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\n// StrategyMath licensed under AGPL-3.0-only\\\\nimport {StrategyMath} from \\\\\\\"./StrategyMath.sol\\\\\\\";\\\\nimport {VaultLib} from \\\\\\\"../../libs/VaultLib.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev StrategyBase contract\\\\n * @notice base contract for PowerToken strategy\\\\n * @author opyn team\\\\n */\\\\ncontract StrategyBase is ERC20 {\\\\n    using StrategyMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    /// @dev power token controller\\\\n    IController public powerTokenController;\\\\n\\\\n    /// @dev WETH token\\\\n    address public immutable weth;\\\\n    address public immutable wPowerPerp;\\\\n\\\\n    /// @dev power token strategy vault ID\\\\n    uint256 public immutable vaultId;\\\\n\\\\n    /**\\\\n     * @notice constructor for StrategyBase\\\\n     * @dev this will open a vault in the power token contract and store the vault ID\\\\n     * @param _powerTokenController power token controller address\\\\n     * @param _weth weth token address\\\\n     * @param _name token name for strategy ERC20 token\\\\n     * @param _symbol token symbol for strategy ERC20 token\\\\n     */\\\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\\\n        require(_powerTokenController != address(0), \\\\\\\"invalid controller address\\\\\\\");\\\\n        require(_weth != address(0), \\\\\\\"invalid weth address\\\\\\\");\\\\n\\\\n        weth = _weth;\\\\n        powerTokenController = IController(_powerTokenController);\\\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\\\n    }\\\\n    /**\\\\n     * @notice get power token strategy vault ID \\\\n     * @return vault ID\\\\n     */\\\\n    function getStrategyVaultId() external view returns (uint256) {\\\\n        return vaultId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n    */\\\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\\\n        return _getVaultDetails();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint WPowerPerp and deposit collateral\\\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\\\n     * @param _to receiver address\\\\n     * @param _wAmount amount of WPowerPerp to mint\\\\n     * @param _collateral amount of collateral to deposit\\\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\\\n     */\\\\n    function _mintWPowerPerp(\\\\n        address _to,\\\\n        uint256 _wAmount,\\\\n        uint256 _collateral,\\\\n        bool _keepWsqueeth\\\\n    ) internal {\\\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\\\n\\\\n        if (!_keepWsqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn WPowerPerp and withdraw collateral\\\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\\\n     * @param _from WPowerPerp holder address\\\\n     * @param _amount amount of wPowerPerp to burn\\\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\\\n     */\\\\n    function _burnWPowerPerp(\\\\n        address _from,\\\\n        uint256 _amount,\\\\n        uint256 _collateralToWithdraw,\\\\n        bool _isOwnedWSqueeth\\\\n    ) internal {\\\\n        if (!_isOwnedWSqueeth) {\\\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\\\n        }\\\\n\\\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint strategy token\\\\n     * @param _to recepient address\\\\n     * @param _amount token amount\\\\n     */\\\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\\\n        _mint(_to, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get strategy debt amount for a specific strategy token amount\\\\n     * @param _strategyAmount strategy amount\\\\n     * @return debt amount\\\\n     */\\\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the vault composition of the strategy \\\\n     * @return operator\\\\n     * @return nft collateral id\\\\n     * @return collateral amount\\\\n     * @return short amount\\\\n     */\\\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\\\n\\\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\\\n    }\\\\n}\\\\n\\\\n\\\",\\\"keccak256\\\":\\\"0xa18ad4c34899e27bdf048a866834e05dda91ee8ff904fac23587dddf69a5d675\\\",\\\"license\\\":\\\"GPL-3.0-only\\\"},\\\"contracts/strategy/base/StrategyFlashSwap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n\\\\n// interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n// lib\\\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\\\n\\\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\\\n    using Path for bytes;\\\\n    using SafeCast for uint256;\\\\n    using LowGasSafeMath for uint256;\\\\n    using LowGasSafeMath for int256;\\\\n\\\\n    /// @dev Uniswap factory address\\\\n    address public immutable factory;\\\\n\\\\n    struct SwapCallbackData {\\\\n        bytes path;\\\\n        address caller;\\\\n        uint8 callSource;\\\\n        bytes callData;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev constructor\\\\n     * @param _factory uniswap factory address\\\\n     */\\\\n    constructor(\\\\n        address _factory\\\\n    ) {\\\\n        require(_factory != address(0), \\\\\\\"invalid factory address\\\\\\\");\\\\n        factory = _factory;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice uniswap swap callback function for flashes\\\\n     * @param amount0Delta amount of token0\\\\n     * @param amount1Delta amount of token1\\\\n     * @param _data callback data encoded as SwapCallbackData struct\\\\n     */\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata _data\\\\n    ) external override {\\\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\\\n\\\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //ensure that callback comes from uniswap pool\\\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\\\n\\\\n        //determine the amount that needs to be repaid as part of the flashswap\\\\n        uint256 amountToPay =\\\\n            amount0Delta > 0\\\\n                ?  uint256(amount0Delta)\\\\n                :  uint256(amount1Delta);\\\\n        \\\\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountIn amount to sell\\\\n     * @param _amountOutMinimum minimum amount to receive\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountOut = _exactInputInternal(\\\\n            _amountIn,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n       \\\\n        //slippage limit check\\\\n        require(amountOut >= _amountOutMinimum, \\\\\\\"amount out less than min\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\\\n     * @param _tokenIn token address to sell\\\\n     * @param _tokenOut token address to receive\\\\n     * @param _fee pool fee\\\\n     * @param _amountOut exact amount to receive\\\\n     * @param _amountInMaximum maximum amount to sell\\\\n     * @param _callSource function call source\\\\n     * @param _data arbitrary data assigned with the call \\\\n     */\\\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\\\n        uint256 amountIn = _exactOutputInternal(\\\\n            _amountOut,\\\\n            address(this),\\\\n            uint160(0),\\\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\\\n        );\\\\n        \\\\n        //slippage limit check\\\\n        require(amountIn <= _amountInMaximum, \\\\\\\"amount in greater than max\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice function to be called by uniswap callback. \\\\n     * @dev this function should be overridden by the child contract\\\\n     * param _caller initial strategy function caller\\\\n     * param _tokenIn token address sold\\\\n     * param _tokenOut token address bought\\\\n     * param _fee pool fee\\\\n     * param _amountToPay amount to pay for the pool second token\\\\n     * param _callData arbitrary data assigned with the flashswap call \\\\n     * param _callSource function call source\\\\n     */\\\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\\\n    \\\\n    /** \\\\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\\\n    * @param _amountIn amount of token to pay\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token bought (amountOut)\\\\n    */\\\\n    function _exactInputInternal(\\\\n        uint256 _amountIn,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\\\n       \\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n\\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0, int256 amount1) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                _amountIn.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n        \\\\n        //determine the amountOut based on which token has a lower address\\\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\\\n    * @param _amountOut amount of token to receive\\\\n    * @param _recipient recipient for receive\\\\n    * @param _sqrtPriceLimitX96 price limit\\\\n    * @return amount of token sold (amountIn)\\\\n    */\\\\n    function _exactOutputInternal(\\\\n        uint256 _amountOut,\\\\n        address _recipient,\\\\n        uint160 _sqrtPriceLimitX96,\\\\n        SwapCallbackData memory data\\\\n    ) private returns (uint256) {\\\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\\\n\\\\n        //uniswap token0 has a lower address than token1\\\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\\\n        //zeroForOne determines which token is being sold and which is being bought\\\\n        bool zeroForOne = tokenIn < tokenOut;\\\\n        \\\\n        //swap on uniswap, including data to trigger call back for flashswap\\\\n        (int256 amount0Delta, int256 amount1Delta) =\\\\n            _getPool(tokenIn, tokenOut, fee).swap(\\\\n                _recipient,\\\\n                zeroForOne,\\\\n                -_amountOut.toInt256(),\\\\n                _sqrtPriceLimitX96 == 0\\\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\\\n                    : _sqrtPriceLimitX96,\\\\n                abi.encode(data)\\\\n            );\\\\n\\\\n        //determine the amountIn and amountOut based on which token has a lower address\\\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\\\n        // it's technically possible to not receive the full output amount,\\\\n        // so if no price limit has been specified, require this possibility away\\\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\\\n\\\\n        return amountIn;\\\\n    }\\\\n\\\\n    /** \\\\n    * @notice returns the uniswap pool for the given token pair and fee\\\\n    * @dev the pool contract may or may not exist\\\\n    * @param tokenA address of first token \\\\n    * @param tokenB address of second token \\\\n    * @param fee fee tier for pool\\\\n    */\\\\n    function _getPool(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal view returns (IUniswapV3Pool) {\\\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x91b49caf229fd114fbb589e73056772cf15a0adaba0a6f5eca4dff9cd12b9575\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/strategy/base/StrategyMath.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: AGPL-3.0-only\\\\n\\\\n/// math.sol -- mixin for inline numerical wizardry\\\\n\\\\n// This program is free software: you can redistribute it and/or modify\\\\n// it under the terms of the GNU General Public License as published by\\\\n// the Free Software Foundation, either version 3 of the License, or\\\\n// (at your option) any later version.\\\\n\\\\n// This program is distributed in the hope that it will be useful,\\\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\\\n// GNU General Public License for more details.\\\\n\\\\n// You should have received a copy of the GNU General Public License\\\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\\\n\\\\npragma solidity >0.4.13;\\\\n\\\\n\\\\n/**\\\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\\\n * @dev change contract to library, added div() function\\\\n */\\\\nlibrary StrategyMath {\\\\n    function add(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x + y) >= x, \\\\\\\"ds-math-add-overflow\\\\\\\");\\\\n    }\\\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\\\n        require((z = x - y) <= x, \\\\\\\"ds-math-sub-underflow\\\\\\\");\\\\n    }\\\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\\\n        require(y == 0 || (z = x * y) / y == x, \\\\\\\"ds-math-mul-overflow\\\\\\\");\\\\n    }\\\\n\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    function min(uint x, uint y) internal pure returns (uint z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function max(uint x, uint y) internal pure returns (uint z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n    function imin(int x, int y) internal pure returns (int z) {\\\\n        return x <= y ? x : y;\\\\n    }\\\\n    function imax(int x, int y) internal pure returns (int z) {\\\\n        return x >= y ? x : y;\\\\n    }\\\\n\\\\n    uint constant WAD = 10 ** 18;\\\\n    uint constant RAY = 10 ** 27;\\\\n\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), WAD / 2) / WAD;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, y), RAY / 2) / RAY;\\\\n    }\\\\n    //rounds to zero if x*y < WAD / 2\\\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, WAD), y / 2) / y;\\\\n    }\\\\n    //rounds to zero if x*y < RAY / 2\\\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\\\n        z = add(mul(x, RAY), y / 2) / y;\\\\n    }\\\\n\\\\n    // Ceil A to a multiple m\\\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(sub(add(a, m), 1), m), m);\\\\n    }\\\\n\\\\n    // Floor A to a multiple m\\\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\\\n        z = mul(div(a, m), m);\\\\n    }\\\\n\\\\n    // This famous algorithm is called \\\\\\\"exponentiation by squaring\\\\\\\"\\\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\\\n    //\\\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\\\n    //\\\\n    // These facts are why it works:\\\\n    //\\\\n    //  If n is even, then x^n = (x^2)^(n/2).\\\\n    //  If n is odd,  then x^n = x * x^(n-1),\\\\n    //   and applying the equation for even x gives\\\\n    //    x^n = x * (x^2)^((n-1) / 2).\\\\n    //\\\\n    //  Also, EVM division is flooring and\\\\n    //    floor[(n-1) / 2] = floor[n / 2].\\\\n    //\\\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\\\n        z = n % 2 != 0 ? x : RAY;\\\\n\\\\n        for (n /= 2; n != 0; n /= 2) {\\\\n            x = rmul(x, x);\\\\n\\\\n            if (n % 2 != 0) {\\\\n                z = rmul(z, x);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\",\\\"keccak256\\\":\\\"0xfec6fa07fbbb639f94321d6503f5363286776cf831215017ce28aae67295613b\\\",\\\"license\\\":\\\"AGPL-3.0-only\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x61022060405266b1a2bc2ec50000600955600a805463ffffffff19166101a41790553480156200002e57600080fd5b506040516200621538038062006215833981016040819052620000519162000669565b60405180604001604052806007815260200166437261624f544360c81b815250604051806040016040528060018152602001601960f91b815250878b8a6040518060400160405280601081526020016f21b930b11029ba3930ba32b3bc903b1960811b8152506040518060400160405280600681526020016521b930b13b1960d11b81525081818160039080519060200190620000f09291906200057c565b508051620001069060049060208401906200057c565b50506005805460ff19166012179055506001600160a01b038416620001485760405162461bcd60e51b81526004016200013f90620007af565b60405180910390fd5b6001600160a01b038316620001715760405162461bcd60e51b81526004016200013f90620007e6565b606083901b6001600160601b03191660805260058054610100600160a81b0319166101006001600160a01b0387811682029290921792839055604080516307f07b1360e41b815290519190930490911691637f07b130916004808301926020929190829003018186803b158015620001e857600080fd5b505afa158015620001fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000223919062000645565b6001600160601b031960609190911b1660a052600554604051630728cf2360e31b81526101009091046001600160a01b0316906339467918906200027190600090819081906004016200072a565b602060405180830381600087803b1580156200028c57600080fd5b505af1158015620002a1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002c7919062000711565b60c052505050506001600160a01b038116620002f75760405162461bcd60e51b81526004016200013f906200075c565b60601b6001600160601b03191660e052600160065560006200031862000510565b600780546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35081516020808401919091208251918301919091206101408290526101608190527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620003b162000514565b61012052620003c281848462000518565b6101005261018052505050506001600160a01b038816620003f75760405162461bcd60e51b81526004016200013f9062000855565b6001600160a01b038416620004205760405162461bcd60e51b81526004016200013f906200081d565b6001600160a01b038516620004495760405162461bcd60e51b81526004016200013f9062000871565b6001600160a01b038316620004725760405162461bcd60e51b81526004016200013f9062000740565b60008211620004955760405162461bcd60e51b81526004016200013f9062000793565b600081118015620004ae5750670de0b6b3a76400008111155b620004cd5760405162461bcd60e51b81526004016200013f9062000839565b6001600160601b0319606098891b81166101c05294881b85166101a052600b91909155600c5590851b82166101e05290931b90921661020052506200088d915050565b3390565b4690565b60008383836200052762000514565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620005b45760008555620005ff565b82601f10620005cf57805160ff1916838001178555620005ff565b82800160010185558215620005ff579182015b82811115620005ff578251825591602001919060010190620005e2565b506200060d92915062000611565b5090565b5b808211156200060d576000815560010162000612565b80516001600160a01b03811681146200064057600080fd5b919050565b60006020828403121562000657578081fd5b620006628262000628565b9392505050565b60008060008060008060008060006101208a8c03121562000688578485fd5b620006938a62000628565b9850620006a360208b0162000628565b9750620006b360408b0162000628565b9650620006c360608b0162000628565b9550620006d360808b0162000628565b9450620006e360a08b0162000628565b9350620006f360c08b0162000628565b925060e08a015191506101008a015190509295985092959850929598565b60006020828403121562000723578081fd5b5051919050565b9283526020830191909152604082015260600190565b602080825260029082015261219b60f11b604082015260600190565b60208082526017908201527f696e76616c696420666163746f72792061646472657373000000000000000000604082015260600190565b602080825260029082015261433760f01b604082015260600190565b6020808252601a908201527f696e76616c696420636f6e74726f6c6c65722061646472657373000000000000604082015260600190565b60208082526014908201527f696e76616c696420776574682061646472657373000000000000000000000000604082015260600190565b60208082526002908201526110cd60f21b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b602080825260029082015261433360f01b604082015260600190565b602080825260029082015261433560f01b604082015260600190565b60805160601c60a05160601c60c05160e05160601c61010051610120516101405161016051610180516101a05160601c6101c05160601c6101e05160601c6102005160601c615820620009f560003980610bb55280611d54525080611b495280611d2752508061119852806129395280612ace52806144a2525080610f4452806129665280612afb52806144c352508061264852508061268a5250806126695250806125ef52508061261f525080611a5f5280611fc45280614463525080610cb65280610fb6528061146e5280611c485280611cee5280612859528061328d5280613b3a5250806111bc52806118df52806120b052806129885280612b1d5280613329528061357952806136ad5280613a8152806144e452508061037f5280610f2052806118be52806120d152806129aa5280612b3f5280612e345280612ed65280612f6e5280612ff35280613465528061376152806137e7528061450552506158206000f3fe60806040526004361061036f5760003560e01c80637f07b130116101c6578063cae74029116100f7578063e9c3cb4f11610095578063f5d278e41161006f578063f5d278e41461095e578063f73e19c314610973578063fa461e3314610993578063fc5b73ff146109b3576103e1565b8063e9c3cb4f14610914578063f101d92f14610929578063f2fde38b1461093e576103e1565b8063d2dd9f79116100d1578063d2dd9f79146108ac578063d33219b4146108cc578063dcbab608146108e1578063dd62ed3e146108f4576103e1565b8063cae740291461087a578063cfa70b181461088f578063d0e30db0146108a4576103e1565b8063a457c2d711610164578063b52b7ff01161013e578063b52b7ff014610810578063bdd438b814610830578063c245168914610850578063c45a015514610865576103e1565b8063a457c2d7146107b0578063a9059cbb146107d0578063b24f719b146107f0576103e1565b80638f8b8dbc116101a05780638f8b8dbc1461074657806395d89b41146107665780639ff69a511461077b578063a319b29f1461079b576103e1565b80637f07b1301461070757806388626eb81461071c5780638da5cb5b14610731576103e1565b80633d65fdac116102a057806366a91b761161023e57806370a082311161021857806370a082311461069d578063715018a6146106bd5780637bcdc16e146106d25780637dc0d1d0146106f2576103e1565b806366a91b761461065e57806367b8c345146106735780636c1040a914610688576103e1565b80634d76e6fc1161027a5780634d76e6fc146105ef578063502e1a1614610604578063533092ef1461062457806363bbc4b614610649576103e1565b80633d65fdac146105a55780633dcb0c5d146105c55780633fc8cef3146105da576103e1565b8063313ce5671161030d578063392e53cd116102e7578063392e53cd1461052e5780633950935114610543578063395ebb69146105635780633d3a62ee14610585576103e1565b8063313ce567146104e257806333194c0a146105045780633644e51514610519576103e1565b806318160ddd1161034957806318160ddd1461045e57806323b872dd14610480578063281e78d1146104a05780632e1a7d4d146104c2576103e1565b806306fdde03146103e6578063095ea7b3146104115780630ca514cd1461043e576103e1565b366103e157336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103ba575060055461010090046001600160a01b031633145b6103df5760405162461bcd60e51b81526004016103d69061547e565b60405180910390fd5b005b600080fd5b3480156103f257600080fd5b506103fb6109c6565b604051610408919061511f565b60405180910390f35b34801561041d57600080fd5b5061043161042c366004614a72565b610a5d565b60405161040891906150d3565b34801561044a57600080fd5b506103df610459366004614cd2565b610a7b565b34801561046a57600080fd5b50610473610b25565b6040516104089190614fab565b34801561048c57600080fd5b5061043161049b366004614a32565b610b2b565b3480156104ac57600080fd5b506104b5610bb3565b6040516104089190614fb4565b3480156104ce57600080fd5b506103df6104dd366004614cd2565b610bd7565b3480156104ee57600080fd5b506104f7610cab565b604051610408919061559b565b34801561051057600080fd5b50610473610cb4565b34801561052557600080fd5b50610473610cd8565b34801561053a57600080fd5b50610431610ce7565b34801561054f57600080fd5b5061043161055e366004614a72565b610cf8565b34801561056f57600080fd5b50610578610d46565b604051610408919061558a565b34801561059157600080fd5b506103df6105a0366004614cd2565b610d4c565b3480156105b157600080fd5b506103df6105c0366004614cd2565b610ee4565b3480156105d157600080fd5b506104b5610f0a565b3480156105e657600080fd5b506104b5610f1e565b3480156105fb57600080fd5b506104b5610f42565b34801561061057600080fd5b5061043161061f366004614a72565b610f66565b34801561063057600080fd5b50610639610f86565b6040516104089493929190615078565b34801561065557600080fd5b50610473610fa2565b34801561066a57600080fd5b50610473610fa8565b34801561067f57600080fd5b50610473610fae565b34801561069457600080fd5b50610473610fb4565b3480156106a957600080fd5b506104736106b83660046149c2565b610fd8565b3480156106c957600080fd5b506103df610ff7565b3480156106de57600080fd5b506103df6106ed366004614cd2565b6110c2565b3480156106fe57600080fd5b506104b5611196565b34801561071357600080fd5b506104b56111ba565b34801561072857600080fd5b506104316111de565b34801561073d57600080fd5b506104b56111e8565b34801561075257600080fd5b506103df610761366004614ef1565b6111f7565b34801561077257600080fd5b506103fb6112d7565b34801561078757600080fd5b506103df610796366004614cd2565b611338565b3480156107a757600080fd5b506103df611409565b3480156107bc57600080fd5b506104316107cb366004614a72565b6114ca565b3480156107dc57600080fd5b506104316107eb366004614a72565b611532565b3480156107fc57600080fd5b506103df61080b366004614d2d565b611546565b34801561081c57600080fd5b506103df61082b366004614e83565b61184f565b34801561083c57600080fd5b506103df61084b366004614cd2565b611976565b34801561085c57600080fd5b50610431611a53565b34801561087157600080fd5b506104b5611a5d565b34801561088657600080fd5b50610473611a81565b34801561089b57600080fd5b50610473611a87565b6103df611a93565b3480156108b857600080fd5b506103df6108c73660046149c2565b611b3e565b3480156108d857600080fd5b506104b5611d25565b6103df6108ef366004614eb7565b611d49565b34801561090057600080fd5b5061047361090f3660046149fa565b611e0f565b34801561092057600080fd5b50610473611e3a565b34801561093557600080fd5b50610473611e40565b34801561094a57600080fd5b506103df6109593660046149c2565b611e46565b34801561096a57600080fd5b50610578611f68565b34801561097f57600080fd5b5061047361098e366004614cd2565b611f74565b34801561099f57600080fd5b506103df6109ae366004614adc565b611f7f565b6103df6109c1366004614d02565b612025565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b820191906000526020600020905b815481529060010190602001808311610a3557829003601f168201915b505050505090505b90565b6000610a71610a6a612172565b8484612176565b5060015b92915050565b610a83612172565b6001600160a01b0316610a946111e8565b6001600160a01b031614610aef576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff16610b195760405162461bcd60e51b81526004016103d6906151f7565b610b2281612262565b50565b60025490565b6000610b38848484612297565b610ba884610b44612172565b610ba385604051806060016040528060288152602001615734602891396001600160a01b038a16600090815260016020526040812090610b82612172565b6001600160a01b0316815260208101919091526040016000205491906123f2565b612176565b5060015b9392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60026006541415610c2f576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610c3f82612489565b90506000610c5033848460006124b4565b9050610c5c3382612501565b336001600160a01b03167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94848484604051610c9993929190615574565b60405180910390a25050600160065550565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce26125eb565b905090565b600a54640100000000900460ff1681565b6000610a71610d05612172565b84610ba38560016000610d16612172565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906126b5565b6101a481565b60026006541415610da4576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600681905550600560019054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610dfc57600080fd5b505af1158015610e10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e349190614a9d565b610e505760405162461bcd60e51b81526004016103d6906153ee565b600f5460ff16610e725760405162461bcd60e51b81526004016103d6906152aa565b6000610e8582610e80610b25565b61270f565b90506000610e93824761271b565b9050610e9f3384612727565b610ea93382612501565b336001600160a01b03167fe9ab9870b9093d99f8e981919f65ad09b7ae90ff80f1031639af9e0357eb9ed68483604051610c99929190615549565b33600090815260106020908152604080832093835292905220805460ff19166001179055565b60055461010090046001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b601060209081526000928352604080842090915290825290205460ff1681565b600080600080610f94612823565b935093509350935090919293565b600e5481565b600b5481565b600d5481565b7f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0381166000908152602081905260409020545b919050565b610fff612172565b6001600160a01b03166110106111e8565b6001600160a01b03161461106b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6007546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36007805473ffffffffffffffffffffffffffffffffffffffff19169055565b6110ca612172565b6001600160a01b03166110db6111e8565b6001600160a01b031614611136576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081116111565760405162461bcd60e51b81526004016103d69061540b565b600b8190556040517f28e0e4ee0b14d4b056ce88e1bcd890ccd32b22e213723c8765901381b5eae7059061118b908390614fab565b60405180910390a150565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce261291a565b6007546001600160a01b031690565b6111ff612172565b6001600160a01b03166112106111e8565b6001600160a01b03161461126b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60b48163ffffffff1610156112925760405162461bcd60e51b81526004016103d690615169565b600a805463ffffffff191663ffffffff83161790556040517f1cd9c7f99a5530a38c8f2b387dcc78e8a76cb5b203e0c4316a66777d993dee359061118b90839061558a565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b611340612172565b6001600160a01b03166113516111e8565b6001600160a01b0316146113ac576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6702c68af0bb1400008111156113d45760405162461bcd60e51b81526004016103d6906153d1565b60098190556040517f829c71710efa317bbdb8e5c4ca2b6d2551b7c2d7d37ea199975807eb3f5c0e7c9061118b908390614fab565b600a54640100000000900460ff166114335760405162461bcd60e51b81526004016103d6906151f7565b600f8054600160ff19909116179055600554604051634bf7d4a160e11b81526101009091046001600160a01b0316906397efa94290611496907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b600060405180830381600087803b1580156114b057600080fd5b505af11580156114c4573d6000803e3d6000fd5b50505050565b6000610a716114d7612172565b84610ba3856040518060600160405280602581526020016157c66025913960016000611501612172565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906123f2565b6000610a7161153f612172565b8484612297565b61154e612172565b6001600160a01b031661155f6111e8565b6001600160a01b0316146115ba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff166115e45760405162461bcd60e51b81526004016103d6906151f7565b600083116116045760405162461bcd60e51b81526004016103d690615398565b61160c612a90565b8061161a575061161a61291a565b6116365760405162461bcd60e51b81526004016103d690615444565b6116408383612ab1565b42600d55600e839055805184906000908390829061165a57fe5b602002602001015160600151905060008360008151811061167757fe5b602002602001015160600151905060008460008151811061169457fe5b602002602001015160800151905080151586151514156116c65760405162461bcd60e51b81526004016103d690615324565b60005b85518110156117ef578581815181106116de57fe5b60200260200101516060015192508115158682815181106116fb57fe5b6020026020010151608001511515146117265760405162461bcd60e51b81526004016103d690615427565b8615611751578383101561174c5760405162461bcd60e51b81526004016103d690615341565b611771565b838311156117715760405162461bcd60e51b81526004016103d690615341565b829350611792858988848151811061178557fe5b6020026020010151612c71565b85818151811061179e57fe5b6020026020010151604001518511156117e2576117db8682815181106117c057fe5b602002602001015160400151866130e390919063ffffffff16565b94506117e7565b6117ef565b6001016116c9565b507fbbc3ba742efe346cfdf333000069964e0ee3087c68da267dac977d299f2366fb8560008151811061181e57fe5b60200260200101516000015189888a60405161183d9493929190615557565b60405180910390a15050505050505050565b600260065414156118a7576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560006118b784612489565b90506119287f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084848760018a6040516020016119149190614fab565b60405160208183030381529060405261313b565b336001600160a01b03167fa13b272c1cf13ba724064d3d4809d9f557aab8da2bb582cba031a2f57e728e9d8583604051611963929190615549565b60405180910390a2505060016006555050565b61197e612172565b6001600160a01b031661198f6111e8565b6001600160a01b0316146119ea576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081118015611a025750670de0b6b3a76400008111155b611a1e5760405162461bcd60e51b81526004016103d6906154d4565b600c8190556040517f789e4b8ad1c375952cea7f07c9b3b6619a84b406432b948246cecb8ced96b9fa9061118b908390614fab565b6000610ce2612a90565b7f000000000000000000000000000000000000000000000000000000000000000081565b60085481565b6702c68af0bb14000081565b60026006541415611aeb576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065534600080611aff3384836131bc565b91509150336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158383604051610c99929190615549565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611b865760405162461bcd60e51b81526004016103d6906153b5565b600a54640100000000900460ff16611bb05760405162461bcd60e51b81526004016103d6906151f7565b600560019054906101000a90046001600160a01b03166001600160a01b0316639d4c94426040518163ffffffff1660e01b815260040160206040518083038186803b158015611bfe57600080fd5b505afa158015611c12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3691906149de565b6001600160a01b03166342842e0e30837f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401611c8593929190614fc8565b600060405180830381600087803b158015611c9f57600080fd5b505af1158015611cb3573d6000803e3d6000fd5b50505050611cc16000612262565b806001600160a01b03167fae97956757017853415251f661bfe857898f44ddb9c90b2483065719b84b0c697f0000000000000000000000000000000000000000000000000000000000000000604051611d1a9190614fab565b60405180910390a250565b7f000000000000000000000000000000000000000000000000000000000000000081565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611d915760405162461bcd60e51b81526004016103d69061528d565b600a54640100000000900460ff1615611dbc5760405162461bcd60e51b81526004016103d69061535e565b611dc581612262565b34611dd1816000613230565b600d849055600e839055611de8338783600061325f565b611df233866133b9565b5050600a805464ff00000000191664010000000017905550505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60095481565b600c5481565b611e4e612172565b6001600160a01b0316611e5f6111e8565b6001600160a01b031614611eba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611eff5760405162461bcd60e51b81526004018080602001828103825260268152602001806156486026913960400191505060405180910390fd5b6007546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600a5463ffffffff1681565b6000610a7582612489565b6000841380611f8e5750600083135b611f9757600080fd5b6000611fa582840184614b72565b90506000806000611fb984600001516133c3565b925092509250611feb7f00000000000000000000000000000000000000000000000000000000000000008484846133f4565b506000808913611ffb5787611ffd565b885b905061201a8560200151858585858a606001518b60400151613413565b505050505050505050565b6002600654141561207d576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560008061208d6138ec565b9150915061209b8482613230565b60006120a8858484613906565b5090506121237f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086846120fc8a346130e3565b60008b60405160200161210f9190614fab565b604051602081830303815290604052613995565b336001600160a01b03167f5d85169ff8329e90f3225f9798e0eba54d00c55d3bbfe201a0d1606febb23a8e868360405161215e929190615549565b60405180910390a250506001600655505050565b3390565b6001600160a01b0383166121bb5760405162461bcd60e51b81526004018080602001828103825260248152602001806157a26024913960400191505060405180910390fd5b6001600160a01b0382166122005760405162461bcd60e51b815260040180806020018281038252602281526020018061566e6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60088190556040517f29600e2e028c8c5c2b112d021938e0d0237d8fafcbb20394c56cf9fa4661ca279061118b908390614fab565b6001600160a01b0383166122dc5760405162461bcd60e51b815260040180806020018281038252602581526020018061577d6025913960400191505060405180910390fd5b6001600160a01b0382166123215760405162461bcd60e51b81526004018080602001828103825260238152602001806156036023913960400191505060405180910390fd5b61232c8383836125e6565b61236981604051806060016040528060268152602001615690602691396001600160a01b03861660009081526020819052604090205491906123f2565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461239890826126b5565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156124815760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561244657818101518382015260200161242e565b50505050905090810190601f1680156124735780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600080612494612823565b9350505050610bac6124a4610b25565b6124ae8386613a0c565b90613a45565b6000806124bf6138ec565b91505060006124d086610e80610b25565b905060006124de828461271b565b90506124ec88878388613a65565b6124f68888612727565b979650505050505050565b80471015612556576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146125a1576040519150601f19603f3d011682016040523d82523d6000602084013e6125a6565b606091505b50509050806125e65760405162461bcd60e51b815260040180806020018281038252603a8152602001806156b6603a913960400191505060405180910390fd5b505050565b60007f0000000000000000000000000000000000000000000000000000000000000000612616613b94565b141561264357507f0000000000000000000000000000000000000000000000000000000000000000610a5a565b6126ae7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000613b98565b9050610a5a565b600082820183811015610bac576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610bac8383613a45565b6000610bac8284613a0c565b6001600160a01b03821661276c5760405162461bcd60e51b815260040180806020018281038252602181526020018061575c6021913960400191505060405180910390fd5b612778826000836125e6565b6127b581604051806060016040528060228152602001615626602291396001600160a01b03851660009081526020819052604090205491906123f2565b6001600160a01b0383166000908152602081905260409020556002546127db9082613bfa565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600554604051634632752560e11b8152600091829182918291829161010090046001600160a01b031690638c64ea4a90612881907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b60806040518083038186803b15801561289957600080fd5b505afa1580156128ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d19190614c30565b805160208201516040830151606090930151919863ffffffff90911697506bffffffffffffffffffffffff90921695506fffffffffffffffffffffffffffffffff169350915050565b600a5460405163cce79bd560e01b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd5916129de917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff90911690600190600401614fec565b60206040518083038186803b1580156129f657600080fd5b505afa158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190614cea565b90506000612a47600e5483613a4590919063ffffffff16565b90506000670de0b6b3a76400008211612a7157612a6c670de0b6b3a7640000836130e3565b612a83565b612a8382670de0b6b3a76400006130e3565b600c541115935050505090565b6000612aa9600b54600d54613c5790919063ffffffff16565b421015905090565b600a5460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591612b71917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff1690600190600401614fec565b60206040518083038186803b158015612b8957600080fd5b505afa158015612b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc19190614cea565b90508115612c2657612c02670de0b6b3a7640000612bfc612bf5600954670de0b6b3a7640000613c5790919063ffffffff16565b8490613caf565b90613d1b565b831115612c215760405162461bcd60e51b81526004016103d6906152c7565b6125e6565b612c52670de0b6b3a7640000612bfc612bf5600954670de0b6b3a76400006130e390919063ffffffff16565b8310156125e65760405162461bcd60e51b81526004016103d690615230565b806080015115612ca4578060600151821115612c9f5760405162461bcd60e51b81526004016103d69061549a565b612cc8565b8060600151821015612cc85760405162461bcd60e51b81526004016103d69061537b565b612cda81602001518260c00151613d7a565b60007fc8aea8e60353611f3ed5409dad2d3173390bd252431198e7300eda67fefb66b1826000015183602001518460400151856060015186608001518760a001518860c00151604051602001612d379897969594939291906150de565b6040516020818303038152906040528051906020012090506000612d5a82613dee565b90506000612d78828560e00151866101000151876101200151613e3a565b905083602001516001600160a01b0316816001600160a01b031614612daf5760405162461bcd60e51b81526004016103d690615461565b428460a001511015612dd35760405162461bcd60e51b81526004016103d690615186565b8360400151861015612de757604084018690525b6000612e0c670de0b6b3a7640000612bfc888860400151613caf90919063ffffffff16565b9050846080015115612f575760208501516040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916323b872dd91612e6c919030908690600401614fc8565b602060405180830381600087803b158015612e8657600080fd5b505af1158015612e9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ebe9190614a9d565b50604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612f0b908490600401614fab565b600060405180830381600087803b158015612f2557600080fd5b505af1158015612f39573d6000803e3d6000fd5b50505050612f528560200151866040015183600061325f565b613085565b612f6c85602001518660400151836000613a65565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612fc757600080fd5b505af1158015612fdb573d6000803e3d6000fd5b50505050602086015160405163a9059cbb60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063a9059cbb9161303191859060040161505f565b602060405180830381600087803b15801561304b57600080fd5b505af115801561305f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130839190614a9d565b505b7f68c36f17c620d197a81d3aeff305f83abf3bb29943a38cd6efc299041238652d856020015186600001518760400151886060015189608001518b6040516130d29695949392919061509e565b60405180910390a150505050505050565b80820382811115610a75576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b60006131908530600060405180608001604052808c8c8f60405160200161316493929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052613faf565b9050838111156131b25760405162461bcd60e51b81526004016103d6906151c0565b5050505050505050565b6000806000806131ca6138ec565b915091506131d88682613230565b6000806131e6888585613906565b909250905060006132086131fa8a846130e3565b85613203610b25565b61411c565b90506132168a848b8b61325f565b6132208a826133b9565b9199919850909650505050505050565b60085461323d8284613c57565b111561325b5760405162461bcd60e51b81526004016103d690615213565b5050565b600554604051630728cf2360e31b81526101009091046001600160a01b03169063394679189084906132ba907f0000000000000000000000000000000000000000000000000000000000000000908890600090600401615574565b6020604051808303818588803b1580156132d357600080fd5b505af11580156132e7573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061330c9190614cea565b50806114c45760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613360908790879060040161505f565b602060405180830381600087803b15801561337a57600080fd5b505af115801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b29190614a9d565b5050505050565b61325b828261416b565b600080806133d1848261425b565b92506133de846014614327565b90506133eb84601761425b565b91509193909250565b600061340a856134058686866143e3565b614439565b95945050505050565b60008160ff16600181111561342457fe5b600181111561342f57fe5b14156136665760008280602001905181019061344b9190614b57565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906134a2903090600401614fb4565b60206040518083038186803b1580156134ba57600080fd5b505afa1580156134ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f29190614cea565b6040518263ffffffff1660e01b815260040161350e9190614fab565b600060405180830381600087803b15801561352857600080fd5b505af115801561353c573d6000803e3d6000fd5b5050505061355088826000015160016131bc565b5050600061355f88888861445c565b60405163a9059cbb60e01b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906135b0908490899060040161505f565b602060405180830381600087803b1580156135ca57600080fd5b505af11580156135de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136029190614a9d565b50886001600160a01b03167fc355ebece16d7e85e486911f0cde1074bc4bd3fec251c88cdddc7076d3e99adb864760405161363e929190615549565b60405180910390a2471561365f5761365f6001600160a01b038a1647612501565b50506138e3565b60018160ff16600181111561367757fe5b600181111561368257fe5b14156138e35760008280602001905181019061369e9190614b57565b9050600061374e8983600001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016136f79190614fb4565b60206040518083038186803b15801561370f57600080fd5b505afa158015613723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137479190614cea565b60016124b4565b9050600061375d89898961445c565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b1580156137ba57600080fd5b505af11580156137ce573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250613821915084908a9060040161505f565b602060405180830381600087803b15801561383b57600080fd5b505af115801561384f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138739190614a9d565b50600061388083886130e3565b90508a6001600160a01b03167f6f3269a64126ef2a1959892f3d921e81865181e09a7f72f55d3a49550c53b48d88836040516138bd929190615549565b60405180910390a280156138de576138de6001600160a01b038c1682612501565b505050505b50505050505050565b6000806000806138fa612823565b96509450505050509091565b60008060008061391461449a565b9050600086158015613924575085155b80156139365750613933610b25565b15155b905080156139565760405162461bcd60e51b81526004016103d6906151a3565b61397761396d6139668985613a0c565b8890613c57565b6124ae8a8a613a0c565b925060006139858484613a0c565b9399939850929650505050505050565b60006139ea8530600060405180608001604052808d8c8e6040516020016139be93929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526145d1565b9050838110156131b25760405162461bcd60e51b81526004016103d690615132565b6000670de0b6b3a7640000613a36613a248585613caf565b6002670de0b6b3a76400005b04613c57565b81613a3d57fe5b049392505050565b600081613a36613a5d85670de0b6b3a7640000613caf565b600285613a30565b80613b0e576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90613aba90879030908890600401614fc8565b602060405180830381600087803b158015613ad457600080fd5b505af1158015613ae8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b0c9190614a9d565b505b600554604051638632cb0360e01b81526101009091046001600160a01b031690638632cb0390613b66907f00000000000000000000000000000000000000000000000000000000000000009087908790600401615574565b600060405180830381600087803b158015613b8057600080fd5b505af11580156131b2573d6000803e3d6000fd5b4690565b6000838383613ba5613b94565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b600082821115613c51576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b80820182811015610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000811580613cca57505080820282828281613cc757fe5b04145b610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000808211613d71576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613a3d57fe5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff1615613dbe5760405162461bcd60e51b81526004016103d6906154b7565b6001600160a01b03909116600090815260106020908152604080832093835292905220805460ff19166001179055565b6000613df86125eb565b82604051602001808061190160f01b81525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613e9b5760405162461bcd60e51b81526004018080602001828103825260228152602001806156f06022913960400191505060405180910390fd5b8360ff16601b1480613eb057508360ff16601c145b613eeb5760405162461bcd60e51b81526004018080602001828103825260228152602001806157126022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613f47573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661340a576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b600080600080613fc285600001516133c3565b919450925090506001600160a01b0380841690831610600080613fe685878661445c565b6001600160a01b031663128acb088b85613fff8f614710565b6000036001600160a01b038e1615614017578d61403d565b876140365773fffd8963efd1fc6a506488495d951d5263988d2561403d565b6401000276a45b8d60405160200161404e91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161407d959493929190615025565b6040805180830381600087803b15801561409657600080fd5b505af11580156140aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140ce9190614ab9565b91509150600080846140e45782846000036140ea565b83836000035b915091508a6001600160a01b03166000141561410c578c811461410c57600080fd5b509b9a5050505050505050505050565b60008061413361412c8587613c57565b8690613a45565b905082156141625761415a614150670de0b6b3a7640000836130e3565b6124ae8584613a0c565b915050610bac565b50929392505050565b6001600160a01b0382166141c6576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6141d2600083836125e6565b6002546141df90826126b5565b6002556001600160a01b03821660009081526020819052604090205461420590826126b5565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000818260140110156142b5576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b816014018351101561430e576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015614381576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156143da576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6143eb6148c8565b826001600160a01b0316846001600160a01b03161115614409579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b60006144458383614726565b9050336001600160a01b03821614610a7557600080fd5b60006144927f000000000000000000000000000000000000000000000000000000000000000061448d8686866143e3565b614726565b949350505050565b60008061452e7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a46000614822565b90506000600560019054906101000a90046001600160a01b03166001600160a01b031663978bbdb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561458057600080fd5b505afa158015614594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145b89190614cea565b90506145ca612710612bfc8484613caf565b9250505090565b6000806000806145e485600001516133c3565b919450925090506001600160a01b038083169084161060008061460886868661445c565b6001600160a01b031663128acb088b856146218f614710565b6001600160a01b038e1615614636578d61465c565b876146555773fffd8963efd1fc6a506488495d951d5263988d2561465c565b6401000276a45b8d60405160200161466d91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161469c959493929190615025565b6040805180830381600087803b1580156146b557600080fd5b505af11580156146c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146ed9190614ab9565b91509150826146fc57816146fe565b805b6000039b9a5050505050505050505050565b6000600160ff1b821061472257600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b03161061474e57600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b15801561489157600080fd5b505afa1580156148a5573d6000803e3d6000fd5b505050506040513d60208110156148bb57600080fd5b5051979650505050505050565b604080516060810182526000808252602082018190529181019190915290565b8035610ff2816155cd565b8035610ff2816155e2565b600082601f83011261490e578081fd5b813567ffffffffffffffff81111561492257fe5b614935601f8201601f19166020016155a9565b818152846020838601011115614949578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215614974578081fd5b6040516020810181811067ffffffffffffffff8211171561499157fe5b6040529151825250919050565b803562ffffff81168114610ff257600080fd5b803560ff81168114610ff257600080fd5b6000602082840312156149d3578081fd5b8135610bac816155cd565b6000602082840312156149ef578081fd5b8151610bac816155cd565b60008060408385031215614a0c578081fd5b8235614a17816155cd565b91506020830135614a27816155cd565b809150509250929050565b600080600060608486031215614a46578081fd5b8335614a51816155cd565b92506020840135614a61816155cd565b929592945050506040919091013590565b60008060408385031215614a84578182fd5b8235614a8f816155cd565b946020939093013593505050565b600060208284031215614aae578081fd5b8151610bac816155e2565b60008060408385031215614acb578182fd5b505080516020909101519092909150565b60008060008060608587031215614af1578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614b16578384fd5b818701915087601f830112614b29578384fd5b813581811115614b37578485fd5b886020828501011115614b48578485fd5b95989497505060200194505050565b600060208284031215614b68578081fd5b610bac8383614963565b600060208284031215614b83578081fd5b813567ffffffffffffffff80821115614b9a578283fd5b9083019060808286031215614bad578283fd5b604051608081018181108382111715614bc257fe5b604052823582811115614bd3578485fd5b614bdf878286016148fe565b825250614bee602084016148e8565b6020820152614bff604084016149b1565b6040820152606083013582811115614c15578485fd5b614c21878286016148fe565b60608301525095945050505050565b600060808284031215614c41578081fd5b6040516080810181811067ffffffffffffffff82111715614c5e57fe5b6040528251614c6c816155cd565b81526020830151614c7c816155f0565b602082015260408301516bffffffffffffffffffffffff81168114614c9f578283fd5b604082015260608301516fffffffffffffffffffffffffffffffff81168114614cc6578283fd5b60608201529392505050565b600060208284031215614ce3578081fd5b5035919050565b600060208284031215614cfb578081fd5b5051919050565b60008060408385031215614d14578182fd5b82359150614d246020840161499e565b90509250929050565b60008060008060808587031215614d42578182fd5b843593506020808601359350604080870135614d5d816155e2565b9350606087013567ffffffffffffffff80821115614d79578485fd5b818901915089601f830112614d8c578485fd5b813581811115614d9857fe5b614da585868302016155a9565b8181528581019250838601610140808402860188018e1015614dc5578889fd5b8895505b83861015614e6f5780828f031215614ddf578889fd5b614de8816155a9565b82358152614df78984016148e8565b89820152878301358882015260608301356060820152614e19608084016148f3565b608082015260a0838101359082015260c0808401359082015260e0614e3f8185016149b1565b90820152610100838101359082015261012080840135908201528552600195909501949387019390810190614dc9565b505080965050505050505092959194509250565b600080600060608486031215614e97578081fd5b8335925060208401359150614eae6040850161499e565b90509250925092565b600080600080600060a08688031215614ece578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b600060208284031215614f02578081fd5b8135610bac816155f0565b60008151808452815b81811015614f3257602081850181015186830182015201614f16565b81811115614f435782602083870101525b50601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b90815260200190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a060808301526124f660a0830184614f0d565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b039690961686526020860194909452604085019290925260608401521515608083015260a082015260c00190565b901515815260200190565b97885260208801969096526001600160a01b0394909416604087015260608601929092526080850152151560a084015260c083015260e08201526101000190565b600060208252610bac6020830184614f0d565b60208082526018908201527f616d6f756e74206f7574206c657373207468616e206d696e0000000000000000604082015260600190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b6020808252601a908201527f616d6f756e7420696e2067726561746572207468616e206d6178000000000000604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526027908201527f507269636520746f6f206c6f772072656c617469766520746f20556e6973776160408201527f7020747761702e00000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526204331360ec1b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526028908201527f507269636520746f6f20686967682072656c617469766520746f20556e69737760408201527f617020747761702e000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526243313160e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b602080825260029082015261433960f01b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b60208082526003908201526243323760e81b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b60006020825282516080602084015261550c60a0840182614f0d565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f1984830301608085015261340a8282614f0d565b918252602082015260400190565b938452602084019290925215156040830152606082015260800190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b60405181810167ffffffffffffffff811182821017156155c557fe5b604052919050565b6001600160a01b0381168114610b2257600080fd5b8015158114610b2257600080fd5b63ffffffff81168114610b2257600080fdfe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445434453413a20696e76616c6964207369676e6174757265202773272076616c756545434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212205588e36b593aca521cd7221641031ca4fe125d2300af7c70ba2abc8ce18bf28564736f6c63430007060033\",\n  \"deployedBytecode\": \"0x60806040526004361061036f5760003560e01c80637f07b130116101c6578063cae74029116100f7578063e9c3cb4f11610095578063f5d278e41161006f578063f5d278e41461095e578063f73e19c314610973578063fa461e3314610993578063fc5b73ff146109b3576103e1565b8063e9c3cb4f14610914578063f101d92f14610929578063f2fde38b1461093e576103e1565b8063d2dd9f79116100d1578063d2dd9f79146108ac578063d33219b4146108cc578063dcbab608146108e1578063dd62ed3e146108f4576103e1565b8063cae740291461087a578063cfa70b181461088f578063d0e30db0146108a4576103e1565b8063a457c2d711610164578063b52b7ff01161013e578063b52b7ff014610810578063bdd438b814610830578063c245168914610850578063c45a015514610865576103e1565b8063a457c2d7146107b0578063a9059cbb146107d0578063b24f719b146107f0576103e1565b80638f8b8dbc116101a05780638f8b8dbc1461074657806395d89b41146107665780639ff69a511461077b578063a319b29f1461079b576103e1565b80637f07b1301461070757806388626eb81461071c5780638da5cb5b14610731576103e1565b80633d65fdac116102a057806366a91b761161023e57806370a082311161021857806370a082311461069d578063715018a6146106bd5780637bcdc16e146106d25780637dc0d1d0146106f2576103e1565b806366a91b761461065e57806367b8c345146106735780636c1040a914610688576103e1565b80634d76e6fc1161027a5780634d76e6fc146105ef578063502e1a1614610604578063533092ef1461062457806363bbc4b614610649576103e1565b80633d65fdac146105a55780633dcb0c5d146105c55780633fc8cef3146105da576103e1565b8063313ce5671161030d578063392e53cd116102e7578063392e53cd1461052e5780633950935114610543578063395ebb69146105635780633d3a62ee14610585576103e1565b8063313ce567146104e257806333194c0a146105045780633644e51514610519576103e1565b806318160ddd1161034957806318160ddd1461045e57806323b872dd14610480578063281e78d1146104a05780632e1a7d4d146104c2576103e1565b806306fdde03146103e6578063095ea7b3146104115780630ca514cd1461043e576103e1565b366103e157336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103ba575060055461010090046001600160a01b031633145b6103df5760405162461bcd60e51b81526004016103d69061547e565b60405180910390fd5b005b600080fd5b3480156103f257600080fd5b506103fb6109c6565b604051610408919061511f565b60405180910390f35b34801561041d57600080fd5b5061043161042c366004614a72565b610a5d565b60405161040891906150d3565b34801561044a57600080fd5b506103df610459366004614cd2565b610a7b565b34801561046a57600080fd5b50610473610b25565b6040516104089190614fab565b34801561048c57600080fd5b5061043161049b366004614a32565b610b2b565b3480156104ac57600080fd5b506104b5610bb3565b6040516104089190614fb4565b3480156104ce57600080fd5b506103df6104dd366004614cd2565b610bd7565b3480156104ee57600080fd5b506104f7610cab565b604051610408919061559b565b34801561051057600080fd5b50610473610cb4565b34801561052557600080fd5b50610473610cd8565b34801561053a57600080fd5b50610431610ce7565b34801561054f57600080fd5b5061043161055e366004614a72565b610cf8565b34801561056f57600080fd5b50610578610d46565b604051610408919061558a565b34801561059157600080fd5b506103df6105a0366004614cd2565b610d4c565b3480156105b157600080fd5b506103df6105c0366004614cd2565b610ee4565b3480156105d157600080fd5b506104b5610f0a565b3480156105e657600080fd5b506104b5610f1e565b3480156105fb57600080fd5b506104b5610f42565b34801561061057600080fd5b5061043161061f366004614a72565b610f66565b34801561063057600080fd5b50610639610f86565b6040516104089493929190615078565b34801561065557600080fd5b50610473610fa2565b34801561066a57600080fd5b50610473610fa8565b34801561067f57600080fd5b50610473610fae565b34801561069457600080fd5b50610473610fb4565b3480156106a957600080fd5b506104736106b83660046149c2565b610fd8565b3480156106c957600080fd5b506103df610ff7565b3480156106de57600080fd5b506103df6106ed366004614cd2565b6110c2565b3480156106fe57600080fd5b506104b5611196565b34801561071357600080fd5b506104b56111ba565b34801561072857600080fd5b506104316111de565b34801561073d57600080fd5b506104b56111e8565b34801561075257600080fd5b506103df610761366004614ef1565b6111f7565b34801561077257600080fd5b506103fb6112d7565b34801561078757600080fd5b506103df610796366004614cd2565b611338565b3480156107a757600080fd5b506103df611409565b3480156107bc57600080fd5b506104316107cb366004614a72565b6114ca565b3480156107dc57600080fd5b506104316107eb366004614a72565b611532565b3480156107fc57600080fd5b506103df61080b366004614d2d565b611546565b34801561081c57600080fd5b506103df61082b366004614e83565b61184f565b34801561083c57600080fd5b506103df61084b366004614cd2565b611976565b34801561085c57600080fd5b50610431611a53565b34801561087157600080fd5b506104b5611a5d565b34801561088657600080fd5b50610473611a81565b34801561089b57600080fd5b50610473611a87565b6103df611a93565b3480156108b857600080fd5b506103df6108c73660046149c2565b611b3e565b3480156108d857600080fd5b506104b5611d25565b6103df6108ef366004614eb7565b611d49565b34801561090057600080fd5b5061047361090f3660046149fa565b611e0f565b34801561092057600080fd5b50610473611e3a565b34801561093557600080fd5b50610473611e40565b34801561094a57600080fd5b506103df6109593660046149c2565b611e46565b34801561096a57600080fd5b50610578611f68565b34801561097f57600080fd5b5061047361098e366004614cd2565b611f74565b34801561099f57600080fd5b506103df6109ae366004614adc565b611f7f565b6103df6109c1366004614d02565b612025565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b820191906000526020600020905b815481529060010190602001808311610a3557829003601f168201915b505050505090505b90565b6000610a71610a6a612172565b8484612176565b5060015b92915050565b610a83612172565b6001600160a01b0316610a946111e8565b6001600160a01b031614610aef576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff16610b195760405162461bcd60e51b81526004016103d6906151f7565b610b2281612262565b50565b60025490565b6000610b38848484612297565b610ba884610b44612172565b610ba385604051806060016040528060288152602001615734602891396001600160a01b038a16600090815260016020526040812090610b82612172565b6001600160a01b0316815260208101919091526040016000205491906123f2565b612176565b5060015b9392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60026006541415610c2f576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610c3f82612489565b90506000610c5033848460006124b4565b9050610c5c3382612501565b336001600160a01b03167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca94848484604051610c9993929190615574565b60405180910390a25050600160065550565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce26125eb565b905090565b600a54640100000000900460ff1681565b6000610a71610d05612172565b84610ba38560016000610d16612172565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906126b5565b6101a481565b60026006541415610da4576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600681905550600560019054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610dfc57600080fd5b505af1158015610e10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e349190614a9d565b610e505760405162461bcd60e51b81526004016103d6906153ee565b600f5460ff16610e725760405162461bcd60e51b81526004016103d6906152aa565b6000610e8582610e80610b25565b61270f565b90506000610e93824761271b565b9050610e9f3384612727565b610ea93382612501565b336001600160a01b03167fe9ab9870b9093d99f8e981919f65ad09b7ae90ff80f1031639af9e0357eb9ed68483604051610c99929190615549565b33600090815260106020908152604080832093835292905220805460ff19166001179055565b60055461010090046001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b601060209081526000928352604080842090915290825290205460ff1681565b600080600080610f94612823565b935093509350935090919293565b600e5481565b600b5481565b600d5481565b7f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b0381166000908152602081905260409020545b919050565b610fff612172565b6001600160a01b03166110106111e8565b6001600160a01b03161461106b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6007546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36007805473ffffffffffffffffffffffffffffffffffffffff19169055565b6110ca612172565b6001600160a01b03166110db6111e8565b6001600160a01b031614611136576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081116111565760405162461bcd60e51b81526004016103d69061540b565b600b8190556040517f28e0e4ee0b14d4b056ce88e1bcd890ccd32b22e213723c8765901381b5eae7059061118b908390614fab565b60405180910390a150565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ce261291a565b6007546001600160a01b031690565b6111ff612172565b6001600160a01b03166112106111e8565b6001600160a01b03161461126b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60b48163ffffffff1610156112925760405162461bcd60e51b81526004016103d690615169565b600a805463ffffffff191663ffffffff83161790556040517f1cd9c7f99a5530a38c8f2b387dcc78e8a76cb5b203e0c4316a66777d993dee359061118b90839061558a565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a525780601f10610a2757610100808354040283529160200191610a52565b611340612172565b6001600160a01b03166113516111e8565b6001600160a01b0316146113ac576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6702c68af0bb1400008111156113d45760405162461bcd60e51b81526004016103d6906153d1565b60098190556040517f829c71710efa317bbdb8e5c4ca2b6d2551b7c2d7d37ea199975807eb3f5c0e7c9061118b908390614fab565b600a54640100000000900460ff166114335760405162461bcd60e51b81526004016103d6906151f7565b600f8054600160ff19909116179055600554604051634bf7d4a160e11b81526101009091046001600160a01b0316906397efa94290611496907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b600060405180830381600087803b1580156114b057600080fd5b505af11580156114c4573d6000803e3d6000fd5b50505050565b6000610a716114d7612172565b84610ba3856040518060600160405280602581526020016157c66025913960016000611501612172565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906123f2565b6000610a7161153f612172565b8484612297565b61154e612172565b6001600160a01b031661155f6111e8565b6001600160a01b0316146115ba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600a54640100000000900460ff166115e45760405162461bcd60e51b81526004016103d6906151f7565b600083116116045760405162461bcd60e51b81526004016103d690615398565b61160c612a90565b8061161a575061161a61291a565b6116365760405162461bcd60e51b81526004016103d690615444565b6116408383612ab1565b42600d55600e839055805184906000908390829061165a57fe5b602002602001015160600151905060008360008151811061167757fe5b602002602001015160600151905060008460008151811061169457fe5b602002602001015160800151905080151586151514156116c65760405162461bcd60e51b81526004016103d690615324565b60005b85518110156117ef578581815181106116de57fe5b60200260200101516060015192508115158682815181106116fb57fe5b6020026020010151608001511515146117265760405162461bcd60e51b81526004016103d690615427565b8615611751578383101561174c5760405162461bcd60e51b81526004016103d690615341565b611771565b838311156117715760405162461bcd60e51b81526004016103d690615341565b829350611792858988848151811061178557fe5b6020026020010151612c71565b85818151811061179e57fe5b6020026020010151604001518511156117e2576117db8682815181106117c057fe5b602002602001015160400151866130e390919063ffffffff16565b94506117e7565b6117ef565b6001016116c9565b507fbbc3ba742efe346cfdf333000069964e0ee3087c68da267dac977d299f2366fb8560008151811061181e57fe5b60200260200101516000015189888a60405161183d9493929190615557565b60405180910390a15050505050505050565b600260065414156118a7576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560006118b784612489565b90506119287f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084848760018a6040516020016119149190614fab565b60405160208183030381529060405261313b565b336001600160a01b03167fa13b272c1cf13ba724064d3d4809d9f557aab8da2bb582cba031a2f57e728e9d8583604051611963929190615549565b60405180910390a2505060016006555050565b61197e612172565b6001600160a01b031661198f6111e8565b6001600160a01b0316146119ea576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600081118015611a025750670de0b6b3a76400008111155b611a1e5760405162461bcd60e51b81526004016103d6906154d4565b600c8190556040517f789e4b8ad1c375952cea7f07c9b3b6619a84b406432b948246cecb8ced96b9fa9061118b908390614fab565b6000610ce2612a90565b7f000000000000000000000000000000000000000000000000000000000000000081565b60085481565b6702c68af0bb14000081565b60026006541415611aeb576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065534600080611aff3384836131bc565b91509150336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158383604051610c99929190615549565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611b865760405162461bcd60e51b81526004016103d6906153b5565b600a54640100000000900460ff16611bb05760405162461bcd60e51b81526004016103d6906151f7565b600560019054906101000a90046001600160a01b03166001600160a01b0316639d4c94426040518163ffffffff1660e01b815260040160206040518083038186803b158015611bfe57600080fd5b505afa158015611c12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3691906149de565b6001600160a01b03166342842e0e30837f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401611c8593929190614fc8565b600060405180830381600087803b158015611c9f57600080fd5b505af1158015611cb3573d6000803e3d6000fd5b50505050611cc16000612262565b806001600160a01b03167fae97956757017853415251f661bfe857898f44ddb9c90b2483065719b84b0c697f0000000000000000000000000000000000000000000000000000000000000000604051611d1a9190614fab565b60405180910390a250565b7f000000000000000000000000000000000000000000000000000000000000000081565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611d915760405162461bcd60e51b81526004016103d69061528d565b600a54640100000000900460ff1615611dbc5760405162461bcd60e51b81526004016103d69061535e565b611dc581612262565b34611dd1816000613230565b600d849055600e839055611de8338783600061325f565b611df233866133b9565b5050600a805464ff00000000191664010000000017905550505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60095481565b600c5481565b611e4e612172565b6001600160a01b0316611e5f6111e8565b6001600160a01b031614611eba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611eff5760405162461bcd60e51b81526004018080602001828103825260268152602001806156486026913960400191505060405180910390fd5b6007546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600a5463ffffffff1681565b6000610a7582612489565b6000841380611f8e5750600083135b611f9757600080fd5b6000611fa582840184614b72565b90506000806000611fb984600001516133c3565b925092509250611feb7f00000000000000000000000000000000000000000000000000000000000000008484846133f4565b506000808913611ffb5787611ffd565b885b905061201a8560200151858585858a606001518b60400151613413565b505050505050505050565b6002600654141561207d576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065560008061208d6138ec565b9150915061209b8482613230565b60006120a8858484613906565b5090506121237f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086846120fc8a346130e3565b60008b60405160200161210f9190614fab565b604051602081830303815290604052613995565b336001600160a01b03167f5d85169ff8329e90f3225f9798e0eba54d00c55d3bbfe201a0d1606febb23a8e868360405161215e929190615549565b60405180910390a250506001600655505050565b3390565b6001600160a01b0383166121bb5760405162461bcd60e51b81526004018080602001828103825260248152602001806157a26024913960400191505060405180910390fd5b6001600160a01b0382166122005760405162461bcd60e51b815260040180806020018281038252602281526020018061566e6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60088190556040517f29600e2e028c8c5c2b112d021938e0d0237d8fafcbb20394c56cf9fa4661ca279061118b908390614fab565b6001600160a01b0383166122dc5760405162461bcd60e51b815260040180806020018281038252602581526020018061577d6025913960400191505060405180910390fd5b6001600160a01b0382166123215760405162461bcd60e51b81526004018080602001828103825260238152602001806156036023913960400191505060405180910390fd5b61232c8383836125e6565b61236981604051806060016040528060268152602001615690602691396001600160a01b03861660009081526020819052604090205491906123f2565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461239890826126b5565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156124815760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561244657818101518382015260200161242e565b50505050905090810190601f1680156124735780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600080612494612823565b9350505050610bac6124a4610b25565b6124ae8386613a0c565b90613a45565b6000806124bf6138ec565b91505060006124d086610e80610b25565b905060006124de828461271b565b90506124ec88878388613a65565b6124f68888612727565b979650505050505050565b80471015612556576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146125a1576040519150601f19603f3d011682016040523d82523d6000602084013e6125a6565b606091505b50509050806125e65760405162461bcd60e51b815260040180806020018281038252603a8152602001806156b6603a913960400191505060405180910390fd5b505050565b60007f0000000000000000000000000000000000000000000000000000000000000000612616613b94565b141561264357507f0000000000000000000000000000000000000000000000000000000000000000610a5a565b6126ae7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000613b98565b9050610a5a565b600082820183811015610bac576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610bac8383613a45565b6000610bac8284613a0c565b6001600160a01b03821661276c5760405162461bcd60e51b815260040180806020018281038252602181526020018061575c6021913960400191505060405180910390fd5b612778826000836125e6565b6127b581604051806060016040528060228152602001615626602291396001600160a01b03851660009081526020819052604090205491906123f2565b6001600160a01b0383166000908152602081905260409020556002546127db9082613bfa565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600554604051634632752560e11b8152600091829182918291829161010090046001600160a01b031690638c64ea4a90612881907f000000000000000000000000000000000000000000000000000000000000000090600401614fab565b60806040518083038186803b15801561289957600080fd5b505afa1580156128ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d19190614c30565b805160208201516040830151606090930151919863ffffffff90911697506bffffffffffffffffffffffff90921695506fffffffffffffffffffffffffffffffff169350915050565b600a5460405163cce79bd560e01b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd5916129de917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff90911690600190600401614fec565b60206040518083038186803b1580156129f657600080fd5b505afa158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190614cea565b90506000612a47600e5483613a4590919063ffffffff16565b90506000670de0b6b3a76400008211612a7157612a6c670de0b6b3a7640000836130e3565b612a83565b612a8382670de0b6b3a76400006130e3565b600c541115935050505090565b6000612aa9600b54600d54613c5790919063ffffffff16565b421015905090565b600a5460405163cce79bd560e01b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163cce79bd591612b71917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009163ffffffff1690600190600401614fec565b60206040518083038186803b158015612b8957600080fd5b505afa158015612b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc19190614cea565b90508115612c2657612c02670de0b6b3a7640000612bfc612bf5600954670de0b6b3a7640000613c5790919063ffffffff16565b8490613caf565b90613d1b565b831115612c215760405162461bcd60e51b81526004016103d6906152c7565b6125e6565b612c52670de0b6b3a7640000612bfc612bf5600954670de0b6b3a76400006130e390919063ffffffff16565b8310156125e65760405162461bcd60e51b81526004016103d690615230565b806080015115612ca4578060600151821115612c9f5760405162461bcd60e51b81526004016103d69061549a565b612cc8565b8060600151821015612cc85760405162461bcd60e51b81526004016103d69061537b565b612cda81602001518260c00151613d7a565b60007fc8aea8e60353611f3ed5409dad2d3173390bd252431198e7300eda67fefb66b1826000015183602001518460400151856060015186608001518760a001518860c00151604051602001612d379897969594939291906150de565b6040516020818303038152906040528051906020012090506000612d5a82613dee565b90506000612d78828560e00151866101000151876101200151613e3a565b905083602001516001600160a01b0316816001600160a01b031614612daf5760405162461bcd60e51b81526004016103d690615461565b428460a001511015612dd35760405162461bcd60e51b81526004016103d690615186565b8360400151861015612de757604084018690525b6000612e0c670de0b6b3a7640000612bfc888860400151613caf90919063ffffffff16565b9050846080015115612f575760208501516040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916323b872dd91612e6c919030908690600401614fc8565b602060405180830381600087803b158015612e8657600080fd5b505af1158015612e9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ebe9190614a9d565b50604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612f0b908490600401614fab565b600060405180830381600087803b158015612f2557600080fd5b505af1158015612f39573d6000803e3d6000fd5b50505050612f528560200151866040015183600061325f565b613085565b612f6c85602001518660400151836000613a65565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612fc757600080fd5b505af1158015612fdb573d6000803e3d6000fd5b50505050602086015160405163a9059cbb60e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063a9059cbb9161303191859060040161505f565b602060405180830381600087803b15801561304b57600080fd5b505af115801561305f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130839190614a9d565b505b7f68c36f17c620d197a81d3aeff305f83abf3bb29943a38cd6efc299041238652d856020015186600001518760400151886060015189608001518b6040516130d29695949392919061509e565b60405180910390a150505050505050565b80820382811115610a75576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b60006131908530600060405180608001604052808c8c8f60405160200161316493929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a1690820152606001879052613faf565b9050838111156131b25760405162461bcd60e51b81526004016103d6906151c0565b5050505050505050565b6000806000806131ca6138ec565b915091506131d88682613230565b6000806131e6888585613906565b909250905060006132086131fa8a846130e3565b85613203610b25565b61411c565b90506132168a848b8b61325f565b6132208a826133b9565b9199919850909650505050505050565b60085461323d8284613c57565b111561325b5760405162461bcd60e51b81526004016103d690615213565b5050565b600554604051630728cf2360e31b81526101009091046001600160a01b03169063394679189084906132ba907f0000000000000000000000000000000000000000000000000000000000000000908890600090600401615574565b6020604051808303818588803b1580156132d357600080fd5b505af11580156132e7573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061330c9190614cea565b50806114c45760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90613360908790879060040161505f565b602060405180830381600087803b15801561337a57600080fd5b505af115801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b29190614a9d565b5050505050565b61325b828261416b565b600080806133d1848261425b565b92506133de846014614327565b90506133eb84601761425b565b91509193909250565b600061340a856134058686866143e3565b614439565b95945050505050565b60008160ff16600181111561342457fe5b600181111561342f57fe5b14156136665760008280602001905181019061344b9190614b57565b6040516370a0823160e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906134a2903090600401614fb4565b60206040518083038186803b1580156134ba57600080fd5b505afa1580156134ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f29190614cea565b6040518263ffffffff1660e01b815260040161350e9190614fab565b600060405180830381600087803b15801561352857600080fd5b505af115801561353c573d6000803e3d6000fd5b5050505061355088826000015160016131bc565b5050600061355f88888861445c565b60405163a9059cbb60e01b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906135b0908490899060040161505f565b602060405180830381600087803b1580156135ca57600080fd5b505af11580156135de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136029190614a9d565b50886001600160a01b03167fc355ebece16d7e85e486911f0cde1074bc4bd3fec251c88cdddc7076d3e99adb864760405161363e929190615549565b60405180910390a2471561365f5761365f6001600160a01b038a1647612501565b50506138e3565b60018160ff16600181111561367757fe5b600181111561368257fe5b14156138e35760008280602001905181019061369e9190614b57565b9050600061374e8983600001517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016136f79190614fb4565b60206040518083038186803b15801561370f57600080fd5b505afa158015613723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137479190614cea565b60016124b4565b9050600061375d89898961445c565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b1580156137ba57600080fd5b505af11580156137ce573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250613821915084908a9060040161505f565b602060405180830381600087803b15801561383b57600080fd5b505af115801561384f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138739190614a9d565b50600061388083886130e3565b90508a6001600160a01b03167f6f3269a64126ef2a1959892f3d921e81865181e09a7f72f55d3a49550c53b48d88836040516138bd929190615549565b60405180910390a280156138de576138de6001600160a01b038c1682612501565b505050505b50505050505050565b6000806000806138fa612823565b96509450505050509091565b60008060008061391461449a565b9050600086158015613924575085155b80156139365750613933610b25565b15155b905080156139565760405162461bcd60e51b81526004016103d6906151a3565b61397761396d6139668985613a0c565b8890613c57565b6124ae8a8a613a0c565b925060006139858484613a0c565b9399939850929650505050505050565b60006139ea8530600060405180608001604052808d8c8e6040516020016139be93929190614f58565b60408051601f1981840301815291815290825233602083015260ff8a16908201526060018790526145d1565b9050838110156131b25760405162461bcd60e51b81526004016103d690615132565b6000670de0b6b3a7640000613a36613a248585613caf565b6002670de0b6b3a76400005b04613c57565b81613a3d57fe5b049392505050565b600081613a36613a5d85670de0b6b3a7640000613caf565b600285613a30565b80613b0e576040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90613aba90879030908890600401614fc8565b602060405180830381600087803b158015613ad457600080fd5b505af1158015613ae8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b0c9190614a9d565b505b600554604051638632cb0360e01b81526101009091046001600160a01b031690638632cb0390613b66907f00000000000000000000000000000000000000000000000000000000000000009087908790600401615574565b600060405180830381600087803b158015613b8057600080fd5b505af11580156131b2573d6000803e3d6000fd5b4690565b6000838383613ba5613b94565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b03168152602001955050505050506040516020818303038152906040528051906020012090509392505050565b600082821115613c51576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b80820182811015610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000811580613cca57505080820282828281613cc757fe5b04145b610a75576040805162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b6000808211613d71576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613a3d57fe5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff1615613dbe5760405162461bcd60e51b81526004016103d6906154b7565b6001600160a01b03909116600090815260106020908152604080832093835292905220805460ff19166001179055565b6000613df86125eb565b82604051602001808061190160f01b81525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613e9b5760405162461bcd60e51b81526004018080602001828103825260228152602001806156f06022913960400191505060405180910390fd5b8360ff16601b1480613eb057508360ff16601c145b613eeb5760405162461bcd60e51b81526004018080602001828103825260228152602001806157126022913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613f47573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661340a576040805162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b600080600080613fc285600001516133c3565b919450925090506001600160a01b0380841690831610600080613fe685878661445c565b6001600160a01b031663128acb088b85613fff8f614710565b6000036001600160a01b038e1615614017578d61403d565b876140365773fffd8963efd1fc6a506488495d951d5263988d2561403d565b6401000276a45b8d60405160200161404e91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161407d959493929190615025565b6040805180830381600087803b15801561409657600080fd5b505af11580156140aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140ce9190614ab9565b91509150600080846140e45782846000036140ea565b83836000035b915091508a6001600160a01b03166000141561410c578c811461410c57600080fd5b509b9a5050505050505050505050565b60008061413361412c8587613c57565b8690613a45565b905082156141625761415a614150670de0b6b3a7640000836130e3565b6124ae8584613a0c565b915050610bac565b50929392505050565b6001600160a01b0382166141c6576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6141d2600083836125e6565b6002546141df90826126b5565b6002556001600160a01b03821660009081526020819052604090205461420590826126b5565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000818260140110156142b5576040805162461bcd60e51b815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b816014018351101561430e576040805162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015614381576040805162461bcd60e51b815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b81600301835110156143da576040805162461bcd60e51b815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b6143eb6148c8565b826001600160a01b0316846001600160a01b03161115614409579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b60006144458383614726565b9050336001600160a01b03821614610a7557600080fd5b60006144927f000000000000000000000000000000000000000000000000000000000000000061448d8686866143e3565b614726565b949350505050565b60008061452e7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006101a46000614822565b90506000600560019054906101000a90046001600160a01b03166001600160a01b031663978bbdb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561458057600080fd5b505afa158015614594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145b89190614cea565b90506145ca612710612bfc8484613caf565b9250505090565b6000806000806145e485600001516133c3565b919450925090506001600160a01b038083169084161060008061460886868661445c565b6001600160a01b031663128acb088b856146218f614710565b6001600160a01b038e1615614636578d61465c565b876146555773fffd8963efd1fc6a506488495d951d5263988d2561465c565b6401000276a45b8d60405160200161466d91906154f0565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161469c959493929190615025565b6040805180830381600087803b1580156146b557600080fd5b505af11580156146c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146ed9190614ab9565b91509150826146fc57816146fe565b805b6000039b9a5050505050505050505050565b6000600160ff1b821061472257600080fd5b5090565b600081602001516001600160a01b031682600001516001600160a01b03161061474e57600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b6040805163cce79bd560e01b81526001600160a01b0387811660048301528681166024830152858116604483015263ffffffff851660648301528315156084830152915160009289169163cce79bd59160a4808301926020929190829003018186803b15801561489157600080fd5b505afa1580156148a5573d6000803e3d6000fd5b505050506040513d60208110156148bb57600080fd5b5051979650505050505050565b604080516060810182526000808252602082018190529181019190915290565b8035610ff2816155cd565b8035610ff2816155e2565b600082601f83011261490e578081fd5b813567ffffffffffffffff81111561492257fe5b614935601f8201601f19166020016155a9565b818152846020838601011115614949578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215614974578081fd5b6040516020810181811067ffffffffffffffff8211171561499157fe5b6040529151825250919050565b803562ffffff81168114610ff257600080fd5b803560ff81168114610ff257600080fd5b6000602082840312156149d3578081fd5b8135610bac816155cd565b6000602082840312156149ef578081fd5b8151610bac816155cd565b60008060408385031215614a0c578081fd5b8235614a17816155cd565b91506020830135614a27816155cd565b809150509250929050565b600080600060608486031215614a46578081fd5b8335614a51816155cd565b92506020840135614a61816155cd565b929592945050506040919091013590565b60008060408385031215614a84578182fd5b8235614a8f816155cd565b946020939093013593505050565b600060208284031215614aae578081fd5b8151610bac816155e2565b60008060408385031215614acb578182fd5b505080516020909101519092909150565b60008060008060608587031215614af1578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115614b16578384fd5b818701915087601f830112614b29578384fd5b813581811115614b37578485fd5b886020828501011115614b48578485fd5b95989497505060200194505050565b600060208284031215614b68578081fd5b610bac8383614963565b600060208284031215614b83578081fd5b813567ffffffffffffffff80821115614b9a578283fd5b9083019060808286031215614bad578283fd5b604051608081018181108382111715614bc257fe5b604052823582811115614bd3578485fd5b614bdf878286016148fe565b825250614bee602084016148e8565b6020820152614bff604084016149b1565b6040820152606083013582811115614c15578485fd5b614c21878286016148fe565b60608301525095945050505050565b600060808284031215614c41578081fd5b6040516080810181811067ffffffffffffffff82111715614c5e57fe5b6040528251614c6c816155cd565b81526020830151614c7c816155f0565b602082015260408301516bffffffffffffffffffffffff81168114614c9f578283fd5b604082015260608301516fffffffffffffffffffffffffffffffff81168114614cc6578283fd5b60608201529392505050565b600060208284031215614ce3578081fd5b5035919050565b600060208284031215614cfb578081fd5b5051919050565b60008060408385031215614d14578182fd5b82359150614d246020840161499e565b90509250929050565b60008060008060808587031215614d42578182fd5b843593506020808601359350604080870135614d5d816155e2565b9350606087013567ffffffffffffffff80821115614d79578485fd5b818901915089601f830112614d8c578485fd5b813581811115614d9857fe5b614da585868302016155a9565b8181528581019250838601610140808402860188018e1015614dc5578889fd5b8895505b83861015614e6f5780828f031215614ddf578889fd5b614de8816155a9565b82358152614df78984016148e8565b89820152878301358882015260608301356060820152614e19608084016148f3565b608082015260a0838101359082015260c0808401359082015260e0614e3f8185016149b1565b90820152610100838101359082015261012080840135908201528552600195909501949387019390810190614dc9565b505080965050505050505092959194509250565b600080600060608486031215614e97578081fd5b8335925060208401359150614eae6040850161499e565b90509250925092565b600080600080600060a08688031215614ece578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b600060208284031215614f02578081fd5b8135610bac816155f0565b60008151808452815b81811015614f3257602081850181015186830182015201614f16565b81811115614f435782602083870101525b50601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b90815260200190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b60006001600160a01b038088168352861515602084015285604084015280851660608401525060a060808301526124f660a0830184614f0d565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b039690961686526020860194909452604085019290925260608401521515608083015260a082015260c00190565b901515815260200190565b97885260208801969096526001600160a01b0394909416604087015260608601929092526080850152151560a084015260c083015260e08201526101000190565b600060208252610bac6020830184614f0d565b60208082526018908201527f616d6f756e74206f7574206c657373207468616e206d696e0000000000000000604082015260600190565b60208082526003908201526210cc4d60ea1b604082015260600190565b60208082526003908201526204332360ec1b604082015260600190565b60208082526003908201526221991b60e91b604082015260600190565b6020808252601a908201527f616d6f756e7420696e2067726561746572207468616e206d6178000000000000604082015260600190565b602080825260029082015261219960f11b604082015260600190565b60208082526003908201526221989b60e91b604082015260600190565b60208082526027908201527f507269636520746f6f206c6f772072656c617469766520746f20556e6973776160408201527f7020747761702e00000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526204331360ec1b604082015260600190565b60208082526003908201526243313360e81b604082015260600190565b60208082526028908201527f507269636520746f6f20686967682072656c617469766520746f20556e69737760408201527f617020747761702e000000000000000000000000000000000000000000000000606082015260800190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526243323560e81b604082015260600190565b60208082526003908201526243313160e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b602080825260029082015261433160f01b604082015260600190565b60208082526003908201526243313560e81b604082015260600190565b60208082526003908201526221989960e91b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b602080825260029082015261433960f01b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b60208082526003908201526243323760e81b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b60006020825282516080602084015261550c60a0840182614f0d565b90506001600160a01b03602085015116604084015260ff60408501511660608401526060840151601f1984830301608085015261340a8282614f0d565b918252602082015260400190565b938452602084019290925215156040830152606082015260800190565b9283526020830191909152604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b60405181810167ffffffffffffffff811182821017156155c557fe5b604052919050565b6001600160a01b0381168114610b2257600080fd5b8015158114610b2257600080fd5b63ffffffff81168114610b2257600080fdfe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d6179206861766520726576657274656445434453413a20696e76616c6964207369676e6174757265202773272076616c756545434453413a20696e76616c6964207369676e6174757265202776272076616c756545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212205588e36b593aca521cd7221641031ca4fe125d2300af7c70ba2abc8ce18bf28564736f6c63430007060033\",\n  \"devdoc\": {\n    \"author\": \"Opyn team\",\n    \"details\": \"CrabStrategyV2 contract\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"DOMAIN_SEPARATOR()\": {\n        \"details\": \"view function to get the domain seperator used in signing\"\n      },\n      \"allowance(address,address)\": {\n        \"details\": \"See {IERC20-allowance}.\"\n      },\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC20-balanceOf}.\"\n      },\n      \"checkPriceHedge()\": {\n        \"returns\": {\n          \"_0\": \"true if hedging is allowed\"\n        }\n      },\n      \"checkTimeHedge()\": {\n        \"returns\": {\n          \"_0\": \"true if hedging is allowed\"\n        }\n      },\n      \"constructor\": {\n        \"details\": \"this will open a vault in the power token contract and store the vault ID\",\n        \"params\": {\n          \"_crabMigration\": \"crab migration contract address\",\n          \"_ethWSqueethPool\": \"eth:wSqueeth uniswap pool address\",\n          \"_hedgePriceThreshold\": \"hedge price threshold (0.1*1e18 = 10%)\",\n          \"_hedgeTimeThreshold\": \"hedge time threshold (seconds)\",\n          \"_oracle\": \"oracle address\",\n          \"_timelock\": \"timelock contract address\",\n          \"_uniswapFactory\": \"uniswap factory address\",\n          \"_wSqueethController\": \"power token controller address\",\n          \"_weth\": \"weth address\"\n        }\n      },\n      \"decimals()\": {\n        \"details\": \"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"\n      },\n      \"decreaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"\n      },\n      \"deposit()\": {\n        \"details\": \"provide ETH, return wSqueeth and strategy token\"\n      },\n      \"flashDeposit(uint256,uint24)\": {\n        \"details\": \"this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth_ethToDeposit must be less than msg.value plus the proceeds from the flash swapthe difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\",\n        \"params\": {\n          \"_ethToDeposit\": \"total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\",\n          \"_poolFee\": \"Uniswap pool fee\"\n        }\n      },\n      \"flashWithdraw(uint256,uint256,uint24)\": {\n        \"details\": \"this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\",\n        \"params\": {\n          \"_crabAmount\": \"strategy token amount to burn\",\n          \"_maxEthToPay\": \"maximum ETH to pay to buy back the wSqueeth debt\",\n          \"_poolFee\": \"Uniswap pool fee\"\n        }\n      },\n      \"getStrategyVaultId()\": {\n        \"returns\": {\n          \"_0\": \"vault ID\"\n        }\n      },\n      \"getVaultDetails()\": {\n        \"returns\": {\n          \"_0\": \"operator\",\n          \"_1\": \"nft collateral id\",\n          \"_2\": \"collateral amount\",\n          \"_3\": \"short amount\"\n        }\n      },\n      \"getWsqueethFromCrabAmount(uint256)\": {\n        \"params\": {\n          \"_crabAmount\": \"strategy token amount\"\n        },\n        \"returns\": {\n          \"_0\": \"wSqueeth amount\"\n        }\n      },\n      \"hedgeOTC(uint256,uint256,bool,(uint256,address,uint256,uint256,bool,uint256,uint256,uint8,bytes32,bytes32)[])\": {\n        \"details\": \"hedge function to reduce delta using an array of signed orders\",\n        \"params\": {\n          \"_clearingPrice\": \"clearing price in weth\",\n          \"_isHedgeBuying\": \"direction of hedge trade\",\n          \"_orders\": \"an array of signed order to swap tokens\",\n          \"_totalQuantity\": \"quantity the manager wants to trade\"\n        }\n      },\n      \"increaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"initialize(uint256,uint256,uint256,uint256,uint256)\": {\n        \"params\": {\n          \"_crabSharesToMint\": \"crab shares to mint\",\n          \"_priceAtLastHedge\": \"price at last hedge for crab V1\",\n          \"_strategyCap\": \"strategy cap for crab V2\",\n          \"_timeAtLastHedge\": \"time at last hedge for crab V1\",\n          \"_wSqueethToMint\": \"amount of wPowerPerp to mint\"\n        }\n      },\n      \"name()\": {\n        \"details\": \"Returns the name of the token.\"\n      },\n      \"owner()\": {\n        \"details\": \"Returns the address of the current owner.\"\n      },\n      \"redeemShortShutdown()\": {\n        \"details\": \"needs to be called before users can exit strategy using withdrawShutdown\"\n      },\n      \"renounceOwnership()\": {\n        \"details\": \"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"\n      },\n      \"setHedgePriceThreshold(uint256)\": {\n        \"params\": {\n          \"_hedgePriceThreshold\": \"the hedge price threshold, in percent, scaled by 1e18\"\n        }\n      },\n      \"setHedgeTimeThreshold(uint256)\": {\n        \"params\": {\n          \"_hedgeTimeThreshold\": \"the hedge time threshold, in seconds\"\n        }\n      },\n      \"setHedgingTwapPeriod(uint32)\": {\n        \"params\": {\n          \"_hedgingTwapPeriod\": \"the twap period, in seconds\"\n        }\n      },\n      \"setNonceTrue(uint256)\": {\n        \"params\": {\n          \"_nonce\": \"the number to be set true\"\n        }\n      },\n      \"setOTCPriceTolerance(uint256)\": {\n        \"params\": {\n          \"_otcPriceTolerance\": \"the OTC price tolerance, in percent, scaled by 1e18\"\n        }\n      },\n      \"setStrategyCap(uint256)\": {\n        \"details\": \"deposits are rejected if it would put the strategy above the cap amountstrategy collateral can be above the cap amount due to hedging activities\",\n        \"params\": {\n          \"_capAmount\": \"the maximum strategy collateral in ETH, checked on deposits\"\n        }\n      },\n      \"symbol()\": {\n        \"details\": \"Returns the symbol of the token, usually a shorter version of the name.\"\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC20-totalSupply}.\"\n      },\n      \"transfer(address,uint256)\": {\n        \"details\": \"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"\n      },\n      \"transferOwnership(address)\": {\n        \"details\": \"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"\n      },\n      \"transferVault(address)\": {\n        \"details\": \"strategy cap is set to 0 to avoid future deposits\",\n        \"params\": {\n          \"_newStrategy\": \"new strategy contract address\"\n        }\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"params\": {\n          \"_data\": \"callback data encoded as SwapCallbackData struct\",\n          \"amount0Delta\": \"amount of token0\",\n          \"amount1Delta\": \"amount of token1\"\n        }\n      },\n      \"withdraw(uint256)\": {\n        \"details\": \"provide strategy tokens and wSqueeth, returns ETH\",\n        \"params\": {\n          \"_crabAmount\": \"amount of strategy token to burn\"\n        }\n      },\n      \"withdrawShutdown(uint256)\": {\n        \"params\": {\n          \"_crabAmount\": \"amount of strategy token to burn\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"ONE\": {\n        \"details\": \"basic unit used for calculation\"\n      },\n      \"POWER_PERP_PERIOD\": {\n        \"details\": \"the TWAP_PERIOD used in the PowerPerp Controller contract\"\n      },\n      \"_CRAB_BALANCE_TYPEHASH\": {\n        \"details\": \"typehash for signed orders\"\n      },\n      \"ethWSqueethPool\": {\n        \"details\": \"ETH:wSqueeth uniswap pool\"\n      },\n      \"hasRedeemedInShutdown\": {\n        \"details\": \"set to true when redeemShortShutdown has been called\"\n      },\n      \"hedgePriceThreshold\": {\n        \"details\": \"price movement to trigger a hedge (0.1*1e18 = 10%)\"\n      },\n      \"hedgeTimeThreshold\": {\n        \"details\": \"time difference to trigger a hedge (seconds)\"\n      },\n      \"hedgingTwapPeriod\": {\n        \"details\": \"twap period to use for hedge calculations\"\n      },\n      \"isInitialized\": {\n        \"details\": \"true if CrabV2 was initialized\"\n      },\n      \"nonces\": {\n        \"details\": \"store the used flag for a nonce for each address\"\n      },\n      \"oracle\": {\n        \"details\": \"strategy uniswap oracle\"\n      },\n      \"priceAtLastHedge\": {\n        \"details\": \"wSqueeth/Eth price when last hedge executed\"\n      },\n      \"strategyCap\": {\n        \"details\": \"the cap in ETH for the strategy, above which deposits will be rejected\"\n      },\n      \"timeAtLastHedge\": {\n        \"details\": \"timestamp when last hedge executed\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"checkPriceHedge()\": {\n        \"notice\": \"check if hedging based on price threshold is allowed\"\n      },\n      \"checkTimeHedge()\": {\n        \"notice\": \"check if hedging based on time threshold is allowed\"\n      },\n      \"constructor\": {\n        \"notice\": \"strategy constructor\"\n      },\n      \"deposit()\": {\n        \"notice\": \"deposit ETH into strategy\"\n      },\n      \"flashDeposit(uint256,uint24)\": {\n        \"notice\": \"flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\"\n      },\n      \"flashWithdraw(uint256,uint256,uint24)\": {\n        \"notice\": \"flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\"\n      },\n      \"getStrategyVaultId()\": {\n        \"notice\": \"get power token strategy vault ID \"\n      },\n      \"getVaultDetails()\": {\n        \"notice\": \"get the vault composition of the strategy \"\n      },\n      \"getWsqueethFromCrabAmount(uint256)\": {\n        \"notice\": \"get wSqueeth debt amount associated with strategy token amount\"\n      },\n      \"initialize(uint256,uint256,uint256,uint256,uint256)\": {\n        \"notice\": \"initializes the collateral ratio after the first migration\"\n      },\n      \"redeemShortShutdown()\": {\n        \"notice\": \"called to redeem the net value of a vault post shutdown\"\n      },\n      \"setHedgePriceThreshold(uint256)\": {\n        \"notice\": \"owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\"\n      },\n      \"setHedgeTimeThreshold(uint256)\": {\n        \"notice\": \"owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\"\n      },\n      \"setHedgingTwapPeriod(uint32)\": {\n        \"notice\": \"owner can set the twap period in seconds that is used for calculating twaps for hedging\"\n      },\n      \"setNonceTrue(uint256)\": {\n        \"notice\": \"set nonce to true\"\n      },\n      \"setOTCPriceTolerance(uint256)\": {\n        \"notice\": \"owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\"\n      },\n      \"setStrategyCap(uint256)\": {\n        \"notice\": \"owner can set the strategy cap in ETH collateral terms\"\n      },\n      \"transferVault(address)\": {\n        \"notice\": \"transfer vault NFT to new contract\"\n      },\n      \"uniswapV3SwapCallback(int256,int256,bytes)\": {\n        \"notice\": \"uniswap swap callback function for flashes\"\n      },\n      \"withdraw(uint256)\": {\n        \"notice\": \"withdraw WETH from strategy\"\n      },\n      \"withdrawShutdown(uint256)\": {\n        \"notice\": \"called to exit a vault if the Squeeth Power Perp contracts are shutdown\"\n      }\n    },\n    \"notice\": \"Contract for Crab strategy\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 881,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_balances\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 887,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_allowances\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n      },\n      {\n        \"astId\": 889,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_totalSupply\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 891,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 893,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 895,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_decimals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint8\"\n      },\n      {\n        \"astId\": 27260,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"powerTokenController\",\n        \"offset\": 1,\n        \"slot\": \"5\",\n        \"type\": \"t_contract(IController)11604\"\n      },\n      {\n        \"astId\": 4176,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 7,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"_owner\",\n        \"offset\": 0,\n        \"slot\": \"7\",\n        \"type\": \"t_address\"\n      },\n      {\n        \"astId\": 25273,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"strategyCap\",\n        \"offset\": 0,\n        \"slot\": \"8\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25287,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"otcPriceTolerance\",\n        \"offset\": 0,\n        \"slot\": \"9\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25294,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hedgingTwapPeriod\",\n        \"offset\": 0,\n        \"slot\": \"10\",\n        \"type\": \"t_uint32\"\n      },\n      {\n        \"astId\": 25297,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"isInitialized\",\n        \"offset\": 4,\n        \"slot\": \"10\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 25319,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hedgeTimeThreshold\",\n        \"offset\": 0,\n        \"slot\": \"11\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25322,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hedgePriceThreshold\",\n        \"offset\": 0,\n        \"slot\": \"12\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25325,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"timeAtLastHedge\",\n        \"offset\": 0,\n        \"slot\": \"13\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25328,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"priceAtLastHedge\",\n        \"offset\": 0,\n        \"slot\": \"14\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 25331,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"hasRedeemedInShutdown\",\n        \"offset\": 0,\n        \"slot\": \"15\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 25338,\n        \"contract\": \"contracts/strategy/CrabStrategyV2.sol:CrabStrategyV2\",\n        \"label\": \"nonces\",\n        \"offset\": 0,\n        \"slot\": \"16\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_uint256,t_bool))\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_contract(IController)11604\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"contract IController\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => uint256))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_uint256)\"\n      },\n      \"t_mapping(t_address,t_mapping(t_uint256,t_bool))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(uint256 => bool))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_uint256,t_bool)\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_mapping(t_uint256,t_bool)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => bool)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_bool\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint32\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint32\",\n        \"numberOfBytes\": \"4\"\n      },\n      \"t_uint8\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint8\",\n        \"numberOfBytes\": \"1\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/NonfungiblePositionManager.json",
    "content": "{\n  \"address\": \"0x8c7C1F786dA4DEe7d4bB49697A9B0C0c8Fb328e0\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_factory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_WETH9\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_tokenDescriptor_\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"approved\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"approved\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"ApprovalForAll\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Collect\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"DecreaseLiquidity\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"IncreaseLiquidity\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"DOMAIN_SEPARATOR\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"PERMIT_TYPEHASH\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"WETH9\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"baseURI\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burn\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount0Max\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"amount1Max\",\n              \"type\": \"uint128\"\n            }\n          ],\n          \"internalType\": \"struct INonfungiblePositionManager.CollectParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"collect\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token0\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token1\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96\",\n          \"type\": \"uint160\"\n        }\n      ],\n      \"name\": \"createAndInitializePoolIfNecessary\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"pool\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint128\",\n              \"name\": \"liquidity\",\n              \"type\": \"uint128\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct INonfungiblePositionManager.DecreaseLiquidityParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"decreaseLiquidity\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getApproved\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"tokenId\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Desired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Desired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct INonfungiblePositionManager.IncreaseLiquidityParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"increaseLiquidity\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"isApprovedForAll\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"token0\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"token1\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"tickLower\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"int24\",\n              \"name\": \"tickUpper\",\n              \"type\": \"int24\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Desired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Desired\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount0Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount1Min\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct INonfungiblePositionManager.MintParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"mint\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes[]\",\n          \"name\": \"data\",\n          \"type\": \"bytes[]\"\n        }\n      ],\n      \"name\": \"multicall\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes[]\",\n          \"name\": \"results\",\n          \"type\": \"bytes[]\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ownerOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"deadline\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"permit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"positions\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint96\",\n          \"name\": \"nonce\",\n          \"type\": \"uint96\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token0\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token1\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tickLower\",\n          \"type\": \"int24\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tickUpper\",\n          \"type\": \"int24\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"feeGrowthInside0LastX128\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"feeGrowthInside1LastX128\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"tokensOwed0\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"tokensOwed1\",\n          \"type\": \"uint128\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"refundETH\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"safeTransferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"safeTransferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"deadline\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"nonce\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"expiry\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitAllowed\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"nonce\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"expiry\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitAllowedIfNecessary\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"deadline\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitIfNecessary\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"approved\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"setApprovalForAll\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"interfaceId\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"name\": \"supportsInterface\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"sweepToken\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"index\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenByIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"index\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenOfOwnerByIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenURI\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0Owed\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1Owed\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3MintCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"unwrapWETH9\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x116ca89253e2448fae6f69cd9e0fdab1d8fbfd8a263f4b6d1590fec8a606601a\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0x8c7C1F786dA4DEe7d4bB49697A9B0C0c8Fb328e0\",\n    \"transactionIndex\": 3,\n    \"gasUsed\": \"5471290\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0xcdc1713135f33d861871c4fdad1d66a219c88ca538cdfde21959738ad0f70ecf\",\n    \"transactionHash\": \"0x116ca89253e2448fae6f69cd9e0fdab1d8fbfd8a263f4b6d1590fec8a606601a\",\n    \"logs\": [],\n    \"blockNumber\": 11342319,\n    \"cumulativeGasUsed\": \"5747286\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n    \"0xc778417e063141139fce010982780140aa0cd5ab\",\n    \"0x0000000000000000000000000000000000000000\"\n  ],\n  \"bytecode\": \"0x610120604052600d80546001600160b01b0319166001176001600160b01b0316600160b01b1790553480156200003457600080fd5b50604051620062e9380380620062e98339810160408190526200005791620002db565b82826040518060400160405280601b81526020017f556e697377617020563320506f736974696f6e73204e46542d563100000000008152506040518060400160405280600a815260200169554e492d56332d504f5360b01b815250604051806040016040528060018152602001603160f81b8152508282620000e66301ffc9a760e01b6200018d60201b60201c565b8151620000fb90600690602085019062000212565b5080516200011190600790602084019062000212565b50620001246380ac58cd60e01b6200018d565b62000136635b5e139f60e01b6200018d565b6200014863780e9d6360e01b6200018d565b50508251602093840120608052805192019190912060a052506001600160601b0319606092831b811660c05290821b811660e05291901b166101005250620003249050565b6001600160e01b03198082161415620001ed576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152602081905260409020805460ff19166001179055565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826200024a576000855562000295565b82601f106200026557805160ff191683800117855562000295565b8280016001018555821562000295579182015b828111156200029557825182559160200191906001019062000278565b50620002a3929150620002a7565b5090565b5b80821115620002a35760008155600101620002a8565b80516001600160a01b0381168114620002d657600080fd5b919050565b600080600060608486031215620002f0578283fd5b620002fb84620002be565b92506200030b60208501620002be565b91506200031b60408501620002be565b90509250925092565b60805160a05160c05160601c60e05160601c6101005160601c615f40620003a960003980612a835250806102995280611718528061180e52806118965280613e5d5280613ea35280613f17525080610aa75280610dde5280610ea55280612a1d5280612b235280612e4452806136e15250806114ff5250806114de5250615f406000f3fe6080604052600436106102895760003560e01c80636352211e11610153578063ac9650d8116100cb578063d34879971161007f578063e985e9c511610064578063e985e9c5146106f5578063f3995c6714610715578063fc6f7865146107285761030d565b8063d3487997146106c2578063df2ab5bb146106e25761030d565b8063c2e3140a116100b0578063c2e3140a1461067a578063c45a01551461068d578063c87b56dd146106a25761030d565b8063ac9650d81461063a578063b88d4fde1461065a5761030d565b8063883164561161012257806399fbab881161010757806399fbab88146105cf578063a22cb46514610607578063a4a78f0c146106275761030d565b8063883164561461059757806395d89b41146105ba5761030d565b80636352211e1461052f5780636c0360eb1461054f57806370a08231146105645780637ac2ff7b146105845761030d565b806323b872dd1161020157806342966c68116101b557806349404b7c1161019a57806349404b7c146104e75780634aa4a4fc146104fa5780634f6ccce71461050f5761030d565b806342966c68146104c15780634659a494146104d45761030d565b806330adf81f116101e657806330adf81f146104775780633644e5151461048c57806342842e0e146104a15761030d565b806323b872dd146104375780632f745c59146104575761030d565b80630c49ccbe1161025857806313ead5621161023d57806313ead562146103e057806318160ddd146103f3578063219f5d17146104155761030d565b80630c49ccbe146103b757806312210e8a146103d85761030d565b806301ffc9a71461031257806306fdde0314610348578063081812fc1461036a578063095ea7b3146103975761030d565b3661030d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461030b576040805162461bcd60e51b815260206004820152600960248201527f4e6f742057455448390000000000000000000000000000000000000000000000604482015290519081900360640190fd5b005b600080fd5b34801561031e57600080fd5b5061033261032d3660046153a6565b61073b565b60405161033f919061591e565b60405180910390f35b34801561035457600080fd5b5061035d610776565b60405161033f9190615971565b34801561037657600080fd5b5061038a6103853660046156b8565b61080c565b60405161033f91906157e2565b3480156103a357600080fd5b5061030b6103b2366004615270565b610868565b6103ca6103c5366004615483565b61093e565b60405161033f929190615b42565b61030b610daa565b61038a6103ee366004615103565b610dbc565b3480156103ff57600080fd5b506104086110c9565b60405161033f9190615929565b610428610423366004615494565b6110da565b60405161033f93929190615afd565b34801561044357600080fd5b5061030b61045236600461515c565b611413565b34801561046357600080fd5b50610408610472366004615270565b61146a565b34801561048357600080fd5b50610408611495565b34801561049857600080fd5b506104086114b9565b3480156104ad57600080fd5b5061030b6104bc36600461515c565b611577565b61030b6104cf3660046156b8565b611592565b61030b6104e23660046152dc565b611661565b61030b6104f53660046156d0565b611714565b34801561050657600080fd5b5061038a611894565b34801561051b57600080fd5b5061040861052a3660046156b8565b6118b8565b34801561053b57600080fd5b5061038a61054a3660046156b8565b6118ce565b34801561055b57600080fd5b5061035d6118f6565b34801561057057600080fd5b5061040861057f3660046150af565b6118fb565b61030b6105923660046152dc565b611963565b6105aa6105a5366004615550565b611e0f565b60405161033f9493929190615b1e565b3480156105c657600080fd5b5061035d612370565b3480156105db57600080fd5b506105ef6105ea3660046156b8565b6123d1565b60405161033f9c9b9a99989796959493929190615b50565b34801561061357600080fd5b5061030b610622366004615243565b612600565b61030b6106353660046152dc565b612723565b61064d610648366004615337565b6127d5565b60405161033f91906158a0565b34801561066657600080fd5b5061030b61067536600461519c565b612915565b61030b6106883660046152dc565b612973565b34801561069957600080fd5b5061038a612a1b565b3480156106ae57600080fd5b5061035d6106bd3660046156b8565b612a3f565b3480156106ce57600080fd5b5061030b6106dd366004615717565b612b0e565b61030b6106f036600461529b565b612b8c565b34801561070157600080fd5b506103326107103660046150cb565b612c6f565b61030b6107233660046152dc565b612c9d565b6103ca61073636600461546c565b612d28565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081526020819052604090205460ff165b919050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156108025780601f106107d757610100808354040283529160200191610802565b820191906000526020600020905b8154815290600101906020018083116107e557829003601f168201915b5050505050905090565b600061081782613246565b61083c5760405162461bcd60e51b8152600401610833906159bb565b60405180910390fd5b506000908152600c60205260409020546c0100000000000000000000000090046001600160a01b031690565b6000610873826118ce565b9050806001600160a01b0316836001600160a01b031614156108c65760405162461bcd60e51b8152600401808060200182810382526021815260200180615ee26021913960400191505060405180910390fd5b806001600160a01b03166108d8613253565b6001600160a01b031614806108f457506108f481610710613253565b61092f5760405162461bcd60e51b8152600401808060200182810382526038815260200180615e0c6038913960400191505060405180910390fd5b6109398383613257565b505050565b600080823561094d33826132db565b6109695760405162461bcd60e51b815260040161083390615984565b836080013580610977613377565b11156109ca576040805162461bcd60e51b815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b60006109dc6040870160208801615562565b6001600160801b0316116109ef57600080fd5b84356000908152600c602090815260409182902060018101549092600160801b9091046001600160801b031691610a2a918901908901615562565b6001600160801b0316816001600160801b03161015610a4857600080fd5b60018281015469ffffffffffffffffffff166000908152600b60209081526040808320815160608101835281546001600160a01b039081168252919095015490811692850192909252600160a01b90910462ffffff1690830152610acc7f00000000000000000000000000000000000000000000000000000000000000008361337b565b60018501549091506001600160a01b0382169063a34123a7906a01000000000000000000008104600290810b91600160681b9004900b610b1260408e0160208f01615562565b6040518463ffffffff1660e01b8152600401610b309392919061594b565b6040805180830381600087803b158015610b4957600080fd5b505af1158015610b5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8191906156f4565b909850965060408901358810801590610b9e575088606001358710155b610bba5760405162461bcd60e51b815260040161083390615a18565b6001840154600090610bea9030906a01000000000000000000008104600290810b91600160681b9004900b613477565b9050600080836001600160a01b031663514ea4bf846040518263ffffffff1660e01b8152600401610c1b9190615929565b60a06040518083038186803b158015610c3357600080fd5b505afa158015610c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6b91906155ac565b50509250925050610c9087600201548303876001600160801b0316600160801b6134d1565b6004880180546fffffffffffffffffffffffffffffffff198116928e016001600160801b039182160181169290921790556003880154610cda91908303908816600160801b6134d1565b6004880180546001600160801b03808216938e01600160801b9283900482160116029190911790556002870182905560038701819055610d2060408d0160208e01615562565b86038760010160106101000a8154816001600160801b0302191690836001600160801b031602179055508b600001357f26f6a048ee9138f2c0ce266f322cb99228e8d619ae2bff30c67f8dcf9d2377b48d6020016020810190610d839190615562565b8d8d604051610d9493929190615afd565b60405180910390a2505050505050505050915091565b4715610dba57610dba3347613580565b565b6000836001600160a01b0316856001600160a01b031610610ddc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631698ee828686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018262ffffff168152602001935050505060206040518083038186803b158015610e6757600080fd5b505afa158015610e7b573d6000803e3d6000fd5b505050506040513d6020811015610e9157600080fd5b505190506001600160a01b038116610fe0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a16712958686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018262ffffff1681526020019350505050602060405180830381600087803b158015610f3057600080fd5b505af1158015610f44573d6000803e3d6000fd5b505050506040513d6020811015610f5a57600080fd5b5051604080517ff637731d0000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015291519293509083169163f637731d9160248082019260009290919082900301818387803b158015610fc357600080fd5b505af1158015610fd7573d6000803e3d6000fd5b505050506110c1565b6000816001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561101b57600080fd5b505afa15801561102f573d6000803e3d6000fd5b505050506040513d60e081101561104557600080fd5b505190506001600160a01b0381166110bf57816001600160a01b031663f637731d846040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156110a657600080fd5b505af11580156110ba573d6000803e3d6000fd5b505050505b505b949350505050565b60006110d56002613689565b905090565b60008060008360a00135806110ed613377565b1115611140576040805162461bcd60e51b815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b84356000908152600c6020908152604080832060018082015469ffffffffffffffffffff81168652600b855283862084516060808201875282546001600160a01b039081168352929094015480831682890190815262ffffff600160a01b9092048216838901908152885161014081018a528451861681529151909416818a01529251168287015230828501526a01000000000000000000008304600290810b810b608080850191909152600160681b909404810b900b60a0830152958c013560c0820152938b013560e0850152908a0135610100840152890135610120830152929061122c90613694565b6001870154939a50919850965091506000906112669030906a01000000000000000000008104600290810b91600160681b9004900b613477565b9050600080836001600160a01b031663514ea4bf846040518263ffffffff1660e01b81526004016112979190615929565b60a06040518083038186803b1580156112af57600080fd5b505afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e791906155ac565b50509250925050611323866002015483038760010160109054906101000a90046001600160801b03166001600160801b0316600160801b6134d1565b6004870180546001600160801b0380821690930183166fffffffffffffffffffffffffffffffff19909116179055600387015460018801546113739291840391600160801b9182900416906134d1565b6004870180546001600160801b03600160801b80830482169094018116840291811691909117909155600288018490556003880183905560018801805483810483168e018316909302929091169190911790556040518b35907f3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f906113fd908d908d908d90615afd565b60405180910390a2505050505050509193909250565b61142461141e613253565b826132db565b61145f5760405162461bcd60e51b8152600401808060200182810382526031815260200180615f036031913960400191505060405180910390fd5b6109398383836138cf565b6001600160a01b038216600090815260016020526040812061148c9083613a1b565b90505b92915050565b7f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad81565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611526613a27565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b031681526020019550505050505060405160208183030381529060405280519060200120905090565b61093983838360405180602001604052806000815250612915565b8061159d33826132db565b6115b95760405162461bcd60e51b815260040161083390615984565b6000828152600c602052604090206001810154600160801b90046001600160801b03161580156115f4575060048101546001600160801b0316155b801561161257506004810154600160801b90046001600160801b0316155b61162e5760405162461bcd60e51b815260040161083390615a86565b6000838152600c602052604081208181556001810182905560028101829055600381018290556004015561093983613a2b565b604080517f8fcbaf0c00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101879052606481018690526001608482015260ff851660a482015260c4810184905260e4810183905290516001600160a01b03881691638fcbaf0c9161010480830192600092919082900301818387803b1580156116f457600080fd5b505af1158015611708573d6000803e3d6000fd5b50505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561178357600080fd5b505afa158015611797573d6000803e3d6000fd5b505050506040513d60208110156117ad57600080fd5b5051905082811015611806576040805162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e742057455448390000000000000000000000000000604482015290519081900360640190fd5b8015610939577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561187257600080fd5b505af1158015611886573d6000803e3d6000fd5b505050506109398282613580565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806118c6600284613af8565b509392505050565b600061148f82604051806060016040528060298152602001615e6e6029913960029190613b16565b606090565b60006001600160a01b0382166119425760405162461bcd60e51b815260040180806020018281038252602a815260200180615e44602a913960400191505060405180910390fd5b6001600160a01b038216600090815260016020526040902061148f90613689565b8361196c613377565b11156119bf576040805162461bcd60e51b815260206004820152600e60248201527f5065726d69742065787069726564000000000000000000000000000000000000604482015290519081900360640190fd5b60006119c96114b9565b7f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad88886119f581613b23565b604080516020808201969096526001600160a01b03909416848201526060840192909252608083015260a08083018a90528151808403909101815260c0830182528051908401207f190100000000000000000000000000000000000000000000000000000000000060e084015260e283019490945261010280830194909452805180830390940184526101229091019052815191012090506000611a98876118ce565b9050806001600160a01b0316886001600160a01b03161415611aeb5760405162461bcd60e51b8152600401808060200182810382526027815260200180615d6f6027913960400191505060405180910390fd5b611af481613b62565b15611ccf576040805160208082018790528183018690527fff0000000000000000000000000000000000000000000000000000000000000060f889901b16606083015282516041818403018152606183018085527f1626ba7e0000000000000000000000000000000000000000000000000000000090526065830186815260858401948552815160a585015281516001600160a01b03871695631626ba7e958995919260c59091019185019080838360005b83811015611bbe578181015183820152602001611ba6565b50505050905090810190601f168015611beb5780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b158015611c0957600080fd5b505afa158015611c1d573d6000803e3d6000fd5b505050506040513d6020811015611c3357600080fd5b50517fffffffff00000000000000000000000000000000000000000000000000000000167f1626ba7e0000000000000000000000000000000000000000000000000000000014611cca576040805162461bcd60e51b815260206004820152600c60248201527f556e617574686f72697a65640000000000000000000000000000000000000000604482015290519081900360640190fd5b611dfb565b600060018387878760405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611d2b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611d93576040805162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015290519081900360640190fd5b816001600160a01b0316816001600160a01b031614611df9576040805162461bcd60e51b815260206004820152600c60248201527f556e617574686f72697a65640000000000000000000000000000000000000000604482015290519081900360640190fd5b505b611e058888613257565b5050505050505050565b60008060008084610140013580611e24613377565b1115611e77576040805162461bcd60e51b815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b604080516101408101909152600090611f439080611e9860208b018b6150af565b6001600160a01b03168152602001896020016020810190611eb991906150af565b6001600160a01b03168152602001611ed760608b0160408c0161569e565b62ffffff168152306020820152604001611ef760808b0160608c016153e6565b60020b8152602001611f0f60a08b0160808c016153e6565b60020b81526020018960a0013581526020018960c0013581526020018960e001358152602001896101000135815250613694565b92975090955093509050611fb7611f6261014089016101208a016150af565b600d80547fffffffffffffffffffff000000000000000000000000000000000000000000008116600175ffffffffffffffffffffffffffffffffffffffffffff92831690810190921617909155975087613b68565b6000611fe230611fcd60808b0160608c016153e6565b611fdd60a08c0160808d016153e6565b613477565b9050600080836001600160a01b031663514ea4bf846040518263ffffffff1660e01b81526004016120139190615929565b60a06040518083038186803b15801561202b57600080fd5b505afa15801561203f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206391906155ac565b5050925092505060006120dc8560405180606001604052808e600001602081019061208e91906150af565b6001600160a01b031681526020018e60200160208101906120af91906150af565b6001600160a01b031681526020018e60400160208101906120d0919061569e565b62ffffff169052613c96565b905060405180610140016040528060006bffffffffffffffffffffffff16815260200160006001600160a01b031681526020018269ffffffffffffffffffff1681526020018c606001602081019061213491906153e6565b60020b815260200161214c60a08e0160808f016153e6565b60020b81526020018a6001600160801b0316815260200184815260200183815260200160006001600160801b0316815260200160006001600160801b0316815250600c60008c815260200190815260200160002060008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160006101000a81548169ffffffffffffffffffff021916908369ffffffffffffffffffff160217905550606082015181600101600a6101000a81548162ffffff021916908360020b62ffffff160217905550608082015181600101600d6101000a81548162ffffff021916908360020b62ffffff16021790555060a08201518160010160106101000a8154816001600160801b0302191690836001600160801b0316021790555060c0820151816002015560e082015181600301556101008201518160040160006101000a8154816001600160801b0302191690836001600160801b031602179055506101208201518160040160106101000a8154816001600160801b0302191690836001600160801b03160217905550905050897f3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f8a8a8a60405161235b93929190615afd565b60405180910390a25050505050509193509193565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156108025780601f106107d757610100808354040283529160200191610802565b6000818152600c6020908152604080832081516101408101835281546bffffffffffffffffffffffff811682526001600160a01b036c010000000000000000000000009091041693810193909352600181015469ffffffffffffffffffff81169284018390526a01000000000000000000008104600290810b810b810b6060860152600160681b8204810b810b810b60808601526001600160801b03600160801b92839004811660a08701529083015460c0860152600383015460e0860152600490920154808316610100860152041661012083015282918291829182918291829182918291829182918291906124da5760405162461bcd60e51b815260040161083390615a4f565b6000600b6000836040015169ffffffffffffffffffff1669ffffffffffffffffffff1681526020019081526020016000206040518060600160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160149054906101000a900462ffffff1662ffffff1662ffffff1681525050905081600001518260200151826000015183602001518460400151866060015187608001518860a001518960c001518a60e001518b61010001518c61012001519d509d509d509d509d509d509d509d509d509d509d509d50505091939597999b5091939597999b565b612608613253565b6001600160a01b0316826001600160a01b0316141561266e576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b806005600061267b613253565b6001600160a01b0390811682526020808301939093526040918201600090812091871680825291909352912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016921515929092179091556126dd613253565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523360048201523060248201529051600019916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b15801561278d57600080fd5b505afa1580156127a1573d6000803e3d6000fd5b505050506040513d60208110156127b757600080fd5b505110156127cd576127cd868686868686611661565b505050505050565b60608167ffffffffffffffff811180156127ee57600080fd5b5060405190808252806020026020018201604052801561282257816020015b606081526020019060019003908161280d5790505b50905060005b8281101561290e576000803086868581811061284057fe5b90506020028101906128529190615bef565b6040516128609291906157d2565b600060405180830381855af49150503d806000811461289b576040519150601f19603f3d011682016040523d82523d6000602084013e6128a0565b606091505b5091509150816128ec576044815110156128b957600080fd5b600481019050808060200190518101906128d39190615402565b60405162461bcd60e51b81526004016108339190615971565b808484815181106128f957fe5b60209081029190910101525050600101612828565b5092915050565b612926612920613253565b836132db565b6129615760405162461bcd60e51b8152600401808060200182810382526031815260200180615f036031913960400191505060405180910390fd5b61296d84848484613de6565b50505050565b604080517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152905186916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b1580156129db57600080fd5b505afa1580156129ef573d6000803e3d6000fd5b505050506040513d6020811015612a0557600080fd5b505110156127cd576127cd868686868686612c9d565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060612a4a82613246565b612a5357600080fd5b6040517fe9dc63750000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e9dc637590612aba9030908690600401615932565b60006040518083038186803b158015612ad257600080fd5b505afa158015612ae6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261148f9190810190615402565b6000612b1c828401846154a5565b9050612b4c7f00000000000000000000000000000000000000000000000000000000000000008260000151613e38565b508415612b67578051516020820151612b6791903388613e5b565b8315612b8557612b8581600001516020015182602001513387613e5b565b5050505050565b6000836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612bdb57600080fd5b505afa158015612bef573d6000803e3d6000fd5b505050506040513d6020811015612c0557600080fd5b5051905082811015612c5e576040805162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e7420746f6b656e0000000000000000000000000000604482015290519081900360640190fd5b801561296d5761296d848383613feb565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b604080517fd505accf000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018790526064810186905260ff8516608482015260a4810184905260c4810183905290516001600160a01b0388169163d505accf9160e480830192600092919082900301818387803b1580156116f457600080fd5b6000808235612d3733826132db565b612d535760405162461bcd60e51b815260040161083390615984565b6000612d656060860160408701615562565b6001600160801b03161180612d9257506000612d876080860160608701615562565b6001600160801b0316115b612d9b57600080fd5b600080612dae60408701602088016150af565b6001600160a01b031614612dd157612dcc60408601602087016150af565b612dd3565b305b85356000908152600c6020908152604080832060018082015469ffffffffffffffffffff168552600b8452828520835160608101855281546001600160a01b039081168252919092015490811694820194909452600160a01b90930462ffffff169183019190915292935090612e697f00000000000000000000000000000000000000000000000000000000000000008361337b565b600484015460018501549192506001600160801b0380821692600160801b92839004821692900416156130865760018501546040517fa34123a70000000000000000000000000000000000000000000000000000000081526001600160a01b0385169163a34123a791612f00916a01000000000000000000008104600290810b92600160681b909204900b9060009060040161594b565b6040805180830381600087803b158015612f1957600080fd5b505af1158015612f2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5191906156f4565b5050600185015460009081906001600160a01b0386169063514ea4bf90612f969030906a01000000000000000000008104600290810b91600160681b9004900b613477565b6040518263ffffffff1660e01b8152600401612fb29190615929565b60a06040518083038186803b158015612fca57600080fd5b505afa158015612fde573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300291906155ac565b5050925092505061303e876002015483038860010160109054906101000a90046001600160801b03166001600160801b0316600160801b6134d1565b84019350613077876003015482038860010160109054906101000a90046001600160801b03166001600160801b0316600160801b6134d1565b60028801929092556003870155015b6000806001600160801b0384166130a360608e0160408f01615562565b6001600160801b0316116130c6576130c160608d0160408e01615562565b6130c8565b835b836001600160801b03168d60600160208101906130e59190615562565b6001600160801b0316116131085761310360808e0160608f01615562565b61310a565b835b60018901546040517f4f1eb3d80000000000000000000000000000000000000000000000000000000081529294509092506001600160a01b03871691634f1eb3d89161317d918c916a01000000000000000000008104600290810b92600160681b909204900b9088908890600401615839565b6040805180830381600087803b15801561319657600080fd5b505af11580156131aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ce919061557e565b6004890180546fffffffffffffffffffffffffffffffff196001600160801b03918216600160801b878a0384160217168689038216179091556040519281169d50169a508c35907f40d0efd1a53d60ecbf40971b9daf7dc90178c3aadc7aab1765632738fa8b8f0190610d94908b9086908690615876565b600061148f60028361417b565b3390565b6000818152600c6020526040902080546bffffffffffffffffffffffff166c010000000000000000000000006001600160a01b0385169081029190911790915581906132a2826118ce565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006132e682613246565b6133215760405162461bcd60e51b815260040180806020018281038252602c815260200180615de0602c913960400191505060405180910390fd5b600061332c836118ce565b9050806001600160a01b0316846001600160a01b031614806133675750836001600160a01b031661335c8461080c565b6001600160a01b0316145b806110c157506110c18185612c6f565b4290565b600081602001516001600160a01b031682600001516001600160a01b0316106133a357600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516bffffffffffffffffffffffff19606086901b16602080830191909152600285810b60e890811b60348501529085900b901b60378301528251601a818403018152603a90920190925280519101205b9392505050565b600080806000198587098686029250828110908390030390508061350757600084116134fc57600080fd5b5082900490506134ca565b80841161351357600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b604080516000808252602082019092526001600160a01b0384169083906040518082805190602001908083835b602083106135cc5780518252601f1990920191602091820191016135ad565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461362e576040519150601f19603f3d011682016040523d82523d6000602084013e613633565b606091505b5050905080610939576040805162461bcd60e51b815260206004820152600360248201527f5354450000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600061148f82614187565b6000806000806000604051806060016040528087600001516001600160a01b0316815260200187602001516001600160a01b03168152602001876040015162ffffff1681525090506137067f00000000000000000000000000000000000000000000000000000000000000008261337b565b91506000826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561374357600080fd5b505afa158015613757573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377b919061560d565b50505050505090506000613792886080015161418b565b905060006137a38960a0015161418b565b90506137ba8383838c60c001518d60e001516144d9565b9750505050816001600160a01b0316633c8a7d8d876060015188608001518960a00151896040518060400160405280888152602001336001600160a01b031681525060405160200161380c9190615abd565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161383b9594939291906157f6565b6040805180830381600087803b15801561385457600080fd5b505af1158015613868573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061388c91906156f4565b610100880151919550935084108015906138ab57508561012001518310155b6138c75760405162461bcd60e51b815260040161083390615a18565b509193509193565b826001600160a01b03166138e2826118ce565b6001600160a01b0316146139275760405162461bcd60e51b8152600401808060200182810382526029815260200180615eb96029913960400191505060405180910390fd5b6001600160a01b03821661396c5760405162461bcd60e51b8152600401808060200182810382526024815260200180615d966024913960400191505060405180910390fd5b613977838383610939565b613982600082613257565b6001600160a01b03831660009081526001602052604090206139a4908261459d565b506001600160a01b03821660009081526001602052604090206139c790826145a9565b506139d4600282846145b5565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061148c83836145cb565b4690565b6000613a36826118ce565b9050613a4481600084610939565b613a4f600083613257565b6000828152600860205260409020546002600019610100600184161502019091160415613a8d576000828152600860205260408120613a8d9161501f565b6001600160a01b0381166000908152600160205260409020613aaf908361459d565b50613abb60028361462f565b5060405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000808080613b07868661463b565b909450925050505b9250929050565b60006110c18484846146b6565b6000908152600c6020526040902080546bffffffffffffffffffffffff19811660016bffffffffffffffffffffffff9283169081019092161790915590565b3b151590565b6001600160a01b038216613bc3576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b613bcc81613246565b15613c1e576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b613c2a60008383610939565b6001600160a01b0382166000908152600160205260409020613c4c90826145a9565b50613c59600282846145b5565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6001600160a01b0382166000908152600a602052604090205469ffffffffffffffffffff168061148f5750600d8054600169ffffffffffffffffffff76010000000000000000000000000000000000000000000080840482168381019092160275ffffffffffffffffffffffffffffffffffffffffffff909316929092179092556001600160a01b038085166000908152600a6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffff000000000000000000001686179055848352600b825291829020865181549085167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617825591870151950180549287015162ffffff16600160a01b027fffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffff969094169290911691909117939093161790915592915050565b613df18484846138cf565b613dfd84848484614780565b61296d5760405162461bcd60e51b8152600401808060200182810382526032815260200180615d3d6032913960400191505060405180910390fd5b6000613e44838361337b565b9050336001600160a01b0382161461148f57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316148015613e9c5750804710155b15613fbe577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015613efc57600080fd5b505af1158015613f10573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015613f8c57600080fd5b505af1158015613fa0573d6000803e3d6000fd5b505050506040513d6020811015613fb657600080fd5b5061296d9050565b6001600160a01b038316301415613fdf57613fda848383613feb565b61296d565b61296d8484848461495c565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781529251825160009485949389169392918291908083835b602083106140955780518252601f199092019160209182019101614076565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146140f7576040519150601f19603f3d011682016040523d82523d6000602084013e6140fc565b606091505b509150915081801561412a57508051158061412a575080806020019051602081101561412757600080fd5b50515b612b85576040805162461bcd60e51b815260206004820152600260248201527f5354000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600061148c8383614af4565b5490565b60008060008360020b126141a2578260020b6141aa565b8260020b6000035b9050620d89e8811115614204576040805162461bcd60e51b815260206004820152600160248201527f5400000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60006001821661421857600160801b61422a565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561425e576ffff97272373d413259a46990580e213a0260801c5b600482161561427d576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b600882161561429c576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b60108216156142bb576fffcb9843d60f6159c9db58835c9266440260801c5b60208216156142da576fff973b41fa98c081472e6896dfb254c00260801c5b60408216156142f9576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615614318576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615614338576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615614358576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615614378576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615614398576fe7159475a2c29b7443b29c7fa6e889d90260801c5b6110008216156143b8576fd097f3bdfd2022b8845ad8f792aa58250260801c5b6120008216156143d8576fa9f746462d870fdf8a65dc1f90e061e50260801c5b6140008216156143f8576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615614418576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615614439576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615614459576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615614478576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615614495576b048a170391f7dc42444e8fa20260801c5b60008460020b13156144b05780600019816144ac57fe5b0490505b6401000000008106156144c45760016144c7565b60005b60ff16602082901c0192505050919050565b6000836001600160a01b0316856001600160a01b031611156144f9579293925b846001600160a01b0316866001600160a01b0316116145245761451d858585614b0c565b9050614594565b836001600160a01b0316866001600160a01b0316101561458657600061454b878686614b0c565b9050600061455a878986614b78565b9050806001600160801b0316826001600160801b03161061457b578061457d565b815b92505050614594565b614591858584614b78565b90505b95945050505050565b600061148c8383614bbe565b600061148c8383614c84565b60006110c184846001600160a01b038516614cce565b8154600090821061460d5760405162461bcd60e51b8152600401808060200182810382526022815260200180615d1b6022913960400191505060405180910390fd5b82600001828154811061461c57fe5b9060005260206000200154905092915050565b600061148c8383614d65565b81546000908190831061467f5760405162461bcd60e51b8152600401808060200182810382526022815260200180615e976022913960400191505060405180910390fd5b600084600001848154811061469057fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816147515760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156147165781810151838201526020016146fe565b50505050905090810190601f1680156147435780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5084600001600182038154811061476457fe5b9060005260206000209060020201600101549150509392505050565b6000614794846001600160a01b0316613b62565b6147a0575060016110c1565b60006148f17f150b7a02000000000000000000000000000000000000000000000000000000006147ce613253565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561483557818101518382015260200161481d565b50505050905090810190601f1680156148625780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001615d3d603291396001600160a01b0388169190614e39565b9050600081806020019051602081101561490a57600080fd5b50517fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001492505050949350505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000178152925182516000948594938a169392918291908083835b60208310614a0e5780518252601f1990920191602091820191016149ef565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614a70576040519150601f19603f3d011682016040523d82523d6000602084013e614a75565b606091505b5091509150818015614aa3575080511580614aa35750808060200190516020811015614aa057600080fd5b50515b6127cd576040805162461bcd60e51b815260206004820152600360248201527f5354460000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60009081526001919091016020526040902054151590565b6000826001600160a01b0316846001600160a01b03161115614b2c579192915b6000614b58856001600160a01b0316856001600160a01b03166c010000000000000000000000006134d1565b9050614594614b7384838888036001600160a01b03166134d1565b614e48565b6000826001600160a01b0316846001600160a01b03161115614b98579192915b6110c1614b73836c010000000000000000000000008787036001600160a01b03166134d1565b60008181526001830160205260408120548015614c7a5783546000198083019190810190600090879083908110614bf157fe5b9060005260206000200154905080876000018481548110614c0e57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080614c3e57fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061148f565b600091505061148f565b6000614c908383614af4565b614cc65750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561148f565b50600061148f565b600082815260018401602052604081205480614d335750506040805180820182528381526020808201848152865460018181018955600089815284812095516002909302909501918255915190820155865486845281880190925292909120556134ca565b82856000016001830381548110614d4657fe5b90600052602060002090600202016001018190555060009150506134ca565b60008181526001830160205260408120548015614c7a5783546000198083019190810190600090879083908110614d9857fe5b9060005260206000209060020201905080876000018481548110614db857fe5b600091825260208083208454600290930201918255600193840154918401919091558354825289830190526040902090840190558654879080614df757fe5b600082815260208082206002600019909401938402018281556001908101839055929093558881528982019092526040822091909155945061148f9350505050565b60606110c18484600085614e5e565b806001600160801b038116811461077157600080fd5b606082471015614e9f5760405162461bcd60e51b8152600401808060200182810382526026815260200180615dba6026913960400191505060405180910390fd5b614ea885613b62565b614ef9576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310614f375780518252601f199092019160209182019101614f18565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614f99576040519150601f19603f3d011682016040523d82523d6000602084013e614f9e565b606091505b5091509150614fae828286614fb9565b979650505050505050565b60608315614fc85750816134ca565b825115614fd85782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156147165781810151838201526020016146fe565b50805460018160011615610100020316600290046000825580601f106150455750615063565b601f0160209004906000526020600020908101906150639190615066565b50565b5b8082111561507b5760008155600101615067565b5090565b803561077181615cc4565b805161ffff8116811461077157600080fd5b803562ffffff8116811461077157600080fd5b6000602082840312156150c0578081fd5b81356134ca81615cc4565b600080604083850312156150dd578081fd5b82356150e881615cc4565b915060208301356150f881615cc4565b809150509250929050565b60008060008060808587031215615118578182fd5b843561512381615cc4565b9350602085013561513381615cc4565b92506151416040860161509c565b9150606085013561515181615cc4565b939692955090935050565b600080600060608486031215615170578081fd5b833561517b81615cc4565b9250602084013561518b81615cc4565b929592945050506040919091013590565b600080600080608085870312156151b1578182fd5b84356151bc81615cc4565b935060208501356151cc81615cc4565b925060408501359150606085013567ffffffffffffffff8111156151ee578182fd5b8501601f810187136151fe578182fd5b803561521161520c82615c76565b615c52565b818152886020838501011115615225578384fd5b81602084016020830137908101602001929092525092959194509250565b60008060408385031215615255578182fd5b823561526081615cc4565b915060208301356150f881615cd9565b60008060408385031215615282578182fd5b823561528d81615cc4565b946020939093013593505050565b6000806000606084860312156152af578081fd5b83356152ba81615cc4565b92506020840135915060408401356152d181615cc4565b809150509250925092565b60008060008060008060c087890312156152f4578384fd5b86356152ff81615cc4565b95506020870135945060408701359350606087013561531d81615d0b565b9598949750929560808101359460a0909101359350915050565b60008060208385031215615349578182fd5b823567ffffffffffffffff80821115615360578384fd5b818501915085601f830112615373578384fd5b813581811115615381578485fd5b8660208083028501011115615394578485fd5b60209290920196919550909350505050565b6000602082840312156153b7578081fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146134ca578182fd5b6000602082840312156153f7578081fd5b81356134ca81615ce7565b600060208284031215615413578081fd5b815167ffffffffffffffff811115615429578182fd5b8201601f81018413615439578182fd5b805161544761520c82615c76565b81815285602083850101111561545b578384fd5b614594826020830160208601615c98565b60006080828403121561547d578081fd5b50919050565b600060a0828403121561547d578081fd5b600060c0828403121561547d578081fd5b600081830360808112156154b7578182fd5b6040516040810167ffffffffffffffff82821081831117156154d557fe5b8160405260608412156154e6578485fd5b60a08301935081841081851117156154fa57fe5b50826040528435925061550c83615cc4565b91825260208401359161551e83615cc4565b8260608301526155306040860161509c565b608083015281526155436060850161507f565b6020820152949350505050565b6000610160828403121561547d578081fd5b600060208284031215615573578081fd5b81356134ca81615cf6565b60008060408385031215615590578182fd5b825161559b81615cf6565b60208401519092506150f881615cf6565b600080600080600060a086880312156155c3578283fd5b85516155ce81615cf6565b80955050602086015193506040860151925060608601516155ee81615cf6565b60808701519092506155ff81615cf6565b809150509295509295909350565b600080600080600080600060e0888a031215615627578485fd5b875161563281615cc4565b602089015190975061564381615ce7565b95506156516040890161508a565b945061565f6060890161508a565b935061566d6080890161508a565b925060a088015161567d81615d0b565b60c089015190925061568e81615cd9565b8091505092959891949750929550565b6000602082840312156156af578081fd5b61148c8261509c565b6000602082840312156156c9578081fd5b5035919050565b600080604083850312156156e2578182fd5b8235915060208301356150f881615cc4565b60008060408385031215615706578182fd5b505080516020909101519092909150565b6000806000806060858703121561572c578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615751578384fd5b818701915087601f830112615764578384fd5b813581811115615772578485fd5b886020828501011115615783578485fd5b95989497505060200194505050565b600081518084526157aa816020860160208601615c98565b601f01601f19169290920160200192915050565b60020b9052565b6001600160801b03169052565b6000828483379101908152919050565b6001600160a01b0391909116815260200190565b60006001600160a01b03871682528560020b60208301528460020b60408301526001600160801b038416606083015260a06080830152614fae60a0830184615792565b6001600160a01b03959095168552600293840b60208601529190920b60408401526001600160801b03918216606084015216608082015260a00190565b6001600160a01b039390931683526001600160801b03918216602084015216604082015260600190565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015615911577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526158ff858351615792565b945092850192908501906001016158c5565b5092979650505050505050565b901515815260200190565b90815260200190565b6001600160a01b03929092168252602082015260400190565b600293840b81529190920b60208201526001600160801b03909116604082015260600190565b60006020825261148c6020830184615792565b6020808252600c908201527f4e6f7420617070726f7665640000000000000000000000000000000000000000604082015260600190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201527f697374656e7420746f6b656e0000000000000000000000000000000000000000606082015260800190565b60208082526014908201527f507269636520736c69707061676520636865636b000000000000000000000000604082015260600190565b60208082526010908201527f496e76616c696420746f6b656e20494400000000000000000000000000000000604082015260600190565b6020808252600b908201527f4e6f7420636c6561726564000000000000000000000000000000000000000000604082015260600190565b815180516001600160a01b03908116835260208083015182168185015260409283015162ffffff1692840192909252920151909116606082015260800190565b6001600160801b039390931683526020830191909152604082015260600190565b9384526001600160801b039290921660208401526040830152606082015260800190565b918252602082015260400190565b6bffffffffffffffffffffffff8d1681526001600160a01b038c811660208301528b811660408301528a16606082015262ffffff89166080820152600288900b60a08201526101808101615ba760c08301896157be565b615bb460e08301886157c5565b8561010083015284610120830152615bd06101408301856157c5565b615bde6101608301846157c5565b9d9c50505050505050505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615c23578283fd5b83018035915067ffffffffffffffff821115615c3d578283fd5b602001915036819003821315613b0f57600080fd5b60405181810167ffffffffffffffff81118282101715615c6e57fe5b604052919050565b600067ffffffffffffffff821115615c8a57fe5b50601f01601f191660200190565b60005b83811015615cb3578181015183820152602001615c9b565b8381111561296d5750506000910152565b6001600160a01b038116811461506357600080fd5b801515811461506357600080fd5b8060020b811461506357600080fd5b6001600160801b038116811461506357600080fd5b60ff8116811461506357600080fdfe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732315065726d69743a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a164736f6c6343000706000a\"\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/Oracle.json",
    "content": "{\n  \"address\": \"0xBD9F4bE886653177D22fA9c79FD0DFc41407fC89\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_base\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_quote\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_secondsAgoToStartOfTwap\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_secondsAgoToEndOfTwap\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getHistoricalTwap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"getMaxPeriod\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        }\n      ],\n      \"name\": \"getTimeWeightedAverageTickSafe\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"timeWeightedAverageTick\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_pool\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_base\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_quote\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"_period\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"_checkPeriod\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getTwap\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0xbdc943e7539c8291bdc621977da530c276fbfc71876d2b05abe6854ef7754dba\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xf668606B896389066a39B132741763e1ca6d76a2\",\n    \"contractAddress\": \"0xBD9F4bE886653177D22fA9c79FD0DFc41407fC89\",\n    \"transactionIndex\": 15,\n    \"gasUsed\": \"874024\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x79d874bdb9f493f14de830b7f8903c356ae2e0906a63a5ac403b268a600ad21d\",\n    \"transactionHash\": \"0xbdc943e7539c8291bdc621977da530c276fbfc71876d2b05abe6854ef7754dba\",\n    \"logs\": [],\n    \"blockNumber\": 11808026,\n    \"cumulativeGasUsed\": \"2163560\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"5f450d03d2b8109eaf06de68c57d8c2b\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_base\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_quote\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_secondsAgoToStartOfTwap\\\",\\\"type\\\":\\\"uint32\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_secondsAgoToEndOfTwap\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getHistoricalTwap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"getMaxPeriod\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"}],\\\"name\\\":\\\"getTimeWeightedAverageTickSafe\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"timeWeightedAverageTick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_pool\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_base\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_quote\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint32\\\",\\\"name\\\":\\\"_period\\\",\\\"type\\\":\\\"uint32\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"_checkPeriod\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getTwap\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"details\\\":\\\"if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"getHistoricalTwap(address,address,address,uint32,uint32)\\\":{\\\"details\\\":\\\"if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\",\\\"params\\\":{\\\"_base\\\":\\\"base currency. to get eth/usd price, eth is base token\\\",\\\"_pool\\\":\\\"uniswap pool address\\\",\\\"_quote\\\":\\\"quote currency. to get eth/usd price, usd is the quote currency\\\",\\\"_secondsAgoToEndOfTwap\\\":\\\"amount of seconds in the past to end calculating time-weighted average\\\",\\\"_secondsAgoToStartOfTwap\\\":\\\"amount of seconds in the past to start calculating time-weighted average\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"price of 1 base currency in quote currency. scaled by 1e18\\\"}},\\\"getMaxPeriod(address)\\\":{\\\"params\\\":{\\\"_pool\\\":\\\"uniswap pool address\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"max period can be used to request twap\\\"}},\\\"getTimeWeightedAverageTickSafe(address,uint32)\\\":{\\\"details\\\":\\\"this function will not revert\\\",\\\"params\\\":{\\\"_period\\\":\\\"period in second that we want to calculate average on\\\",\\\"_pool\\\":\\\"address of the pool\\\"},\\\"returns\\\":{\\\"timeWeightedAverageTick\\\":\\\"the time weighted average tick\\\"}},\\\"getTwap(address,address,address,uint32,bool)\\\":{\\\"details\\\":\\\"if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\",\\\"params\\\":{\\\"_base\\\":\\\"base currency. to get eth/usd price, eth is base token\\\",\\\"_period\\\":\\\"number of seconds in the past to start calculating time-weighted average\\\",\\\"_pool\\\":\\\"uniswap pool address\\\",\\\"_quote\\\":\\\"quote currency. to get eth/usd price, usd is the quote currency\\\"},\\\"returns\\\":{\\\"_0\\\":\\\"price of 1 base currency in quote currency. scaled by 1e18\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"getHistoricalTwap(address,address,address,uint32,uint32)\\\":{\\\"notice\\\":\\\"get twap for a specific period of time, converted with base & quote token decimals\\\"},\\\"getMaxPeriod(address)\\\":{\\\"notice\\\":\\\"get the max period that can be used to request twap\\\"},\\\"getTimeWeightedAverageTickSafe(address,uint32)\\\":{\\\"notice\\\":\\\"get time weighed average tick, not converted to price\\\"},\\\"getTwap(address,address,address,uint32,bool)\\\":{\\\"notice\\\":\\\"get twap converted with base & quote token decimals\\\"}},\\\"notice\\\":\\\"read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/Oracle.sol\\\":\\\"Oracle\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport './pool/IUniswapV3PoolImmutables.sol';\\\\nimport './pool/IUniswapV3PoolState.sol';\\\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\\\nimport './pool/IUniswapV3PoolActions.sol';\\\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\\\nimport './pool/IUniswapV3PoolEvents.sol';\\\\n\\\\n/// @title The interface for a Uniswap V3 Pool\\\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\\\n/// to the ERC20 specification\\\\n/// @dev The pool interface is broken up into many smaller pieces\\\\ninterface IUniswapV3Pool is\\\\n    IUniswapV3PoolImmutables,\\\\n    IUniswapV3PoolState,\\\\n    IUniswapV3PoolDerivedState,\\\\n    IUniswapV3PoolActions,\\\\n    IUniswapV3PoolOwnerActions,\\\\n    IUniswapV3PoolEvents\\\\n{\\\\n\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfe6113d518466cd6652c85b111e01f33eb62157f49ae5ed7d5a3947a2044adb1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissionless pool actions\\\\n/// @notice Contains pool methods that can be called by anyone\\\\ninterface IUniswapV3PoolActions {\\\\n    /// @notice Sets the initial price for the pool\\\\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\\\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\\\n    function initialize(uint160 sqrtPriceX96) external;\\\\n\\\\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\\\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\\\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\\\n    /// @param recipient The address for which the liquidity will be created\\\\n    /// @param tickLower The lower tick of the position in which to add liquidity\\\\n    /// @param tickUpper The upper tick of the position in which to add liquidity\\\\n    /// @param amount The amount of liquidity to mint\\\\n    /// @param data Any data that should be passed through to the callback\\\\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\\\n    function mint(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount,\\\\n        bytes calldata data\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Collects tokens owed to a position\\\\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\\\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\\\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\\\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\\\n    /// @param recipient The address which should receive the fees collected\\\\n    /// @param tickLower The lower tick of the position for which to collect fees\\\\n    /// @param tickUpper The upper tick of the position for which to collect fees\\\\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\\\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(\\\\n        address recipient,\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n\\\\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\\\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\\\n    /// @dev Fees must be collected separately via a call to #collect\\\\n    /// @param tickLower The lower tick of the position for which to burn liquidity\\\\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\\\\n    /// @param amount How much liquidity to burn\\\\n    /// @return amount0 The amount of token0 sent to the recipient\\\\n    /// @return amount1 The amount of token1 sent to the recipient\\\\n    function burn(\\\\n        int24 tickLower,\\\\n        int24 tickUpper,\\\\n        uint128 amount\\\\n    ) external returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Swap token0 for token1, or token1 for token0\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\\\n    /// @param recipient The address to receive the output of the swap\\\\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\\\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\\\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\\\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\\\n    /// @param data Any data to be passed through to the callback\\\\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\\\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\\\n    function swap(\\\\n        address recipient,\\\\n        bool zeroForOne,\\\\n        int256 amountSpecified,\\\\n        uint160 sqrtPriceLimitX96,\\\\n        bytes calldata data\\\\n    ) external returns (int256 amount0, int256 amount1);\\\\n\\\\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\\\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\\\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\\\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\\\n    /// @param recipient The address which will receive the token0 and token1 amounts\\\\n    /// @param amount0 The amount of token0 to send\\\\n    /// @param amount1 The amount of token1 to send\\\\n    /// @param data Any data to be passed through to the callback\\\\n    function flash(\\\\n        address recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        bytes calldata data\\\\n    ) external;\\\\n\\\\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\\\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\\\n    /// the input observationCardinalityNext.\\\\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\\\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9453dd0e7442188667d01d9b65de3f1e14e9511ff3e303179a15f6fc267f7634\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that is not stored\\\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\\\n/// blockchain. The functions here may have variable gas costs.\\\\ninterface IUniswapV3PoolDerivedState {\\\\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\\\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\\\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\\\n    /// you must call it with secondsAgos = [3600, 0].\\\\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\\\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\\\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\\\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\\\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\\\n    /// timestamp\\\\n    function observe(uint32[] calldata secondsAgos)\\\\n        external\\\\n        view\\\\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\\\\n\\\\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\\\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\\\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\\\n    /// snapshot is taken and the second snapshot is taken.\\\\n    /// @param tickLower The lower tick of the range\\\\n    /// @param tickUpper The upper tick of the range\\\\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\\\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\\\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\\\\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            int56 tickCumulativeInside,\\\\n            uint160 secondsPerLiquidityInsideX128,\\\\n            uint32 secondsInside\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe603ac5b17ecdee73ba2b27efdf386c257a19c14206e87eee77e2017b742d9e5\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Events emitted by a pool\\\\n/// @notice Contains all events emitted by the pool\\\\ninterface IUniswapV3PoolEvents {\\\\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\\\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\\\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\\\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\\\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\\\\n\\\\n    /// @notice Emitted when liquidity is minted for a given position\\\\n    /// @param sender The address that minted the liquidity\\\\n    /// @param owner The owner of the position and recipient of any minted liquidity\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity minted to the position range\\\\n    /// @param amount0 How much token0 was required for the minted liquidity\\\\n    /// @param amount1 How much token1 was required for the minted liquidity\\\\n    event Mint(\\\\n        address sender,\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when fees are collected by the owner of a position\\\\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\\\n    /// @param owner The owner of the position for which fees are collected\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount0 The amount of token0 fees collected\\\\n    /// @param amount1 The amount of token1 fees collected\\\\n    event Collect(\\\\n        address indexed owner,\\\\n        address recipient,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount0,\\\\n        uint128 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted when a position's liquidity is removed\\\\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\\\n    /// @param owner The owner of the position for which liquidity is removed\\\\n    /// @param tickLower The lower tick of the position\\\\n    /// @param tickUpper The upper tick of the position\\\\n    /// @param amount The amount of liquidity to remove\\\\n    /// @param amount0 The amount of token0 withdrawn\\\\n    /// @param amount1 The amount of token1 withdrawn\\\\n    event Burn(\\\\n        address indexed owner,\\\\n        int24 indexed tickLower,\\\\n        int24 indexed tickUpper,\\\\n        uint128 amount,\\\\n        uint256 amount0,\\\\n        uint256 amount1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any swaps between token0 and token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the output of the swap\\\\n    /// @param amount0 The delta of the token0 balance of the pool\\\\n    /// @param amount1 The delta of the token1 balance of the pool\\\\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\\\n    /// @param liquidity The liquidity of the pool after the swap\\\\n    /// @param tick The log base 1.0001 of price of the pool after the swap\\\\n    event Swap(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        int256 amount0,\\\\n        int256 amount1,\\\\n        uint160 sqrtPriceX96,\\\\n        uint128 liquidity,\\\\n        int24 tick\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for any flashes of token0/token1\\\\n    /// @param sender The address that initiated the swap call, and that received the callback\\\\n    /// @param recipient The address that received the tokens from flash\\\\n    /// @param amount0 The amount of token0 that was flashed\\\\n    /// @param amount1 The amount of token1 that was flashed\\\\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\\\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\\\n    event Flash(\\\\n        address indexed sender,\\\\n        address indexed recipient,\\\\n        uint256 amount0,\\\\n        uint256 amount1,\\\\n        uint256 paid0,\\\\n        uint256 paid1\\\\n    );\\\\n\\\\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\\\\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\\\n    /// just before a mint/swap/burn.\\\\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\\\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\\\n    event IncreaseObservationCardinalityNext(\\\\n        uint16 observationCardinalityNextOld,\\\\n        uint16 observationCardinalityNextNew\\\\n    );\\\\n\\\\n    /// @notice Emitted when the protocol fee is changed by the pool\\\\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\\\\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\\\\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\\\\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\\\\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\\\\n\\\\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\\\n    /// @param sender The address that collects the protocol fees\\\\n    /// @param recipient The address that receives the collected protocol fees\\\\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\\\\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\\\\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8071514d0fe5d17d6fbd31c191cdfb703031c24e0ece3621d88ab10e871375cd\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that never changes\\\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\\\ninterface IUniswapV3PoolImmutables {\\\\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\\\n    /// @return The contract address\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @notice The first of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token0() external view returns (address);\\\\n\\\\n    /// @notice The second of the two tokens of the pool, sorted by address\\\\n    /// @return The token contract address\\\\n    function token1() external view returns (address);\\\\n\\\\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\\\n    /// @return The fee\\\\n    function fee() external view returns (uint24);\\\\n\\\\n    /// @notice The pool tick spacing\\\\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\\\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\\\n    /// This value is an int24 to avoid casting even though it is always positive.\\\\n    /// @return The tick spacing\\\\n    function tickSpacing() external view returns (int24);\\\\n\\\\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\\\\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\\\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\\\n    /// @return The max amount of liquidity per tick\\\\n    function maxLiquidityPerTick() external view returns (uint128);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Permissioned pool actions\\\\n/// @notice Contains pool methods that may only be called by the factory owner\\\\ninterface IUniswapV3PoolOwnerActions {\\\\n    /// @notice Set the denominator of the protocol's % share of the fees\\\\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\\\\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\\\\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\\\n\\\\n    /// @notice Collect the protocol fee accrued to the pool\\\\n    /// @param recipient The address to which collected protocol fees should be sent\\\\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\\\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\\\n    /// @return amount0 The protocol fee collected in token0\\\\n    /// @return amount1 The protocol fee collected in token1\\\\n    function collectProtocol(\\\\n        address recipient,\\\\n        uint128 amount0Requested,\\\\n        uint128 amount1Requested\\\\n    ) external returns (uint128 amount0, uint128 amount1);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Pool state that can change\\\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\\\n/// per transaction\\\\ninterface IUniswapV3PoolState {\\\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\\\n    /// when accessed externally.\\\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\\\n    /// boundary.\\\\n    /// observationIndex The index of the last oracle observation that was written,\\\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\\\n    /// unlocked Whether the pool is currently locked to reentrancy\\\\n    function slot0()\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint160 sqrtPriceX96,\\\\n            int24 tick,\\\\n            uint16 observationIndex,\\\\n            uint16 observationCardinality,\\\\n            uint16 observationCardinalityNext,\\\\n            uint8 feeProtocol,\\\\n            bool unlocked\\\\n        );\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\\\n\\\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\\\n    /// @dev This value can overflow the uint256\\\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\\\n\\\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\\\n\\\\n    /// @notice The currently in range liquidity available to the pool\\\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\\\n    function liquidity() external view returns (uint128);\\\\n\\\\n    /// @notice Look up information about a specific tick in the pool\\\\n    /// @param tick The tick to look up\\\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\\\n    /// tick upper,\\\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\\\n    /// a specific position.\\\\n    function ticks(int24 tick)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 liquidityGross,\\\\n            int128 liquidityNet,\\\\n            uint256 feeGrowthOutside0X128,\\\\n            uint256 feeGrowthOutside1X128,\\\\n            int56 tickCumulativeOutside,\\\\n            uint160 secondsPerLiquidityOutsideX128,\\\\n            uint32 secondsOutside,\\\\n            bool initialized\\\\n        );\\\\n\\\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\\\n\\\\n    /// @notice Returns the information about a position by the position's key\\\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\\\n    /// @return _liquidity The amount of liquidity in the position,\\\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\\\n    function positions(bytes32 key)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint128 _liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    /// @notice Returns data about a specific observation index\\\\n    /// @param index The element of the observations array to fetch\\\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\\\n    /// ago, rather than at a specific index in the array.\\\\n    /// @return blockTimestamp The timestamp of the observation,\\\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\\\n    function observations(uint256 index)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint32 blockTimestamp,\\\\n            int56 tickCumulative,\\\\n            uint160 secondsPerLiquidityCumulativeX128,\\\\n            bool initialized\\\\n        );\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x852dc1f5df7dcf7f11e7bb3eed79f0cea72ad4b25f6a9d2c35aafb48925fd49f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMath {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), 'T');\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1f864a2bf61ba05f3173eaf2e3f94c5e1da4bec0554757527b6d1ef1fe439e4e\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/core/Oracle.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\n// uniswap Library only works under 0.7.6\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IUniswapV3Pool} from \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\nimport {IERC20Detailed} from \\\\\\\"../interfaces/IERC20Detailed.sol\\\\\\\";\\\\n\\\\n//library\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"../libs/Uint256Casting.sol\\\\\\\";\\\\nimport {OracleLibrary} from \\\\\\\"../libs/OracleLibrary.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\\\n */\\\\ncontract Oracle {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint128 private constant ONE = 1e18;\\\\n\\\\n    /**\\\\n     * @notice get twap converted with base & quote token decimals\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\\\n     */\\\\n    function getTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period,\\\\n        bool _checkPeriod\\\\n    ) external view returns (uint256) {\\\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\\\n\\\\n        // make sure the requested period < maxPeriod the pool recorded.\\\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\\\n     */\\\\n    function getHistoricalTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _secondsAgoToStartOfTwap,\\\\n        uint32 _secondsAgoToEndOfTwap\\\\n    ) external view returns (uint256) {\\\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the max period that can be used to request twap\\\\n     * @param _pool uniswap pool address\\\\n     * @return max period can be used to request twap\\\\n     */\\\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\\\n        return _getMaxPeriod(_pool);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get time weighed average tick, not converted to price\\\\n     * @dev this function will not revert\\\\n     * @param _pool address of the pool\\\\n     * @param _period period in second that we want to calculate average on\\\\n     * @return timeWeightedAverageTick the time weighted average tick\\\\n     */\\\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\\\n        external\\\\n        view\\\\n        returns (int24 timeWeightedAverageTick)\\\\n    {\\\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap converted with base & quote token decimals\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return twap price which is scaled\\\\n     */\\\\n    function _fetchTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\\\n\\\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\\\n\\\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\\\n\\\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get raw twap from the uniswap pool\\\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\".\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\\\n     * @return amount of quote currency received for _amountIn of base currency\\\\n     */\\\\n    function _fetchRawTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _period\\\\n    ) internal view returns (uint256) {\\\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\\\\\"OLD\\\\\\\"\\\\n     * @param _pool uniswap pool address\\\\n     * @param _base base currency. to get eth/usd price, eth is base token\\\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\\\n     */\\\\n    function _fetchHistoricTwap(\\\\n        address _pool,\\\\n        address _base,\\\\n        address _quote,\\\\n        uint32 _secondsAgoToStartOfTwap,\\\\n        uint32 _secondsAgoToEndOfTwap\\\\n    ) internal view returns (uint256) {\\\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\\\n\\\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the max period that can be used to request twap\\\\n     * @param _pool uniswap pool address\\\\n     * @return max period can be used to request twap\\\\n     */\\\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\\\n        // observationIndex: the index of the last oracle observation that was written\\\\n        // cardinality: the current maximum number of observations stored in the pool\\\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\\\n\\\\n        // first observation index\\\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\\\n\\\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\\\n\\\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\\\n\\\\n        // (index + 1) % cardinality is not the oldest index,\\\\n        // probably because cardinality is increased after last observation.\\\\n        // in this case, observation at index 0 should be the oldest.\\\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\\\n\\\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc264ae8c3df6e1db22a95c30e3bbca563d4a351fbfc7d0428fb0da76567aa661\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IERC20Detailed.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// uniswap Library only works under 0.7.6\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IERC20Detailed is IERC20 {\\\\n    function decimals() external view returns (uint8);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcd59a0158d0711810c499904b9d37a71fdb34d1c4403f3cb67ca47de5e88bf7b\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/OracleLibrary.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity >=0.5.0 <0.8.0;\\\\n\\\\n//interface\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\\\\\";\\\\n\\\\n/// @title oracle library\\\\n/// @notice provides functions to integrate with uniswap v3 oracle\\\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\\\nlibrary OracleLibrary {\\\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\\\n    /// @dev written by opyn team\\\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\\\n    function consultAtHistoricTime(\\\\n        address pool,\\\\n        uint32 _secondsAgoToStartOfTwap,\\\\n        uint32 _secondsAgoToEndOfTwap\\\\n    ) internal view returns (int24) {\\\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\\\\\"BP\\\\\\\");\\\\n        int24 timeWeightedAverageTick;\\\\n        uint32[] memory secondAgos = new uint32[](2);\\\\n\\\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\\\n\\\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\\\n\\\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\\\n\\\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\\\n\\\\n        // Always round to negative infinity\\\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\\\n\\\\n        return timeWeightedAverageTick;\\\\n    }\\\\n\\\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\\\n    /// @param tick tick value used to calculate the quote\\\\n    /// @param baseAmount amount of token to be converted\\\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\\\n    function getQuoteAtTick(\\\\n        int24 tick,\\\\n        uint128 baseAmount,\\\\n        address baseToken,\\\\n        address quoteToken\\\\n    ) internal pure returns (uint256 quoteAmount) {\\\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\\\n\\\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\\\n        if (sqrtRatioX96 <= type(uint128).max) {\\\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\\\n            quoteAmount = baseToken < quoteToken\\\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\\\n        } else {\\\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\\\n            quoteAmount = baseToken < quoteToken\\\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x83858224ba4dc88b7ab7f26de42c32d2debfd48a59bd5d011afe7be5d7cbb24f\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x608060405234801561001057600080fd5b50610edc806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634a0a96eb146100515780634ac78d111461009a578063cce79bd5146100f6578063de5a6e2214610140575b600080fd5b6100836004803603604081101561006757600080fd5b5080356001600160a01b0316906020013563ffffffff1661017f565b6040805160029290920b8252519081900360200190f35b6100e4600480360360a08110156100b057600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013581169160800135166101c3565b60408051918252519081900360200190f35b6100e4600480360360a081101561010c57600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013516906080013515156101de565b6101666004803603602081101561015657600080fd5b50356001600160a01b031661023c565b6040805163ffffffff9092168252519081900360200190f35b60008061018b8461024f565b905060008163ffffffff168463ffffffff16116101a857836101aa565b815b90506101b8858260006103fb565b925050505b92915050565b60006101d28686868686610713565b90505b95945050505050565b6000816101f8576101f186868686610742565b90506101d5565b60006102038761024f565b905060008163ffffffff168563ffffffff16116102205784610222565b815b905061023088888884610742565b98975050505050505050565b60006102478261024f565b90505b919050565b600080829050600080826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561029157600080fd5b505afa1580156102a5573d6000803e3d6000fd5b505050506040513d60e08110156102bb57600080fd5b5060408101516060909101519092509050600061ffff808316906001850116816102e157fe5b069050600080856001600160a01b031663252c09d7846040518263ffffffff1660e01b8152600401808261ffff16815260200191505060806040518083038186803b15801561032f57600080fd5b505afa158015610343573d6000803e3d6000fd5b505050506040513d608081101561035957600080fd5b5080516060909101519092509050801561037c57504203945061024a9350505050565b856001600160a01b031663252c09d760006040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b1580156103c157600080fd5b505afa1580156103d5573d6000803e3d6000fd5b505050506040513d60808110156103eb57600080fd5b5051420398975050505050505050565b60008163ffffffff168363ffffffff1611610442576040805162461bcd60e51b8152602060048201526002602482015261042560f41b604482015290519081900360640190fd5b6040805160028082526060820183526000928392919060208301908036833701905050905060008486039050858260008151811061047c57fe5b602002602001019063ffffffff16908163ffffffff168152505084826001815181106104a457fe5b63ffffffff90921660209283029190910182015260405163883bdbfd60e01b8152600481018281528451602483015284516000936001600160a01b038c169363883bdbfd938893909283926044019185820191028083838b5b838110156105155781810151838201526020016104fd565b505050509050019250505060006040518083038186803b15801561053857600080fd5b505afa15801561054c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604090815281101561057557600080fd5b810190808051604051939291908464010000000082111561059557600080fd5b9083019060208201858111156105aa57600080fd5b82518660208202830111640100000000821117156105c757600080fd5b82525081516020918201928201910280838360005b838110156105f45781810151838201526020016105dc565b505050509050016040526020018051604051939291908464010000000082111561061d57600080fd5b90830190602082018581111561063257600080fd5b825186602082028301116401000000008211171561064f57600080fd5b82525081516020918201928201910280838360005b8381101561067c578181015183820152602001610664565b5050505090500160405250505050905060008160008151811061069b57fe5b6020026020010151826001815181106106b057fe5b60200260200101510390508263ffffffff168160060b816106cd57fe5b05945060008160060b1280156106f757508263ffffffff168160060b816106f057fe5b0760060b15155b1561070457600019909401935b509293505050505b9392505050565b6000806107218785856103fb565b905061073781670de0b6b3a76400008888610891565b979650505050505050565b600080610751868686866109b5565b90506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561078e57600080fd5b505afa1580156107a2573d6000803e3d6000fd5b505050506040513d60208110156107b857600080fd5b50516040805163313ce56760e01b815290519192506000916001600160a01b0388169163313ce567916004808301926020929190829003018186803b15801561080057600080fd5b505afa158015610814573d6000803e3d6000fd5b505050506040513d602081101561082a57600080fd5b5051905060ff828116908216141561084757829350505050610889565b8060ff168260ff161115610871576108678360ff83850316600a0a6109e4565b9350505050610889565b6108838360ff84840316600a0a610a3d565b93505050505b949350505050565b60008061089d86610aa4565b90506fffffffffffffffffffffffffffffffff6001600160a01b03821611610927576001600160a01b03808216800290848116908616106108fe576108f9600160c01b876fffffffffffffffffffffffffffffffff1683610dd6565b61091f565b61091f81876fffffffffffffffffffffffffffffffff16600160c01b610dd6565b9250506109ac565b60006109466001600160a01b0383168068010000000000000000610dd6565b9050836001600160a01b0316856001600160a01b03161061098757610982600160801b876fffffffffffffffffffffffffffffffff1683610dd6565b6109a8565b6109a881876fffffffffffffffffffffffffffffffff16600160801b610dd6565b9250505b50949350505050565b6000806109c4868460006103fb565b90506109da81670de0b6b3a76400008787610891565b9695505050505050565b6000826109f3575060006101bd565b82820282848281610a0057fe5b041461070c5760405162461bcd60e51b8152600401808060200182810382526021815260200180610e866021913960400191505060405180910390fd5b6000808211610a93576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610a9c57fe5b049392505050565b60008060008360020b12610abb578260020b610ac3565b8260020b6000035b9050620d89e8811115610b01576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216610b1557600160801b610b27565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610b5b576ffff97272373d413259a46990580e213a0260801c5b6004821615610b7a576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615610b99576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610bb8576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610bd7576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610bf6576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610c15576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610c35576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615610c55576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615610c75576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615610c95576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610cb5576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610cd5576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610cf5576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610d15576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610d36576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615610d56576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615610d75576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615610d92576b048a170391f7dc42444e8fa20260801c5b60008460020b1315610dad578060001981610da957fe5b0490505b640100000000810615610dc1576001610dc4565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080610e0c5760008411610e0157600080fd5b50829004905061070c565b808411610e1857600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a0290910302918190038190046001018684119095039490940291909403929092049190911791909102915050939250505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220b1a443112ea45879a00fbc518b3cc36f190c9940d1022cd43a38928e460276ce64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80634a0a96eb146100515780634ac78d111461009a578063cce79bd5146100f6578063de5a6e2214610140575b600080fd5b6100836004803603604081101561006757600080fd5b5080356001600160a01b0316906020013563ffffffff1661017f565b6040805160029290920b8252519081900360200190f35b6100e4600480360360a08110156100b057600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013581169160800135166101c3565b60408051918252519081900360200190f35b6100e4600480360360a081101561010c57600080fd5b506001600160a01b03813581169160208101358216916040820135169063ffffffff606082013516906080013515156101de565b6101666004803603602081101561015657600080fd5b50356001600160a01b031661023c565b6040805163ffffffff9092168252519081900360200190f35b60008061018b8461024f565b905060008163ffffffff168463ffffffff16116101a857836101aa565b815b90506101b8858260006103fb565b925050505b92915050565b60006101d28686868686610713565b90505b95945050505050565b6000816101f8576101f186868686610742565b90506101d5565b60006102038761024f565b905060008163ffffffff168563ffffffff16116102205784610222565b815b905061023088888884610742565b98975050505050505050565b60006102478261024f565b90505b919050565b600080829050600080826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561029157600080fd5b505afa1580156102a5573d6000803e3d6000fd5b505050506040513d60e08110156102bb57600080fd5b5060408101516060909101519092509050600061ffff808316906001850116816102e157fe5b069050600080856001600160a01b031663252c09d7846040518263ffffffff1660e01b8152600401808261ffff16815260200191505060806040518083038186803b15801561032f57600080fd5b505afa158015610343573d6000803e3d6000fd5b505050506040513d608081101561035957600080fd5b5080516060909101519092509050801561037c57504203945061024a9350505050565b856001600160a01b031663252c09d760006040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b1580156103c157600080fd5b505afa1580156103d5573d6000803e3d6000fd5b505050506040513d60808110156103eb57600080fd5b5051420398975050505050505050565b60008163ffffffff168363ffffffff1611610442576040805162461bcd60e51b8152602060048201526002602482015261042560f41b604482015290519081900360640190fd5b6040805160028082526060820183526000928392919060208301908036833701905050905060008486039050858260008151811061047c57fe5b602002602001019063ffffffff16908163ffffffff168152505084826001815181106104a457fe5b63ffffffff90921660209283029190910182015260405163883bdbfd60e01b8152600481018281528451602483015284516000936001600160a01b038c169363883bdbfd938893909283926044019185820191028083838b5b838110156105155781810151838201526020016104fd565b505050509050019250505060006040518083038186803b15801561053857600080fd5b505afa15801561054c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604090815281101561057557600080fd5b810190808051604051939291908464010000000082111561059557600080fd5b9083019060208201858111156105aa57600080fd5b82518660208202830111640100000000821117156105c757600080fd5b82525081516020918201928201910280838360005b838110156105f45781810151838201526020016105dc565b505050509050016040526020018051604051939291908464010000000082111561061d57600080fd5b90830190602082018581111561063257600080fd5b825186602082028301116401000000008211171561064f57600080fd5b82525081516020918201928201910280838360005b8381101561067c578181015183820152602001610664565b5050505090500160405250505050905060008160008151811061069b57fe5b6020026020010151826001815181106106b057fe5b60200260200101510390508263ffffffff168160060b816106cd57fe5b05945060008160060b1280156106f757508263ffffffff168160060b816106f057fe5b0760060b15155b1561070457600019909401935b509293505050505b9392505050565b6000806107218785856103fb565b905061073781670de0b6b3a76400008888610891565b979650505050505050565b600080610751868686866109b5565b90506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561078e57600080fd5b505afa1580156107a2573d6000803e3d6000fd5b505050506040513d60208110156107b857600080fd5b50516040805163313ce56760e01b815290519192506000916001600160a01b0388169163313ce567916004808301926020929190829003018186803b15801561080057600080fd5b505afa158015610814573d6000803e3d6000fd5b505050506040513d602081101561082a57600080fd5b5051905060ff828116908216141561084757829350505050610889565b8060ff168260ff161115610871576108678360ff83850316600a0a6109e4565b9350505050610889565b6108838360ff84840316600a0a610a3d565b93505050505b949350505050565b60008061089d86610aa4565b90506fffffffffffffffffffffffffffffffff6001600160a01b03821611610927576001600160a01b03808216800290848116908616106108fe576108f9600160c01b876fffffffffffffffffffffffffffffffff1683610dd6565b61091f565b61091f81876fffffffffffffffffffffffffffffffff16600160c01b610dd6565b9250506109ac565b60006109466001600160a01b0383168068010000000000000000610dd6565b9050836001600160a01b0316856001600160a01b03161061098757610982600160801b876fffffffffffffffffffffffffffffffff1683610dd6565b6109a8565b6109a881876fffffffffffffffffffffffffffffffff16600160801b610dd6565b9250505b50949350505050565b6000806109c4868460006103fb565b90506109da81670de0b6b3a76400008787610891565b9695505050505050565b6000826109f3575060006101bd565b82820282848281610a0057fe5b041461070c5760405162461bcd60e51b8152600401808060200182810382526021815260200180610e866021913960400191505060405180910390fd5b6000808211610a93576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610a9c57fe5b049392505050565b60008060008360020b12610abb578260020b610ac3565b8260020b6000035b9050620d89e8811115610b01576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216610b1557600160801b610b27565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610b5b576ffff97272373d413259a46990580e213a0260801c5b6004821615610b7a576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615610b99576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610bb8576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610bd7576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610bf6576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610c15576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610c35576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615610c55576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615610c75576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615610c95576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610cb5576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610cd5576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610cf5576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610d15576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610d36576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615610d56576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615610d75576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615610d92576b048a170391f7dc42444e8fa20260801c5b60008460020b1315610dad578060001981610da957fe5b0490505b640100000000810615610dc1576001610dc4565b60005b60ff16602082901c0192505050919050565b6000808060001985870986860292508281109083900303905080610e0c5760008411610e0157600080fd5b50829004905061070c565b808411610e1857600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a0290910302918190038190046001018684119095039490940291909403929092049190911791909102915050939250505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220b1a443112ea45879a00fbc518b3cc36f190c9940d1022cd43a38928e460276ce64736f6c63430007060033\",\n  \"devdoc\": {\n    \"details\": \"if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"getHistoricalTwap(address,address,address,uint32,uint32)\": {\n        \"details\": \"if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\",\n        \"params\": {\n          \"_base\": \"base currency. to get eth/usd price, eth is base token\",\n          \"_pool\": \"uniswap pool address\",\n          \"_quote\": \"quote currency. to get eth/usd price, usd is the quote currency\",\n          \"_secondsAgoToEndOfTwap\": \"amount of seconds in the past to end calculating time-weighted average\",\n          \"_secondsAgoToStartOfTwap\": \"amount of seconds in the past to start calculating time-weighted average\"\n        },\n        \"returns\": {\n          \"_0\": \"price of 1 base currency in quote currency. scaled by 1e18\"\n        }\n      },\n      \"getMaxPeriod(address)\": {\n        \"params\": {\n          \"_pool\": \"uniswap pool address\"\n        },\n        \"returns\": {\n          \"_0\": \"max period can be used to request twap\"\n        }\n      },\n      \"getTimeWeightedAverageTickSafe(address,uint32)\": {\n        \"details\": \"this function will not revert\",\n        \"params\": {\n          \"_period\": \"period in second that we want to calculate average on\",\n          \"_pool\": \"address of the pool\"\n        },\n        \"returns\": {\n          \"timeWeightedAverageTick\": \"the time weighted average tick\"\n        }\n      },\n      \"getTwap(address,address,address,uint32,bool)\": {\n        \"details\": \"if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\",\n        \"params\": {\n          \"_base\": \"base currency. to get eth/usd price, eth is base token\",\n          \"_period\": \"number of seconds in the past to start calculating time-weighted average\",\n          \"_pool\": \"uniswap pool address\",\n          \"_quote\": \"quote currency. to get eth/usd price, usd is the quote currency\"\n        },\n        \"returns\": {\n          \"_0\": \"price of 1 base currency in quote currency. scaled by 1e18\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"getHistoricalTwap(address,address,address,uint32,uint32)\": {\n        \"notice\": \"get twap for a specific period of time, converted with base & quote token decimals\"\n      },\n      \"getMaxPeriod(address)\": {\n        \"notice\": \"get the max period that can be used to request twap\"\n      },\n      \"getTimeWeightedAverageTickSafe(address,uint32)\": {\n        \"notice\": \"get time weighed average tick, not converted to price\"\n      },\n      \"getTwap(address,address,address,uint32,bool)\": {\n        \"notice\": \"get twap converted with base & quote token decimals\"\n      }\n    },\n    \"notice\": \"read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/Quoter.json",
    "content": "{\n  \"address\": \"0x267aEB76BEb6DC7Ab0D88FeEaC8A948e237e2d69\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_factory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_WETH9\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"WETH9\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"path\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"quoteExactInput\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160[]\",\n          \"name\": \"sqrtPriceX96AfterList\",\n          \"type\": \"uint160[]\"\n        },\n        {\n          \"internalType\": \"uint32[]\",\n          \"name\": \"initializedTicksCrossedList\",\n          \"type\": \"uint32[]\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountIn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct IQuoterV2.QuoteExactInputSingleParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"quoteExactInputSingle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96After\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"initializedTicksCrossed\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"path\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"quoteExactOutput\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160[]\",\n          \"name\": \"sqrtPriceX96AfterList\",\n          \"type\": \"uint160[]\"\n        },\n        {\n          \"internalType\": \"uint32[]\",\n          \"name\": \"initializedTicksCrossedList\",\n          \"type\": \"uint32[]\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amount\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct IQuoterV2.QuoteExactOutputSingleParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"quoteExactOutputSingle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96After\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint32\",\n          \"name\": \"initializedTicksCrossed\",\n          \"type\": \"uint32\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"gasEstimate\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"path\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0xfbff624db8c9bc8c0a1656fc910af187e86ab49794bce038201e50a962d400dd\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0x267aEB76BEb6DC7Ab0D88FeEaC8A948e237e2d69\",\n    \"transactionIndex\": 2,\n    \"gasUsed\": \"1836365\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0xdf48fcfd22afb19549753b340d9b39c60f5f2ff0c6bed33e9203f7f19e8c15d8\",\n    \"transactionHash\": \"0xfbff624db8c9bc8c0a1656fc910af187e86ab49794bce038201e50a962d400dd\",\n    \"logs\": [],\n    \"blockNumber\": 11342322,\n    \"cumulativeGasUsed\": \"4160508\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n    \"0xc778417e063141139fce010982780140aa0cd5ab\"\n  ],\n  \"bytecode\": \"0x60c06040523480156200001157600080fd5b506040516200212c3803806200212c833981016040819052620000349162000070565b6001600160601b0319606092831b8116608052911b1660a052620000a7565b80516001600160a01b03811681146200006b57600080fd5b919050565b6000806040838503121562000083578182fd5b6200008e8362000053565b91506200009e6020840162000053565b90509250929050565b60805160601c60a05160601c612051620000db60003980610321525080610577528061095d5280610b9252506120516000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063c45a01551161005b578063c45a0155146100e6578063c6a5026a146100ee578063cdca175314610101578063fa461e33146101145761007d565b80632f80bb1d146100825780634aa4a4fc146100ae578063bd21704a146100c3575b600080fd5b610095610090366004611b2b565b610129565b6040516100a59493929190611eac565b60405180910390f35b6100b661031f565b6040516100a59190611def565b6100d66100d1366004611c49565b610343565b6040516100a59493929190611f54565b6100b6610575565b6100d66100fc366004611c49565b610599565b61009561010f366004611b2b565b610754565b610127610122366004611b91565b61092c565b005b6000606080600061013986610ae8565b67ffffffffffffffff8111801561014f57600080fd5b50604051908082528060200260200182016040528015610179578160200160208202803683370190505b50925061018586610ae8565b67ffffffffffffffff8111801561019b57600080fd5b506040519080825280602002602001820160405280156101c5578160200160208202803683370190505b50915060005b60008060006101d98a610b17565b92509250925060008060008061025c6040518060a001604052808873ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018f81526020018762ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250610343565b9350935093509350828b898151811061027157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818a89815181106102b857fe5b63ffffffff90921660209283029190910190910152929b50968201966001909601958b926102e58e610b48565b156102fa576102f38e610b50565b9d5061030a565b8c9b505050505050505050610316565b505050505050506101cb565b92959194509250565b7f000000000000000000000000000000000000000000000000000000000000000081565b60208101518151606083015160009283928392839273ffffffffffffffffffffffffffffffffffffffff808216908416109284926103819290610b8b565b9050866080015173ffffffffffffffffffffffffffffffffffffffff16600014156103af5760408701516000555b60005a90508173ffffffffffffffffffffffffffffffffffffffff1663128acb0830856103df8c60400151610bc9565b6000038c6080015173ffffffffffffffffffffffffffffffffffffffff1660001461040e578c60800151610434565b8761042d5773fffd8963efd1fc6a506488495d951d5263988d25610434565b6401000276a45b8d602001518e606001518f6000015160405160200161045593929190611d89565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610484959493929190611e10565b6040805180830381600087803b15801561049d57600080fd5b505af19250505080156104eb575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526104e891810190611b6e565b60015b610568573d808015610519576040519150601f19603f3d011682016040523d82523d6000602084013e61051e565b606091505b505a82039450886080015173ffffffffffffffffffffffffffffffffffffffff166000141561054c57600080555b610557818487610bfb565b97509750975097505050505061056e565b50505050505b9193509193565b7f000000000000000000000000000000000000000000000000000000000000000081565b60208101518151606083015160009283928392839273ffffffffffffffffffffffffffffffffffffffff808216908416109284926105d79290610b8b565b905060005a90508173ffffffffffffffffffffffffffffffffffffffff1663128acb0830856106098c60400151610bc9565b60808d015173ffffffffffffffffffffffffffffffffffffffff1615610633578c60800151610659565b876106525773fffd8963efd1fc6a506488495d951d5263988d25610659565b6401000276a45b8d600001518e606001518f6020015160405160200161067a93929190611d89565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016106a9959493929190611e10565b6040805180830381600087803b1580156106c257600080fd5b505af1925050508015610710575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261070d91810190611b6e565b60015b610568573d80801561073e576040519150601f19603f3d011682016040523d82523d6000602084013e610743565b606091505b505a82039450610557818487610bfb565b6000606080600061076486610ae8565b67ffffffffffffffff8111801561077a57600080fd5b506040519080825280602002602001820160405280156107a4578160200160208202803683370190505b5092506107b086610ae8565b67ffffffffffffffff811180156107c657600080fd5b506040519080825280602002602001820160405280156107f0578160200160208202803683370190505b50915060005b60008060006108048a610b17565b9250925092506000806000806108876040518060a001604052808973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018f81526020018762ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250610599565b9350935093509350828b898151811061089c57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818a89815181106108e357fe5b63ffffffff90921660209283029190910190910152929b50968201966001909601958b926109108e610b48565b156102fa5761091e8e610b50565b9d50505050505050506107f6565b600083138061093b5750600082135b61094457600080fd5b600080600061095284610b17565b9250925092506109847f0000000000000000000000000000000000000000000000000000000000000000848484610ccf565b5060008060008089136109ca578573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1610888a6000036109ff565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161089896000035b9250925092506000610a12878787610b8b565b90506000808273ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610a5d57600080fd5b505afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190611c6b565b5050505050915091508515610abb57604051848152826020820152816040820152606081fd5b60005415610ad1576000548414610ad157600080fd5b604051858152826020820152816040820152606081fd5b805160177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec909101045b919050565b60008080610b258482610cee565b9250610b32846014610dee565b9050610b3f846017610cee565b91509193909250565b516042111590565b8051606090610b859083906017907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901610ede565b92915050565b6000610bc17f0000000000000000000000000000000000000000000000000000000000000000610bbc8686866110c5565b611142565b949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210610bf757600080fd5b5090565b6000806000806000808773ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610c4a57600080fd5b505afa158015610c5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c829190611c6b565b50939650610c9794508d935061127892505050565b91975095509050610cbf73ffffffffffffffffffffffffffffffffffffffff89168383611339565b9350869250505093509350935093565b6000610ce585610ce08686866110c5565b611991565b95945050505050565b600081826014011015610d6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b8160140183511015610dd557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015610e6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b8160030183511015610ed557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b60608182601f011015610f5257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b828284011015610fc357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b8183018451101561103557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015290519081900360640190fd5b60608215801561105457604051915060008252602082016040526110bc565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561108d578051835260209283019201611075565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6110cd6119fa565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161115611105579192915b506040805160608101825273ffffffffffffffffffffffffffffffffffffffff948516815292909316602083015262ffffff169181019190915290565b6000816020015173ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff161061118457600080fd5b508051602080830151604093840151845173ffffffffffffffffffffffffffffffffffffffff94851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b60008060008351606014611318576044845110156112cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c290611e75565b60405180910390fd5b600484019350838060200190518101906112e59190611bdf565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c29190611e62565b8380602001905181019061132c9190611d02565b9250925092509193909250565b60008060008060008060008060088b73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561138d57600080fd5b505afa1580156113a1573d6000803e3d6000fd5b505050506040513d60208110156113b757600080fd5b5051600290810b908c900b816113c957fe5b0560020b901d905060006101008c73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561141c57600080fd5b505afa158015611430573d6000803e3d6000fd5b505050506040513d602081101561144657600080fd5b5051600290810b908d900b8161145857fe5b0560020b8161146357fe5b079050600060088d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114b057600080fd5b505afa1580156114c4573d6000803e3d6000fd5b505050506040513d60208110156114da57600080fd5b5051600290810b908d900b816114ec57fe5b0560020b901d905060006101008e73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561153f57600080fd5b505afa158015611553573d6000803e3d6000fd5b505050506040513d602081101561156957600080fd5b5051600290810b908e900b8161157b57fe5b0560020b8161158657fe5b07905060008160ff166001901b8f73ffffffffffffffffffffffffffffffffffffffff16635339c296856040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b5051161180156116a457508d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561166257600080fd5b505afa158015611676573d6000803e3d6000fd5b505050506040513d602081101561168c57600080fd5b5051600290810b908d900b8161169e57fe5b0760020b155b80156116b557508b60020b8d60020b135b945060008360ff166001901b8f73ffffffffffffffffffffffffffffffffffffffff16635339c296876040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b15801561171557600080fd5b505afa158015611729573d6000803e3d6000fd5b505050506040513d602081101561173f57600080fd5b5051161180156117d257508d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561179057600080fd5b505afa1580156117a4573d6000803e3d6000fd5b505050506040513d60208110156117ba57600080fd5b5051600290810b908e900b816117cc57fe5b0760020b155b80156117e357508b60020b8d60020b125b95508160010b8460010b128061180f57508160010b8460010b14801561180f57508060ff168360ff1611155b1561182557839950829750819850809650611832565b8199508097508398508296505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff87161b9150505b8560010b8760010b13611969578560010b8760010b14156118a3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff858103161c165b6000818c73ffffffffffffffffffffffffffffffffffffffff16635339c2968a6040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b1580156118fa57600080fd5b505afa15801561190e573d6000803e3d6000fd5b505050506040513d602081101561192457600080fd5b5051169050611932816119c1565b61ffff16989098019750506001909501947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61185e565b8115611976576001880397505b8215611983576001880397505b505050505050509392505050565b600061199d8383611142565b90503373ffffffffffffffffffffffffffffffffffffffff821614610b8557600080fd5b6000805b8215610b85577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301909216916001016119c5565b604080516060810182526000808252602082018190529181019190915290565b600082601f830112611a2a578081fd5b8135611a3d611a3882611faf565b611f8b565b818152846020838601011115611a51578283fd5b816020850160208301379081016020019190915292915050565b8051600281900b8114610b1257600080fd5b600060a08284031215611a8e578081fd5b60405160a0810181811067ffffffffffffffff82111715611aab57fe5b6040529050808235611abc8161201f565b81526020830135611acc8161201f565b602082015260408381013590820152606083013562ffffff81168114611af157600080fd5b6060820152611b0260808401611b0e565b60808201525092915050565b8035610b128161201f565b805161ffff81168114610b1257600080fd5b60008060408385031215611b3d578182fd5b823567ffffffffffffffff811115611b53578283fd5b611b5f85828601611a1a565b95602094909401359450505050565b60008060408385031215611b80578182fd5b505080516020909101519092909150565b600080600060608486031215611ba5578081fd5b8335925060208401359150604084013567ffffffffffffffff811115611bc9578182fd5b611bd586828701611a1a565b9150509250925092565b600060208284031215611bf0578081fd5b815167ffffffffffffffff811115611c06578182fd5b8201601f81018413611c16578182fd5b8051611c24611a3882611faf565b818152856020838501011115611c38578384fd5b610ce5826020830160208601611fef565b600060a08284031215611c5a578081fd5b611c648383611a7d565b9392505050565b600080600080600080600060e0888a031215611c85578283fd5b8751611c908161201f565b9650611c9e60208901611a6b565b9550611cac60408901611b19565b9450611cba60608901611b19565b9350611cc860808901611b19565b925060a088015160ff81168114611cdd578283fd5b60c08901519092508015158114611cf2578182fd5b8091505092959891949750929550565b600080600060608486031215611d16578081fd5b835192506020840151611d288161201f565b9150611d3660408501611a6b565b90509250925092565b60008151808452611d57816020860160208601611fef565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a06080830152611e5760a0830184611d3f565b979650505050505050565b600060208252611c646020830184611d3f565b60208082526010908201527f556e6578706563746564206572726f7200000000000000000000000000000000604082015260600190565b600060808201868352602060808185015281875180845260a0860191508289019350845b81811015611f0257845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101611ed0565b505084810360408601528651808252908201925081870190845b81811015611f3e57825163ffffffff1685529383019391830191600101611f1c565b5050505060609290920192909252949350505050565b93845273ffffffffffffffffffffffffffffffffffffffff92909216602084015263ffffffff166040830152606082015260800190565b60405181810167ffffffffffffffff81118282101715611fa757fe5b604052919050565b600067ffffffffffffffff821115611fc357fe5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b8381101561200a578181015183820152602001611ff2565b83811115612019576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461204157600080fd5b5056fea164736f6c6343000706000a\"\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/ShortHelper.json",
    "content": "{\n  \"address\": \"0x8903918DFE74476E90B63061E5b9c3E63b65d3F4\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controllerAddr\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_swapRouter\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_wethAddr\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_wPowerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_withdrawAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOut\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountInMaximum\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactOutputSingleParams\",\n          \"name\": \"_exactOutputParams\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"closeShort\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"controller\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IController\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"onERC721Received\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_vaultId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_powerPerpAmount\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_uniNftId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountIn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOutMinimum\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactInputSingleParams\",\n          \"name\": \"_exactInputParams\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"openShort\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"router\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract ISwapRouter\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"shortPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IShortPowerPerp\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"wPowerPerp\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"weth\",\n      \"outputs\": [\n        {\n          \"internalType\": \"contract IWETH9\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x43bd6bf9f65c032e95c398a26e08f31d6ba4b0e11c696c425a50f5a254b4fb6b\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xf668606B896389066a39B132741763e1ca6d76a2\",\n    \"contractAddress\": \"0x8903918DFE74476E90B63061E5b9c3E63b65d3F4\",\n    \"transactionIndex\": 0,\n    \"gasUsed\": \"1067520\",\n    \"logsBloom\": \"0x00000000000000100000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000300000040000000000000000000800000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200010000800000000000000000000000000002000000000000000008020000000\",\n    \"blockHash\": \"0xbda47d8f578ebc76c8b7527fb40f150abd0f47e45ac2a1d76c3c86591b14e214\",\n    \"transactionHash\": \"0x43bd6bf9f65c032e95c398a26e08f31d6ba4b0e11c696c425a50f5a254b4fb6b\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 0,\n        \"blockNumber\": 11808055,\n        \"transactionHash\": \"0x43bd6bf9f65c032e95c398a26e08f31d6ba4b0e11c696c425a50f5a254b4fb6b\",\n        \"address\": \"0xa4222f78d23593e82Aa74742d25D06720DCa4ab7\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x0000000000000000000000008903918dfe74476e90b63061e5b9c3e63b65d3f4\",\n          \"0x000000000000000000000000528a19a3e88861e7298c86fe5490b8ec007a4204\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 0,\n        \"blockHash\": \"0xbda47d8f578ebc76c8b7527fb40f150abd0f47e45ac2a1d76c3c86591b14e214\"\n      },\n      {\n        \"transactionIndex\": 0,\n        \"blockNumber\": 11808055,\n        \"transactionHash\": \"0x43bd6bf9f65c032e95c398a26e08f31d6ba4b0e11c696c425a50f5a254b4fb6b\",\n        \"address\": \"0xc778417E063141139Fce010982780140Aa0cD5Ab\",\n        \"topics\": [\n          \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n          \"0x0000000000000000000000008903918dfe74476e90b63061e5b9c3e63b65d3f4\",\n          \"0x000000000000000000000000528a19a3e88861e7298c86fe5490b8ec007a4204\"\n        ],\n        \"data\": \"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\",\n        \"logIndex\": 1,\n        \"blockHash\": \"0xbda47d8f578ebc76c8b7527fb40f150abd0f47e45ac2a1d76c3c86591b14e214\"\n      }\n    ],\n    \"blockNumber\": 11808055,\n    \"cumulativeGasUsed\": \"1067520\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n    \"0x528a19A3e88861E7298C86fE5490B8Ec007a4204\",\n    \"0xc778417e063141139fce010982780140aa0cd5ab\"\n  ],\n  \"solcInputHash\": \"5f450d03d2b8109eaf06de68c57d8c2b\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controllerAddr\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_swapRouter\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_wethAddr\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_wPowerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_withdrawAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"deadline\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountOut\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountInMaximum\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceLimitX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"internalType\\\":\\\"struct ISwapRouter.ExactOutputSingleParams\\\",\\\"name\\\":\\\"_exactOutputParams\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"closeShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IController\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"onERC721Received\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_vaultId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_powerPerpAmount\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_uniNftId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"components\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"deadline\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountIn\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountOutMinimum\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceLimitX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"internalType\\\":\\\"struct ISwapRouter.ExactInputSingleParams\\\",\\\"name\\\":\\\"_exactInputParams\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"openShort\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"router\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract ISwapRouter\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"shortPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IShortPowerPerp\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"wPowerPerp\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"weth\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"contract IWETH9\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"receive\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"params\\\":{\\\"_vaultId\\\":\\\"short wPowerPerp vault id\\\",\\\"_wPowerPerpAmount\\\":\\\"amount of wPowerPerp to burn\\\",\\\"_withdrawAmount\\\":\\\"amount to withdraw\\\"}},\\\"constructor\\\":{\\\"params\\\":{\\\"_controllerAddr\\\":\\\"controller address for wPowerPerp\\\",\\\"_swapRouter\\\":\\\"uniswap v3 swap router address\\\",\\\"_wethAddr\\\":\\\"weth address\\\"}},\\\"onERC721Received(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"accept erc721 from safeTransferFrom and safeMint after callback\\\",\\\"returns\\\":{\\\"_0\\\":\\\"returns received selector\\\"}},\\\"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"params\\\":{\\\"_powerPerpAmount\\\":\\\"amount of powerPerp to mint/sell\\\",\\\"_uniNftId\\\":\\\"uniswap v3 position token id\\\",\\\"_vaultId\\\":\\\"short wPowerPerp vault id\\\"}}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"notice\\\":\\\"buy back wPowerPerp with eth on uniswap v3 and close position\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"constructor for short helper\\\"},\\\"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\\\":{\\\"notice\\\":\\\"mint power perp, trade with uniswap v3 and send back premium in eth\\\"}},\\\"notice\\\":\\\"contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/periphery/ShortHelper.sol\\\":\\\"ShortHelper\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Contract module that helps prevent reentrant calls to a function.\\\\n *\\\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\\\n * available, which can be applied to functions to make sure there are no nested\\\\n * (reentrant) calls to them.\\\\n *\\\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\\\n * `nonReentrant` may not call one another. This can be worked around by making\\\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\\\n * points to them.\\\\n *\\\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\\\n * to protect against it, check out our blog post\\\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\\\n */\\\\nabstract contract ReentrancyGuard {\\\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\\\n    // word because each write operation emits an extra SLOAD to first read the\\\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\\\n    // back. This is the compiler's defense against contract upgrades and\\\\n    // pointer aliasing, and it cannot be disabled.\\\\n\\\\n    // The values being non-zero value makes deployment a bit more expensive,\\\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\\\n    // amount. Since refunds are capped to a percentage of the total\\\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\\\n    // increase the likelihood of the full refund coming into effect.\\\\n    uint256 private constant _NOT_ENTERED = 1;\\\\n    uint256 private constant _ENTERED = 2;\\\\n\\\\n    uint256 private _status;\\\\n\\\\n    constructor () {\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\\\n     * function is not supported. It is possible to prevent this from happening\\\\n     * by making the `nonReentrant` function external, and make it call a\\\\n     * `private` function that does the actual work.\\\\n     */\\\\n    modifier nonReentrant() {\\\\n        // On the first call to nonReentrant, _notEntered will be true\\\\n        require(_status != _ENTERED, \\\\\\\"ReentrancyGuard: reentrant call\\\\\\\");\\\\n\\\\n        // Any calls to nonReentrant after this point will fail\\\\n        _status = _ENTERED;\\\\n\\\\n        _;\\\\n\\\\n        // By storing the original value once again, a refund is triggered (see\\\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\\\n        _status = _NOT_ENTERED;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x1153f6dd334c01566417b8c551122450542a2b75a2bbb379d59a8c320ed6da28\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Callback for IUniswapV3PoolActions#swap\\\\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\\\\ninterface IUniswapV3SwapCallback {\\\\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\\\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\\\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\\\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\\\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\\\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\\\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\\\n    function uniswapV3SwapCallback(\\\\n        int256 amount0Delta,\\\\n        int256 amount1Delta,\\\\n        bytes calldata data\\\\n    ) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x3f485fb1a44e8fbeadefb5da07d66edab3cfe809f0ac4074b1e54e3eb3c4cf69\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\\\n\\\\n/// @title Router token swapping functionality\\\\n/// @notice Functions for swapping tokens via Uniswap V3\\\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\\\n    struct ExactInputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactInputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountIn;\\\\n        uint256 amountOutMinimum;\\\\n    }\\\\n\\\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\\\n    /// @return amountOut The amount of the received token\\\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\\\n\\\\n    struct ExactOutputSingleParams {\\\\n        address tokenIn;\\\\n        address tokenOut;\\\\n        uint24 fee;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n        uint160 sqrtPriceLimitX96;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\\\n\\\\n    struct ExactOutputParams {\\\\n        bytes path;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n        uint256 amountOut;\\\\n        uint256 amountInMaximum;\\\\n    }\\\\n\\\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\\\n    /// @return amountIn The amount of the input token\\\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9bfaf1feb32814623e627ab70f2409760b15d95f1f9b058e2b3399a8bb732975\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnOnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc5d6230c8bafcaf2ae7260efd68c45ab13e91819ed9e11881b29dc48386e4bc7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IShortPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\n\\\\ninterface IShortPowerPerp is IERC721 {\\\\n    function nextId() external view returns (uint256);\\\\n\\\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf2d2cb2decac32a199e63f0d5141e46a6e989620944ec5f0144e5aebd0c7989e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWETH9.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWETH9 is IERC20 {\\\\n    function deposit() external payable;\\\\n\\\\n    function withdraw(uint256 wad) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8a9a4512f1fc29b14dcf97ca149f263f28de43191a3ee31336f2389e3f2f5f8e\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x939175a827c8e9d8d09ee55957e8127a6a55bf42d6a0b3e48b0b59c895aa85af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/periphery/ShortHelper.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\npragma abicoder v2;\\\\n// Interfaces\\\\nimport {IERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\\\\\";\\\\nimport {IERC721Receiver} from \\\\\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\\\\\";\\\\nimport {ISwapRouter} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\\\\\";\\\\n\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\nimport {IWETH9} from \\\\\\\"../interfaces/IWETH9.sol\\\\\\\";\\\\nimport {IShortPowerPerp} from \\\\\\\"../interfaces/IShortPowerPerp.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\n\\\\n// Libraries\\\\nimport {Address} from \\\\\\\"@openzeppelin/contracts/utils/Address.sol\\\\\\\";\\\\nimport {ReentrancyGuard} from \\\\\\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\\\\\";\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\\\n */\\\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\\\n    using SafeMath for uint256;\\\\n    using Address for address payable;\\\\n\\\\n    IController public immutable controller;\\\\n    ISwapRouter public immutable router;\\\\n    IWETH9 public immutable weth;\\\\n    IShortPowerPerp public immutable shortPowerPerp;\\\\n    address public immutable wPowerPerp;\\\\n\\\\n    /**\\\\n     * @notice constructor for short helper\\\\n     * @param _controllerAddr controller address for wPowerPerp\\\\n     * @param _swapRouter uniswap v3 swap router address\\\\n     * @param _wethAddr weth address\\\\n     */\\\\n    constructor(\\\\n        address _controllerAddr,\\\\n        address _swapRouter,\\\\n        address _wethAddr\\\\n    ) {\\\\n        require(_controllerAddr != address(0), \\\\\\\"Invalid controller address\\\\\\\");\\\\n        require(_swapRouter != address(0), \\\\\\\"Invalid swap router address\\\\\\\");\\\\n        require(_wethAddr != address(0), \\\\\\\"Invalid weth address\\\\\\\");\\\\n        IController _controller = IController(_controllerAddr);\\\\n        router = ISwapRouter(_swapRouter);\\\\n        wPowerPerp = _controller.wPowerPerp();\\\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\\\n        IWETH9 _weth = IWETH9(_wethAddr);\\\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\\\n        _weth.approve(_swapRouter, type(uint256).max);\\\\n\\\\n        // assign immutable variables\\\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\\\n        weth = _weth;\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\\\n     * @param _vaultId short wPowerPerp vault id\\\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\\\n     * @param _uniNftId uniswap v3 position token id\\\\n     */\\\\n    function openShort(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniNftId,\\\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\\\n    ) external payable nonReentrant {\\\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\\\\\"Not allowed\\\\\\\");\\\\n        require(\\\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\\\n            \\\\\\\"Wrong swap tokens\\\\\\\"\\\\n        );\\\\n\\\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\\\n            _vaultId,\\\\n            _powerPerpAmount,\\\\n            _uniNftId\\\\n        );\\\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\\\n\\\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\\\n\\\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\\\n        if (_exactInputParams.recipient == address(this)) {\\\\n            weth.withdraw(amountOut);\\\\n            payable(msg.sender).sendValue(amountOut);\\\\n        }\\\\n\\\\n        // this is a newly open vault, transfer to the user.\\\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\\\n     * @param _vaultId short wPowerPerp vault id\\\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\\\n     * @param _withdrawAmount amount to withdraw\\\\n     */\\\\n    function closeShort(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount,\\\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\\\n    ) external payable nonReentrant {\\\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\\\\\"Not allowed\\\\\\\");\\\\n        require(\\\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\\\n            \\\\\\\"Wrong swap tokens\\\\\\\"\\\\n        );\\\\n\\\\n        // wrap eth to weth\\\\n        weth.deposit{value: msg.value}();\\\\n\\\\n        // pay weth and get wPowerPerp in return.\\\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\\\n\\\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\\\n\\\\n        // send back unused eth and withdrawn collateral\\\\n        weth.withdraw(msg.value.sub(amountIn));\\\\n        // no eth should be left in the contract, so we send it all back\\\\n        payable(msg.sender).sendValue(address(this).balance);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev only receive eth from weth contract and controller.\\\\n     */\\\\n    receive() external payable {\\\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\\\\\"can't receive eth\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\\\n     * @return returns received selector\\\\n     */\\\\n    function onERC721Received(\\\\n        address,\\\\n        address,\\\\n        uint256,\\\\n        bytes memory\\\\n    ) public virtual override returns (bytes4) {\\\\n        return this.onERC721Received.selector;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x512bb00cb9e4a780ba460ef629f3c581feb8ca669373417beeefdcbc1233c4d1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x6101206040523480156200001257600080fd5b5060405162001643380380620016438339810160408190526200003591620003e6565b60016000556001600160a01b0383166200006c5760405162461bcd60e51b81526004016200006390620004a1565b60405180910390fd5b6001600160a01b038216620000955760405162461bcd60e51b81526004016200006390620004d8565b6001600160a01b038116620000be5760405162461bcd60e51b815260040162000063906200046a565b6000839050826001600160a01b031660a0816001600160a01b031660601b81525050806001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b1580156200011a57600080fd5b505afa1580156200012f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001559190620003c2565b6001600160a01b0316610100816001600160a01b031660601b815250506000816001600160a01b0316637f07b1306040518163ffffffff1660e01b815260040160206040518083038186803b158015620001ae57600080fd5b505afa158015620001c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001e99190620003c2565b60405163095ea7b360e01b815290915083906001600160a01b0383169063095ea7b390620002209088906000199060040162000451565b602060405180830381600087803b1580156200023b57600080fd5b505af115801562000250573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200027691906200042f565b5060405163095ea7b360e01b81526001600160a01b0382169063095ea7b390620002a99088906000199060040162000451565b602060405180830381600087803b158015620002c457600080fd5b505af1158015620002d9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ff91906200042f565b50826001600160a01b0316639d4c94426040518163ffffffff1660e01b815260040160206040518083038186803b1580156200033a57600080fd5b505afa1580156200034f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003759190620003c2565b6001600160601b0319606091821b811660e05291811b821660c0529290921b909116608052506200050f92505050565b80516001600160a01b0381168114620003bd57600080fd5b919050565b600060208284031215620003d4578081fd5b620003df82620003a5565b9392505050565b600080600060608486031215620003fb578182fd5b6200040684620003a5565b92506200041660208501620003a5565b91506200042660408501620003a5565b90509250925092565b60006020828403121562000441578081fd5b81518015158114620003df578182fd5b6001600160a01b03929092168252602082015260400190565b60208082526014908201527f496e76616c696420776574682061646472657373000000000000000000000000604082015260600190565b6020808252601a908201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604082015260600190565b6020808252601b908201527f496e76616c6964207377617020726f7574657220616464726573730000000000604082015260600190565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c611097620005ac60003980610314528061060a52806107b952508061025f528061062e52806106c45280610a1e525080608f528061035452806103aa528061054a52806105e65280610779528061098e52508061043452806108d85280610abe52508060c152806104d752806108125280610a9a52506110976000f3fe60806040526004361061007f5760003560e01c80639d4c94421161004e5780639d4c94421461018f578063e56cfbbe146101a4578063f77c4791146101b7578063f887ea40146101cc5761010a565b8063150b7a021461010f57806317fd9e0e146101455780633fc8cef3146101585780637f07b1301461017a5761010a565b3661010a57336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100e35750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6101085760405162461bcd60e51b81526004016100ff90610f86565b60405180910390fd5b005b600080fd5b34801561011b57600080fd5b5061012f61012a366004610d1e565b6101e1565b60405161013c9190610eeb565b60405180910390f35b610108610153366004610e0f565b6101f1565b34801561016457600080fd5b5061016d6105e4565b60405161013c9190610eb3565b34801561018657600080fd5b5061016d610608565b34801561019b57600080fd5b5061016d61062c565b6101086101b2366004610e0f565b610650565b3480156101c357600080fd5b5061016d610a98565b3480156101d857600080fd5b5061016d610abc565b630a85bd0160e11b949350505050565b60026000541415610249576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000556040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e9061029c908890600401610fcc565b60206040518083038186803b1580156102b457600080fd5b505afa1580156102c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ec9190610cfb565b6001600160a01b0316146103125760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b031614801561038c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b6103a85760405162461bcd60e51b81526004016100ff90610f18565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561040357600080fd5b505af1158015610417573d6000803e3d6000fd5b5050604051631b67c43360e31b8152600093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063db3e2198915061046b908590600401610fbd565b602060405180830381600087803b15801561048557600080fd5b505af1158015610499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104bd9190610dd4565b604051638632cb0360e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638632cb039061051090889088908890600401610fd5565b600060405180830381600087803b15801561052a57600080fd5b505af115801561053e573d6000803e3d6000fd5b50506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169150632e1a7d4d905061057d3484610ae0565b6040518263ffffffff1660e01b81526004016105999190610fcc565b600060405180830381600087803b1580156105b357600080fd5b505af11580156105c7573d6000803e3d6000fd5b506105d89250339150479050610b42565b50506001600055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600260005414156106a8576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000558315610777576040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90610701908890600401610fcc565b60206040518083038186803b15801561071957600080fd5b505afa15801561072d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107519190610cfb565b6001600160a01b0316146107775760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b03161480156107f157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b61080d5760405162461bcd60e51b81526004016100ff90610f18565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631bf7bf6c348888886040518563ffffffff1660e01b815260040161086193929190610fd5565b60408051808303818588803b15801561087957600080fd5b505af115801561088d573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906108b29190610dec565b60a0850181905260405163414bf38960e01b815291935091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063414bf3899061090d908790600401610fbd565b602060405180830381600087803b15801561092757600080fd5b505af115801561093b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095f9190610dd4565b60608501519091506001600160a01b0316301415610a0257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906109c3908490600401610fcc565b600060405180830381600087803b1580156109dd57600080fd5b505af11580156109f1573d6000803e3d6000fd5b50610a029250339150839050610b42565b86610a8a57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610a5790309033908890600401610ec7565b600060405180830381600087803b158015610a7157600080fd5b505af1158015610a85573d6000803e3d6000fd5b505050505b505060016000555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600082821115610b37576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b80471015610b97576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610be2576040519150601f19603f3d011682016040523d82523d6000602084013e610be7565b606091505b5050905080610c275760405162461bcd60e51b815260040180806020018281038252603a815260200180611028603a913960400191505060405180910390fd5b505050565b8035610c378161100f565b919050565b6000610100808385031215610c4f578182fd5b6040519081019067ffffffffffffffff82118183101715610c6c57fe5b81604052809250610c7c84610c2c565b8152610c8a60208501610c2c565b6020820152610c9b60408501610ce8565b6040820152610cac60608501610c2c565b60608201526080840135608082015260a084013560a082015260c084013560c0820152610cdb60e08501610c2c565b60e0820152505092915050565b803562ffffff81168114610c3757600080fd5b600060208284031215610d0c578081fd5b8151610d178161100f565b9392505050565b60008060008060808587031215610d33578283fd5b8435610d3e8161100f565b9350602085810135610d4f8161100f565b935060408601359250606086013567ffffffffffffffff80821115610d72578384fd5b818801915088601f830112610d85578384fd5b813581811115610d9157fe5b610da3601f8201601f19168501610feb565b91508082528984828501011115610db8578485fd5b8084840185840137810190920192909252939692955090935050565b600060208284031215610de5578081fd5b5051919050565b60008060408385031215610dfe578182fd5b505080516020909101519092909150565b6000806000806101608587031215610e25578384fd5b843593506020850135925060408501359150610e448660608701610c3c565b905092959194509250565b6001600160a01b0380825116835280602083015116602084015262ffffff60408301511660408401528060608301511660608401526080820151608084015260a082015160a084015260c082015160c08401528060e08301511660e0840152505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b60208082526011908201527f57726f6e67207377617020746f6b656e73000000000000000000000000000000604082015260600190565b6020808252600b908201527f4e6f7420616c6c6f776564000000000000000000000000000000000000000000604082015260600190565b60208082526011908201527f63616e2774207265636569766520657468000000000000000000000000000000604082015260600190565b6101008101610b3c8284610e4f565b90815260200190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561100757fe5b604052919050565b6001600160a01b038116811461102457600080fd5b5056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a2646970667358221220dca83f927accd8f5dd17b8c7ca8e2147659fcc484c1799c390e51729507a6b9f64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x60806040526004361061007f5760003560e01c80639d4c94421161004e5780639d4c94421461018f578063e56cfbbe146101a4578063f77c4791146101b7578063f887ea40146101cc5761010a565b8063150b7a021461010f57806317fd9e0e146101455780633fc8cef3146101585780637f07b1301461017a5761010a565b3661010a57336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806100e35750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6101085760405162461bcd60e51b81526004016100ff90610f86565b60405180910390fd5b005b600080fd5b34801561011b57600080fd5b5061012f61012a366004610d1e565b6101e1565b60405161013c9190610eeb565b60405180910390f35b610108610153366004610e0f565b6101f1565b34801561016457600080fd5b5061016d6105e4565b60405161013c9190610eb3565b34801561018657600080fd5b5061016d610608565b34801561019b57600080fd5b5061016d61062c565b6101086101b2366004610e0f565b610650565b3480156101c357600080fd5b5061016d610a98565b3480156101d857600080fd5b5061016d610abc565b630a85bd0160e11b949350505050565b60026000541415610249576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000556040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e9061029c908890600401610fcc565b60206040518083038186803b1580156102b457600080fd5b505afa1580156102c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ec9190610cfb565b6001600160a01b0316146103125760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b031614801561038c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b6103a85760405162461bcd60e51b81526004016100ff90610f18565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561040357600080fd5b505af1158015610417573d6000803e3d6000fd5b5050604051631b67c43360e31b8152600093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063db3e2198915061046b908590600401610fbd565b602060405180830381600087803b15801561048557600080fd5b505af1158015610499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104bd9190610dd4565b604051638632cb0360e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638632cb039061051090889088908890600401610fd5565b600060405180830381600087803b15801561052a57600080fd5b505af115801561053e573d6000803e3d6000fd5b50506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169150632e1a7d4d905061057d3484610ae0565b6040518263ffffffff1660e01b81526004016105999190610fcc565b600060405180830381600087803b1580156105b357600080fd5b505af11580156105c7573d6000803e3d6000fd5b506105d89250339150479050610b42565b50506001600055505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600260005414156106a8576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000558315610777576040516331a9108f60e11b815233907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90610701908890600401610fcc565b60206040518083038186803b15801561071957600080fd5b505afa15801561072d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107519190610cfb565b6001600160a01b0316146107775760405162461bcd60e51b81526004016100ff90610f4f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b03161480156107f157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681600001516001600160a01b0316145b61080d5760405162461bcd60e51b81526004016100ff90610f18565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631bf7bf6c348888886040518563ffffffff1660e01b815260040161086193929190610fd5565b60408051808303818588803b15801561087957600080fd5b505af115801561088d573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906108b29190610dec565b60a0850181905260405163414bf38960e01b815291935091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063414bf3899061090d908790600401610fbd565b602060405180830381600087803b15801561092757600080fd5b505af115801561093b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095f9190610dd4565b60608501519091506001600160a01b0316301415610a0257604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906109c3908490600401610fcc565b600060405180830381600087803b1580156109dd57600080fd5b505af11580156109f1573d6000803e3d6000fd5b50610a029250339150839050610b42565b86610a8a57604051632142170760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90610a5790309033908890600401610ec7565b600060405180830381600087803b158015610a7157600080fd5b505af1158015610a85573d6000803e3d6000fd5b505050505b505060016000555050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600082821115610b37576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b80471015610b97576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114610be2576040519150601f19603f3d011682016040523d82523d6000602084013e610be7565b606091505b5050905080610c275760405162461bcd60e51b815260040180806020018281038252603a815260200180611028603a913960400191505060405180910390fd5b505050565b8035610c378161100f565b919050565b6000610100808385031215610c4f578182fd5b6040519081019067ffffffffffffffff82118183101715610c6c57fe5b81604052809250610c7c84610c2c565b8152610c8a60208501610c2c565b6020820152610c9b60408501610ce8565b6040820152610cac60608501610c2c565b60608201526080840135608082015260a084013560a082015260c084013560c0820152610cdb60e08501610c2c565b60e0820152505092915050565b803562ffffff81168114610c3757600080fd5b600060208284031215610d0c578081fd5b8151610d178161100f565b9392505050565b60008060008060808587031215610d33578283fd5b8435610d3e8161100f565b9350602085810135610d4f8161100f565b935060408601359250606086013567ffffffffffffffff80821115610d72578384fd5b818801915088601f830112610d85578384fd5b813581811115610d9157fe5b610da3601f8201601f19168501610feb565b91508082528984828501011115610db8578485fd5b8084840185840137810190920192909252939692955090935050565b600060208284031215610de5578081fd5b5051919050565b60008060408385031215610dfe578182fd5b505080516020909101519092909150565b6000806000806101608587031215610e25578384fd5b843593506020850135925060408501359150610e448660608701610c3c565b905092959194509250565b6001600160a01b0380825116835280602083015116602084015262ffffff60408301511660408401528060608301511660608401526080820151608084015260a082015160a084015260c082015160c08401528060e08301511660e0840152505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b60208082526011908201527f57726f6e67207377617020746f6b656e73000000000000000000000000000000604082015260600190565b6020808252600b908201527f4e6f7420616c6c6f776564000000000000000000000000000000000000000000604082015260600190565b60208082526011908201527f63616e2774207265636569766520657468000000000000000000000000000000604082015260600190565b6101008101610b3c8284610e4f565b90815260200190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561100757fe5b604052919050565b6001600160a01b038116811461102457600080fd5b5056fe416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564a2646970667358221220dca83f927accd8f5dd17b8c7ca8e2147659fcc484c1799c390e51729507a6b9f64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"params\": {\n          \"_vaultId\": \"short wPowerPerp vault id\",\n          \"_wPowerPerpAmount\": \"amount of wPowerPerp to burn\",\n          \"_withdrawAmount\": \"amount to withdraw\"\n        }\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_controllerAddr\": \"controller address for wPowerPerp\",\n          \"_swapRouter\": \"uniswap v3 swap router address\",\n          \"_wethAddr\": \"weth address\"\n        }\n      },\n      \"onERC721Received(address,address,uint256,bytes)\": {\n        \"details\": \"accept erc721 from safeTransferFrom and safeMint after callback\",\n        \"returns\": {\n          \"_0\": \"returns received selector\"\n        }\n      },\n      \"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"params\": {\n          \"_powerPerpAmount\": \"amount of powerPerp to mint/sell\",\n          \"_uniNftId\": \"uniswap v3 position token id\",\n          \"_vaultId\": \"short wPowerPerp vault id\"\n        }\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"closeShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"notice\": \"buy back wPowerPerp with eth on uniswap v3 and close position\"\n      },\n      \"constructor\": {\n        \"notice\": \"constructor for short helper\"\n      },\n      \"openShort(uint256,uint256,uint256,(address,address,uint24,address,uint256,uint256,uint256,uint160))\": {\n        \"notice\": \"mint power perp, trade with uniswap v3 and send back premium in eth\"\n      }\n    },\n    \"notice\": \"contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 3698,\n        \"contract\": \"contracts/periphery/ShortHelper.sol:ShortHelper\",\n        \"label\": \"_status\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_uint256\"\n      }\n    ],\n    \"types\": {\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/ShortPowerPerp.json",
    "content": "{\n  \"address\": \"0x49721ED2d693F3653BC1216b8E330fA53CFC80eD\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_name\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_symbol\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"approved\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bool\",\n          \"name\": \"approved\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"ApprovalForAll\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"baseURI\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"controller\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"getApproved\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controller\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"init\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"isApprovedForAll\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_recipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"mintNFT\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"nextId\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ownerOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"safeTransferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"safeTransferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"operator\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"approved\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"setApprovalForAll\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes4\",\n          \"name\": \"interfaceId\",\n          \"type\": \"bytes4\"\n        }\n      ],\n      \"name\": \"supportsInterface\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"index\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenByIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"index\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenOfOwnerByIndex\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"tokenURI\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"tokenId\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0xb5199ef3cb3408a4de4824276e1c5b37bd6b96dca8ac2b8c399c175cf79a0400\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xf668606B896389066a39B132741763e1ca6d76a2\",\n    \"contractAddress\": \"0x49721ED2d693F3653BC1216b8E330fA53CFC80eD\",\n    \"transactionIndex\": 16,\n    \"gasUsed\": \"1944244\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x50c0f0d447465112ecb485396c98947c8a38bcad9e1acc9829f89ed3d036a50d\",\n    \"transactionHash\": \"0xb5199ef3cb3408a4de4824276e1c5b37bd6b96dca8ac2b8c399c175cf79a0400\",\n    \"logs\": [],\n    \"blockNumber\": 11808027,\n    \"cumulativeGasUsed\": \"7514922\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"short Squeeth\",\n    \"sSQTH\"\n  ],\n  \"solcInputHash\": \"5f450d03d2b8109eaf06de68c57d8c2b\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_name\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_symbol\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"ApprovalForAll\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"baseURI\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"getApproved\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controller\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"init\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"isApprovedForAll\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_recipient\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"mintNFT\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"nextId\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ownerOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"safeTransferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"_data\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"name\\\":\\\"safeTransferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"operator\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"approved\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"setApprovalForAll\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bytes4\\\",\\\"name\\\":\\\"interfaceId\\\",\\\"type\\\":\\\"bytes4\\\"}],\\\"name\\\":\\\"supportsInterface\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"index\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenByIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"index\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenOfOwnerByIndex\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"tokenURI\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"tokenId\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-approve}.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC721-balanceOf}.\\\"},\\\"baseURI()\\\":{\\\"details\\\":\\\"Returns the base URI set via {_setBaseURI}. This will be automatically added as a prefix in {tokenURI} to each token's URI, or to the token ID if no specific URI is set for that token ID.\\\"},\\\"constructor\\\":{\\\"params\\\":{\\\"_name\\\":\\\"token name for ERC721\\\",\\\"_symbol\\\":\\\"token symbol for ERC721\\\"}},\\\"getApproved(uint256)\\\":{\\\"details\\\":\\\"See {IERC721-getApproved}.\\\"},\\\"init(address)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\"}},\\\"isApprovedForAll(address,address)\\\":{\\\"details\\\":\\\"See {IERC721-isApprovedForAll}.\\\"},\\\"mintNFT(address)\\\":{\\\"details\\\":\\\"autoincrement tokenId starts at 1\\\",\\\"params\\\":{\\\"_recipient\\\":\\\"recipient address for NFT\\\"}},\\\"name()\\\":{\\\"details\\\":\\\"See {IERC721Metadata-name}.\\\"},\\\"ownerOf(uint256)\\\":{\\\"details\\\":\\\"See {IERC721-ownerOf}.\\\"},\\\"safeTransferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-safeTransferFrom}.\\\"},\\\"safeTransferFrom(address,address,uint256,bytes)\\\":{\\\"details\\\":\\\"See {IERC721-safeTransferFrom}.\\\"},\\\"setApprovalForAll(address,bool)\\\":{\\\"details\\\":\\\"See {IERC721-setApprovalForAll}.\\\"},\\\"supportsInterface(bytes4)\\\":{\\\"details\\\":\\\"See {IERC165-supportsInterface}. Time complexity O(1), guaranteed to always use less than 30 000 gas.\\\"},\\\"symbol()\\\":{\\\"details\\\":\\\"See {IERC721Metadata-symbol}.\\\"},\\\"tokenByIndex(uint256)\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-tokenByIndex}.\\\"},\\\"tokenOfOwnerByIndex(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-tokenOfOwnerByIndex}.\\\"},\\\"tokenURI(uint256)\\\":{\\\"details\\\":\\\"See {IERC721Metadata-tokenURI}.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC721Enumerable-totalSupply}.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC721-transferFrom}.\\\"}},\\\"stateVariables\\\":{\\\"nextId\\\":{\\\"details\\\":\\\"tokenId for the next vault opened\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"constructor\\\":{\\\"notice\\\":\\\"short power perpetual constructor\\\"},\\\"init(address)\\\":{\\\"notice\\\":\\\"initialize short contract\\\"},\\\"mintNFT(address)\\\":{\\\"notice\\\":\\\"mint new NFT\\\"}},\\\"notice\\\":\\\"ERC721 NFT representing ownership of a vault (short position)\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/ShortPowerPerp.sol\\\":\\\"ShortPowerPerp\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/introspection/ERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Implementation of the {IERC165} interface.\\\\n *\\\\n * Contracts may inherit from this and call {_registerInterface} to declare\\\\n * their support of an interface.\\\\n */\\\\nabstract contract ERC165 is IERC165 {\\\\n    /*\\\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\\\n\\\\n    /**\\\\n     * @dev Mapping of interface ids to whether or not it's supported.\\\\n     */\\\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\\\n\\\\n    constructor () {\\\\n        // Derived contracts need only register support for their own interfaces,\\\\n        // we register support for ERC165 itself here\\\\n        _registerInterface(_INTERFACE_ID_ERC165);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC165-supportsInterface}.\\\\n     *\\\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\\\n        return _supportedInterfaces[interfaceId];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Registers the contract as an implementer of the interface defined by\\\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\\\n     * registering its interface id is not required.\\\\n     *\\\\n     * See {IERC165-supportsInterface}.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\\\n     */\\\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\\\n        require(interfaceId != 0xffffffff, \\\\\\\"ERC165: invalid interface id\\\\\\\");\\\\n        _supportedInterfaces[interfaceId] = true;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x234cdf2c3efd5f0dc17d32fe65d33c21674ca17de1e945eb60ac1076d7152d96\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/introspection/IERC165.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC165 standard, as defined in the\\\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\\\n *\\\\n * Implementers can declare support of contract interfaces, which can then be\\\\n * queried by others ({ERC165Checker}).\\\\n *\\\\n * For an implementation, see {ERC165}.\\\\n */\\\\ninterface IERC165 {\\\\n    /**\\\\n     * @dev Returns true if this contract implements the interface defined by\\\\n     * `interfaceId`. See the corresponding\\\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\\\n     * to learn more about how these ids are created.\\\\n     *\\\\n     * This function call must use less than 30 000 gas.\\\\n     */\\\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// solhint-disable-next-line compiler-version\\\\npragma solidity >=0.4.24 <0.8.0;\\\\n\\\\nimport \\\\\\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\\\nabstract contract Initializable {\\\\n\\\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\\\n    function _isConstructor() private view returns (bool) {\\\\n        return !Address.isContract(address(this));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9abeffe138f098b16557187383ba0f9e8503602fa95cd668132986ee115237ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721Metadata.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721Enumerable.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC721Receiver.sol\\\\\\\";\\\\nimport \\\\\\\"../../introspection/ERC165.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/Address.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/EnumerableSet.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/EnumerableMap.sol\\\\\\\";\\\\nimport \\\\\\\"../../utils/Strings.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\\\n    using SafeMath for uint256;\\\\n    using Address for address;\\\\n    using EnumerableSet for EnumerableSet.UintSet;\\\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\\\n    using Strings for uint256;\\\\n\\\\n    // Equals to `bytes4(keccak256(\\\\\\\"onERC721Received(address,address,uint256,bytes)\\\\\\\"))`\\\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\\\n\\\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\\\n\\\\n    // Enumerable mapping from token ids to their owners\\\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\\\n\\\\n    // Mapping from token ID to approved address\\\\n    mapping (uint256 => address) private _tokenApprovals;\\\\n\\\\n    // Mapping from owner to operator approvals\\\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\\\n\\\\n    // Token name\\\\n    string private _name;\\\\n\\\\n    // Token symbol\\\\n    string private _symbol;\\\\n\\\\n    // Optional mapping for token URIs\\\\n    mapping (uint256 => string) private _tokenURIs;\\\\n\\\\n    // Base URI\\\\n    string private _baseURI;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\\\n     *\\\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\\\n     *\\\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\\\n\\\\n    /*\\\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\\\n     *\\\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\\\n     */\\\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\\\n\\\\n    /**\\\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\\\n     */\\\\n    constructor (string memory name_, string memory symbol_) {\\\\n        _name = name_;\\\\n        _symbol = symbol_;\\\\n\\\\n        // register the supported interfaces to conform to ERC721 via ERC165\\\\n        _registerInterface(_INTERFACE_ID_ERC721);\\\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-balanceOf}.\\\\n     */\\\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\\\n        require(owner != address(0), \\\\\\\"ERC721: balance query for the zero address\\\\\\\");\\\\n        return _holderTokens[owner].length();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-ownerOf}.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\\\n        return _tokenOwners.get(tokenId, \\\\\\\"ERC721: owner query for nonexistent token\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-name}.\\\\n     */\\\\n    function name() public view virtual override returns (string memory) {\\\\n        return _name;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-symbol}.\\\\n     */\\\\n    function symbol() public view virtual override returns (string memory) {\\\\n        return _symbol;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Metadata-tokenURI}.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721Metadata: URI query for nonexistent token\\\\\\\");\\\\n\\\\n        string memory _tokenURI = _tokenURIs[tokenId];\\\\n        string memory base = baseURI();\\\\n\\\\n        // If there is no base URI, return the token URI.\\\\n        if (bytes(base).length == 0) {\\\\n            return _tokenURI;\\\\n        }\\\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\\\n        if (bytes(_tokenURI).length > 0) {\\\\n            return string(abi.encodePacked(base, _tokenURI));\\\\n        }\\\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\\\n        return string(abi.encodePacked(base, tokenId.toString()));\\\\n    }\\\\n\\\\n    /**\\\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\\\n    * to the token ID if no specific URI is set for that token ID.\\\\n    */\\\\n    function baseURI() public view virtual returns (string memory) {\\\\n        return _baseURI;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\\\n        return _holderTokens[owner].at(index);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-totalSupply}.\\\\n     */\\\\n    function totalSupply() public view virtual override returns (uint256) {\\\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\\\n        return _tokenOwners.length();\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\\\n     */\\\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\\\n        return tokenId;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-approve}.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) public virtual override {\\\\n        address owner = ERC721.ownerOf(tokenId);\\\\n        require(to != owner, \\\\\\\"ERC721: approval to current owner\\\\\\\");\\\\n\\\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\\\n            \\\\\\\"ERC721: approve caller is not owner nor approved for all\\\\\\\"\\\\n        );\\\\n\\\\n        _approve(to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-getApproved}.\\\\n     */\\\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721: approved query for nonexistent token\\\\\\\");\\\\n\\\\n        return _tokenApprovals[tokenId];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-setApprovalForAll}.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\\\n        require(operator != _msgSender(), \\\\\\\"ERC721: approve to caller\\\\\\\");\\\\n\\\\n        _operatorApprovals[_msgSender()][operator] = approved;\\\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-isApprovedForAll}.\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\\\n        return _operatorApprovals[owner][operator];\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-transferFrom}.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\\\n        //solhint-disable-next-line max-line-length\\\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\\\\\"ERC721: transfer caller is not owner nor approved\\\\\\\");\\\\n\\\\n        _transfer(from, to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-safeTransferFrom}.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\\\n        safeTransferFrom(from, to, tokenId, \\\\\\\"\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev See {IERC721-safeTransferFrom}.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\\\\\"ERC721: transfer caller is not owner nor approved\\\\\\\");\\\\n        _safeTransfer(from, to, tokenId, _data);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\\\n     *\\\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\\\n        _transfer(from, to, tokenId);\\\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns whether `tokenId` exists.\\\\n     *\\\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Tokens start existing when they are minted (`_mint`),\\\\n     * and stop existing when they are burned (`_burn`).\\\\n     */\\\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\\\n        return _tokenOwners.contains(tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721: operator query for nonexistent token\\\\\\\");\\\\n        address owner = ERC721.ownerOf(tokenId);\\\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\\\n     *\\\\n     * Requirements:\\\\n     d*\\\\n     * - `tokenId` must not exist.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\\\n        _safeMint(to, tokenId, \\\\\\\"\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\\\n     */\\\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\\\n        _mint(to, tokenId);\\\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Mints `tokenId` and transfers it to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must not exist.\\\\n     * - `to` cannot be the zero address.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _mint(address to, uint256 tokenId) internal virtual {\\\\n        require(to != address(0), \\\\\\\"ERC721: mint to the zero address\\\\\\\");\\\\n        require(!_exists(tokenId), \\\\\\\"ERC721: token already minted\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(address(0), to, tokenId);\\\\n\\\\n        _holderTokens[to].add(tokenId);\\\\n\\\\n        _tokenOwners.set(tokenId, to);\\\\n\\\\n        emit Transfer(address(0), to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Destroys `tokenId`.\\\\n     * The approval is cleared when the token is burned.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _burn(uint256 tokenId) internal virtual {\\\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\\\n\\\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\\\n\\\\n        // Clear approvals\\\\n        _approve(address(0), tokenId);\\\\n\\\\n        // Clear metadata (if any)\\\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\\\n            delete _tokenURIs[tokenId];\\\\n        }\\\\n\\\\n        _holderTokens[owner].remove(tokenId);\\\\n\\\\n        _tokenOwners.remove(tokenId);\\\\n\\\\n        emit Transfer(owner, address(0), tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` from `from` to `to`.\\\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\\\n        require(ERC721.ownerOf(tokenId) == from, \\\\\\\"ERC721: transfer of token that is not own\\\\\\\"); // internal owner\\\\n        require(to != address(0), \\\\\\\"ERC721: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(from, to, tokenId);\\\\n\\\\n        // Clear approvals from the previous owner\\\\n        _approve(address(0), tokenId);\\\\n\\\\n        _holderTokens[from].remove(tokenId);\\\\n        _holderTokens[to].add(tokenId);\\\\n\\\\n        _tokenOwners.set(tokenId, to);\\\\n\\\\n        emit Transfer(from, to, tokenId);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\\\n        require(_exists(tokenId), \\\\\\\"ERC721Metadata: URI set of nonexistent token\\\\\\\");\\\\n        _tokenURIs[tokenId] = _tokenURI;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Internal function to set the base URI for all token IDs. It is\\\\n     * automatically added as a prefix to the value returned in {tokenURI},\\\\n     * or to the token ID if {tokenURI} is empty.\\\\n     */\\\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\\\n        _baseURI = baseURI_;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\\\n     * The call is not executed if the target address is not a contract.\\\\n     *\\\\n     * @param from address representing the previous owner of the given token ID\\\\n     * @param to target address that will receive the tokens\\\\n     * @param tokenId uint256 ID of the token to be transferred\\\\n     * @param _data bytes optional data to send along with the call\\\\n     * @return bool whether the call correctly returned the expected magic value\\\\n     */\\\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\\\n        private returns (bool)\\\\n    {\\\\n        if (!to.isContract()) {\\\\n            return true;\\\\n        }\\\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\\\n            IERC721Receiver(to).onERC721Received.selector,\\\\n            _msgSender(),\\\\n            from,\\\\n            tokenId,\\\\n            _data\\\\n        ), \\\\\\\"ERC721: transfer to non ERC721Receiver implementer\\\\\\\");\\\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\\\n        return (retval == _ERC721_RECEIVED);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Approve `to` to operate on `tokenId`\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function _approve(address to, uint256 tokenId) internal virtual {\\\\n        _tokenApprovals[tokenId] = to;\\\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Hook that is called before any token transfer. This includes minting\\\\n     * and burning.\\\\n     *\\\\n     * Calling conditions:\\\\n     *\\\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\\\n     * transferred to `to`.\\\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     *\\\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\\\n     */\\\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x93e4f65a89c3c888afbaa3ee18c3fa4f51c422419bbcd9cca47676a0f8e507ea\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../introspection/IERC165.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @dev Required interface of an ERC721 compliant contract.\\\\n */\\\\ninterface IERC721 is IERC165 {\\\\n    /**\\\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\\\n     */\\\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\\\n\\\\n    /**\\\\n     * @dev Returns the number of tokens in ``owner``'s account.\\\\n     */\\\\n    function balanceOf(address owner) external view returns (uint256 balance);\\\\n\\\\n    /**\\\\n     * @dev Returns the owner of the `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\\\n\\\\n    /**\\\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must exist and be owned by `from`.\\\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\\\n     *\\\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `from` cannot be the zero address.\\\\n     * - `to` cannot be the zero address.\\\\n     * - `tokenId` token must be owned by `from`.\\\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\\\n     * The approval is cleared when the token is transferred.\\\\n     *\\\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The caller must own the token or be an approved operator.\\\\n     * - `tokenId` must exist.\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address to, uint256 tokenId) external;\\\\n\\\\n    /**\\\\n     * @dev Returns the account approved for `tokenId` token.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `tokenId` must exist.\\\\n     */\\\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\\\n\\\\n    /**\\\\n     * @dev Approve or remove `operator` as an operator for the caller.\\\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The `operator` cannot be the caller.\\\\n     *\\\\n     * Emits an {ApprovalForAll} event.\\\\n     */\\\\n    function setApprovalForAll(address operator, bool _approved) external;\\\\n\\\\n    /**\\\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\\\n     *\\\\n     * See {setApprovalForAll}\\\\n     */\\\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\\\n\\\\n    /**\\\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\\\n      *\\\\n      * Requirements:\\\\n      *\\\\n      * - `from` cannot be the zero address.\\\\n      * - `to` cannot be the zero address.\\\\n      * - `tokenId` token must exist and be owned by `from`.\\\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\\\n      *\\\\n      * Emits a {Transfer} event.\\\\n      */\\\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Enumerable is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the total amount of tokens stored by the contract.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\\\n     */\\\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\\\n\\\\n    /**\\\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\\\n     * Use along with {totalSupply} to enumerate all tokens.\\\\n     */\\\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2789dfea2d73182683d637db5729201f6730dae6113030a94c828f8688f38f2f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"./IERC721.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\\\n */\\\\ninterface IERC721Metadata is IERC721 {\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection name.\\\\n     */\\\\n    function name() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the token collection symbol.\\\\n     */\\\\n    function symbol() external view returns (string memory);\\\\n\\\\n    /**\\\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\\\n     */\\\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc82c7d1d732081d9bd23f1555ebdf8f3bc1738bc42c2bfc4b9aa7564d9fa3573\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @title ERC721 token receiver interface\\\\n * @dev Interface for any contract that wants to support safeTransfers\\\\n * from ERC721 asset contracts.\\\\n */\\\\ninterface IERC721Receiver {\\\\n    /**\\\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\\\n     * by `operator` from `from`, this function is called.\\\\n     *\\\\n     * It must return its Solidity selector to confirm the token transfer.\\\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\\\n     *\\\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\\\n     */\\\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x05604ffcf69e416b8a42728bb0e4fd75170d8fac70bf1a284afeb4752a9bc52f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/EnumerableMap.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Library for managing an enumerable variant of Solidity's\\\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\\\n * type.\\\\n *\\\\n * Maps have the following properties:\\\\n *\\\\n * - Entries are added, removed, and checked for existence in constant time\\\\n * (O(1)).\\\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\\\n *\\\\n * ```\\\\n * contract Example {\\\\n *     // Add the library methods\\\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\\\n *\\\\n *     // Declare a set state variable\\\\n *     EnumerableMap.UintToAddressMap private myMap;\\\\n * }\\\\n * ```\\\\n *\\\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\\\n * supported.\\\\n */\\\\nlibrary EnumerableMap {\\\\n    // To implement this library for multiple types with as little code\\\\n    // repetition as possible, we write it in terms of a generic Map type with\\\\n    // bytes32 keys and values.\\\\n    // The Map implementation uses private functions, and user-facing\\\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\\\n    // the underlying Map.\\\\n    // This means that we can only create new EnumerableMaps for types that fit\\\\n    // in bytes32.\\\\n\\\\n    struct MapEntry {\\\\n        bytes32 _key;\\\\n        bytes32 _value;\\\\n    }\\\\n\\\\n    struct Map {\\\\n        // Storage of map keys and values\\\\n        MapEntry[] _entries;\\\\n\\\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\\\n        // because index 0 means a key is not in the map.\\\\n        mapping (bytes32 => uint256) _indexes;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\\\n     * key. O(1).\\\\n     *\\\\n     * Returns true if the key was added to the map, that is if it was not\\\\n     * already present.\\\\n     */\\\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\\\n        uint256 keyIndex = map._indexes[key];\\\\n\\\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\\\n            // The entry is stored at length-1, but we add 1 to all indexes\\\\n            // and use 0 as a sentinel value\\\\n            map._indexes[key] = map._entries.length;\\\\n            return true;\\\\n        } else {\\\\n            map._entries[keyIndex - 1]._value = value;\\\\n            return false;\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Removes a key-value pair from a map. O(1).\\\\n     *\\\\n     * Returns true if the key was removed from the map, that is if it was present.\\\\n     */\\\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\\\n        uint256 keyIndex = map._indexes[key];\\\\n\\\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\\\n            // This modifies the order of the array, as noted in {at}.\\\\n\\\\n            uint256 toDeleteIndex = keyIndex - 1;\\\\n            uint256 lastIndex = map._entries.length - 1;\\\\n\\\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\\\n\\\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\\\n\\\\n            // Move the last entry to the index where the entry to delete is\\\\n            map._entries[toDeleteIndex] = lastEntry;\\\\n            // Update the index for the moved entry\\\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\\\n\\\\n            // Delete the slot where the moved entry was stored\\\\n            map._entries.pop();\\\\n\\\\n            // Delete the index for the deleted slot\\\\n            delete map._indexes[key];\\\\n\\\\n            return true;\\\\n        } else {\\\\n            return false;\\\\n        }\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns true if the key is in the map. O(1).\\\\n     */\\\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\\\n        return map._indexes[key] != 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\\\n     */\\\\n    function _length(Map storage map) private view returns (uint256) {\\\\n        return map._entries.length;\\\\n    }\\\\n\\\\n   /**\\\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\\\n    *\\\\n    * Note that there are no guarantees on the ordering of entries inside the\\\\n    * array, and it may change when more entries are added or removed.\\\\n    *\\\\n    * Requirements:\\\\n    *\\\\n    * - `index` must be strictly less than {length}.\\\\n    */\\\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\\\n        require(map._entries.length > index, \\\\\\\"EnumerableMap: index out of bounds\\\\\\\");\\\\n\\\\n        MapEntry storage entry = map._entries[index];\\\\n        return (entry._key, entry._value);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\\\n     * Does not revert if `key` is not in the map.\\\\n     */\\\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the value associated with `key`.  O(1).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `key` must be in the map.\\\\n     */\\\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        require(keyIndex != 0, \\\\\\\"EnumerableMap: nonexistent key\\\\\\\"); // Equivalent to contains(map, key)\\\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\\\n     */\\\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\\\n        uint256 keyIndex = map._indexes[key];\\\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\\\n    }\\\\n\\\\n    // UintToAddressMap\\\\n\\\\n    struct UintToAddressMap {\\\\n        Map _inner;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\\\n     * key. O(1).\\\\n     *\\\\n     * Returns true if the key was added to the map, that is if it was not\\\\n     * already present.\\\\n     */\\\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Removes a value from a set. O(1).\\\\n     *\\\\n     * Returns true if the key was removed from the map, that is if it was present.\\\\n     */\\\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\\\n        return _remove(map._inner, bytes32(key));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns true if the key is in the map. O(1).\\\\n     */\\\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\\\n        return _contains(map._inner, bytes32(key));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the number of elements in the map. O(1).\\\\n     */\\\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\\\n        return _length(map._inner);\\\\n    }\\\\n\\\\n   /**\\\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\\\n        return (uint256(key), address(uint160(uint256(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\\\n     * Does not revert if `key` is not in the map.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\\\n        return (success, address(uint160(uint256(value))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the value associated with `key`.  O(1).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `key` must be in the map.\\\\n     */\\\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\\\n     */\\\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x2114555153edb5f273008b3d34205f511db9af06b88f752e4c280dd612c4c549\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.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\\\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\\\n\\\\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] = toDeleteIndex + 1; // All indexes are 1-based\\\\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        require(set._values.length > index, \\\\\\\"EnumerableSet: index out of bounds\\\\\\\");\\\\n        return set._values[index];\\\\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    // 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    // 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\\\",\\\"keccak256\\\":\\\"0x9a2c1eebb65250f0e11882237038600f22a62376f0547db4acc0dfe0a3d8d34f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Strings.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev String operations.\\\\n */\\\\nlibrary Strings {\\\\n    /**\\\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\\\n        temp = value;\\\\n        while (temp != 0) {\\\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\\\n            temp /= 10;\\\\n        }\\\\n        return string(buffer);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x08e38e034333372aea8cb1b8846085b7fbab42c6b77a0af464d2c6827827c4f0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math functions that do not check inputs or outputs\\\\n/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks\\\\nlibrary UnsafeMath {\\\\n    /// @notice Returns ceil(x / y)\\\\n    /// @dev division by 0 has unspecified behavior, and must be checked externally\\\\n    /// @param x The dividend\\\\n    /// @param y The divisor\\\\n    /// @return z The quotient, ceil(x / y)\\\\n    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\\\n        assembly {\\\\n            z := add(div(x, y), gt(mod(x, y), 0))\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5f36d7d16348d8c37fe64fda932018d6e5e8acecd054f0f97d32db62d20c6c88\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\\\n\\\\n/// @title ERC721 with permit\\\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\\\ninterface IERC721Permit is IERC721 {\\\\n    /// @notice The permit typehash used in the permit signature\\\\n    /// @return The typehash for the permit\\\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\\\n\\\\n    /// @notice The domain separator used in the permit signature\\\\n    /// @return The domain seperator used in encoding of permit signature\\\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\\\n\\\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\\\n    /// @param spender The account that is being approved\\\\n    /// @param tokenId The ID of the token that is being approved for spending\\\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\\\n    function permit(\\\\n        address spender,\\\\n        uint256 tokenId,\\\\n        uint256 deadline,\\\\n        uint8 v,\\\\n        bytes32 r,\\\\n        bytes32 s\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9e3c2a4ee65ddf95b2dfcb0815784eea3a295707e6f8b83e4c4f0f8fe2e3a1d4\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\\\n\\\\nimport './IPoolInitializer.sol';\\\\nimport './IERC721Permit.sol';\\\\nimport './IPeripheryPayments.sol';\\\\nimport './IPeripheryImmutableState.sol';\\\\nimport '../libraries/PoolAddress.sol';\\\\n\\\\n/// @title Non-fungible token for positions\\\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\\\n/// and authorized.\\\\ninterface INonfungiblePositionManager is\\\\n    IPoolInitializer,\\\\n    IPeripheryPayments,\\\\n    IPeripheryImmutableState,\\\\n    IERC721Metadata,\\\\n    IERC721Enumerable,\\\\n    IERC721Permit\\\\n{\\\\n    /// @notice Emitted when liquidity is increased for a position NFT\\\\n    /// @dev Also emitted when a token is minted\\\\n    /// @param tokenId The ID of the token for which liquidity was increased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\\\n    /// @notice Emitted when tokens are collected for a position NFT\\\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\\\n    /// @param recipient The address of the account that received the collected tokens\\\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Returns the position information associated with a given token ID.\\\\n    /// @dev Throws if the token ID is not valid.\\\\n    /// @param tokenId The ID of the token that represents the position\\\\n    /// @return nonce The nonce for permits\\\\n    /// @return operator The address that is approved for spending\\\\n    /// @return token0 The address of the token0 for a specific pool\\\\n    /// @return token1 The address of the token1 for a specific pool\\\\n    /// @return fee The fee associated with the pool\\\\n    /// @return tickLower The lower end of the tick range for the position\\\\n    /// @return tickUpper The higher end of the tick range for the position\\\\n    /// @return liquidity The liquidity of the position\\\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\\\n    function positions(uint256 tokenId)\\\\n        external\\\\n        view\\\\n        returns (\\\\n            uint96 nonce,\\\\n            address operator,\\\\n            address token0,\\\\n            address token1,\\\\n            uint24 fee,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint256 feeGrowthInside0LastX128,\\\\n            uint256 feeGrowthInside1LastX128,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        );\\\\n\\\\n    struct MintParams {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n        int24 tickLower;\\\\n        int24 tickUpper;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        address recipient;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Creates a new position wrapped in a NFT\\\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\\\n    /// @return tokenId The ID of the token that represents the minted position\\\\n    /// @return liquidity The amount of liquidity for this position\\\\n    /// @return amount0 The amount of token0\\\\n    /// @return amount1 The amount of token1\\\\n    function mint(MintParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint256 tokenId,\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct IncreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint256 amount0Desired;\\\\n        uint256 amount1Desired;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\\\n    /// amount0Desired The desired amount of token0 to be spent,\\\\n    /// amount1Desired The desired amount of token1 to be spent,\\\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return liquidity The new liquidity amount as a result of the increase\\\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (\\\\n            uint128 liquidity,\\\\n            uint256 amount0,\\\\n            uint256 amount1\\\\n        );\\\\n\\\\n    struct DecreaseLiquidityParams {\\\\n        uint256 tokenId;\\\\n        uint128 liquidity;\\\\n        uint256 amount0Min;\\\\n        uint256 amount1Min;\\\\n        uint256 deadline;\\\\n    }\\\\n\\\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\\\n    /// amount The amount by which liquidity will be decreased,\\\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\\\n    /// deadline The time by which the transaction must be included to effect the change\\\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\\\n        external\\\\n        payable\\\\n        returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    struct CollectParams {\\\\n        uint256 tokenId;\\\\n        address recipient;\\\\n        uint128 amount0Max;\\\\n        uint128 amount1Max;\\\\n    }\\\\n\\\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\\\n    /// recipient The account that should receive the tokens,\\\\n    /// amount0Max The maximum amount of token0 to collect,\\\\n    /// amount1Max The maximum amount of token1 to collect\\\\n    /// @return amount0 The amount of fees collected in token0\\\\n    /// @return amount1 The amount of fees collected in token1\\\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\\\n\\\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\\\n    /// must be collected first.\\\\n    /// @param tokenId The ID of the token that is being burned\\\\n    function burn(uint256 tokenId) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe1dadc73e60bf05d0b4e0f05bd2847c5783e833cc10352c14763360b13495ee1\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Immutable state\\\\n/// @notice Functions that return immutable state of the router\\\\ninterface IPeripheryImmutableState {\\\\n    /// @return Returns the address of the Uniswap V3 factory\\\\n    function factory() external view returns (address);\\\\n\\\\n    /// @return Returns the address of WETH9\\\\n    function WETH9() external view returns (address);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x7affcfeb5127c0925a71d6a65345e117c33537523aeca7bc98085ead8452519d\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\n\\\\n/// @title Periphery Payments\\\\n/// @notice Functions to ease deposits and withdrawals of ETH\\\\ninterface IPeripheryPayments {\\\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\\\n    /// @param recipient The address receiving ETH\\\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\\\n\\\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\\\n    /// that use ether for the input amount\\\\n    function refundETH() external payable;\\\\n\\\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\\\n    /// @param recipient The destination address of the token\\\\n    function sweepToken(\\\\n        address token,\\\\n        uint256 amountMinimum,\\\\n        address recipient\\\\n    ) external payable;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xb547e10f1e69bed03621a62b73a503e260643066c6b4054867a4d1fef47eb274\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.7.5;\\\\npragma abicoder v2;\\\\n\\\\n/// @title Creates and initializes V3 Pools\\\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\\\n/// require the pool to exist.\\\\ninterface IPoolInitializer {\\\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\\\n    /// @param token0 The contract address of token0 of the pool\\\\n    /// @param token1 The contract address of token1 of the pool\\\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\\\n    function createAndInitializePoolIfNecessary(\\\\n        address token0,\\\\n        address token1,\\\\n        uint24 fee,\\\\n        uint160 sqrtPriceX96\\\\n    ) external payable returns (address pool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9d7695e8d94c22cc5fcced602017aabb988de89981ea7bee29ea629d5328a862\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\\\nlibrary PoolAddress {\\\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\\\n\\\\n    /// @notice The identifying key of the pool\\\\n    struct PoolKey {\\\\n        address token0;\\\\n        address token1;\\\\n        uint24 fee;\\\\n    }\\\\n\\\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\\\n    /// @param tokenA The first token of a pool, unsorted\\\\n    /// @param tokenB The second token of a pool, unsorted\\\\n    /// @param fee The fee level of the pool\\\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\\\n    function getPoolKey(\\\\n        address tokenA,\\\\n        address tokenB,\\\\n        uint24 fee\\\\n    ) internal pure returns (PoolKey memory) {\\\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\\\n    }\\\\n\\\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\\\n    /// @param factory The Uniswap V3 factory contract address\\\\n    /// @param key The PoolKey\\\\n    /// @return pool The contract address of the V3 pool\\\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\\\n        require(key.token0 < key.token1);\\\\n        pool = address(\\\\n            uint256(\\\\n                keccak256(\\\\n                    abi.encodePacked(\\\\n                        hex'ff',\\\\n                        factory,\\\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\\\n                        POOL_INIT_CODE_HASH\\\\n                    )\\\\n                )\\\\n            )\\\\n        );\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5edd84eb8ba7c12fd8cb6cffe52e1e9f3f6464514ee5f539c2283826209035a2\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/core/ShortPowerPerp.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//contract\\\\nimport {ERC721} from \\\\\\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\\\\\";\\\\nimport {Initializable} from \\\\\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\\\\\";\\\\nimport {IController} from \\\\\\\"../interfaces/IController.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\\\n */\\\\ncontract ShortPowerPerp is ERC721, Initializable {\\\\n    /// @dev tokenId for the next vault opened\\\\n    uint256 public nextId = 1;\\\\n\\\\n    address public controller;\\\\n    address private immutable deployer;\\\\n\\\\n    modifier onlyController() {\\\\n        require(msg.sender == controller, \\\\\\\"Not controller\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice short power perpetual constructor\\\\n     * @param _name token name for ERC721\\\\n     * @param _symbol token symbol for ERC721\\\\n     */\\\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\\\n        deployer = msg.sender;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice initialize short contract\\\\n     * @param _controller controller address\\\\n     */\\\\n    function init(address _controller) public initializer {\\\\n        require(msg.sender == deployer, \\\\\\\"Invalid caller of init\\\\\\\");\\\\n        require(_controller != address(0), \\\\\\\"Invalid controller address\\\\\\\");\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint new NFT\\\\n     * @dev autoincrement tokenId starts at 1\\\\n     * @param _recipient recipient address for NFT\\\\n     */\\\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\\\n        // mint NFT\\\\n        _safeMint(_recipient, (tokenId = nextId++));\\\\n    }\\\\n\\\\n    function _beforeTokenTransfer(\\\\n        address, /* from */\\\\n        address, /* to */\\\\n        uint256 tokenId\\\\n    ) internal override {\\\\n        IController(controller).updateOperator(tokenId, address(0));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x5597686c00b4341803c9119e8402e9207b0d13ca722e724fa9d2c85e8ea6dbf5\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/interfaces/IController.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\npragma abicoder v2;\\\\n\\\\nimport {VaultLib} from \\\\\\\"../libs/VaultLib.sol\\\\\\\";\\\\n\\\\ninterface IController {\\\\n    function ethQuoteCurrencyPool() external view returns (address);\\\\n\\\\n    function feeRate() external view returns (uint256);\\\\n\\\\n    function getFee(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _collateralAmount\\\\n    ) external view returns (uint256);\\\\n\\\\n    function quoteCurrency() external view returns (address);\\\\n\\\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\\\n\\\\n    function shortPowerPerp() external view returns (address);\\\\n\\\\n    function wPowerPerp() external view returns (address);\\\\n\\\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\\\n\\\\n    function mintPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\\\n\\\\n    function mintWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _uniTokenId\\\\n    ) external payable returns (uint256 vaultId);\\\\n\\\\n    /**\\\\n     * Deposit collateral into a vault\\\\n     */\\\\n    function deposit(uint256 _vaultId) external payable;\\\\n\\\\n    /**\\\\n     * Withdraw collateral from a vault.\\\\n     */\\\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\\\n\\\\n    function burnWPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _wPowerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external;\\\\n\\\\n    function burnOnPowerPerpAmount(\\\\n        uint256 _vaultId,\\\\n        uint256 _powerPerpAmount,\\\\n        uint256 _withdrawAmount\\\\n    ) external returns (uint256 wPowerPerpAmount);\\\\n\\\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\\\n\\\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\\\n\\\\n    /**\\\\n     * External function to update the normalized factor as a way to pay funding.\\\\n     */\\\\n    function applyFunding() external;\\\\n\\\\n    function redeemShort(uint256 _vaultId) external;\\\\n\\\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\\\n\\\\n    function isShutDown() external returns (bool);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xc5d6230c8bafcaf2ae7260efd68c45ab13e91819ed9e11881b29dc48386e4bc7\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"contracts/libs/Uint256Casting.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nlibrary Uint256Casting {\\\\n    /**\\\\n     * @notice cast a uint256 to a uint128, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint128\\\\n     */\\\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\\\n        require((z = uint128(y)) == y, \\\\\\\"OF128\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint96, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint96\\\\n     */\\\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\\\n        require((z = uint96(y)) == y, \\\\\\\"OF96\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice cast a uint256 to a uint32, revert on overflow\\\\n     * @param y the uint256 to be downcasted\\\\n     * @return z the downcasted integer, now type uint32\\\\n     */\\\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\\\n        require((z = uint32(y)) == y, \\\\\\\"OF32\\\\\\\");\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xcccbe82f8696be398d0d0f5a44988e9bab70e18dd40c9563620cdf160d8bcd7c\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/libs/VaultLib.sol\\\":{\\\"content\\\":\\\"//SPDX-License-Identifier: GPL-2.0-or-later\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {INonfungiblePositionManager} from \\\\\\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\\\\\";\\\\n\\\\n//lib\\\\nimport {SafeMath} from \\\\\\\"@openzeppelin/contracts/math/SafeMath.sol\\\\\\\";\\\\nimport {TickMathExternal} from \\\\\\\"./TickMathExternal.sol\\\\\\\";\\\\nimport {SqrtPriceMathPartial} from \\\\\\\"./SqrtPriceMathPartial.sol\\\\\\\";\\\\nimport {Uint256Casting} from \\\\\\\"./Uint256Casting.sol\\\\\\\";\\\\n\\\\n/**\\\\n * Error code:\\\\n * V1: Vault already had nft\\\\n * V2: Vault has no NFT\\\\n */\\\\nlibrary VaultLib {\\\\n    using SafeMath for uint256;\\\\n    using Uint256Casting for uint256;\\\\n\\\\n    uint256 constant ONE_ONE = 1e36;\\\\n\\\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\\\n    uint256 public constant CR_NUMERATOR = 3;\\\\n    uint256 public constant CR_DENOMINATOR = 2;\\\\n\\\\n    struct Vault {\\\\n        // the address that can update the vault\\\\n        address operator;\\\\n        // uniswap position token id deposited into the vault as collateral\\\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\\\n        uint32 NftCollateralId;\\\\n        // amount of eth (wei) used in the vault as collateral\\\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\\\n        uint96 collateralAmount;\\\\n        // amount of wPowerPerp minted from the vault\\\\n        uint128 shortAmount;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add eth collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to add\\\\n     */\\\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add uniswap position token collateral to a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _tokenId uniswap position token id\\\\n     */\\\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\\\n        require(_vault.NftCollateralId == 0, \\\\\\\"V1\\\\\\\");\\\\n        require(_tokenId != 0, \\\\\\\"C23\\\\\\\");\\\\n        _vault.NftCollateralId = _tokenId.toUint32();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove eth collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of eth to remove\\\\n     */\\\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove uniswap position token collateral from a vault\\\\n     * @param _vault in-memory vault\\\\n     */\\\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\\\n        require(_vault.NftCollateralId != 0, \\\\\\\"V2\\\\\\\");\\\\n        _vault.NftCollateralId = 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice add debt to vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to add\\\\n     */\\\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice remove debt from vault\\\\n     * @param _vault in-memory vault\\\\n     * @param _amount amount of debt to remove\\\\n     */\\\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice check if a vault is properly collateralized\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return true if the vault is sufficiently collateralized\\\\n     * @return true if the vault is considered as a dust vault\\\\n     */\\\\n    function getVaultStatus(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        uint256 _minCollateral,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (bool, bool) {\\\\n        if (_vault.shortAmount == 0) return (true, false);\\\\n\\\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        uint256 totalCollateral = _getEffectiveCollateral(\\\\n            _vault,\\\\n            _positionManager,\\\\n            _normalizationFactor,\\\\n            _ethQuoteCurrencyPrice,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n\\\\n        bool isDust = totalCollateral < _minCollateral;\\\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\\\n        return (isAboveWater, isDust);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get the total effective collateral of a vault, which is:\\\\n     *         collateral amount + uniswap position token equivelent amount in eth\\\\n     * @param _vault the vault we want to check\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _normalizationFactor current _normalizationFactor\\\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\\\n     * @return the total worth of collateral in the vault\\\\n     */\\\\n    function _getEffectiveCollateral(\\\\n        Vault memory _vault,\\\\n        address _positionManager,\\\\n        uint256 _normalizationFactor,\\\\n        uint256 _ethQuoteCurrencyPrice,\\\\n        int24 _wsqueethPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256) {\\\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\\\n\\\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\\\n            _positionManager,\\\\n            _vault.NftCollateralId,\\\\n            _wsqueethPoolTick,\\\\n            _isWethToken0\\\\n        );\\\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\\\n            ONE_ONE\\\\n        );\\\\n        // add eth value from uniswap position token as collateral\\\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\\\n     * @param _positionManager address of the uniswap position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @param _wPowerPerpPoolTick current price tick\\\\n     * @param _isWethToken0 whether weth is token0 in the pool\\\\n     * @return ethAmount the eth amount this LP token contains\\\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\\\n     */\\\\n    function _getUniPositionBalances(\\\\n        address _positionManager,\\\\n        uint256 _tokenId,\\\\n        int24 _wPowerPerpPoolTick,\\\\n        bool _isWethToken0\\\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\\\n        (\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\\\n            tickLower,\\\\n            tickUpper,\\\\n            _wPowerPerpPoolTick,\\\\n            liquidity\\\\n        );\\\\n\\\\n        return\\\\n            _isWethToken0\\\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get uniswap position token info\\\\n     * @param _positionManager address of the uniswap position position manager\\\\n     * @param _tokenId uniswap position token id\\\\n     * @return tickLower lower tick of the position\\\\n     * @return tickUpper upper tick of the position\\\\n     * @return liquidity raw liquidity amount of the position\\\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\\\n     */\\\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\\\n        internal\\\\n        view\\\\n        returns (\\\\n            int24,\\\\n            int24,\\\\n            uint128,\\\\n            uint128,\\\\n            uint128\\\\n        )\\\\n    {\\\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\\\n        (\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            ,\\\\n            int24 tickLower,\\\\n            int24 tickUpper,\\\\n            uint128 liquidity,\\\\n            ,\\\\n            ,\\\\n            uint128 tokensOwed0,\\\\n            uint128 tokensOwed1\\\\n        ) = positionManager.positions(_tokenId);\\\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice get balances of token0 / token1 in a uniswap position\\\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\\\n     * @param _tickLower address of the uniswap position manager\\\\n     * @param _tickUpper uniswap position token id\\\\n     * @param _tick current price tick used for calculation\\\\n     * @return amount0 the amount of token0 in the uniswap position token\\\\n     * @return amount1 the amount of token1 in the uniswap position token\\\\n     */\\\\n    function _getToken0Token1Balances(\\\\n        int24 _tickLower,\\\\n        int24 _tickUpper,\\\\n        int24 _tick,\\\\n        uint128 _liquidity\\\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\\\n        // get the current price and tick from wPowerPerp pool\\\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\\\n\\\\n        if (_tick < _tickLower) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else if (_tick < _tickUpper) {\\\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\\\n                sqrtPriceX96,\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                sqrtPriceX96,\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        } else {\\\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\\\n                _liquidity,\\\\n                true\\\\n            );\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x939175a827c8e9d8d09ee55957e8127a6a55bf42d6a0b3e48b0b59c895aa85af\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60a06040526001600b553480156200001657600080fd5b506040516200229c3803806200229c833981810160405260408110156200003c57600080fd5b81019080805160405193929190846401000000008211156200005d57600080fd5b9083019060208201858111156200007357600080fd5b82516401000000008111828201881017156200008e57600080fd5b82525081516020918201929091019080838360005b83811015620000bd578181015183820152602001620000a3565b50505050905090810190601f168015620000eb5780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200010f57600080fd5b9083019060208201858111156200012557600080fd5b82516401000000008111828201881017156200014057600080fd5b82525081516020918201929091019080838360005b838110156200016f57818101518382015260200162000155565b50505050905090810190601f1680156200019d5780820380516001836020036101000a031916815260200191505b5060405250839150829050620001ba6301ffc9a760e01b6200022d565b8151620001cf906006906020850190620002b2565b508051620001e5906007906020840190620002b2565b50620001f86380ac58cd60e01b6200022d565b6200020a635b5e139f60e01b6200022d565b6200021c63780e9d6360e01b6200022d565b5050503360601b608052506200035e565b6001600160e01b031980821614156200028d576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152602081905260409020805460ff19166001179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620002ea576000855562000335565b82601f106200030557805160ff191683800117855562000335565b8280016001018555821562000335579182015b828111156200033557825182559160200191906001019062000318565b506200034392915062000347565b5090565b5b8082111562000343576000815560010162000348565b60805160601c611f206200037c600039806107f75250611f206000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806354ba0f27116100d857806395d89b411161008c578063c87b56dd11610066578063c87b56dd14610505578063e985e9c514610522578063f77c47911461055057610177565b806395d89b4114610409578063a22cb46514610411578063b88d4fde1461043f57610177565b80636352211e116100bd5780636352211e146103be5780636c0360eb146103db57806370a08231146103e357610177565b806354ba0f271461039057806361b8ce8c146103b657610177565b806319ab453c1161012f5780632f745c59116101145780632f745c591461031157806342842e0e1461033d5780634f6ccce71461037357610177565b806319ab453c146102b557806323b872dd146102db57610177565b8063081812fc11610160578063081812fc14610234578063095ea7b31461026d57806318160ddd1461029b57610177565b806301ffc9a71461017c57806306fdde03146101b7575b600080fd5b6101a36004803603602081101561019257600080fd5b50356001600160e01b031916610558565b604080519115158252519081900360200190f35b6101bf61057b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f95781810151838201526020016101e1565b50505050905090810190601f1680156102265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102516004803603602081101561024a57600080fd5b5035610611565b604080516001600160a01b039092168252519081900360200190f35b6102996004803603604081101561028357600080fd5b506001600160a01b038135169060200135610673565b005b6102a361074e565b60408051918252519081900360200190f35b610299600480360360208110156102cb57600080fd5b50356001600160a01b031661075f565b610299600480360360608110156102f157600080fd5b506001600160a01b03813581169160208101359091169060400135610902565b6102a36004803603604081101561032757600080fd5b506001600160a01b038135169060200135610959565b6102996004803603606081101561035357600080fd5b506001600160a01b03813581169160208101359091169060400135610984565b6102a36004803603602081101561038957600080fd5b503561099f565b6102a3600480360360208110156103a657600080fd5b50356001600160a01b03166109b5565b6102a3610a2d565b610251600480360360208110156103d457600080fd5b5035610a33565b6101bf610a5b565b6102a3600480360360208110156103f957600080fd5b50356001600160a01b0316610abc565b6101bf610b24565b6102996004803603604081101561042757600080fd5b506001600160a01b0381351690602001351515610b85565b6102996004803603608081101561045557600080fd5b6001600160a01b0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561049057600080fd5b8201836020820111156104a257600080fd5b803590602001918460018302840111640100000000831117156104c457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610c8a945050505050565b6101bf6004803603602081101561051b57600080fd5b5035610ce8565b6101a36004803603604081101561053857600080fd5b506001600160a01b0381358116916020013516610f69565b610251610f97565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b820191906000526020600020905b8154815290600101906020018083116105ea57829003601f168201915b5050505050905090565b600061061c82610fa6565b6106575760405162461bcd60e51b815260040180806020018281038252602c815260200180611e15602c913960400191505060405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061067e82610a33565b9050806001600160a01b0316836001600160a01b031614156106d15760405162461bcd60e51b8152600401808060200182810382526021815260200180611e996021913960400191505060405180910390fd5b806001600160a01b03166106e3610fb3565b6001600160a01b031614806107045750610704816106ff610fb3565b610f69565b61073f5760405162461bcd60e51b8152600401808060200182810382526038815260200180611d3a6038913960400191505060405180910390fd5b6107498383610fb7565b505050565b600061075a6002611032565b905090565b600a54610100900460ff1680610778575061077861103d565b806107865750600a5460ff16155b6107c15760405162461bcd60e51b815260040180806020018281038252602e815260200180611dc5602e913960400191505060405180910390fd5b600a54610100900460ff161580156107ec57600a805460ff1961ff0019909116610100171660011790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610869576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166108c4576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600c805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905580156108fe57600a805461ff00191690555b5050565b61091361090d610fb3565b8261104e565b61094e5760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b6107498383836110f2565b6001600160a01b038216600090815260016020526040812061097b908361123e565b90505b92915050565b61074983838360405180602001604052806000815250610c8a565b6000806109ad60028461124a565b509392505050565b600c546000906001600160a01b03163314610a17576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b50600b8054600181019091556105768282611266565b600b5481565b600061097e82604051806060016040528060298152602001611d9c6029913960029190611280565b60098054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b60006001600160a01b038216610b035760405162461bcd60e51b815260040180806020018281038252602a815260200180611d72602a913960400191505060405180910390fd5b6001600160a01b038216600090815260016020526040902061097e90611032565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b610b8d610fb3565b6001600160a01b0316826001600160a01b03161415610bf3576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060056000610c00610fb3565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155610c44610fb3565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b610c9b610c95610fb3565b8361104e565b610cd65760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b610ce284848484611297565b50505050565b6060610cf382610fa6565b610d2e5760405162461bcd60e51b815260040180806020018281038252602f815260200180611e6a602f913960400191505060405180910390fd5b60008281526008602090815260408083208054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015610dc15780601f10610d9657610100808354040283529160200191610dc1565b820191906000526020600020905b815481529060010190602001808311610da457829003601f168201915b505050505090506000610dd2610a5b565b9050805160001415610de657509050610576565b815115610ea75780826040516020018083805190602001908083835b60208310610e215780518252601f199092019160209182019101610e02565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610e695780518252601f199092019160209182019101610e4a565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050610576565b80610eb1856112e9565b6040516020018083805190602001908083835b60208310610ee35780518252601f199092019160209182019101610ec4565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610f2b5780518252601f199092019160209182019101610f0c565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050919050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b600c546001600160a01b031681565b600061097e6002836113dc565b3390565b6000818152600460205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091558190610ff982610a33565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061097e826113e8565b6000611048306113ec565b15905090565b600061105982610fa6565b6110945760405162461bcd60e51b815260040180806020018281038252602c815260200180611d0e602c913960400191505060405180910390fd5b600061109f83610a33565b9050806001600160a01b0316846001600160a01b031614806110da5750836001600160a01b03166110cf84610611565b6001600160a01b0316145b806110ea57506110ea8185610f69565b949350505050565b826001600160a01b031661110582610a33565b6001600160a01b03161461114a5760405162461bcd60e51b8152600401808060200182810382526029815260200180611e416029913960400191505060405180910390fd5b6001600160a01b03821661118f5760405162461bcd60e51b8152600401808060200182810382526024815260200180611cea6024913960400191505060405180910390fd5b61119a8383836113f2565b6111a5600082610fb7565b6001600160a01b03831660009081526001602052604090206111c79082611462565b506001600160a01b03821660009081526001602052604090206111ea908261146e565b506111f76002828461147a565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061097b8383611490565b600080808061125986866114f4565b9097909650945050505050565b6108fe82826040518060200160405280600081525061156f565b600061128d8484846115c1565b90505b9392505050565b6112a28484846110f2565b6112ae8484848461168b565b610ce25760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b60608161130e57506040805180820190915260018152600360fc1b6020820152610576565b8160005b811561132657600101600a82049150611312565b60008167ffffffffffffffff8111801561133f57600080fd5b506040519080825280601f01601f19166020018201604052801561136a576020820181803683370190505b50859350905060001982015b83156113d357600a840660300160f81b8282806001900393508151811061139957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84049350611376565b50949350505050565b600061097b838361181d565b5490565b3b151590565b600c546040805163c65a391d60e01b81526004810184905260006024820181905291516001600160a01b039093169263c65a391d9260448084019391929182900301818387803b15801561144557600080fd5b505af1158015611459573d6000803e3d6000fd5b50505050505050565b600061097b8383611835565b600061097b83836118fb565b600061128d84846001600160a01b038516611945565b815460009082106114d25760405162461bcd60e51b8152600401808060200182810382526022815260200180611c966022913960400191505060405180910390fd5b8260000182815481106114e157fe5b9060005260206000200154905092915050565b8154600090819083106115385760405162461bcd60e51b8152600401808060200182810382526022815260200180611df36022913960400191505060405180910390fd5b600084600001848154811061154957fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b61157983836119dc565b611586600084848461168b565b6107495760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b6000828152600184016020526040812054828161165c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611621578181015183820152602001611609565b50505050905090810190601f16801561164e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5084600001600182038154811061166f57fe5b9060005260206000209060020201600101549150509392505050565b600061169f846001600160a01b03166113ec565b6116ab575060016110ea565b60006117e3630a85bd0160e11b6116c0610fb3565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561172757818101518382015260200161170f565b50505050905090810190601f1680156117545780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001611cb8603291396001600160a01b0388169190611b0a565b905060008180602001905160208110156117fc57600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b600081815260018301602052604081205480156118f1578354600019808301919081019060009087908390811061186857fe5b906000526020600020015490508087600001848154811061188557fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806118b557fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061097e565b600091505061097e565b6000611907838361181d565b61193d5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561097e565b50600061097e565b6000828152600184016020526040812054806119aa575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611290565b828560000160018303815481106119bd57fe5b9060005260206000209060020201600101819055506000915050611290565b6001600160a01b038216611a37576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b611a4081610fa6565b15611a92576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b611a9e600083836113f2565b6001600160a01b0382166000908152600160205260409020611ac0908261146e565b50611acd6002828461147a565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b606061128d848460008585611b1e856113ec565b611b6f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310611bad5780518252601f199092019160209182019101611b8e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611c0f576040519150601f19603f3d011682016040523d82523d6000602084013e611c14565b606091505b5091509150611c24828286611c2f565b979650505050505050565b60608315611c3e575081611290565b825115611c4e5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561162157818101518382015260200161160956fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a2646970667358221220d3f1a23837994f40417509b4bc6ecf5c3e0a993c2a5fa9467490d40d7655c57964736f6c63430007060033\",\n  \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101775760003560e01c806354ba0f27116100d857806395d89b411161008c578063c87b56dd11610066578063c87b56dd14610505578063e985e9c514610522578063f77c47911461055057610177565b806395d89b4114610409578063a22cb46514610411578063b88d4fde1461043f57610177565b80636352211e116100bd5780636352211e146103be5780636c0360eb146103db57806370a08231146103e357610177565b806354ba0f271461039057806361b8ce8c146103b657610177565b806319ab453c1161012f5780632f745c59116101145780632f745c591461031157806342842e0e1461033d5780634f6ccce71461037357610177565b806319ab453c146102b557806323b872dd146102db57610177565b8063081812fc11610160578063081812fc14610234578063095ea7b31461026d57806318160ddd1461029b57610177565b806301ffc9a71461017c57806306fdde03146101b7575b600080fd5b6101a36004803603602081101561019257600080fd5b50356001600160e01b031916610558565b604080519115158252519081900360200190f35b6101bf61057b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f95781810151838201526020016101e1565b50505050905090810190601f1680156102265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102516004803603602081101561024a57600080fd5b5035610611565b604080516001600160a01b039092168252519081900360200190f35b6102996004803603604081101561028357600080fd5b506001600160a01b038135169060200135610673565b005b6102a361074e565b60408051918252519081900360200190f35b610299600480360360208110156102cb57600080fd5b50356001600160a01b031661075f565b610299600480360360608110156102f157600080fd5b506001600160a01b03813581169160208101359091169060400135610902565b6102a36004803603604081101561032757600080fd5b506001600160a01b038135169060200135610959565b6102996004803603606081101561035357600080fd5b506001600160a01b03813581169160208101359091169060400135610984565b6102a36004803603602081101561038957600080fd5b503561099f565b6102a3600480360360208110156103a657600080fd5b50356001600160a01b03166109b5565b6102a3610a2d565b610251600480360360208110156103d457600080fd5b5035610a33565b6101bf610a5b565b6102a3600480360360208110156103f957600080fd5b50356001600160a01b0316610abc565b6101bf610b24565b6102996004803603604081101561042757600080fd5b506001600160a01b0381351690602001351515610b85565b6102996004803603608081101561045557600080fd5b6001600160a01b0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561049057600080fd5b8201836020820111156104a257600080fd5b803590602001918460018302840111640100000000831117156104c457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610c8a945050505050565b6101bf6004803603602081101561051b57600080fd5b5035610ce8565b6101a36004803603604081101561053857600080fd5b506001600160a01b0381358116916020013516610f69565b610251610f97565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b820191906000526020600020905b8154815290600101906020018083116105ea57829003601f168201915b5050505050905090565b600061061c82610fa6565b6106575760405162461bcd60e51b815260040180806020018281038252602c815260200180611e15602c913960400191505060405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061067e82610a33565b9050806001600160a01b0316836001600160a01b031614156106d15760405162461bcd60e51b8152600401808060200182810382526021815260200180611e996021913960400191505060405180910390fd5b806001600160a01b03166106e3610fb3565b6001600160a01b031614806107045750610704816106ff610fb3565b610f69565b61073f5760405162461bcd60e51b8152600401808060200182810382526038815260200180611d3a6038913960400191505060405180910390fd5b6107498383610fb7565b505050565b600061075a6002611032565b905090565b600a54610100900460ff1680610778575061077861103d565b806107865750600a5460ff16155b6107c15760405162461bcd60e51b815260040180806020018281038252602e815260200180611dc5602e913960400191505060405180910390fd5b600a54610100900460ff161580156107ec57600a805460ff1961ff0019909116610100171660011790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610869576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166108c4576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600c805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905580156108fe57600a805461ff00191690555b5050565b61091361090d610fb3565b8261104e565b61094e5760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b6107498383836110f2565b6001600160a01b038216600090815260016020526040812061097b908361123e565b90505b92915050565b61074983838360405180602001604052806000815250610c8a565b6000806109ad60028461124a565b509392505050565b600c546000906001600160a01b03163314610a17576040805162461bcd60e51b815260206004820152600e60248201527f4e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b50600b8054600181019091556105768282611266565b600b5481565b600061097e82604051806060016040528060298152602001611d9c6029913960029190611280565b60098054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b60006001600160a01b038216610b035760405162461bcd60e51b815260040180806020018281038252602a815260200180611d72602a913960400191505060405180910390fd5b6001600160a01b038216600090815260016020526040902061097e90611032565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106075780601f106105dc57610100808354040283529160200191610607565b610b8d610fb3565b6001600160a01b0316826001600160a01b03161415610bf3576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060056000610c00610fb3565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155610c44610fb3565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b610c9b610c95610fb3565b8361104e565b610cd65760405162461bcd60e51b8152600401808060200182810382526031815260200180611eba6031913960400191505060405180910390fd5b610ce284848484611297565b50505050565b6060610cf382610fa6565b610d2e5760405162461bcd60e51b815260040180806020018281038252602f815260200180611e6a602f913960400191505060405180910390fd5b60008281526008602090815260408083208054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015610dc15780601f10610d9657610100808354040283529160200191610dc1565b820191906000526020600020905b815481529060010190602001808311610da457829003601f168201915b505050505090506000610dd2610a5b565b9050805160001415610de657509050610576565b815115610ea75780826040516020018083805190602001908083835b60208310610e215780518252601f199092019160209182019101610e02565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610e695780518252601f199092019160209182019101610e4a565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050610576565b80610eb1856112e9565b6040516020018083805190602001908083835b60208310610ee35780518252601f199092019160209182019101610ec4565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310610f2b5780518252601f199092019160209182019101610f0c565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050919050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b600c546001600160a01b031681565b600061097e6002836113dc565b3390565b6000818152600460205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091558190610ff982610a33565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061097e826113e8565b6000611048306113ec565b15905090565b600061105982610fa6565b6110945760405162461bcd60e51b815260040180806020018281038252602c815260200180611d0e602c913960400191505060405180910390fd5b600061109f83610a33565b9050806001600160a01b0316846001600160a01b031614806110da5750836001600160a01b03166110cf84610611565b6001600160a01b0316145b806110ea57506110ea8185610f69565b949350505050565b826001600160a01b031661110582610a33565b6001600160a01b03161461114a5760405162461bcd60e51b8152600401808060200182810382526029815260200180611e416029913960400191505060405180910390fd5b6001600160a01b03821661118f5760405162461bcd60e51b8152600401808060200182810382526024815260200180611cea6024913960400191505060405180910390fd5b61119a8383836113f2565b6111a5600082610fb7565b6001600160a01b03831660009081526001602052604090206111c79082611462565b506001600160a01b03821660009081526001602052604090206111ea908261146e565b506111f76002828461147a565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061097b8383611490565b600080808061125986866114f4565b9097909650945050505050565b6108fe82826040518060200160405280600081525061156f565b600061128d8484846115c1565b90505b9392505050565b6112a28484846110f2565b6112ae8484848461168b565b610ce25760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b60608161130e57506040805180820190915260018152600360fc1b6020820152610576565b8160005b811561132657600101600a82049150611312565b60008167ffffffffffffffff8111801561133f57600080fd5b506040519080825280601f01601f19166020018201604052801561136a576020820181803683370190505b50859350905060001982015b83156113d357600a840660300160f81b8282806001900393508151811061139957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84049350611376565b50949350505050565b600061097b838361181d565b5490565b3b151590565b600c546040805163c65a391d60e01b81526004810184905260006024820181905291516001600160a01b039093169263c65a391d9260448084019391929182900301818387803b15801561144557600080fd5b505af1158015611459573d6000803e3d6000fd5b50505050505050565b600061097b8383611835565b600061097b83836118fb565b600061128d84846001600160a01b038516611945565b815460009082106114d25760405162461bcd60e51b8152600401808060200182810382526022815260200180611c966022913960400191505060405180910390fd5b8260000182815481106114e157fe5b9060005260206000200154905092915050565b8154600090819083106115385760405162461bcd60e51b8152600401808060200182810382526022815260200180611df36022913960400191505060405180910390fd5b600084600001848154811061154957fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b61157983836119dc565b611586600084848461168b565b6107495760405162461bcd60e51b8152600401808060200182810382526032815260200180611cb86032913960400191505060405180910390fd5b6000828152600184016020526040812054828161165c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611621578181015183820152602001611609565b50505050905090810190601f16801561164e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5084600001600182038154811061166f57fe5b9060005260206000209060020201600101549150509392505050565b600061169f846001600160a01b03166113ec565b6116ab575060016110ea565b60006117e3630a85bd0160e11b6116c0610fb3565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561172757818101518382015260200161170f565b50505050905090810190601f1680156117545780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001611cb8603291396001600160a01b0388169190611b0a565b905060008180602001905160208110156117fc57600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b600081815260018301602052604081205480156118f1578354600019808301919081019060009087908390811061186857fe5b906000526020600020015490508087600001848154811061188557fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806118b557fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061097e565b600091505061097e565b6000611907838361181d565b61193d5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561097e565b50600061097e565b6000828152600184016020526040812054806119aa575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611290565b828560000160018303815481106119bd57fe5b9060005260206000209060020201600101819055506000915050611290565b6001600160a01b038216611a37576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b611a4081610fa6565b15611a92576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b611a9e600083836113f2565b6001600160a01b0382166000908152600160205260409020611ac0908261146e565b50611acd6002828461147a565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b606061128d848460008585611b1e856113ec565b611b6f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310611bad5780518252601f199092019160209182019101611b8e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611c0f576040519150601f19603f3d011682016040523d82523d6000602084013e611c14565b606091505b5091509150611c24828286611c2f565b979650505050505050565b60608315611c3e575081611290565b825115611c4e5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561162157818101518382015260200161160956fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a2646970667358221220d3f1a23837994f40417509b4bc6ecf5c3e0a993c2a5fa9467490d40d7655c57964736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC721-approve}.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC721-balanceOf}.\"\n      },\n      \"baseURI()\": {\n        \"details\": \"Returns the base URI set via {_setBaseURI}. This will be automatically added as a prefix in {tokenURI} to each token's URI, or to the token ID if no specific URI is set for that token ID.\"\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_name\": \"token name for ERC721\",\n          \"_symbol\": \"token symbol for ERC721\"\n        }\n      },\n      \"getApproved(uint256)\": {\n        \"details\": \"See {IERC721-getApproved}.\"\n      },\n      \"init(address)\": {\n        \"params\": {\n          \"_controller\": \"controller address\"\n        }\n      },\n      \"isApprovedForAll(address,address)\": {\n        \"details\": \"See {IERC721-isApprovedForAll}.\"\n      },\n      \"mintNFT(address)\": {\n        \"details\": \"autoincrement tokenId starts at 1\",\n        \"params\": {\n          \"_recipient\": \"recipient address for NFT\"\n        }\n      },\n      \"name()\": {\n        \"details\": \"See {IERC721Metadata-name}.\"\n      },\n      \"ownerOf(uint256)\": {\n        \"details\": \"See {IERC721-ownerOf}.\"\n      },\n      \"safeTransferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC721-safeTransferFrom}.\"\n      },\n      \"safeTransferFrom(address,address,uint256,bytes)\": {\n        \"details\": \"See {IERC721-safeTransferFrom}.\"\n      },\n      \"setApprovalForAll(address,bool)\": {\n        \"details\": \"See {IERC721-setApprovalForAll}.\"\n      },\n      \"supportsInterface(bytes4)\": {\n        \"details\": \"See {IERC165-supportsInterface}. Time complexity O(1), guaranteed to always use less than 30 000 gas.\"\n      },\n      \"symbol()\": {\n        \"details\": \"See {IERC721Metadata-symbol}.\"\n      },\n      \"tokenByIndex(uint256)\": {\n        \"details\": \"See {IERC721Enumerable-tokenByIndex}.\"\n      },\n      \"tokenOfOwnerByIndex(address,uint256)\": {\n        \"details\": \"See {IERC721Enumerable-tokenOfOwnerByIndex}.\"\n      },\n      \"tokenURI(uint256)\": {\n        \"details\": \"See {IERC721Metadata-tokenURI}.\"\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC721Enumerable-totalSupply}.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC721-transferFrom}.\"\n      }\n    },\n    \"stateVariables\": {\n      \"nextId\": {\n        \"details\": \"tokenId for the next vault opened\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"constructor\": {\n        \"notice\": \"short power perpetual constructor\"\n      },\n      \"init(address)\": {\n        \"notice\": \"initialize short contract\"\n      },\n      \"mintNFT(address)\": {\n        \"notice\": \"mint new NFT\"\n      }\n    },\n    \"notice\": \"ERC721 NFT representing ownership of a vault (short position)\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 123,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_supportedInterfaces\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_bytes4,t_bool)\"\n      },\n      {\n        \"astId\": 1226,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_holderTokens\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_struct(UintSet)3592_storage)\"\n      },\n      {\n        \"astId\": 1228,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_tokenOwners\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_struct(UintToAddressMap)2969_storage\"\n      },\n      {\n        \"astId\": 1232,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_tokenApprovals\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_mapping(t_uint256,t_address)\"\n      },\n      {\n        \"astId\": 1238,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_operatorApprovals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_bool))\"\n      },\n      {\n        \"astId\": 1240,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"6\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 1242,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"7\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 1246,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_tokenURIs\",\n        \"offset\": 0,\n        \"slot\": \"8\",\n        \"type\": \"t_mapping(t_uint256,t_string_storage)\"\n      },\n      {\n        \"astId\": 1248,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_baseURI\",\n        \"offset\": 0,\n        \"slot\": \"9\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 540,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_initialized\",\n        \"offset\": 0,\n        \"slot\": \"10\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 543,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"_initializing\",\n        \"offset\": 1,\n        \"slot\": \"10\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 10465,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"nextId\",\n        \"offset\": 0,\n        \"slot\": \"11\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 10467,\n        \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n        \"label\": \"controller\",\n        \"offset\": 0,\n        \"slot\": \"12\",\n        \"type\": \"t_address\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_array(t_bytes32)dyn_storage\": {\n        \"base\": \"t_bytes32\",\n        \"encoding\": \"dynamic_array\",\n        \"label\": \"bytes32[]\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_array(t_struct(MapEntry)2643_storage)dyn_storage\": {\n        \"base\": \"t_struct(MapEntry)2643_storage\",\n        \"encoding\": \"dynamic_array\",\n        \"label\": \"struct EnumerableMap.MapEntry[]\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_bytes32\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bytes32\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_bytes4\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bytes4\",\n        \"numberOfBytes\": \"4\"\n      },\n      \"t_mapping(t_address,t_bool)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => bool)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_bool\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_bool))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => bool))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_bool)\"\n      },\n      \"t_mapping(t_address,t_struct(UintSet)3592_storage)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => struct EnumerableSet.UintSet)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_struct(UintSet)3592_storage\"\n      },\n      \"t_mapping(t_bytes32,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_bytes32\",\n        \"label\": \"mapping(bytes32 => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_mapping(t_bytes4,t_bool)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_bytes4\",\n        \"label\": \"mapping(bytes4 => bool)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_bool\"\n      },\n      \"t_mapping(t_uint256,t_address)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => address)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_address\"\n      },\n      \"t_mapping(t_uint256,t_string_storage)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_uint256\",\n        \"label\": \"mapping(uint256 => string)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_string_storage\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_struct(Map)2651_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableMap.Map\",\n        \"members\": [\n          {\n            \"astId\": 2646,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_entries\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_array(t_struct(MapEntry)2643_storage)dyn_storage\"\n          },\n          {\n            \"astId\": 2650,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_indexes\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_mapping(t_bytes32,t_uint256)\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(MapEntry)2643_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableMap.MapEntry\",\n        \"members\": [\n          {\n            \"astId\": 2640,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_key\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_bytes32\"\n          },\n          {\n            \"astId\": 2642,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_value\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_bytes32\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(Set)3206_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableSet.Set\",\n        \"members\": [\n          {\n            \"astId\": 3201,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_values\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_array(t_bytes32)dyn_storage\"\n          },\n          {\n            \"astId\": 3205,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_indexes\",\n            \"offset\": 0,\n            \"slot\": \"1\",\n            \"type\": \"t_mapping(t_bytes32,t_uint256)\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(UintSet)3592_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableSet.UintSet\",\n        \"members\": [\n          {\n            \"astId\": 3591,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_inner\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_struct(Set)3206_storage\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_struct(UintToAddressMap)2969_storage\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"struct EnumerableMap.UintToAddressMap\",\n        \"members\": [\n          {\n            \"astId\": 2968,\n            \"contract\": \"contracts/core/ShortPowerPerp.sol:ShortPowerPerp\",\n            \"label\": \"_inner\",\n            \"offset\": 0,\n            \"slot\": \"0\",\n            \"type\": \"t_struct(Map)2651_storage\"\n          }\n        ],\n        \"numberOfBytes\": \"64\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/SqrtPriceMathPartial.json",
    "content": "{\n  \"address\": \"0x565483126A5fC6004455F4e11014C442A61D740c\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioAX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioBX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"roundUp\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getAmount0Delta\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount0\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioAX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtRatioBX96\",\n          \"type\": \"uint160\"\n        },\n        {\n          \"internalType\": \"uint128\",\n          \"name\": \"liquidity\",\n          \"type\": \"uint128\"\n        },\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"roundUp\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"name\": \"getAmount1Delta\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount1\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x8d568f9d19f3b7aa6356244e87a3688008f54525359448d94e0429d52e24e7a9\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0x565483126A5fC6004455F4e11014C442A61D740c\",\n    \"transactionIndex\": 8,\n    \"gasUsed\": \"245472\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x18333a696dad5e7147d9f7be84c896aa74bfa831e406f8a34daa5f5f60603a54\",\n    \"transactionHash\": \"0x8d568f9d19f3b7aa6356244e87a3688008f54525359448d94e0429d52e24e7a9\",\n    \"logs\": [],\n    \"blockNumber\": 12325018,\n    \"cumulativeGasUsed\": \"6622810\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"d91027c30078be5bfba0223abd5c6e60\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioAX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioBX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"roundUp\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getAmount0Delta\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount0\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioAX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtRatioBX96\\\",\\\"type\\\":\\\"uint160\\\"},{\\\"internalType\\\":\\\"uint128\\\",\\\"name\\\":\\\"liquidity\\\",\\\"type\\\":\\\"uint128\\\"},{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"roundUp\\\",\\\"type\\\":\\\"bool\\\"}],\\\"name\\\":\\\"getAmount1Delta\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount1\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"getAmount0Delta(uint160,uint160,uint128,bool)\\\":{\\\"details\\\":\\\"Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper), i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\",\\\"params\\\":{\\\"liquidity\\\":\\\"The amount of usable liquidity\\\",\\\"roundUp\\\":\\\"Whether to round the amount up or down\\\",\\\"sqrtRatioAX96\\\":\\\"A sqrt price\\\",\\\"sqrtRatioBX96\\\":\\\"Another sqrt price\\\"},\\\"returns\\\":{\\\"amount0\\\":\\\"Amount of token0 required to cover a position of size liquidity between the two passed prices\\\"}},\\\"getAmount1Delta(uint160,uint160,uint128,bool)\\\":{\\\"details\\\":\\\"Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\",\\\"params\\\":{\\\"liquidity\\\":\\\"The amount of usable liquidity\\\",\\\"roundUp\\\":\\\"Whether to round the amount up, or down\\\",\\\"sqrtRatioAX96\\\":\\\"A sqrt price\\\",\\\"sqrtRatioBX96\\\":\\\"Another sqrt price\\\"},\\\"returns\\\":{\\\"amount1\\\":\\\"Amount of token1 required to cover a position of size liquidity between the two passed prices\\\"}}},\\\"title\\\":\\\"Functions based on Q64.96 sqrt price and liquidity\\\",\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"getAmount0Delta(uint160,uint160,uint128,bool)\\\":{\\\"notice\\\":\\\"Gets the amount0 delta between two prices\\\"},\\\"getAmount1Delta(uint160,uint160,uint128,bool)\\\":{\\\"notice\\\":\\\"Gets the amount1 delta between two prices\\\"}},\\\"notice\\\":\\\"Exposes two functions from @uniswap/v3-core SqrtPriceMath that use square root of price as a Q64.96 and liquidity to compute deltas\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":\\\"SqrtPriceMathPartial\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title FixedPoint96\\\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\\\n/// @dev Used in SqrtPriceMath.sol\\\\nlibrary FixedPoint96 {\\\\n    uint8 internal constant RESOLUTION = 96;\\\\n    uint256 internal constant Q96 = 0x1000000000000000000000000;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"},\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\npragma solidity >=0.4.0;\\\\n\\\\n/// @title Contains 512-bit math functions\\\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\\\n/// @dev Handles \\\\\\\"phantom overflow\\\\\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\\\nlibrary FullMath {\\\\n    /// @notice Calculates floor(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\\\n    function mulDiv(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        // 512-bit multiply [prod1 prod0] = a * b\\\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\\\n        // then use the Chinese Remainder Theorem to reconstruct\\\\n        // the 512 bit result. The result is stored in two 256\\\\n        // variables such that product = prod1 * 2**256 + prod0\\\\n        uint256 prod0; // Least significant 256 bits of the product\\\\n        uint256 prod1; // Most significant 256 bits of the product\\\\n        assembly {\\\\n            let mm := mulmod(a, b, not(0))\\\\n            prod0 := mul(a, b)\\\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\\\n        }\\\\n\\\\n        // Handle non-overflow cases, 256 by 256 division\\\\n        if (prod1 == 0) {\\\\n            require(denominator > 0);\\\\n            assembly {\\\\n                result := div(prod0, denominator)\\\\n            }\\\\n            return result;\\\\n        }\\\\n\\\\n        // Make sure the result is less than 2**256.\\\\n        // Also prevents denominator == 0\\\\n        require(denominator > prod1);\\\\n\\\\n        ///////////////////////////////////////////////\\\\n        // 512 by 256 division.\\\\n        ///////////////////////////////////////////////\\\\n\\\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\\\n        // Compute remainder using mulmod\\\\n        uint256 remainder;\\\\n        assembly {\\\\n            remainder := mulmod(a, b, denominator)\\\\n        }\\\\n        // Subtract 256 bit number from 512 bit number\\\\n        assembly {\\\\n            prod1 := sub(prod1, gt(remainder, prod0))\\\\n            prod0 := sub(prod0, remainder)\\\\n        }\\\\n\\\\n        // Factor powers of two out of denominator\\\\n        // Compute largest power of two divisor of denominator.\\\\n        // Always >= 1.\\\\n        uint256 twos = -denominator & denominator;\\\\n        // Divide denominator by power of two\\\\n        assembly {\\\\n            denominator := div(denominator, twos)\\\\n        }\\\\n\\\\n        // Divide [prod1 prod0] by the factors of two\\\\n        assembly {\\\\n            prod0 := div(prod0, twos)\\\\n        }\\\\n        // Shift in bits from prod1 into prod0. For this we need\\\\n        // to flip `twos` such that it is 2**256 / twos.\\\\n        // If twos is zero, then it becomes one\\\\n        assembly {\\\\n            twos := add(div(sub(0, twos), twos), 1)\\\\n        }\\\\n        prod0 |= prod1 * twos;\\\\n\\\\n        // Invert denominator mod 2**256\\\\n        // Now that denominator is an odd number, it has an inverse\\\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\\\n        // Compute the inverse by starting with a seed that is correct\\\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\\\n        uint256 inv = (3 * denominator) ^ 2;\\\\n        // Now use Newton-Raphson iteration to improve the precision.\\\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\\\n        // arithmetic, doubling the correct bits in each step.\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\\\n\\\\n        // Because the division is now exact we can divide by multiplying\\\\n        // with the modular inverse of denominator. This will give us the\\\\n        // correct result modulo 2**256. Since the precoditions guarantee\\\\n        // that the outcome is less than 2**256, this is the final result.\\\\n        // We don't need to compute the high bits of the result and prod1\\\\n        // is no longer required.\\\\n        result = prod0 * inv;\\\\n        return result;\\\\n    }\\\\n\\\\n    /// @notice Calculates ceil(a\\\\u00d7b\\\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\\\n    /// @param a The multiplicand\\\\n    /// @param b The multiplier\\\\n    /// @param denominator The divisor\\\\n    /// @return result The 256-bit result\\\\n    function mulDivRoundingUp(\\\\n        uint256 a,\\\\n        uint256 b,\\\\n        uint256 denominator\\\\n    ) internal pure returns (uint256 result) {\\\\n        result = mulDiv(a, b, denominator);\\\\n        if (mulmod(a, b, denominator) > 0) {\\\\n            require(result < type(uint256).max);\\\\n            result++;\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe511530871deaef86692cea9adb6076d26d7b47fd4815ce51af52af981026057\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@uniswap/v3-core/contracts/libraries/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\\\"},\\\"contracts/libs/SqrtPriceMathPartial.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\\\\\";\\\\nimport \\\\\\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\\\\\";\\\\n\\\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\\\nlibrary SqrtPriceMathPartial {\\\\n    /// @notice Gets the amount0 delta between two prices\\\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up or down\\\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount0Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount0) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\\\n\\\\n        require(sqrtRatioAX96 > 0);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? UnsafeMath.divRoundingUp(\\\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\\\n                    sqrtRatioAX96\\\\n                )\\\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\\\n    }\\\\n\\\\n    /// @notice Gets the amount1 delta between two prices\\\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\\\n    /// @param sqrtRatioAX96 A sqrt price\\\\n    /// @param sqrtRatioBX96 Another sqrt price\\\\n    /// @param liquidity The amount of usable liquidity\\\\n    /// @param roundUp Whether to round the amount up, or down\\\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\\\n    function getAmount1Delta(\\\\n        uint160 sqrtRatioAX96,\\\\n        uint160 sqrtRatioBX96,\\\\n        uint128 liquidity,\\\\n        bool roundUp\\\\n    ) external pure returns (uint256 amount1) {\\\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\\\n\\\\n        return\\\\n            roundUp\\\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x34b98f373514d057151a41d35aa42031af3b1a47e910888ed73315f72520e429\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x61037c610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80632c32d4b61461004557806348a0c5bd146100a7575b600080fd5b6100956004803603608081101561005b57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156100f7565b60408051918252519081900360200190f35b610095600480360360808110156100bd57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156101b4565b6000836001600160a01b0316856001600160a01b03161115610117579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661015357600080fd5b8361018357866001600160a01b03166101768383896001600160a01b0316610251565b8161017d57fe5b046101a9565b6101a961019a8383896001600160a01b0316610301565b886001600160a01b031661033b565b979650505050505050565b6000836001600160a01b0316856001600160a01b031611156101d4579293925b816102135761020e836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610251565b610248565b610248836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610301565b95945050505050565b6000808060001985870986860292508281109083900303905080610287576000841161027c57600080fd5b5082900490506102fa565b80841161029357600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b600061030e848484610251565b90506000828061031a57fe5b84860911156102fa57600019811061033157600080fd5b6001019392505050565b80820491061515019056fea264697066735822122015b1d5e98e518aedb03f0724756a56b09b753efd09a45ae663413fd3cad16d6d64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80632c32d4b61461004557806348a0c5bd146100a7575b600080fd5b6100956004803603608081101561005b57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156100f7565b60408051918252519081900360200190f35b610095600480360360808110156100bd57600080fd5b506001600160a01b0381358116916020810135909116906fffffffffffffffffffffffffffffffff604082013516906060013515156101b4565b6000836001600160a01b0316856001600160a01b03161115610117579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661015357600080fd5b8361018357866001600160a01b03166101768383896001600160a01b0316610251565b8161017d57fe5b046101a9565b6101a961019a8383896001600160a01b0316610301565b886001600160a01b031661033b565b979650505050505050565b6000836001600160a01b0316856001600160a01b031611156101d4579293925b816102135761020e836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610251565b610248565b610248836fffffffffffffffffffffffffffffffff168686036001600160a01b03166c01000000000000000000000000610301565b95945050505050565b6000808060001985870986860292508281109083900303905080610287576000841161027c57600080fd5b5082900490506102fa565b80841161029357600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b600061030e848484610251565b90506000828061031a57fe5b84860911156102fa57600019811061033157600080fd5b6001019392505050565b80820491061515019056fea264697066735822122015b1d5e98e518aedb03f0724756a56b09b753efd09a45ae663413fd3cad16d6d64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"getAmount0Delta(uint160,uint160,uint128,bool)\": {\n        \"details\": \"Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper), i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\",\n        \"params\": {\n          \"liquidity\": \"The amount of usable liquidity\",\n          \"roundUp\": \"Whether to round the amount up or down\",\n          \"sqrtRatioAX96\": \"A sqrt price\",\n          \"sqrtRatioBX96\": \"Another sqrt price\"\n        },\n        \"returns\": {\n          \"amount0\": \"Amount of token0 required to cover a position of size liquidity between the two passed prices\"\n        }\n      },\n      \"getAmount1Delta(uint160,uint160,uint128,bool)\": {\n        \"details\": \"Calculates liquidity * (sqrt(upper) - sqrt(lower))\",\n        \"params\": {\n          \"liquidity\": \"The amount of usable liquidity\",\n          \"roundUp\": \"Whether to round the amount up, or down\",\n          \"sqrtRatioAX96\": \"A sqrt price\",\n          \"sqrtRatioBX96\": \"Another sqrt price\"\n        },\n        \"returns\": {\n          \"amount1\": \"Amount of token1 required to cover a position of size liquidity between the two passed prices\"\n        }\n      }\n    },\n    \"title\": \"Functions based on Q64.96 sqrt price and liquidity\",\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"getAmount0Delta(uint160,uint160,uint128,bool)\": {\n        \"notice\": \"Gets the amount0 delta between two prices\"\n      },\n      \"getAmount1Delta(uint160,uint160,uint128,bool)\": {\n        \"notice\": \"Gets the amount1 delta between two prices\"\n      }\n    },\n    \"notice\": \"Exposes two functions from @uniswap/v3-core SqrtPriceMath that use square root of price as a Q64.96 and liquidity to compute deltas\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/SwapRouter.json",
    "content": "{\n  \"address\": \"0x528a19A3e88861E7298C86fE5490B8Ec007a4204\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_factory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_WETH9\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"WETH9\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"bytes\",\n              \"name\": \"path\",\n              \"type\": \"bytes\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountIn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOutMinimum\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactInputParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"exactInput\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountIn\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOutMinimum\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactInputSingleParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"exactInputSingle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"bytes\",\n              \"name\": \"path\",\n              \"type\": \"bytes\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOut\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountInMaximum\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactOutputParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"exactOutput\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenIn\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"tokenOut\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint24\",\n              \"name\": \"fee\",\n              \"type\": \"uint24\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"recipient\",\n              \"type\": \"address\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"deadline\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOut\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountInMaximum\",\n              \"type\": \"uint256\"\n            },\n            {\n              \"internalType\": \"uint160\",\n              \"name\": \"sqrtPriceLimitX96\",\n              \"type\": \"uint160\"\n            }\n          ],\n          \"internalType\": \"struct ISwapRouter.ExactOutputSingleParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"exactOutputSingle\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountIn\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"factory\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes[]\",\n          \"name\": \"data\",\n          \"type\": \"bytes[]\"\n        }\n      ],\n      \"name\": \"multicall\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes[]\",\n          \"name\": \"results\",\n          \"type\": \"bytes[]\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"refundETH\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"deadline\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermit\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"nonce\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"expiry\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitAllowed\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"nonce\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"expiry\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitAllowedIfNecessary\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"deadline\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"v\",\n          \"type\": \"uint8\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"r\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"s\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"selfPermitIfNecessary\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"sweepToken\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"feeBips\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"feeRecipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"sweepTokenWithFee\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount0Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"int256\",\n          \"name\": \"amount1Delta\",\n          \"type\": \"int256\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"_data\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"name\": \"uniswapV3SwapCallback\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"unwrapWETH9\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountMinimum\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"feeBips\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"feeRecipient\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"unwrapWETH9WithFee\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"receive\"\n    }\n  ],\n  \"transactionHash\": \"0x5156746674281f7caf64050be1125e79ee9772ac5c6acdf1c3554122ad1a1873\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0x528a19A3e88861E7298C86fE5490B8Ec007a4204\",\n    \"transactionIndex\": 10,\n    \"gasUsed\": \"2667120\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x97f56cc9a9dd67d7c8d26a803f550c4ce1e028fc15ecb55d3c46337aaeb2d7fb\",\n    \"transactionHash\": \"0x5156746674281f7caf64050be1125e79ee9772ac5c6acdf1c3554122ad1a1873\",\n    \"logs\": [],\n    \"blockNumber\": 11342318,\n    \"cumulativeGasUsed\": \"6429773\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n    \"0xc778417e063141139fce010982780140aa0cd5ab\"\n  ],\n  \"bytecode\": \"0x60c06040526000196000553480156200001757600080fd5b506040516200302f3803806200302f8339810160408190526200003a9162000076565b6001600160601b0319606092831b8116608052911b1660a052620000ad565b80516001600160a01b03811681146200007157600080fd5b919050565b6000806040838503121562000089578182fd5b620000948362000059565b9150620000a46020840162000059565b90509250929050565b60805160601c60a05160601c612f26620001096000398061012f528061058352806106ad5280610747528061078752806108b15280611c435280611ca35280611d24525080610dc6528061140c5280611e265250612f266000f3fe6080604052600436106101125760003560e01c8063c04b8d59116100a5578063df2ab5bb11610074578063f28c049811610059578063f28c0498146102f5578063f3995c6714610308578063fa461e331461031b576101bd565b8063df2ab5bb146102cf578063e0e189a0146102e2576101bd565b8063c04b8d5914610281578063c2e3140a14610294578063c45a0155146102a7578063db3e2198146102bc576101bd565b80634aa4a4fc116100e15780634aa4a4fc146102195780639b2c0a371461023b578063a4a78f0c1461024e578063ac9650d814610261576101bd565b806312210e8a146101c2578063414bf389146101ca5780634659a494146101f357806349404b7c14610206576101bd565b366101bd573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146101bb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4e6f742057455448390000000000000000000000000000000000000000000000604482015290519081900360640190fd5b005b600080fd5b6101bb61033b565b6101dd6101d83660046129f8565b61034d565b6040516101ea9190612df1565b60405180910390f35b6101bb610201366004612776565b6104bf565b6101bb610214366004612aff565b61057f565b34801561022557600080fd5b5061022e610745565b6040516101ea9190612c37565b6101bb610249366004612b2e565b610769565b6101bb61025c366004612776565b610981565b61027461026f3660046127d6565b610a56565b6040516101ea9190612caa565b6101dd61028f36600461294d565b610bb0565b6101bb6102a2366004612776565b610d0f565b3480156102b357600080fd5b5061022e610dc4565b6101dd6102ca3660046129f8565b610de8565b6101bb6102dd3660046126d7565b610f78565b6101bb6102f0366004612718565b611095565b6101dd610303366004612a14565b6111fb565b6101bb610316366004612776565b61132f565b34801561032757600080fd5b506101bb610336366004612868565b6113c7565b471561034b5761034b334761150e565b565b600081608001358061035d61165c565b11156103ca57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b61047060a08401356103e260808601606087016126b4565b6103f3610100870160e088016126b4565b604080518082019091528061040b60208a018a6126b4565b61041b60608b0160408c01612adc565b61042b60408c0160208d016126b4565b60405160200161043d93929190612bc1565b60405160208183030381529060405281526020013373ffffffffffffffffffffffffffffffffffffffff16815250611660565b91508260c001358210156104b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b090612d72565b60405180910390fd5b50919050565b604080517f8fcbaf0c00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101879052606481018690526001608482015260ff851660a482015260c4810184905260e48101839052905173ffffffffffffffffffffffffffffffffffffffff881691638fcbaf0c9161010480830192600092919082900301818387803b15801561055f57600080fd5b505af1158015610573573d6000803e3d6000fd5b50505050505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561060857600080fd5b505afa15801561061c573d6000803e3d6000fd5b505050506040513d602081101561063257600080fd5b50519050828110156106a557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e742057455448390000000000000000000000000000604482015290519081900360640190fd5b8015610740577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561071e57600080fd5b505af1158015610732573d6000803e3d6000fd5b50505050610740828261150e565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008211801561077a575060648211155b61078357600080fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561080c57600080fd5b505afa158015610820573d6000803e3d6000fd5b505050506040513d602081101561083657600080fd5b50519050848110156108a957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e742057455448390000000000000000000000000000604482015290519081900360640190fd5b801561097a577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561092257600080fd5b505af1158015610936573d6000803e3d6000fd5b50505050600061271061095285846117e690919063ffffffff16565b8161095957fe5b049050801561096c5761096c838261150e565b6109788582840361150e565b505b5050505050565b604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815233600482015230602482015290517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9173ffffffffffffffffffffffffffffffffffffffff89169163dd62ed3e91604480820192602092909190829003018186803b158015610a1657600080fd5b505afa158015610a2a573d6000803e3d6000fd5b505050506040513d6020811015610a4057600080fd5b50511015610978576109788686868686866104bf565b60608167ffffffffffffffff81118015610a6f57600080fd5b50604051908082528060200260200182016040528015610aa357816020015b6060815260200190600190039081610a8e5790505b50905060005b82811015610ba95760008030868685818110610ac157fe5b9050602002810190610ad39190612dfa565b604051610ae1929190612c27565b600060405180830381855af49150503d8060008114610b1c576040519150601f19603f3d011682016040523d82523d6000602084013e610b21565b606091505b509150915081610b8757604481511015610b3a57600080fd5b60048101905080806020019051810190610b5491906128e3565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b09190612d28565b80848481518110610b9457fe5b60209081029190910101525050600101610aa9565b5092915050565b6000816040015180610bc061165c565b1115610c2d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b335b6000610c3e8560000151611810565b9050610c97856060015182610c57578660200151610c59565b305b60006040518060400160405280610c738b6000015161181c565b81526020018773ffffffffffffffffffffffffffffffffffffffff16815250611660565b60608601528015610cb7578451309250610cb09061182b565b8552610cc4565b8460600151935050610cca565b50610c2f565b8360800151831015610d08576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b090612d72565b5050919050565b604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523360048201523060248201529051869173ffffffffffffffffffffffffffffffffffffffff89169163dd62ed3e91604480820192602092909190829003018186803b158015610d8457600080fd5b505afa158015610d98573d6000803e3d6000fd5b505050506040513d6020811015610dae57600080fd5b505110156109785761097886868686868661132f565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000816080013580610df861165c565b1115610e6557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b610f0e60a0840135610e7d60808601606087016126b4565b610e8e610100870160e088016126b4565b6040518060400160405280886020016020810190610eac91906126b4565b610ebc60608b0160408c01612adc565b610ec960208c018c6126b4565b604051602001610edb93929190612bc1565b60405160208183030381529060405281526020013373ffffffffffffffffffffffffffffffffffffffff16815250611860565b91508260c00135821115610f4e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b090612d3b565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600055919050565b60008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610fe157600080fd5b505afa158015610ff5573d6000803e3d6000fd5b505050506040513d602081101561100b57600080fd5b505190508281101561107e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e7420746f6b656e0000000000000000000000000000604482015290519081900360640190fd5b801561108f5761108f848383611a1c565b50505050565b6000821180156110a6575060648211155b6110af57600080fd5b60008573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561111857600080fd5b505afa15801561112c573d6000803e3d6000fd5b505050506040513d602081101561114257600080fd5b50519050848110156111b557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e7420746f6b656e0000000000000000000000000000604482015290519081900360640190fd5b80156109785760006127106111ca83866117e6565b816111d157fe5b04905080156111e5576111e5878483611a1c565b6111f28786838503611a1c565b50505050505050565b600081604001358061120b61165c565b111561127857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b6112eb606084013561129060408601602087016126b4565b60408051808201909152600090806112a88980612dfa565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525033602090910152611860565b5060005491508260800135821115610f4e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104b090612d3b565b604080517fd505accf000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018790526064810186905260ff8516608482015260a4810184905260c48101839052905173ffffffffffffffffffffffffffffffffffffffff88169163d505accf9160e480830192600092919082900301818387803b15801561055f57600080fd5b60008413806113d65750600083135b6113df57600080fd5b60006113ed82840184612a4c565b905060008060006114018460000151611bf1565b9250925092506114337f0000000000000000000000000000000000000000000000000000000000000000848484611c22565b5060008060008a13611474578473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610896114a5565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16108a5b9150915081156114c4576114bf8587602001513384611c41565b610573565b85516114cf90611810565b156114f45785516114df9061182b565b86526114ee8133600089611860565b50610573565b806000819055508394506105738587602001513384611c41565b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040518082805190602001908083835b6020831061158557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611548565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146115e7576040519150601f19603f3d011682016040523d82523d6000602084013e6115ec565b606091505b505090508061074057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f5354450000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b4290565b600073ffffffffffffffffffffffffffffffffffffffff8416611681573093505b60008060006116938560000151611bf1565b9194509250905073ffffffffffffffffffffffffffffffffffffffff808316908416106000806116c4868686611e1f565b73ffffffffffffffffffffffffffffffffffffffff1663128acb088b856116ea8f611e5d565b73ffffffffffffffffffffffffffffffffffffffff8e161561170c578d611732565b8761172b5773fffd8963efd1fc6a506488495d951d5263988d25611732565b6401000276a45b8d6040516020016117439190612da9565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401611772959493929190612c58565b6040805180830381600087803b15801561178b57600080fd5b505af115801561179f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c39190612845565b91509150826117d257816117d4565b805b6000039b9a5050505050505050505050565b6000821580611801575050818102818382816117fe57fe5b04145b61180a57600080fd5b92915050565b8051604211155b919050565b606061180a826000602b611e8f565b805160609061180a9083906017907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901611e8f565b600073ffffffffffffffffffffffffffffffffffffffff8416611881573093505b60008060006118938560000151611bf1565b9194509250905073ffffffffffffffffffffffffffffffffffffffff808416908316106000806118c4858786611e1f565b73ffffffffffffffffffffffffffffffffffffffff1663128acb088b856118ea8f611e5d565b60000373ffffffffffffffffffffffffffffffffffffffff8e161561190f578d611935565b8761192e5773fffd8963efd1fc6a506488495d951d5263988d25611935565b6401000276a45b8d6040516020016119469190612da9565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401611975959493929190612c58565b6040805180830381600087803b15801561198e57600080fd5b505af11580156119a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c69190612845565b915091506000836119db5781836000036119e1565b82826000035b909850905073ffffffffffffffffffffffffffffffffffffffff8a16611a0d578b8114611a0d57600080fd5b50505050505050949350505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781529251825160009485949389169392918291908083835b60208310611af157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611ab4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611b53576040519150601f19603f3d011682016040523d82523d6000602084013e611b58565b606091505b5091509150818015611b86575080511580611b865750808060200190516020811015611b8357600080fd5b50515b61097a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f5354000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60008080611bff8482612076565b9250611c0c846014612176565b9050611c19846017612076565b91509193909250565b6000611c3885611c33868686612266565b6122e3565b95945050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148015611c9c5750804710155b15611de5577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d0957600080fd5b505af1158015611d1d573d6000803e3d6000fd5b50505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611db357600080fd5b505af1158015611dc7573d6000803e3d6000fd5b505050506040513d6020811015611ddd57600080fd5b5061108f9050565b73ffffffffffffffffffffffffffffffffffffffff8316301415611e1357611e0e848383611a1c565b61108f565b61108f84848484612313565b6000611e557f0000000000000000000000000000000000000000000000000000000000000000611e50868686612266565b6124f0565b949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210611e8b57600080fd5b5090565b60608182601f011015611f0357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b828284011015611f7457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b81830184511015611fe657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015290519081900360640190fd5b606082158015612005576040519150600082526020820160405261206d565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561203e578051835260209283019201612026565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6000818260140110156120ea57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b816014018351101561215d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b6000818260030110156121ea57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b816003018351101561225d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b61226e612626565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1611156122a6579192915b506040805160608101825273ffffffffffffffffffffffffffffffffffffffff948516815292909316602083015262ffffff169181019190915290565b60006122ef83836124f0565b90503373ffffffffffffffffffffffffffffffffffffffff82161461180a57600080fd5b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000178152925182516000948594938a169392918291908083835b602083106123f057805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016123b3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612452576040519150601f19603f3d011682016040523d82523d6000602084013e612457565b606091505b5091509150818015612485575080511580612485575080806020019051602081101561248257600080fd5b50515b61097857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f5354460000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000816020015173ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff161061253257600080fd5b508051602080830151604093840151845173ffffffffffffffffffffffffffffffffffffffff94851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b803561181781612ef4565b600082601f830112612661578081fd5b813561267461266f82612e88565b612e64565b818152846020838601011115612688578283fd5b816020850160208301379081016020019190915292915050565b600061010082840312156104b9578081fd5b6000602082840312156126c5578081fd5b81356126d081612ef4565b9392505050565b6000806000606084860312156126eb578182fd5b83356126f681612ef4565b925060208401359150604084013561270d81612ef4565b809150509250925092565b600080600080600060a0868803121561272f578081fd5b853561273a81612ef4565b945060208601359350604086013561275181612ef4565b925060608601359150608086013561276881612ef4565b809150509295509295909350565b60008060008060008060c0878903121561278e578081fd5b863561279981612ef4565b95506020870135945060408701359350606087013560ff811681146127bc578182fd5b9598949750929560808101359460a0909101359350915050565b600080602083850312156127e8578182fd5b823567ffffffffffffffff808211156127ff578384fd5b818501915085601f830112612812578384fd5b813581811115612820578485fd5b8660208083028501011115612833578485fd5b60209290920196919550909350505050565b60008060408385031215612857578182fd5b505080516020909101519092909150565b6000806000806060858703121561287d578182fd5b8435935060208501359250604085013567ffffffffffffffff808211156128a2578384fd5b818701915087601f8301126128b5578384fd5b8135818111156128c3578485fd5b8860208285010111156128d4578485fd5b95989497505060200194505050565b6000602082840312156128f4578081fd5b815167ffffffffffffffff81111561290a578182fd5b8201601f8101841361291a578182fd5b805161292861266f82612e88565b81815285602083850101111561293c578384fd5b611c38826020830160208601612ec8565b60006020828403121561295e578081fd5b813567ffffffffffffffff80821115612975578283fd5b9083019060a08286031215612988578283fd5b60405160a08101818110838211171561299d57fe5b6040528235828111156129ae578485fd5b6129ba87828601612651565b8252506129c960208401612646565b602082015260408301356040820152606083013560608201526080830135608082015280935050505092915050565b60006101008284031215612a0a578081fd5b6126d083836126a2565b600060208284031215612a25578081fd5b813567ffffffffffffffff811115612a3b578182fd5b820160a081850312156126d0578182fd5b600060208284031215612a5d578081fd5b813567ffffffffffffffff80821115612a74578283fd5b9083019060408286031215612a87578283fd5b604051604081018181108382111715612a9c57fe5b604052823582811115612aad578485fd5b612ab987828601612651565b82525060208301359250612acc83612ef4565b6020810192909252509392505050565b600060208284031215612aed578081fd5b813562ffffff811681146126d0578182fd5b60008060408385031215612b11578182fd5b823591506020830135612b2381612ef4565b809150509250929050565b60008060008060808587031215612b43578182fd5b843593506020850135612b5581612ef4565b9250604085013591506060850135612b6c81612ef4565b939692955090935050565b60008151808452612b8f816020860160208601612ec8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b6000828483379101908152919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a06080830152612c9f60a0830184612b77565b979650505050505050565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015612d1b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452612d09858351612b77565b94509285019290850190600101612ccf565b5092979650505050505050565b6000602082526126d06020830184612b77565b60208082526012908201527f546f6f206d756368207265717565737465640000000000000000000000000000604082015260600190565b60208082526013908201527f546f6f206c6974746c6520726563656976656400000000000000000000000000604082015260600190565b600060208252825160406020840152612dc56060840182612b77565b905073ffffffffffffffffffffffffffffffffffffffff60208501511660408401528091505092915050565b90815260200190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612e2e578283fd5b83018035915067ffffffffffffffff821115612e48578283fd5b602001915036819003821315612e5d57600080fd5b9250929050565b60405181810167ffffffffffffffff81118282101715612e8057fe5b604052919050565b600067ffffffffffffffff821115612e9c57fe5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b83811015612ee3578181015183820152602001612ecb565b8381111561108f5750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114612f1657600080fd5b5056fea164736f6c6343000706000a\"\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/TickMathExternal.json",
    "content": "{\n  \"address\": \"0x0772382Dd7D99adb5218d31fAdfE1c68c8477335\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tick\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"name\": \"getSqrtRatioAtTick\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96\",\n          \"type\": \"uint160\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint160\",\n          \"name\": \"sqrtPriceX96\",\n          \"type\": \"uint160\"\n        }\n      ],\n      \"name\": \"getTickAtSqrtRatio\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tick\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"stateMutability\": \"pure\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x0a80270d637a17744e7d2a1817f02f1b799a8b34bae9e5473ee2c2e07ec60f8a\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0x0772382Dd7D99adb5218d31fAdfE1c68c8477335\",\n    \"transactionIndex\": 10,\n    \"gasUsed\": \"461403\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x411639e2564e56aae9d011a850a25337237649de69a05c62c2dfebbd28d6387f\",\n    \"transactionHash\": \"0x0a80270d637a17744e7d2a1817f02f1b799a8b34bae9e5473ee2c2e07ec60f8a\",\n    \"logs\": [],\n    \"blockNumber\": 12325016,\n    \"cumulativeGasUsed\": \"5435106\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"solcInputHash\": \"d91027c30078be5bfba0223abd5c6e60\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"tick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"name\\\":\\\"getSqrtRatioAtTick\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint160\\\",\\\"name\\\":\\\"sqrtPriceX96\\\",\\\"type\\\":\\\"uint160\\\"}],\\\"name\\\":\\\"getTickAtSqrtRatio\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"int24\\\",\\\"name\\\":\\\"tick\\\",\\\"type\\\":\\\"int24\\\"}],\\\"stateMutability\\\":\\\"pure\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"getSqrtRatioAtTick(int24)\\\":{\\\"details\\\":\\\"Throws if |tick| > max tick\\\",\\\"params\\\":{\\\"tick\\\":\\\"The input tick for the above formula\\\"},\\\"returns\\\":{\\\"sqrtPriceX96\\\":\\\"A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) at the given tick\\\"}},\\\"getTickAtSqrtRatio(uint160)\\\":{\\\"details\\\":\\\"Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may ever return.\\\",\\\"params\\\":{\\\"sqrtPriceX96\\\":\\\"The sqrt ratio for which to compute the tick as a Q64.96\\\"},\\\"returns\\\":{\\\"tick\\\":\\\"The greatest tick for which the ratio is less than or equal to the input ratio\\\"}}},\\\"stateVariables\\\":{\\\"MAX_SQRT_RATIO\\\":{\\\"details\\\":\\\"The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\"},\\\"MAX_TICK\\\":{\\\"details\\\":\\\"The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\"},\\\"MIN_SQRT_RATIO\\\":{\\\"details\\\":\\\"The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\"},\\\"MIN_TICK\\\":{\\\"details\\\":\\\"The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\"}},\\\"title\\\":\\\"Math library for computing sqrt prices from ticks and vice versa\\\",\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"getSqrtRatioAtTick(int24)\\\":{\\\"notice\\\":\\\"Calculates sqrt(1.0001^tick) * 2^96\\\"},\\\"getTickAtSqrtRatio(uint160)\\\":{\\\"notice\\\":\\\"Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\"}},\\\"notice\\\":\\\"Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports prices between 2**-128 and 2**128\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/libs/TickMathExternal.sol\\\":\\\"TickMathExternal\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":800},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"contracts/libs/TickMathExternal.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: GPL-2.0-or-later\\\\npragma solidity >=0.5.0;\\\\n\\\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\\\n/// prices between 2**-128 and 2**128\\\\nlibrary TickMathExternal {\\\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\\\n    int24 internal constant MIN_TICK = -887272;\\\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\\\n\\\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\\\n\\\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\\\n    /// @dev Throws if |tick| > max tick\\\\n    /// @param tick The input tick for the above formula\\\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\\\n    /// at the given tick\\\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\\\n        require(absTick <= uint256(MAX_TICK), \\\\\\\"T\\\\\\\");\\\\n\\\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\\\n\\\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\\\n\\\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\\\n    }\\\\n\\\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\\\n    /// ever return.\\\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\\\n        // second inequality must be < because the price can never reach the price at the max tick\\\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\\\\\"R\\\\\\\");\\\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\\\n\\\\n        uint256 r = ratio;\\\\n        uint256 msb = 0;\\\\n\\\\n        assembly {\\\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(4, gt(r, 0xFFFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(3, gt(r, 0xFF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(2, gt(r, 0xF))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := shl(1, gt(r, 0x3))\\\\n            msb := or(msb, f)\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            let f := gt(r, 0x1)\\\\n            msb := or(msb, f)\\\\n        }\\\\n\\\\n        if (msb >= 128) r = ratio >> (msb - 127);\\\\n        else r = ratio << (127 - msb);\\\\n\\\\n        int256 log_2 = (int256(msb) - 128) << 64;\\\\n\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(63, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(62, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(61, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(60, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(59, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(58, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(57, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(56, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(55, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(54, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(53, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(52, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(51, f))\\\\n            r := shr(f, r)\\\\n        }\\\\n        assembly {\\\\n            r := shr(127, mul(r, r))\\\\n            let f := shr(128, r)\\\\n            log_2 := or(log_2, shl(50, f))\\\\n        }\\\\n\\\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\\\n\\\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\\\n\\\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xfd917bc787958baa0b7fd6f526f88a63a5b98a32d3ff1c0f67665e7a1be86e10\\\",\\\"license\\\":\\\"GPL-2.0-or-later\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x610768610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80634f76c05814610045578063986cfba314610082575b600080fd5b61006b6004803603602081101561005b57600080fd5b50356001600160a01b03166100be565b6040805160029290920b8252519081900360200190f35b6100a26004803603602081101561009857600080fd5b503560020b6103f3565b604080516001600160a01b039092168252519081900360200190f35b60006401000276a36001600160a01b038316108015906100fa575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b61012f576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106101d957607f810383901c91506101e3565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146103e457886001600160a01b03166103c8826103f3565b6001600160a01b031611156103dd57816103df565b805b6103e6565b815b9998505050505050505050565b60008060008360020b1261040a578260020b610412565b8260020b6000035b9050620d89e8811115610450576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b60006001821661047157700100000000000000000000000000000000610483565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156104b7576ffff97272373d413259a46990580e213a0260801c5b60048216156104d6576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b60088216156104f5576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610514576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610533576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610552576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610571576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610591576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b6102008216156105b1576ff987a7253ac413176f2b074cf7815e540260801c5b6104008216156105d1576ff3392b0822b70005940c7a398e4b70f30260801c5b6108008216156105f1576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610611576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610631576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610651576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610671576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610692576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156106b2576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156106d1576d2216e584f5fa1ea926041bedfe980260801c5b620800008216156106ee576b048a170391f7dc42444e8fa20260801c5b60008460020b131561070957806000198161070557fe5b0490505b64010000000081061561071d576001610720565b60005b60ff16602082901c019250505091905056fea26469706673582212202e5ff2dd11e1c84c4b4e2364d3ed76b64538bfce96b28ff3a83052ea235fa8ed64736f6c63430007060033\",\n  \"deployedBytecode\": \"0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80634f76c05814610045578063986cfba314610082575b600080fd5b61006b6004803603602081101561005b57600080fd5b50356001600160a01b03166100be565b6040805160029290920b8252519081900360200190f35b6100a26004803603602081101561009857600080fd5b503560020b6103f3565b604080516001600160a01b039092168252519081900360200190f35b60006401000276a36001600160a01b038316108015906100fa575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b61012f576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106101d957607f810383901c91506101e3565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146103e457886001600160a01b03166103c8826103f3565b6001600160a01b031611156103dd57816103df565b805b6103e6565b815b9998505050505050505050565b60008060008360020b1261040a578260020b610412565b8260020b6000035b9050620d89e8811115610450576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b60006001821661047157700100000000000000000000000000000000610483565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156104b7576ffff97272373d413259a46990580e213a0260801c5b60048216156104d6576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b60088216156104f5576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615610514576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615610533576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615610552576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615610571576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615610591576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b6102008216156105b1576ff987a7253ac413176f2b074cf7815e540260801c5b6104008216156105d1576ff3392b0822b70005940c7a398e4b70f30260801c5b6108008216156105f1576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615610611576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615610631576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615610651576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615610671576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615610692576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156106b2576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156106d1576d2216e584f5fa1ea926041bedfe980260801c5b620800008216156106ee576b048a170391f7dc42444e8fa20260801c5b60008460020b131561070957806000198161070557fe5b0490505b64010000000081061561071d576001610720565b60005b60ff16602082901c019250505091905056fea26469706673582212202e5ff2dd11e1c84c4b4e2364d3ed76b64538bfce96b28ff3a83052ea235fa8ed64736f6c63430007060033\",\n  \"devdoc\": {\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"getSqrtRatioAtTick(int24)\": {\n        \"details\": \"Throws if |tick| > max tick\",\n        \"params\": {\n          \"tick\": \"The input tick for the above formula\"\n        },\n        \"returns\": {\n          \"sqrtPriceX96\": \"A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) at the given tick\"\n        }\n      },\n      \"getTickAtSqrtRatio(uint160)\": {\n        \"details\": \"Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may ever return.\",\n        \"params\": {\n          \"sqrtPriceX96\": \"The sqrt ratio for which to compute the tick as a Q64.96\"\n        },\n        \"returns\": {\n          \"tick\": \"The greatest tick for which the ratio is less than or equal to the input ratio\"\n        }\n      }\n    },\n    \"stateVariables\": {\n      \"MAX_SQRT_RATIO\": {\n        \"details\": \"The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\"\n      },\n      \"MAX_TICK\": {\n        \"details\": \"The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\"\n      },\n      \"MIN_SQRT_RATIO\": {\n        \"details\": \"The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\"\n      },\n      \"MIN_TICK\": {\n        \"details\": \"The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\"\n      }\n    },\n    \"title\": \"Math library for computing sqrt prices from ticks and vice versa\",\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"getSqrtRatioAtTick(int24)\": {\n        \"notice\": \"Calculates sqrt(1.0001^tick) * 2^96\"\n      },\n      \"getTickAtSqrtRatio(uint160)\": {\n        \"notice\": \"Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\"\n      }\n    },\n    \"notice\": \"Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports prices between 2**-128 and 2**128\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [],\n    \"types\": null\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/Timelock.json",
    "content": "{\n  \"address\": \"0xF15964458bcA1941dE53fBc004BA7842f4783EC6\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"admin_\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"delay_\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"bytes32\",\n          \"name\": \"txHash\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"CancelTransaction\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"bytes32\",\n          \"name\": \"txHash\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"ExecuteTransaction\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newAdmin\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"NewAdmin\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint256\",\n          \"name\": \"newDelay\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"NewDelay\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newPendingAdmin\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"NewPendingAdmin\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"bytes32\",\n          \"name\": \"txHash\",\n          \"type\": \"bytes32\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"QueueTransaction\",\n      \"type\": \"event\"\n    },\n    {\n      \"stateMutability\": \"payable\",\n      \"type\": \"fallback\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"GRACE_PERIOD\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"MAXIMUM_DELAY\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"MINIMUM_DELAY\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"acceptAdmin\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"admin\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"cancelTransaction\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"delay\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"executeTransaction\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"\",\n          \"type\": \"bytes\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"pendingAdmin\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"target\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"signature\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"bytes\",\n          \"name\": \"data\",\n          \"type\": \"bytes\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"eta\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"queueTransaction\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"bytes32\",\n          \"name\": \"\",\n          \"type\": \"bytes32\"\n        }\n      ],\n      \"name\": \"queuedTransactions\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"delay_\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"setDelay\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"pendingAdmin_\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"setPendingAdmin\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x966ab04c12173726b8dc7b739d1d62e953e312197ed9d0416efd466daf381f06\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0xF15964458bcA1941dE53fBc004BA7842f4783EC6\",\n    \"transactionIndex\": 9,\n    \"gasUsed\": \"1731280\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0xcb01fe82556cd2da6ef7de2f706662331d89c272086fa9b15b41337bf3d23d3d\",\n    \"transactionHash\": \"0x966ab04c12173726b8dc7b739d1d62e953e312197ed9d0416efd466daf381f06\",\n    \"logs\": [],\n    \"blockNumber\": 12482222,\n    \"cumulativeGasUsed\": \"3284638\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    172800\n  ],\n  \"solcInputHash\": \"e85d9fda89ae8c3780a8ae01da3f423c\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.8.10+commit.fc410830\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"admin_\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"delay_\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"txHash\\\",\\\"type\\\":\\\"bytes32\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"CancelTransaction\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"txHash\\\",\\\"type\\\":\\\"bytes32\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"ExecuteTransaction\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newAdmin\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"NewAdmin\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"newDelay\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"NewDelay\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"newPendingAdmin\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"NewPendingAdmin\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"txHash\\\",\\\"type\\\":\\\"bytes32\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"QueueTransaction\\\",\\\"type\\\":\\\"event\\\"},{\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"fallback\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"GRACE_PERIOD\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"MAXIMUM_DELAY\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"MINIMUM_DELAY\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"acceptAdmin\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"admin\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"cancelTransaction\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"delay\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"executeTransaction\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"pendingAdmin\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"target\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"signature\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"bytes\\\",\\\"name\\\":\\\"data\\\",\\\"type\\\":\\\"bytes\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"eta\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"queueTransaction\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"bytes32\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bytes32\\\"}],\\\"name\\\":\\\"queuedTransactions\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"delay_\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"setDelay\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"pendingAdmin_\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"setPendingAdmin\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/strategy/timelock/Timelock.sol\\\":\\\"Timelock\\\"},\\\"evmVersion\\\":\\\"london\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\"},\\\"optimizer\\\":{\\\"enabled\\\":false,\\\"runs\\\":200},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"contracts/strategy/timelock/SafeMath.sol\\\":{\\\"keccak256\\\":\\\"0x4096f1e15e33c0219aebf8c574521db0d47a23106edf539bbb21539a91716137\\\",\\\"license\\\":\\\"BSD-3-Clause\\\",\\\"urls\\\":[\\\"bzz-raw://a14a79ba570f2ca27848c0d8ea1bfc24c285e0559fd8c899804d96ab45f37039\\\",\\\"dweb:/ipfs/QmSrcv1vMeinEqSS2YDKrQDmwH4eXugWMAuLjMDAYMzNtk\\\"]},\\\"contracts/strategy/timelock/Timelock.sol\\\":{\\\"keccak256\\\":\\\"0x1255ec6e3c4fbd6b853907bb0c602b059ddbce72346d210c555cd93b3729429f\\\",\\\"license\\\":\\\"BSD-3-Clause\\\",\\\"urls\\\":[\\\"bzz-raw://61996a81280b3cbf08aa666dd0765468953367386c7290ba7396b9ec7278a402\\\",\\\"dweb:/ipfs/QmXssf8kKgEDaYGcxpM36Cx3gefdg4PQiSQny2d8DKbdbU\\\"]}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60806040523480156200001157600080fd5b50604051620020cc380380620020cc8339818101604052810190620000379190620001bd565b6202a30081101562000080576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000077906200028b565b60405180910390fd5b62278d00811115620000c9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000c09062000323565b60405180910390fd5b816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600281905550505062000345565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200014a826200011d565b9050919050565b6200015c816200013d565b81146200016857600080fd5b50565b6000815190506200017c8162000151565b92915050565b6000819050919050565b620001978162000182565b8114620001a357600080fd5b50565b600081519050620001b7816200018c565b92915050565b60008060408385031215620001d757620001d662000118565b5b6000620001e7858286016200016b565b9250506020620001fa85828601620001a6565b9150509250929050565b600082825260208201905092915050565b7f54696d656c6f636b3a3a636f6e7374727563746f723a2044656c6179206d757360008201527f7420657863656564206d696e696d756d2064656c61792e000000000000000000602082015250565b60006200027360378362000204565b9150620002808262000215565b604082019050919050565b60006020820190508181036000830152620002a68162000264565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206e60008201527f6f7420657863656564206d6178696d756d2064656c61792e0000000000000000602082015250565b60006200030b60388362000204565b91506200031882620002ad565b604082019050919050565b600060208201905081810360008301526200033e81620002fc565b9050919050565b611d7780620003556000396000f3fe6080604052600436106100c65760003560e01c80636a42b8f81161007f578063c1a287e211610059578063c1a287e21461024b578063e177246e14610276578063f2b065371461029f578063f851a440146102dc576100c7565b80636a42b8f8146101ca5780637d645fab146101f5578063b1b43ae514610220576100c7565b80630825f38f146100c95780630e18b681146100f957806326782247146101105780633a66f9011461013b5780634dd18bf514610178578063591fcdfe146101a1576100c7565b5b005b6100e360048036038101906100de9190611080565b610307565b6040516100f091906111bb565b60405180910390f35b34801561010557600080fd5b5061010e610654565b005b34801561011c57600080fd5b506101256107cb565b60405161013291906111ec565b60405180910390f35b34801561014757600080fd5b50610162600480360381019061015d9190611080565b6107f1565b60405161016f9190611220565b60405180910390f35b34801561018457600080fd5b5061019f600480360381019061019a919061123b565b6109a1565b005b3480156101ad57600080fd5b506101c860048036038101906101c39190611080565b610ab8565b005b3480156101d657600080fd5b506101df610c02565b6040516101ec9190611277565b60405180910390f35b34801561020157600080fd5b5061020a610c08565b6040516102179190611277565b60405180910390f35b34801561022c57600080fd5b50610235610c0f565b6040516102429190611277565b60405180910390f35b34801561025757600080fd5b50610260610c16565b60405161026d9190611277565b60405180910390f35b34801561028257600080fd5b5061029d60048036038101906102989190611292565b610c1d565b005b3480156102ab57600080fd5b506102c660048036038101906102c191906112eb565b610d50565b6040516102d39190611333565b60405180910390f35b3480156102e857600080fd5b506102f1610d70565b6040516102fe91906111ec565b60405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161038e906113d1565b60405180910390fd5b600086868686866040516020016103b2959493929190611435565b6040516020818303038152906040528051906020012090506003600082815260200190815260200160002060009054906101000a900460ff1661042a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042190611508565b60405180910390fd5b82610433610d94565b1015610474576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046b906115c0565b60405180910390fd5b61048a6212750084610d9c90919063ffffffff16565b610492610d94565b11156104d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104ca90611652565b60405180910390fd5b60006003600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060606000865114156105135784905061053f565b85805190602001208560405160200161052d9291906116fb565b60405160208183030381529060405290505b6000808973ffffffffffffffffffffffffffffffffffffffff1689846040516105689190611723565b60006040518083038185875af1925050503d80600081146105a5576040519150601f19603f3d011682016040523d82523d6000602084013e6105aa565b606091505b5091509150816105ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e6906117ac565b60405180910390fd5b8973ffffffffffffffffffffffffffffffffffffffff16847fa560e3198060a2f10670c1ec5b403077ea6ae93ca8de1c32b451dc1a943cd6e78b8b8b8b60405161063c94939291906117cc565b60405180910390a38094505050505095945050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106db90611891565b60405180910390fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c60405160405180910390a2565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610882576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087990611923565b60405180910390fd5b61089e600254610890610d94565b610d9c90919063ffffffff16565b8210156108e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d7906119db565b60405180910390fd5b600086868686866040516020016108fb959493929190611435565b60405160208183030381529060405280519060200120905060016003600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508673ffffffffffffffffffffffffffffffffffffffff16817f76e2796dc3a81d57b0e8504b647febcbeeb5f4af818e164f11eef8131a6a763f8888888860405161098c94939291906117cc565b60405180910390a38091505095945050505050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0690611a6d565b60405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f69d78e38a01985fbb1462961809b4b2d65531bc93b2b94037f3334b82ca4a75660405160405180910390a250565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b46576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3d90611aff565b60405180910390fd5b60008585858585604051602001610b61959493929190611435565b60405160208183030381529060405280519060200120905060006003600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508573ffffffffffffffffffffffffffffffffffffffff16817f2fffc091a501fd91bfbff27141450d3acb40fb8e6d8382b243ec7a812a3aaf8787878787604051610bf294939291906117cc565b60405180910390a3505050505050565b60025481565b62278d0081565b6202a30081565b6212750081565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8290611b91565b60405180910390fd5b6202a300811015610cd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc890611c23565b60405180910390fd5b62278d00811115610d17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0e90611cb5565b60405180910390fd5b806002819055506002547f948b1f6a42ee138b7e34058ba85a37f716d55ff25ff05a763f15bed6a04c8d2c60405160405180910390a250565b60036020528060005260406000206000915054906101000a900460ff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600042905090565b600080828401905083811015610de7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dde90611d21565b60405180910390fd5b8091505092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610e3082610e05565b9050919050565b610e4081610e25565b8114610e4b57600080fd5b50565b600081359050610e5d81610e37565b92915050565b6000819050919050565b610e7681610e63565b8114610e8157600080fd5b50565b600081359050610e9381610e6d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610eec82610ea3565b810181811067ffffffffffffffff82111715610f0b57610f0a610eb4565b5b80604052505050565b6000610f1e610df1565b9050610f2a8282610ee3565b919050565b600067ffffffffffffffff821115610f4a57610f49610eb4565b5b610f5382610ea3565b9050602081019050919050565b82818337600083830152505050565b6000610f82610f7d84610f2f565b610f14565b905082815260208101848484011115610f9e57610f9d610e9e565b5b610fa9848285610f60565b509392505050565b600082601f830112610fc657610fc5610e99565b5b8135610fd6848260208601610f6f565b91505092915050565b600067ffffffffffffffff821115610ffa57610ff9610eb4565b5b61100382610ea3565b9050602081019050919050565b600061102361101e84610fdf565b610f14565b90508281526020810184848401111561103f5761103e610e9e565b5b61104a848285610f60565b509392505050565b600082601f83011261106757611066610e99565b5b8135611077848260208601611010565b91505092915050565b600080600080600060a0868803121561109c5761109b610dfb565b5b60006110aa88828901610e4e565b95505060206110bb88828901610e84565b945050604086013567ffffffffffffffff8111156110dc576110db610e00565b5b6110e888828901610fb1565b935050606086013567ffffffffffffffff81111561110957611108610e00565b5b61111588828901611052565b925050608061112688828901610e84565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b8381101561116d578082015181840152602081019050611152565b8381111561117c576000848401525b50505050565b600061118d82611133565b611197818561113e565b93506111a781856020860161114f565b6111b081610ea3565b840191505092915050565b600060208201905081810360008301526111d58184611182565b905092915050565b6111e681610e25565b82525050565b600060208201905061120160008301846111dd565b92915050565b6000819050919050565b61121a81611207565b82525050565b60006020820190506112356000830184611211565b92915050565b60006020828403121561125157611250610dfb565b5b600061125f84828501610e4e565b91505092915050565b61127181610e63565b82525050565b600060208201905061128c6000830184611268565b92915050565b6000602082840312156112a8576112a7610dfb565b5b60006112b684828501610e84565b91505092915050565b6112c881611207565b81146112d357600080fd5b50565b6000813590506112e5816112bf565b92915050565b60006020828403121561130157611300610dfb565b5b600061130f848285016112d6565b91505092915050565b60008115159050919050565b61132d81611318565b82525050565b60006020820190506113486000830184611324565b92915050565b600082825260208201905092915050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20436160008201527f6c6c206d75737420636f6d652066726f6d2061646d696e2e0000000000000000602082015250565b60006113bb60388361134e565b91506113c68261135f565b604082019050919050565b600060208201905081810360008301526113ea816113ae565b9050919050565b600081519050919050565b6000611407826113f1565b611411818561134e565b935061142181856020860161114f565b61142a81610ea3565b840191505092915050565b600060a08201905061144a60008301886111dd565b6114576020830187611268565b818103604083015261146981866113fc565b9050818103606083015261147d8185611182565b905061148c6080830184611268565b9695505050505050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206861736e2774206265656e207175657565642e000000602082015250565b60006114f2603d8361134e565b91506114fd82611496565b604082019050919050565b60006020820190508181036000830152611521816114e5565b9050919050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206861736e2774207375727061737365642074696d652060208201527f6c6f636b2e000000000000000000000000000000000000000000000000000000604082015250565b60006115aa60458361134e565b91506115b582611528565b606082019050919050565b600060208201905081810360008301526115d98161159d565b9050919050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206973207374616c652e00000000000000000000000000602082015250565b600061163c60338361134e565b9150611647826115e0565b604082019050919050565b6000602082019050818103600083015261166b8161162f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b6116b96116b482611672565b61169e565b82525050565b600081905092915050565b60006116d582611133565b6116df81856116bf565b93506116ef81856020860161114f565b80840191505092915050565b600061170782856116a8565b60048201915061171782846116ca565b91508190509392505050565b600061172f82846116ca565b915081905092915050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e20657865637574696f6e2072657665727465642e000000602082015250565b6000611796603d8361134e565b91506117a18261173a565b604082019050919050565b600060208201905081810360008301526117c581611789565b9050919050565b60006080820190506117e16000830187611268565b81810360208301526117f381866113fc565b905081810360408301526118078185611182565b90506118166060830184611268565b95945050505050565b7f54696d656c6f636b3a3a61636365707441646d696e3a2043616c6c206d75737460008201527f20636f6d652066726f6d2070656e64696e6741646d696e2e0000000000000000602082015250565b600061187b60388361134e565b91506118868261181f565b604082019050919050565b600060208201905081810360008301526118aa8161186e565b9050919050565b7f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a2043616c6c60008201527f206d75737420636f6d652066726f6d2061646d696e2e00000000000000000000602082015250565b600061190d60368361134e565b9150611918826118b1565b604082019050919050565b6000602082019050818103600083015261193c81611900565b9050919050565b7f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a204573746960008201527f6d6174656420657865637574696f6e20626c6f636b206d75737420736174697360208201527f66792064656c61792e0000000000000000000000000000000000000000000000604082015250565b60006119c560498361134e565b91506119d082611943565b606082019050919050565b600060208201905081810360008301526119f4816119b8565b9050919050565b7f54696d656c6f636b3a3a73657450656e64696e6741646d696e3a2043616c6c2060008201527f6d75737420636f6d652066726f6d2054696d656c6f636b2e0000000000000000602082015250565b6000611a5760388361134e565b9150611a62826119fb565b604082019050919050565b60006020820190508181036000830152611a8681611a4a565b9050919050565b7f54696d656c6f636b3a3a63616e63656c5472616e73616374696f6e3a2043616c60008201527f6c206d75737420636f6d652066726f6d2061646d696e2e000000000000000000602082015250565b6000611ae960378361134e565b9150611af482611a8d565b604082019050919050565b60006020820190508181036000830152611b1881611adc565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2043616c6c206d75737420636f60008201527f6d652066726f6d2054696d656c6f636b2e000000000000000000000000000000602082015250565b6000611b7b60318361134e565b9150611b8682611b1f565b604082019050919050565b60006020820190508181036000830152611baa81611b6e565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206560008201527f7863656564206d696e696d756d2064656c61792e000000000000000000000000602082015250565b6000611c0d60348361134e565b9150611c1882611bb1565b604082019050919050565b60006020820190508181036000830152611c3c81611c00565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206e60008201527f6f7420657863656564206d6178696d756d2064656c61792e0000000000000000602082015250565b6000611c9f60388361134e565b9150611caa82611c43565b604082019050919050565b60006020820190508181036000830152611cce81611c92565b9050919050565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000600082015250565b6000611d0b601b8361134e565b9150611d1682611cd5565b602082019050919050565b60006020820190508181036000830152611d3a81611cfe565b905091905056fea2646970667358221220cf514a935c267519527cd5a3c0353bc9a6b4bf8a678929991b92751553d4419964736f6c634300080a0033\",\n  \"deployedBytecode\": \"0x6080604052600436106100c65760003560e01c80636a42b8f81161007f578063c1a287e211610059578063c1a287e21461024b578063e177246e14610276578063f2b065371461029f578063f851a440146102dc576100c7565b80636a42b8f8146101ca5780637d645fab146101f5578063b1b43ae514610220576100c7565b80630825f38f146100c95780630e18b681146100f957806326782247146101105780633a66f9011461013b5780634dd18bf514610178578063591fcdfe146101a1576100c7565b5b005b6100e360048036038101906100de9190611080565b610307565b6040516100f091906111bb565b60405180910390f35b34801561010557600080fd5b5061010e610654565b005b34801561011c57600080fd5b506101256107cb565b60405161013291906111ec565b60405180910390f35b34801561014757600080fd5b50610162600480360381019061015d9190611080565b6107f1565b60405161016f9190611220565b60405180910390f35b34801561018457600080fd5b5061019f600480360381019061019a919061123b565b6109a1565b005b3480156101ad57600080fd5b506101c860048036038101906101c39190611080565b610ab8565b005b3480156101d657600080fd5b506101df610c02565b6040516101ec9190611277565b60405180910390f35b34801561020157600080fd5b5061020a610c08565b6040516102179190611277565b60405180910390f35b34801561022c57600080fd5b50610235610c0f565b6040516102429190611277565b60405180910390f35b34801561025757600080fd5b50610260610c16565b60405161026d9190611277565b60405180910390f35b34801561028257600080fd5b5061029d60048036038101906102989190611292565b610c1d565b005b3480156102ab57600080fd5b506102c660048036038101906102c191906112eb565b610d50565b6040516102d39190611333565b60405180910390f35b3480156102e857600080fd5b506102f1610d70565b6040516102fe91906111ec565b60405180910390f35b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161038e906113d1565b60405180910390fd5b600086868686866040516020016103b2959493929190611435565b6040516020818303038152906040528051906020012090506003600082815260200190815260200160002060009054906101000a900460ff1661042a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042190611508565b60405180910390fd5b82610433610d94565b1015610474576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046b906115c0565b60405180910390fd5b61048a6212750084610d9c90919063ffffffff16565b610492610d94565b11156104d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104ca90611652565b60405180910390fd5b60006003600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060606000865114156105135784905061053f565b85805190602001208560405160200161052d9291906116fb565b60405160208183030381529060405290505b6000808973ffffffffffffffffffffffffffffffffffffffff1689846040516105689190611723565b60006040518083038185875af1925050503d80600081146105a5576040519150601f19603f3d011682016040523d82523d6000602084013e6105aa565b606091505b5091509150816105ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e6906117ac565b60405180910390fd5b8973ffffffffffffffffffffffffffffffffffffffff16847fa560e3198060a2f10670c1ec5b403077ea6ae93ca8de1c32b451dc1a943cd6e78b8b8b8b60405161063c94939291906117cc565b60405180910390a38094505050505095945050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106db90611891565b60405180910390fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c60405160405180910390a2565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610882576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087990611923565b60405180910390fd5b61089e600254610890610d94565b610d9c90919063ffffffff16565b8210156108e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d7906119db565b60405180910390fd5b600086868686866040516020016108fb959493929190611435565b60405160208183030381529060405280519060200120905060016003600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508673ffffffffffffffffffffffffffffffffffffffff16817f76e2796dc3a81d57b0e8504b647febcbeeb5f4af818e164f11eef8131a6a763f8888888860405161098c94939291906117cc565b60405180910390a38091505095945050505050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0690611a6d565b60405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f69d78e38a01985fbb1462961809b4b2d65531bc93b2b94037f3334b82ca4a75660405160405180910390a250565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b46576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3d90611aff565b60405180910390fd5b60008585858585604051602001610b61959493929190611435565b60405160208183030381529060405280519060200120905060006003600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508573ffffffffffffffffffffffffffffffffffffffff16817f2fffc091a501fd91bfbff27141450d3acb40fb8e6d8382b243ec7a812a3aaf8787878787604051610bf294939291906117cc565b60405180910390a3505050505050565b60025481565b62278d0081565b6202a30081565b6212750081565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8290611b91565b60405180910390fd5b6202a300811015610cd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc890611c23565b60405180910390fd5b62278d00811115610d17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0e90611cb5565b60405180910390fd5b806002819055506002547f948b1f6a42ee138b7e34058ba85a37f716d55ff25ff05a763f15bed6a04c8d2c60405160405180910390a250565b60036020528060005260406000206000915054906101000a900460ff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600042905090565b600080828401905083811015610de7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dde90611d21565b60405180910390fd5b8091505092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610e3082610e05565b9050919050565b610e4081610e25565b8114610e4b57600080fd5b50565b600081359050610e5d81610e37565b92915050565b6000819050919050565b610e7681610e63565b8114610e8157600080fd5b50565b600081359050610e9381610e6d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610eec82610ea3565b810181811067ffffffffffffffff82111715610f0b57610f0a610eb4565b5b80604052505050565b6000610f1e610df1565b9050610f2a8282610ee3565b919050565b600067ffffffffffffffff821115610f4a57610f49610eb4565b5b610f5382610ea3565b9050602081019050919050565b82818337600083830152505050565b6000610f82610f7d84610f2f565b610f14565b905082815260208101848484011115610f9e57610f9d610e9e565b5b610fa9848285610f60565b509392505050565b600082601f830112610fc657610fc5610e99565b5b8135610fd6848260208601610f6f565b91505092915050565b600067ffffffffffffffff821115610ffa57610ff9610eb4565b5b61100382610ea3565b9050602081019050919050565b600061102361101e84610fdf565b610f14565b90508281526020810184848401111561103f5761103e610e9e565b5b61104a848285610f60565b509392505050565b600082601f83011261106757611066610e99565b5b8135611077848260208601611010565b91505092915050565b600080600080600060a0868803121561109c5761109b610dfb565b5b60006110aa88828901610e4e565b95505060206110bb88828901610e84565b945050604086013567ffffffffffffffff8111156110dc576110db610e00565b5b6110e888828901610fb1565b935050606086013567ffffffffffffffff81111561110957611108610e00565b5b61111588828901611052565b925050608061112688828901610e84565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b8381101561116d578082015181840152602081019050611152565b8381111561117c576000848401525b50505050565b600061118d82611133565b611197818561113e565b93506111a781856020860161114f565b6111b081610ea3565b840191505092915050565b600060208201905081810360008301526111d58184611182565b905092915050565b6111e681610e25565b82525050565b600060208201905061120160008301846111dd565b92915050565b6000819050919050565b61121a81611207565b82525050565b60006020820190506112356000830184611211565b92915050565b60006020828403121561125157611250610dfb565b5b600061125f84828501610e4e565b91505092915050565b61127181610e63565b82525050565b600060208201905061128c6000830184611268565b92915050565b6000602082840312156112a8576112a7610dfb565b5b60006112b684828501610e84565b91505092915050565b6112c881611207565b81146112d357600080fd5b50565b6000813590506112e5816112bf565b92915050565b60006020828403121561130157611300610dfb565b5b600061130f848285016112d6565b91505092915050565b60008115159050919050565b61132d81611318565b82525050565b60006020820190506113486000830184611324565b92915050565b600082825260208201905092915050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20436160008201527f6c6c206d75737420636f6d652066726f6d2061646d696e2e0000000000000000602082015250565b60006113bb60388361134e565b91506113c68261135f565b604082019050919050565b600060208201905081810360008301526113ea816113ae565b9050919050565b600081519050919050565b6000611407826113f1565b611411818561134e565b935061142181856020860161114f565b61142a81610ea3565b840191505092915050565b600060a08201905061144a60008301886111dd565b6114576020830187611268565b818103604083015261146981866113fc565b9050818103606083015261147d8185611182565b905061148c6080830184611268565b9695505050505050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206861736e2774206265656e207175657565642e000000602082015250565b60006114f2603d8361134e565b91506114fd82611496565b604082019050919050565b60006020820190508181036000830152611521816114e5565b9050919050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206861736e2774207375727061737365642074696d652060208201527f6c6f636b2e000000000000000000000000000000000000000000000000000000604082015250565b60006115aa60458361134e565b91506115b582611528565b606082019050919050565b600060208201905081810360008301526115d98161159d565b9050919050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e206973207374616c652e00000000000000000000000000602082015250565b600061163c60338361134e565b9150611647826115e0565b604082019050919050565b6000602082019050818103600083015261166b8161162f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b6116b96116b482611672565b61169e565b82525050565b600081905092915050565b60006116d582611133565b6116df81856116bf565b93506116ef81856020860161114f565b80840191505092915050565b600061170782856116a8565b60048201915061171782846116ca565b91508190509392505050565b600061172f82846116ca565b915081905092915050565b7f54696d656c6f636b3a3a657865637574655472616e73616374696f6e3a20547260008201527f616e73616374696f6e20657865637574696f6e2072657665727465642e000000602082015250565b6000611796603d8361134e565b91506117a18261173a565b604082019050919050565b600060208201905081810360008301526117c581611789565b9050919050565b60006080820190506117e16000830187611268565b81810360208301526117f381866113fc565b905081810360408301526118078185611182565b90506118166060830184611268565b95945050505050565b7f54696d656c6f636b3a3a61636365707441646d696e3a2043616c6c206d75737460008201527f20636f6d652066726f6d2070656e64696e6741646d696e2e0000000000000000602082015250565b600061187b60388361134e565b91506118868261181f565b604082019050919050565b600060208201905081810360008301526118aa8161186e565b9050919050565b7f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a2043616c6c60008201527f206d75737420636f6d652066726f6d2061646d696e2e00000000000000000000602082015250565b600061190d60368361134e565b9150611918826118b1565b604082019050919050565b6000602082019050818103600083015261193c81611900565b9050919050565b7f54696d656c6f636b3a3a71756575655472616e73616374696f6e3a204573746960008201527f6d6174656420657865637574696f6e20626c6f636b206d75737420736174697360208201527f66792064656c61792e0000000000000000000000000000000000000000000000604082015250565b60006119c560498361134e565b91506119d082611943565b606082019050919050565b600060208201905081810360008301526119f4816119b8565b9050919050565b7f54696d656c6f636b3a3a73657450656e64696e6741646d696e3a2043616c6c2060008201527f6d75737420636f6d652066726f6d2054696d656c6f636b2e0000000000000000602082015250565b6000611a5760388361134e565b9150611a62826119fb565b604082019050919050565b60006020820190508181036000830152611a8681611a4a565b9050919050565b7f54696d656c6f636b3a3a63616e63656c5472616e73616374696f6e3a2043616c60008201527f6c206d75737420636f6d652066726f6d2061646d696e2e000000000000000000602082015250565b6000611ae960378361134e565b9150611af482611a8d565b604082019050919050565b60006020820190508181036000830152611b1881611adc565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2043616c6c206d75737420636f60008201527f6d652066726f6d2054696d656c6f636b2e000000000000000000000000000000602082015250565b6000611b7b60318361134e565b9150611b8682611b1f565b604082019050919050565b60006020820190508181036000830152611baa81611b6e565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206560008201527f7863656564206d696e696d756d2064656c61792e000000000000000000000000602082015250565b6000611c0d60348361134e565b9150611c1882611bb1565b604082019050919050565b60006020820190508181036000830152611c3c81611c00565b9050919050565b7f54696d656c6f636b3a3a73657444656c61793a2044656c6179206d757374206e60008201527f6f7420657863656564206d6178696d756d2064656c61792e0000000000000000602082015250565b6000611c9f60388361134e565b9150611caa82611c43565b604082019050919050565b60006020820190508181036000830152611cce81611c92565b9050919050565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000600082015250565b6000611d0b601b8361134e565b9150611d1682611cd5565b602082019050919050565b60006020820190508181036000830152611d3a81611cfe565b905091905056fea2646970667358221220cf514a935c267519527cd5a3c0353bc9a6b4bf8a678929991b92751553d4419964736f6c634300080a0033\"\n}\n"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/UniswapV3Factory.json",
    "content": "{\n  \"address\": \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n  \"abi\": [\n    {\n      \"inputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"int24\",\n          \"name\": \"tickSpacing\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"name\": \"FeeAmountEnabled\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"oldOwner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"newOwner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"OwnerChanged\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"token0\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"token1\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"int24\",\n          \"name\": \"tickSpacing\",\n          \"type\": \"int24\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"address\",\n          \"name\": \"pool\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"PoolCreated\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"tokenA\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"tokenB\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"createPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"pool\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tickSpacing\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"name\": \"enableFeeAmount\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"feeAmountTickSpacing\",\n      \"outputs\": [\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"\",\n          \"type\": \"uint24\"\n        }\n      ],\n      \"name\": \"getPool\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"owner\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"parameters\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"factory\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token0\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"token1\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint24\",\n          \"name\": \"fee\",\n          \"type\": \"uint24\"\n        },\n        {\n          \"internalType\": \"int24\",\n          \"name\": \"tickSpacing\",\n          \"type\": \"int24\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_owner\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"setOwner\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0xecdd81129a8de0e8db441a349e897ae3edf9a9b4d37ac692ebefc5aee8de025b\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0x5599b4EAdDd319e2F462b27fC8378B0BFaD309CA\",\n    \"contractAddress\": \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n    \"transactionIndex\": 3,\n    \"gasUsed\": \"5439096\",\n    \"logsBloom\": \"0x00000000000000000100000000040020000020000000000000080000800000000400000000000800080000000000000000084000060000000020000000000000000000000000002000000000000000000000000000000040000000000080000000000000021000000000000000000800000080100000000000000000000000004000000000000000010000000000000000000010000000000000000000000000000000000000000000000000800100000000000000000000000000000000000000000001000000000000000000000000040000000000080000000000000020000000000000000004000000200000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x360bc318cc77a83990169abf1e92c8acbe034123f5f5c2f9c3d277c487dda56a\",\n    \"transactionHash\": \"0xecdd81129a8de0e8db441a349e897ae3edf9a9b4d37ac692ebefc5aee8de025b\",\n    \"logs\": [\n      {\n        \"transactionIndex\": 3,\n        \"blockNumber\": 11342317,\n        \"transactionHash\": \"0xecdd81129a8de0e8db441a349e897ae3edf9a9b4d37ac692ebefc5aee8de025b\",\n        \"address\": \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n        \"topics\": [\n          \"0xb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n          \"0x0000000000000000000000005599b4eaddd319e2f462b27fc8378b0bfad309ca\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 0,\n        \"blockHash\": \"0x360bc318cc77a83990169abf1e92c8acbe034123f5f5c2f9c3d277c487dda56a\"\n      },\n      {\n        \"transactionIndex\": 3,\n        \"blockNumber\": 11342317,\n        \"transactionHash\": \"0xecdd81129a8de0e8db441a349e897ae3edf9a9b4d37ac692ebefc5aee8de025b\",\n        \"address\": \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n        \"topics\": [\n          \"0xc66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc\",\n          \"0x00000000000000000000000000000000000000000000000000000000000001f4\",\n          \"0x000000000000000000000000000000000000000000000000000000000000000a\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 1,\n        \"blockHash\": \"0x360bc318cc77a83990169abf1e92c8acbe034123f5f5c2f9c3d277c487dda56a\"\n      },\n      {\n        \"transactionIndex\": 3,\n        \"blockNumber\": 11342317,\n        \"transactionHash\": \"0xecdd81129a8de0e8db441a349e897ae3edf9a9b4d37ac692ebefc5aee8de025b\",\n        \"address\": \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n        \"topics\": [\n          \"0xc66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc\",\n          \"0x0000000000000000000000000000000000000000000000000000000000000bb8\",\n          \"0x000000000000000000000000000000000000000000000000000000000000003c\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 2,\n        \"blockHash\": \"0x360bc318cc77a83990169abf1e92c8acbe034123f5f5c2f9c3d277c487dda56a\"\n      },\n      {\n        \"transactionIndex\": 3,\n        \"blockNumber\": 11342317,\n        \"transactionHash\": \"0xecdd81129a8de0e8db441a349e897ae3edf9a9b4d37ac692ebefc5aee8de025b\",\n        \"address\": \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n        \"topics\": [\n          \"0xc66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc\",\n          \"0x0000000000000000000000000000000000000000000000000000000000002710\",\n          \"0x00000000000000000000000000000000000000000000000000000000000000c8\"\n        ],\n        \"data\": \"0x\",\n        \"logIndex\": 3,\n        \"blockHash\": \"0x360bc318cc77a83990169abf1e92c8acbe034123f5f5c2f9c3d277c487dda56a\"\n      }\n    ],\n    \"blockNumber\": 11342317,\n    \"cumulativeGasUsed\": \"5502240\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [],\n  \"bytecode\": \"0x60a060405234801561001057600080fd5b503060601b608052600380546001600160a01b031916339081179091556040516000907fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c908290a36101f4600081815260046020527ffb8cf1d12598d1a039dd1d106665851a96aadf67d0d9ed76fceea282119208b7805462ffffff1916600a90811790915560405190929160008051602061614b83398151915291a3610bb8600081815260046020527f72dffa9b822156d9cf4b0090fa0b656bcb9cc2b2c60eb6acfc20a34f54b31743805462ffffff1916603c90811790915560405190929160008051602061614b83398151915291a3612710600081815260046020527f8cc740d51daa94ff54f33bd779c2d20149f524c340519b49181be5a08615f829805462ffffff191660c890811790915560405190929160008051602061614b83398151915291a360805160601c615fd7610174600039806105515250615fd76000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063890357301161005b578063890357301461013b5780638a7c195f146101855780638da5cb5b146101b0578063a1671295146101b85761007d565b806313af4035146100825780631698ee82146100aa57806322afcccb14610102575b600080fd5b6100a86004803603602081101561009857600080fd5b50356001600160a01b03166101f4565b005b6100e6600480360360608110156100c057600080fd5b5080356001600160a01b03908116916020810135909116906040013562ffffff16610267565b604080516001600160a01b039092168252519081900360200190f35b6101246004803603602081101561011857600080fd5b503562ffffff16610293565b6040805160029290920b8252519081900360200190f35b6101436102a8565b604080516001600160a01b0396871681529486166020860152929094168383015262ffffff16606083015260029290920b608082015290519081900360a00190f35b6100a86004803603604081101561019b57600080fd5b5062ffffff813516906020013560020b6102de565b6100e66103a1565b6100e6600480360360608110156101ce57600080fd5b5080356001600160a01b03908116916020810135909116906040013562ffffff166103b0565b6003546001600160a01b0316331461020b57600080fd5b6003546040516001600160a01b038084169216907fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c90600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b60056020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b60046020526000908152604090205460020b81565b600054600154600280546001600160a01b03938416939283169281169162ffffff600160a01b83041691600160b81b9004900b85565b6003546001600160a01b031633146102f557600080fd5b620f42408262ffffff161061030957600080fd5b60008160020b13801561032057506140008160020b125b61032957600080fd5b62ffffff8216600090815260046020526040902054600290810b900b1561034f57600080fd5b62ffffff828116600081815260046020526040808220805462ffffff1916600287900b958616179055517fc66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc9190a35050565b6003546001600160a01b031681565b60006103ba610546565b826001600160a01b0316846001600160a01b031614156103d957600080fd5b600080846001600160a01b0316866001600160a01b0316106103fc5784866103ff565b85855b90925090506001600160a01b03821661041757600080fd5b62ffffff8416600090815260046020526040902054600290810b9081900b61043e57600080fd5b6001600160a01b0383811660009081526005602090815260408083208685168452825280832062ffffff8a168452909152902054161561047d57600080fd5b61048a308484888561057d565b6001600160a01b03808516600081815260056020818152604080842089871680865290835281852062ffffff8e168087529084528286208054988a166001600160a01b0319998a1681179091558287529484528286208787528452828620818752845294829020805490971684179096558051600289900b815291820192909252815195995091947f783cca1c0412dd0d695e784568c96da2e9c22ff989357a2e8b1d9b2b4e6b71189281900390910190a45050509392505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461057b57600080fd5b565b6040805160a0810182526001600160a01b03878116808352878216602080850182905292881684860181905262ffffff888116606080880182905260028a810b6080998a01819052600080546001600160a01b03199081169099178155600180548a1689179055825490981686177fffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffff16600160a01b8502177fffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffff16600160b81b91830b9095160293909317909255875180870194909452838801929092528281019190915285518083039091018152930193849052825192909101919091209091610686906106f5565b8190604051809103906000f59050801580156106a6573d6000803e3d6000fd5b50600080546001600160a01b0319908116909155600180549091169055600280547fffffffffffff00000000000000000000000000000000000000000000000000001690559695505050505050565b6158c8806107038339019056fe6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000aa164736f6c6343000706000ac66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc\"\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/WPowerPerp.json",
    "content": "{\n  \"address\": \"0xa4222f78d23593e82Aa74742d25D06720DCa4ab7\",\n  \"abi\": [\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_name\",\n          \"type\": \"string\"\n        },\n        {\n          \"internalType\": \"string\",\n          \"name\": \"_symbol\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"from\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": true,\n          \"internalType\": \"address\",\n          \"name\": \"to\",\n          \"type\": \"address\"\n        },\n        {\n          \"indexed\": false,\n          \"internalType\": \"uint256\",\n          \"name\": \"value\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"owner\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"account\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"balanceOf\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"burn\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"controller\",\n      \"outputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"\",\n          \"type\": \"address\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint8\",\n          \"name\": \"\",\n          \"type\": \"uint8\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"subtractedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"decreaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"spender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"addedValue\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"increaseAllowance\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_controller\",\n          \"type\": \"address\"\n        }\n      ],\n      \"name\": \"init\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"_account\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"_amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"mint\",\n      \"outputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [\n        {\n          \"internalType\": \"string\",\n          \"name\": \"\",\n          \"type\": \"string\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address\",\n          \"name\": \"sender\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"address\",\n          \"name\": \"recipient\",\n          \"type\": \"address\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amount\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [\n        {\n          \"internalType\": \"bool\",\n          \"name\": \"\",\n          \"type\": \"bool\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"transactionHash\": \"0x73353e0b3ecbf9f394032566a21ac1595d08aafc033f665a822e64a435873857\",\n  \"receipt\": {\n    \"to\": null,\n    \"from\": \"0xf668606B896389066a39B132741763e1ca6d76a2\",\n    \"contractAddress\": \"0xa4222f78d23593e82Aa74742d25D06720DCa4ab7\",\n    \"transactionIndex\": 13,\n    \"gasUsed\": \"1032138\",\n    \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n    \"blockHash\": \"0x141d2687d84c38d5a19db3ec95cecefc393624b94c54b897c3e41a4c8b43bdbf\",\n    \"transactionHash\": \"0x73353e0b3ecbf9f394032566a21ac1595d08aafc033f665a822e64a435873857\",\n    \"logs\": [],\n    \"blockNumber\": 11808030,\n    \"cumulativeGasUsed\": \"7093318\",\n    \"status\": 1,\n    \"byzantium\": true\n  },\n  \"args\": [\n    \"Opyn Squeeth\",\n    \"oSQTH\"\n  ],\n  \"solcInputHash\": \"5f450d03d2b8109eaf06de68c57d8c2b\",\n  \"metadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.7.6+commit.7338295f\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_name\\\",\\\"type\\\":\\\"string\\\"},{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"_symbol\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Approval\\\",\\\"type\\\":\\\"event\\\"},{\\\"anonymous\\\":false,\\\"inputs\\\":[{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"from\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":true,\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"to\\\",\\\"type\\\":\\\"address\\\"},{\\\"indexed\\\":false,\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"Transfer\\\",\\\"type\\\":\\\"event\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"owner\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"allowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"approve\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"account\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"balanceOf\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"burn\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"controller\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"address\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"decimals\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint8\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"subtractedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"decreaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"spender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"addedValue\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"increaseAllowance\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_controller\\\",\\\"type\\\":\\\"address\\\"}],\\\"name\\\":\\\"init\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"_account\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"_amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"mint\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"name\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"symbol\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"string\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"string\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"totalSupply\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transfer\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"sender\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"recipient\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"transferFrom\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"bool\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"bool\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"details\\\":\\\"value of power perpetual is expected to go down over time through the impact of funding\\\",\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{\\\"allowance(address,address)\\\":{\\\"details\\\":\\\"See {IERC20-allowance}.\\\"},\\\"approve(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\\\"},\\\"balanceOf(address)\\\":{\\\"details\\\":\\\"See {IERC20-balanceOf}.\\\"},\\\"burn(address,uint256)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"account to burn from\\\",\\\"_amount\\\":\\\"amount to burn\\\"}},\\\"constructor\\\":{\\\"params\\\":{\\\"_name\\\":\\\"token name for ERC20\\\",\\\"_symbol\\\":\\\"token symbol for ERC20\\\"}},\\\"decimals()\\\":{\\\"details\\\":\\\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\\\"},\\\"decreaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\\\"},\\\"increaseAllowance(address,uint256)\\\":{\\\"details\\\":\\\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\\\"},\\\"init(address)\\\":{\\\"params\\\":{\\\"_controller\\\":\\\"controller address\\\"}},\\\"mint(address,uint256)\\\":{\\\"params\\\":{\\\"_account\\\":\\\"account to mint to\\\",\\\"_amount\\\":\\\"amount to mint\\\"}},\\\"name()\\\":{\\\"details\\\":\\\"Returns the name of the token.\\\"},\\\"symbol()\\\":{\\\"details\\\":\\\"Returns the symbol of the token, usually a shorter version of the name.\\\"},\\\"totalSupply()\\\":{\\\"details\\\":\\\"See {IERC20-totalSupply}.\\\"},\\\"transfer(address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\\\"},\\\"transferFrom(address,address,uint256)\\\":{\\\"details\\\":\\\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\\\"}},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{\\\"burn(address,uint256)\\\":{\\\"notice\\\":\\\"burn wPowerPerp\\\"},\\\"constructor\\\":{\\\"notice\\\":\\\"long power perpetual constructor\\\"},\\\"init(address)\\\":{\\\"notice\\\":\\\"init wPowerPerp contract\\\"},\\\"mint(address,uint256)\\\":{\\\"notice\\\":\\\"mint wPowerPerp\\\"}},\\\"notice\\\":\\\"ERC20 Token representing wrapped long power perpetual position\\\",\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"contracts/core/WPowerPerp.sol\\\":\\\"WPowerPerp\\\"},\\\"evmVersion\\\":\\\"istanbul\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\",\\\"useLiteralContent\\\":true},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":825},\\\"remappings\\\":[]},\\\"sources\\\":{\\\"@openzeppelin/contracts/math/SafeMath.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\\\n * checks.\\\\n *\\\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\\\n * in bugs, because programmers usually assume that an overflow raises an\\\\n * error, which is the standard behavior in high level programming languages.\\\\n * `SafeMath` restores this intuition by reverting the transaction when an\\\\n * operation overflows.\\\\n *\\\\n * Using this library instead of the unchecked operations eliminates an entire\\\\n * class of bugs, so it's recommended to use it always.\\\\n */\\\\nlibrary SafeMath {\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        uint256 c = a + b;\\\\n        if (c < a) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b > a) return (false, 0);\\\\n        return (true, a - b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\\\n        // benefit is lost if 'b' is also tested.\\\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\\\n        if (a == 0) return (true, 0);\\\\n        uint256 c = a * b;\\\\n        if (c / a != b) return (false, 0);\\\\n        return (true, c);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a / b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\\\n        if (b == 0) return (false, 0);\\\\n        return (true, a % b);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the addition of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `+` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Addition cannot overflow.\\\\n     */\\\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        uint256 c = a + b;\\\\n        require(c >= a, \\\\\\\"SafeMath: addition overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b <= a, \\\\\\\"SafeMath: subtraction overflow\\\\\\\");\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\\\n     * overflow.\\\\n     *\\\\n     * Counterpart to Solidity's `*` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Multiplication cannot overflow.\\\\n     */\\\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        if (a == 0) return 0;\\\\n        uint256 c = a * b;\\\\n        require(c / a == b, \\\\\\\"SafeMath: multiplication overflow\\\\\\\");\\\\n        return c;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: division by zero\\\\\\\");\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting when dividing by zero.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\\\n        require(b > 0, \\\\\\\"SafeMath: modulo by zero\\\\\\\");\\\\n        return a % b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\\\n     * overflow (when the result is negative).\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\\\n     *\\\\n     * Counterpart to Solidity's `-` operator.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - Subtraction cannot overflow.\\\\n     */\\\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b <= a, errorMessage);\\\\n        return a - b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\\\n     * division by zero. The result is rounded towards zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\\\n     *\\\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a / b;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\\\n     * reverting with custom message when dividing by zero.\\\\n     *\\\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\\\n     *\\\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\\\n     * invalid opcode to revert (consuming all remaining gas).\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - The divisor cannot be zero.\\\\n     */\\\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\\\n        require(b > 0, errorMessage);\\\\n        return a % b;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\n// solhint-disable-next-line compiler-version\\\\npragma solidity >=0.4.24 <0.8.0;\\\\n\\\\nimport \\\\\\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\\\nabstract contract Initializable {\\\\n\\\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\\\n    function _isConstructor() private view returns (bool) {\\\\n        return !Address.isContract(address(this));\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x9abeffe138f098b16557187383ba0f9e8503602fa95cd668132986ee115237ed\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\nimport \\\\\\\"../../utils/Context.sol\\\\\\\";\\\\nimport \\\\\\\"./IERC20.sol\\\\\\\";\\\\nimport \\\\\\\"../../math/SafeMath.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 guidelines: functions revert instead\\\\n * of returning `false` on failure. This behavior is nonetheless conventional\\\\n * and does not conflict with the expectations of ERC20 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 {\\\\n    using SafeMath for uint256;\\\\n\\\\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    uint8 private _decimals;\\\\n\\\\n    /**\\\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\\\n     * a default value of 18.\\\\n     *\\\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\\\n     *\\\\n     * All three 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        _decimals = 18;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Returns the name of the token.\\\\n     */\\\\n    function name() public view virtual 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 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 {_setupDecimals} is\\\\n     * called.\\\\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 returns (uint8) {\\\\n        return _decimals;\\\\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     * - `recipient` cannot be the zero address.\\\\n     * - the caller must have a balance of at least `amount`.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\\\n     *\\\\n     * - `spender` cannot be the zero address.\\\\n     */\\\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\\\n        _approve(_msgSender(), 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     * Requirements:\\\\n     *\\\\n     * - `sender` and `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\\\n     * `amount`.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\\\n        _transfer(sender, recipient, amount);\\\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\\\\\"ERC20: transfer amount exceeds allowance\\\\\\\"));\\\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\\\\\"ERC20: decreased allowance below zero\\\\\\\"));\\\\n        return true;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\\\n     *\\\\n     * This is 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     * - `sender` cannot be the zero address.\\\\n     * - `recipient` cannot be the zero address.\\\\n     * - `sender` must have a balance of at least `amount`.\\\\n     */\\\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\\\n        require(sender != address(0), \\\\\\\"ERC20: transfer from the zero address\\\\\\\");\\\\n        require(recipient != address(0), \\\\\\\"ERC20: transfer to the zero address\\\\\\\");\\\\n\\\\n        _beforeTokenTransfer(sender, recipient, amount);\\\\n\\\\n        _balances[sender] = _balances[sender].sub(amount, \\\\\\\"ERC20: transfer amount exceeds balance\\\\\\\");\\\\n        _balances[recipient] = _balances[recipient].add(amount);\\\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\\\n        _balances[account] = _balances[account].add(amount);\\\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\\\\\"ERC20: burn amount exceeds balance\\\\\\\");\\\\n        _totalSupply = _totalSupply.sub(amount);\\\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\\\n     *\\\\n     * WARNING: This function should only be called from the constructor. Most\\\\n     * applications that interact with token contracts will not expect\\\\n     * {decimals} to ever change, and may work incorrectly if it does.\\\\n     */\\\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\\\n        _decimals = decimals_;\\\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\\\n */\\\\ninterface IERC20 {\\\\n    /**\\\\n     * @dev Returns the amount of tokens in existence.\\\\n     */\\\\n    function totalSupply() external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Returns the amount of tokens owned by `account`.\\\\n     */\\\\n    function balanceOf(address account) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Returns the remaining number of tokens that `spender` will be\\\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\\\n     * zero by default.\\\\n     *\\\\n     * This value changes when {approve} or {transferFrom} are called.\\\\n     */\\\\n    function allowance(address owner, address spender) external view returns (uint256);\\\\n\\\\n    /**\\\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\\\n     * that someone may use both the old and the new allowance by unfortunate\\\\n     * transaction ordering. One possible solution to mitigate this race\\\\n     * condition is to first reduce the spender's allowance to 0 and set the\\\\n     * desired value afterwards:\\\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\\\n     *\\\\n     * Emits an {Approval} event.\\\\n     */\\\\n    function approve(address spender, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\\\n     * allowance mechanism. `amount` is then deducted from the caller's\\\\n     * allowance.\\\\n     *\\\\n     * Returns a boolean value indicating whether the operation succeeded.\\\\n     *\\\\n     * Emits a {Transfer} event.\\\\n     */\\\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\\\n\\\\n    /**\\\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\\\n     * another (`to`).\\\\n     *\\\\n     * Note that `value` may be zero.\\\\n     */\\\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\\\n\\\\n    /**\\\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\\\n     * a call to {approve}. `value` is the new allowance.\\\\n     */\\\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Address.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity ^0.7.0;\\\\n\\\\n/**\\\\n * @dev Collection of functions related to the address type\\\\n */\\\\nlibrary Address {\\\\n    /**\\\\n     * @dev Returns true if `account` is a contract.\\\\n     *\\\\n     * [IMPORTANT]\\\\n     * ====\\\\n     * It is unsafe to assume that an address for which this function returns\\\\n     * false is an externally-owned account (EOA) and not a contract.\\\\n     *\\\\n     * Among others, `isContract` will return false for the following\\\\n     * types of addresses:\\\\n     *\\\\n     *  - an externally-owned account\\\\n     *  - a contract in construction\\\\n     *  - an address where a contract will be created\\\\n     *  - an address where a contract lived, but was destroyed\\\\n     * ====\\\\n     */\\\\n    function isContract(address account) internal view returns (bool) {\\\\n        // This method relies on extcodesize, which returns 0 for contracts in\\\\n        // construction, since the code is only stored at the end of the\\\\n        // constructor execution.\\\\n\\\\n        uint256 size;\\\\n        // solhint-disable-next-line no-inline-assembly\\\\n        assembly { size := extcodesize(account) }\\\\n        return size > 0;\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\\\n     * `recipient`, forwarding all available gas and reverting on errors.\\\\n     *\\\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\\\n     * imposed by `transfer`, making them unable to receive funds via\\\\n     * `transfer`. {sendValue} removes this limitation.\\\\n     *\\\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\\\n     *\\\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\\\n     * taken to not create reentrancy vulnerabilities. Consider using\\\\n     * {ReentrancyGuard} or the\\\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\\\n     */\\\\n    function sendValue(address payable recipient, uint256 amount) internal {\\\\n        require(address(this).balance >= amount, \\\\\\\"Address: insufficient balance\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\\\n        (bool success, ) = recipient.call{ value: amount }(\\\\\\\"\\\\\\\");\\\\n        require(success, \\\\\\\"Address: unable to send value, recipient may have reverted\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Performs a Solidity function call using a low level `call`. A\\\\n     * plain`call` is an unsafe replacement for a function call: use this\\\\n     * function instead.\\\\n     *\\\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\\\n     * function (like regular Solidity function calls).\\\\n     *\\\\n     * Returns the raw returned data. To convert to the expected return value,\\\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - `target` must be a contract.\\\\n     * - calling `target` with `data` must not revert.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n      return functionCall(target, data, \\\\\\\"Address: low-level call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, 0, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but also transferring `value` wei to `target`.\\\\n     *\\\\n     * Requirements:\\\\n     *\\\\n     * - the calling contract must have an ETH balance of at least `value`.\\\\n     * - the called Solidity function must be `payable`.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\\\n        return functionCallWithValue(target, data, value, \\\\\\\"Address: low-level call with value failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\\\n     *\\\\n     * _Available since v3.1._\\\\n     */\\\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(address(this).balance >= value, \\\\\\\"Address: insufficient balance for call\\\\\\\");\\\\n        require(isContract(target), \\\\\\\"Address: call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\\\n        return functionStaticCall(target, data, \\\\\\\"Address: low-level static call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a static call.\\\\n     *\\\\n     * _Available since v3.3._\\\\n     */\\\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: static call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\\\n        return functionDelegateCall(target, data, \\\\\\\"Address: low-level delegate call failed\\\\\\\");\\\\n    }\\\\n\\\\n    /**\\\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\\\n     * but performing a delegate call.\\\\n     *\\\\n     * _Available since v3.4._\\\\n     */\\\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\\\n        require(isContract(target), \\\\\\\"Address: delegate call to non-contract\\\\\\\");\\\\n\\\\n        // solhint-disable-next-line avoid-low-level-calls\\\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\\\n        return _verifyCallResult(success, returndata, errorMessage);\\\\n    }\\\\n\\\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\\\n        if (success) {\\\\n            return returndata;\\\\n        } else {\\\\n            // Look for revert reason and bubble it up if present\\\\n            if (returndata.length > 0) {\\\\n                // The easiest way to bubble the revert reason is using memory via assembly\\\\n\\\\n                // solhint-disable-next-line no-inline-assembly\\\\n                assembly {\\\\n                    let returndata_size := mload(returndata)\\\\n                    revert(add(32, returndata), returndata_size)\\\\n                }\\\\n            } else {\\\\n                revert(errorMessage);\\\\n            }\\\\n        }\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\\\",\\\"license\\\":\\\"MIT\\\"},\\\"@openzeppelin/contracts/utils/Context.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\\\n        return msg.sender;\\\\n    }\\\\n\\\\n    function _msgData() internal view virtual returns (bytes memory) {\\\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\\\n        return msg.data;\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\\\",\\\"license\\\":\\\"MIT\\\"},\\\"contracts/core/WPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: BUSL-1.1\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\n//interface\\\\nimport {IWPowerPerp} from \\\\\\\"../interfaces/IWPowerPerp.sol\\\\\\\";\\\\n\\\\n//contract\\\\nimport {ERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\\\\\";\\\\nimport {Initializable} from \\\\\\\"@openzeppelin/contracts/proxy/Initializable.sol\\\\\\\";\\\\n\\\\n/**\\\\n * @notice ERC20 Token representing wrapped long power perpetual position\\\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\\\n */\\\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\\\n    address public controller;\\\\n    address private immutable deployer;\\\\n\\\\n    /**\\\\n     * @notice long power perpetual constructor\\\\n     * @param _name token name for ERC20\\\\n     * @param _symbol token symbol for ERC20\\\\n     */\\\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\\\n        deployer = msg.sender;\\\\n    }\\\\n\\\\n    modifier onlyController() {\\\\n        require(msg.sender == controller, \\\\\\\"Not controller\\\\\\\");\\\\n        _;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice init wPowerPerp contract\\\\n     * @param _controller controller address\\\\n     */\\\\n    function init(address _controller) external initializer {\\\\n        require(msg.sender == deployer, \\\\\\\"Invalid caller of init\\\\\\\");\\\\n        require(_controller != address(0), \\\\\\\"Invalid controller address\\\\\\\");\\\\n        controller = _controller;\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice mint wPowerPerp\\\\n     * @param _account account to mint to\\\\n     * @param _amount amount to mint\\\\n     */\\\\n    function mint(address _account, uint256 _amount) external override onlyController {\\\\n        _mint(_account, _amount);\\\\n    }\\\\n\\\\n    /**\\\\n     * @notice burn wPowerPerp\\\\n     * @param _account account to burn from\\\\n     * @param _amount amount to burn\\\\n     */\\\\n    function burn(address _account, uint256 _amount) external override onlyController {\\\\n        _burn(_account, _amount);\\\\n    }\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x46a9dd6652f902a62c5e538d99c4566bcd23cbe21247621c2f17b67250c334c5\\\",\\\"license\\\":\\\"BUSL-1.1\\\"},\\\"contracts/interfaces/IWPowerPerp.sol\\\":{\\\"content\\\":\\\"// SPDX-License-Identifier: MIT\\\\n\\\\npragma solidity =0.7.6;\\\\n\\\\nimport {IERC20} from \\\\\\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\\\\\";\\\\n\\\\ninterface IWPowerPerp is IERC20 {\\\\n    function mint(address _account, uint256 _amount) external;\\\\n\\\\n    function burn(address _account, uint256 _amount) external;\\\\n}\\\\n\\\",\\\"keccak256\\\":\\\"0x873a337fcb47b96ed0714dbc2edbf1d200f529752efb7beb18109c9e6a9d7271\\\",\\\"license\\\":\\\"MIT\\\"}},\\\"version\\\":1}\",\n  \"bytecode\": \"0x60a06040523480156200001157600080fd5b506040516200130238038062001302833981810160405260408110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200010a57600080fd5b9083019060208201858111156200012057600080fd5b82516401000000008111828201881017156200013b57600080fd5b82525081516020918201929091019080838360005b838110156200016a57818101518382015260200162000150565b50505050905090810190601f168015620001985780820380516001836020036101000a031916815260200191505b50604052505082518391508290620001b8906003906020850190620001ed565b508051620001ce906004906020840190620001ed565b50506005805460ff191660121790555050503360601b60805262000299565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928262000225576000855562000270565b82601f106200024057805160ff191683800117855562000270565b8280016001018555821562000270579182015b828111156200027057825182559160200191906001019062000253565b506200027e92915062000282565b5090565b5b808211156200027e576000815560010162000283565b60805160601c61104b620002b760003980610505525061104b6000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806340c10f1911610097578063a457c2d711610066578063a457c2d7146102ff578063a9059cbb1461032b578063dd62ed3e14610357578063f77c479114610385576100f5565b806340c10f191461027957806370a08231146102a557806395d89b41146102cb5780639dc29fac146102d3576100f5565b806319ab453c116100d357806319ab453c146101d157806323b872dd146101f9578063313ce5671461022f578063395093511461024d576100f5565b806306fdde03146100fa578063095ea7b31461017757806318160ddd146101b7575b600080fd5b6101026103a9565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013c578181015183820152602001610124565b50505050905090810190601f1680156101695780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101a36004803603604081101561018d57600080fd5b506001600160a01b03813516906020013561043f565b604080519115158252519081900360200190f35b6101bf61045c565b60408051918252519081900360200190f35b6101f7600480360360208110156101e757600080fd5b50356001600160a01b0316610462565b005b6101a36004803603606081101561020f57600080fd5b506001600160a01b03813581169160208101359091169060400135610622565b6102376106a9565b6040805160ff9092168252519081900360200190f35b6101a36004803603604081101561026357600080fd5b506001600160a01b0381351690602001356106b2565b6101f76004803603604081101561028f57600080fd5b506001600160a01b038135169060200135610700565b6101bf600480360360208110156102bb57600080fd5b50356001600160a01b0316610761565b61010261077c565b6101f7600480360360408110156102e957600080fd5b506001600160a01b0381351690602001356107dd565b6101a36004803603604081101561031557600080fd5b506001600160a01b03813516906020013561083e565b6101a36004803603604081101561034157600080fd5b506001600160a01b0381351690602001356108a6565b6101bf6004803603604081101561036d57600080fd5b506001600160a01b03813581169160200135166108ba565b61038d6108e5565b604080516001600160a01b039092168252519081900360200190f35b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b820191906000526020600020905b81548152906001019060200180831161041857829003601f168201915b5050505050905090565b600061045361044c6108fb565b84846108ff565b50600192915050565b60025490565b60055462010000900460ff168061047c575061047c6109eb565b8061048f5750600554610100900460ff16155b6104ca5760405162461bcd60e51b815260040180806020018281038252602e815260200180610f31602e913960400191505060405180910390fd5b60055462010000900460ff161580156104fa576005805461ff001962ff0000199091166201000017166101001790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610577576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166105d2576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600580547fffffffffffffffffff0000000000000000000000000000000000000000ffffff1663010000006001600160a01b03851602179055801561061e576005805462ff0000191690555b5050565b600061062f8484846109fc565b61069f8461063b6108fb565b61069a85604051806060016040528060288152602001610f5f602891396001600160a01b038a166000908152600160205260408120906106796108fb565b6001600160a01b031681526020810191909152604001600020549190610b57565b6108ff565b5060019392505050565b60055460ff1690565b60006104536106bf6108fb565b8461069a85600160006106d06108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610bee565b600554630100000090046001600160a01b03163314610757576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610c4f565b6001600160a01b031660009081526020819052604090205490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b600554630100000090046001600160a01b03163314610834576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610d3f565b600061045361084b6108fb565b8461069a85604051806060016040528060258152602001610ff160259139600160006108756108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610b57565b60006104536108b36108fb565b84846109fc565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600554630100000090046001600160a01b031681565b3390565b6001600160a01b0383166109445760405162461bcd60e51b8152600401808060200182810382526024815260200180610fcd6024913960400191505060405180910390fd5b6001600160a01b0382166109895760405162461bcd60e51b8152600401808060200182810382526022815260200180610ee96022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60006109f630610e3b565b15905090565b6001600160a01b038316610a415760405162461bcd60e51b8152600401808060200182810382526025815260200180610fa86025913960400191505060405180910390fd5b6001600160a01b038216610a865760405162461bcd60e51b8152600401808060200182810382526023815260200180610ea46023913960400191505060405180910390fd5b610a91838383610e41565b610ace81604051806060016040528060268152602001610f0b602691396001600160a01b0386166000908152602081905260409020549190610b57565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610afd9082610bee565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610be65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610bab578181015183820152602001610b93565b50505050905090810190601f168015610bd85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610c48576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610caa576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610cb660008383610e41565b600254610cc39082610bee565b6002556001600160a01b038216600090815260208190526040902054610ce99082610bee565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610d845760405162461bcd60e51b8152600401808060200182810382526021815260200180610f876021913960400191505060405180910390fd5b610d9082600083610e41565b610dcd81604051806060016040528060228152602001610ec7602291396001600160a01b0385166000908152602081905260409020549190610b57565b6001600160a01b038316600090815260208190526040902055600254610df39082610e46565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b3b151590565b505050565b600082821115610e9d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220b212f681aae3a839369df006b7b5ca6280b5bb82909bb3e14edfc182234e45d164736f6c63430007060033\",\n  \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806340c10f1911610097578063a457c2d711610066578063a457c2d7146102ff578063a9059cbb1461032b578063dd62ed3e14610357578063f77c479114610385576100f5565b806340c10f191461027957806370a08231146102a557806395d89b41146102cb5780639dc29fac146102d3576100f5565b806319ab453c116100d357806319ab453c146101d157806323b872dd146101f9578063313ce5671461022f578063395093511461024d576100f5565b806306fdde03146100fa578063095ea7b31461017757806318160ddd146101b7575b600080fd5b6101026103a9565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013c578181015183820152602001610124565b50505050905090810190601f1680156101695780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101a36004803603604081101561018d57600080fd5b506001600160a01b03813516906020013561043f565b604080519115158252519081900360200190f35b6101bf61045c565b60408051918252519081900360200190f35b6101f7600480360360208110156101e757600080fd5b50356001600160a01b0316610462565b005b6101a36004803603606081101561020f57600080fd5b506001600160a01b03813581169160208101359091169060400135610622565b6102376106a9565b6040805160ff9092168252519081900360200190f35b6101a36004803603604081101561026357600080fd5b506001600160a01b0381351690602001356106b2565b6101f76004803603604081101561028f57600080fd5b506001600160a01b038135169060200135610700565b6101bf600480360360208110156102bb57600080fd5b50356001600160a01b0316610761565b61010261077c565b6101f7600480360360408110156102e957600080fd5b506001600160a01b0381351690602001356107dd565b6101a36004803603604081101561031557600080fd5b506001600160a01b03813516906020013561083e565b6101a36004803603604081101561034157600080fd5b506001600160a01b0381351690602001356108a6565b6101bf6004803603604081101561036d57600080fd5b506001600160a01b03813581169160200135166108ba565b61038d6108e5565b604080516001600160a01b039092168252519081900360200190f35b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b820191906000526020600020905b81548152906001019060200180831161041857829003601f168201915b5050505050905090565b600061045361044c6108fb565b84846108ff565b50600192915050565b60025490565b60055462010000900460ff168061047c575061047c6109eb565b8061048f5750600554610100900460ff16155b6104ca5760405162461bcd60e51b815260040180806020018281038252602e815260200180610f31602e913960400191505060405180910390fd5b60055462010000900460ff161580156104fa576005805461ff001962ff0000199091166201000017166101001790555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610577576040805162461bcd60e51b815260206004820152601660248201527f496e76616c69642063616c6c6572206f6620696e697400000000000000000000604482015290519081900360640190fd5b6001600160a01b0382166105d2576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420636f6e74726f6c6c65722061646472657373000000000000604482015290519081900360640190fd5b600580547fffffffffffffffffff0000000000000000000000000000000000000000ffffff1663010000006001600160a01b03851602179055801561061e576005805462ff0000191690555b5050565b600061062f8484846109fc565b61069f8461063b6108fb565b61069a85604051806060016040528060288152602001610f5f602891396001600160a01b038a166000908152600160205260408120906106796108fb565b6001600160a01b031681526020810191909152604001600020549190610b57565b6108ff565b5060019392505050565b60055460ff1690565b60006104536106bf6108fb565b8461069a85600160006106d06108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610bee565b600554630100000090046001600160a01b03163314610757576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610c4f565b6001600160a01b031660009081526020819052604090205490565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104355780601f1061040a57610100808354040283529160200191610435565b600554630100000090046001600160a01b03163314610834576040805162461bcd60e51b815260206004820152600e60248201526d2737ba1031b7b73a3937b63632b960911b604482015290519081900360640190fd5b61061e8282610d3f565b600061045361084b6108fb565b8461069a85604051806060016040528060258152602001610ff160259139600160006108756108fb565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610b57565b60006104536108b36108fb565b84846109fc565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600554630100000090046001600160a01b031681565b3390565b6001600160a01b0383166109445760405162461bcd60e51b8152600401808060200182810382526024815260200180610fcd6024913960400191505060405180910390fd5b6001600160a01b0382166109895760405162461bcd60e51b8152600401808060200182810382526022815260200180610ee96022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60006109f630610e3b565b15905090565b6001600160a01b038316610a415760405162461bcd60e51b8152600401808060200182810382526025815260200180610fa86025913960400191505060405180910390fd5b6001600160a01b038216610a865760405162461bcd60e51b8152600401808060200182810382526023815260200180610ea46023913960400191505060405180910390fd5b610a91838383610e41565b610ace81604051806060016040528060268152602001610f0b602691396001600160a01b0386166000908152602081905260409020549190610b57565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610afd9082610bee565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610be65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610bab578181015183820152602001610b93565b50505050905090810190601f168015610bd85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610c48576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038216610caa576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610cb660008383610e41565b600254610cc39082610bee565b6002556001600160a01b038216600090815260208190526040902054610ce99082610bee565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038216610d845760405162461bcd60e51b8152600401808060200182810382526021815260200180610f876021913960400191505060405180910390fd5b610d9082600083610e41565b610dcd81604051806060016040528060228152602001610ec7602291396001600160a01b0385166000908152602081905260409020549190610b57565b6001600160a01b038316600090815260208190526040902055600254610df39082610e46565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b3b151590565b505050565b600082821115610e9d576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b5090039056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220b212f681aae3a839369df006b7b5ca6280b5bb82909bb3e14edfc182234e45d164736f6c63430007060033\",\n  \"devdoc\": {\n    \"details\": \"value of power perpetual is expected to go down over time through the impact of funding\",\n    \"kind\": \"dev\",\n    \"methods\": {\n      \"allowance(address,address)\": {\n        \"details\": \"See {IERC20-allowance}.\"\n      },\n      \"approve(address,uint256)\": {\n        \"details\": \"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"balanceOf(address)\": {\n        \"details\": \"See {IERC20-balanceOf}.\"\n      },\n      \"burn(address,uint256)\": {\n        \"params\": {\n          \"_account\": \"account to burn from\",\n          \"_amount\": \"amount to burn\"\n        }\n      },\n      \"constructor\": {\n        \"params\": {\n          \"_name\": \"token name for ERC20\",\n          \"_symbol\": \"token symbol for ERC20\"\n        }\n      },\n      \"decimals()\": {\n        \"details\": \"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"\n      },\n      \"decreaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"\n      },\n      \"increaseAllowance(address,uint256)\": {\n        \"details\": \"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"\n      },\n      \"init(address)\": {\n        \"params\": {\n          \"_controller\": \"controller address\"\n        }\n      },\n      \"mint(address,uint256)\": {\n        \"params\": {\n          \"_account\": \"account to mint to\",\n          \"_amount\": \"amount to mint\"\n        }\n      },\n      \"name()\": {\n        \"details\": \"Returns the name of the token.\"\n      },\n      \"symbol()\": {\n        \"details\": \"Returns the symbol of the token, usually a shorter version of the name.\"\n      },\n      \"totalSupply()\": {\n        \"details\": \"See {IERC20-totalSupply}.\"\n      },\n      \"transfer(address,uint256)\": {\n        \"details\": \"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"\n      },\n      \"transferFrom(address,address,uint256)\": {\n        \"details\": \"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"\n      }\n    },\n    \"version\": 1\n  },\n  \"userdoc\": {\n    \"kind\": \"user\",\n    \"methods\": {\n      \"burn(address,uint256)\": {\n        \"notice\": \"burn wPowerPerp\"\n      },\n      \"constructor\": {\n        \"notice\": \"long power perpetual constructor\"\n      },\n      \"init(address)\": {\n        \"notice\": \"init wPowerPerp contract\"\n      },\n      \"mint(address,uint256)\": {\n        \"notice\": \"mint wPowerPerp\"\n      }\n    },\n    \"notice\": \"ERC20 Token representing wrapped long power perpetual position\",\n    \"version\": 1\n  },\n  \"storageLayout\": {\n    \"storage\": [\n      {\n        \"astId\": 616,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_balances\",\n        \"offset\": 0,\n        \"slot\": \"0\",\n        \"type\": \"t_mapping(t_address,t_uint256)\"\n      },\n      {\n        \"astId\": 622,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_allowances\",\n        \"offset\": 0,\n        \"slot\": \"1\",\n        \"type\": \"t_mapping(t_address,t_mapping(t_address,t_uint256))\"\n      },\n      {\n        \"astId\": 624,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_totalSupply\",\n        \"offset\": 0,\n        \"slot\": \"2\",\n        \"type\": \"t_uint256\"\n      },\n      {\n        \"astId\": 626,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_name\",\n        \"offset\": 0,\n        \"slot\": \"3\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 628,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_symbol\",\n        \"offset\": 0,\n        \"slot\": \"4\",\n        \"type\": \"t_string_storage\"\n      },\n      {\n        \"astId\": 630,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_decimals\",\n        \"offset\": 0,\n        \"slot\": \"5\",\n        \"type\": \"t_uint8\"\n      },\n      {\n        \"astId\": 540,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_initialized\",\n        \"offset\": 1,\n        \"slot\": \"5\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 543,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"_initializing\",\n        \"offset\": 2,\n        \"slot\": \"5\",\n        \"type\": \"t_bool\"\n      },\n      {\n        \"astId\": 10590,\n        \"contract\": \"contracts/core/WPowerPerp.sol:WPowerPerp\",\n        \"label\": \"controller\",\n        \"offset\": 3,\n        \"slot\": \"5\",\n        \"type\": \"t_address\"\n      }\n    ],\n    \"types\": {\n      \"t_address\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"address\",\n        \"numberOfBytes\": \"20\"\n      },\n      \"t_bool\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"bool\",\n        \"numberOfBytes\": \"1\"\n      },\n      \"t_mapping(t_address,t_mapping(t_address,t_uint256))\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => mapping(address => uint256))\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_mapping(t_address,t_uint256)\"\n      },\n      \"t_mapping(t_address,t_uint256)\": {\n        \"encoding\": \"mapping\",\n        \"key\": \"t_address\",\n        \"label\": \"mapping(address => uint256)\",\n        \"numberOfBytes\": \"32\",\n        \"value\": \"t_uint256\"\n      },\n      \"t_string_storage\": {\n        \"encoding\": \"bytes\",\n        \"label\": \"string\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint256\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint256\",\n        \"numberOfBytes\": \"32\"\n      },\n      \"t_uint8\": {\n        \"encoding\": \"inplace\",\n        \"label\": \"uint8\",\n        \"numberOfBytes\": \"1\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/solcInputs/30afee76cfee2d4cc1c12451e0258499.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // Ceil A to a multiple m\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(sub(add(a, m), 1), m), m);\\n    }\\n\\n    // Floor A to a multiple m\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(a, m), m);\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {EIP712} from \\\"@openzeppelin/contracts/drafts/EIP712.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\nimport {ECDSA} from \\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * Crab V2 Error Codes:\\n * C1: Caller is not timelock\\n * C2: Contract not yet initialized\\n * C3: Invalid oracle address\\n * C4: Invalid timelock address\\n * C5: Invalid ETH:WSqueeth address\\n * C6: Invalid crabMigration address\\n * C7: Invalid hedge time threshold\\n * C8: Invalid hedge price threshold\\n * C9: Cannot receive ETH\\n * C10: Caller not Crab Migration contract\\n * C11: Crab V2 already initialized\\n * C12: Squeeth contracts not shut down\\n * C13: Crab must redeemShortShutdown\\n * C14: Twap period is too short\\n * C15: Price tolerance is too high\\n * C16: Deposit exceeds strategy cap\\n * C17: Clearing Price should be below bid price\\n * C18: Clearing Price should be above offer price\\n * C19: Invalid offer signature\\n * C20: Order has expired\\n * C21: Manager Price should be greater than 0\\n * C22: Not a valid Time or Price hedge\\n * C23: Orders must take the opposite side of the hedge\\n * C24: All orders must be either buying or selling\\n * C25: Orders are not arranged properly\\n * C26: Crab contracts shut down\\n *  C27: Nonce already used.\\n */\\n\\n/**\\n * @dev CrabStrategyV2 contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    // @dev OTC price must be within this distance of the uniswap twap price\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\n\\n    // @dev OTC price tolerance cannot exceed 20%\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\n\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n    /// @dev true if CrabV2 was initialized\\n    bool public isInitialized;\\n\\n    /// @dev typehash for signed orders\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\n        keccak256(\\n            \\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\"\\n        );\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:wSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable timelock;\\n    address public immutable crabMigration;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev wSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    /// @dev store the used flag for a nonce for each address\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct Order {\\n        uint256 bidId;\\n        address trader;\\n        uint256 quantity;\\n        uint256 price;\\n        bool isBuying;\\n        uint256 expiry;\\n        uint256 nonce;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event HedgeOTCSingle(\\n        address trader,\\n        uint256 bidId,\\n        uint256 quantity,\\n        uint256 price,\\n        bool isBuying,\\n        uint256 clearingPrice\\n    );\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\n\\n    modifier onlyTimelock() {\\n        require(msg.sender == timelock, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialization() {\\n        require(isInitialized, \\\"C2\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _timelock timelock contract address\\n     * @param _crabMigration crab migration contract address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        address _timelock,\\n        address _crabMigration,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold\\n    )\\n        StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy v2\\\", \\\"Crabv2\\\")\\n        StrategyFlashSwap(_uniswapFactory)\\n        EIP712(\\\"CrabOTC\\\", \\\"2\\\")\\n    {\\n        require(_oracle != address(0), \\\"C3\\\");\\n        require(_timelock != address(0), \\\"C4\\\");\\n        require(_ethWSqueethPool != address(0), \\\"C5\\\");\\n        require(_crabMigration != address(0), \\\"C6\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        timelock = _timelock;\\n        crabMigration = _crabMigration;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"C9\\\");\\n    }\\n\\n    /**\\n     * @notice initializes the collateral ratio after the first migration\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\n     * @param _crabSharesToMint crab shares to mint\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\n     * @param _strategyCap strategy cap for crab V2\\n     */\\n    function initialize(\\n        uint256 _wSqueethToMint,\\n        uint256 _crabSharesToMint,\\n        uint256 _timeAtLastHedge,\\n        uint256 _priceAtLastHedge,\\n        uint256 _strategyCap\\n    ) external payable {\\n        require(msg.sender == crabMigration, \\\"C10\\\");\\n        require(!isInitialized, \\\"C11\\\");\\n\\n        _setStrategyCap(_strategyCap);\\n\\n        uint256 amount = msg.value;\\n\\n        _checkStrategyCap(amount, 0);\\n\\n        // store hedge data from crab V1\\n        timeAtLastHedge = _timeAtLastHedge;\\n        priceAtLastHedge = _priceAtLastHedge;\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\n\\n        isInitialized = true;\\n    }\\n\\n    /**\\n     * @notice transfer vault NFT to new contract\\n     * @dev strategy cap is set to 0 to avoid future deposits\\n     * @param _newStrategy new strategy contract address\\n     */\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\n        _setStrategyCap(0);\\n\\n        emit VaultTransferred(_newStrategy, vaultId);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\n        _setStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice set strategy cap amount\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function _setStrategyCap(uint256 _capAmount) internal {\\n        strategyCap = _capAmount;\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external afterInitialization {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     * @param _poolFee Uniswap pool fee\\n     */\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _poolFee,\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\n     * @param _poolFee Uniswap pool fee\\n\\n     */\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _poolFee,\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"C12\\\");\\n        require(hasRedeemedInShutdown, \\\"C13\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice set nonce to true\\n     * @param _nonce the number to be set true\\n     */\\n    function setNonceTrue(uint256 _nonce) external {\\n        nonces[msg.sender][_nonce] = true;\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"C14\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\n     */\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\n        // Tolerance cannot be more than 20%\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\"C15\\\");\\n\\n        otcPriceTolerance = _otcPriceTolerance;\\n\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"C16\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            // will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            // return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\n\\n            // excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @dev set nonce flag of the trader to true\\n     * @param _trader address of the signer\\n     * @param _nonce number that is to be traded only once\\n     */\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\n        require(!nonces[_trader][_nonce], \\\"C27\\\");\\n        nonces[_trader][_nonce] = true;\\n    }\\n\\n    /**\\n     * @dev view function to get the domain seperator used in signing\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev check the signer and swap tokens in the order\\n     * @param _remainingAmount quantity the manager wants to trade\\n     * @param _clearingPrice the price at which all orders are traded\\n     * @param _order a signed order to swap tokens\\n     */\\n    function _execOrder(\\n        uint256 _remainingAmount,\\n        uint256 _clearingPrice,\\n        Order memory _order\\n    ) internal {\\n        // check that order beats clearing price\\n        if (_order.isBuying) {\\n            require(_clearingPrice <= _order.price, \\\"C17\\\");\\n        } else {\\n            require(_clearingPrice >= _order.price, \\\"C18\\\");\\n        }\\n\\n        _useNonce(_order.trader, _order.nonce);\\n        bytes32 structHash = keccak256(\\n            abi.encode(\\n                _CRAB_BALANCE_TYPEHASH,\\n                _order.bidId,\\n                _order.trader,\\n                _order.quantity,\\n                _order.price,\\n                _order.isBuying,\\n                _order.expiry,\\n                _order.nonce\\n            )\\n        );\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\n        require(offerSigner == _order.trader, \\\"C19\\\");\\n        require(_order.expiry >= block.timestamp, \\\"C20\\\");\\n\\n        // adjust quantity for partial fills\\n        if (_remainingAmount < _order.quantity) {\\n            _order.quantity = _remainingAmount;\\n        }\\n        // weth clearing price for the order\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\n\\n        if (_order.isBuying) {\\n            // trader sends weth and receives oSQTH\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\n            IWETH9(weth).withdraw(wethAmount);\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n        } else {\\n            // trader sends oSQTH and receives weth\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n            // wrap it\\n            IWETH9(weth).deposit{value: wethAmount}();\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\n        }\\n\\n        emit HedgeOTCSingle(\\n            _order.trader, // market maker\\n            _order.bidId,\\n            _order.quantity, // order oSQTH quantity\\n            _order.price, // order price\\n            _order.isBuying, // order direction\\n            _clearingPrice // executed price for order\\n        );\\n    }\\n\\n    /**\\n     * @dev hedge function to reduce delta using an array of signed orders\\n     * @param _totalQuantity quantity the manager wants to trade\\n     * @param _clearingPrice clearing price in weth\\n     * @param _isHedgeBuying direction of hedge trade\\n     * @param _orders an array of signed order to swap tokens\\n     */\\n    function hedgeOTC(\\n        uint256 _totalQuantity,\\n        uint256 _clearingPrice,\\n        bool _isHedgeBuying,\\n        Order[] memory _orders\\n    ) external onlyOwner afterInitialization {\\n        require(_clearingPrice > 0, \\\"C21\\\");\\n        require(_isTimeHedge() || _isPriceHedge(), \\\"C22\\\");\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = _clearingPrice;\\n\\n        uint256 remainingAmount = _totalQuantity;\\n        uint256 prevPrice = _orders[0].price;\\n        uint256 currentPrice = _orders[0].price;\\n        bool isOrderBuying = _orders[0].isBuying;\\n        require(_isHedgeBuying != isOrderBuying, \\\"C23\\\");\\n\\n        // iterate through order array and execute if valid\\n        for (uint256 i; i < _orders.length; ++i) {\\n            currentPrice = _orders[i].price;\\n            require(_orders[i].isBuying == isOrderBuying, \\\"C24\\\");\\n            if (_isHedgeBuying) {\\n                require(currentPrice >= prevPrice, \\\"C25\\\");\\n            } else {\\n                require(currentPrice <= prevPrice, \\\"C25\\\");\\n            }\\n            prevPrice = currentPrice;\\n\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\n\\n            if (remainingAmount > _orders[i].quantity) {\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\n            } else {\\n                break;\\n            }\\n        }\\n\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\n    }\\n\\n    /**\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\n     * @param _price clearing price provided by manager\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\n     */\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\n        // Get twap\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n\\n        if (_isHedgeBuying) {\\n            require(\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\n                \\\"Price too high relative to Uniswap twap.\\\"\\n            );\\n        } else {\\n            require(\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\n                \\\"Price too low relative to Uniswap twap.\\\"\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\n        require(!isShutdown, \\\"C26\\\");\\n\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n        );\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     */\\n    function _isTimeHedge() internal view returns (bool) {\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge() internal view returns (bool) {\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge() external view returns (bool) {\\n        return _isPriceHedge();\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkTimeHedge() external view returns (bool) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/drafts/EIP712.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = _getChainId();\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n        return keccak256(\\n            abi.encode(\\n                typeHash,\\n                name,\\n                version,\\n                _getChainId(),\\n                address(this)\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/cryptography/ECDSA.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        // Check the signature length\\n        if (signature.length != 65) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        }\\n\\n        // Divide the signature in r, s and v variables\\n        bytes32 r;\\n        bytes32 s;\\n        uint8 v;\\n\\n        // ecrecover takes the signature parameters, and the only way to get them\\n        // currently is to use assembly.\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            r := mload(add(signature, 0x20))\\n            s := mload(add(signature, 0x40))\\n            v := byte(0, mload(add(signature, 0x60)))\\n        }\\n\\n        return recover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n        require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n        return signer;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * replicates the behavior of the\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n     * JSON-RPC method.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\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) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/strategy/CrabHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {ICrabStrategyV2} from \\\"../interfaces/ICrabStrategyV2.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {StrategySwap} from \\\"./helper/StrategySwap.sol\\\";\\n\\n/**\\n * @dev CrabHelper contract\\n * @notice Contract for Crab helper functions\\n * @author Opyn team\\n */\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\n    using Address for address payable;\\n\\n    address public immutable crab;\\n    address public immutable weth;\\n\\n    event FlashDepositERC20(\\n        address indexed depositor,\\n        address depositedERC20,\\n        uint256 depositedAmount,\\n        uint256 depositedEthAmount,\\n        uint256 crabAmount,\\n        uint256 returnedEth\\n    );\\n\\n    event FlashWithdrawERC20(\\n        address indexed withdrawer,\\n        address withdrawnERC20,\\n        uint256 withdrawnAmount,\\n        uint256 withdrawnEthAmount,\\n        uint256 crabAmount\\n    );\\n\\n    /**\\n     * @notice constructor\\n     * @param _crab address of crabV2 contract\\n     * @param _swapRouter address of Uniswap swap router\\n     */\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\n        require(_crab != address(0), \\\"Invalid crab address\\\");\\n\\n        crab = _crab;\\n        weth = ICrabStrategyV2(_crab).weth();\\n    }\\n\\n    /**\\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\\n     * @param _ethToDeposit amount of ETH to deposit\\n     * @param _amountIn amount of ERC20 token to swap for weth\\n     * @param _minEthToGet min amount of ETH to receive in the swap\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     * @param _tokenIn ERC20 token to pay\\n     */\\n    function flashDepositERC20(\\n        uint256 _ethToDeposit,\\n        uint256 _amountIn,\\n        uint256 _minEthToGet,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee,\\n        address _tokenIn\\n    ) external nonReentrant {\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\\n\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\\n\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\n\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\n\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\n\\n        if (address(this).balance > 0) {\\n            payable(msg.sender).sendValue(address(this).balance);\\n        }\\n    }\\n\\n    /**\\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\\n     * @param _crabAmount amount of crab shares to withdraw\\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\\n     * @param _tokenOut ERC20 token to receive\\n     * @param _minAmountOut min amount of ERC20 to receive\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     */\\n    function flashWithdrawERC20(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        address _tokenOut,\\n        uint256 _minAmountOut,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee\\n    ) external nonReentrant {\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\n\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\\n\\n        uint256 ethBalance = address(this).balance;\\n        IWETH9(weth).deposit{value: ethBalance}();\\n        uint256 tokenReceived = _swapExactInputSingle(\\n            weth,\\n            _tokenOut,\\n            address(this),\\n            msg.sender,\\n            ethBalance,\\n            _minAmountOut,\\n            _erc20Fee\\n        );\\n\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crab, \\\"Cannot receive eth\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/ICrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\ninterface ICrabStrategyV2 {\\n    function wPowerPerp() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\\n\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/strategy/helper/StrategySwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract StrategySwap {\\n    ISwapRouter public immutable swapRouter;\\n\\n    constructor(address _swapRouter) {\\n        require(_swapRouter != address(0), \\\"invalid swap router address\\\");\\n        swapRouter = ISwapRouter(_swapRouter);\\n    }\\n\\n    /**\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _from from which user we are selling\\n     * @param _to Recipient to get the tokens\\n     * @param _amountIn Exact amount to sell\\n     * @param _minAmountOut Minimum amount to be paid\\n     * @param _fee pool fee\\n     * @return amountOut The amount of WETH9 received.\\n     */\\n    function _swapExactInputSingle(\\n        address _tokenIn,\\n        address _tokenOut,\\n        address _from,\\n        address _to,\\n        uint256 _amountIn,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) internal returns (uint256 amountOut) {\\n        // _from must approve this contract\\n\\n        // Transfer the specified amount of tokenIn to this contract.\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\n\\n        // Approve the router to spend tokenIn.\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\n\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\n            tokenIn: _tokenIn,\\n            tokenOut: _tokenOut,\\n            fee: _fee,\\n            recipient: _to,\\n            deadline: block.timestamp,\\n            amountIn: _amountIn,\\n            amountOutMinimum: _minAmountOut,\\n            sqrtPriceLimitX96: 0\\n        });\\n\\n        // The call to `exactInputSingle` executes the swap.\\n        amountOut = swapRouter.exactInputSingle(params);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabMigration.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport {IEulerExec, IDToken} from \\\"../interfaces/IEuler.sol\\\";\\nimport {WETH9} from \\\"../external/WETH9.sol\\\";\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// contract\\nimport {CrabStrategyV2} from \\\"./CrabStrategyV2.sol\\\";\\nimport {CrabStrategy} from \\\"./CrabStrategy.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * Migration Error Codes:\\n * M1: Migration already happened\\n * M2: Migration has not yet happened\\n * M3: msg.sender is not Euler Mainnet Contract\\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\\n * M5: Can't withdraw more than you own\\n * M6: Not enough ETH to repay the loan\\n * M7: Invalid crabV2 address\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\n * M10: Wrong migration function, use flashMigrateFromV1toV2\\n * M11: crabV2 address not yet set\\n */\\n\\n/**\\n * @dev CrabMigration contract\\n * @notice Contract for Migrating from Crab V1 to Crab V2\\n * @author Opyn team\\n */\\ncontract CrabMigration is Ownable {\\n    using SafeERC20 for IERC20;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    mapping(address => uint256) public sharesDeposited;\\n    bool public isMigrated;\\n\\n    address payable public crabV1;\\n    address payable public crabV2;\\n    address public immutable euler;\\n    address public immutable weth;\\n\\n    address immutable EULER_MAINNET;\\n    address immutable dToken;\\n    address immutable wPowerPerp;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    struct BatchMigrate {\\n        uint256 strategyCap;\\n    }\\n\\n    struct FlashMigrateV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFee;\\n    }\\n\\n    struct FlashMigrateAndBuyV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 withdrawMaxEthToPay;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFeeFlashDeposit;\\n    }\\n\\n    enum FLASH_SOURCE {\\n        BATCH_MIGRATE,\\n        FLASH_MIGRATE_V1_TO_V2,\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\n    }\\n\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\\n\\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\\n\\n    modifier beforeMigration() {\\n        require(!isMigrated, \\\"M1\\\");\\n        _;\\n    }\\n\\n    modifier afterMigration() {\\n        require(isMigrated, \\\"M2\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialized() {\\n        require(crabV2 != address(0), \\\"M11\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice migration constructor\\n     * @param _crabV1 address of crab V1\\n     * @param _weth address of weth\\n     * @param _eulerExec address of euler exec contract\\n     * @param _dToken address of euler liability token\\n     * @param _eulerMainnet address of euler deployment on mainnet\\n     */\\n    constructor(\\n        address payable _crabV1,\\n        address _weth,\\n        address _eulerExec,\\n        address _dToken,\\n        address _eulerMainnet\\n    ) {\\n        require(_eulerExec != address(0), \\\"invalid _eulerExec address\\\");\\n        require(_dToken != address(0), \\\"invalid _dToken address\\\");\\n        require(_eulerMainnet != address(0), \\\"invalid _eulerMainnet address\\\");\\n        require(_weth != address(0), \\\"invalid _weth address\\\");\\n        require(_crabV1 != address(0), \\\"invalid _crabv1 address\\\");\\n        require(IDToken(_dToken).underlyingAsset() == _weth, \\\"dToken underlying asset should be weth\\\");\\n\\n        crabV1 = _crabV1;\\n        euler = _eulerExec;\\n        EULER_MAINNET = _eulerMainnet;\\n        weth = _weth;\\n        dToken = _dToken;\\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\\n    }\\n\\n    /**\\n     * @notice set the crabV2 address\\n     * @param _crabV2 address of crab V2\\n     */\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\n        require(_crabV2 != address(0), \\\"M7\\\");\\n        crabV2 = _crabV2;\\n    }\\n\\n    /**\\n     * @notice deposit crab V1 shares in the pool for migration\\n     * @param _amount amount of crabV1 shares to deposit\\n     */\\n    function depositV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] += _amount;\\n\\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\\n\\n        emit DepositV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice withdraw crab V1 shares in the pool before migration\\n     * @param _amount amount of V1 shares to withdraw\\n     */\\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\\n\\n        emit WithdrawV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\\n     * the V2 contract at the same collateral ratio as the V1 contract\\n     * @param _strategyCap strategy cap in ETH\\n     */\\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\\n        // 1. update isMigrated\\n        isMigrated = true;\\n\\n        // 2. flash floan eth from euler eq to amt\\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: amountEthToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Euler callback function\\n     * @param encodedData callback data\\n     */\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\n        require(msg.sender == EULER_MAINNET, \\\"M3\\\");\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        // 1. borrow weth\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\n        WETH9(weth).withdraw(data.amountToBorrow);\\n\\n        // 2. callback\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\n\\n        // 3. repay the weth\\n        WETH9(weth).deposit{value: data.amountToBorrow}();\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     * @notice callback function for flash actions\\n     * @param _initiator address of original function caller\\n     * @param _amount  amount to pay back for flashswap\\n     * @param _callSource identifier for which function triggered callback\\n     * @param _calldata arbitrary data attached to callback\\n\\n     */\\n    function _flashCallback(\\n        address _initiator,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\\n\\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n\\n            // 2. mint osqth in crab V2\\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\\n                wSqueethToMint,\\n                crabV1Balance,\\n                timeAtLastHedge,\\n                priceAtLastHedge,\\n                data.strategyCap\\n            );\\n\\n            // 3. call withdraw from crab V1\\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\n\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n\\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\\n\\n            // flash deposit remaining ETH, otherwise refund\\n            // if CR1 = CR2 ethToFlashDeposit should be 0\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFee\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n            // send back V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\n            uint256 initialCrabAmount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\\n\\n            // find crab amount for contract's sqth balance\\n            // remaining crab can be withdrawn using flash withdraw\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\n\\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\\n\\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\n            require(address(this).balance >= _amount, \\\"M6\\\");\\n\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFeeFlashDeposit\\n                );\\n            }\\n\\n            uint256 crabV2ToTransfer = CrabStrategyV2(crabV2).balanceOf(address(this)).sub(initialCrabAmount);\\n\\n            // send V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2ToTransfer);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2ToTransfer, excessEth.sub(_amount));\\n\\n            // send back the excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares\\n     */\\n    function claimV2Shares() external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        sharesDeposited[msg.sender] = 0;\\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares and flash withdraw from crab V2\\n     * @param _amountToWithdraw V2 shares to claim\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee Uniswap pool fee for flash withdraw\\n     */\\n    function claimAndWithdraw(\\n        uint256 _amountToWithdraw,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        require(_amountToWithdraw <= amountV1Deposited, \\\"M5\\\");\\n\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\\n\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\n\\n        // send eth to user\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice view details of flash migration for specified amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function flashMigrationDetails(uint256 _v1Shares)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return _flashMigrationDetails(_v1Shares);\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\n     * @param _poolFee uniswap pool fee for flash deposit\\n     */\\n    function flashMigrateFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(isFlashOnlyMigrate, \\\"M9\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: ethNeededForV2,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateV1toV2({\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFee: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\\n     */\\n    function flashMigrateAndWithdrawFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint256 _ethToBorrow,\\n        uint256 _withdrawMaxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(!isFlashOnlyMigrate, \\\"M10\\\");\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\"M8\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: _ethToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateAndBuyV1toV2({\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFeeFlashDeposit: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice get migration details for given amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function _flashMigrationDetails(uint256 _v1Shares)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\\n\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\\n\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \\\"M4\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IEuler.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\ninterface IEulerExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IDToken {\\n    function underlyingAsset() external view returns (address);\\n\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\"\n    },\n    \"contracts/external/WETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\n\\ncontract WETH9 {\\n    string public name = \\\"Wrapped Ether\\\";\\n    string public symbol = \\\"WETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        payable(msg.sender).transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockEulerDToken.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockEulerDToken {\\n    ERC20 weth;\\n\\n    constructor(address _weth) {\\n        weth = ERC20(_weth);\\n    }\\n\\n    function borrow(uint256, uint256 amount) external {\\n        weth.transfer(msg.sender, amount);\\n    }\\n\\n    function repay(uint256, uint256 amount) external {\\n        weth.transferFrom(msg.sender, address(this), amount);\\n    }\\n\\n    function underlyingAsset() external view returns (address) {\\n        return address(weth);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockCrab.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockCrab is ERC20 {\\n    address operator;\\n    uint256 vaultId;\\n    uint256 collateral;\\n    uint256 short;\\n    address public wPowerPerp;\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    function setVaultDetails(\\n        uint256 _vaultId,\\n        uint256 _collateral,\\n        uint256 _short\\n    ) external {\\n        vaultId = _vaultId;\\n        collateral = _collateral;\\n        short = _short;\\n    }\\n\\n    function getVaultDetails()\\n        external\\n        view\\n        returns (\\n            address,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return (operator, vaultId, collateral, short);\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"C3\\\");\\n\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/solcInputs/5f450d03d2b8109eaf06de68c57d8c2b.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 6.9 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnOnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid power token controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, all uint to uint256, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    // strategy will only allow hedging if collateral to trade is at least 0.1% of the total strategy collateral\\n    uint256 public constant DELTA_HEDGE_THRESHOLD = 1e15;\\n\\n    uint256 public strategyCap;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public immutable hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public immutable hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public immutable auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for end sell auction (scaled 1e18)\\n    uint256 public immutable minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public immutable maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n    uint256 public auctionStartTime;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool public hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount, uint256 oldCapAmount);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"auction min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid auction min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"auction max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     * @return wSqueethToMint minted amount of wSqueeth\\n     * @return depositorCrabAmount minted amount of strategy token\\n     */\\n    function deposit() external payable nonReentrant returns (uint256, uint256) {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external payable nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts are not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Strategy has not redeemed vault proceeds\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @param _minWSqueeth minimum WSqueeth amount of profit if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount of profit if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        require(block.timestamp >= auctionTriggerTime, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime timestamp where auction started\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime alleged timestamp where auction was triggered\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        return (isTimeHedgeAllowed, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @dev _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        uint256 oldCap = strategyCap;\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount, oldCap);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price greater than max accepted price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price greater than min accepted price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"can not execute hedging trade as auction type changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(\\n                totalSupply() == 0,\\n                \\\"Crab strategy shut down due to full liquidation or shutdown of squeeth contracts\\\"\\n            );\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + TWAP_PERIOD,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        uint256 collateralRatioToHedge = targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta);\\n\\n        require(collateralRatioToHedge > DELTA_HEDGE_THRESHOLD, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 825\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/solcInputs/6176622d73f0107e1e6916638dbba9b9.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0 <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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0 <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    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) public payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) public payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // Ceil A to a multiple m\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(sub(add(a, m), 1), m), m);\\n    }\\n\\n    // Floor A to a multiple m\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(a, m), m);\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {EIP712} from \\\"@openzeppelin/contracts/drafts/EIP712.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\nimport {Counters} from \\\"@openzeppelin/contracts/utils/Counters.sol\\\";\\nimport {ECDSA} from \\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * @dev CrabStrategyV2 contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\n    using Counters for Counters.Counter;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    // @dev OTC price must be within this distance of the uniswap twap price\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\n\\n    // @dev OTC price tolerance cannot exceed 20%\\n    uint256 public maxOTCPriceTolerance = 2e17; // 20%\\n\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n    /// @dev true if CrabV2 was initialized\\n    bool public isInitialized;\\n\\n    /// @dev typehash for signed orders\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\n        keccak256(\\n            \\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\"\\n        );\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n    address public immutable timelock;\\n    address public immutable crabMigration;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    /// @dev store the current nonce for each address\\n    mapping(address => Counters.Counter) private _nonces;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct Order {\\n        uint256 bidId;\\n        address trader;\\n        uint256 quantity;\\n        uint256 price;\\n        bool isBuying;\\n        uint256 expiry;\\n        uint256 nonce;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event HedgeOTC(address trader, uint256 quantity, uint256 price, bool isBuying, uint256 clearingPrice);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\n\\n    modifier onlyTimelock() {\\n        require(msg.sender == timelock, \\\"Caller is not timelock\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialization() {\\n        require(isInitialized, \\\"Contract not yet initialized\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        address _timelock,\\n        address _crabMigration,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold\\n    )\\n        StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy v2\\\", \\\"Crabv2\\\")\\n        StrategyFlashSwap(_uniswapFactory)\\n        EIP712(\\\"CrabOTC\\\", \\\"2\\\")\\n    {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_timelock != address(0), \\\"invalid timelock address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_crabMigration != address(0), \\\"invalid crabMigration address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n        timelock = _timelock;\\n        crabMigration = _crabMigration;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice initializes the collateral ratio upon the first migration\\n     */\\n    function initialize(\\n        uint256 _wSqueethToMint,\\n        uint256 _crabSharesToMint,\\n        uint256 _timeAtLastHedge,\\n        uint256 _priceAtLastHedge\\n    ) external payable {\\n        require(msg.sender == crabMigration, \\\"not Crab Migration contract\\\");\\n        require(!isInitialized, \\\"Crab V2 already initialized\\\");\\n\\n        uint256 amount = msg.value;\\n        uint256 strategyDebt;\\n        uint256 strategyCollateral;\\n\\n        _checkStrategyCap(amount, strategyCollateral);\\n\\n        require((strategyDebt == 0 && strategyCollateral == 0), \\\"C5\\\");\\n        // store hedge data from crab v1\\n        timeAtLastHedge = _timeAtLastHedge;\\n        priceAtLastHedge = _priceAtLastHedge;\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\n\\n        isInitialized = true;\\n    }\\n\\n    /**\\n     * @notice Tranfer vault NFT to new contract\\n     * @dev strategy cap is set to 0 to avoid future deposits.\\n     */\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\n        _setStrategyCap(0);\\n\\n        emit VaultTransferred(_newStrategy, vaultId);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        _setStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice set strategy cap amount\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function _setStrategyCap(uint256 _capAmount) internal {\\n        strategyCap = _capAmount;\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external afterInitialization {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable afterInitialization nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external afterInitialization nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable afterInitialization nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external afterInitialization nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external afterInitialization nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\n     */\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\n        // Tolerance cannot be more than 20%\\n        require(_otcPriceTolerance <= maxOTCPriceTolerance, \\\"price tolerance is too high\\\");\\n\\n        otcPriceTolerance = _otcPriceTolerance;\\n\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @dev increment current nonce of the address\\n     * @param _owner address of signer\\n     * @return current the current nonce of the address\\n     */\\n    function _useNonce(address _owner) internal returns (uint256 current) {\\n        Counters.Counter storage nonce = _nonces[_owner];\\n        current = nonce.current();\\n        nonce.increment();\\n    }\\n\\n    /*\\n     * @notice user can increment their own nonce to cancel previous orders\\n     * @return new nonce for user\\n     */\\n    function incrementNonce() external returns (uint256 current) {\\n        Counters.Counter storage nonce = _nonces[msg.sender];\\n        nonce.increment();\\n        current = nonce.current();\\n    }\\n\\n    /**\\n     * @dev get current nonce of the address\\n     * @param _owner address of signer\\n     * @return current the current nonce of the address\\n     */\\n    function nonces(address _owner) external view returns (uint256) {\\n        return _nonces[_owner].current();\\n    }\\n\\n    /**\\n     * @dev view function to get the domain seperator used in signing\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev check the signer and swap tokens in the order\\n     * @param _remainingAmount quantity the manager wants to sell\\n     * @param _clearingPrice the price at which the manager is buying\\n     * @param _order a signed order to swap tokens\\n     */\\n    function _execOrder(\\n        uint256 _remainingAmount,\\n        uint256 _clearingPrice,\\n        Order memory _order\\n    ) internal {\\n        // Check order beats clearing price\\n        if (_order.isBuying) {\\n            require(_clearingPrice <= _order.price, \\\"Clearing Price should be below bid price\\\");\\n        } else {\\n            require(_clearingPrice >= _order.price, \\\"Clearing Price should be above offer price\\\");\\n        }\\n\\n        bytes32 structHash = keccak256(\\n            abi.encode(\\n                _CRAB_BALANCE_TYPEHASH,\\n                _order.bidId,\\n                _order.trader,\\n                _order.quantity,\\n                _order.price,\\n                _order.isBuying,\\n                _order.expiry,\\n                _useNonce(_order.trader)\\n            )\\n        );\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\n        require(offerSigner == _order.trader, \\\"Invalid offer signature\\\");\\n        require(_order.expiry >= block.timestamp, \\\"Order has expired\\\");\\n\\n        //adjust quantity for partial fills\\n        if (_remainingAmount < _order.quantity) {\\n            _order.quantity = _remainingAmount;\\n        }\\n        // weth clearing price for the order\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(1e18);\\n\\n        if (_order.isBuying) {\\n            // trader sends weth and receives oSQTH\\n            IERC20(weth).transferFrom(_order.trader, address(this), wethAmount);\\n            IWETH9(weth).withdraw(wethAmount);\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n        } else {\\n            // trader sends oSQTH and receives weth\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n            //wrap it\\n            IWETH9(weth).deposit{value: wethAmount}();\\n            IERC20(weth).transfer(_order.trader, wethAmount);\\n        }\\n\\n        emit HedgeOTC(\\n            _order.trader, // market maker\\n            _order.quantity, // order oSQTH quantity\\n            _order.price, // order price\\n            _order.isBuying, // order direction\\n            _clearingPrice // executed price for order\\n        );\\n    }\\n\\n    /**\\n     * @dev hedge function to reduce delta using an array of signed orders\\n     * @param _totalQuantity quantity the manager wants to trade\\n     * @param _clearingPrice clearing price in weth\\n     * @param _isHedgeBuying direction of hedge trade\\n     * @param _orders an array of signed order to swap tokens\\n     */\\n    function hedgeOTC(\\n        uint256 _totalQuantity,\\n        uint256 _clearingPrice,\\n        bool _isHedgeBuying,\\n        Order[] memory _orders\\n    ) external onlyOwner afterInitialization {\\n        require(_clearingPrice > 0, \\\"Manager Price should be greater than 0\\\");\\n        require(_isTimeHedge() || _isPriceHedge(), \\\"Time or Price is not within range\\\");\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = _clearingPrice;\\n\\n        uint256 remainingAmount = _totalQuantity;\\n        uint256 prevPrice = _orders[0].price;\\n        uint256 currentPrice = _orders[0].price;\\n        bool isOrderBuying = _orders[0].isBuying;\\n        require(_isHedgeBuying != isOrderBuying, \\\"Orders must be buying when hedge is selling\\\");\\n\\n        for (uint256 i = 0; i < _orders.length; i++) {\\n            currentPrice = _orders[i].price;\\n            require(_orders[i].isBuying == isOrderBuying, \\\"All orders must be either buying or selling\\\");\\n            if (_isHedgeBuying) {\\n                require(currentPrice >= prevPrice, \\\"Orders are not arranged properly\\\");\\n            } else {\\n                require(currentPrice <= prevPrice, \\\"Orders are not arranged properly\\\");\\n            }\\n            prevPrice = currentPrice;\\n\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\n\\n            if (remainingAmount >= _orders[i].quantity) {\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\n            } else {\\n                break;\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\n     * @param _price clearing price provided by manager\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\n     */\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\n        // Get twap\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n\\n        if (_isHedgeBuying) {\\n            require(\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\n                \\\"Price too high relative to Uniswap twap.\\\"\\n            );\\n        } else {\\n            require(\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\n                \\\"Price too low relative to Uniswap twap.\\\"\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\n        require(!isShutdown, \\\"Crab contracts shut down\\\");\\n\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n        );\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     */\\n    function _isTimeHedge() internal view returns (bool) {\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge() internal view returns (bool) {\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge() external view returns (bool) {\\n        return _isPriceHedge();\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkTimeHedge() external view returns (bool) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/drafts/EIP712.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = _getChainId();\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n        return keccak256(\\n            abi.encode(\\n                typeHash,\\n                name,\\n                version,\\n                _getChainId(),\\n                address(this)\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Counters.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../math/SafeMath.sol\\\";\\n\\n/**\\n * @title Counters\\n * @author Matt Condon (@shrugs)\\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\\n *\\n * Include with `using Counters for Counters.Counter;`\\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\\n * directly accessed.\\n */\\nlibrary Counters {\\n    using SafeMath for uint256;\\n\\n    struct Counter {\\n        // This variable should never be directly accessed by users of the library: interactions must be restricted to\\n        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\\n        // this feature: see https://github.com/ethereum/solidity/issues/4637\\n        uint256 _value; // default: 0\\n    }\\n\\n    function current(Counter storage counter) internal view returns (uint256) {\\n        return counter._value;\\n    }\\n\\n    function increment(Counter storage counter) internal {\\n        // The {SafeMath} overflow check can be skipped here, see the comment at the top\\n        counter._value += 1;\\n    }\\n\\n    function decrement(Counter storage counter) internal {\\n        counter._value = counter._value.sub(1);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/cryptography/ECDSA.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        // Check the signature length\\n        if (signature.length != 65) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        }\\n\\n        // Divide the signature in r, s and v variables\\n        bytes32 r;\\n        bytes32 s;\\n        uint8 v;\\n\\n        // ecrecover takes the signature parameters, and the only way to get them\\n        // currently is to use assembly.\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            r := mload(add(signature, 0x20))\\n            s := mload(add(signature, 0x40))\\n            v := byte(0, mload(add(signature, 0x60)))\\n        }\\n\\n        return recover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n        require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n        return signer;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * replicates the behavior of the\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n     * JSON-RPC method.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\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) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabMigration.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport {IEulerExec, IDToken} from \\\"../interfaces/IEuler.sol\\\";\\nimport {WETH9} from \\\"../external/WETH9.sol\\\";\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// contract\\nimport {CrabStrategyV2} from \\\"./CrabStrategyV2.sol\\\";\\nimport {CrabStrategy} from \\\"./CrabStrategy.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * Migration Error Codes:\\n * M1: Crab V2 Address already set\\n * M2: Migration already happened\\n * M3: Migration has not yet happened\\n * M4: msg.sender is not Euler Mainnet Contract\\n * M5: msg. sender cannot send ETH\\n * M6: Can't withdraw more than you own\\n * M7: Not enough ETH to repay the loan\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\n * M9: invalid crabV2 address\\n * M10: crab v2 address not yet set\\n * M11: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\n * M12: Wrong migration function, use flashMigrateFromV1toV2\\n */\\n\\n/**\\n * @dev CrabMigration contract\\n * @notice Contract for Migrating from Crab v1 to Crab v2\\n * @author Opyn team\\n */\\ncontract CrabMigration is Ownable {\\n    using SafeERC20 for IERC20;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    mapping(address => uint256) public sharesDeposited;\\n    bool public isMigrated;\\n    CrabStrategy public crabV1;\\n    CrabStrategyV2 public crabV2;\\n    IEulerExec public euler;\\n    WETH9 weth;\\n\\n    uint256 public totalCrabV1SharesMigrated;\\n    uint256 public totalCrabV2SharesReceived;\\n    address immutable EULER_MAINNET;\\n    address immutable dToken;\\n    address immutable wPowerPerp;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    struct FlashMigrateV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 crabV1ToWithdraw;\\n    }\\n\\n    struct FlashMigrateAndBuyV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 withdrawMaxEthToPay;\\n        uint256 crabV1ToWithdraw;\\n    }\\n\\n    enum FLASH_SOURCE {\\n        BATCH_MIGRATE,\\n        FLASH_MIGRATE_V1_TO_V2,\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\n    }\\n\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\n\\n    modifier beforeMigration() {\\n        require(!isMigrated, \\\"M2\\\");\\n        _;\\n    }\\n\\n    modifier afterMigration() {\\n        require(isMigrated, \\\"M3\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialized() {\\n        require(address(crabV2) != address(0), \\\"M8\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice migration constructor\\n     * @param _crabV1 address of crab v1\\n     * @param _weth address of weth\\n     * @param _eulerExec address of euler exec contract\\n     * @param _dToken address of euler deposit token\\n     * @param _eulerMainnet address of euler deployment on mainnet\\n     */\\n    constructor(\\n        address payable _crabV1,\\n        address _weth,\\n        address _eulerExec,\\n        address _dToken,\\n        address _eulerMainnet\\n    ) {\\n        crabV1 = CrabStrategy(_crabV1);\\n        euler = IEulerExec(_eulerExec);\\n        EULER_MAINNET = _eulerMainnet;\\n        weth = WETH9(_weth);\\n        dToken = _dToken;\\n        wPowerPerp = crabV1.wPowerPerp();\\n    }\\n\\n    /**\\n     * @notice set the crabV2 address\\n     * @param _crabV2 address of crab v2\\n     */\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\n        require(address(crabV2) == address(0), \\\"M1\\\");\\n        require(_crabV2 != address(0), \\\"M9\\\");\\n        crabV2 = CrabStrategyV2(_crabV2);\\n    }\\n\\n    /**\\n     * @notice allows users to deposit their crab v1 shares in the pool for migration\\n     */\\n    function depositV1Shares(uint256 amount) external afterInitialized beforeMigration {\\n        sharesDeposited[msg.sender] += amount;\\n        totalCrabV1SharesMigrated += amount;\\n        crabV1.transferFrom(msg.sender, address(this), amount);\\n    }\\n\\n    /**\\n     * @notice the owner batch migrates all the crab v1 shares in this contract to crab v2 and initializes\\n     * the v2 contract at the same collateral ratio as the v1 contract.\\n     */\\n    function batchMigrate() external onlyOwner afterInitialized beforeMigration {\\n        // 1. update isMigrated\\n        isMigrated = true;\\n\\n        // 2. flash floan eth from euler eq to amt\\n        uint256 crabV1Balance = crabV1.balanceOf(address(this));\\n        uint256 crabV1Supply = crabV1.totalSupply();\\n        (, , uint256 totalCollateral, ) = crabV1.getVaultDetails();\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\n        bytes memory data;\\n        euler.deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: amountEthToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\n                    callData: data\\n                })\\n            )\\n        );\\n\\n        // 3. record totalV2Shares\\n        totalCrabV2SharesReceived = crabV2.balanceOf(address(this));\\n    }\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\n        require(msg.sender == EULER_MAINNET, \\\"M4\\\");\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        // 1. Borrow weth\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\n        weth.withdraw(data.amountToBorrow);\\n\\n        // 2. Callback\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\n\\n        // 4. Repay the weth:\\n        weth.deposit{value: data.amountToBorrow}();\\n        weth.approve(EULER_MAINNET, type(uint256).max);\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\n            uint256 crabV1Balance = crabV1.balanceOf(address(this));\\n\\n            // 2. mint osqth in crab v2\\n            uint256 wSqueethToMint = crabV1.getWsqueethFromCrabAmount(crabV1Balance);\\n            uint256 timeAtLastHedge = crabV1.timeAtLastHedge();\\n            uint256 priceAtLastHedge = crabV1.priceAtLastHedge();\\n            crabV2.initialize{value: _amount}(\\n                wSqueethToMint,\\n                totalCrabV1SharesMigrated,\\n                timeAtLastHedge,\\n                priceAtLastHedge\\n            );\\n\\n            // 3. call withdraw from crab v1\\n            IERC20(wPowerPerp).approve(address(crabV1), type(uint256).max);\\n            crabV1.approve(address(crabV1), crabV1Balance);\\n            crabV1.withdraw(crabV1Balance);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\n\\n            crabV2.deposit{value: _amount}();\\n\\n            crabV1.transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n\\n            IERC20(wPowerPerp).approve(address(crabV1), data.v1oSqthToPay);\\n            crabV1.withdraw(data.crabV1ToWithdraw);\\n\\n            // Flash deposit remaining ETH, if user said so. Else return back the ETH. If CR1 = CR2 ethToFlashDeposit should be 0\\n            if (data.ethToFlashDeposit > 0) {\\n                crabV2.flashDeposit{value: address(this).balance.sub(_amount)}(data.ethToFlashDeposit);\\n            }\\n\\n            // Sent back the V2 tokens to the user\\n            crabV2.transfer(_initiator, crabV2.balanceOf(address(this)));\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            // Sent back the excess ETH\\n            if (address(this).balance > _amount) {\\n                payable(_initiator).sendValue(address(this).balance.sub(_amount));\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\n            (, , , uint256 v1Short) = crabV1.getVaultDetails();\\n\\n            crabV1.transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n            crabV2.deposit{value: _amount}();\\n\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\n            IERC20(wPowerPerp).approve(address(crabV1), oSqthToPay);\\n\\n            // Find crab amount for contract's sqth balance. Remaining crab sould be withdrawn using flash withdraw\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(crabV1.totalSupply()).rdiv(v1Short);\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\n\\n            crabV1.withdraw(crabV1ToWithdraw);\\n\\n            crabV1.flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\n            require(address(this).balance >= _amount, \\\"M7\\\");\\n\\n            if (data.ethToFlashDeposit > 0) {\\n                crabV2.flashDeposit{value: address(this).balance.sub(_amount)}(data.ethToFlashDeposit);\\n            }\\n\\n            // Sent back the V2 tokens to the user\\n            crabV2.transfer(_initiator, crabV2.balanceOf(address(this)));\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            // Sent back the excess ETH\\n            if (address(this).balance > _amount) {\\n                payable(_initiator).sendValue(address(this).balance.sub(_amount));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice allows users to claim their amount of crab v2 shares\\n     */\\n    function claimV2Shares() external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        sharesDeposited[msg.sender] = 0;\\n        uint256 amountV2ToTransfer = amountV1Deposited.wmul(totalCrabV2SharesReceived).wdiv(totalCrabV1SharesMigrated);\\n        crabV2.transfer(msg.sender, amountV2ToTransfer);\\n    }\\n\\n    /**\\n     * @notice allows users to claim crabV2 shares and flash withdraw from crabV2\\n     *\\n     * @param _amountToWithdraw V2 shares to claim\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function claimAndWithdraw(uint256 _amountToWithdraw, uint256 _maxEthToPay) external afterMigration {\\n        uint256 amountV1toClaim = _getV1SharesForV2Share(_amountToWithdraw);\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        require(amountV1toClaim <= amountV1Deposited, \\\"M6\\\");\\n\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(amountV1toClaim);\\n        crabV2.flashWithdraw(_amountToWithdraw, _maxEthToPay);\\n\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\n\\n        // Pay user's ETH back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice For input v2 shares returns the equivalent v1 shares\\n     */\\n    function _getV1SharesForV2Share(uint256 _amountV2) internal view returns (uint256) {\\n        return _amountV2.wmul(totalCrabV1SharesMigrated).wdiv(totalCrabV2SharesReceived);\\n    }\\n\\n    function flashMigrationDetails(uint256 _v1Shares)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return _flashMigrationDetails(_v1Shares);\\n    }\\n\\n    /**\\n     * @notice Used to migrate from crab V1 to crab V2 when CR1 >= CR2\\n     *\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit Flash deposit amount in crab v2 with excess ETH. If 0 will returned to sender\\n     */\\n    function flashMigrateFromV1toV2(uint256 _v1Shares, uint256 _ethToFlashDeposit) external afterMigration {\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(isFlashOnlyMigrate, \\\"M11\\\");\\n\\n        euler.deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: ethNeededForV2,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateV1toV2({\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            crabV1ToWithdraw: _v1Shares\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Used to migrate from crab V1 to crab V2 when CR1 < CR2\\n     *\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit Flash deposit amount in crab v2 with excess ETH. If 0 will returned to sender\\n     * @param _ethToBorrow Amount to flash loan to deposit in crab v2\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashMigrateAndWithdrawFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint256 _ethToBorrow,\\n        uint256 _withdrawMaxEthToPay\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(!isFlashOnlyMigrate, \\\"M12\\\");\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\"M8\\\");\\n\\n        euler.deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: _ethToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateAndBuyV1toV2({\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            crabV1ToWithdraw: _v1Shares\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Get migration details for given amount of v1 shares\\n     */\\n    function _flashMigrationDetails(uint256 _v1Shares)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = crabV1.getVaultDetails();\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = crabV2.getVaultDetails();\\n\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(crabV1.totalSupply());\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(crabV1.totalSupply()).wmul(v1TotalCollateral);\\n\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(crabV1) || msg.sender == address(crabV2), \\\"M5\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IEuler.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\ninterface IEulerExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\"\n    },\n    \"contracts/external/WETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\n\\ncontract WETH9 {\\n    string public name = \\\"Wrapped Ether\\\";\\n    string public symbol = \\\"WETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        payable(msg.sender).transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockEulerDToken.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockEulerDToken {\\n    ERC20 weth;\\n\\n    constructor(address _weth) {\\n        weth = ERC20(_weth);\\n    }\\n\\n    function borrow(uint256, uint256 amount) external {\\n        weth.transfer(msg.sender, amount);\\n    }\\n\\n    function repay(uint256, uint256 amount) external {\\n        weth.transferFrom(msg.sender, address(this), amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockCrab.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockCrab is ERC20 {\\n    address operator;\\n    uint256 vaultId;\\n    uint256 collateral;\\n    uint256 short;\\n    address public wPowerPerp;\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    function setVaultDetails(\\n        uint256 _vaultId,\\n        uint256 _collateral,\\n        uint256 _short\\n    ) external {\\n        vaultId = _vaultId;\\n        collateral = _collateral;\\n        short = _short;\\n    }\\n\\n    function getVaultDetails()\\n        external\\n        view\\n        returns (\\n            address,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return (operator, vaultId, collateral, short);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/helper/StrategySwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract StrategySwap {\\n    ISwapRouter public immutable swapRouter;\\n\\n    constructor(address _swapRouter) {\\n        require(_swapRouter != address(0), \\\"invalid swap router address\\\");\\n        swapRouter = ISwapRouter(_swapRouter);\\n    }\\n\\n    /**\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _from from which user we are selling\\n     * @param _to Recipient to get the tokens\\n     * @param _amountIn Exact amount to sell\\n     * @param _minAmountOut Minimum amount to be paid\\n     * @param _fee pool fee\\n     * @return amountOut The amount of WETH9 received.\\n     */\\n    function _swapExactInputSingle(\\n        address _tokenIn,\\n        address _tokenOut,\\n        address _from,\\n        address _to,\\n        uint256 _amountIn,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) internal returns (uint256 amountOut) {\\n        // _from must approve this contract\\n\\n        // Transfer the specified amount of tokenIn to this contract.\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\n\\n        // Approve the router to spend tokenIn.\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\n\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\n            tokenIn: _tokenIn,\\n            tokenOut: _tokenOut,\\n            fee: _fee,\\n            recipient: _to,\\n            deadline: block.timestamp,\\n            amountIn: _amountIn,\\n            amountOutMinimum: _minAmountOut,\\n            sqrtPriceLimitX96: 0\\n        });\\n\\n        // The call to `exactInputSingle` executes the swap.\\n        amountOut = swapRouter.exactInputSingle(params);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {ICrabStrategyV2} from \\\"../interfaces/ICrabStrategyV2.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {StrategySwap} from \\\"./helper/StrategySwap.sol\\\";\\n\\n/**\\n * @dev CrabHelper contract\\n * @notice Contract for Crab helper functions\\n * @author Opyn team\\n */\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\n    using Address for address payable;\\n\\n    address public immutable crab;\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    event FlashDepositERC20(\\n        address indexed depositor,\\n        address depositedERC20,\\n        uint256 depositedAmount,\\n        uint256 depositedEthAmount,\\n        uint256 crabAmount,\\n        uint256 returnedEth\\n    );\\n\\n    event FlashWithdrawERC20(\\n        address indexed withdrawer,\\n        address withdrawnERC20,\\n        uint256 withdrawnAmount,\\n        uint256 withdrawnEthAmount,\\n        uint256 crabAmount\\n    );\\n\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\n        require(_crab != address(0), \\\"Invalid crab address\\\");\\n\\n        crab = _crab;\\n        weth = ICrabStrategyV2(_crab).weth();\\n        wPowerPerp = ICrabStrategyV2(_crab).wPowerPerp();\\n    }\\n\\n    function flashDepositERC20(\\n        uint256 _ethToDeposit,\\n        uint256 _amountIn,\\n        uint256 _minEthToGet,\\n        uint24 _fee,\\n        address _tokenIn\\n    ) external nonReentrant {\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _fee);\\n\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit);\\n\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\n\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\n\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\n\\n        if (address(this).balance > 0) {\\n            payable(msg.sender).sendValue(address(this).balance);\\n        }\\n    }\\n\\n    function flashWithdrawERC20(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        address _tokenOut,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) external nonReentrant {\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\n\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay);\\n\\n        uint256 ethBalance = address(this).balance;\\n        IWETH9(weth).deposit{value: ethBalance}();\\n        uint256 tokenReceived = _swapExactInputSingle(\\n            weth,\\n            _tokenOut,\\n            address(this),\\n            msg.sender,\\n            ethBalance,\\n            _minAmountOut,\\n            _fee\\n        );\\n\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crab, \\\"Cannot receive eth\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/ICrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\ninterface ICrabStrategyV2 {\\n    function wPowerPerp() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function flashDeposit(uint256 _ethToDeposit) external payable;\\n\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external;\\n}\\n\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"C3\\\");\\n\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/solcInputs/ab83bcba860cd7677bf7e9d807e32da5.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // Ceil A to a multiple m\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(sub(add(a, m), 1), m), m);\\n    }\\n\\n    // Floor A to a multiple m\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(a, m), m);\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {EIP712} from \\\"@openzeppelin/contracts/drafts/EIP712.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\nimport {ECDSA} from \\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * Crab V2 Error Codes:\\n * C1: Caller is not timelock\\n * C2: Contract not yet initialized\\n * C3: Invalid oracle address\\n * C4: Invalid timelock address\\n * C5: Invalid ETH:WSqueeth address\\n * C6: Invalid crabMigration address\\n * C7: Invalid hedge time threshold\\n * C8: Invalid hedge price threshold\\n * C9: Cannot receive ETH\\n * C10: Caller not Crab Migration contract\\n * C11: Crab V2 already initialized\\n * C12: Squeeth contracts not shut down\\n * C13: Crab must redeemShortShutdown\\n * C14: Twap period is too short\\n * C15: Price tolerance is too high\\n * C16: Deposit exceeds strategy cap\\n * C17: Clearing Price should be below bid price\\n * C18: Clearing Price should be above offer price\\n * C19: Invalid offer signature\\n * C20: Order has expired\\n * C21: Manager Price should be greater than 0\\n * C22: Not a valid Time or Price hedge\\n * C23: Orders must take the opposite side of the hedge\\n * C24: All orders must be either buying or selling\\n * C25: Orders are not arranged properly\\n * C26: Crab contracts shut down\\n *  C27: Nonce already used.\\n */\\n\\n/**\\n * @dev CrabStrategyV2 contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    // @dev OTC price must be within this distance of the uniswap twap price\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\n\\n    // @dev OTC price tolerance cannot exceed 20%\\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\\n\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n    /// @dev true if CrabV2 was initialized\\n    bool public isInitialized;\\n\\n    /// @dev typehash for signed orders\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\n        keccak256(\\n            \\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\"\\n        );\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:wSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable timelock;\\n    address public immutable crabMigration;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev wSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    /// @dev store the used flag for a nonce for each address\\n    mapping(address => mapping(uint256 => bool)) public nonces;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct Order {\\n        uint256 bidId;\\n        address trader;\\n        uint256 quantity;\\n        uint256 price;\\n        bool isBuying;\\n        uint256 expiry;\\n        uint256 nonce;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event HedgeOTCSingle(\\n        address trader,\\n        uint256 bidId,\\n        uint256 quantity,\\n        uint256 price,\\n        bool isBuying,\\n        uint256 clearingPrice\\n    );\\n    event HedgeOTC(uint256 bidId, uint256 quantity, bool isBuying, uint256 clearingPrice);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\n\\n    modifier onlyTimelock() {\\n        require(msg.sender == timelock, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialization() {\\n        require(isInitialized, \\\"C2\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _timelock timelock contract address\\n     * @param _crabMigration crab migration contract address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        address _timelock,\\n        address _crabMigration,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold\\n    )\\n        StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy v2\\\", \\\"Crabv2\\\")\\n        StrategyFlashSwap(_uniswapFactory)\\n        EIP712(\\\"CrabOTC\\\", \\\"2\\\")\\n    {\\n        require(_oracle != address(0), \\\"C3\\\");\\n        require(_timelock != address(0), \\\"C4\\\");\\n        require(_ethWSqueethPool != address(0), \\\"C5\\\");\\n        require(_crabMigration != address(0), \\\"C6\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        timelock = _timelock;\\n        crabMigration = _crabMigration;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"C9\\\");\\n    }\\n\\n    /**\\n     * @notice initializes the collateral ratio after the first migration\\n     * @param _wSqueethToMint amount of wPowerPerp to mint\\n     * @param _crabSharesToMint crab shares to mint\\n     * @param _timeAtLastHedge time at last hedge for crab V1\\n     * @param _priceAtLastHedge price at last hedge for crab V1\\n     * @param _strategyCap strategy cap for crab V2\\n     */\\n    function initialize(\\n        uint256 _wSqueethToMint,\\n        uint256 _crabSharesToMint,\\n        uint256 _timeAtLastHedge,\\n        uint256 _priceAtLastHedge,\\n        uint256 _strategyCap\\n    ) external payable {\\n        require(msg.sender == crabMigration, \\\"C10\\\");\\n        require(!isInitialized, \\\"C11\\\");\\n\\n        _setStrategyCap(_strategyCap);\\n\\n        uint256 amount = msg.value;\\n\\n        _checkStrategyCap(amount, 0);\\n\\n        // store hedge data from crab V1\\n        timeAtLastHedge = _timeAtLastHedge;\\n        priceAtLastHedge = _priceAtLastHedge;\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\n\\n        isInitialized = true;\\n    }\\n\\n    /**\\n     * @notice transfer vault NFT to new contract\\n     * @dev strategy cap is set to 0 to avoid future deposits\\n     * @param _newStrategy new strategy contract address\\n     */\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\n        _setStrategyCap(0);\\n\\n        emit VaultTransferred(_newStrategy, vaultId);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner afterInitialization {\\n        _setStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice set strategy cap amount\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function _setStrategyCap(uint256 _capAmount) internal {\\n        strategyCap = _capAmount;\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called before users can exit strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external afterInitialization {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     * @param _poolFee Uniswap pool fee\\n     */\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _poolFee,\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the wSqueeth debt\\n     * @param _poolFee Uniswap pool fee\\n\\n     */\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _poolFee,\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns ETH\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"C12\\\");\\n        require(hasRedeemedInShutdown, \\\"C13\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice set nonce to true\\n     * @param _nonce the number to be set true\\n     */\\n    function setNonceTrue(uint256 _nonce) external {\\n        nonces[msg.sender][_nonce] = true;\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"C14\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"C7\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require((_hedgePriceThreshold > 0) && (_hedgePriceThreshold <= ONE), \\\"C8\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\n     */\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\n        // Tolerance cannot be more than 20%\\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \\\"C15\\\");\\n\\n        otcPriceTolerance = _otcPriceTolerance;\\n\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"C16\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            // use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            // will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(address(pool), _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            // return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            // use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            IUniswapV3Pool pool = _getPool(_tokenIn, _tokenOut, _fee);\\n\\n            // use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(address(pool), _amountToPay);\\n\\n            // excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @dev set nonce flag of the trader to true\\n     * @param _trader address of the signer\\n     * @param _nonce number that is to be traded only once\\n     */\\n    function _useNonce(address _trader, uint256 _nonce) internal {\\n        require(!nonces[_trader][_nonce], \\\"C27\\\");\\n        nonces[_trader][_nonce] = true;\\n    }\\n\\n    /**\\n     * @dev view function to get the domain seperator used in signing\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev check the signer and swap tokens in the order\\n     * @param _remainingAmount quantity the manager wants to trade\\n     * @param _clearingPrice the price at which all orders are traded\\n     * @param _order a signed order to swap tokens\\n     */\\n    function _execOrder(\\n        uint256 _remainingAmount,\\n        uint256 _clearingPrice,\\n        Order memory _order\\n    ) internal {\\n        // check that order beats clearing price\\n        if (_order.isBuying) {\\n            require(_clearingPrice <= _order.price, \\\"C17\\\");\\n        } else {\\n            require(_clearingPrice >= _order.price, \\\"C18\\\");\\n        }\\n\\n        _useNonce(_order.trader, _order.nonce);\\n        bytes32 structHash = keccak256(\\n            abi.encode(\\n                _CRAB_BALANCE_TYPEHASH,\\n                _order.bidId,\\n                _order.trader,\\n                _order.quantity,\\n                _order.price,\\n                _order.isBuying,\\n                _order.expiry,\\n                _order.nonce\\n            )\\n        );\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\n        require(offerSigner == _order.trader, \\\"C19\\\");\\n        require(_order.expiry >= block.timestamp, \\\"C20\\\");\\n\\n        // adjust quantity for partial fills\\n        if (_remainingAmount < _order.quantity) {\\n            _order.quantity = _remainingAmount;\\n        }\\n        // weth clearing price for the order\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(ONE);\\n\\n        if (_order.isBuying) {\\n            // trader sends weth and receives oSQTH\\n            IWETH9(weth).transferFrom(_order.trader, address(this), wethAmount);\\n            IWETH9(weth).withdraw(wethAmount);\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n        } else {\\n            // trader sends oSQTH and receives weth\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n            // wrap it\\n            IWETH9(weth).deposit{value: wethAmount}();\\n            IWETH9(weth).transfer(_order.trader, wethAmount);\\n        }\\n\\n        emit HedgeOTCSingle(\\n            _order.trader, // market maker\\n            _order.bidId,\\n            _order.quantity, // order oSQTH quantity\\n            _order.price, // order price\\n            _order.isBuying, // order direction\\n            _clearingPrice // executed price for order\\n        );\\n    }\\n\\n    /**\\n     * @dev hedge function to reduce delta using an array of signed orders\\n     * @param _totalQuantity quantity the manager wants to trade\\n     * @param _clearingPrice clearing price in weth\\n     * @param _isHedgeBuying direction of hedge trade\\n     * @param _orders an array of signed order to swap tokens\\n     */\\n    function hedgeOTC(\\n        uint256 _totalQuantity,\\n        uint256 _clearingPrice,\\n        bool _isHedgeBuying,\\n        Order[] memory _orders\\n    ) external onlyOwner afterInitialization {\\n        require(_clearingPrice > 0, \\\"C21\\\");\\n        require(_isTimeHedge() || _isPriceHedge(), \\\"C22\\\");\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = _clearingPrice;\\n\\n        uint256 remainingAmount = _totalQuantity;\\n        uint256 prevPrice = _orders[0].price;\\n        uint256 currentPrice = _orders[0].price;\\n        bool isOrderBuying = _orders[0].isBuying;\\n        require(_isHedgeBuying != isOrderBuying, \\\"C23\\\");\\n\\n        // iterate through order array and execute if valid\\n        for (uint256 i; i < _orders.length; ++i) {\\n            currentPrice = _orders[i].price;\\n            require(_orders[i].isBuying == isOrderBuying, \\\"C24\\\");\\n            if (_isHedgeBuying) {\\n                require(currentPrice >= prevPrice, \\\"C25\\\");\\n            } else {\\n                require(currentPrice <= prevPrice, \\\"C25\\\");\\n            }\\n            prevPrice = currentPrice;\\n\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\n\\n            if (remainingAmount > _orders[i].quantity) {\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\n            } else {\\n                break;\\n            }\\n        }\\n\\n        emit HedgeOTC(_orders[0].bidId, _totalQuantity, _isHedgeBuying, _clearingPrice);\\n    }\\n\\n    /**\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\n     * @param _price clearing price provided by manager\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\n     */\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\n        // Get twap\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n\\n        if (_isHedgeBuying) {\\n            require(\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\n                \\\"Price too high relative to Uniswap twap.\\\"\\n            );\\n        } else {\\n            require(\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\n                \\\"Price too low relative to Uniswap twap.\\\"\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\n        require(!isShutdown, \\\"C26\\\");\\n\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n        );\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     */\\n    function _isTimeHedge() internal view returns (bool) {\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge() internal view returns (bool) {\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > ONE ? (cachedRatio).sub(ONE) : uint256(ONE).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge() external view returns (bool) {\\n        return _isPriceHedge();\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkTimeHedge() external view returns (bool) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/drafts/EIP712.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = _getChainId();\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n        return keccak256(\\n            abi.encode(\\n                typeHash,\\n                name,\\n                version,\\n                _getChainId(),\\n                address(this)\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/cryptography/ECDSA.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        // Check the signature length\\n        if (signature.length != 65) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        }\\n\\n        // Divide the signature in r, s and v variables\\n        bytes32 r;\\n        bytes32 s;\\n        uint8 v;\\n\\n        // ecrecover takes the signature parameters, and the only way to get them\\n        // currently is to use assembly.\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            r := mload(add(signature, 0x20))\\n            s := mload(add(signature, 0x40))\\n            v := byte(0, mload(add(signature, 0x60)))\\n        }\\n\\n        return recover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n        require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n        return signer;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * replicates the behavior of the\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n     * JSON-RPC method.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\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) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/strategy/CrabHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {ICrabStrategyV2} from \\\"../interfaces/ICrabStrategyV2.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {StrategySwap} from \\\"./helper/StrategySwap.sol\\\";\\n\\n/**\\n * @dev CrabHelper contract\\n * @notice Contract for Crab helper functions\\n * @author Opyn team\\n */\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\n    using Address for address payable;\\n\\n    address public immutable crab;\\n    address public immutable weth;\\n\\n    event FlashDepositERC20(\\n        address indexed depositor,\\n        address depositedERC20,\\n        uint256 depositedAmount,\\n        uint256 depositedEthAmount,\\n        uint256 crabAmount,\\n        uint256 returnedEth\\n    );\\n\\n    event FlashWithdrawERC20(\\n        address indexed withdrawer,\\n        address withdrawnERC20,\\n        uint256 withdrawnAmount,\\n        uint256 withdrawnEthAmount,\\n        uint256 crabAmount\\n    );\\n\\n    /**\\n     * @notice constructor\\n     * @param _crab address of crabV2 contract\\n     * @param _swapRouter address of Uniswap swap router\\n     */\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\n        require(_crab != address(0), \\\"Invalid crab address\\\");\\n\\n        crab = _crab;\\n        weth = ICrabStrategyV2(_crab).weth();\\n    }\\n\\n    /**\\n     * @notice allows user to flash deposit into crab from an aribtrary ERC20\\n     * @param _ethToDeposit amount of ETH to deposit\\n     * @param _amountIn amount of ERC20 token to swap for weth\\n     * @param _minEthToGet min amount of ETH to receive in the swap\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     * @param _tokenIn ERC20 token to pay\\n     */\\n    function flashDepositERC20(\\n        uint256 _ethToDeposit,\\n        uint256 _amountIn,\\n        uint256 _minEthToGet,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee,\\n        address _tokenIn\\n    ) external nonReentrant {\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _erc20Fee);\\n\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit, _wPowerPerpFee);\\n\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\n\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\n\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\n\\n        if (address(this).balance > 0) {\\n            payable(msg.sender).sendValue(address(this).balance);\\n        }\\n    }\\n\\n    /**\\n     * @notice allows user to flash withdraw from crab to an aribtrary ERC20\\n     * @param _crabAmount amount of crab shares to withdraw\\n     * @param _maxEthToPay max eth to pay in swap for wPowerPerp\\n     * @param _tokenOut ERC20 token to receive\\n     * @param _minAmountOut min amount of ERC20 to receive\\n     * @param _erc20Fee pool fee for transfer ERC20/eth pool (3000 = 30bps)\\n     * @param _wPowerPerpFee pool fee for wPowerPerp/eth pool (3000 = 30bps)\\n     */\\n    function flashWithdrawERC20(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        address _tokenOut,\\n        uint256 _minAmountOut,\\n        uint24 _erc20Fee,\\n        uint24 _wPowerPerpFee\\n    ) external nonReentrant {\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\n\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay, _wPowerPerpFee);\\n\\n        uint256 ethBalance = address(this).balance;\\n        IWETH9(weth).deposit{value: ethBalance}();\\n        uint256 tokenReceived = _swapExactInputSingle(\\n            weth,\\n            _tokenOut,\\n            address(this),\\n            msg.sender,\\n            ethBalance,\\n            _minAmountOut,\\n            _erc20Fee\\n        );\\n\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crab, \\\"Cannot receive eth\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/ICrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\ninterface ICrabStrategyV2 {\\n    function wPowerPerp() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\\n\\n    function flashWithdraw(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/strategy/helper/StrategySwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract StrategySwap {\\n    ISwapRouter public immutable swapRouter;\\n\\n    constructor(address _swapRouter) {\\n        require(_swapRouter != address(0), \\\"invalid swap router address\\\");\\n        swapRouter = ISwapRouter(_swapRouter);\\n    }\\n\\n    /**\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _from from which user we are selling\\n     * @param _to Recipient to get the tokens\\n     * @param _amountIn Exact amount to sell\\n     * @param _minAmountOut Minimum amount to be paid\\n     * @param _fee pool fee\\n     * @return amountOut The amount of WETH9 received.\\n     */\\n    function _swapExactInputSingle(\\n        address _tokenIn,\\n        address _tokenOut,\\n        address _from,\\n        address _to,\\n        uint256 _amountIn,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) internal returns (uint256 amountOut) {\\n        // _from must approve this contract\\n\\n        // Transfer the specified amount of tokenIn to this contract.\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\n\\n        // Approve the router to spend tokenIn.\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\n\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\n            tokenIn: _tokenIn,\\n            tokenOut: _tokenOut,\\n            fee: _fee,\\n            recipient: _to,\\n            deadline: block.timestamp,\\n            amountIn: _amountIn,\\n            amountOutMinimum: _minAmountOut,\\n            sqrtPriceLimitX96: 0\\n        });\\n\\n        // The call to `exactInputSingle` executes the swap.\\n        amountOut = swapRouter.exactInputSingle(params);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabMigration.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport {IEulerExec, IDToken} from \\\"../interfaces/IEuler.sol\\\";\\nimport {WETH9} from \\\"../external/WETH9.sol\\\";\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// contract\\nimport {CrabStrategyV2} from \\\"./CrabStrategyV2.sol\\\";\\nimport {CrabStrategy} from \\\"./CrabStrategy.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * Migration Error Codes:\\n * M1: Migration already happened\\n * M2: Migration has not yet happened\\n * M3: msg.sender is not Euler Mainnet Contract\\n * M4: Can only receive ETH from weth, crabv1, or crabv2 contract\\n * M5: Can't withdraw more than you own\\n * M6: Not enough ETH to repay the loan\\n * M7: Invalid crabV2 address\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\n * M9: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\n * M10: Wrong migration function, use flashMigrateFromV1toV2\\n * M11: crabV2 address not yet set\\n */\\n\\n/**\\n * @dev CrabMigration contract\\n * @notice Contract for Migrating from Crab V1 to Crab V2\\n * @author Opyn team\\n */\\ncontract CrabMigration is Ownable {\\n    using SafeERC20 for IERC20;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    mapping(address => uint256) public sharesDeposited;\\n    bool public isMigrated;\\n\\n    address payable public crabV1;\\n    address payable public crabV2;\\n    address public immutable euler;\\n    address public immutable weth;\\n\\n    address immutable EULER_MAINNET;\\n    address immutable dToken;\\n    address immutable wPowerPerp;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    struct BatchMigrate {\\n        uint256 strategyCap;\\n    }\\n\\n    struct FlashMigrateV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFee;\\n    }\\n\\n    struct FlashMigrateAndBuyV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 withdrawMaxEthToPay;\\n        uint256 crabV1ToWithdraw;\\n        uint24 poolFeeFlashDeposit;\\n    }\\n\\n    enum FLASH_SOURCE {\\n        BATCH_MIGRATE,\\n        FLASH_MIGRATE_V1_TO_V2,\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\n    }\\n\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\n    event DepositV1Shares(address indexed user, uint256 crabV1Amount);\\n    event ClaimV2Shares(address indexed user, uint256 crabAmount);\\n    event FlashMigrate(address indexed user, uint256 crabV1Amount, uint256 crabV2Amount, uint256 excessEth);\\n\\n    event WithdrawV1Shares(address indexed user, uint256 crabV1Amount);\\n\\n    modifier beforeMigration() {\\n        require(!isMigrated, \\\"M1\\\");\\n        _;\\n    }\\n\\n    modifier afterMigration() {\\n        require(isMigrated, \\\"M2\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialized() {\\n        require(crabV2 != address(0), \\\"M11\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice migration constructor\\n     * @param _crabV1 address of crab V1\\n     * @param _weth address of weth\\n     * @param _eulerExec address of euler exec contract\\n     * @param _dToken address of euler liability token\\n     * @param _eulerMainnet address of euler deployment on mainnet\\n     */\\n    constructor(\\n        address payable _crabV1,\\n        address _weth,\\n        address _eulerExec,\\n        address _dToken,\\n        address _eulerMainnet\\n    ) {\\n        require(_eulerExec != address(0), \\\"invalid _eulerExec address\\\");\\n        require(_dToken != address(0), \\\"invalid _dToken address\\\");\\n        require(_eulerMainnet != address(0), \\\"invalid _eulerMainnet address\\\");\\n        require(_weth != address(0), \\\"invalid _weth address\\\");\\n        require(_crabV1 != address(0), \\\"invalid _crabv1 address\\\");\\n        require(IDToken(_dToken).underlyingAsset() == _weth, \\\"dToken underlying asset should be weth\\\");\\n\\n        crabV1 = _crabV1;\\n        euler = _eulerExec;\\n        EULER_MAINNET = _eulerMainnet;\\n        weth = _weth;\\n        dToken = _dToken;\\n        wPowerPerp = CrabStrategy(crabV1).wPowerPerp();\\n        WETH9(_weth).approve(_eulerMainnet, type(uint256).max);\\n    }\\n\\n    /**\\n     * @notice set the crabV2 address\\n     * @param _crabV2 address of crab V2\\n     */\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\n        require(_crabV2 != address(0), \\\"M7\\\");\\n        crabV2 = _crabV2;\\n    }\\n\\n    /**\\n     * @notice deposit crab V1 shares in the pool for migration\\n     * @param _amount amount of crabV1 shares to deposit\\n     */\\n    function depositV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] += _amount;\\n\\n        CrabStrategy(crabV1).transferFrom(msg.sender, address(this), _amount);\\n\\n        emit DepositV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice withdraw crab V1 shares in the pool before migration\\n     * @param _amount amount of V1 shares to withdraw\\n     */\\n    function withdrawV1Shares(uint256 _amount) external beforeMigration {\\n        sharesDeposited[msg.sender] = sharesDeposited[msg.sender].sub(_amount);\\n        CrabStrategy(crabV1).transfer(msg.sender, _amount);\\n\\n        emit WithdrawV1Shares(msg.sender, _amount);\\n    }\\n\\n    /**\\n     * @notice the owner batch migrates all the crab V1 shares in this contract to crab V2 and initializes\\n     * the V2 contract at the same collateral ratio as the V1 contract\\n     * @param _strategyCap strategy cap in ETH\\n     */\\n    function batchMigrate(uint256 _strategyCap) external onlyOwner afterInitialized beforeMigration {\\n        // 1. update isMigrated\\n        isMigrated = true;\\n\\n        // 2. flash floan eth from euler eq to amt\\n        uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n        uint256 crabV1Supply = CrabStrategy(crabV1).totalSupply();\\n        (, , uint256 totalCollateral, ) = CrabStrategy(crabV1).getVaultDetails();\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: amountEthToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\n                    callData: abi.encode(BatchMigrate({strategyCap: _strategyCap}))\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Euler callback function\\n     * @param encodedData callback data\\n     */\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\n        require(msg.sender == EULER_MAINNET, \\\"M3\\\");\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        // 1. borrow weth\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\n        WETH9(weth).withdraw(data.amountToBorrow);\\n\\n        // 2. callback\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\n\\n        // 3. repay the weth\\n        WETH9(weth).deposit{value: data.amountToBorrow}();\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     * @notice callback function for flash actions\\n     * @param _initiator address of original function caller\\n     * @param _amount  amount to pay back for flashswap\\n     * @param _callSource identifier for which function triggered callback\\n     * @param _calldata arbitrary data attached to callback\\n\\n     */\\n    function _flashCallback(\\n        address _initiator,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\n            BatchMigrate memory data = abi.decode(_calldata, (BatchMigrate));\\n\\n            uint256 crabV1Balance = CrabStrategy(crabV1).balanceOf(address(this));\\n\\n            // 2. mint osqth in crab V2\\n            uint256 wSqueethToMint = CrabStrategy(crabV1).getWsqueethFromCrabAmount(crabV1Balance);\\n            uint256 timeAtLastHedge = CrabStrategy(crabV1).timeAtLastHedge();\\n            uint256 priceAtLastHedge = CrabStrategy(crabV1).priceAtLastHedge();\\n            CrabStrategyV2(crabV2).initialize{value: _amount}(\\n                wSqueethToMint,\\n                crabV1Balance,\\n                timeAtLastHedge,\\n                priceAtLastHedge,\\n                data.strategyCap\\n            );\\n\\n            // 3. call withdraw from crab V1\\n            IERC20(wPowerPerp).approve(crabV1, type(uint256).max);\\n            CrabStrategy(crabV1).withdraw(crabV1Balance);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\n\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n\\n            IERC20(wPowerPerp).approve(crabV1, data.v1oSqthToPay);\\n            CrabStrategy(crabV1).withdraw(data.crabV1ToWithdraw);\\n\\n            // flash deposit remaining ETH, otherwise refund\\n            // if CR1 = CR2 ethToFlashDeposit should be 0\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFee\\n                );\\n            }\\n\\n            uint256 crabV2Amount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n            // send back V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2Amount);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2Amount, excessEth.sub(_amount));\\n\\n            // send back excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\n            (, , , uint256 v1Short) = CrabStrategy(crabV1).getVaultDetails();\\n\\n            CrabStrategy(crabV1).transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n            CrabStrategyV2(crabV2).deposit{value: _amount}();\\n\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\n            IERC20(wPowerPerp).approve(crabV1, oSqthToPay);\\n\\n            // find crab amount for contract's sqth balance\\n            // remaining crab can be withdrawn using flash withdraw\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(CrabStrategy(crabV1).totalSupply()).rdiv(v1Short);\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\n\\n            CrabStrategy(crabV1).withdraw(crabV1ToWithdraw);\\n\\n            CrabStrategy(crabV1).flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\n            require(address(this).balance >= _amount, \\\"M6\\\");\\n\\n            if (data.ethToFlashDeposit > 0) {\\n                CrabStrategyV2(crabV2).flashDeposit{value: address(this).balance.sub(_amount)}(\\n                    data.ethToFlashDeposit,\\n                    data.poolFeeFlashDeposit\\n                );\\n            }\\n\\n            uint256 crabV2Amount = CrabStrategyV2(crabV2).balanceOf(address(this));\\n\\n            // send V2 tokens to the user\\n            CrabStrategyV2(crabV2).transfer(_initiator, crabV2Amount);\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            uint256 excessEth = address(this).balance;\\n\\n            emit FlashMigrate(_initiator, data.crabV1ToWithdraw, crabV2Amount, excessEth.sub(_amount));\\n\\n            // send back the excess ETH\\n            if (excessEth > _amount) {\\n                payable(_initiator).sendValue(excessEth.sub(_amount));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares\\n     */\\n    function claimV2Shares() external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        sharesDeposited[msg.sender] = 0;\\n        CrabStrategyV2(crabV2).transfer(msg.sender, amountV1Deposited);\\n        emit ClaimV2Shares(msg.sender, amountV1Deposited);\\n    }\\n\\n    /**\\n     * @notice claim crab V2 shares and flash withdraw from crab V2\\n     * @param _amountToWithdraw V2 shares to claim\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee Uniswap pool fee for flash withdraw\\n     */\\n    function claimAndWithdraw(\\n        uint256 _amountToWithdraw,\\n        uint256 _maxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        require(_amountToWithdraw <= amountV1Deposited, \\\"M5\\\");\\n\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(_amountToWithdraw);\\n        CrabStrategyV2(crabV2).flashWithdraw(_amountToWithdraw, _maxEthToPay, _poolFee);\\n\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\n\\n        // send eth to user\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice view details of flash migration for specified amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function flashMigrationDetails(uint256 _v1Shares)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return _flashMigrationDetails(_v1Shares);\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 >= CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will return to sender)\\n     * @param _poolFee uniswap pool fee for flash deposit\\n     */\\n    function flashMigrateFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(isFlashOnlyMigrate, \\\"M9\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: ethNeededForV2,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateV1toV2({\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFee: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice used to migrate from crab V1 to crab V2 when CR1 < CR2\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit flash deposit amount in crab v2 with excess ETH (if 0 will returned to sender)\\n     * @param _ethToBorrow amount to flash loan to deposit in crab v2\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     * @param _poolFee uniswap pool fee for the optional flash deposit into crab v2\\n     */\\n    function flashMigrateAndWithdrawFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint256 _ethToBorrow,\\n        uint256 _withdrawMaxEthToPay,\\n        uint24 _poolFee\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(!isFlashOnlyMigrate, \\\"M10\\\");\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\"M8\\\");\\n\\n        IEulerExec(euler).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: _ethToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateAndBuyV1toV2({\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            crabV1ToWithdraw: _v1Shares,\\n                            poolFeeFlashDeposit: _poolFee\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice get migration details for given amount of V1 shares\\n     * @param _v1Shares amount of crab V1 shares\\n     */\\n    function _flashMigrationDetails(uint256 _v1Shares)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = CrabStrategy(crabV1).getVaultDetails();\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = CrabStrategyV2(crabV2).getVaultDetails();\\n\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(CrabStrategy(crabV1).totalSupply());\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(CrabStrategy(crabV1).totalSupply()).wmul(v1TotalCollateral);\\n\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crabV1 || msg.sender == crabV2, \\\"M4\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IEuler.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\ninterface IEulerExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IDToken {\\n    function underlyingAsset() external view returns (address);\\n\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\"\n    },\n    \"contracts/external/WETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\n\\ncontract WETH9 {\\n    string public name = \\\"Wrapped Ether\\\";\\n    string public symbol = \\\"WETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        payable(msg.sender).transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockEulerDToken.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockEulerDToken {\\n    ERC20 weth;\\n\\n    constructor(address _weth) {\\n        weth = ERC20(_weth);\\n    }\\n\\n    function borrow(uint256, uint256 amount) external {\\n        weth.transfer(msg.sender, amount);\\n    }\\n\\n    function repay(uint256, uint256 amount) external {\\n        weth.transferFrom(msg.sender, address(this), amount);\\n    }\\n\\n    function underlyingAsset() external view returns (address) {\\n        return address(weth);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockCrab.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockCrab is ERC20 {\\n    address operator;\\n    uint256 vaultId;\\n    uint256 collateral;\\n    uint256 short;\\n    address public wPowerPerp;\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    function setVaultDetails(\\n        uint256 _vaultId,\\n        uint256 _collateral,\\n        uint256 _short\\n    ) external {\\n        vaultId = _vaultId;\\n        collateral = _collateral;\\n        short = _short;\\n    }\\n\\n    function getVaultDetails()\\n        external\\n        view\\n        returns (\\n            address,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return (operator, vaultId, collateral, short);\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"C3\\\");\\n\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/solcInputs/cd8e568ab17078249f8bced32d618ecf.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnOnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid power token controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, all uint to uint256, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    // strategy will only allow hedging if collateral to trade is at least 0.1% of the total strategy collateral\\n    uint256 public constant DELTA_HEDGE_THRESHOLD = 1e15;\\n\\n    uint256 public strategyCap;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public immutable hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public immutable hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public immutable auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for end sell auction (scaled 1e18)\\n    uint256 public immutable minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public immutable maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n    uint256 public auctionStartTime;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool public hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount, uint256 oldCapAmount);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"auction min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid auction min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"auction max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     * @return wSqueethToMint minted amount of wSqueeth\\n     * @return depositorCrabAmount minted amount of strategy token\\n     */\\n    function deposit() external payable nonReentrant returns (uint256, uint256) {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external payable nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts are not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Strategy has not redeemed vault proceeds\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @param _minWSqueeth minimum WSqueeth amount of profit if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount of profit if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        require(block.timestamp >= auctionTriggerTime, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime timestamp where auction started\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime alleged timestamp where auction was triggered\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        return (isTimeHedgeAllowed, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @dev _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        uint256 oldCap = strategyCap;\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount, oldCap);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price greater than max accepted price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price greater than min accepted price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"can not execute hedging trade as auction type changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(\\n                totalSupply() == 0,\\n                \\\"Crab strategy shut down due to full liquidation or shutdown of squeeth contracts\\\"\\n            );\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP_PERIOD, true);\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + TWAP_PERIOD,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        uint256 collateralRatioToHedge = targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta);\\n\\n        require(collateralRatioToHedge > DELTA_HEDGE_THRESHOLD, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 825\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/solcInputs/d91027c30078be5bfba0223abd5c6e60.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"hardhat/console.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >= 0.4.22 <0.9.0;\\n\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction _sendLogPayload(bytes memory payload) private view {\\n\\t\\tuint256 payloadLength = payload.length;\\n\\t\\taddress consoleAddress = CONSOLE_ADDRESS;\\n\\t\\tassembly {\\n\\t\\t\\tlet payloadStart := add(payload, 32)\\n\\t\\t\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n\\t\\t}\\n\\t}\\n\\n\\tfunction log() internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t}\\n\\n\\tfunction logInt(int p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdraw wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerp\\n        uint24 poolFee;\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;\\n        bool burnExactRemoved;\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;\\n        bool burnExactRemoved;\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from tokenIn to tokenOut\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in\\n        address tokenOut; // token to swap out\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell),\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n        console.log(\\\"after checkClosedLp\\\");\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount),\\n                    _limitPriceEthPerPowerPerp.mul(_wPowerPerpAmountToBurn.sub(_wPowerPerpAmount)).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/solcInputs/dfd7860ebd97501ecbdb5935c168e58b.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.closeUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdraw wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.closeUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerp wPowerPerp contract address\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        uint256 _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n            _mintAndLpParams.vaultId,\\n            _mintAndLpParams.wPowerPerpAmount,\\n            0\\n        );\\n\\n        // LP _mintAndLpParams._wPowerPerpAmount & _mintAndLpParams.collateralToLp in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _controller,\\n            _nonfungiblePositionManager,\\n            _wPowerPerpPool,\\n            _wPowerPerp,\\n            _vaultId,\\n            ControllerHelperDataType.LpWPowerPerpPool({\\n                recipient: _mintAndLpParams.recipient,\\n                ethAmount: _mintAndLpParams.collateralToLp,\\n                amount0Desired: _isWethToken0 ? _mintAndLpParams.collateralToLp : _mintAndLpParams.wPowerPerpAmount,\\n                amount1Desired: _isWethToken0 ? _mintAndLpParams.wPowerPerpAmount : _mintAndLpParams.collateralToLp,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParam struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParam memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToMint > 0) {\\n            IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                _vaultId,\\n                _increaseLiquidityParam.wPowerPerpAmountToMint,\\n                0\\n            );\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToMint,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToMint : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n\\n        checkExcess(_controller, _nonfungiblePositionManager, _wPowerPerp, _vaultId);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _vaultId vault Id\\n     * @param __wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintIntoVault(address _controller, uint256 _vaultId, uint256 __wPowerPerpToMint, uint256 _collateralToDeposit) public {\\n        IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n            _vaultId,\\n            __wPowerPerpToMint,\\n            0\\n        );\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _vaultId vault Id\\n     * @param __wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function withdrawFromVault(address _controller, uint256 _vaultId, uint256 __wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            __wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _wPowerPerp wPowerPerp address\\n     * @param _vaultId vault ID\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPool struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _controller, \\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        address _wPowerPerp,\\n        uint256 _vaultId,\\n        ControllerHelperDataType.LpWPowerPerpPool memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint{value: _params.ethAmount}(\\n            mintParams\\n        );\\n\\n        checkExcess(_controller, _nonfungiblePositionManager, _wPowerPerp, _vaultId);\\n\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice check if LP was closed fully or partially, transfer back to user or deposit into vault\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkPartialLpClose(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if (_liquidityPercentage < 1e18) {\\n            if (_vaultId == 0) {\\n                INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                    address(this),\\n                    msg.sender,\\n                    _tokenId\\n                );\\n            } else {\\n                IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice check if excess ETH or _wPowerPerp was sent for minting LP position, if so burn _wPowerPerp from vault and withdraw ETH from Uni pool\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerp wPowerPerp address \\n     * @param _vaultId vault ID to burn _wPowerPerp from\\n     */\\n    function checkExcess(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, uint256 _vaultId) public {\\n        uint256 remainingWPowerPerp = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (remainingWPowerPerp > 0) {\\n            if (_vaultId > 0) {\\n                IController(_controller).burnWPowerPerpAmount(_vaultId, remainingWPowerPerp, 0);\\n            } else {\\n                IWPowerPerp(_wPowerPerp).transfer(msg.sender, remainingWPowerPerp);\\n            }\\n        }\\n        // in case _collateralToLP > amount needed to LP, withdraw excess ETH\\n        INonfungiblePositionManager(_nonfungiblePositionManager).refundETH();\\n    }\\n\\n    /**\\n     * @notice send ETH\\n     */\\n    function sendBack(address _weth) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_VAULT_NFT\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        MintIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp\\n    }\\n\\n    /// @dev params for flashswapWMint()\\n    struct FlashswapWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 totalCollateralToDeposit;   // total collateral to deposit into vault\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 minToReceive;   // minimum to receive for flashswapping wPowerPerp to WETH\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralAmount;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerp\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n    }\\n\\n    /// @dev params for batchMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintDepositNftParams {\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (could be zero)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 lpAmount0Min; // amount0Min for Uni LPing\\n        uint256 lpAmount1Min; // amount1Min for Uni LPing\\n        int24 lpLowerTick; // Uni LP lower tick\\n        int24 lpUpperTick; // Uni LP upper tick\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct closeUniLpParams {\\n        uint256 tokenId;    // Uni NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for asset0\\n        uint128 amount1Min; // amount min to get for asset1\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct SellAll {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n    }\\n\\n    /// @dev params for rebalanceWithoutVault()\\n    struct RebalanceWithoutVault {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 ethAmountToLp;  // amount of WETH to lp\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPool {\\n        address recipient;  // recipient address\\n        uint256 ethAmount;  // ETH amount to LP\\n        uint256 amount0Desired; // amount to LP for asset0\\n        uint256 amount1Desired; // amount to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceVaultNft()\\n    struct RebalanceVaultNftParams {\\n        RebalanceVaultNftType rebalanceVaultNftType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParam {\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct MintIntoVault {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVault {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        console.log(\\\"amountOut\\\", amountOut);\\n        console.log(\\\"_amountOutMinimum\\\", _amountOutMinimum);\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        console.log(\\\"amountIn\\\", amountIn);\\n        console.log(\\\"_amountInMaximum\\\", _amountInMaximum);\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address, /*_caller*/\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256, /*_amountToPay*/\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    // function _flashCallback(\\n    //     uint256 _fee0,\\n    //     uint256 _fee1,\\n    //     bytes memory _callData,\\n    //     uint8 _callSource\\n    // ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = _getPool(tokenIn, tokenOut, fee).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = _getPool(tokenIn, tokenOut, fee).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"hardhat/console.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >= 0.4.22 <0.9.0;\\n\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction _sendLogPayload(bytes memory payload) private view {\\n\\t\\tuint256 payloadLength = payload.length;\\n\\t\\taddress consoleAddress = CONSOLE_ADDRESS;\\n\\t\\tassembly {\\n\\t\\t\\tlet payloadStart := add(payload, 32)\\n\\t\\t\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n\\t\\t}\\n\\t}\\n\\n\\tfunction log() internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t}\\n\\n\\tfunction logInt(int p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {AaveControllerHelper} from \\\"./AaveControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\n\\n/**\\n * Error code\\n * E0: user not allowed to operate vault\\n * E1: max ETH to pay for long wPowerPerp is less than amount available\\n * E2: ETH sent is less than amount to use for minting short plus amount to use for LPing\\n * E3: amount out less than min\\n * E4: amont in greater than max\\n * E5: invalid factory address\\n * E6: invalid assets length\\n */\\ncontract ControllerHelper is UniswapControllerHelper, AaveControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    address public immutable controller;\\n    address public immutable oracle;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerpPool;\\n    address public immutable wPowerPerp;\\n    address public immutable weth;\\n    address public immutable nonfungiblePositionManager;\\n    bool public immutable isWethToken0;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _lendingPoolAddressProvider\\n    ) UniswapControllerHelper(_uniswapFactory) AaveControllerHelper(_lendingPoolAddressProvider) {\\n        controller = _controller;\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        oracle = IController(_controller).oracle();\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerpPool = IController(_controller).wPowerPerpPool();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash mint WPowerPerp using flashswap\\n     * @param _params ControllerHelperDataType.FlashswapWMintParams struct\\n     */\\n    function flashswapWMint(ControllerHelperDataType.FlashswapWMintParams calldata _params) external payable {\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(wPowerPerpPool).fee(),\\n            _params.wPowerPerpAmount,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_MINT),\\n            abi.encode(_params)\\n        );\\n\\n        // no need to unwrap WETH received from swap as it is done in the callback function\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(wPowerPerpPool).fee(),\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n\\n        // flashswap and mint short position\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(wPowerPerpPool).fee(),\\n            _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell),\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.closeUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp\\n        );\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkPartialLpClose(\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function batchMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            wPowerPerpPool,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintDepositNftParams struct\\n     */\\n    function flashloanWMintDepositNft(ControllerHelperDataType.FlashloanWMintDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.SellAll struct\\n     */\\n    function sellAll(ControllerHelperDataType.SellAll calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.closeUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(wPowerPerpPool).fee(),\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceWithoutVault struct\\n     */\\n    function rebalanceWithoutVault(ControllerHelperDataType.RebalanceWithoutVault calldata _params) external payable {\\n        // if user need to send ETH to change LP composition, wrap to WETH\\n        if (msg.value > 0) IWETH9(weth).deposit{value: msg.value}();\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.closeUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        if (_params.wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(wPowerPerpPool).fee(),\\n                _params.wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(_params.wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(\\n                    1e18\\n                ),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (_params.wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(_params.wPowerPerpAmountDesired);\\n\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(wPowerPerpPool).fee(),\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            0,\\n            ControllerHelperDataType.LpWPowerPerpPool({\\n                recipient: msg.sender,\\n                ethAmount: _params.ethAmountToLp,\\n                amount0Desired: (isWethToken0) ? _params.wethAmountDesired : _params.wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? _params.wPowerPerpAmountDesired : _params.wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceVaultNftParams structs\\n     */\\n    function rebalanceVaultNft(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceVaultNftParams[] calldata _params\\n    ) external payable {\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_VAULT_NFT),\\n            abi.encode(_vaultId, _params)\\n        );\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint256 _premium,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintDepositNftParams)\\n            );\\n\\n            // convert flashloaned WETH to ETH\\n            IWETH9(weth).withdraw(_amount);\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                wPowerPerpPool,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.lpAmount0Min,\\n                    amount1Min: data.lpAmount1Min,\\n                    lowerTick: data.lpLowerTick,\\n                    upperTick: data.lpUpperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            INonfungiblePositionManager(nonfungiblePositionManager).approve(controller, uniTokenId);\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            IController(controller).withdraw(vaultId, _amount.add(data.collateralToWithdraw));\\n\\n            // convert flashloaned amount + fee from ETH to WETH to prepare for payback\\n            IWETH9(weth).deposit{value: _amount.add(_premium)}();\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            // convert flashloaned WETH to ETH\\n            IWETH9(weth).withdraw(_amount);\\n\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.closeUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp\\n            );\\n            ControllerHelperUtil.checkPartialLpClose(\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_VAULT_NFT\\n        ) {\\n            // convert flashloaned WETH to ETH\\n            IWETH9(weth).withdraw(_amount);\\n\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceVaultNftParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceVaultNftParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n\\n            console.log(\\\"vaultId\\\", vaultId);\\n\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceVaultNftType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    if (address(this).balance > 0) IWETH9(weth).deposit{value: address(this).balance}();\\n\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParam memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParam)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n                } else if (\\n                    data[i].rebalanceVaultNftType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.closeUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to mint in vault, deposit collateral in vault or mint + deposit\\n                    data[i].rebalanceVaultNftType == ControllerHelperDataType.RebalanceVaultNftType.MintIntoVault\\n                ) {\\n                    ControllerHelperDataType.MintIntoVault memory mintIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintIntoVault)\\n                    );\\n\\n                    ControllerHelperUtil.mintIntoVault(\\n                        controller,\\n                        vaultId,\\n                        mintIntoVaultParams.wPowerPerpToMint,\\n                        mintIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceVaultNftType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVault memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVault)\\n                    );\\n\\n                    ControllerHelperUtil.withdrawFromVault(\\n                        controller,\\n                        vaultId,\\n                        withdrawFromVaultParams.wPowerPerpToBurn,\\n                        withdrawFromVaultParams.collateralToWithdraw\\n                    );\\n                } else if (data[i].rebalanceVaultNftType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.LpWPowerPerpPool memory mintNewLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.LpWPowerPerpPool)\\n                    );\\n\\n                    uint256 tokenId = ControllerHelperUtil.lpWPowerPerpPool(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerpPool,\\n                        wPowerPerp,\\n                        vaultId,\\n                        mintNewLpParams\\n                    );\\n\\n                    // deposit Uni NFT token in vault\\n                    INonfungiblePositionManager(nonfungiblePositionManager).approve(controller, tokenId);\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            IController(controller).withdraw(vaultId, _amount);\\n\\n            // convert flashloaned amount + fee from ETH to WETH to prepare for payback\\n            IWETH9(weth).deposit{value: _amount.add(_premium)}();\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashswapWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWMintParams)\\n            );\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //will revert if data.totalCollateralToDeposit is > eth balance in contract\\n            uint256 vaultId = IController(controller).mintWPowerPerpAmount{value: data.totalCollateralToDeposit}(\\n                data.vaultId,\\n                data.wPowerPerpAmount,\\n                0\\n            );\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(wPowerPerpPool, _amountToPay);\\n\\n            // this is a newly open vault, transfer to the user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            IController(controller).burnWPowerPerpAmount(\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(wPowerPerpPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, data.wPowerPerpAmountToBuy);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            uint256 vaultId = IController(controller).mintWPowerPerpAmount{value: data.collateralAmount}(\\n                data.vaultId,\\n                data.wPowerPerpAmountToMint,\\n                0\\n            );\\n\\n            IWPowerPerp(wPowerPerp).transfer(wPowerPerpPool, _amountToPay);\\n\\n            // this is a newly open vault, transfer to the user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(wPowerPerpPool, _amountToPay);\\n\\n            IWETH9(weth).deposit{value: address(this).balance}();\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(wPowerPerpPool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            IController(controller).burnWPowerPerpAmount(\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            // at this level, we have some ETH from burnWPowerPerpAmount() and maybe WETH from closing LP position\\n            // need to convert all to WETH to make sure we using all available balance for flashswap and flashloan repayment\\n            IWETH9(weth).deposit{value: address(this).balance}();\\n\\n            IWETH9(weth).transfer(wPowerPerpPool, _amountToPay);\\n        }\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp\\n    ) private {\\n        if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n            // swap needed wPowerPerp amount to close short position\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(wPowerPerpPool).fee(),\\n                _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount),\\n                _limitPriceEthPerPowerPerp.mul(_wPowerPerpAmountToBurn.sub(_wPowerPerpAmount)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n            );\\n        } else {\\n            // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n            IController(controller).burnWPowerPerpAmount(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw);\\n\\n            uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n            if (wPowerPerpExcess > 0) {\\n                _exactInFlashSwap(\\n                    wPowerPerp,\\n                    weth,\\n                    IUniswapV3Pool(wPowerPerpPool).fee(),\\n                    wPowerPerpExcess,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                    \\\"\\\"\\n                );\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/AaveControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\nimport {IFlashLoanReceiver} from \\\"../interfaces/IFlashLoanReceiver.sol\\\";\\nimport {ILendingPoolAddressesProvider} from \\\"../interfaces/ILendingPoolAddressesProvider.sol\\\";\\nimport {ILendingPool} from \\\"../interfaces/ILendingPool.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ncontract AaveControllerHelper is IFlashLoanReceiver {\\n    using SafeMath for uint256;\\n\\n    ILendingPoolAddressesProvider public immutable override ADDRESSES_PROVIDER;\\n    ILendingPool public immutable override LENDING_POOL;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(address _provider) {\\n        ADDRESSES_PROVIDER = ILendingPoolAddressesProvider(_provider);\\n        // make sure this work for tests file where _provider == 0x0\\n        (_provider != address(0))\\n            ? LENDING_POOL = ILendingPool(ILendingPoolAddressesProvider(_provider).getLendingPool())\\n            : ILendingPool(address(0));\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint256 _premium,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function executeOperation(\\n        address[] calldata assets,\\n        uint256[] calldata amounts,\\n        uint256[] calldata premiums,\\n        address, /*initiator*/\\n        bytes calldata params\\n    ) external override returns (bool) {\\n        // sanity checks\\n        require(msg.sender == address(LENDING_POOL));\\n        require(assets.length == 1);\\n\\n        FlashloanCallbackData memory data = abi.decode(params, (FlashloanCallbackData));\\n\\n        // this assume that this contract will never flashloan more than 1 asset\\n        _flashCallback(data.caller, assets[0], amounts[0], premiums[0], data.callSource, data.callData);\\n\\n        // Approve the LENDING_POOL contract allowance to *pull* the owed amount\\n        IERC20Detailed(assets[0]).approve(address(LENDING_POOL), amounts[0].add(premiums[0]));\\n\\n        return true;\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        address[] memory assets = new address[](1);\\n        assets[0] = _asset;\\n\\n        uint256[] memory amounts = new uint256[](1);\\n        amounts[0] = _amount;\\n\\n        uint256[] memory modes = new uint256[](1);\\n        modes[0] = 0;\\n\\n        LENDING_POOL.flashLoan(\\n            address(this),\\n            assets,\\n            amounts,\\n            modes,\\n            address(this),\\n            abi.encode(FlashloanCallbackData({caller: msg.sender, callSource: _callSource, callData: _data})),\\n            0\\n        );\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IFlashLoanReceiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\n\\nimport {ILendingPoolAddressesProvider} from \\\"./ILendingPoolAddressesProvider.sol\\\";\\nimport {ILendingPool} from \\\"./ILendingPool.sol\\\";\\n\\n/**\\n * @title IFlashLoanReceiver interface\\n * @notice Interface for the Aave fee IFlashLoanReceiver.\\n * @author Aave\\n * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\\n **/\\ninterface IFlashLoanReceiver {\\n    function executeOperation(\\n        address[] calldata assets,\\n        uint256[] calldata amounts,\\n        uint256[] calldata premiums,\\n        address initiator,\\n        bytes calldata params\\n    ) external returns (bool);\\n\\n    function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider);\\n\\n    function LENDING_POOL() external view returns (ILendingPool);\\n}\\n\"\n    },\n    \"contracts/interfaces/ILendingPoolAddressesProvider.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\n\\n/**\\n * @title LendingPoolAddressesProvider contract\\n * @dev Main registry of addresses part of or connected to the protocol, including permissioned roles\\n * - Acting also as factory of proxies and admin of those, so with right to change its implementations\\n * - Owned by the Aave Governance\\n * @author Aave\\n **/\\ninterface ILendingPoolAddressesProvider {\\n    event MarketIdSet(string newMarketId);\\n    event LendingPoolUpdated(address indexed newAddress);\\n    event ConfigurationAdminUpdated(address indexed newAddress);\\n    event EmergencyAdminUpdated(address indexed newAddress);\\n    event LendingPoolConfiguratorUpdated(address indexed newAddress);\\n    event LendingPoolCollateralManagerUpdated(address indexed newAddress);\\n    event PriceOracleUpdated(address indexed newAddress);\\n    event LendingRateOracleUpdated(address indexed newAddress);\\n    event ProxyCreated(bytes32 id, address indexed newAddress);\\n    event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);\\n\\n    function getMarketId() external view returns (string memory);\\n\\n    function setMarketId(string calldata marketId) external;\\n\\n    function setAddress(bytes32 id, address newAddress) external;\\n\\n    function setAddressAsProxy(bytes32 id, address impl) external;\\n\\n    function getAddress(bytes32 id) external view returns (address);\\n\\n    function getLendingPool() external view returns (address);\\n\\n    function setLendingPoolImpl(address pool) external;\\n\\n    function getLendingPoolConfigurator() external view returns (address);\\n\\n    function setLendingPoolConfiguratorImpl(address configurator) external;\\n\\n    function getLendingPoolCollateralManager() external view returns (address);\\n\\n    function setLendingPoolCollateralManager(address manager) external;\\n\\n    function getPoolAdmin() external view returns (address);\\n\\n    function setPoolAdmin(address admin) external;\\n\\n    function getEmergencyAdmin() external view returns (address);\\n\\n    function setEmergencyAdmin(address admin) external;\\n\\n    function getPriceOracle() external view returns (address);\\n\\n    function setPriceOracle(address priceOracle) external;\\n\\n    function getLendingRateOracle() external view returns (address);\\n\\n    function setLendingRateOracle(address lendingRateOracle) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/ILendingPool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma experimental ABIEncoderV2;\\n\\nimport {ILendingPoolAddressesProvider} from \\\"./ILendingPoolAddressesProvider.sol\\\";\\n\\nlibrary DataTypes {\\n    // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.\\n    struct ReserveData {\\n        //stores the reserve configuration\\n        ReserveConfigurationMap configuration;\\n        //the liquidity index. Expressed in ray\\n        uint128 liquidityIndex;\\n        //variable borrow index. Expressed in ray\\n        uint128 variableBorrowIndex;\\n        //the current supply rate. Expressed in ray\\n        uint128 currentLiquidityRate;\\n        //the current variable borrow rate. Expressed in ray\\n        uint128 currentVariableBorrowRate;\\n        //the current stable borrow rate. Expressed in ray\\n        uint128 currentStableBorrowRate;\\n        uint40 lastUpdateTimestamp;\\n        //tokens addresses\\n        address aTokenAddress;\\n        address stableDebtTokenAddress;\\n        address variableDebtTokenAddress;\\n        //address of the interest rate strategy\\n        address interestRateStrategyAddress;\\n        //the id of the reserve. Represents the position in the list of the active reserves\\n        uint8 id;\\n    }\\n\\n    struct ReserveConfigurationMap {\\n        //bit 0-15: LTV\\n        //bit 16-31: Liq. threshold\\n        //bit 32-47: Liq. bonus\\n        //bit 48-55: Decimals\\n        //bit 56: Reserve is active\\n        //bit 57: reserve is frozen\\n        //bit 58: borrowing is enabled\\n        //bit 59: stable rate borrowing enabled\\n        //bit 60-63: reserved\\n        //bit 64-79: reserve factor\\n        uint256 data;\\n    }\\n\\n    struct UserConfigurationMap {\\n        uint256 data;\\n    }\\n\\n    enum InterestRateMode {\\n        NONE,\\n        STABLE,\\n        VARIABLE\\n    }\\n}\\n\\ninterface ILendingPool {\\n    /**\\n     * @dev Emitted on deposit()\\n     * @param reserve The address of the underlying asset of the reserve\\n     * @param user The address initiating the deposit\\n     * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens\\n     * @param amount The amount deposited\\n     * @param referral The referral code used\\n     **/\\n    event Deposit(\\n        address indexed reserve,\\n        address user,\\n        address indexed onBehalfOf,\\n        uint256 amount,\\n        uint16 indexed referral\\n    );\\n\\n    /**\\n     * @dev Emitted on withdraw()\\n     * @param reserve The address of the underlyng asset being withdrawn\\n     * @param user The address initiating the withdrawal, owner of aTokens\\n     * @param to Address that will receive the underlying\\n     * @param amount The amount to be withdrawn\\n     **/\\n    event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);\\n\\n    /**\\n     * @dev Emitted on borrow() and flashLoan() when debt needs to be opened\\n     * @param reserve The address of the underlying asset being borrowed\\n     * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just\\n     * initiator of the transaction on flashLoan()\\n     * @param onBehalfOf The address that will be getting the debt\\n     * @param amount The amount borrowed out\\n     * @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable\\n     * @param borrowRate The numeric rate at which the user has borrowed\\n     * @param referral The referral code used\\n     **/\\n    event Borrow(\\n        address indexed reserve,\\n        address user,\\n        address indexed onBehalfOf,\\n        uint256 amount,\\n        uint256 borrowRateMode,\\n        uint256 borrowRate,\\n        uint16 indexed referral\\n    );\\n\\n    /**\\n     * @dev Emitted on repay()\\n     * @param reserve The address of the underlying asset of the reserve\\n     * @param user The beneficiary of the repayment, getting his debt reduced\\n     * @param repayer The address of the user initiating the repay(), providing the funds\\n     * @param amount The amount repaid\\n     **/\\n    event Repay(address indexed reserve, address indexed user, address indexed repayer, uint256 amount);\\n\\n    /**\\n     * @dev Emitted on swapBorrowRateMode()\\n     * @param reserve The address of the underlying asset of the reserve\\n     * @param user The address of the user swapping his rate mode\\n     * @param rateMode The rate mode that the user wants to swap to\\n     **/\\n    event Swap(address indexed reserve, address indexed user, uint256 rateMode);\\n\\n    /**\\n     * @dev Emitted on setUserUseReserveAsCollateral()\\n     * @param reserve The address of the underlying asset of the reserve\\n     * @param user The address of the user enabling the usage as collateral\\n     **/\\n    event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);\\n\\n    /**\\n     * @dev Emitted on setUserUseReserveAsCollateral()\\n     * @param reserve The address of the underlying asset of the reserve\\n     * @param user The address of the user enabling the usage as collateral\\n     **/\\n    event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);\\n\\n    /**\\n     * @dev Emitted on rebalanceStableBorrowRate()\\n     * @param reserve The address of the underlying asset of the reserve\\n     * @param user The address of the user for which the rebalance has been executed\\n     **/\\n    event RebalanceStableBorrowRate(address indexed reserve, address indexed user);\\n\\n    /**\\n     * @dev Emitted on flashLoan()\\n     * @param target The address of the flash loan receiver contract\\n     * @param initiator The address initiating the flash loan\\n     * @param asset The address of the asset being flash borrowed\\n     * @param amount The amount flash borrowed\\n     * @param premium The fee flash borrowed\\n     * @param referralCode The referral code used\\n     **/\\n    event FlashLoan(\\n        address indexed target,\\n        address indexed initiator,\\n        address indexed asset,\\n        uint256 amount,\\n        uint256 premium,\\n        uint16 referralCode\\n    );\\n\\n    /**\\n     * @dev Emitted when the pause is triggered.\\n     */\\n    event Paused();\\n\\n    /**\\n     * @dev Emitted when the pause is lifted.\\n     */\\n    event Unpaused();\\n\\n    /**\\n     * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via\\n     * LendingPoolCollateral manager using a DELEGATECALL\\n     * This allows to have the events in the generated ABI for LendingPool.\\n     * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation\\n     * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation\\n     * @param user The address of the borrower getting liquidated\\n     * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover\\n     * @param liquidatedCollateralAmount The amount of collateral received by the liiquidator\\n     * @param liquidator The address of the liquidator\\n     * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants\\n     * to receive the underlying collateral asset directly\\n     **/\\n    event LiquidationCall(\\n        address indexed collateralAsset,\\n        address indexed debtAsset,\\n        address indexed user,\\n        uint256 debtToCover,\\n        uint256 liquidatedCollateralAmount,\\n        address liquidator,\\n        bool receiveAToken\\n    );\\n\\n    /**\\n     * @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared\\n     * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,\\n     * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it\\n     * gets added to the LendingPool ABI\\n     * @param reserve The address of the underlying asset of the reserve\\n     * @param liquidityRate The new liquidity rate\\n     * @param stableBorrowRate The new stable borrow rate\\n     * @param variableBorrowRate The new variable borrow rate\\n     * @param liquidityIndex The new liquidity index\\n     * @param variableBorrowIndex The new variable borrow index\\n     **/\\n    event ReserveDataUpdated(\\n        address indexed reserve,\\n        uint256 liquidityRate,\\n        uint256 stableBorrowRate,\\n        uint256 variableBorrowRate,\\n        uint256 liquidityIndex,\\n        uint256 variableBorrowIndex\\n    );\\n\\n    /**\\n     * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\\n     * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\\n     * @param asset The address of the underlying asset to deposit\\n     * @param amount The amount to be deposited\\n     * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\\n     *   wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\\n     *   is a different wallet\\n     * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\\n     *   0 if the action is executed directly by the user, without any middle-man\\n     **/\\n    function deposit(\\n        address asset,\\n        uint256 amount,\\n        address onBehalfOf,\\n        uint16 referralCode\\n    ) external;\\n\\n    /**\\n     * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\\n     * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\\n     * @param asset The address of the underlying asset to withdraw\\n     * @param amount The underlying amount to be withdrawn\\n     *   - Send the value type(uint256).max in order to withdraw the whole aToken balance\\n     * @param to Address that will receive the underlying, same as msg.sender if the user\\n     *   wants to receive it on his own wallet, or a different address if the beneficiary is a\\n     *   different wallet\\n     * @return The final amount withdrawn\\n     **/\\n    function withdraw(\\n        address asset,\\n        uint256 amount,\\n        address to\\n    ) external returns (uint256);\\n\\n    /**\\n     * @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower\\n     * already deposited enough collateral, or he was given enough allowance by a credit delegator on the\\n     * corresponding debt token (StableDebtToken or VariableDebtToken)\\n     * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet\\n     *   and 100 stable/variable debt tokens, depending on the `interestRateMode`\\n     * @param asset The address of the underlying asset to borrow\\n     * @param amount The amount to be borrowed\\n     * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable\\n     * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\\n     *   0 if the action is executed directly by the user, without any middle-man\\n     * @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself\\n     * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator\\n     * if he has been given credit delegation allowance\\n     **/\\n    function borrow(\\n        address asset,\\n        uint256 amount,\\n        uint256 interestRateMode,\\n        uint16 referralCode,\\n        address onBehalfOf\\n    ) external;\\n\\n    /**\\n     * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned\\n     * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address\\n     * @param asset The address of the borrowed underlying asset previously borrowed\\n     * @param amount The amount to repay\\n     * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`\\n     * @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable\\n     * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the\\n     * user calling the function if he wants to reduce/remove his own debt, or the address of any other\\n     * other borrower whose debt should be removed\\n     * @return The final amount repaid\\n     **/\\n    function repay(\\n        address asset,\\n        uint256 amount,\\n        uint256 rateMode,\\n        address onBehalfOf\\n    ) external returns (uint256);\\n\\n    /**\\n     * @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa\\n     * @param asset The address of the underlying asset borrowed\\n     * @param rateMode The rate mode that the user wants to swap to\\n     **/\\n    function swapBorrowRateMode(address asset, uint256 rateMode) external;\\n\\n    /**\\n     * @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.\\n     * - Users can be rebalanced if the following conditions are satisfied:\\n     *     1. Usage ratio is above 95%\\n     *     2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been\\n     *        borrowed at a stable rate and depositors are not earning enough\\n     * @param asset The address of the underlying asset borrowed\\n     * @param user The address of the user to be rebalanced\\n     **/\\n    function rebalanceStableBorrowRate(address asset, address user) external;\\n\\n    /**\\n     * @dev Allows depositors to enable/disable a specific deposited asset as collateral\\n     * @param asset The address of the underlying asset deposited\\n     * @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise\\n     **/\\n    function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;\\n\\n    /**\\n     * @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1\\n     * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives\\n     *   a proportionally amount of the `collateralAsset` plus a bonus to cover market risk\\n     * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation\\n     * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation\\n     * @param user The address of the borrower getting liquidated\\n     * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover\\n     * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants\\n     * to receive the underlying collateral asset directly\\n     **/\\n    function liquidationCall(\\n        address collateralAsset,\\n        address debtAsset,\\n        address user,\\n        uint256 debtToCover,\\n        bool receiveAToken\\n    ) external;\\n\\n    /**\\n     * @dev Allows smartcontracts to access the liquidity of the pool within one transaction,\\n     * as long as the amount taken plus a fee is returned.\\n     * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration.\\n     * For further details please visit https://developers.aave.com\\n     * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface\\n     * @param assets The addresses of the assets being flash-borrowed\\n     * @param amounts The amounts amounts being flash-borrowed\\n     * @param modes Types of the debt to open if the flash loan is not returned:\\n     *   0 -> Don't open any debt, just revert if funds can't be transferred from the receiver\\n     *   1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address\\n     *   2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address\\n     * @param onBehalfOf The address  that will receive the debt in the case of using on `modes` 1 or 2\\n     * @param params Variadic packed params to pass to the receiver as extra information\\n     * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\\n     *   0 if the action is executed directly by the user, without any middle-man\\n     **/\\n    function flashLoan(\\n        address receiverAddress,\\n        address[] calldata assets,\\n        uint256[] calldata amounts,\\n        uint256[] calldata modes,\\n        address onBehalfOf,\\n        bytes calldata params,\\n        uint16 referralCode\\n    ) external;\\n\\n    /**\\n     * @dev Returns the user account data across all the reserves\\n     * @param user The address of the user\\n     * @return totalCollateralETH the total collateral in ETH of the user\\n     * @return totalDebtETH the total debt in ETH of the user\\n     * @return availableBorrowsETH the borrowing power left of the user\\n     * @return currentLiquidationThreshold the liquidation threshold of the user\\n     * @return ltv the loan to value of the user\\n     * @return healthFactor the current health factor of the user\\n     **/\\n    function getUserAccountData(address user)\\n        external\\n        view\\n        returns (\\n            uint256 totalCollateralETH,\\n            uint256 totalDebtETH,\\n            uint256 availableBorrowsETH,\\n            uint256 currentLiquidationThreshold,\\n            uint256 ltv,\\n            uint256 healthFactor\\n        );\\n\\n    function initReserve(\\n        address reserve,\\n        address aTokenAddress,\\n        address stableDebtAddress,\\n        address variableDebtAddress,\\n        address interestRateStrategyAddress\\n    ) external;\\n\\n    function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress) external;\\n\\n    function setConfiguration(address reserve, uint256 configuration) external;\\n\\n    /**\\n     * @dev Returns the configuration of the reserve\\n     * @param asset The address of the underlying asset of the reserve\\n     * @return The configuration of the reserve\\n     **/\\n    function getConfiguration(address asset) external view returns (DataTypes.ReserveConfigurationMap memory);\\n\\n    /**\\n     * @dev Returns the configuration of the user across all the reserves\\n     * @param user The user address\\n     * @return The configuration of the user\\n     **/\\n    function getUserConfiguration(address user) external view returns (DataTypes.UserConfigurationMap memory);\\n\\n    /**\\n     * @dev Returns the normalized income normalized income of the reserve\\n     * @param asset The address of the underlying asset of the reserve\\n     * @return The reserve's normalized income\\n     */\\n    function getReserveNormalizedIncome(address asset) external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the normalized variable debt per unit of asset\\n     * @param asset The address of the underlying asset of the reserve\\n     * @return The reserve normalized variable debt\\n     */\\n    function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the state and configuration of the reserve\\n     * @param asset The address of the underlying asset of the reserve\\n     * @return The state of the reserve\\n     **/\\n    function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);\\n\\n    function finalizeTransfer(\\n        address asset,\\n        address from,\\n        address to,\\n        uint256 amount,\\n        uint256 balanceFromAfter,\\n        uint256 balanceToBefore\\n    ) external;\\n\\n    function getReservesList() external view returns (address[] memory);\\n\\n    function getAddressesProvider() external view returns (ILendingPoolAddressesProvider);\\n\\n    function setPause(bool val) external;\\n\\n    function paused() external view returns (bool);\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 5\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/solcInputs/e2a303b98172c2b7a0e4fda5f2d8e859.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // Ceil A to a multiple m\\n    function ceil(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(sub(add(a, m), 1), m), m);\\n    }\\n\\n    // Floor A to a multiple m\\n    function floor(uint a, uint m) internal pure returns(uint z) {\\n        z = mul(div(a, m), m);\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {EIP712} from \\\"@openzeppelin/contracts/drafts/EIP712.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\nimport {Counters} from \\\"@openzeppelin/contracts/utils/Counters.sol\\\";\\nimport {ECDSA} from \\\"@openzeppelin/contracts/cryptography/ECDSA.sol\\\";\\n\\n/**\\n * @dev CrabStrategyV2 contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategyV2 is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable, EIP712 {\\n    using Counters for Counters.Counter;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    // @dev OTC price must be within this distance of the uniswap twap price\\n    uint256 public otcPriceTolerance = 5e16; // 5%\\n\\n    // @dev OTC price tolerance cannot exceed 20%\\n    uint256 public maxOTCPriceTolerance = 2e17; // 20%\\n\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n    /// @dev true if CrabV2 was initialized\\n    bool public isInitialized;\\n\\n    /// @dev typehash for signed orders\\n    bytes32 private constant _CRAB_BALANCE_TYPEHASH =\\n        keccak256(\\n            \\\"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\\\"\\n        );\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n    address public immutable timelock;\\n    address public immutable crabMigration;\\n\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    /// @dev store the current nonce for each address\\n    mapping(address => Counters.Counter) private _nonces;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct Order {\\n        uint256 bidId;\\n        address trader;\\n        uint256 quantity;\\n        uint256 price;\\n        bool isBuying;\\n        uint256 expiry;\\n        uint256 nonce;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event HedgeOTC(address trader, uint256 quantity, uint256 price, bool isBuying, uint256 clearingPrice);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetOTCPriceTolerance(uint256 otcPriceTolerance);\\n    event VaultTransferred(address indexed newStrategy, uint256 vaultId);\\n\\n    modifier onlyTimelock() {\\n        require(msg.sender == timelock, \\\"Caller is not timelock\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialization() {\\n        require(isInitialized, \\\"Contract not yet initialized\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        address _timelock,\\n        address _crabMigration,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold\\n    )\\n        StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy v2\\\", \\\"Crabv2\\\")\\n        StrategyFlashSwap(_uniswapFactory)\\n        EIP712(\\\"CrabOTC\\\", \\\"2\\\")\\n    {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_timelock != address(0), \\\"invalid timelock address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_crabMigration != address(0), \\\"invalid crabMigration address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n        timelock = _timelock;\\n        crabMigration = _crabMigration;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice initializes the collateral ratio upon the first migration\\n     */\\n    function initialize(\\n        uint256 _wSqueethToMint,\\n        uint256 _crabSharesToMint,\\n        uint256 _timeAtLastHedge,\\n        uint256 _priceAtLastHedge\\n    ) external payable {\\n        require(msg.sender == crabMigration, \\\"not Crab Migration contract\\\");\\n        require(!isInitialized, \\\"Crab V2 already initialized\\\");\\n\\n        uint256 amount = msg.value;\\n        uint256 strategyDebt;\\n        uint256 strategyCollateral;\\n\\n        _checkStrategyCap(amount, strategyCollateral);\\n\\n        require((strategyDebt == 0 && strategyCollateral == 0), \\\"C5\\\");\\n        // store hedge data from crab v1\\n        timeAtLastHedge = _timeAtLastHedge;\\n        priceAtLastHedge = _priceAtLastHedge;\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(msg.sender, _wSqueethToMint, amount, false);\\n        // mint LP to depositor\\n        _mintStrategyToken(msg.sender, _crabSharesToMint);\\n\\n        isInitialized = true;\\n    }\\n\\n    /**\\n     * @notice Tranfer vault NFT to new contract\\n     * @dev strategy cap is set to 0 to avoid future deposits.\\n     */\\n    function transferVault(address _newStrategy) external onlyTimelock afterInitialization {\\n        IShortPowerPerp(powerTokenController.shortPowerPerp()).safeTransferFrom(address(this), _newStrategy, vaultId);\\n        _setStrategyCap(0);\\n\\n        emit VaultTransferred(_newStrategy, vaultId);\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        _setStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice set strategy cap amount\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function _setStrategyCap(uint256 _capAmount) internal {\\n        strategyCap = _capAmount;\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external afterInitialization {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable afterInitialization nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external afterInitialization nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable afterInitialization nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external afterInitialization nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external afterInitialization nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\\n     */\\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\\n        // Tolerance cannot be more than 20%\\n        require(_otcPriceTolerance <= maxOTCPriceTolerance, \\\"price tolerance is too high\\\");\\n\\n        otcPriceTolerance = _otcPriceTolerance;\\n\\n        emit SetOTCPriceTolerance(_otcPriceTolerance);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @dev increment current nonce of the address\\n     * @param _owner address of signer\\n     * @return current the current nonce of the address\\n     */\\n    function _useNonce(address _owner) internal returns (uint256 current) {\\n        Counters.Counter storage nonce = _nonces[_owner];\\n        current = nonce.current();\\n        nonce.increment();\\n    }\\n\\n    /*\\n     * @notice user can increment their own nonce to cancel previous orders\\n     * @return new nonce for user\\n     */\\n    function incrementNonce() external returns (uint256 current) {\\n        Counters.Counter storage nonce = _nonces[msg.sender];\\n        nonce.increment();\\n        current = nonce.current();\\n    }\\n\\n    /**\\n     * @dev get current nonce of the address\\n     * @param _owner address of signer\\n     * @return current the current nonce of the address\\n     */\\n    function nonces(address _owner) external view returns (uint256) {\\n        return _nonces[_owner].current();\\n    }\\n\\n    /**\\n     * @dev view function to get the domain seperator used in signing\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev check the signer and swap tokens in the order\\n     * @param _remainingAmount quantity the manager wants to sell\\n     * @param _clearingPrice the price at which the manager is buying\\n     * @param _order a signed order to swap tokens\\n     */\\n    function _execOrder(\\n        uint256 _remainingAmount,\\n        uint256 _clearingPrice,\\n        Order memory _order\\n    ) internal {\\n        // Check order beats clearing price\\n        if (_order.isBuying) {\\n            require(_clearingPrice <= _order.price, \\\"Clearing Price should be below bid price\\\");\\n        } else {\\n            require(_clearingPrice >= _order.price, \\\"Clearing Price should be above offer price\\\");\\n        }\\n\\n        bytes32 structHash = keccak256(\\n            abi.encode(\\n                _CRAB_BALANCE_TYPEHASH,\\n                _order.bidId,\\n                _order.trader,\\n                _order.quantity,\\n                _order.price,\\n                _order.isBuying,\\n                _order.expiry,\\n                _useNonce(_order.trader)\\n            )\\n        );\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\\n        require(offerSigner == _order.trader, \\\"Invalid offer signature\\\");\\n        require(_order.expiry >= block.timestamp, \\\"Order has expired\\\");\\n\\n        //adjust quantity for partial fills\\n        if (_remainingAmount < _order.quantity) {\\n            _order.quantity = _remainingAmount;\\n        }\\n        // weth clearing price for the order\\n        uint256 wethAmount = _order.quantity.mul(_clearingPrice).div(1e18);\\n\\n        if (_order.isBuying) {\\n            // trader sends weth and receives oSQTH\\n            IERC20(weth).transferFrom(_order.trader, address(this), wethAmount);\\n            IWETH9(weth).withdraw(wethAmount);\\n            _mintWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n        } else {\\n            // trader sends oSQTH and receives weth\\n            _burnWPowerPerp(_order.trader, _order.quantity, wethAmount, false);\\n            //wrap it\\n            IWETH9(weth).deposit{value: wethAmount}();\\n            IERC20(weth).transfer(_order.trader, wethAmount);\\n        }\\n\\n        emit HedgeOTC(\\n            _order.trader, // market maker\\n            _order.quantity, // order oSQTH quantity\\n            _order.price, // order price\\n            _order.isBuying, // order direction\\n            _clearingPrice // executed price for order\\n        );\\n    }\\n\\n    /**\\n     * @dev hedge function to reduce delta using an array of signed orders\\n     * @param _totalQuantity quantity the manager wants to trade\\n     * @param _clearingPrice clearing price in weth\\n     * @param _isHedgeBuying direction of hedge trade\\n     * @param _orders an array of signed order to swap tokens\\n     */\\n    function hedgeOTC(\\n        uint256 _totalQuantity,\\n        uint256 _clearingPrice,\\n        bool _isHedgeBuying,\\n        Order[] memory _orders\\n    ) external onlyOwner afterInitialization {\\n        require(_clearingPrice > 0, \\\"Manager Price should be greater than 0\\\");\\n        require(_isTimeHedge() || _isPriceHedge(), \\\"Time or Price is not within range\\\");\\n        _checkOTCPrice(_clearingPrice, _isHedgeBuying);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = _clearingPrice;\\n\\n        uint256 remainingAmount = _totalQuantity;\\n        uint256 prevPrice = _orders[0].price;\\n        uint256 currentPrice = _orders[0].price;\\n        bool isOrderBuying = _orders[0].isBuying;\\n        require(_isHedgeBuying != isOrderBuying, \\\"Orders must be buying when hedge is selling\\\");\\n\\n        for (uint256 i = 0; i < _orders.length; i++) {\\n            currentPrice = _orders[i].price;\\n            require(_orders[i].isBuying == isOrderBuying, \\\"All orders must be either buying or selling\\\");\\n            if (_isHedgeBuying) {\\n                require(currentPrice >= prevPrice, \\\"Orders are not arranged properly\\\");\\n            } else {\\n                require(currentPrice <= prevPrice, \\\"Orders are not arranged properly\\\");\\n            }\\n            prevPrice = currentPrice;\\n\\n            _execOrder(remainingAmount, _clearingPrice, _orders[i]);\\n\\n            if (remainingAmount > _orders[i].quantity) {\\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\\n            } else {\\n                break;\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\\n     * @param _price clearing price provided by manager\\n     * @param _isHedgeBuying is crab buying or selling oSQTH\\n     */\\n    function _checkOTCPrice(uint256 _price, bool _isHedgeBuying) internal view {\\n        // Get twap\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n\\n        if (_isHedgeBuying) {\\n            require(\\n                _price <= wSqueethEthPrice.mul((ONE.add(otcPriceTolerance))).div(ONE),\\n                \\\"Price too high relative to Uniswap twap.\\\"\\n            );\\n        } else {\\n            require(\\n                _price >= wSqueethEthPrice.mul((ONE.sub(otcPriceTolerance))).div(ONE),\\n                \\\"Price too low relative to Uniswap twap.\\\"\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        bool isShutdown = (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) && (totalSupply() != 0);\\n        require(!isShutdown, \\\"Crab contracts shut down\\\");\\n\\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n        );\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     */\\n    function _isTimeHedge() internal view returns (bool) {\\n        return (block.timestamp >= timeAtLastHedge.add(hedgeTimeThreshold));\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge() internal view returns (bool) {\\n        uint256 wSqueethEthPrice = IOracle(oracle).getTwap(ethWSqueethPool, wPowerPerp, weth, hedgingTwapPeriod, true);\\n        uint256 cachedRatio = wSqueethEthPrice.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge() external view returns (bool) {\\n        return _isPriceHedge();\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if hedging is allowed\\n     */\\n    function checkTimeHedge() external view returns (bool) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/drafts/EIP712.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = _getChainId();\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        if (_getChainId() == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {\\n        return keccak256(\\n            abi.encode(\\n                typeHash,\\n                name,\\n                version,\\n                _getChainId(),\\n                address(this)\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Counters.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../math/SafeMath.sol\\\";\\n\\n/**\\n * @title Counters\\n * @author Matt Condon (@shrugs)\\n * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number\\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\\n *\\n * Include with `using Counters for Counters.Counter;`\\n * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}\\n * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never\\n * directly accessed.\\n */\\nlibrary Counters {\\n    using SafeMath for uint256;\\n\\n    struct Counter {\\n        // This variable should never be directly accessed by users of the library: interactions must be restricted to\\n        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\\n        // this feature: see https://github.com/ethereum/solidity/issues/4637\\n        uint256 _value; // default: 0\\n    }\\n\\n    function current(Counter storage counter) internal view returns (uint256) {\\n        return counter._value;\\n    }\\n\\n    function increment(Counter storage counter) internal {\\n        // The {SafeMath} overflow check can be skipped here, see the comment at the top\\n        counter._value += 1;\\n    }\\n\\n    function decrement(Counter storage counter) internal {\\n        counter._value = counter._value.sub(1);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/cryptography/ECDSA.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        // Check the signature length\\n        if (signature.length != 65) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        }\\n\\n        // Divide the signature in r, s and v variables\\n        bytes32 r;\\n        bytes32 s;\\n        uint8 v;\\n\\n        // ecrecover takes the signature parameters, and the only way to get them\\n        // currently is to use assembly.\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            r := mload(add(signature, 0x20))\\n            s := mload(add(signature, 0x40))\\n            v := byte(0, mload(add(signature, 0x60)))\\n        }\\n\\n        return recover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, \\\"ECDSA: invalid signature 's' value\\\");\\n        require(v == 27 || v == 28, \\\"ECDSA: invalid signature 'v' value\\\");\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        require(signer != address(0), \\\"ECDSA: invalid signature\\\");\\n\\n        return signer;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * replicates the behavior of the\\n     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]\\n     * JSON-RPC method.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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        // solhint-disable-next-line max-line-length\\n        require((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(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\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) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabMigration.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {SafeERC20} from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport {IEulerExec, IDToken} from \\\"../interfaces/IEuler.sol\\\";\\nimport {WETH9} from \\\"../external/WETH9.sol\\\";\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// contract\\nimport {CrabStrategyV2} from \\\"./CrabStrategyV2.sol\\\";\\nimport {CrabStrategy} from \\\"./CrabStrategy.sol\\\";\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\n\\n/**\\n * Migration Error Codes:\\n * M1: Crab V2 Address already set\\n * M2: Migration already happened\\n * M3: Migration has not yet happened\\n * M4: msg.sender is not Euler Mainnet Contract\\n * M5: msg. sender cannot send ETH\\n * M6: Can't withdraw more than you own\\n * M7: Not enough ETH to repay the loan\\n * M8: _ethToBorrow or _withdrawMaxEthToPay can't be 0\\n * M9: invalid crabV2 address\\n * M10: crab v2 address not yet set\\n * M11: Wrong migration function, use flashMigrateAndWithdrawFromV1toV2\\n * M12: Wrong migration function, use flashMigrateFromV1toV2\\n */\\n\\n/**\\n * @dev CrabMigration contract\\n * @notice Contract for Migrating from Crab v1 to Crab v2\\n * @author Opyn team\\n */\\ncontract CrabMigration is Ownable {\\n    using SafeERC20 for IERC20;\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    mapping(address => uint256) public sharesDeposited;\\n    bool public isMigrated;\\n    CrabStrategy public crabV1;\\n    CrabStrategyV2 public crabV2;\\n    IEulerExec public euler;\\n    WETH9 weth;\\n\\n    uint256 public totalCrabV1SharesMigrated;\\n    uint256 public totalCrabV2SharesReceived;\\n    address immutable EULER_MAINNET;\\n    address immutable dToken;\\n    address immutable wPowerPerp;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    struct FlashMigrateV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 crabV1ToWithdraw;\\n    }\\n\\n    struct FlashMigrateAndBuyV1toV2 {\\n        uint256 v1oSqthToPay;\\n        uint256 ethToFlashDeposit;\\n        uint256 withdrawMaxEthToPay;\\n        uint256 crabV1ToWithdraw;\\n    }\\n\\n    enum FLASH_SOURCE {\\n        BATCH_MIGRATE,\\n        FLASH_MIGRATE_V1_TO_V2,\\n        FLASH_MIGRATE_WITHDRAW_V1_TO_V2\\n    }\\n\\n    event ClaimAndWithdraw(address indexed user, uint256 crabAmount);\\n\\n    modifier beforeMigration() {\\n        require(!isMigrated, \\\"M2\\\");\\n        _;\\n    }\\n\\n    modifier afterMigration() {\\n        require(isMigrated, \\\"M3\\\");\\n        _;\\n    }\\n\\n    modifier afterInitialized() {\\n        require(address(crabV2) != address(0), \\\"M8\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice migration constructor\\n     * @param _crabV1 address of crab v1\\n     * @param _weth address of weth\\n     * @param _eulerExec address of euler exec contract\\n     * @param _dToken address of euler deposit token\\n     * @param _eulerMainnet address of euler deployment on mainnet\\n     */\\n    constructor(\\n        address payable _crabV1,\\n        address _weth,\\n        address _eulerExec,\\n        address _dToken,\\n        address _eulerMainnet\\n    ) {\\n        crabV1 = CrabStrategy(_crabV1);\\n        euler = IEulerExec(_eulerExec);\\n        EULER_MAINNET = _eulerMainnet;\\n        weth = WETH9(_weth);\\n        dToken = _dToken;\\n        wPowerPerp = crabV1.wPowerPerp();\\n    }\\n\\n    /**\\n     * @notice set the crabV2 address\\n     * @param _crabV2 address of crab v2\\n     */\\n    function setCrabV2(address payable _crabV2) external onlyOwner {\\n        require(address(crabV2) == address(0), \\\"M1\\\");\\n        require(_crabV2 != address(0), \\\"M9\\\");\\n        crabV2 = CrabStrategyV2(_crabV2);\\n    }\\n\\n    /**\\n     * @notice allows users to deposit their crab v1 shares in the pool for migration\\n     */\\n    function depositV1Shares(uint256 amount) external afterInitialized beforeMigration {\\n        sharesDeposited[msg.sender] += amount;\\n        totalCrabV1SharesMigrated += amount;\\n        crabV1.transferFrom(msg.sender, address(this), amount);\\n    }\\n\\n    /**\\n     * @notice the owner batch migrates all the crab v1 shares in this contract to crab v2 and initializes\\n     * the v2 contract at the same collateral ratio as the v1 contract.\\n     */\\n    function batchMigrate() external onlyOwner afterInitialized beforeMigration {\\n        // 1. update isMigrated\\n        isMigrated = true;\\n\\n        // 2. flash floan eth from euler eq to amt\\n        uint256 crabV1Balance = crabV1.balanceOf(address(this));\\n        uint256 crabV1Supply = crabV1.totalSupply();\\n        (, , uint256 totalCollateral, ) = crabV1.getVaultDetails();\\n        uint256 amountEthToBorrow = totalCollateral.wmul(crabV1Balance.wdiv(crabV1Supply));\\n        bytes memory data;\\n        euler.deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: amountEthToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.BATCH_MIGRATE),\\n                    callData: data\\n                })\\n            )\\n        );\\n\\n        // 3. record totalV2Shares\\n        totalCrabV2SharesReceived = crabV2.balanceOf(address(this));\\n    }\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external afterInitialized {\\n        require(msg.sender == EULER_MAINNET, \\\"M4\\\");\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        // 1. Borrow weth\\n        IDToken(dToken).borrow(0, data.amountToBorrow);\\n        weth.withdraw(data.amountToBorrow);\\n\\n        // 2. Callback\\n        _flashCallback(data.caller, data.amountToBorrow, data.callSource, data.callData);\\n\\n        // 4. Repay the weth:\\n        weth.deposit{value: data.amountToBorrow}();\\n        weth.approve(EULER_MAINNET, type(uint256).max);\\n        IDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.BATCH_MIGRATE) {\\n            uint256 crabV1Balance = crabV1.balanceOf(address(this));\\n\\n            // 2. mint osqth in crab v2\\n            uint256 wSqueethToMint = crabV1.getWsqueethFromCrabAmount(crabV1Balance);\\n            uint256 timeAtLastHedge = crabV1.timeAtLastHedge();\\n            uint256 priceAtLastHedge = crabV1.priceAtLastHedge();\\n            crabV2.initialize{value: _amount}(\\n                wSqueethToMint,\\n                totalCrabV1SharesMigrated,\\n                timeAtLastHedge,\\n                priceAtLastHedge\\n            );\\n\\n            // 3. call withdraw from crab v1\\n            IERC20(wPowerPerp).approve(address(crabV1), type(uint256).max);\\n            crabV1.approve(address(crabV1), crabV1Balance);\\n            crabV1.withdraw(crabV1Balance);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2) {\\n            FlashMigrateV1toV2 memory data = abi.decode(_calldata, (FlashMigrateV1toV2));\\n\\n            crabV2.deposit{value: _amount}();\\n\\n            crabV1.transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n\\n            IERC20(wPowerPerp).approve(address(crabV1), data.v1oSqthToPay);\\n            crabV1.withdraw(data.crabV1ToWithdraw);\\n\\n            // Flash deposit remaining ETH, if user said so. Else return back the ETH. If CR1 = CR2 ethToFlashDeposit should be 0\\n            if (data.ethToFlashDeposit > 0) {\\n                crabV2.flashDeposit{value: address(this).balance.sub(_amount)}(data.ethToFlashDeposit);\\n            }\\n\\n            // Sent back the V2 tokens to the user\\n            crabV2.transfer(_initiator, crabV2.balanceOf(address(this)));\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            // Sent back the excess ETH\\n            if (address(this).balance > _amount) {\\n                payable(_initiator).sendValue(address(this).balance.sub(_amount));\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2) {\\n            FlashMigrateAndBuyV1toV2 memory data = abi.decode(_calldata, (FlashMigrateAndBuyV1toV2));\\n            (, , , uint256 v1Short) = crabV1.getVaultDetails();\\n\\n            crabV1.transferFrom(_initiator, address(this), data.crabV1ToWithdraw);\\n            crabV2.deposit{value: _amount}();\\n\\n            uint256 oSqthToPay = IERC20(wPowerPerp).balanceOf(address(this));\\n            IERC20(wPowerPerp).approve(address(crabV1), oSqthToPay);\\n\\n            // Find crab amount for contract's sqth balance. Remaining crab sould be withdrawn using flash withdraw\\n            uint256 crabV1ToWithdrawRmul = oSqthToPay.wmul(crabV1.totalSupply()).rdiv(v1Short);\\n            uint256 crabV1ToWithdraw = crabV1ToWithdrawRmul.floor(10**9) / (10**9);\\n\\n            crabV1.withdraw(crabV1ToWithdraw);\\n\\n            crabV1.flashWithdraw(data.crabV1ToWithdraw.sub(crabV1ToWithdraw), data.withdrawMaxEthToPay);\\n            require(address(this).balance >= _amount, \\\"M7\\\");\\n\\n            if (data.ethToFlashDeposit > 0) {\\n                crabV2.flashDeposit{value: address(this).balance.sub(_amount)}(data.ethToFlashDeposit);\\n            }\\n\\n            // Sent back the V2 tokens to the user\\n            crabV2.transfer(_initiator, crabV2.balanceOf(address(this)));\\n            IERC20(wPowerPerp).transfer(_initiator, IERC20(wPowerPerp).balanceOf(address(this)));\\n\\n            // Sent back the excess ETH\\n            if (address(this).balance > _amount) {\\n                payable(_initiator).sendValue(address(this).balance.sub(_amount));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice allows users to claim their amount of crab v2 shares\\n     */\\n    function claimV2Shares() external afterMigration {\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        sharesDeposited[msg.sender] = 0;\\n        uint256 amountV2ToTransfer = amountV1Deposited.wmul(totalCrabV2SharesReceived).wdiv(totalCrabV1SharesMigrated);\\n        crabV2.transfer(msg.sender, amountV2ToTransfer);\\n    }\\n\\n    /**\\n     * @notice allows users to claim crabV2 shares and flash withdraw from crabV2\\n     *\\n     * @param _amountToWithdraw V2 shares to claim\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function claimAndWithdraw(uint256 _amountToWithdraw, uint256 _maxEthToPay) external afterMigration {\\n        uint256 amountV1toClaim = _getV1SharesForV2Share(_amountToWithdraw);\\n        uint256 amountV1Deposited = sharesDeposited[msg.sender];\\n        require(amountV1toClaim <= amountV1Deposited, \\\"M6\\\");\\n\\n        sharesDeposited[msg.sender] = amountV1Deposited.sub(amountV1toClaim);\\n        crabV2.flashWithdraw(_amountToWithdraw, _maxEthToPay);\\n\\n        emit ClaimAndWithdraw(msg.sender, _amountToWithdraw);\\n\\n        // Pay user's ETH back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @notice For input v2 shares returns the equivalent v1 shares\\n     */\\n    function _getV1SharesForV2Share(uint256 _amountV2) internal view returns (uint256) {\\n        return _amountV2.wmul(totalCrabV1SharesMigrated).wdiv(totalCrabV2SharesReceived);\\n    }\\n\\n    function flashMigrationDetails(uint256 _v1Shares)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return _flashMigrationDetails(_v1Shares);\\n    }\\n\\n    /**\\n     * @notice Used to migrate from crab V1 to crab V2 when CR1 >= CR2\\n     *\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit Flash deposit amount in crab v2 with excess ETH. If 0 will returned to sender\\n     */\\n    function flashMigrateFromV1toV2(uint256 _v1Shares, uint256 _ethToFlashDeposit) external afterMigration {\\n        (bool isFlashOnlyMigrate, uint256 ethNeededForV2, uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(isFlashOnlyMigrate, \\\"M11\\\");\\n\\n        euler.deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: ethNeededForV2,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateV1toV2({\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            crabV1ToWithdraw: _v1Shares\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Used to migrate from crab V1 to crab V2 when CR1 < CR2\\n     *\\n     * @param _v1Shares V1 shares to migrate\\n     * @param _ethToFlashDeposit Flash deposit amount in crab v2 with excess ETH. If 0 will returned to sender\\n     * @param _ethToBorrow Amount to flash loan to deposit in crab v2\\n     * @param _withdrawMaxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashMigrateAndWithdrawFromV1toV2(\\n        uint256 _v1Shares,\\n        uint256 _ethToFlashDeposit,\\n        uint256 _ethToBorrow,\\n        uint256 _withdrawMaxEthToPay\\n    ) external afterMigration {\\n        (bool isFlashOnlyMigrate, , uint256 v1oSqthToPay, ) = _flashMigrationDetails(_v1Shares);\\n\\n        require(!isFlashOnlyMigrate, \\\"M12\\\");\\n        require(_ethToBorrow > 0 && _withdrawMaxEthToPay > 0, \\\"M8\\\");\\n\\n        euler.deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    amountToBorrow: _ethToBorrow,\\n                    callSource: uint8(FLASH_SOURCE.FLASH_MIGRATE_WITHDRAW_V1_TO_V2),\\n                    callData: abi.encode(\\n                        FlashMigrateAndBuyV1toV2({\\n                            withdrawMaxEthToPay: _withdrawMaxEthToPay,\\n                            ethToFlashDeposit: _ethToFlashDeposit,\\n                            v1oSqthToPay: v1oSqthToPay,\\n                            crabV1ToWithdraw: _v1Shares\\n                        })\\n                    )\\n                })\\n            )\\n        );\\n    }\\n\\n    /**\\n     * @notice Get migration details for given amount of v1 shares\\n     */\\n    function _flashMigrationDetails(uint256 _v1Shares)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (, , uint256 v1TotalCollateral, uint256 v1TotalShort) = crabV1.getVaultDetails();\\n        (, , uint256 v2TotalCollateral, uint256 v2TotalShort) = crabV2.getVaultDetails();\\n\\n        uint256 v1oSqthToPay = v1TotalShort.wmul(_v1Shares).wdiv(crabV1.totalSupply());\\n        uint256 ethNeededForV2 = v1oSqthToPay.wmul(v2TotalCollateral).rdiv(v2TotalShort).ceil(10**9) / (10**9);\\n        uint256 ethToGetFromV1 = _v1Shares.wdiv(crabV1.totalSupply()).wmul(v1TotalCollateral);\\n\\n        return (ethNeededForV2 <= ethToGetFromV1, ethNeededForV2, v1oSqthToPay, ethToGetFromV1);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(crabV1) || msg.sender == address(crabV2), \\\"M5\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IEuler.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\ninterface IEulerExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\"\n    },\n    \"contracts/external/WETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n// copied from https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol\\n\\ncontract WETH9 {\\n    string public name = \\\"Wrapped Ether\\\";\\n    string public symbol = \\\"WETH\\\";\\n    uint8 public decimals = 18;\\n\\n    event Approval(address indexed src, address indexed guy, uint256 wad);\\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\\n    event Deposit(address indexed dst, uint256 wad);\\n    event Withdrawal(address indexed src, uint256 wad);\\n\\n    mapping(address => uint256) public balanceOf;\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    function deposit() public payable {\\n        balanceOf[msg.sender] += msg.value;\\n        emit Deposit(msg.sender, msg.value);\\n    }\\n\\n    function withdraw(uint256 wad) public {\\n        require(balanceOf[msg.sender] >= wad);\\n        balanceOf[msg.sender] -= wad;\\n        payable(msg.sender).transfer(wad);\\n        emit Withdrawal(msg.sender, wad);\\n    }\\n\\n    function totalSupply() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    function approve(address guy, uint256 wad) public returns (bool) {\\n        allowance[msg.sender][guy] = wad;\\n        emit Approval(msg.sender, guy, wad);\\n        return true;\\n    }\\n\\n    function transfer(address dst, uint256 wad) public returns (bool) {\\n        return transferFrom(msg.sender, dst, wad);\\n    }\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 wad\\n    ) public returns (bool) {\\n        require(balanceOf[src] >= wad);\\n\\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\\n            require(allowance[src][msg.sender] >= wad);\\n            allowance[src][msg.sender] -= wad;\\n        }\\n\\n        balanceOf[src] -= wad;\\n        balanceOf[dst] += wad;\\n\\n        emit Transfer(src, dst, wad);\\n\\n        return true;\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockEulerDToken.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockEulerDToken {\\n    ERC20 weth;\\n\\n    constructor(address _weth) {\\n        weth = ERC20(_weth);\\n    }\\n\\n    function borrow(uint256, uint256 amount) external {\\n        weth.transfer(msg.sender, amount);\\n    }\\n\\n    function repay(uint256, uint256 amount) external {\\n        weth.transferFrom(msg.sender, address(this), amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockCrab.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\n\\n// interface\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockCrab is ERC20 {\\n    address operator;\\n    uint256 vaultId;\\n    uint256 collateral;\\n    uint256 short;\\n    address public wPowerPerp;\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n\\n    function setVaultDetails(\\n        uint256 _vaultId,\\n        uint256 _collateral,\\n        uint256 _short\\n    ) external {\\n        vaultId = _vaultId;\\n        collateral = _collateral;\\n        short = _short;\\n    }\\n\\n    function getVaultDetails()\\n        external\\n        view\\n        returns (\\n            address,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        return (operator, vaultId, collateral, short);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/helper/StrategySwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract StrategySwap {\\n    ISwapRouter public immutable swapRouter;\\n\\n    constructor(address _swapRouter) {\\n        require(_swapRouter != address(0), \\\"invalid swap router address\\\");\\n        swapRouter = ISwapRouter(_swapRouter);\\n    }\\n\\n    /**\\n     * @notice swapExactInputSingle swaps a given amount of tokenIn for a maximum possible amount of tokenOut\\n     * @dev The calling address must approve this contract to spend at least `amountIn` worth of its tokenIn for this function to succeed.\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _from from which user we are selling\\n     * @param _to Recipient to get the tokens\\n     * @param _amountIn Exact amount to sell\\n     * @param _minAmountOut Minimum amount to be paid\\n     * @param _fee pool fee\\n     * @return amountOut The amount of WETH9 received.\\n     */\\n    function _swapExactInputSingle(\\n        address _tokenIn,\\n        address _tokenOut,\\n        address _from,\\n        address _to,\\n        uint256 _amountIn,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) internal returns (uint256 amountOut) {\\n        // _from must approve this contract\\n\\n        // Transfer the specified amount of tokenIn to this contract.\\n        IERC20(_tokenIn).transferFrom(_from, address(this), _amountIn);\\n\\n        // Approve the router to spend tokenIn.\\n        IERC20(_tokenIn).approve(address(swapRouter), _amountIn);\\n\\n        // We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.\\n        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\\n            tokenIn: _tokenIn,\\n            tokenOut: _tokenOut,\\n            fee: _fee,\\n            recipient: _to,\\n            deadline: block.timestamp,\\n            amountIn: _amountIn,\\n            amountOutMinimum: _minAmountOut,\\n            sqrtPriceLimitX96: 0\\n        });\\n\\n        // The call to `exactInputSingle` executes the swap.\\n        amountOut = swapRouter.exactInputSingle(params);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/CrabHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\nimport {ICrabStrategyV2} from \\\"../interfaces/ICrabStrategyV2.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {StrategySwap} from \\\"./helper/StrategySwap.sol\\\";\\n\\n/**\\n * @dev CrabHelper contract\\n * @notice Contract for Crab helper functions\\n * @author Opyn team\\n */\\ncontract CrabHelper is StrategySwap, ReentrancyGuard {\\n    using Address for address payable;\\n\\n    address public immutable crab;\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    event FlashDepositERC20(\\n        address indexed depositor,\\n        address depositedERC20,\\n        uint256 depositedAmount,\\n        uint256 depositedEthAmount,\\n        uint256 crabAmount,\\n        uint256 returnedEth\\n    );\\n\\n    event FlashWithdrawERC20(\\n        address indexed withdrawer,\\n        address withdrawnERC20,\\n        uint256 withdrawnAmount,\\n        uint256 withdrawnEthAmount,\\n        uint256 crabAmount\\n    );\\n\\n    constructor(address _crab, address _swapRouter) StrategySwap(_swapRouter) {\\n        require(_crab != address(0), \\\"Invalid crab address\\\");\\n\\n        crab = _crab;\\n        weth = ICrabStrategyV2(_crab).weth();\\n        wPowerPerp = ICrabStrategyV2(_crab).wPowerPerp();\\n    }\\n\\n    function flashDepositERC20(\\n        uint256 _ethToDeposit,\\n        uint256 _amountIn,\\n        uint256 _minEthToGet,\\n        uint24 _fee,\\n        address _tokenIn\\n    ) external nonReentrant {\\n        _swapExactInputSingle(_tokenIn, weth, msg.sender, address(this), _amountIn, _minEthToGet, _fee);\\n\\n        IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n        ICrabStrategyV2(crab).flashDeposit{value: address(this).balance}(_ethToDeposit);\\n\\n        uint256 crabAmount = IERC20(crab).balanceOf(address(this));\\n\\n        emit FlashDepositERC20(msg.sender, _tokenIn, _amountIn, _ethToDeposit, crabAmount, address(this).balance);\\n\\n        IERC20(crab).transfer(msg.sender, crabAmount);\\n\\n        if (address(this).balance > 0) {\\n            payable(msg.sender).sendValue(address(this).balance);\\n        }\\n    }\\n\\n    function flashWithdrawERC20(\\n        uint256 _crabAmount,\\n        uint256 _maxEthToPay,\\n        address _tokenOut,\\n        uint256 _minAmountOut,\\n        uint24 _fee\\n    ) external nonReentrant {\\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\\n\\n        ICrabStrategyV2(crab).flashWithdraw(_crabAmount, _maxEthToPay);\\n\\n        uint256 ethBalance = address(this).balance;\\n        IWETH9(weth).deposit{value: ethBalance}();\\n        uint256 tokenReceived = _swapExactInputSingle(\\n            weth,\\n            _tokenOut,\\n            address(this),\\n            msg.sender,\\n            ethBalance,\\n            _minAmountOut,\\n            _fee\\n        );\\n\\n        emit FlashWithdrawERC20(msg.sender, _tokenOut, tokenReceived, ethBalance, _crabAmount);\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == crab, \\\"Cannot receive eth\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/ICrabStrategyV2.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\ninterface ICrabStrategyV2 {\\n    function wPowerPerp() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function flashDeposit(uint256 _ethToDeposit) external payable;\\n\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external;\\n}\\n\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        require(_canModifyVault(_vaultId, msg.sender), \\\"C3\\\");\\n\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/solcInputs/e85d9fda89ae8c3780a8ae01da3f423c.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/strategy/timelock/Timelock.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity =0.8.10;\\n\\nimport \\\"./SafeMath.sol\\\";\\n\\ncontract Timelock {\\n    using SafeMath for uint;\\n\\n    event NewAdmin(address indexed newAdmin);\\n    event NewPendingAdmin(address indexed newPendingAdmin);\\n    event NewDelay(uint indexed newDelay);\\n    event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature,  bytes data, uint eta);\\n    event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature,  bytes data, uint eta);\\n    event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);\\n\\n    uint public constant GRACE_PERIOD = 14 days;\\n    uint public constant MINIMUM_DELAY = 2 days;\\n    uint public constant MAXIMUM_DELAY = 30 days;\\n\\n    address public admin;\\n    address public pendingAdmin;\\n    uint public delay;\\n\\n    mapping (bytes32 => bool) public queuedTransactions;\\n\\n\\n    constructor(address admin_, uint delay_) public {\\n        require(delay_ >= MINIMUM_DELAY, \\\"Timelock::constructor: Delay must exceed minimum delay.\\\");\\n        require(delay_ <= MAXIMUM_DELAY, \\\"Timelock::setDelay: Delay must not exceed maximum delay.\\\");\\n\\n        admin = admin_;\\n        delay = delay_;\\n    }\\n\\n    fallback() external payable { }\\n\\n    function setDelay(uint delay_) public {\\n        require(msg.sender == address(this), \\\"Timelock::setDelay: Call must come from Timelock.\\\");\\n        require(delay_ >= MINIMUM_DELAY, \\\"Timelock::setDelay: Delay must exceed minimum delay.\\\");\\n        require(delay_ <= MAXIMUM_DELAY, \\\"Timelock::setDelay: Delay must not exceed maximum delay.\\\");\\n        delay = delay_;\\n\\n        emit NewDelay(delay);\\n    }\\n\\n    function acceptAdmin() public {\\n        require(msg.sender == pendingAdmin, \\\"Timelock::acceptAdmin: Call must come from pendingAdmin.\\\");\\n        admin = msg.sender;\\n        pendingAdmin = address(0);\\n\\n        emit NewAdmin(admin);\\n    }\\n\\n    function setPendingAdmin(address pendingAdmin_) public {\\n        require(msg.sender == address(this), \\\"Timelock::setPendingAdmin: Call must come from Timelock.\\\");\\n        pendingAdmin = pendingAdmin_;\\n\\n        emit NewPendingAdmin(pendingAdmin);\\n    }\\n\\n    function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) {\\n        require(msg.sender == admin, \\\"Timelock::queueTransaction: Call must come from admin.\\\");\\n        require(eta >= getBlockTimestamp().add(delay), \\\"Timelock::queueTransaction: Estimated execution block must satisfy delay.\\\");\\n\\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\\n        queuedTransactions[txHash] = true;\\n\\n        emit QueueTransaction(txHash, target, value, signature, data, eta);\\n        return txHash;\\n    }\\n\\n    function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public {\\n        require(msg.sender == admin, \\\"Timelock::cancelTransaction: Call must come from admin.\\\");\\n\\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\\n        queuedTransactions[txHash] = false;\\n\\n        emit CancelTransaction(txHash, target, value, signature, data, eta);\\n    }\\n\\n    function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) {\\n        require(msg.sender == admin, \\\"Timelock::executeTransaction: Call must come from admin.\\\");\\n\\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\\n        require(queuedTransactions[txHash], \\\"Timelock::executeTransaction: Transaction hasn't been queued.\\\");\\n        require(getBlockTimestamp() >= eta, \\\"Timelock::executeTransaction: Transaction hasn't surpassed time lock.\\\");\\n        require(getBlockTimestamp() <= eta.add(GRACE_PERIOD), \\\"Timelock::executeTransaction: Transaction is stale.\\\");\\n\\n        queuedTransactions[txHash] = false;\\n\\n        bytes memory callData;\\n\\n        if (bytes(signature).length == 0) {\\n            callData = data;\\n        } else {\\n            callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);\\n        }\\n\\n        // solium-disable-next-line security/no-call-value\\n        (bool success, bytes memory returnData) = target.call{value: value}(callData);\\n        require(success, \\\"Timelock::executeTransaction: Transaction execution reverted.\\\");\\n\\n        emit ExecuteTransaction(txHash, target, value, signature, data, eta);\\n\\n        return returnData;\\n    }\\n\\n    function getBlockTimestamp() internal view returns (uint) {\\n        // solium-disable-next-line security/no-block-members\\n        return block.timestamp;\\n    }\\n}\"\n    },\n    \"contracts/strategy/timelock/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity =0.8.10;\\n\\n// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol\\n// Subject to the MIT license.\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c;\\n        unchecked { c = a + b; }\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        uint256 c;\\n        unchecked { c = a + b; }\\n        require(c >= a, errorMessage);\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     * - Subtraction cannot underflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return sub(a, b, \\\"SafeMath: subtraction underflow\\\");\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     * - Subtraction cannot underflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        uint256 c = a - b;\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) {\\n            return 0;\\n        }\\n\\n        uint256 c;\\n        unchecked { c = a * b; }\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) {\\n            return 0;\\n        }\\n\\n        uint256 c;\\n        unchecked { c = a * b; }\\n        require(c / a == b, errorMessage);\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers.\\n     * Reverts on division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return div(a, b, \\\"SafeMath: division by zero\\\");\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers.\\n     * Reverts with custom message on division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        // Solidity only automatically asserts when dividing by 0\\n        require(b > 0, errorMessage);\\n        uint256 c = a / b;\\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * Reverts when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * Reverts with custom message when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b != 0, errorMessage);\\n        return a % b;\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": false,\n      \"runs\": 200\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/deployments/ropsten/solcInputs/fc32ed9e00a9017e491333926bef5473.json",
    "content": "{\n  \"language\": \"Solidity\",\n  \"sources\": {\n    \"contracts/core/Controller.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\n//contract\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n *\\n * Error\\n * C0: Paused\\n * C1: Not paused\\n * C2: Shutdown\\n * C3: Not shutdown\\n * C4: Invalid oracle address\\n * C5: Invalid shortPowerPerp address\\n * C6: Invalid wPowerPerp address\\n * C7: Invalid weth address\\n * C8: Invalid quote currency address\\n * C9: Invalid eth:quoteCurrency pool address\\n * C10: Invalid wPowerPerp:eth pool address\\n * C11: Invalid Uniswap position manager\\n * C12: Can not liquidate safe vault\\n * C13: Invalid address\\n * C14: Set fee recipient first\\n * C15: Fee too high\\n * C16: Paused too many times\\n * C17: Pause time limit exceeded\\n * C18: Not enough paused time has passed\\n * C19: Cannot receive eth\\n * C20: Not allowed\\n * C21: Need full liquidation\\n * C22: Dust vault left\\n * C23: Invalid nft\\n * C24: Invalid state\\n * C25: 0 liquidity Uniswap position token\\n * C26: Wrong fee tier for NFT deposit\\n */\\ncontract Controller is Ownable, ReentrancyGuard, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using ABDKMath64x64 for int128;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant MIN_COLLATERAL = 0.5 ether;\\n    /// @dev system can only be paused for 182 days from deployment\\n    uint256 internal constant PAUSE_TIME_LIMIT = 182 days;\\n\\n    uint256 public constant FUNDING_PERIOD = 420 hours;\\n    uint24 public immutable feeTier;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    //80% of index\\n    uint256 internal constant LOWER_MARK_RATIO = 8e17;\\n    //140% of index\\n    uint256 internal constant UPPER_MARK_RATIO = 140e16;\\n    // 10%\\n    uint256 internal constant LIQUIDATION_BOUNTY = 1e17;\\n    // 2%\\n    uint256 internal constant REDUCE_DEBT_BOUNTY = 2e16;\\n\\n    /// @dev basic unit used for calculation\\n    uint256 private constant ONE = 1e18;\\n\\n    address public immutable weth;\\n    address public immutable quoteCurrency;\\n    address public immutable ethQuoteCurrencyPool;\\n    /// @dev address of the powerPerp/weth pool\\n    address public immutable wPowerPerpPool;\\n    address internal immutable uniswapPositionManager;\\n    address public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n    address public immutable oracle;\\n    address public feeRecipient;\\n\\n    uint256 internal immutable deployTimestamp;\\n    /// @dev fee rate in basis point. feeRate of 1 = 0.01%\\n    uint256 public feeRate;\\n    /// @dev the settlement price for each wPowerPerp for settlement\\n    uint256 public indexForSettlement;\\n\\n    uint256 public pausesLeft = 4;\\n    uint256 public lastPauseTime;\\n\\n    // these 2 parameters are always updated together. Use uint128 to batch read and write.\\n    uint128 public normalizationFactor;\\n    uint128 public lastFundingUpdateTimestamp;\\n\\n    bool internal immutable isWethToken0;\\n    bool public isShutDown;\\n    bool public isSystemPaused;\\n\\n    /// @dev vault data storage\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    /// Events\\n    event OpenVault(address sender, uint256 vaultId);\\n    event DepositCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event DepositUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event WithdrawCollateral(address sender, uint256 vaultId, uint256 amount);\\n    event WithdrawUniPositionToken(address sender, uint256 vaultId, uint256 tokenId);\\n    event MintShort(address sender, uint256 amount, uint256 vaultId);\\n    event BurnShort(address sender, uint256 amount, uint256 vaultId);\\n    event ReduceDebt(\\n        address sender,\\n        uint256 vaultId,\\n        uint256 ethRedeemed,\\n        uint256 wPowerPerpRedeemed,\\n        uint256 wPowerPerpBurned,\\n        uint256 wPowerPerpExcess,\\n        uint256 bounty\\n    );\\n    event UpdateOperator(address sender, uint256 vaultId, address operator);\\n    event FeeRateUpdated(uint256 oldFee, uint256 newFee);\\n    event FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient);\\n    event Liquidate(address liquidator, uint256 vaultId, uint256 debtAmount, uint256 collateralPaid);\\n    event NormalizationFactorUpdated(\\n        uint256 oldNormFactor,\\n        uint256 newNormFactor,\\n        uint256 lastModificationTimestamp,\\n        uint256 timestamp\\n    );\\n    event Paused(uint256 pausesLeft);\\n    event UnPaused(address unpauser);\\n    event Shutdown(uint256 indexForSettlement);\\n    event RedeemLong(address sender, uint256 wPowerPerpAmount, uint256 payoutAmount);\\n    event RedeemShort(address sender, uint256 vauldId, uint256 collateralAmount);\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"C0\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"C1\\\");\\n        _;\\n    }\\n\\n    modifier notShutdown() {\\n        require(!isShutDown, \\\"C2\\\");\\n        _;\\n    }\\n\\n    modifier isShutdown() {\\n        require(isShutDown, \\\"C3\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice constructor\\n     * @param _oracle oracle address\\n     * @param _shortPowerPerp ERC721 token address representing the short position\\n     * @param _wPowerPerp ERC20 token address representing the long position\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _wPowerPerpPool uniswap v3 pool for wPowerPerp / weth\\n     * @param _uniPositionManager uniswap v3 position manager address\\n     */\\n    constructor(\\n        address _oracle,\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager,\\n        uint24 _feeTier\\n    ) {\\n        require(_oracle != address(0), \\\"C4\\\");\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"C6\\\");\\n        require(_weth != address(0), \\\"C7\\\");\\n        require(_quoteCurrency != address(0), \\\"C8\\\");\\n        require(_ethQuoteCurrencyPool != address(0), \\\"C9\\\");\\n        require(_wPowerPerpPool != address(0), \\\"C10\\\");\\n        require(_uniPositionManager != address(0), \\\"C11\\\");\\n\\n        oracle = _oracle;\\n        shortPowerPerp = _shortPowerPerp;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        feeTier = _feeTier;\\n        isWethToken0 = _weth < _wPowerPerp;\\n\\n        normalizationFactor = 1e18;\\n        deployTimestamp = block.timestamp;\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n    }\\n\\n    /**\\n     * ======================\\n     * | External Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice returns the expected normalization factor, if the funding is paid right now\\n     * @dev can be used for on-chain and off-chain calculations\\n     */\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return _getNewNormalizationFactor();\\n    }\\n\\n    /**\\n     * @notice get the index price of the powerPerp, scaled down\\n     * @dev the index price is scaled down by INDEX_SCALE in the associated PowerXBase library\\n     * @dev this is the index price used when calculating funding and for collateralization\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @dev this is the mark that would be be used for future funding after a new normalization factor is applied\\n     * @param _period period which you want to calculate twap with\\n     * @return index price denominated in $USD, scaled by 1e18\\n     */\\n    function getUnscaledIndex(uint32 _period) external view returns (uint256) {\\n        return Power2Base._getUnscaledIndex(_period, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n    }\\n\\n    /**\\n     * @notice get the expected mark price of powerPerp after funding has been applied\\n     * @param _period period of time for the twap in seconds\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMark(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                _getNewNormalizationFactor()\\n            );\\n    }\\n\\n    /**\\n     * @notice get the mark price of powerPerp before funding has been applied\\n     * @dev this is the mark that would be used to calculate a new normalization factor if funding was calculated now\\n     * @param _period period which you want to calculate twap with\\n     * @return mark price denominated in $USD, scaled by 1e18\\n     */\\n    function getDenormalizedMarkForFunding(uint32 _period) external view returns (uint256) {\\n        return\\n            Power2Base._getDenormalizedMark(\\n                _period,\\n                oracle,\\n                wPowerPerpPool,\\n                ethQuoteCurrencyPool,\\n                weth,\\n                quoteCurrency,\\n                wPowerPerp,\\n                normalizationFactor\\n            );\\n    }\\n\\n    /**\\n     * @dev return if the vault is properly collateralized\\n     * @param _vaultId id of the vault\\n     * @return true if the vault is properly collateralized\\n     */\\n    function isVaultSafe(uint256 _vaultId) external view returns (bool) {\\n        VaultLib.Vault memory vault = vaults[_vaultId];\\n        uint256 expectedNormalizationFactor = _getNewNormalizationFactor();\\n        return _isVaultSafe(vault, expectedNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _powerPerpAmount amount of powerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     * @return amount of wPowerPerp minted\\n     */\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256, uint256) {\\n        return _openDepositMint(msg.sender, _vaultId, _powerPerpAmount, msg.value, _uniTokenId, false);\\n    }\\n\\n    /**\\n     * @notice deposit collateral and mint wPowerPerp\\n     * @param _vaultId vault to mint wPowerPerp in\\n     * @param _wPowerPerpAmount amount of wPowerPerp to mint\\n     * @param _uniTokenId uniswap v3 position token id (additional collateral)\\n     * @return vaultId\\n     */\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable notPaused nonReentrant returns (uint256) {\\n        (uint256 vaultId, ) = _openDepositMint(msg.sender, _vaultId, _wPowerPerpAmount, msg.value, _uniTokenId, true);\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @dev deposit collateral into a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function deposit(uint256 _vaultId) external payable notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _addEthCollateral(cachedVault, _vaultId, msg.value);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap position token into a vault to increase collateral ratio\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _depositUniPositionToken(cachedVault, msg.sender, _vaultId, _uniTokenId);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _withdrawCollateral(cachedVault, _vaultId, _amount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n        payable(msg.sender).sendValue(_amount);\\n    }\\n\\n    /**\\n     * @notice withdraw uniswap v3 position token from a vault\\n     * @param _vaultId id of the vault\\n     */\\n    function withdrawUniPositionToken(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        uint256 cachedNormFactor = _applyFunding();\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _withdrawUniPositionToken(cachedVault, msg.sender, _vaultId);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     */\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        _burnAndWithdraw(msg.sender, _vaultId, _wPowerPerpAmount, _withdrawAmount, true);\\n    }\\n\\n    /**\\n     * @notice burn powerPerp and remove collateral from a vault\\n     * @param _vaultId id of the vault\\n     * @param _powerPerpAmount amount of powerPerp to burn\\n     * @param _withdrawAmount amount of eth to withdraw\\n     * @return amount of wPowerPerp burned\\n     */\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external notPaused nonReentrant returns (uint256) {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        return _burnAndWithdraw(msg.sender, _vaultId, _powerPerpAmount, _withdrawAmount, false);\\n    }\\n\\n    /**\\n     * @notice after the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\\n     * @notice if a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\\n     * @param _vaultId vault containing uniswap v3 position to liquidate\\n     */\\n    function reduceDebtShutdown(uint256 _vaultId) external isShutdown nonReentrant {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice withdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\\n     * @dev the caller won't get any bounty. this is expected to be used by vault owner\\n     * @param _vaultId target vault\\n     */\\n    function reduceDebt(uint256 _vaultId) external notPaused nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, false);\\n\\n        _writeVault(_vaultId, cachedVault);\\n    }\\n\\n    /**\\n     * @notice if a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\\n     * @dev liquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\\n     * @dev normally can only liquidate 50% of a vault's debt\\n     * @dev if a vault is under dust limit after a liquidation can fully liquidate\\n     * @dev will attempt to reduceDebt first, and can earn a bounty if sucessful\\n     * @param _vaultId vault to liquidate\\n     * @param _maxDebtAmount max amount of wPowerPerpetual to repay\\n     * @return amount of wPowerPerp repaid\\n     */\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external notPaused nonReentrant returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n\\n        require(!_isVaultSafe(cachedVault, cachedNormFactor), \\\"C12\\\");\\n\\n        // try to save target vault before liquidation by reducing debt\\n        uint256 bounty = _reduceDebt(cachedVault, IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId), _vaultId, true);\\n\\n        // if vault is safe after saving, pay bounty and return early\\n        if (_isVaultSafe(cachedVault, cachedNormFactor)) {\\n            _writeVault(_vaultId, cachedVault);\\n            payable(msg.sender).sendValue(bounty);\\n            return 0;\\n        }\\n\\n        // add back the bounty amount, liquidators onlly get reward from liquidation\\n        cachedVault.addEthCollateral(bounty);\\n\\n        // if the vault is still not safe after saving, liquidate it\\n        (uint256 debtAmount, uint256 collateralPaid) = _liquidate(\\n            cachedVault,\\n            _maxDebtAmount,\\n            cachedNormFactor,\\n            msg.sender\\n        );\\n\\n        emit Liquidate(msg.sender, _vaultId, debtAmount, collateralPaid);\\n\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay the liquidator\\n        payable(msg.sender).sendValue(collateralPaid);\\n\\n        return debtAmount;\\n    }\\n\\n    /**\\n     * @notice authorize an address to modify the vault\\n     * @dev can be revoke by setting address to 0\\n     * @param _vaultId id of the vault\\n     * @param _operator new operator address\\n     */\\n    function updateOperator(uint256 _vaultId, address _operator) external {\\n        require(\\n            (shortPowerPerp == msg.sender) || (IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender),\\n            \\\"C20\\\"\\n        );\\n        vaults[_vaultId].operator = _operator;\\n        emit UpdateOperator(msg.sender, _vaultId, _operator);\\n    }\\n\\n    /**\\n     * @notice set the recipient who will receive the fee\\n     * @dev this should be a contract handling insurance\\n     * @param _newFeeRecipient new fee recipient\\n     */\\n    function setFeeRecipient(address _newFeeRecipient) external onlyOwner {\\n        require(_newFeeRecipient != address(0), \\\"C13\\\");\\n        emit FeeRecipientUpdated(feeRecipient, _newFeeRecipient);\\n        feeRecipient = _newFeeRecipient;\\n    }\\n\\n    /**\\n     * @notice set the fee rate when user mints\\n     * @dev this function cannot be called if the feeRecipient is still un-set\\n     * @param _newFeeRate new fee rate in basis points. can't be higher than 1%\\n     */\\n    function setFeeRate(uint256 _newFeeRate) external onlyOwner {\\n        require(feeRecipient != address(0), \\\"C14\\\");\\n        require(_newFeeRate <= 100, \\\"C15\\\");\\n        emit FeeRateUpdated(feeRate, _newFeeRate);\\n        feeRate = _newFeeRate;\\n    }\\n\\n    /**\\n     * @notice shutting down the system allows all long wPowerPerp to be settled at index * normalizationFactor\\n     * @notice short positions can be redeemed for vault collateral minus value of debt\\n     * @notice pause (if not paused) and then immediately shutdown the system, can be called when paused already\\n     * @dev this bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\\n     */\\n    function shutDown() external onlyOwner notShutdown {\\n        isSystemPaused = true;\\n        isShutDown = true;\\n        indexForSettlement = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            false\\n        );\\n        emit Shutdown(indexForSettlement);\\n    }\\n\\n    /**\\n     * @notice pause the system for up to 24 hours after which any one can unpause\\n     * @dev can only be called for 365 days since the contract was launched or 4 times\\n     */\\n    function pause() external onlyOwner notShutdown notPaused {\\n        require(pausesLeft > 0, \\\"C16\\\");\\n        uint256 timeSinceDeploy = block.timestamp.sub(deployTimestamp);\\n        require(timeSinceDeploy < PAUSE_TIME_LIMIT, \\\"C17\\\");\\n        isSystemPaused = true;\\n        pausesLeft -= 1;\\n        lastPauseTime = block.timestamp;\\n\\n        emit Paused(pausesLeft);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev anyone can unpause the contract after 24 hours\\n     */\\n    function unPauseAnyone() external isPaused notShutdown {\\n        require(block.timestamp > (lastPauseTime + 1 days), \\\"C18\\\");\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     * @dev owner can unpause at any time\\n     */\\n    function unPauseOwner() external onlyOwner isPaused notShutdown {\\n        isSystemPaused = false;\\n        emit UnPaused(msg.sender);\\n    }\\n\\n    /**\\n     * @notice redeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\\n     * @param _wPerpAmount amount of wPowerPerp to burn\\n     */\\n    function redeemLong(uint256 _wPerpAmount) external isShutdown nonReentrant {\\n        IWPowerPerp(wPowerPerp).burn(msg.sender, _wPerpAmount);\\n\\n        uint256 longValue = Power2Base._getLongSettlementValue(_wPerpAmount, indexForSettlement, normalizationFactor);\\n        payable(msg.sender).sendValue(longValue);\\n\\n        emit RedeemLong(msg.sender, _wPerpAmount, longValue);\\n    }\\n\\n    /**\\n     * @notice redeem short position when the system is shutdown\\n     * @dev short position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\\n     * @param _vaultId vault id\\n     */\\n    function redeemShort(uint256 _vaultId) external isShutdown nonReentrant {\\n        _checkCanModifyVault(_vaultId, msg.sender);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        uint256 cachedNormFactor = normalizationFactor;\\n\\n        _reduceDebt(cachedVault, msg.sender, _vaultId, false);\\n\\n        uint256 debt = Power2Base._getLongSettlementValue(\\n            cachedVault.shortAmount,\\n            indexForSettlement,\\n            cachedNormFactor\\n        );\\n        // if the debt is more than collateral, this line will revert\\n        uint256 excess = uint256(cachedVault.collateralAmount).sub(debt);\\n\\n        // reset the vault but don't burn the nft, just because people may want to keep it\\n        cachedVault.shortAmount = 0;\\n        cachedVault.collateralAmount = 0;\\n        _writeVault(_vaultId, cachedVault);\\n\\n        payable(msg.sender).sendValue(excess);\\n\\n        emit RedeemShort(msg.sender, _vaultId, excess);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay funding\\n     */\\n    function applyFunding() external notPaused {\\n        _applyFunding();\\n    }\\n\\n    /**\\n     * @notice add eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\\n     */\\n    function donate() external payable isShutdown {}\\n\\n    /**\\n     * @notice fallback function to accept eth\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth, \\\"C19\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /*\\n     * ======================\\n     * | Internal Functions |\\n     * ======================\\n     */\\n\\n    /**\\n     * @notice check if an address can modify a vault\\n     * @param _vaultId the id of the vault to check if can be modified by _account\\n     * @param _account the address to check if can modify the vault\\n     */\\n    function _checkCanModifyVault(uint256 _vaultId, address _account) internal view {\\n        require(\\n            IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account,\\n            \\\"C20\\\"\\n        );\\n    }\\n\\n    /**\\n     * @notice wrapper function which opens a vault, adds collateral and mints wPowerPerp\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _mintAmount amount to mint\\n     * @param _depositAmount amount of eth as collateral\\n     * @param _uniTokenId id of uniswap v3 position token\\n     * @param _isWAmount if the input amount is a wPowerPerp amount (as opposed to rebasing powerPerp)\\n     * @return the vaultId that was acted on or for a new vault the newly created vaultId\\n     * @return the minted wPowerPerp amount\\n     */\\n    function _openDepositMint(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 _depositAmount,\\n        uint256 _uniTokenId,\\n        bool _isWAmount\\n    ) internal returns (uint256, uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 depositAmountWithFee = _depositAmount;\\n        uint256 wPowerPerpAmount = _isWAmount ? _mintAmount : _mintAmount.mul(ONE).div(cachedNormFactor);\\n        uint256 feeAmount;\\n        VaultLib.Vault memory cachedVault;\\n\\n        // load vault or create new a new one\\n        if (_vaultId == 0) {\\n            (_vaultId, cachedVault) = _openVault(_account);\\n        } else {\\n            // make sure we're not accessing an unexistent vault.\\n            _checkCanModifyVault(_vaultId, msg.sender);\\n            cachedVault = vaults[_vaultId];\\n        }\\n\\n        if (wPowerPerpAmount > 0) {\\n            (feeAmount, depositAmountWithFee) = _getFee(cachedVault, wPowerPerpAmount, _depositAmount);\\n            _mintWPowerPerp(cachedVault, _account, _vaultId, wPowerPerpAmount);\\n        }\\n        if (_depositAmount > 0) _addEthCollateral(cachedVault, _vaultId, depositAmountWithFee);\\n        if (_uniTokenId != 0) _depositUniPositionToken(cachedVault, _account, _vaultId, _uniTokenId);\\n\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        // pay insurance fee\\n        if (feeAmount > 0) payable(feeRecipient).sendValue(feeAmount);\\n\\n        return (_vaultId, wPowerPerpAmount);\\n    }\\n\\n    /**\\n     * @notice wrapper function to burn wPowerPerp and redeem collateral\\n     * @param _account who should receive collateral\\n     * @param _vaultId id of the vault\\n     * @param _burnAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount of eth collateral to withdraw\\n     * @param _isWAmount true if the amount is wPowerPerp (as opposed to rebasing powerPerp)\\n     * @return total burned wPowerPower amount\\n     */\\n    function _burnAndWithdraw(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _burnAmount,\\n        uint256 _withdrawAmount,\\n        bool _isWAmount\\n    ) internal returns (uint256) {\\n        uint256 cachedNormFactor = _applyFunding();\\n        uint256 wBurnAmount = _isWAmount ? _burnAmount : _burnAmount.mul(ONE).div(cachedNormFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        if (wBurnAmount > 0) _burnWPowerPerp(cachedVault, _account, _vaultId, wBurnAmount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(cachedVault, _vaultId, _withdrawAmount);\\n        _checkVault(cachedVault, cachedNormFactor);\\n        _writeVault(_vaultId, cachedVault);\\n\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n\\n        return wBurnAmount;\\n    }\\n\\n    /**\\n     * @notice open a new vault\\n     * @dev create a new vault and bind it with a new short vault id\\n     * @param _recipient owner of new vault\\n     * @return id of the new vault\\n     * @return new in-memory vault\\n     */\\n    function _openVault(address _recipient) internal returns (uint256, VaultLib.Vault memory) {\\n        uint256 vaultId = IShortPowerPerp(shortPowerPerp).mintNFT(_recipient);\\n\\n        VaultLib.Vault memory vault = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n        emit OpenVault(msg.sender, vaultId);\\n        return (vaultId, vault);\\n    }\\n\\n    /**\\n     * @notice deposit uniswap v3 position token into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to transfer the uniswap v3 position from\\n     * @param _vaultId id of the vault\\n     * @param _uniTokenId uniswap position token id\\n     */\\n    function _depositUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _uniTokenId\\n    ) internal {\\n        //get tokens for uniswap NFT\\n        (, , address token0, address token1, uint24 fee, , , uint128 liquidity, , , , ) = INonfungiblePositionManager(\\n            uniswapPositionManager\\n        ).positions(_uniTokenId);\\n\\n        // require that liquidity is above 0\\n        require(liquidity > 0, \\\"C25\\\");\\n        // accept NFTs from only the wPowerPerp pool\\n        require(fee == feeTier, \\\"C26\\\");\\n        // check token0 and token1\\n        require((token0 == wPowerPerp && token1 == weth) || (token1 == wPowerPerp && token0 == weth), \\\"C23\\\");\\n\\n        _vault.addUniNftCollateral(_uniTokenId);\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(_account, address(this), _uniTokenId);\\n        emit DepositUniPositionToken(msg.sender, _vaultId, _uniTokenId);\\n    }\\n\\n    /**\\n     * @notice add eth collateral into a vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update.\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth adding to the vault\\n     */\\n    function _addEthCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.addEthCollateral(_amount);\\n        emit DepositCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice remove uniswap v3 position token from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account where to send the uni position token to\\n     * @param _vaultId id of the vault\\n     */\\n    function _withdrawUniPositionToken(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId\\n    ) internal {\\n        uint256 tokenId = _vault.NftCollateralId;\\n        _vault.removeUniNftCollateral();\\n        INonfungiblePositionManager(uniswapPositionManager).safeTransferFrom(address(this), _account, tokenId);\\n        emit WithdrawUniPositionToken(msg.sender, _vaultId, tokenId);\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from the vault\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _vaultId id of the vault\\n     * @param _amount amount of eth to withdraw\\n     */\\n    function _withdrawCollateral(\\n        VaultLib.Vault memory _vault,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        _vault.removeEthCollateral(_amount);\\n\\n        emit WithdrawCollateral(msg.sender, _vaultId, _amount);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp (ERC20) to an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account to receive wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to mint\\n     */\\n    function _mintWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.addShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).mint(_account, _wPowerPerpAmount);\\n\\n        emit MintShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp (ERC20) from an account\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _account account burning the wPowerPerp\\n     * @param _vaultId id of the vault\\n     * @param _wPowerPerpAmount wPowerPerp amount to burn\\n     */\\n    function _burnWPowerPerp(\\n        VaultLib.Vault memory _vault,\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal {\\n        _vault.removeShort(_wPowerPerpAmount);\\n        IWPowerPerp(wPowerPerp).burn(_account, _wPowerPerpAmount);\\n\\n        emit BurnShort(msg.sender, _wPowerPerpAmount, _vaultId);\\n    }\\n\\n    /**\\n     * @notice liquidate a vault, pay the liquidator\\n     * @dev liquidator can only liquidate at most 1/2 of the vault in 1 transaction\\n     * @dev this function will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _maxWPowerPerpAmount maximum debt amount liquidator is willing to repay\\n     * @param _normalizationFactor current normalization factor\\n     * @param _liquidator liquidator address to receive eth\\n     * @return debtAmount amount of wPowerPerp repaid (burn from the vault)\\n     * @return collateralToPay amount of collateral paid to liquidator\\n     */\\n    function _liquidate(\\n        VaultLib.Vault memory _vault,\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _normalizationFactor,\\n        address _liquidator\\n    ) internal returns (uint256, uint256) {\\n        (uint256 liquidateAmount, uint256 collateralToPay) = _getLiquidationResult(\\n            _maxWPowerPerpAmount,\\n            uint256(_vault.shortAmount),\\n            uint256(_vault.collateralAmount)\\n        );\\n\\n        // if the liquidator didn't specify enough wPowerPerp to burn, revert.\\n        require(_maxWPowerPerpAmount >= liquidateAmount, \\\"C21\\\");\\n\\n        IWPowerPerp(wPowerPerp).burn(_liquidator, liquidateAmount);\\n        _vault.removeShort(liquidateAmount);\\n        _vault.removeEthCollateral(collateralToPay);\\n\\n        (, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(!isDust, \\\"C22\\\");\\n\\n        return (liquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice redeem uniswap v3 position in a vault for its constituent eth and wPowerPerp\\n     * @notice this will increase vault collateral by the amount of eth, and decrease debt by the amount of wPowerPerp\\n     * @dev will be executed before liquidation if there's an NFT in the vault\\n     * @dev pays a 2% bounty to the liquidator if called by liquidate()\\n     * @dev will update the vault memory in-place\\n     * @param _vault the Vault memory to update\\n     * @param _owner account to send any excess\\n     * @param _vaultId id of the vault to reduce debt on\\n     * @param _payBounty true if paying caller 2% bounty\\n     * @return bounty amount of bounty paid for liquidator\\n     */\\n    function _reduceDebt(\\n        VaultLib.Vault memory _vault,\\n        address _owner,\\n        uint256 _vaultId,\\n        bool _payBounty\\n    ) internal returns (uint256) {\\n        uint256 nftId = _vault.NftCollateralId;\\n        if (nftId == 0) return 0;\\n\\n        (uint256 withdrawnEthAmount, uint256 withdrawnWPowerPerpAmount) = _redeemUniToken(nftId);\\n\\n        // change weth back to eth\\n        if (withdrawnEthAmount > 0) IWETH9(weth).withdraw(withdrawnEthAmount);\\n\\n        (uint256 burnAmount, uint256 excess, uint256 bounty) = _getReduceDebtResultInVault(\\n            _vault,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            _payBounty\\n        );\\n\\n        if (excess > 0) IWPowerPerp(wPowerPerp).transfer(_owner, excess);\\n        if (burnAmount > 0) IWPowerPerp(wPowerPerp).burn(address(this), burnAmount);\\n\\n        emit ReduceDebt(\\n            msg.sender,\\n            _vaultId,\\n            withdrawnEthAmount,\\n            withdrawnWPowerPerpAmount,\\n            burnAmount,\\n            excess,\\n            bounty\\n        );\\n\\n        return bounty;\\n    }\\n\\n    /**\\n     * @notice pay fee recipient\\n     * @dev pay in eth from either the vault or the deposit amount\\n     * @param _vault the Vault memory to update\\n     * @param _wPowerPerpAmount the amount of wPowerPerpAmount minting\\n     * @param _depositAmount the amount of eth depositing or withdrawing\\n     * @return the amount of actual deposited eth into the vault, this is less than the original amount if a fee was taken\\n     */\\n    function _getFee(\\n        VaultLib.Vault memory _vault,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _depositAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 cachedFeeRate = feeRate;\\n        if (cachedFeeRate == 0) return (uint256(0), _depositAmount);\\n        uint256 depositAmountAfterFee;\\n        uint256 ethEquivalentMinted = Power2Base._getDebtValueInEth(\\n            _wPowerPerpAmount,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n        uint256 feeAmount = ethEquivalentMinted.mul(cachedFeeRate).div(10000);\\n\\n        // if fee can be paid from deposited collateral, pay from _depositAmount\\n        if (_depositAmount > feeAmount) {\\n            depositAmountAfterFee = _depositAmount.sub(feeAmount);\\n            // if not, adjust the vault to pay from the vault collateral\\n        } else {\\n            _vault.removeEthCollateral(feeAmount);\\n            depositAmountAfterFee = _depositAmount;\\n        }\\n        //return the fee and deposit amount, which has only been reduced by a fee if it is paid out of the deposit amount\\n        return (feeAmount, depositAmountAfterFee);\\n    }\\n\\n    /**\\n     * @notice write vault to storage\\n     * @dev writes to vaults mapping\\n     */\\n    function _writeVault(uint256 _vaultId, VaultLib.Vault memory _vault) private {\\n        vaults[_vaultId] = _vault;\\n    }\\n\\n    /**\\n     * @dev redeem a uni position token and get back wPowerPerp and eth\\n     * @param _uniTokenId uniswap v3 position token id\\n     * @return wethAmount amount of weth withdrawn from uniswap\\n     * @return wPowerPerpAmount amount of wPowerPerp withdrawn from uniswap\\n     */\\n    function _redeemUniToken(uint256 _uniTokenId) internal returns (uint256, uint256) {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(uniswapPositionManager);\\n\\n        (, , uint128 liquidity, , ) = VaultLib._getUniswapPositionInfo(uniswapPositionManager, _uniTokenId);\\n\\n        // prepare parameters to withdraw liquidity from uniswap v3 position manager\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _uniTokenId,\\n                liquidity: liquidity,\\n                amount0Min: 0,\\n                amount1Min: 0,\\n                deadline: block.timestamp\\n            });\\n\\n        positionManager.decreaseLiquidity(decreaseParams);\\n\\n        // withdraw max amount of weth and wPowerPerp from uniswap\\n        INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager.CollectParams({\\n            tokenId: _uniTokenId,\\n            recipient: address(this),\\n            amount0Max: uint128(-1),\\n            amount1Max: uint128(-1)\\n        });\\n\\n        (uint256 collectedToken0, uint256 collectedToken1) = positionManager.collect(collectParams);\\n\\n        return isWethToken0 ? (collectedToken0, collectedToken1) : (collectedToken1, collectedToken0);\\n    }\\n\\n    /**\\n     * @notice update the normalization factor as a way to pay in-kind funding\\n     * @dev the normalization factor scales amount of debt that must be repaid, effecting an interest rate paid between long and short positions\\n     * @return new normalization factor\\n     **/\\n    function _applyFunding() internal returns (uint256) {\\n        // only update the norm factor once per block\\n        if (lastFundingUpdateTimestamp == block.timestamp) return normalizationFactor;\\n\\n        uint256 newNormalizationFactor = _getNewNormalizationFactor();\\n\\n        emit NormalizationFactorUpdated(\\n            normalizationFactor,\\n            newNormalizationFactor,\\n            lastFundingUpdateTimestamp,\\n            block.timestamp\\n        );\\n\\n        // the following will be batch into 1 SSTORE because of type uint128\\n        normalizationFactor = newNormalizationFactor.toUint128();\\n        lastFundingUpdateTimestamp = block.timestamp.toUint128();\\n\\n        return newNormalizationFactor;\\n    }\\n\\n    /**\\n     * @dev calculate new normalization factor base on the current timestamp\\n     * @return new normalization factor if funding happens in the current block\\n     */\\n    function _getNewNormalizationFactor() internal view returns (uint256) {\\n        uint32 period = block.timestamp.sub(lastFundingUpdateTimestamp).toUint32();\\n\\n        if (period == 0) {\\n            return normalizationFactor;\\n        }\\n\\n        // make sure we use the same period for mark and index\\n        uint32 periodForOracle = _getConsistentPeriodForOracle(period);\\n\\n        // avoid reading normalizationFactor from storage multiple times\\n        uint256 cacheNormFactor = normalizationFactor;\\n\\n        uint256 mark = Power2Base._getDenormalizedMark(\\n            periodForOracle,\\n            oracle,\\n            wPowerPerpPool,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            wPowerPerp,\\n            cacheNormFactor\\n        );\\n        uint256 index = Power2Base._getIndex(periodForOracle, oracle, ethQuoteCurrencyPool, weth, quoteCurrency);\\n\\n        //the fraction of the funding period. used to compound the funding rate\\n        int128 rFunding = ABDKMath64x64.divu(period, FUNDING_PERIOD);\\n\\n        // floor mark to be at least LOWER_MARK_RATIO of index\\n        uint256 lowerBound = index.mul(LOWER_MARK_RATIO).div(ONE);\\n        if (mark < lowerBound) {\\n            mark = lowerBound;\\n        } else {\\n            // cap mark to be at most UPPER_MARK_RATIO of index\\n            uint256 upperBound = index.mul(UPPER_MARK_RATIO).div(ONE);\\n            if (mark > upperBound) mark = upperBound;\\n        }\\n\\n        // normFactor(new) = multiplier * normFactor(old)\\n        // multiplier = (index/mark)^rFunding\\n        // x^r = n^(log_n(x) * r)\\n        // multiplier = 2^( log2(index/mark) * rFunding )\\n\\n        int128 base = ABDKMath64x64.divu(index, mark);\\n        int128 logTerm = ABDKMath64x64.log_2(base).mul(rFunding);\\n        int128 multiplier = logTerm.exp_2();\\n        return multiplier.mulu(cacheNormFactor);\\n    }\\n\\n    /**\\n     * @notice check if vault has enough collateral and is not a dust vault\\n     * @dev revert if vault has insufficient collateral or is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     */\\n    function _checkVault(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view {\\n        (bool isSafe, bool isDust) = _getVaultStatus(_vault, _normalizationFactor);\\n        require(isSafe, \\\"C24\\\");\\n        require(!isDust, \\\"C22\\\");\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wPowerPerp that should be burned\\n     * @return wPowerPerpExcess amount of wPowerPerp that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(uint256 _ethWithdrawn, uint256 _wPowerPerpReduced) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(_wPowerPerpReduced, oracle, wPowerPerpPool, wPowerPerp, weth)\\n                .add(_ethWithdrawn)\\n                .mul(REDUCE_DEBT_BOUNTY)\\n                .div(ONE);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(uint256 _maxInputWAmount, uint256 _maxLiquidatableWAmount)\\n        internal\\n        view\\n        returns (uint256, uint256)\\n    {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.mul(LIQUIDATION_BOUNTY).div(ONE));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get a period can be used to request a twap for 2 uniswap v3 pools\\n     * @dev if the period is greater than min(max_pool_1, max_pool_2), return min(max_pool_1, max_pool_2)\\n     * @param _period max period that we intend to use\\n     * @return fair period not greator than _period to be used for both pools.\\n     */\\n    function _getConsistentPeriodForOracle(uint32 _period) internal view returns (uint32) {\\n        uint32 maxPeriodPool1 = IOracle(oracle).getMaxPeriod(ethQuoteCurrencyPool);\\n        uint32 maxPeriodPool2 = IOracle(oracle).getMaxPeriod(wPowerPerpPool);\\n\\n        uint32 maxSafePeriod = maxPeriodPool1 > maxPeriodPool2 ? maxPeriodPool2 : maxPeriodPool1;\\n        return _period > maxSafePeriod ? maxSafePeriod : _period;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';\\nimport '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';\\n\\nimport './IPoolInitializer.sol';\\nimport './IERC721Permit.sol';\\nimport './IPeripheryPayments.sol';\\nimport './IPeripheryImmutableState.sol';\\nimport '../libraries/PoolAddress.sol';\\n\\n/// @title Non-fungible token for positions\\n/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred\\n/// and authorized.\\ninterface INonfungiblePositionManager is\\n    IPoolInitializer,\\n    IPeripheryPayments,\\n    IPeripheryImmutableState,\\n    IERC721Metadata,\\n    IERC721Enumerable,\\n    IERC721Permit\\n{\\n    /// @notice Emitted when liquidity is increased for a position NFT\\n    /// @dev Also emitted when a token is minted\\n    /// @param tokenId The ID of the token for which liquidity was increased\\n    /// @param liquidity The amount by which liquidity for the NFT position was increased\\n    /// @param amount0 The amount of token0 that was paid for the increase in liquidity\\n    /// @param amount1 The amount of token1 that was paid for the increase in liquidity\\n    event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when liquidity is decreased for a position NFT\\n    /// @param tokenId The ID of the token for which liquidity was decreased\\n    /// @param liquidity The amount by which liquidity for the NFT position was decreased\\n    /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity\\n    /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity\\n    event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\\n    /// @notice Emitted when tokens are collected for a position NFT\\n    /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior\\n    /// @param tokenId The ID of the token for which underlying tokens were collected\\n    /// @param recipient The address of the account that received the collected tokens\\n    /// @param amount0 The amount of token0 owed to the position that was collected\\n    /// @param amount1 The amount of token1 owed to the position that was collected\\n    event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);\\n\\n    /// @notice Returns the position information associated with a given token ID.\\n    /// @dev Throws if the token ID is not valid.\\n    /// @param tokenId The ID of the token that represents the position\\n    /// @return nonce The nonce for permits\\n    /// @return operator The address that is approved for spending\\n    /// @return token0 The address of the token0 for a specific pool\\n    /// @return token1 The address of the token1 for a specific pool\\n    /// @return fee The fee associated with the pool\\n    /// @return tickLower The lower end of the tick range for the position\\n    /// @return tickUpper The higher end of the tick range for the position\\n    /// @return liquidity The liquidity of the position\\n    /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position\\n    /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position\\n    /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation\\n    /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation\\n    function positions(uint256 tokenId)\\n        external\\n        view\\n        returns (\\n            uint96 nonce,\\n            address operator,\\n            address token0,\\n            address token1,\\n            uint24 fee,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    struct MintParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        address recipient;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Creates a new position wrapped in a NFT\\n    /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized\\n    /// a method does not exist, i.e. the pool is assumed to be initialized.\\n    /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata\\n    /// @return tokenId The ID of the token that represents the minted position\\n    /// @return liquidity The amount of liquidity for this position\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function mint(MintParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint256 tokenId,\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct IncreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`\\n    /// @param params tokenId The ID of the token for which liquidity is being increased,\\n    /// amount0Desired The desired amount of token0 to be spent,\\n    /// amount1Desired The desired amount of token1 to be spent,\\n    /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,\\n    /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return liquidity The new liquidity amount as a result of the increase\\n    /// @return amount0 The amount of token0 to acheive resulting liquidity\\n    /// @return amount1 The amount of token1 to acheive resulting liquidity\\n    function increaseLiquidity(IncreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1\\n        );\\n\\n    struct DecreaseLiquidityParams {\\n        uint256 tokenId;\\n        uint128 liquidity;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Decreases the amount of liquidity in a position and accounts it to the position\\n    /// @param params tokenId The ID of the token for which liquidity is being decreased,\\n    /// amount The amount by which liquidity will be decreased,\\n    /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,\\n    /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,\\n    /// deadline The time by which the transaction must be included to effect the change\\n    /// @return amount0 The amount of token0 accounted to the position's tokens owed\\n    /// @return amount1 The amount of token1 accounted to the position's tokens owed\\n    function decreaseLiquidity(DecreaseLiquidityParams calldata params)\\n        external\\n        payable\\n        returns (uint256 amount0, uint256 amount1);\\n\\n    struct CollectParams {\\n        uint256 tokenId;\\n        address recipient;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient\\n    /// @param params tokenId The ID of the NFT for which tokens are being collected,\\n    /// recipient The account that should receive the tokens,\\n    /// amount0Max The maximum amount of token0 to collect,\\n    /// amount1Max The maximum amount of token1 to collect\\n    /// @return amount0 The amount of fees collected in token0\\n    /// @return amount1 The amount of fees collected in token1\\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\\n\\n    /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens\\n    /// must be collected first.\\n    /// @param tokenId The ID of the token that is being burned\\n    function burn(uint256 tokenId) external payable;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWETH9 is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 wad) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IWPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IWPowerPerp is IERC20 {\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n}\\n\"\n    },\n    \"contracts/interfaces/IShortPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IShortPowerPerp is IERC721 {\\n    function nextId() external view returns (uint256);\\n\\n    function mintNFT(address recipient) external returns (uint256 _newId);\\n}\\n\"\n    },\n    \"contracts/interfaces/IOracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\ninterface IOracle {\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        uint32 _periodToHistoricPrice\\n    ) external view returns (uint256);\\n\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256);\\n\\n    function getMaxPeriod(address _pool) external view returns (uint32);\\n\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n    /**\\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n     * by `operator` from `from`, this function is called.\\n     *\\n     * It must return its Solidity selector to confirm the token transfer.\\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n     *\\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n     */\\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/access/Ownable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), 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        emit OwnershipTransferred(_owner, address(0));\\n        _owner = 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        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor () {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        // On the first call to nonReentrant, _notEntered will be true\\n        require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n\\n        _;\\n\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/math/SafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Address.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/ABDKMath64x64.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with signed\\n * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is\\n * basically a simple fraction whose numerator is signed 128-bit integer and\\n * denominator is 2^64.  As long as denominator is always the same, there is no\\n * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are\\n * represented by int128 type holding only the numerator.\\n *\\n * Commit used - 16d7e1dd8628dfa2f88d5dadab731df7ada70bdd\\n * Copied from - https://github.com/abdk-consulting/abdk-libraries-solidity/tree/v2.4\\n * Changes - some function visibility switched to public, solidity version set to 0.7.x\\n * Changes (cont) - revert strings added\\n * solidity version set to ^0.7.0\\n */\\nlibrary ABDKMath64x64 {\\n    /*\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * Minimum value signed 64.64-bit fixed point number may have.\\n     * -2^127\\n     */\\n    int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;\\n\\n    /*\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * Maximum value signed 64.64-bit fixed point number may have.\\n     * 2^127-1\\n     */\\n    int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n    /**\\n     * Calculate x * y rounding down.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @param y signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function mul(int128 x, int128 y) internal pure returns (int128) {\\n        int256 result = (int256(x) * y) >> 64;\\n        require(result >= MIN_64x64 && result <= MAX_64x64, \\\"MUL-OVUF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x * y rounding down, where x is signed 64.64 fixed point number\\n     * and y is unsigned 256-bit integer number.  Revert on overflow.\\n     *\\n     * @param x signed 64.64 fixed point number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 256-bit integer number\\n     */\\n    function mulu(int128 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) return 0;\\n\\n        require(x >= 0, \\\"MULU-X0\\\");\\n\\n        uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;\\n        uint256 hi = uint256(x) * (y >> 128);\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"MULU-OF1\\\");\\n        hi <<= 64;\\n\\n        require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo, \\\"MULU-OF2\\\");\\n        return hi + lo;\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function divu(uint256 x, uint256 y) public pure returns (int128) {\\n        require(y != 0, \\\"DIVU-INF\\\");\\n        uint128 result = divuu(x, y);\\n        require(result <= uint128(MAX_64x64), \\\"DIVU-OF\\\");\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary logarithm of x.  Revert if x <= 0.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function log_2(int128 x) public pure returns (int128) {\\n        require(x > 0, \\\"LOG_2-X0\\\");\\n\\n        int256 msb = 0;\\n        int256 xc = x;\\n        if (xc >= 0x10000000000000000) {\\n            xc >>= 64;\\n            msb += 64;\\n        }\\n        if (xc >= 0x100000000) {\\n            xc >>= 32;\\n            msb += 32;\\n        }\\n        if (xc >= 0x10000) {\\n            xc >>= 16;\\n            msb += 16;\\n        }\\n        if (xc >= 0x100) {\\n            xc >>= 8;\\n            msb += 8;\\n        }\\n        if (xc >= 0x10) {\\n            xc >>= 4;\\n            msb += 4;\\n        }\\n        if (xc >= 0x4) {\\n            xc >>= 2;\\n            msb += 2;\\n        }\\n        if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n        int256 result = (msb - 64) << 64;\\n        uint256 ux = uint256(x) << uint256(127 - msb);\\n        for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {\\n            ux *= ux;\\n            uint256 b = ux >> 255;\\n            ux >>= 127 + b;\\n            result += bit * int256(b);\\n        }\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate binary exponent of x.  Revert on overflow.\\n     *\\n     * @param x signed 64.64-bit fixed point number\\n     * @return signed 64.64-bit fixed point number\\n     */\\n    function exp_2(int128 x) public pure returns (int128) {\\n        require(x < 0x400000000000000000, \\\"EXP_2-OF\\\"); // Overflow\\n\\n        if (x < -0x400000000000000000) return 0; // Underflow\\n\\n        uint256 result = 0x80000000000000000000000000000000;\\n\\n        if (x & 0x8000000000000000 > 0) result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128;\\n        if (x & 0x4000000000000000 > 0) result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128;\\n        if (x & 0x2000000000000000 > 0) result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128;\\n        if (x & 0x1000000000000000 > 0) result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128;\\n        if (x & 0x800000000000000 > 0) result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128;\\n        if (x & 0x400000000000000 > 0) result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128;\\n        if (x & 0x200000000000000 > 0) result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128;\\n        if (x & 0x100000000000000 > 0) result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128;\\n        if (x & 0x80000000000000 > 0) result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128;\\n        if (x & 0x40000000000000 > 0) result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128;\\n        if (x & 0x20000000000000 > 0) result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128;\\n        if (x & 0x10000000000000 > 0) result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128;\\n        if (x & 0x8000000000000 > 0) result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128;\\n        if (x & 0x4000000000000 > 0) result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128;\\n        if (x & 0x2000000000000 > 0) result = (result * 0x1000162E525EE054754457D5995292026) >> 128;\\n        if (x & 0x1000000000000 > 0) result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128;\\n        if (x & 0x800000000000 > 0) result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128;\\n        if (x & 0x400000000000 > 0) result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128;\\n        if (x & 0x200000000000 > 0) result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128;\\n        if (x & 0x100000000000 > 0) result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128;\\n        if (x & 0x80000000000 > 0) result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128;\\n        if (x & 0x40000000000 > 0) result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128;\\n        if (x & 0x20000000000 > 0) result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128;\\n        if (x & 0x10000000000 > 0) result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128;\\n        if (x & 0x8000000000 > 0) result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128;\\n        if (x & 0x4000000000 > 0) result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128;\\n        if (x & 0x2000000000 > 0) result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128;\\n        if (x & 0x1000000000 > 0) result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128;\\n        if (x & 0x800000000 > 0) result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128;\\n        if (x & 0x400000000 > 0) result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128;\\n        if (x & 0x200000000 > 0) result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128;\\n        if (x & 0x100000000 > 0) result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128;\\n        if (x & 0x80000000 > 0) result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128;\\n        if (x & 0x40000000 > 0) result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128;\\n        if (x & 0x20000000 > 0) result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128;\\n        if (x & 0x10000000 > 0) result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128;\\n        if (x & 0x8000000 > 0) result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128;\\n        if (x & 0x4000000 > 0) result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128;\\n        if (x & 0x2000000 > 0) result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128;\\n        if (x & 0x1000000 > 0) result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128;\\n        if (x & 0x800000 > 0) result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128;\\n        if (x & 0x400000 > 0) result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128;\\n        if (x & 0x200000 > 0) result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128;\\n        if (x & 0x100000 > 0) result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128;\\n        if (x & 0x80000 > 0) result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128;\\n        if (x & 0x40000 > 0) result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128;\\n        if (x & 0x20000 > 0) result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128;\\n        if (x & 0x10000 > 0) result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128;\\n        if (x & 0x8000 > 0) result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128;\\n        if (x & 0x4000 > 0) result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128;\\n        if (x & 0x2000 > 0) result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128;\\n        if (x & 0x1000 > 0) result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128;\\n        if (x & 0x800 > 0) result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128;\\n        if (x & 0x400 > 0) result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128;\\n        if (x & 0x200 > 0) result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128;\\n        if (x & 0x100 > 0) result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128;\\n        if (x & 0x80 > 0) result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128;\\n        if (x & 0x40 > 0) result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128;\\n        if (x & 0x20 > 0) result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128;\\n        if (x & 0x10 > 0) result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128;\\n        if (x & 0x8 > 0) result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128;\\n        if (x & 0x4 > 0) result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128;\\n        if (x & 0x2 > 0) result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128;\\n        if (x & 0x1 > 0) result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128;\\n\\n        result >>= uint256(63 - (x >> 64));\\n        require(result <= uint256(MAX_64x64));\\n\\n        return int128(result);\\n    }\\n\\n    /**\\n     * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit\\n     * integer numbers.  Revert on overflow or when y is zero.\\n     *\\n     * @param x unsigned 256-bit integer number\\n     * @param y unsigned 256-bit integer number\\n     * @return unsigned 64.64-bit fixed point number\\n     */\\n    function divuu(uint256 x, uint256 y) private pure returns (uint128) {\\n        require(y != 0);\\n\\n        uint256 result;\\n\\n        if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y;\\n        else {\\n            uint256 msb = 192;\\n            uint256 xc = x >> 192;\\n            if (xc >= 0x100000000) {\\n                xc >>= 32;\\n                msb += 32;\\n            }\\n            if (xc >= 0x10000) {\\n                xc >>= 16;\\n                msb += 16;\\n            }\\n            if (xc >= 0x100) {\\n                xc >>= 8;\\n                msb += 8;\\n            }\\n            if (xc >= 0x10) {\\n                xc >>= 4;\\n                msb += 4;\\n            }\\n            if (xc >= 0x4) {\\n                xc >>= 2;\\n                msb += 2;\\n            }\\n            if (xc >= 0x2) msb += 1; // No need to shift xc anymore\\n\\n            result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1);\\n            require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF1\\\");\\n\\n            uint256 hi = result * (y >> 128);\\n            uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n\\n            uint256 xh = x >> 192;\\n            uint256 xl = x << 64;\\n\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n            lo = hi << 128;\\n            if (xl < lo) xh -= 1;\\n            xl -= lo; // We rely on overflow behavior here\\n\\n            assert(xh == hi >> 128);\\n\\n            result += xl / y;\\n        }\\n\\n        require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, \\\"DIVUU-OF2\\\");\\n        return uint128(result);\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/VaultLib.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {TickMathExternal} from \\\"./TickMathExternal.sol\\\";\\nimport {SqrtPriceMathPartial} from \\\"./SqrtPriceMathPartial.sol\\\";\\nimport {Uint256Casting} from \\\"./Uint256Casting.sol\\\";\\n\\n/**\\n * Error code:\\n * V1: Vault already had nft\\n * V2: Vault has no NFT\\n */\\nlibrary VaultLib {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint256 constant ONE_ONE = 1e36;\\n\\n    // the collateralization ratio (CR) is checked with the numerator and denominator separately\\n    // a user is safe if - collateral value >= (COLLAT_RATIO_NUMER/COLLAT_RATIO_DENOM)* debt value\\n    uint256 public constant CR_NUMERATOR = 3;\\n    uint256 public constant CR_DENOMINATOR = 2;\\n\\n    struct Vault {\\n        // the address that can update the vault\\n        address operator;\\n        // uniswap position token id deposited into the vault as collateral\\n        // 2^32 is 4,294,967,296, which means the vault structure will work with up to 4 billion positions\\n        uint32 NftCollateralId;\\n        // amount of eth (wei) used in the vault as collateral\\n        // 2^96 / 1e18 = 79,228,162,514, which means a vault can store up to 79 billion eth\\n        // when we need to do calculations, we always cast this number to uint256 to avoid overflow\\n        uint96 collateralAmount;\\n        // amount of wPowerPerp minted from the vault\\n        uint128 shortAmount;\\n    }\\n\\n    /**\\n     * @notice add eth collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to add\\n     */\\n    function addEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).add(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice add uniswap position token collateral to a vault\\n     * @param _vault in-memory vault\\n     * @param _tokenId uniswap position token id\\n     */\\n    function addUniNftCollateral(Vault memory _vault, uint256 _tokenId) internal pure {\\n        require(_vault.NftCollateralId == 0, \\\"V1\\\");\\n        require(_tokenId != 0, \\\"C23\\\");\\n        _vault.NftCollateralId = _tokenId.toUint32();\\n    }\\n\\n    /**\\n     * @notice remove eth collateral from a vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of eth to remove\\n     */\\n    function removeEthCollateral(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.collateralAmount = uint256(_vault.collateralAmount).sub(_amount).toUint96();\\n    }\\n\\n    /**\\n     * @notice remove uniswap position token collateral from a vault\\n     * @param _vault in-memory vault\\n     */\\n    function removeUniNftCollateral(Vault memory _vault) internal pure {\\n        require(_vault.NftCollateralId != 0, \\\"V2\\\");\\n        _vault.NftCollateralId = 0;\\n    }\\n\\n    /**\\n     * @notice add debt to vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to add\\n     */\\n    function addShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).add(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice remove debt from vault\\n     * @param _vault in-memory vault\\n     * @param _amount amount of debt to remove\\n     */\\n    function removeShort(Vault memory _vault, uint256 _amount) internal pure {\\n        _vault.shortAmount = uint256(_vault.shortAmount).sub(_amount).toUint128();\\n    }\\n\\n    /**\\n     * @notice check if a vault is properly collateralized\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _minCollateral minimum collateral that needs to be in a vault\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return true if the vault is sufficiently collateralized\\n     * @return true if the vault is considered as a dust vault\\n     */\\n    function getVaultStatus(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        uint256 _minCollateral,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (bool, bool) {\\n        if (_vault.shortAmount == 0) return (true, false);\\n\\n        uint256 debtValueInETH = uint256(_vault.shortAmount).mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        uint256 totalCollateral = _getEffectiveCollateral(\\n            _vault,\\n            _positionManager,\\n            _normalizationFactor,\\n            _ethQuoteCurrencyPrice,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n\\n        bool isDust = totalCollateral < _minCollateral;\\n        bool isAboveWater = totalCollateral.mul(CR_DENOMINATOR) >= debtValueInETH.mul(CR_NUMERATOR);\\n        return (isAboveWater, isDust);\\n    }\\n\\n    /**\\n     * @notice get the total effective collateral of a vault, which is:\\n     *         collateral amount + uniswap position token equivelent amount in eth\\n     * @param _vault the vault we want to check\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _normalizationFactor current _normalizationFactor\\n     * @param _ethQuoteCurrencyPrice current eth price scaled by 1e18\\n     * @param _wsqueethPoolTick current price tick for wsqueeth pool\\n     * @param _isWethToken0 whether weth is token0 in the wsqueeth pool\\n     * @return the total worth of collateral in the vault\\n     */\\n    function _getEffectiveCollateral(\\n        Vault memory _vault,\\n        address _positionManager,\\n        uint256 _normalizationFactor,\\n        uint256 _ethQuoteCurrencyPrice,\\n        int24 _wsqueethPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256) {\\n        if (_vault.NftCollateralId == 0) return _vault.collateralAmount;\\n\\n        // the user has deposited uniswap position token as collateral, see how much eth / wSqueeth the uniswap position token has\\n        (uint256 nftEthAmount, uint256 nftWsqueethAmount) = _getUniPositionBalances(\\n            _positionManager,\\n            _vault.NftCollateralId,\\n            _wsqueethPoolTick,\\n            _isWethToken0\\n        );\\n        // convert squeeth amount from uniswap position token as equivalent amount of collateral\\n        uint256 wSqueethIndexValueInEth = nftWsqueethAmount.mul(_normalizationFactor).mul(_ethQuoteCurrencyPrice).div(\\n            ONE_ONE\\n        );\\n        // add eth value from uniswap position token as collateral\\n        return nftEthAmount.add(wSqueethIndexValueInEth).add(_vault.collateralAmount);\\n    }\\n\\n    /**\\n     * @notice determine how much eth / wPowerPerp the uniswap position contains\\n     * @param _positionManager address of the uniswap position manager\\n     * @param _tokenId uniswap position token id\\n     * @param _wPowerPerpPoolTick current price tick\\n     * @param _isWethToken0 whether weth is token0 in the pool\\n     * @return ethAmount the eth amount this LP token contains\\n     * @return wPowerPerpAmount the wPowerPerp amount this LP token contains\\n     */\\n    function _getUniPositionBalances(\\n        address _positionManager,\\n        uint256 _tokenId,\\n        int24 _wPowerPerpPoolTick,\\n        bool _isWethToken0\\n    ) internal view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        (\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = _getUniswapPositionInfo(_positionManager, _tokenId);\\n        (uint256 amount0, uint256 amount1) = _getToken0Token1Balances(\\n            tickLower,\\n            tickUpper,\\n            _wPowerPerpPoolTick,\\n            liquidity\\n        );\\n\\n        return\\n            _isWethToken0\\n                ? (amount0 + tokensOwed0, amount1 + tokensOwed1)\\n                : (amount1 + tokensOwed1, amount0 + tokensOwed0);\\n    }\\n\\n    /**\\n     * @notice get uniswap position token info\\n     * @param _positionManager address of the uniswap position position manager\\n     * @param _tokenId uniswap position token id\\n     * @return tickLower lower tick of the position\\n     * @return tickUpper upper tick of the position\\n     * @return liquidity raw liquidity amount of the position\\n     * @return tokensOwed0 amount of token 0 can be collected as fee\\n     * @return tokensOwed1 amount of token 1 can be collected as fee\\n     */\\n    function _getUniswapPositionInfo(address _positionManager, uint256 _tokenId)\\n        internal\\n        view\\n        returns (\\n            int24,\\n            int24,\\n            uint128,\\n            uint128,\\n            uint128\\n        )\\n    {\\n        INonfungiblePositionManager positionManager = INonfungiblePositionManager(_positionManager);\\n        (\\n            ,\\n            ,\\n            ,\\n            ,\\n            ,\\n            int24 tickLower,\\n            int24 tickUpper,\\n            uint128 liquidity,\\n            ,\\n            ,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        ) = positionManager.positions(_tokenId);\\n        return (tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1);\\n    }\\n\\n    /**\\n     * @notice get balances of token0 / token1 in a uniswap position\\n     * @dev knowing liquidity, tick range, and current tick gives balances\\n     * @param _tickLower address of the uniswap position manager\\n     * @param _tickUpper uniswap position token id\\n     * @param _tick current price tick used for calculation\\n     * @return amount0 the amount of token0 in the uniswap position token\\n     * @return amount1 the amount of token1 in the uniswap position token\\n     */\\n    function _getToken0Token1Balances(\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        int24 _tick,\\n        uint128 _liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        // get the current price and tick from wPowerPerp pool\\n        uint160 sqrtPriceX96 = TickMathExternal.getSqrtRatioAtTick(_tick);\\n\\n        if (_tick < _tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        } else if (_tick < _tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtPriceX96,\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                sqrtPriceX96,\\n                _liquidity,\\n                true\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMathExternal.getSqrtRatioAtTick(_tickLower),\\n                TickMathExternal.getSqrtRatioAtTick(_tickUpper),\\n                _liquidity,\\n                true\\n            );\\n        }\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Uint256Casting.sol\": {\n      \"content\": \"//SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nlibrary Uint256Casting {\\n    /**\\n     * @notice cast a uint256 to a uint128, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint128\\n     */\\n    function toUint128(uint256 y) internal pure returns (uint128 z) {\\n        require((z = uint128(y)) == y, \\\"OF128\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint96, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint96\\n     */\\n    function toUint96(uint256 y) internal pure returns (uint96 z) {\\n        require((z = uint96(y)) == y, \\\"OF96\\\");\\n    }\\n\\n    /**\\n     * @notice cast a uint256 to a uint32, revert on overflow\\n     * @param y the uint256 to be downcasted\\n     * @return z the downcasted integer, now type uint32\\n     */\\n    function toUint32(uint256 y) internal pure returns (uint32 z) {\\n        require((z = uint32(y)) == y, \\\"OF32\\\");\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/Power2Base.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\n//lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary Power2Base {\\n    using SafeMath for uint256;\\n\\n    uint32 private constant TWAP_PERIOD = 420 seconds;\\n    uint256 private constant INDEX_SCALE = 1e4;\\n    uint256 private constant ONE = 1e18;\\n    uint256 private constant ONE_ONE = 1e36;\\n\\n    /**\\n     * @notice return the scaled down index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the unscaled index of the power perp in USD, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @return for squeeth, return ethPrice^2\\n     */\\n    function _getUnscaledIndex(\\n        uint32 _period,\\n        address _oracle,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getTwap(_oracle, _ethQuoteCurrencyPool, _weth, _quoteCurrency, _period, false);\\n        return ethQuoteCurrencyPrice.mul(ethQuoteCurrencyPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice return the mark price of power perp in quoteCurrency, scaled by 18 decimals\\n     * @param _period period of time for the twap in seconds (cannot be longer than maximum period for the pool)\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _ethQuoteCurrencyPool uniswap v3 pool for weth / quoteCurrency\\n     * @param _weth weth address\\n     * @param _quoteCurrency quoteCurrency address\\n     * @param _wSqueeth wSqueeth address\\n     * @param _normalizationFactor current normalization factor\\n     * @return for squeeth, return ethPrice * squeethPriceInEth\\n     */\\n    function _getDenormalizedMark(\\n        uint32 _period,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _ethQuoteCurrencyPool,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _wSqueeth,\\n        uint256 _normalizationFactor\\n    ) internal view returns (uint256) {\\n        uint256 ethQuoteCurrencyPrice = _getScaledTwap(\\n            _oracle,\\n            _ethQuoteCurrencyPool,\\n            _weth,\\n            _quoteCurrency,\\n            _period,\\n            false\\n        );\\n        uint256 wsqueethEthPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, _period, false);\\n\\n        return wsqueethEthPrice.mul(ethQuoteCurrencyPrice).div(_normalizationFactor);\\n    }\\n\\n    /**\\n     * @notice get the fair collateral value for a _debtAmount of wSqueeth\\n     * @dev the actual amount liquidator can get should have a 10% bonus on top of this value.\\n     * @param _debtAmount wSqueeth amount paid by liquidator\\n     * @param _oracle oracle address\\n     * @param _wSqueethEthPool uniswap v3 pool for wSqueeth / weth\\n     * @param _wSqueeth wSqueeth address\\n     * @param _weth weth address\\n     * @return returns value of debt in ETH\\n     */\\n    function _getDebtValueInEth(\\n        uint256 _debtAmount,\\n        address _oracle,\\n        address _wSqueethEthPool,\\n        address _wSqueeth,\\n        address _weth\\n    ) internal view returns (uint256) {\\n        uint256 wSqueethPrice = _getTwap(_oracle, _wSqueethEthPool, _wSqueeth, _weth, TWAP_PERIOD, false);\\n        return _debtAmount.mul(wSqueethPrice).div(ONE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle, scaled down by INDEX_SCALE\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average.\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return twap price scaled down by INDEX_SCALE\\n     */\\n    function _getScaledTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        uint256 twap = _getTwap(_oracle, _pool, _base, _quote, _period, _checkPeriod);\\n        return twap.div(INDEX_SCALE);\\n    }\\n\\n    /**\\n     * @notice request twap from our oracle\\n     * @dev this will revert if period is > max period for the pool\\n     * @param _oracle oracle address\\n     * @param _pool uniswap v3 pool address\\n     * @param _base base currency. to get eth/quoteCurrency price, eth is base token\\n     * @param _quote quote currency. to get eth/quoteCurrency price, quoteCurrency is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @param _checkPeriod check that period is not longer than maximum period for the pool to prevent reverts\\n     * @return human readable price. scaled by 1e18\\n     */\\n    function _getTwap(\\n        address _oracle,\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) internal view returns (uint256) {\\n        // period reaching this point should be check, otherwise might revert\\n        return IOracle(_oracle).getTwap(_pool, _base, _quote, _period, _checkPeriod);\\n    }\\n\\n    /**\\n     * @notice get the index value of wsqueeth in wei, used when system settles\\n     * @dev the index of squeeth is ethPrice^2, so each squeeth will need to pay out {ethPrice} eth\\n     * @param _wsqueethAmount amount of wsqueeth used in settlement\\n     * @param _indexPriceForSettlement index price for settlement\\n     * @param _normalizationFactor current normalization factor\\n     * @return amount in wei that should be paid to the token holder\\n     */\\n    function _getLongSettlementValue(\\n        uint256 _wsqueethAmount,\\n        uint256 _indexPriceForSettlement,\\n        uint256 _normalizationFactor\\n    ) internal pure returns (uint256) {\\n        return _wsqueethAmount.mul(_normalizationFactor).mul(_indexPriceForSettlement).div(ONE_ONE);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/IERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n\\n    /**\\n     * @dev Returns the token collection name.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the token collection symbol.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n     */\\n    function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n\\n    /**\\n     * @dev Returns the total amount of tokens stored by the contract.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n    /**\\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n     * Use along with {totalSupply} to enumerate all tokens.\\n     */\\n    function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Creates and initializes V3 Pools\\n/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that\\n/// require the pool to exist.\\ninterface IPoolInitializer {\\n    /// @notice Creates a new pool if it does not exist, then initializes if not initialized\\n    /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool\\n    /// @param token0 The contract address of token0 of the pool\\n    /// @param token1 The contract address of token1 of the pool\\n    /// @param fee The fee amount of the v3 pool for the specified token pair\\n    /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value\\n    /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary\\n    function createAndInitializePoolIfNecessary(\\n        address token0,\\n        address token1,\\n        uint24 fee,\\n        uint160 sqrtPriceX96\\n    ) external payable returns (address pool);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\n\\n/// @title ERC721 with permit\\n/// @notice Extension to ERC721 that includes a permit function for signature based approvals\\ninterface IERC721Permit is IERC721 {\\n    /// @notice The permit typehash used in the permit signature\\n    /// @return The typehash for the permit\\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n    /// @notice The domain separator used in the permit signature\\n    /// @return The domain seperator used in encoding of permit signature\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n\\n    /// @notice Approve of a specific token ID for spending by spender via signature\\n    /// @param spender The account that is being approved\\n    /// @param tokenId The ID of the token that is being approved for spending\\n    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work\\n    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`\\n    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`\\n    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`\\n    function permit(\\n        address spender,\\n        uint256 tokenId,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\n/// @title Periphery Payments\\n/// @notice Functions to ease deposits and withdrawals of ETH\\ninterface IPeripheryPayments {\\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\\n    /// @param recipient The address receiving ETH\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\\n\\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\\n    /// that use ether for the input amount\\n    function refundETH() external payable;\\n\\n    /// @notice Transfers the full amount of a token held by this contract to recipient\\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\\n    /// @param token The contract address of the token which will be transferred to `recipient`\\n    /// @param amountMinimum The minimum amount of token required for a transfer\\n    /// @param recipient The destination address of the token\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Immutable state\\n/// @notice Functions that return immutable state of the router\\ninterface IPeripheryImmutableState {\\n    /// @return Returns the address of the Uniswap V3 factory\\n    function factory() external view returns (address);\\n\\n    /// @return Returns the address of WETH9\\n    function WETH9() external view returns (address);\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\\nlibrary PoolAddress {\\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\\n\\n    /// @notice The identifying key of the pool\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\\n    /// @param tokenA The first token of a pool, unsorted\\n    /// @param tokenB The second token of a pool, unsorted\\n    /// @param fee The fee level of the pool\\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\\n    function getPoolKey(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal pure returns (PoolKey memory) {\\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\\n    }\\n\\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\\n    /// @param factory The Uniswap V3 factory contract address\\n    /// @param key The PoolKey\\n    /// @return pool The contract address of the V3 pool\\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\\n        require(key.token0 < key.token1);\\n        pool = address(\\n            uint256(\\n                keccak256(\\n                    abi.encodePacked(\\n                        hex'ff',\\n                        factory,\\n                        keccak256(abi.encode(key.token0, key.token1, key.fee)),\\n                        POOL_INIT_CODE_HASH\\n                    )\\n                )\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/IERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Context.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/TickMathExternal.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMathExternal {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) public pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), \\\"T\\\");\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, \\\"R\\\");\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"contracts/libs/SqrtPriceMathPartial.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\\\";\\n\\n/// @title Functions based on Q64.96 sqrt price and liquidity\\n/// @notice Exposes two functions from @uniswap/v3-core SqrtPriceMath\\n/// that use square root of price as a Q64.96 and liquidity to compute deltas\\nlibrary SqrtPriceMathPartial {\\n    /// @notice Gets the amount0 delta between two prices\\n    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),\\n    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up or down\\n    /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices\\n    function getAmount0Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;\\n        uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96;\\n\\n        require(sqrtRatioAX96 > 0);\\n\\n        return\\n            roundUp\\n                ? UnsafeMath.divRoundingUp(\\n                    FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96),\\n                    sqrtRatioAX96\\n                )\\n                : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Gets the amount1 delta between two prices\\n    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price\\n    /// @param sqrtRatioBX96 Another sqrt price\\n    /// @param liquidity The amount of usable liquidity\\n    /// @param roundUp Whether to round the amount up, or down\\n    /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices\\n    function getAmount1Delta(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity,\\n        bool roundUp\\n    ) external pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            roundUp\\n                ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96)\\n                : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FullMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n    /// @notice Calculates floor(a×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        // 512-bit multiply [prod1 prod0] = a * b\\n        // Compute the product mod 2**256 and mod 2**256 - 1\\n        // then use the Chinese Remainder Theorem to reconstruct\\n        // the 512 bit result. The result is stored in two 256\\n        // variables such that product = prod1 * 2**256 + prod0\\n        uint256 prod0; // Least significant 256 bits of the product\\n        uint256 prod1; // Most significant 256 bits of the product\\n        assembly {\\n            let mm := mulmod(a, b, not(0))\\n            prod0 := mul(a, b)\\n            prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n        }\\n\\n        // Handle non-overflow cases, 256 by 256 division\\n        if (prod1 == 0) {\\n            require(denominator > 0);\\n            assembly {\\n                result := div(prod0, denominator)\\n            }\\n            return result;\\n        }\\n\\n        // Make sure the result is less than 2**256.\\n        // Also prevents denominator == 0\\n        require(denominator > prod1);\\n\\n        ///////////////////////////////////////////////\\n        // 512 by 256 division.\\n        ///////////////////////////////////////////////\\n\\n        // Make division exact by subtracting the remainder from [prod1 prod0]\\n        // Compute remainder using mulmod\\n        uint256 remainder;\\n        assembly {\\n            remainder := mulmod(a, b, denominator)\\n        }\\n        // Subtract 256 bit number from 512 bit number\\n        assembly {\\n            prod1 := sub(prod1, gt(remainder, prod0))\\n            prod0 := sub(prod0, remainder)\\n        }\\n\\n        // Factor powers of two out of denominator\\n        // Compute largest power of two divisor of denominator.\\n        // Always >= 1.\\n        uint256 twos = -denominator & denominator;\\n        // Divide denominator by power of two\\n        assembly {\\n            denominator := div(denominator, twos)\\n        }\\n\\n        // Divide [prod1 prod0] by the factors of two\\n        assembly {\\n            prod0 := div(prod0, twos)\\n        }\\n        // Shift in bits from prod1 into prod0. For this we need\\n        // to flip `twos` such that it is 2**256 / twos.\\n        // If twos is zero, then it becomes one\\n        assembly {\\n            twos := add(div(sub(0, twos), twos), 1)\\n        }\\n        prod0 |= prod1 * twos;\\n\\n        // Invert denominator mod 2**256\\n        // Now that denominator is an odd number, it has an inverse\\n        // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n        // Compute the inverse by starting with a seed that is correct\\n        // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n        uint256 inv = (3 * denominator) ^ 2;\\n        // Now use Newton-Raphson iteration to improve the precision.\\n        // Thanks to Hensel's lifting lemma, this also works in modular\\n        // arithmetic, doubling the correct bits in each step.\\n        inv *= 2 - denominator * inv; // inverse mod 2**8\\n        inv *= 2 - denominator * inv; // inverse mod 2**16\\n        inv *= 2 - denominator * inv; // inverse mod 2**32\\n        inv *= 2 - denominator * inv; // inverse mod 2**64\\n        inv *= 2 - denominator * inv; // inverse mod 2**128\\n        inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n        // Because the division is now exact we can divide by multiplying\\n        // with the modular inverse of denominator. This will give us the\\n        // correct result modulo 2**256. Since the precoditions guarantee\\n        // that the outcome is less than 2**256, this is the final result.\\n        // We don't need to compute the high bits of the result and prod1\\n        // is no longer required.\\n        result = prod0 * inv;\\n        return result;\\n    }\\n\\n    /// @notice Calculates ceil(a×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        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    },\n    \"@uniswap/v3-core/contracts/libraries/UnsafeMath.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\": {\n      \"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\"\n    },\n    \"contracts/test/LiquidationHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\ncontract LiquidationHelper  {\\n\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n    using VaultLib for VaultLib.Vault;\\n\\n    // constatns\\n    uint256 public constant MIN_COLLATERAL = 0.5 ether;\\n    uint32 public constant TWAP_PERIOD = 420 seconds;\\n\\n    address immutable public controller;\\n    address immutable public oracle;\\n    address immutable public wPowerPerp;\\n    address immutable public weth;\\n    address immutable public quoteCurrency;\\n    address immutable public ethQuoteCurrencyPool;\\n    address immutable public wPowerPerpPool;\\n    address immutable public uniswapPositionManager;\\n\\n    bool immutable isWethToken0;\\n    \\n    constructor(\\n        address _controller,\\n        address _oracle,\\n        address _wPowerPerp,\\n        address _weth,\\n        address _quoteCurrency,\\n        address _ethQuoteCurrencyPool,\\n        address _wPowerPerpPool,\\n        address _uniPositionManager\\n    ) {\\n        controller = _controller;\\n        oracle = _oracle;\\n        wPowerPerp = _wPowerPerp;\\n        weth = _weth;\\n        quoteCurrency = _quoteCurrency;\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        wPowerPerpPool = _wPowerPerpPool;\\n        uniswapPositionManager = _uniPositionManager;\\n        isWethToken0 = _weth < _wPowerPerp;\\n    }\\n    \\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function checkLiquidation(uint256 _vaultId)\\n        external\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 _newNormalizationFactor = IController(controller).getExpectedNormalizationFactor();\\n        return _checkLiquidation(_vaultId, _newNormalizationFactor);\\n    }\\n\\n    /**\\n     * @notice check that the vault has enough collateral\\n     * @param _vault in-memory vault\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is properly collateralized\\n     */\\n    function _isVaultSafe(VaultLib.Vault memory _vault, uint256 _normalizationFactor) internal view returns (bool) {\\n        (bool isSafe, ) = _getVaultStatus(_vault, _normalizationFactor);\\n        return isSafe;\\n    }\\n\\n    /**\\n     * @notice return if the vault is properly collateralized and if it is a dust vault\\n     * @param _vault the Vault memory to update\\n     * @param _normalizationFactor normalization factor\\n     * @return true if the vault is safe\\n     * @return true if the vault is a dust vault\\n     */\\n    function _getVaultStatus(VaultLib.Vault memory _vault, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (bool, bool)\\n    {\\n        uint256 scaledEthPrice = Power2Base._getScaledTwap(\\n            oracle,\\n            ethQuoteCurrencyPool,\\n            weth,\\n            quoteCurrency,\\n            TWAP_PERIOD,\\n            true // do not call more than maximum period so it does not revert\\n        );\\n        return\\n            VaultLib.getVaultStatus(\\n                _vault,\\n                uniswapPositionManager,\\n                _normalizationFactor,\\n                scaledEthPrice,\\n                MIN_COLLATERAL,\\n                IOracle(oracle).getTimeWeightedAverageTickSafe(wPowerPerpPool, TWAP_PERIOD),\\n                isWethToken0\\n            );\\n    }\\n\\n    /**\\n     * @notice check the result of a call to liquidate\\n     * @dev can be used before sending a transaction to determine if the vault is unsafe, if vault can be saved\\n     * @dev the minimum wPowerPerp to repay, the maximum wPowerPerp to repay and the proceeds at max wPowerPerp to repay\\n     * @param _vaultId vault to liquidate\\n     * @return isUnsafe\\n     * @return isLiquidatable after reducing debt\\n     * @return max wPowerPerp to repay, this is only non-zero if saving a vault is not possible\\n     * @return proceeds at max wPowerPerp to repay, if isLiquidatable after reducing debt is false, this is the bounty for saving a vault\\n     */\\n    function _checkLiquidation(uint256 _vaultId, uint256 _normalizationFactor)\\n        internal\\n        view\\n        returns (\\n            bool,\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        VaultLib.Vault memory cachedVault = IController(controller).vaults(_vaultId);\\n\\n        if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n            return (false, false, 0, 0);\\n        }\\n\\n        // if there's a Uniswap Position token in the vault, stimulate reducing debt first\\n        if (cachedVault.NftCollateralId != 0) {\\n            // using current tick to check how much nft is worth\\n            (, int24 spotTick, , , , , ) = IUniswapV3Pool(wPowerPerpPool).slot0();\\n\\n            // simulate vault state after removing nft\\n            (uint256 nftEthAmount, uint256 nftWPowerperpAmount) = VaultLib._getUniPositionBalances(\\n                uniswapPositionManager,\\n                cachedVault.NftCollateralId,\\n                spotTick,\\n                isWethToken0\\n            );\\n\\n            (, , uint256 bounty) = _getReduceDebtResultInVault(\\n                cachedVault,\\n                nftEthAmount,\\n                nftWPowerperpAmount,\\n                true\\n            );\\n\\n            if (_isVaultSafe(cachedVault, _normalizationFactor)) {\\n                return (true, false, 0, bounty);\\n            }\\n            //re-add bounty if not safe after reducing debt\\n            cachedVault.addEthCollateral(bounty);\\n        }\\n\\n        // assuming the max the liquidator is willing to pay full debt, this should give us the max one can liquidate\\n        (uint256 wMaxAmountToLiquidate, uint256 collateralToPay) = _getLiquidationResult(\\n            cachedVault.shortAmount,\\n            cachedVault.shortAmount,\\n            cachedVault.collateralAmount\\n        );\\n\\n        return (true, true, wMaxAmountToLiquidate, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice get the expected excess, burnAmount and bounty if Uniswap position token got burned\\n     * @dev this function will update the vault memory in-place\\n     * @return burnAmount amount of wSqueeth that should be burned\\n     * @return wPowerPerpExcess amount of wSqueeth that should be send to the vault owner\\n     * @return bounty amount of bounty should be paid out to caller\\n     */\\n    function _getReduceDebtResultInVault(\\n        VaultLib.Vault memory _vault,\\n        uint256 nftEthAmount,\\n        uint256 nftWPowerperpAmount,\\n        bool _payBounty\\n    )\\n        internal\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 bounty;\\n        if (_payBounty) bounty = _getReduceDebtBounty(nftEthAmount, nftWPowerperpAmount);\\n\\n        uint256 burnAmount = nftWPowerperpAmount;\\n        uint256 wPowerPerpExcess;\\n\\n        if (nftWPowerperpAmount > _vault.shortAmount) {\\n            wPowerPerpExcess = nftWPowerperpAmount.sub(_vault.shortAmount);\\n            burnAmount = _vault.shortAmount;\\n        }\\n\\n        _vault.removeShort(burnAmount);\\n        _vault.removeUniNftCollateral();\\n        _vault.addEthCollateral(nftEthAmount);\\n        _vault.removeEthCollateral(bounty);\\n\\n        return (burnAmount, wPowerPerpExcess, bounty);\\n    }\\n\\n    /**\\n     * @notice get how much bounty you can get by helping a vault reducing the debt.\\n     * @dev bounty is 2% of the total value of the position token\\n     * @param _ethWithdrawn amount of eth withdrawn from uniswap by redeeming the position token\\n     * @param _wPowerPerpReduced amount of wPowerPerp withdrawn from uniswap by redeeming the position token\\n     */\\n    function _getReduceDebtBounty(\\n        uint256 _ethWithdrawn,\\n        uint256 _wPowerPerpReduced\\n    ) internal view returns (uint256) {\\n        return\\n            Power2Base\\n                ._getDebtValueInEth(\\n                    _wPowerPerpReduced,\\n                    oracle,\\n                    wPowerPerpPool,\\n                    wPowerPerp,\\n                    weth\\n                )\\n                .add(_ethWithdrawn)\\n                .mul(2)\\n                .div(100);\\n    }\\n\\n    /**\\n     * @notice get the expected wPowerPerp needed to liquidate a vault.\\n     * @dev a liquidator cannot liquidate more than half of a vault, unless only liquidating half of the debt will make the vault a \\\"dust vault\\\"\\n     * @dev a liquidator cannot take out more collateral than the vault holds\\n     * @param _maxWPowerPerpAmount the max amount of wPowerPerp willing to pay\\n     * @param _vaultShortAmount the amount of short in the vault\\n     * @param _maxWPowerPerpAmount the amount of collateral in the vault\\n     * @return finalLiquidateAmount the amount that should be liquidated. This amount can be higher than _maxWPowerPerpAmount, which should be checked\\n     * @return collateralToPay final amount of collateral paying out to the liquidator\\n     */\\n    function _getLiquidationResult(\\n        uint256 _maxWPowerPerpAmount,\\n        uint256 _vaultShortAmount,\\n        uint256 _vaultCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        // try limiting liquidation amount to half of the vault debt\\n        (uint256 finalLiquidateAmount, uint256 collateralToPay) = _getSingleLiquidationAmount(\\n            _maxWPowerPerpAmount,\\n            _vaultShortAmount.div(2)\\n        );\\n\\n        if (_vaultCollateralAmount > collateralToPay) {\\n            if (_vaultCollateralAmount.sub(collateralToPay) < MIN_COLLATERAL) {\\n                // the vault is left with dust after liquidation, allow liquidating full vault\\n                // calculate the new liquidation amount and collateral again based on the new limit\\n                (finalLiquidateAmount, collateralToPay) = _getSingleLiquidationAmount(\\n                    _maxWPowerPerpAmount,\\n                    _vaultShortAmount\\n                );\\n            }\\n        }\\n\\n        // check if final collateral to pay is greater than vault amount.\\n        // if so the system only pays out the amount the vault has, which may not be profitable\\n        if (collateralToPay > _vaultCollateralAmount) {\\n            // force liquidator to pay full debt amount\\n            finalLiquidateAmount = _vaultShortAmount;\\n            collateralToPay = _vaultCollateralAmount;\\n        }\\n\\n        return (finalLiquidateAmount, collateralToPay);\\n    }\\n\\n    /**\\n     * @notice determine how much wPowerPerp to liquidate, and how much collateral to return\\n     * @param _maxInputWAmount maximum wPowerPerp amount liquidator is willing to repay\\n     * @param _maxLiquidatableWAmount maximum wPowerPerp amount a liquidator is allowed to repay\\n     * @return finalWAmountToLiquidate amount of wPowerPerp the liquidator will burn\\n     * @return collateralToPay total collateral the liquidator will get\\n     */\\n    function _getSingleLiquidationAmount(\\n        uint256 _maxInputWAmount,\\n        uint256 _maxLiquidatableWAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 finalWAmountToLiquidate = _maxInputWAmount > _maxLiquidatableWAmount\\n            ? _maxLiquidatableWAmount\\n            : _maxInputWAmount;\\n\\n        uint256 collateralToPay = Power2Base._getDebtValueInEth(\\n            finalWAmountToLiquidate,\\n            oracle,\\n            wPowerPerpPool,\\n            wPowerPerp,\\n            weth\\n        );\\n\\n        // add 10% bonus for liquidators\\n        collateralToPay = collateralToPay.add(collateralToPay.div(10));\\n\\n        return (finalWAmountToLiquidate, collateralToPay);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport './pool/IUniswapV3PoolImmutables.sol';\\nimport './pool/IUniswapV3PoolState.sol';\\nimport './pool/IUniswapV3PoolDerivedState.sol';\\nimport './pool/IUniswapV3PoolActions.sol';\\nimport './pool/IUniswapV3PoolOwnerActions.sol';\\nimport './pool/IUniswapV3PoolEvents.sol';\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n    IUniswapV3PoolImmutables,\\n    IUniswapV3PoolState,\\n    IUniswapV3PoolDerivedState,\\n    IUniswapV3PoolActions,\\n    IUniswapV3PoolOwnerActions,\\n    IUniswapV3PoolEvents\\n{\\n\\n}\\n\"\n    },\n    \"contracts/interfaces/IController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ninterface IController {\\n    function ethQuoteCurrencyPool() external view returns (address);\\n\\n    function feeRate() external view returns (uint256);\\n\\n    function getFee(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _collateralAmount\\n    ) external view returns (uint256);\\n\\n    function quoteCurrency() external view returns (address);\\n\\n    function vaults(uint256 _vaultId) external view returns (VaultLib.Vault memory);\\n\\n    function shortPowerPerp() external view returns (address);\\n\\n    function wPowerPerp() external view returns (address);\\n\\n    function wPowerPerpPool() external view returns (address);\\n\\n    function oracle() external view returns (address);\\n\\n    function weth() external view returns (address);\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256);\\n\\n    function mintPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId, uint256 wPowerPerpAmount);\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _uniTokenId\\n    ) external payable returns (uint256 vaultId);\\n\\n    /**\\n     * Deposit collateral into a vault\\n     */\\n    function deposit(uint256 _vaultId) external payable;\\n\\n    /**\\n     * Withdraw collateral from a vault.\\n     */\\n    function withdraw(uint256 _vaultId, uint256 _amount) external payable;\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external;\\n\\n    function burnPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _withdrawAmount\\n    ) external returns (uint256 wPowerPerpAmount);\\n\\n    function liquidate(uint256 _vaultId, uint256 _maxDebtAmount) external returns (uint256);\\n\\n    function updateOperator(uint256 _vaultId, address _operator) external;\\n\\n    /**\\n     * External function to update the normalized factor as a way to pay funding.\\n     */\\n    function applyFunding() external;\\n\\n    function redeemShort(uint256 _vaultId) external;\\n\\n    function reduceDebtShutdown(uint256 _vaultId) external;\\n\\n    function isShutDown() external returns (bool);\\n\\n    function depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId) external;\\n\\n    function withdrawUniPositionToken(uint256 _vaultId) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n    /// when accessed externally.\\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n    /// boundary.\\n    /// observationIndex The index of the last oracle observation that was written,\\n    /// observationCardinality The current maximum number of observations stored in the pool,\\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n    /// feeProtocol The protocol fee for both tokens of the pool.\\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n    /// unlocked Whether the pool is currently locked to reentrancy\\n    function slot0()\\n        external\\n        view\\n        returns (\\n            uint160 sqrtPriceX96,\\n            int24 tick,\\n            uint16 observationIndex,\\n            uint16 observationCardinality,\\n            uint16 observationCardinalityNext,\\n            uint8 feeProtocol,\\n            bool unlocked\\n        );\\n\\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n    /// @dev This value can overflow the uint256\\n    function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\\n    /// @dev Protocol fees will never exceed uint128 max in either token\\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\\n\\n    /// @notice The currently in range liquidity available to the pool\\n    /// @dev This value has no relationship to the total liquidity across all ticks\\n    function liquidity() external view returns (uint128);\\n\\n    /// @notice Look up information about a specific tick in the pool\\n    /// @param tick The tick to look up\\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n    /// tick upper,\\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n    /// a specific position.\\n    function ticks(int24 tick)\\n        external\\n        view\\n        returns (\\n            uint128 liquidityGross,\\n            int128 liquidityNet,\\n            uint256 feeGrowthOutside0X128,\\n            uint256 feeGrowthOutside1X128,\\n            int56 tickCumulativeOutside,\\n            uint160 secondsPerLiquidityOutsideX128,\\n            uint32 secondsOutside,\\n            bool initialized\\n        );\\n\\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n    /// @notice Returns the information about a position by the position's key\\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n    /// @return _liquidity The amount of liquidity in the position,\\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n    function positions(bytes32 key)\\n        external\\n        view\\n        returns (\\n            uint128 _liquidity,\\n            uint256 feeGrowthInside0LastX128,\\n            uint256 feeGrowthInside1LastX128,\\n            uint128 tokensOwed0,\\n            uint128 tokensOwed1\\n        );\\n\\n    /// @notice Returns data about a specific observation index\\n    /// @param index The element of the observations array to fetch\\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n    /// ago, rather than at a specific index in the array.\\n    /// @return blockTimestamp The timestamp of the observation,\\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\\n    function observations(uint256 index)\\n        external\\n        view\\n        returns (\\n            uint32 blockTimestamp,\\n            int56 tickCumulative,\\n            uint160 secondsPerLiquidityCumulativeX128,\\n            bool initialized\\n        );\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol\": {\n      \"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\"\n    },\n    \"contracts/test/OracleTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {Oracle} from \\\"../core/Oracle.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\n/**\\n * use this contract to test how to get twap from exactly 1 timestamp\\n * Since we can't access block.timestamp offchain before sending the tx\\n */\\ncontract OracleTester is Oracle{\\n\\n  using Uint256Casting for uint256;\\n\\n  IOracle oracle;\\n\\n  constructor(address _oracle) {\\n    oracle = IOracle(_oracle);\\n  }\\n\\n  function testGetTwapSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, false);\\n  }\\n\\n  function testGetTwapSafeSince(\\n    uint256 _sinceTimestamp, \\n    address _pool, \\n    address _base, \\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTwap(_pool, _base, _quote, period, true);\\n  }\\n\\n  function testGetWeightedTickSafe(\\n    uint256 _sinceTimestamp,\\n    address _pool\\n  ) view external returns (int24) {\\n    uint32 period = uint32(block.timestamp - _sinceTimestamp);\\n    return oracle.getTimeWeightedAverageTickSafe(_pool, period);\\n  }\\n\\n  function testGetHistoricalTwapToNow(\\n    uint256 _startTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=0;\\n    \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testGetHistoricalTwap(\\n    uint256 _startTimestamp,\\n    uint256 _endTimestamp,\\n    address _pool,\\n    address _base,\\n    address _quote\\n  ) view external returns (uint256) {\\n    uint32 secondsAgoToStartOfTwap = uint32(block.timestamp - _startTimestamp);  \\n    uint32 secondsAgoToEndOfTwap=uint32(block.timestamp - _endTimestamp); \\n        \\n    return oracle.getHistoricalTwap(_pool, _base, _quote, secondsAgoToStartOfTwap, secondsAgoToEndOfTwap);\\n  }\\n\\n  function testToUint128(uint256 y) external pure returns (uint128 z) {\\n      return y.toUint128();\\n  }\\n}\"\n    },\n    \"contracts/core/Oracle.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n//library\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\nimport {OracleLibrary} from \\\"../libs/OracleLibrary.sol\\\";\\n\\n/**\\n * @notice read UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\\n * @dev if ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\\n */\\ncontract Oracle {\\n    using SafeMath for uint256;\\n    using Uint256Casting for uint256;\\n\\n    uint128 private constant ONE = 1e18;\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period,\\n        bool _checkPeriod\\n    ) external view returns (uint256) {\\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\\n\\n        // make sure the requested period < maxPeriod the pool recorded.\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function getHistoricalTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) external view returns (uint256) {\\n        return _fetchHistoricTwap(_pool, _base, _quote, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function getMaxPeriod(address _pool) external view returns (uint32) {\\n        return _getMaxPeriod(_pool);\\n    }\\n\\n    /**\\n     * @notice get time weighed average tick, not converted to price\\n     * @dev this function will not revert\\n     * @param _pool address of the pool\\n     * @param _period period in second that we want to calculate average on\\n     * @return timeWeightedAverageTick the time weighted average tick\\n     */\\n    function getTimeWeightedAverageTickSafe(address _pool, uint32 _period)\\n        external\\n        view\\n        returns (int24 timeWeightedAverageTick)\\n    {\\n        uint32 maxPeriod = _getMaxPeriod(_pool);\\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\\n        return OracleLibrary.consultAtHistoricTime(_pool, requestPeriod, 0);\\n    }\\n\\n    /**\\n     * @notice get twap converted with base & quote token decimals\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return twap price which is scaled\\n     */\\n    function _fetchTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        uint256 quoteAmountOut = _fetchRawTwap(_pool, _base, _quote, _period);\\n\\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\\n\\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\\n        if (baseDecimals > quoteDecimals) return quoteAmountOut.mul(10**(baseDecimals - quoteDecimals));\\n\\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\\n        return quoteAmountOut.div(10**(quoteDecimals - baseDecimals));\\n    }\\n\\n    /**\\n     * @notice get raw twap from the uniswap pool\\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\".\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _period number of seconds in the past to start calculating time-weighted average\\n     * @return amount of quote currency received for _amountIn of base currency\\n     */\\n    function _fetchRawTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _period\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get twap for a specific period of time, converted with base & quote token decimals\\n     * @dev if the _secondsAgoToStartOfTwap period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \\\"OLD\\\"\\n     * @param _pool uniswap pool address\\n     * @param _base base currency. to get eth/usd price, eth is base token\\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\\n     * @param _secondsAgoToStartOfTwap amount of seconds in the past to start calculating time-weighted average\\n     * @param _secondsAgoToEndOfTwap amount of seconds in the past to end calculating time-weighted average\\n     * @return price of 1 base currency in quote currency. scaled by 1e18\\n     */\\n    function _fetchHistoricTwap(\\n        address _pool,\\n        address _base,\\n        address _quote,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (uint256) {\\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _secondsAgoToStartOfTwap, _secondsAgoToEndOfTwap);\\n\\n        return OracleLibrary.getQuoteAtTick(twapTick, ONE, _base, _quote);\\n    }\\n\\n    /**\\n     * @notice get the max period that can be used to request twap\\n     * @param _pool uniswap pool address\\n     * @return max period can be used to request twap\\n     */\\n    function _getMaxPeriod(address _pool) internal view returns (uint32) {\\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\\n        // observationIndex: the index of the last oracle observation that was written\\n        // cardinality: the current maximum number of observations stored in the pool\\n        (, , uint16 observationIndex, uint16 cardinality, , , ) = pool.slot0();\\n\\n        // first observation index\\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\\n\\n        (uint32 oldestObservationTimestamp, , , bool initialized) = pool.observations(oldestObservationIndex);\\n\\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\\n\\n        // (index + 1) % cardinality is not the oldest index,\\n        // probably because cardinality is increased after last observation.\\n        // in this case, observation at index 0 should be the oldest.\\n        (oldestObservationTimestamp, , , ) = pool.observations(0);\\n\\n        return uint32(block.timestamp) - oldestObservationTimestamp;\\n    }\\n}\\n\"\n    },\n    \"contracts/interfaces/IERC20Detailed.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// uniswap Library only works under 0.7.6\\npragma solidity =0.7.6;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC20Detailed is IERC20 {\\n    function decimals() external view returns (uint8);\\n}\\n\"\n    },\n    \"contracts/libs/OracleLibrary.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity >=0.5.0 <0.8.0;\\n\\n//interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n//lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/FullMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n/// @title oracle library\\n/// @notice provides functions to integrate with uniswap v3 oracle\\n/// @author uniswap team other than consultAtHistoricTime(), built by opyn\\nlibrary OracleLibrary {\\n    /// @notice fetches time-weighted average tick using uniswap v3 oracle\\n    /// @dev written by opyn team\\n    /// @param pool Address of uniswap v3 pool that we want to observe\\n    /// @param _secondsAgoToStartOfTwap number of seconds to start of TWAP period\\n    /// @param _secondsAgoToEndOfTwap number of seconds to end of TWAP period\\n    /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - _secondsAgoToStartOfTwap) to _secondsAgoToEndOfTwap\\n    function consultAtHistoricTime(\\n        address pool,\\n        uint32 _secondsAgoToStartOfTwap,\\n        uint32 _secondsAgoToEndOfTwap\\n    ) internal view returns (int24) {\\n        require(_secondsAgoToStartOfTwap > _secondsAgoToEndOfTwap, \\\"BP\\\");\\n        int24 timeWeightedAverageTick;\\n        uint32[] memory secondAgos = new uint32[](2);\\n\\n        uint32 twapDuration = _secondsAgoToStartOfTwap - _secondsAgoToEndOfTwap;\\n\\n        // get TWAP from (now - _secondsAgoToStartOfTwap) -> (now - _secondsAgoToEndOfTwap)\\n        secondAgos[0] = _secondsAgoToStartOfTwap;\\n        secondAgos[1] = _secondsAgoToEndOfTwap;\\n\\n        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);\\n        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];\\n\\n        timeWeightedAverageTick = int24(tickCumulativesDelta / (twapDuration));\\n\\n        // Always round to negative infinity\\n        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % (twapDuration) != 0)) timeWeightedAverageTick--;\\n\\n        return timeWeightedAverageTick;\\n    }\\n\\n    /// @notice given a tick and a token amount, calculates the amount of token received in exchange\\n    /// @param tick tick value used to calculate the quote\\n    /// @param baseAmount amount of token to be converted\\n    /// @param baseToken address of an ERC20 token contract used as the baseAmount denomination\\n    /// @param quoteToken address of an ERC20 token contract used as the quoteAmount denomination\\n    /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\\n    function getQuoteAtTick(\\n        int24 tick,\\n        uint128 baseAmount,\\n        address baseToken,\\n        address quoteToken\\n    ) internal pure returns (uint256 quoteAmount) {\\n        uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);\\n\\n        // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself\\n        if (sqrtRatioX96 <= type(uint128).max) {\\n            uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)\\n                : FullMath.mulDiv(1 << 192, baseAmount, ratioX192);\\n        } else {\\n            uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);\\n            quoteAmount = baseToken < quoteToken\\n                ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)\\n                : FullMath.mulDiv(1 << 128, baseAmount, ratioX128);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/TickMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n    int24 internal constant MIN_TICK = -887272;\\n    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n    int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n    uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n    /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n    /// @dev Throws if |tick| > max tick\\n    /// @param tick The input tick for the above formula\\n    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n    /// at the given tick\\n    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\\n        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\\n        require(absTick <= uint256(MAX_TICK), 'T');\\n\\n        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\\n        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n        if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\\n    }\\n\\n    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n    /// ever return.\\n    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\\n        // second inequality must be < because the price can never reach the price at the max tick\\n        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\\n        uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n        uint256 r = ratio;\\n        uint256 msb = 0;\\n\\n        assembly {\\n            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(5, gt(r, 0xFFFFFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(4, gt(r, 0xFFFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(3, gt(r, 0xFF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(2, gt(r, 0xF))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := shl(1, gt(r, 0x3))\\n            msb := or(msb, f)\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            let f := gt(r, 0x1)\\n            msb := or(msb, f)\\n        }\\n\\n        if (msb >= 128) r = ratio >> (msb - 127);\\n        else r = ratio << (127 - msb);\\n\\n        int256 log_2 = (int256(msb) - 128) << 64;\\n\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(63, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(62, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(61, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(60, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(59, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(58, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(57, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(56, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(55, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(54, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(53, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(52, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(51, f))\\n            r := shr(f, r)\\n        }\\n        assembly {\\n            r := shr(127, mul(r, r))\\n            let f := shr(128, r)\\n            log_2 := or(log_2, shl(50, f))\\n        }\\n\\n        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\\n        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\\n\\n        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\n\\nimport '../libraries/PoolAddress.sol';\\nimport '../libraries/CallbackValidation.sol';\\nimport '../libraries/LiquidityAmounts.sol';\\n\\nimport './PeripheryPayments.sol';\\nimport './PeripheryImmutableState.sol';\\n\\n/// @title Liquidity management functions\\n/// @notice Internal functions for safely managing liquidity in Uniswap V3\\nabstract contract LiquidityManagement is IUniswapV3MintCallback, PeripheryImmutableState, PeripheryPayments {\\n    struct MintCallbackData {\\n        PoolAddress.PoolKey poolKey;\\n        address payer;\\n    }\\n\\n    /// @inheritdoc IUniswapV3MintCallback\\n    function uniswapV3MintCallback(\\n        uint256 amount0Owed,\\n        uint256 amount1Owed,\\n        bytes calldata data\\n    ) external override {\\n        MintCallbackData memory decoded = abi.decode(data, (MintCallbackData));\\n        CallbackValidation.verifyCallback(factory, decoded.poolKey);\\n\\n        if (amount0Owed > 0) pay(decoded.poolKey.token0, decoded.payer, msg.sender, amount0Owed);\\n        if (amount1Owed > 0) pay(decoded.poolKey.token1, decoded.payer, msg.sender, amount1Owed);\\n    }\\n\\n    struct AddLiquidityParams {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n        address recipient;\\n        int24 tickLower;\\n        int24 tickUpper;\\n        uint256 amount0Desired;\\n        uint256 amount1Desired;\\n        uint256 amount0Min;\\n        uint256 amount1Min;\\n    }\\n\\n    /// @notice Add liquidity to an initialized pool\\n    function addLiquidity(AddLiquidityParams memory params)\\n        internal\\n        returns (\\n            uint128 liquidity,\\n            uint256 amount0,\\n            uint256 amount1,\\n            IUniswapV3Pool pool\\n        )\\n    {\\n        PoolAddress.PoolKey memory poolKey =\\n            PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee});\\n\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n\\n        // compute the liquidity amount\\n        {\\n            (uint160 sqrtPriceX96, , , , , , ) = pool.slot0();\\n            uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);\\n            uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);\\n\\n            liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n                sqrtPriceX96,\\n                sqrtRatioAX96,\\n                sqrtRatioBX96,\\n                params.amount0Desired,\\n                params.amount1Desired\\n            );\\n        }\\n\\n        (amount0, amount1) = pool.mint(\\n            params.recipient,\\n            params.tickLower,\\n            params.tickUpper,\\n            liquidity,\\n            abi.encode(MintCallbackData({poolKey: poolKey, payer: msg.sender}))\\n        );\\n\\n        require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3MintCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';\\nimport './PoolAddress.sol';\\n\\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\\nlibrary CallbackValidation {\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param tokenA The contract address of either token0 or token1\\n    /// @param tokenB The contract address of the other token\\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(\\n        address factory,\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (IUniswapV3Pool pool) {\\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n\\n    /// @notice Returns the address of a valid Uniswap V3 Pool\\n    /// @param factory The contract address of the Uniswap V3 factory\\n    /// @param poolKey The identifying key of the V3 pool\\n    /// @return pool The V3 pool contract address\\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\\n        internal\\n        view\\n        returns (IUniswapV3Pool pool)\\n    {\\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\\n        require(msg.sender == address(pool));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nimport '../interfaces/IPeripheryPayments.sol';\\nimport '../interfaces/external/IWETH9.sol';\\n\\nimport '../libraries/TransferHelper.sol';\\n\\nimport './PeripheryImmutableState.sol';\\n\\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\\n    receive() external payable {\\n        require(msg.sender == WETH9, 'Not WETH9');\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable override {\\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\\n\\n        if (balanceWETH9 > 0) {\\n            IWETH9(WETH9).withdraw(balanceWETH9);\\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function sweepToken(\\n        address token,\\n        uint256 amountMinimum,\\n        address recipient\\n    ) external payable override {\\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\\n        require(balanceToken >= amountMinimum, 'Insufficient token');\\n\\n        if (balanceToken > 0) {\\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\\n        }\\n    }\\n\\n    /// @inheritdoc IPeripheryPayments\\n    function refundETH() external payable override {\\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\\n    }\\n\\n    /// @param token The token to pay\\n    /// @param payer The entity that must pay\\n    /// @param recipient The entity that will receive payment\\n    /// @param value The amount to pay\\n    function pay(\\n        address token,\\n        address payer,\\n        address recipient,\\n        uint256 value\\n    ) internal {\\n        if (token == WETH9 && address(this).balance >= value) {\\n            // pay with WETH9\\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\\n            IWETH9(WETH9).transfer(recipient, value);\\n        } else if (payer == address(this)) {\\n            // pay with tokens already in the contract (for the exact input multihop case)\\n            TransferHelper.safeTransfer(token, recipient, value);\\n        } else {\\n            // pull payment\\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\\n        }\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '../interfaces/IPeripheryImmutableState.sol';\\n\\n/// @title Immutable state\\n/// @notice Immutable state used by periphery contracts\\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override factory;\\n    /// @inheritdoc IPeripheryImmutableState\\n    address public immutable override WETH9;\\n\\n    constructor(address _factory, address _WETH9) {\\n        factory = _factory;\\n        WETH9 = _WETH9;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\n/// @title Interface for WETH9\\ninterface IWETH9 is IERC20 {\\n    /// @notice Deposit ether to get wrapped ether\\n    function deposit() external payable;\\n\\n    /// @notice Withdraw wrapped ether to get ether\\n    function withdraw(uint256) external;\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\n\\nlibrary TransferHelper {\\n    /// @notice Transfers tokens from the targeted address to the given destination\\n    /// @notice Errors with 'STF' if transfer fails\\n    /// @param token The contract address of the token to be transferred\\n    /// @param from The originating address from which the tokens will be transferred\\n    /// @param to The destination address of the transfer\\n    /// @param value The amount to be transferred\\n    function safeTransferFrom(\\n        address token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) =\\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\\n    }\\n\\n    /// @notice Transfers tokens from msg.sender to a recipient\\n    /// @dev Errors with ST if transfer fails\\n    /// @param token The contract address of the token which will be transferred\\n    /// @param to The recipient of the transfer\\n    /// @param value The value of the transfer\\n    function safeTransfer(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\\n    }\\n\\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\\n    /// @dev Errors with 'SA' if transfer fails\\n    /// @param token The contract address of the token to be approved\\n    /// @param to The target of the approval\\n    /// @param value The amount of the given token the target will be allowed to spend\\n    function safeApprove(\\n        address token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\\n    }\\n\\n    /// @notice Transfers ETH to the recipient address\\n    /// @dev Fails with `STE`\\n    /// @param to The destination of the transfer\\n    /// @param value The value to be transferred\\n    function safeTransferETH(address to, uint256 value) internal {\\n        (bool success, ) = to.call{value: value}(new bytes(0));\\n        require(success, 'STE');\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/lib/ControllerHelperUtil.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../../interfaces/IWETH9.sol\\\";\\nimport {IOracle} from \\\"../../interfaces/IOracle.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./ControllerHelperDataType.sol\\\";\\nimport {LiquidityAmounts} from \\\"./LiquidityAmounts.sol\\\";\\nimport {TickMathExternal} from \\\"../../libs/TickMathExternal.sol\\\";\\n\\nlibrary ControllerHelperUtil {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    /**\\n     * @notice fully or partially close Uni v3 LP\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _params ControllerHelperDataType.CloseUniLpParams struct \\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return withdrawn wPowerPerp and WETH amounts\\n     */\\n    function closeUniLp(address _nonfungiblePositionManager, ControllerHelperDataType.CloseUniLpParams memory _params, bool _isWethToken0) public returns (uint256, uint256) {\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory decreaseParams = INonfungiblePositionManager\\n            .DecreaseLiquidityParams({\\n                tokenId: _params.tokenId,\\n                liquidity: uint128(_params.liquidity.mul(_params.liquidityPercentage).div(1e18)),\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min,\\n                deadline: block.timestamp\\n            });\\n        INonfungiblePositionManager(_nonfungiblePositionManager).decreaseLiquidity(decreaseParams);\\n\\n        uint256 wethAmount;\\n        uint256 _wPowerPerpAmount;\\n        (_isWethToken0)\\n            ? (wethAmount, _wPowerPerpAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n                INonfungiblePositionManager.CollectParams({\\n                    tokenId: _params.tokenId,\\n                    recipient: address(this),\\n                    amount0Max: type(uint128).max,\\n                    amount1Max: type(uint128).max\\n                })\\n            )\\n            : (_wPowerPerpAmount, wethAmount) = INonfungiblePositionManager(_nonfungiblePositionManager).collect(\\n            INonfungiblePositionManager.CollectParams({\\n                tokenId: _params.tokenId,\\n                recipient: address(this),\\n                amount0Max: type(uint128).max,\\n                amount1Max: type(uint128).max\\n            })\\n        );\\n\\n        return (_wPowerPerpAmount, wethAmount);\\n    }\\n\\n    /**\\n     * @notice get exact amount0 and amount1 that will be LPed on Uni v3 pool, based on initial _collateralToLp and _wPowerPerpAmount\\n     * @param _wPowerPerpPool wPowerPerp Uni v3 pool (oSQTH/ETH pool)\\n     * @param _collateralToLp amount of ETH collateral to LP\\n     * @param _wPowerPerpAmount amount of wPowerPerp to LP\\n     * @param _lowerTick LP position lower tick\\n     * @param _upperTick LP position upper tick\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return exact amount0 and amount1 to be LPed\\n     */\\n    function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {\\n        uint256 amount0Desired; \\n        uint256 amount1Desired;\\n\\n        {\\n            (,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();\\n            uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);\\n            uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);\\n            uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);\\n            (amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);\\n            uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);\\n            (amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);\\n        }\\n        \\n        return (amount0Desired, amount1Desired);\\n    }\\n\\n    /**\\n     * @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool\\n     * @param _controller wPowerPerp controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     * @return _vaultId and tokenId\\n     */\\n    function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {\\n        IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);\\n\\n        (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_mintAndLpParams.wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);\\n                \\n        uint256 _vaultId = _mintAndLpParams.vaultId;\\n        uint256 amountToMint = (_isWethToken0) ? amount1Desired : amount0Desired;\\n        if (IWPowerPerp(_wPowerPerp).balanceOf(address(this)) < amountToMint) {\\n            amountToMint = amountToMint.sub(IWPowerPerp(_wPowerPerp).balanceOf(address(this)));\\n            _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(\\n                _mintAndLpParams.vaultId,\\n                amountToMint,\\n                0\\n            );\\n        }\\n        // LP amount0Desired and amount1Desired in Uni v3\\n        uint256 uniTokenId = lpWPowerPerpPool(\\n            _nonfungiblePositionManager,\\n            _mintAndLpParams.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: _mintAndLpParams.recipient,\\n                amount0Desired: amount0Desired,\\n                amount1Desired: amount1Desired,\\n                amount0Min: _mintAndLpParams.amount0Min,\\n                amount1Min: _mintAndLpParams.amount1Min,\\n                lowerTick: _mintAndLpParams.lowerTick,\\n                upperTick: _mintAndLpParams.upperTick\\n            })\\n        );\\n        return (_vaultId, uniTokenId);\\n    }\\n\\n    /**\\n     * @notice increase liquidityin Uni v3 position\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault Id\\n     * @param _increaseLiquidityParam ControllerHelperDataType.IncreaseLpLiquidityParams struct\\n     * @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool\\n     */\\n    function increaseLpLiquidity(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, uint256 _vaultId, ControllerHelperDataType.IncreaseLpLiquidityParams memory _increaseLiquidityParam, bool _isWethToken0) public {\\n        if (_increaseLiquidityParam.wPowerPerpAmountToLp > 0) {\\n            (\\n                ,\\n                ,\\n                ,\\n                ,\\n                ,\\n                int24 tickLower,\\n                int24 tickUpper,\\n                ,\\n                ,\\n                ,\\n                ,\\n                \\n            ) = INonfungiblePositionManager(_nonfungiblePositionManager).positions(_increaseLiquidityParam.tokenId);\\n            (uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _increaseLiquidityParam.wethAmountToLp, _increaseLiquidityParam.wPowerPerpAmountToLp, tickLower, tickUpper, _isWethToken0);\\n\\n            (_increaseLiquidityParam.wPowerPerpAmountToLp, _increaseLiquidityParam.wethAmountToLp) = (_isWethToken0) ? (amount1Desired, amount0Desired) : (amount0Desired, amount1Desired);\\n            uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n\\n            if (wPowerPerpBalance < _increaseLiquidityParam.wPowerPerpAmountToLp) {\\n                IController(_controller).mintWPowerPerpAmount{value: _increaseLiquidityParam.collateralToDeposit}(\\n                    _vaultId,\\n                    _increaseLiquidityParam.wPowerPerpAmountToLp.sub(wPowerPerpBalance),\\n                    0\\n                );\\n            }\\n        }\\n\\n        INonfungiblePositionManager.IncreaseLiquidityParams memory uniIncreaseParams = INonfungiblePositionManager.IncreaseLiquidityParams({\\n            tokenId: _increaseLiquidityParam.tokenId,\\n            amount0Desired: (_isWethToken0) ? _increaseLiquidityParam.wethAmountToLp : _increaseLiquidityParam.wPowerPerpAmountToLp,\\n            amount1Desired: (_isWethToken0) ? _increaseLiquidityParam.wPowerPerpAmountToLp : _increaseLiquidityParam.wethAmountToLp,\\n            amount0Min: _increaseLiquidityParam.amount0Min,\\n            amount1Min: _increaseLiquidityParam.amount1Min,\\n            deadline: block.timestamp\\n        });\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).increaseLiquidity(uniIncreaseParams);\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp in vault\\n     * @param _controller controller address\\n     * @param _weth WETH address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToMint amount of wPowerPerp to mint\\n     * @param _collateralToDeposit amount of collateral to deposit\\n     */\\n    function mintDepositInVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {\\n        if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);\\n\\n        uint256 vaultId = _vaultId;\\n        if (_wPowerPerpToMint > 0) {\\n            vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(\\n                _vaultId,\\n                _wPowerPerpToMint,\\n                0\\n            );\\n        } else {\\n            IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);\\n        }\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp or just withdraw collateral from vault (or both)\\n     * @param _controller controller address\\n     * @param _weth weth address\\n     * @param _vaultId vault Id\\n     * @param _wPowerPerpToBurn amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     */\\n    function burnWithdrawFromVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToBurn, uint256 _collateralToWithdraw) public {\\n        IController(_controller).burnWPowerPerpAmount(\\n            _vaultId,\\n            _wPowerPerpToBurn,\\n            _collateralToWithdraw\\n        );\\n\\n        if (_collateralToWithdraw > 0) IWETH9(_weth).deposit{value: _collateralToWithdraw}();\\n    }\\n\\n    /**\\n     * @notice LP into Uniswap V3 pool\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _wPowerPerpPool wPowerpPerp pool address in Uni v3\\n     * @param _params ControllerHelperDataType.LpWPowerPerpPoolParams struct\\n     */\\n    function lpWPowerPerpPool(\\n        address _nonfungiblePositionManager,\\n        address _wPowerPerpPool,\\n        ControllerHelperDataType.LpWPowerPerpPoolParams memory _params\\n    ) public returns (uint256) {\\n        INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({\\n            token0: IUniswapV3Pool(_wPowerPerpPool).token0(),\\n            token1: IUniswapV3Pool(_wPowerPerpPool).token1(),\\n            fee: IUniswapV3Pool(_wPowerPerpPool).fee(),\\n            tickLower: int24(_params.lowerTick),\\n            tickUpper: int24(_params.upperTick),\\n            amount0Desired: _params.amount0Desired,\\n            amount1Desired: _params.amount1Desired,\\n            amount0Min: _params.amount0Min,\\n            amount1Min: _params.amount1Min,\\n            recipient: _params.recipient,\\n            deadline: block.timestamp\\n        });\\n        (uint256 tokenId, , , ) = INonfungiblePositionManager(_nonfungiblePositionManager).mint(\\n            mintParams\\n        );\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @notice transfer back LP NFT to user if remaining liquidity == 0 and no vault used, or deposit back into vault if still have liquidity\\n     * @param _user user address\\n     * @param _controller controller address\\n     * @param _nonfungiblePositionManager Uni NonFungiblePositionManager address\\n     * @param _vaultId vault ID\\n     * @param _tokenId Uni LP NFT id\\n     * @param _liquidityPercentage percentage of liquidity that was closed from total amount\\n     */\\n    function checkClosedLp(\\n        address _user,\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        uint256 _vaultId,\\n        uint256 _tokenId,\\n        uint256 _liquidityPercentage\\n    ) public {\\n        if ((_vaultId == 0) || (_liquidityPercentage == 1e18)) {\\n            INonfungiblePositionManager(_nonfungiblePositionManager).safeTransferFrom(\\n                address(this),\\n                _user,\\n                _tokenId\\n            );\\n        } else {\\n            IController(_controller).depositUniPositionToken(_vaultId, _tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @notice send ETH and wPowerPerp\\n     * @param _weth WETH address\\n     * @param _wPowerPerp wPowerPerp address\\n     */\\n    function sendBack(address _weth, address _wPowerPerp) public {\\n        IWETH9(_weth).withdraw(IWETH9(_weth).balanceOf(address(this)));\\n        payable(msg.sender).sendValue(address(this).balance);\\n        uint256 wPowerPerpBalance = IWPowerPerp(_wPowerPerp).balanceOf(address(this));\\n        if (wPowerPerpBalance > 0) {\\n            IWPowerPerp(_wPowerPerp).transfer(msg.sender, wPowerPerpBalance);\\n        }\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/ControllerHelperDataType.sol\": {\n      \"content\": \"pragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n//SPDX-License-Identifier: BUSL-1.1\\n\\n// interface\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\nlibrary ControllerHelperDataType {\\n    using SafeMath for uint256;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum CALLBACK_SOURCE {\\n        FLASH_W_MINT,\\n        FLASH_W_BURN,\\n        FLASH_SELL_LONG_W_MINT,\\n        SWAP_EXACTIN_WPOWERPERP_ETH,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP,\\n        SWAP_EXACTOUT_ETH_WPOWERPERP_BURN,\\n        FLASHLOAN_W_MINT_LP_DEPOSIT_NFT,\\n        FLASHLOAN_CLOSE_VAULT_LP_NFT,\\n        FLASHLOAN_REBALANCE_LP_IN_VAULT,\\n        GENERAL_SWAP\\n    }\\n\\n    /// @dev enum to differentiate between rebalanceVaultNft() actions\\n    enum RebalanceVaultNftType {\\n        IncreaseLpLiquidity,\\n        DecreaseLpLiquidity,\\n        DepositIntoVault,\\n        WithdrawFromVault,\\n        MintNewLp,\\n        generalSwap,\\n        CollectFees, \\n        DepositExistingNft\\n    }\\n    \\n    /// @dev params for flashswapWBurnBuyLong()\\n    struct FlashswapWBurnBuyLongParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToBurn; // wPowerPerp amount to burn    \\n        uint256 wPowerPerpAmountToBuy;  // wPowerPerp amount to buy\\n        uint256 collateralToWithdraw;   // collateral to withdraw from vault\\n        uint256 maxToPay;   // max to pay for flashswapping WETH to wPowerPerp\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev params for flashswapSellLongWMint()\\n    struct FlashSellLongWMintParams {\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmountToMint; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;   // collateral amount to deposit into vault\\n        uint256 wPowerPerpAmountToSell; // wPowerPerp amount to sell\\n        uint256 minToReceive;   // minimum to receive for selling wPowerPerpAmountToSell\\n        uint24 poolFee;     // uniswap pool fee\\n    }\\n\\n    /// @dev data struct for callback initiated in _closeShortWithAmountsFromLp()\\n    struct SwapExactoutEthWPowerPerpData {\\n        uint256 vaultId; // vault ID\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault\\n    }\\n\\n    /// @dev params for CloseShortWithUserNft()\\n    struct CloseShortWithUserNftParams {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity;  // liquidity amount in LP \\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToWithdraw; // amount of ETH collateral to withdraw from vault\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;      // uniswap pool fee\\n        bool burnExactRemoved;      // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for wMintLp()\\n    struct MintAndLpParams {\\n        address recipient;  // recipient address\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 vaultId;    // vault ID\\n        uint256 wPowerPerpAmount;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 collateralToLp; // collateral amount to LP\\n        uint256 amount0Min; // minimum amount to LP of asset0\\n        uint256 amount1Min; // minimum amount to LP of asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for flashloanWMintDepositNft()\\n    struct FlashloanWMintLpDepositNftParams {\\n        address wPowerPerpPool; // address on Uni v3 pool to LP in\\n        uint256 vaultId; // vault ID (could be zero)\\n        uint256 wPowerPerpAmount; // wPowerPerp amount to mint\\n        uint256 collateralToDeposit; // ETH collateral amount to deposit in vault (including the flashloaned amount to use as collateral in vault)\\n        uint256 collateralToFlashloan; // ETH amount to flashloan and use for deposit into vault\\n        uint256 collateralToLp; // ETH collateral amount to use for LPing (could be zero)\\n        uint256 collateralToWithdraw; // ETH amount to withdraw from vault (if collateralToLp>0, this should be = collateralToLp+fee or 50% of collateralToLP and sender include the rest in msg.value)\\n        uint256 amount0Min; // minimum amount of token0 to LP\\n        uint256 amount1Min; // minimum amount of token1 to LP\\n        int24 lowerTick; // range lower tick to LP in\\n        int24 upperTick; // range upper tick to LP in\\n    }\\n\\n    /// @dev params for flashloanCloseVaultLpNft()\\n    struct FlashloanCloseVaultLpNftParam {\\n        uint256 vaultId; // vault ID\\n        uint256 tokenId; // Uni NFT token ID\\n        uint256 liquidity; // amount of liquidity in LP position\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint256 wPowerPerpAmountToBurn; // amount of wPowerPerp to burn in vault\\n        uint256 collateralToFlashloan; // amount of ETH collateral to flashloan and deposit into vault\\n        uint256 collateralToWithdraw; // amount of ETH to withdraw\\n        uint256 limitPriceEthPerPowerPerp; // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint24 poolFee;     // uniswap pool fee\\n        bool burnExactRemoved;  // flag to set burning exact amount removed from LP or the current contract balance\\n    }\\n\\n    /// @dev params for _closeUniLp() \\n    struct CloseUniLpParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min of asset0 to get when closing LP position\\n        uint128 amount1Min; // amount min of asset1 to get when closing LP position\\n    }\\n\\n    /// @dev params for sellAll()\\n    struct ReduceLiquidityAndSellParams {\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // minimum amount of token0 to get from closing Uni LP\\n        uint128 amount1Min; // minimum amount of token1 to get from closing Uni LP\\n        uint256 limitPriceEthPerPowerPerp; // price limit for selling wPowerPerp\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for rebalanceLpWithoutVault()\\n    struct RebalanceLpWithoutVaultParams {\\n        address wPowerPerpPool; // Uni v3 ETH/WPowerPerp pool\\n        uint256 tokenId;    // Uni token ID\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 wPowerPerpAmountDesired;    // wPowerPerp amount to LP\\n        uint256 wethAmountDesired;  // WETH amount to LP\\n        uint256 amount0DesiredMin;  // amount min to get when LPing for asset0\\n        uint256 amount1DesiredMin;  // amount min to get when LPing for asset1\\n        uint256 limitPriceEthPerPowerPerp;  // price limit for swapping between wPowerPerp and ETH (ETH per 1 wPowerPerp)\\n        uint256 amount0Min; // amount min to get when closing LP for asset0\\n        uint256 amount1Min; // amount min to get when closing LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n        uint24 poolFee;     // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev params for ControllerHelperUtil.lpWPowerPerpPool()\\n    struct LpWPowerPerpPoolParams {\\n        address recipient;  // recipient address\\n        uint256 amount0Desired; // amount desired to LP for asset0\\n        uint256 amount1Desired; // amount desired to LP for asset1\\n        uint256 amount0Min; // amount min to LP for asset0\\n        uint256 amount1Min; // amount min to LP for asset1\\n        int24 lowerTick;    // LP lower tick\\n        int24 upperTick;    // LP upper tick\\n    }\\n\\n    /// @dev params for rebalanceLpInVault()\\n    struct RebalanceLpInVaultParams {\\n        RebalanceVaultNftType rebalanceLpInVaultType;\\n        bytes data;\\n    }\\n\\n    /// @dev struct for minting more wPowerPerp and add in LP, or increasing more WETH in LP, or both\\n    struct IncreaseLpLiquidityParams {\\n        address wPowerPerpPool;     // Uni v3 pool address to increase liquidity in\\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 wPowerPerpAmountToLp; // wPowerPerp amount to LP\\n        uint256 collateralToDeposit;    // collateral to deposit into vault\\n        uint256 wethAmountToLp; // WETH amount to LP\\n        uint256 amount0Min; // amount min to get for LPing of asset0\\n        uint256 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for decrease liquidity in LP position\\n    struct DecreaseLpLiquidityParams {  \\n        uint256 tokenId;    // Uni v3 NFT token id\\n        uint256 liquidity;  // LP liquidity amount\\n        uint256 liquidityPercentage; // percentage of liquidity to burn in LP position in decimals with 18 precision(e.g 60% = 0.6 = 6e17)\\n        uint128 amount0Min; // amount min to get for LPing of asset0\\n        uint128 amount1Min; // amount min to get for LPing of asset1\\n    }\\n\\n    /// @dev struct for minting into vault\\n    struct DepositIntoVaultParams {\\n        uint256 wPowerPerpToMint;   // wPowerPerp amount to mint\\n        uint256 collateralToDeposit;    // collateral amount to deposit\\n    }\\n\\n    /// @dev struct for withdrawing from vault\\n    struct withdrawFromVaultParams {  \\n        uint256 wPowerPerpToBurn;   // wPowerPerp amount to burn\\n        uint256 collateralToWithdraw;   // collateral to withdraw\\n        bool burnExactRemoved; // if true, will burn the ControllerHelper oSQTH balance, to a maximum of the vault short amount\\n    }\\n\\n    /// @dev struct for swapping from wPowerPerp to weth or weth to wPowerPerp\\n    struct GeneralSwapParams {\\n        address tokenIn; // token to swap in. Must be either weth or wPowerPerp\\n        address tokenOut; // token to swap out. Must be either weth or wPowerPerp\\n        uint256 amountIn; // amount to swap in\\n        uint256 limitPrice; // limit price in units of tokenOut per unit of tokenIn. Notice that this is not always a ETH per wPowerPerp limit price, like is used elsewhere\\n        uint24 poolFee; // Uniswap pool fee (e.g. 3000 = 30bps)\\n    }\\n\\n    /// @dev struct for collecting fees owed from a uniswap NFT\\n    struct CollectFeesParams {\\n        uint256 tokenId;\\n        uint128 amount0Max;\\n        uint128 amount1Max;\\n    }\\n\\n    /// @dev struct for re-depositing and existing uniswap NFT to a vault\\n    struct DepositExistingNftParams {\\n        uint256 tokenId;    // Uni v3 NFT id\\n    }\\n}\"\n    },\n    \"contracts/periphery/lib/LiquidityAmounts.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport '@uniswap/v3-core/contracts/libraries/FullMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';\\nimport {SqrtPriceMathPartial} from \\\"../../libs/SqrtPriceMathPartial.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\n\\n\\n/// @title Liquidity amount functions\\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\\nlibrary LiquidityAmounts {\\n    /// @notice Downcasts uint256 to uint128\\n    /// @param x The uint258 to be downcasted\\n    /// @return y The passed value, downcasted to uint128\\n    function toUint128(uint256 x) private pure returns (uint128 y) {\\n        require((y = uint128(x)) == x);\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\\n    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount0 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount0(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\\n        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\\n    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount1 The amount1 being sent in\\n    /// @return liquidity The amount of returned liquidity\\n    function getLiquidityForAmount1(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\\n    }\\n\\n    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param amount0 The amount of token0 being sent in\\n    /// @param amount1 The amount of token1 being sent in\\n    /// @return liquidity The maximum amount of liquidity received\\n    function getLiquidityForAmounts(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint256 amount0,\\n        uint256 amount1\\n    ) internal pure returns (uint128 liquidity) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\\n            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\\n\\n            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\\n        } else {\\n            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n        }\\n    }\\n\\n    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    function getAmount0ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return\\n            FullMath.mulDiv(\\n                uint256(liquidity) << FixedPoint96.RESOLUTION,\\n                sqrtRatioBX96 - sqrtRatioAX96,\\n                sqrtRatioBX96\\n            ) / sqrtRatioAX96;\\n    }\\n\\n    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount1 The amount of token1\\n    function getAmount1ForLiquidity(\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\\n    }\\n\\n    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\\n    /// pool prices and the prices at the tick boundaries\\n    /// @param sqrtRatioX96 A sqrt price representing the current pool prices\\n    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\\n    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\\n    /// @param liquidity The liquidity being valued\\n    /// @return amount0 The amount of token0\\n    /// @return amount1 The amount of token1\\n    function getAmountsForLiquidity(\\n        uint160 sqrtRatioX96,\\n        uint160 sqrtRatioAX96,\\n        uint160 sqrtRatioBX96,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\\n\\n        if (sqrtRatioX96 <= sqrtRatioAX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        } else if (sqrtRatioX96 < sqrtRatioBX96) {\\n            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\\n        } else {\\n            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\\n        }\\n    }\\n\\n    function getAmountsFromLiquidity(        \\n        uint160 sqrtRatioX96,\\n        int24 currentTick,\\n        int24 tickLower,\\n        int24 tickUpper,\\n        uint128 liquidity\\n    ) internal pure returns (uint256 amount0, uint256 amount1) {\\n        if (currentTick < tickLower) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n        } else if (currentTick < tickUpper) {\\n            amount0 = SqrtPriceMathPartial.getAmount0Delta(\\n                sqrtRatioX96,\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                sqrtRatioX96,\\n                liquidity,\\n                false\\n            );\\n        } else {\\n            amount1 = SqrtPriceMathPartial.getAmount1Delta(\\n                TickMath.getSqrtRatioAtTick(tickLower),\\n                TickMath.getSqrtRatioAtTick(tickUpper),\\n                liquidity,\\n                false\\n            );\\n            }\\n    \\n    }\\n\\n}\\n\"\n    },\n    \"contracts/test/VaultTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/base/LiquidityManagement.sol\\\";\\n\\ncontract VaultLibTester {\\n\\n  function getUniPositionBalances(\\n      address _positionManager,\\n      uint256 _tokenId,\\n      int24 _wPowerPerpPoolTick,\\n      bool _isWethToken0\\n    ) external view returns (uint256 ethAmount, uint256 wPowerPerpAmount) {\\n        return VaultLib._getUniPositionBalances(_positionManager, _tokenId, _wPowerPerpPoolTick, _isWethToken0);\\n    }\\n\\n  /**\\n   * expose this function so it's easier to test vault lib.\\n   */\\n  function getLiquidity(\\n    uint160 sqrtRatioX96,\\n    int24 tickA,\\n    int24 tickB,\\n    uint256 amount0Desired,\\n    uint256 amount1Desired\\n  ) external pure returns (uint128 liquidity) {\\n\\n    uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    liquidity = LiquidityAmounts.getLiquidityForAmounts(\\n        sqrtRatioX96,\\n        sqrtRatioAX96,\\n        sqrtRatioBX96,\\n        amount0Desired,\\n        amount1Desired\\n    );\\n  }\\n\\n  function getLiquidityForAmount0(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount0\\n  ) external pure returns (uint128 liquidity) {\\n\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\\n  }\\n\\n  function getLiquidityForAmount1(\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint256 amount1\\n  ) external pure returns (uint128 liquidity) {\\n    // uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickA);\\n    // uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickB);\\n\\n    return LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\\n  }\\n\\n  function getAmountsForLiquidity(\\n    uint160 sqrtRatioX96,\\n    uint160 sqrtRatioAX96,\\n    uint160 sqrtRatioBX96,\\n    uint128 liquidity\\n  ) external pure returns (uint256 amount0, uint256 amount1) {\\n    return LiquidityAmounts.getAmountsForLiquidity(\\n      sqrtRatioX96,\\n      sqrtRatioAX96,\\n      sqrtRatioBX96,\\n      liquidity\\n    );\\n  }\\n}\"\n    },\n    \"contracts/strategy/base/StrategyBase.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\n\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../../interfaces/IWPowerPerp.sol\\\";\\n\\n// contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./StrategyMath.sol\\\";\\nimport {VaultLib} from \\\"../../libs/VaultLib.sol\\\";\\n\\n/**\\n * @dev StrategyBase contract\\n * @notice base contract for PowerToken strategy\\n * @author opyn team\\n */\\ncontract StrategyBase is ERC20 {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev power token controller\\n    IController public powerTokenController;\\n\\n    /// @dev WETH token\\n    address public immutable weth;\\n    address public immutable wPowerPerp;\\n\\n    /// @dev power token strategy vault ID\\n    uint256 public immutable vaultId;\\n\\n    /**\\n     * @notice constructor for StrategyBase\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _powerTokenController power token controller address\\n     * @param _weth weth token address\\n     * @param _name token name for strategy ERC20 token\\n     * @param _symbol token symbol for strategy ERC20 token\\n     */\\n    constructor(address _powerTokenController, address _weth, string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        require(_powerTokenController != address(0), \\\"invalid controller address\\\");\\n        require(_weth != address(0), \\\"invalid weth address\\\");\\n\\n        weth = _weth;\\n        powerTokenController = IController(_powerTokenController);\\n        wPowerPerp = address(powerTokenController.wPowerPerp());\\n        vaultId = powerTokenController.mintWPowerPerpAmount(0, 0, 0);\\n    }\\n    /**\\n     * @notice get power token strategy vault ID \\n     * @return vault ID\\n     */\\n    function getStrategyVaultId() external view returns (uint256) {\\n        return vaultId;\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n    */\\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256) {\\n        return _getVaultDetails();\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and deposit collateral\\n    * @dev this function will not send WPowerPerp to msg.sender if _keepWSqueeth == true\\n     * @param _to receiver address\\n     * @param _wAmount amount of WPowerPerp to mint\\n     * @param _collateral amount of collateral to deposit\\n     * @param _keepWsqueeth keep minted wSqueeth in this contract if it is set to true\\n     */\\n    function _mintWPowerPerp(\\n        address _to,\\n        uint256 _wAmount,\\n        uint256 _collateral,\\n        bool _keepWsqueeth\\n    ) internal {\\n        powerTokenController.mintWPowerPerpAmount{value: _collateral}(vaultId, _wAmount, 0);\\n\\n        if (!_keepWsqueeth) {\\n            IWPowerPerp(wPowerPerp).transfer(_to, _wAmount);\\n        }\\n    }\\n\\n    /**\\n     * @notice burn WPowerPerp and withdraw collateral\\n     * @dev this function will not take WPowerPerp from msg.sender if _isOwnedWSqueeth == true\\n     * @param _from WPowerPerp holder address\\n     * @param _amount amount of wPowerPerp to burn\\n     * @param _collateralToWithdraw amount of collateral to withdraw\\n     * @param _isOwnedWSqueeth transfer WPowerPerp from holder if it is set to false\\n     */\\n    function _burnWPowerPerp(\\n        address _from,\\n        uint256 _amount,\\n        uint256 _collateralToWithdraw,\\n        bool _isOwnedWSqueeth\\n    ) internal {\\n        if (!_isOwnedWSqueeth) {\\n            IWPowerPerp(wPowerPerp).transferFrom(_from, address(this), _amount);\\n        }\\n\\n        powerTokenController.burnWPowerPerpAmount(vaultId, _amount, _collateralToWithdraw);\\n    }\\n\\n    /**\\n     * @notice mint strategy token\\n     * @param _to recepient address\\n     * @param _amount token amount\\n     */\\n    function _mintStrategyToken(address _to, uint256 _amount) internal {\\n        _mint(_to, _amount);\\n    }\\n\\n    /**\\n     * @notice get strategy debt amount for a specific strategy token amount\\n     * @param _strategyAmount strategy amount\\n     * @return debt amount\\n     */\\n    function _getDebtFromStrategyAmount(uint256 _strategyAmount) internal view returns (uint256) {\\n        (, , ,uint256 strategyDebt) = _getVaultDetails();\\n        return strategyDebt.wmul(_strategyAmount).wdiv(totalSupply());\\n    }\\n\\n    /**\\n     * @notice get the vault composition of the strategy \\n     * @return operator\\n     * @return nft collateral id\\n     * @return collateral amount\\n     * @return short amount\\n     */\\n    function _getVaultDetails() internal view returns (address, uint256, uint256, uint256) {\\n        VaultLib.Vault memory strategyVault = powerTokenController.vaults(vaultId);\\n\\n        return (strategyVault.operator, strategyVault.NftCollateralId, strategyVault.collateralAmount, strategyVault.shortAmount);\\n    }\\n}\\n\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC20/ERC20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 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 {\\n    using SafeMath for uint256;\\n\\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    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three 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        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual 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 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 {_setupDecimals} is\\n     * called.\\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 returns (uint8) {\\n        return _decimals;\\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     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, 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     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), 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     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is 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     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, 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     * - `to` 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 = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(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        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\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 to 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(address from, address to, uint256 amount) internal virtual { }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyMath.sol\": {\n      \"content\": \"//SPDX-License-Identifier: AGPL-3.0-only\\n\\n/// math.sol -- mixin for inline numerical wizardry\\n\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\\n// GNU General Public License for more details.\\n\\n// You should have received a copy of the GNU General Public License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity >0.4.13;\\n\\n\\n/**\\n * @notice Copied from https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol\\n * @dev change contract to library, added div() function\\n */\\nlibrary StrategyMath {\\n    function add(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x + y) >= x, \\\"ds-math-add-overflow\\\");\\n    }\\n    function sub(uint x, uint y) internal pure returns (uint z) {\\n        require((z = x - y) <= x, \\\"ds-math-sub-underflow\\\");\\n    }\\n    function mul(uint x, uint y) internal pure returns (uint z) {\\n        require(y == 0 || (z = x * y) / y == x, \\\"ds-math-mul-overflow\\\");\\n    }\\n\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    function min(uint x, uint y) internal pure returns (uint z) {\\n        return x <= y ? x : y;\\n    }\\n    function max(uint x, uint y) internal pure returns (uint z) {\\n        return x >= y ? x : y;\\n    }\\n    function imin(int x, int y) internal pure returns (int z) {\\n        return x <= y ? x : y;\\n    }\\n    function imax(int x, int y) internal pure returns (int z) {\\n        return x >= y ? x : y;\\n    }\\n\\n    uint constant WAD = 10 ** 18;\\n    uint constant RAY = 10 ** 27;\\n\\n    //rounds to zero if x*y < WAD / 2\\n    function wmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), WAD / 2) / WAD;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function rmul(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, y), RAY / 2) / RAY;\\n    }\\n    //rounds to zero if x*y < WAD / 2\\n    function wdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, WAD), y / 2) / y;\\n    }\\n    //rounds to zero if x*y < RAY / 2\\n    function rdiv(uint x, uint y) internal pure returns (uint z) {\\n        z = add(mul(x, RAY), y / 2) / y;\\n    }\\n\\n    // This famous algorithm is called \\\"exponentiation by squaring\\\"\\n    // and calculates x^n with x as fixed-point and n as regular unsigned.\\n    //\\n    // It's O(log n), instead of O(n) for naive repeated multiplication.\\n    //\\n    // These facts are why it works:\\n    //\\n    //  If n is even, then x^n = (x^2)^(n/2).\\n    //  If n is odd,  then x^n = x * x^(n-1),\\n    //   and applying the equation for even x gives\\n    //    x^n = x * (x^2)^((n-1) / 2).\\n    //\\n    //  Also, EVM division is flooring and\\n    //    floor[(n-1) / 2] = floor[n / 2].\\n    //\\n    function rpow(uint x, uint n) internal pure returns (uint z) {\\n        z = n % 2 != 0 ? x : RAY;\\n\\n        for (n /= 2; n != 0; n /= 2) {\\n            x = rmul(x, x);\\n\\n            if (n % 2 != 0) {\\n                z = rmul(z, x);\\n            }\\n        }\\n    }\\n}\"\n    },\n    \"contracts/strategy/CrabStrategy.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IOracle} from \\\"../interfaces/IOracle.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// contract\\nimport \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {StrategyBase} from \\\"./base/StrategyBase.sol\\\";\\nimport {StrategyFlashSwap} from \\\"./base/StrategyFlashSwap.sol\\\";\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// lib\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n// StrategyMath licensed under AGPL-3.0-only\\nimport {StrategyMath} from \\\"./base/StrategyMath.sol\\\";\\nimport {Power2Base} from \\\"../libs/Power2Base.sol\\\";\\n\\n/**\\n * @dev CrabStrategy contract\\n * @notice Contract for Crab strategy\\n * @author Opyn team\\n */\\ncontract CrabStrategy is StrategyBase, StrategyFlashSwap, ReentrancyGuard, Ownable {\\n    using StrategyMath for uint256;\\n    using Address for address payable;\\n\\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\\n    uint256 public strategyCap;\\n\\n    /// @dev the TWAP_PERIOD used in the PowerPerp Controller contract\\n    uint32 public constant POWER_PERP_PERIOD = 420 seconds;\\n    /// @dev twap period to use for hedge calculations\\n    uint32 public hedgingTwapPeriod = 420 seconds;\\n\\n    /// @dev enum to differentiate between uniswap swap callback function source\\n    enum FLASH_SOURCE {\\n        FLASH_DEPOSIT,\\n        FLASH_WITHDRAW,\\n        FLASH_HEDGE_SELL,\\n        FLASH_HEDGE_BUY\\n    }\\n\\n    /// @dev ETH:WSqueeth uniswap pool\\n    address public immutable ethWSqueethPool;\\n    /// @dev strategy uniswap oracle\\n    address public immutable oracle;\\n    address public immutable ethQuoteCurrencyPool;\\n    address public immutable quoteCurrency;\\n\\n    /// @dev strategy will only allow hedging if collateral to trade is at least a set percentage of the total strategy collateral\\n    uint256 public deltaHedgeThreshold = 1e15;\\n    /// @dev time difference to trigger a hedge (seconds)\\n    uint256 public hedgeTimeThreshold;\\n    /// @dev price movement to trigger a hedge (0.1*1e18 = 10%)\\n    uint256 public hedgePriceThreshold;\\n    /// @dev hedge auction duration (seconds)\\n    uint256 public auctionTime;\\n    /// @dev start auction price multiplier for hedge buy auction and reserve price for hedge sell auction (scaled 1e18)\\n    uint256 public minPriceMultiplier;\\n    /// @dev start auction price multiplier for hedge sell auction and reserve price for hedge buy auction (scaled 1e18)\\n    uint256 public maxPriceMultiplier;\\n\\n    /// @dev timestamp when last hedge executed\\n    uint256 public timeAtLastHedge;\\n    /// @dev WSqueeth/Eth price when last hedge executed\\n    uint256 public priceAtLastHedge;\\n\\n    /// @dev set to true when redeemShortShutdown has been called\\n    bool private hasRedeemedInShutdown;\\n\\n    struct FlashDepositData {\\n        uint256 totalDeposit;\\n    }\\n\\n    struct FlashWithdrawData {\\n        uint256 crabAmount;\\n    }\\n\\n    struct FlashHedgeData {\\n        uint256 wSqueethAmount;\\n        uint256 ethProceeds;\\n        uint256 minWSqueeth;\\n        uint256 minEth;\\n    }\\n\\n    event Deposit(address indexed depositor, uint256 wSqueethAmount, uint256 lpAmount);\\n    event Withdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn);\\n    event WithdrawShutdown(address indexed withdrawer, uint256 crabAmount, uint256 ethWithdrawn);\\n    event FlashDeposit(address indexed depositor, uint256 depositedAmount, uint256 tradedAmountOut);\\n    event FlashWithdraw(address indexed withdrawer, uint256 crabAmount, uint256 wSqueethAmount);\\n    event FlashDepositCallback(address indexed depositor, uint256 flashswapDebt, uint256 excess);\\n    event FlashWithdrawCallback(address indexed withdrawer, uint256 flashswapDebt, uint256 excess);\\n    event TimeHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event PriceHedgeOnUniswap(\\n        address indexed hedger,\\n        uint256 hedgeTimestamp,\\n        uint256 auctionTriggerTimestamp,\\n        uint256 minWSqueeth,\\n        uint256 minEth\\n    );\\n    event TimeHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event PriceHedge(address indexed hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp);\\n    event Hedge(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 hedgerPrice,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event HedgeOnUniswap(\\n        address indexed hedger,\\n        bool auctionType,\\n        uint256 auctionPrice,\\n        uint256 wSqueethHedgeTargetAmount,\\n        uint256 ethHedgetargetAmount\\n    );\\n    event ExecuteSellAuction(address indexed buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap);\\n    event ExecuteBuyAuction(address indexed seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap);\\n    event SetStrategyCap(uint256 newCapAmount);\\n    event SetDeltaHedgeThreshold(uint256 newDeltaHedgeThreshold);\\n    event SetHedgingTwapPeriod(uint32 newHedgingTwapPeriod);\\n    event SetHedgeTimeThreshold(uint256 newHedgeTimeThreshold);\\n    event SetHedgePriceThreshold(uint256 newHedgePriceThreshold);\\n    event SetAuctionTime(uint256 newAuctionTime);\\n    event SetMinPriceMultiplier(uint256 newMinPriceMultiplier);\\n    event SetMaxPriceMultiplier(uint256 newMaxPriceMultiplier);\\n\\n    /**\\n     * @notice strategy constructor\\n     * @dev this will open a vault in the power token contract and store the vault ID\\n     * @param _wSqueethController power token controller address\\n     * @param _oracle oracle address\\n     * @param _weth weth address\\n     * @param _uniswapFactory uniswap factory address\\n     * @param _ethWSqueethPool eth:wSqueeth uniswap pool address\\n     * @param _hedgeTimeThreshold hedge time threshold (seconds)\\n     * @param _hedgePriceThreshold hedge price threshold (0.1*1e18 = 10%)\\n     * @param _auctionTime auction duration (seconds)\\n     * @param _minPriceMultiplier minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\\n     * @param _maxPriceMultiplier maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\\n     */\\n    constructor(\\n        address _wSqueethController,\\n        address _oracle,\\n        address _weth,\\n        address _uniswapFactory,\\n        address _ethWSqueethPool,\\n        uint256 _hedgeTimeThreshold,\\n        uint256 _hedgePriceThreshold,\\n        uint256 _auctionTime,\\n        uint256 _minPriceMultiplier,\\n        uint256 _maxPriceMultiplier\\n    ) StrategyBase(_wSqueethController, _weth, \\\"Crab Strategy\\\", \\\"Crab\\\") StrategyFlashSwap(_uniswapFactory) {\\n        require(_oracle != address(0), \\\"invalid oracle address\\\");\\n        require(_ethWSqueethPool != address(0), \\\"invalid ETH:WSqueeth address\\\");\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n        require(_minPriceMultiplier > 0, \\\"invalid min price multiplier\\\");\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        oracle = _oracle;\\n        ethWSqueethPool = _ethWSqueethPool;\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n        auctionTime = _auctionTime;\\n        minPriceMultiplier = _minPriceMultiplier;\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n        ethQuoteCurrencyPool = IController(_wSqueethController).ethQuoteCurrencyPool();\\n        quoteCurrency = IController(_wSqueethController).quoteCurrency();\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {\\n        require(msg.sender == weth || msg.sender == address(powerTokenController), \\\"Cannot receive eth\\\");\\n    }\\n\\n    /**\\n     * @notice owner can set the strategy cap in ETH collateral terms\\n     * @dev deposits are rejected if it would put the strategy above the cap amount\\n     * @dev strategy collateral can be above the cap amount due to hedging activities\\n     * @param _capAmount the maximum strategy collateral in ETH, checked on deposits\\n     */\\n    function setStrategyCap(uint256 _capAmount) external onlyOwner {\\n        strategyCap = _capAmount;\\n\\n        emit SetStrategyCap(_capAmount);\\n    }\\n\\n    /**\\n     * @notice called to redeem the net value of a vault post shutdown\\n     * @dev needs to be called 1 time before users can exit the strategy using withdrawShutdown\\n     */\\n    function redeemShortShutdown() external {\\n        hasRedeemedInShutdown = true;\\n        powerTokenController.redeemShort(vaultId);\\n    }\\n\\n    /**\\n     * @notice flash deposit into strategy, providing ETH, selling wSqueeth and receiving strategy tokens\\n     * @dev this function will execute a flash swap where it receives ETH, deposits and mints using flash swap proceeds and msg.value, and then repays the flash swap with wSqueeth\\n     * @dev _ethToDeposit must be less than msg.value plus the proceeds from the flash swap\\n     * @dev the difference between _ethToDeposit and msg.value provides the minimum that a user can receive for their sold wSqueeth\\n     * @param _ethToDeposit total ETH that will be deposited in to the strategy which is a combination of msg.value and flash swap proceeds\\n     */\\n    function flashDeposit(uint256 _ethToDeposit) external payable nonReentrant {\\n        (uint256 cachedStrategyDebt, uint256 cachedStrategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_ethToDeposit, cachedStrategyCollateral);\\n\\n        (uint256 wSqueethToMint, ) = _calcWsqueethToMintAndFee(\\n            _ethToDeposit,\\n            cachedStrategyDebt,\\n            cachedStrategyCollateral\\n        );\\n\\n        if (cachedStrategyDebt == 0 && cachedStrategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            wSqueethToMint,\\n            _ethToDeposit.sub(msg.value),\\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT),\\n            abi.encodePacked(_ethToDeposit)\\n        );\\n\\n        emit FlashDeposit(msg.sender, _ethToDeposit, wSqueethToMint);\\n    }\\n\\n    /**\\n     * @notice flash withdraw from strategy, providing strategy tokens, buying wSqueeth, burning and receiving ETH\\n     * @dev this function will execute a flash swap where it receives wSqueeth, burns, withdraws ETH and then repays the flash swap with ETH\\n     * @param _crabAmount strategy token amount to burn\\n     * @param _maxEthToPay maximum ETH to pay to buy back the owed wSqueeth debt\\n     */\\n    function flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay) external nonReentrant {\\n        uint256 exactWSqueethNeeded = _getDebtFromStrategyAmount(_crabAmount);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            IUniswapV3Pool(ethWSqueethPool).fee(),\\n            exactWSqueethNeeded,\\n            _maxEthToPay,\\n            uint8(FLASH_SOURCE.FLASH_WITHDRAW),\\n            abi.encodePacked(_crabAmount)\\n        );\\n\\n        emit FlashWithdraw(msg.sender, _crabAmount, exactWSqueethNeeded);\\n    }\\n\\n    /**\\n     * @notice deposit ETH into strategy\\n     * @dev provide ETH, return wSqueeth and strategy token\\n     */\\n    function deposit() external payable nonReentrant {\\n        uint256 amount = msg.value;\\n\\n        (uint256 wSqueethToMint, uint256 depositorCrabAmount) = _deposit(msg.sender, amount, false);\\n\\n        emit Deposit(msg.sender, wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev provide strategy tokens and wSqueeth, returns eth\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdraw(uint256 _crabAmount) external nonReentrant {\\n        uint256 wSqueethAmount = _getDebtFromStrategyAmount(_crabAmount);\\n        uint256 ethToWithdraw = _withdraw(msg.sender, _crabAmount, wSqueethAmount, false);\\n\\n        // send back ETH collateral\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n\\n        emit Withdraw(msg.sender, _crabAmount, wSqueethAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice called to exit a vault if the Squeeth Power Perp contracts are shutdown\\n     * @param _crabAmount amount of strategy token to burn\\n     */\\n    function withdrawShutdown(uint256 _crabAmount) external nonReentrant {\\n        require(powerTokenController.isShutDown(), \\\"Squeeth contracts not shut down\\\");\\n        require(hasRedeemedInShutdown, \\\"Crab must redeemShortShutdown\\\");\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, address(this).balance);\\n        _burn(msg.sender, _crabAmount);\\n\\n        payable(msg.sender).sendValue(ethToWithdraw);\\n        emit WithdrawShutdown(msg.sender, _crabAmount, ethToWithdraw);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on time threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function timeHedgeOnUniswap(uint256 _minWSqueeth, uint256 _minEth) external {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedgeOnUniswap(auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit TimeHedgeOnUniswap(msg.sender, block.timestamp, auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice hedge startegy based on price threshold with uniswap arbing\\n     * @dev this function atomically hedges on uniswap and provides a bounty to the caller based on the difference\\n     * @dev between uniswap execution price and the price of the hedging auction\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function priceHedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) external payable {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n\\n        _hedgeOnUniswap(_auctionTriggerTime, _minWSqueeth, _minEth);\\n\\n        emit PriceHedgeOnUniswap(msg.sender, block.timestamp, _auctionTriggerTime, _minWSqueeth, _minEth);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on time threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _isStrategySellingWSqueeth sell or buy auction, true for sell auction\\n     * @param _limitPrice hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice) external payable nonReentrant {\\n        (bool isTimeHedgeAllowed, uint256 auctionTriggerTime) = _isTimeHedge();\\n\\n        require(isTimeHedgeAllowed, \\\"Time hedging is not allowed\\\");\\n\\n        _hedge(auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit TimeHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice strategy hedging based on price threshold\\n     * @dev need to attach msg.value if buying WSqueeth\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @param _isStrategySellingWSqueeth specify the direction of the trade that you expect, this choice impacts the limit price chosen\\n     * @param _limitPrice the min or max price that you will trade at, depending on if buying or selling\\n     */\\n    function priceHedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) external payable nonReentrant {\\n        require(_isPriceHedge(_auctionTriggerTime), \\\"Price hedging not allowed\\\");\\n        _hedge(_auctionTriggerTime, _isStrategySellingWSqueeth, _limitPrice);\\n\\n        emit PriceHedge(msg.sender, _isStrategySellingWSqueeth, _limitPrice, _auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime the time when the price deviation threshold was exceeded and when the auction started\\n     * @return true if hedging is allowed\\n     */\\n    function checkPriceHedge(uint256 _auctionTriggerTime) external view returns (bool) {\\n        return _isPriceHedge(_auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return isTimeHedgeAllowed true if hedging is allowed\\n     * @return auctionTriggertime auction trigger timestamp\\n     */\\n    function checkTimeHedge() external view returns (bool, uint256) {\\n        return _isTimeHedge();\\n    }\\n\\n    /**\\n     * @notice get wSqueeth debt amount associated with strategy token amount\\n     * @param _crabAmount strategy token amount\\n     * @return wSqueeth amount\\n     */\\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256) {\\n        return _getDebtFromStrategyAmount(_crabAmount);\\n    }\\n\\n    /**\\n     * @notice owner can set the delta hedge threshold as a percent scaled by 1e18 of ETH collateral\\n     * @dev the strategy will not allow a hedge if the trade size is below this threshold\\n     * @param _deltaHedgeThreshold minimum hedge size in a percent of ETH collateral\\n     */\\n    function setDeltaHedgeThreshold(uint256 _deltaHedgeThreshold) external onlyOwner {\\n        deltaHedgeThreshold = _deltaHedgeThreshold;\\n\\n        emit SetDeltaHedgeThreshold(_deltaHedgeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the twap period in seconds that is used for calculating twaps for hedging\\n     * @param _hedgingTwapPeriod the twap period, in seconds\\n     */\\n    function setHedgingTwapPeriod(uint32 _hedgingTwapPeriod) external onlyOwner {\\n        require(_hedgingTwapPeriod >= 180, \\\"twap period is too short\\\");\\n\\n        hedgingTwapPeriod = _hedgingTwapPeriod;\\n\\n        emit SetHedgingTwapPeriod(_hedgingTwapPeriod);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in seconds that determines how often the strategy can be hedged\\n     * @param _hedgeTimeThreshold the hedge time threshold, in seconds\\n     */\\n    function setHedgeTimeThreshold(uint256 _hedgeTimeThreshold) external onlyOwner {\\n        require(_hedgeTimeThreshold > 0, \\\"invalid hedge time threshold\\\");\\n\\n        hedgeTimeThreshold = _hedgeTimeThreshold;\\n\\n        emit SetHedgeTimeThreshold(_hedgeTimeThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the hedge time threshold in percent, scaled by 1e18 that determines the deviation in wPowerPerp price that can trigger a rebalance\\n     * @param _hedgePriceThreshold the hedge price threshold, in percent, scaled by 1e18\\n     */\\n    function setHedgePriceThreshold(uint256 _hedgePriceThreshold) external onlyOwner {\\n        require(_hedgePriceThreshold > 0, \\\"invalid hedge price threshold\\\");\\n\\n        hedgePriceThreshold = _hedgePriceThreshold;\\n\\n        emit SetHedgePriceThreshold(_hedgePriceThreshold);\\n    }\\n\\n    /**\\n     * @notice owner can set the auction time, in seconds, that a hedge auction runs for\\n     * @param _auctionTime the length of the hedge auction in seconds\\n     */\\n    function setAuctionTime(uint256 _auctionTime) external onlyOwner {\\n        require(_auctionTime > 0, \\\"invalid auction time\\\");\\n\\n        auctionTime = _auctionTime;\\n\\n        emit SetAuctionTime(_auctionTime);\\n    }\\n\\n    /**\\n     * @notice owner can set the min price multiplier in a percentage scaled by 1e18 (9e17 is 90%)\\n     * @dev the min price multiplier is multiplied by the TWAP price to get the intial auction price\\n     * @param _minPriceMultiplier the min price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMinPriceMultiplier(uint256 _minPriceMultiplier) external onlyOwner {\\n        require(_minPriceMultiplier < 1e18, \\\"min price multiplier too high\\\");\\n\\n        minPriceMultiplier = _minPriceMultiplier;\\n\\n        emit SetMinPriceMultiplier(_minPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice owner can set the max price multiplier in a percentage scaled by 1e18 (11e18 is 110%)\\n     * @dev the max price multiplier is multiplied by the TWAP price to get the final auction price\\n     * @param _maxPriceMultiplier the max price multiplier, a percentage, scaled by 1e18\\n     */\\n    function setMaxPriceMultiplier(uint256 _maxPriceMultiplier) external onlyOwner {\\n        require(_maxPriceMultiplier > 1e18, \\\"max price multiplier too low\\\");\\n\\n        maxPriceMultiplier = _maxPriceMultiplier;\\n\\n        emit SetMaxPriceMultiplier(_maxPriceMultiplier);\\n    }\\n\\n    /**\\n     * @notice get current auction details\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return if strategy is selling wSqueeth, wSqueeth amount to auction, ETH proceeds, auction price, if auction direction has switched\\n     */\\n    function getAuctionDetails(uint256 _auctionTriggerTime)\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256,\\n            bool\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n        bool isAuctionDirectionChanged = isSellingAuction != isStillSellingAuction;\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice, isAuctionDirectionChanged);\\n    }\\n\\n    /**\\n     * @notice check if a user deposit puts the strategy above the cap\\n     * @dev reverts if a deposit amount puts strategy over the cap\\n     * @dev it is possible for the strategy to be over the cap from trading/hedging activities, but withdrawals are still allowed\\n     * @param _depositAmount the user deposit amount in ETH\\n     * @param _strategyCollateral the updated strategy collateral\\n     */\\n    function _checkStrategyCap(uint256 _depositAmount, uint256 _strategyCollateral) internal view {\\n        require(_strategyCollateral.add(_depositAmount) <= strategyCap, \\\"Deposit exceeds strategy cap\\\");\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _strategyFlash(\\n        address _caller,\\n        address, /*_tokenIn*/\\n        address, /*_tokenOut*/\\n        uint24, /*_fee*/\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_DEPOSIT) {\\n            FlashDepositData memory data = abi.decode(_callData, (FlashDepositData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n\\n            //use user msg.value and unwrapped WETH from uniswap flash swap proceeds to deposit into strategy\\n            //will revert if data.totalDeposit is > eth balance in contract\\n            _deposit(_caller, data.totalDeposit, true);\\n\\n            //repay the flash swap\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n\\n            emit FlashDepositCallback(_caller, _amountToPay, address(this).balance);\\n\\n            //return excess eth to the user that was not needed for slippage\\n            if (address(this).balance > 0) {\\n                payable(_caller).sendValue(address(this).balance);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_WITHDRAW) {\\n            FlashWithdrawData memory data = abi.decode(_callData, (FlashWithdrawData));\\n\\n            //use flash swap wSqueeth proceeds to withdraw ETH along with user crabAmount\\n            uint256 ethToWithdraw = _withdraw(\\n                _caller,\\n                data.crabAmount,\\n                IWPowerPerp(wPowerPerp).balanceOf(address(this)),\\n                true\\n            );\\n\\n            //use some amount of withdrawn ETH to repay flash swap\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n\\n            //excess ETH not used to repay flash swap is transferred to the user\\n            uint256 proceeds = ethToWithdraw.sub(_amountToPay);\\n\\n            emit FlashWithdrawCallback(_caller, _amountToPay, proceeds);\\n\\n            if (proceeds > 0) {\\n                payable(_caller).sendValue(proceeds);\\n            }\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_SELL) {\\n            //strategy is selling wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            // convert WETH to ETH as Uniswap uses WETH\\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\\n            //mint wSqueeth to pay hedger and repay flash swap, deposit ETH\\n            _executeSellAuction(_caller, data.ethProceeds, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess wSqueeth that the auction would have sold but is not needed to repay flash swap\\n            uint256 wSqueethProfit = data.wSqueethAmount.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(wSqueethProfit >= data.minWSqueeth, \\\"profit is less than min wSqueeth\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWPowerPerp(wPowerPerp).transfer(ethWSqueethPool, _amountToPay);\\n            IWPowerPerp(wPowerPerp).transfer(_caller, wSqueethProfit);\\n        } else if (FLASH_SOURCE(_callSource) == FLASH_SOURCE.FLASH_HEDGE_BUY) {\\n            //strategy is buying wSqueeth for ETH\\n            FlashHedgeData memory data = abi.decode(_callData, (FlashHedgeData));\\n\\n            //withdraw ETH to pay hedger and repay flash swap, burn wSqueeth\\n            _executeBuyAuction(_caller, data.wSqueethAmount, data.ethProceeds, true);\\n\\n            //determine excess ETH that the auction would have paid but is not needed to repay flash swap\\n            uint256 ethProfit = data.ethProceeds.sub(_amountToPay);\\n\\n            //minimum profit check for hedger\\n            require(ethProfit >= data.minEth, \\\"profit is less than min ETH\\\");\\n\\n            //repay flash swap and transfer profit to hedger\\n            IWETH9(weth).deposit{value: _amountToPay}();\\n            IWETH9(weth).transfer(ethWSqueethPool, _amountToPay);\\n            payable(_caller).sendValue(ethProfit);\\n        }\\n    }\\n\\n    /**\\n     * @notice deposit into strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _depositor depositor address\\n     * @param _amount amount of ETH collateral to deposit\\n     * @param _isFlashDeposit true if called by flashDeposit\\n     * @return wSqueethToMint minted amount of WSqueeth\\n     * @return depositorCrabAmount minted CRAB strategy token amount\\n     */\\n    function _deposit(\\n        address _depositor,\\n        uint256 _amount,\\n        bool _isFlashDeposit\\n    ) internal returns (uint256, uint256) {\\n        (uint256 strategyDebt, uint256 strategyCollateral) = _syncStrategyState();\\n        _checkStrategyCap(_amount, strategyCollateral);\\n\\n        (uint256 wSqueethToMint, uint256 ethFee) = _calcWsqueethToMintAndFee(_amount, strategyDebt, strategyCollateral);\\n\\n        uint256 depositorCrabAmount = _calcSharesToMint(_amount.sub(ethFee), strategyCollateral, totalSupply());\\n\\n        if (strategyDebt == 0 && strategyCollateral == 0) {\\n            // store hedge data as strategy is delta neutral at this point\\n            // only execute this upon first deposit\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            timeAtLastHedge = block.timestamp;\\n            priceAtLastHedge = wSqueethEthPrice;\\n        }\\n\\n        // mint wSqueeth and send it to msg.sender\\n        _mintWPowerPerp(_depositor, wSqueethToMint, _amount, _isFlashDeposit);\\n        // mint LP to depositor\\n        _mintStrategyToken(_depositor, depositorCrabAmount);\\n\\n        return (wSqueethToMint, depositorCrabAmount);\\n    }\\n\\n    /**\\n     * @notice withdraw WETH from strategy\\n     * @dev if _isFlashDeposit is true, keeps wSqueeth in contract, otherwise sends to user\\n     * @param _crabAmount amount of strategy token to burn\\n     * @param _wSqueethAmount amount of wSqueeth to burn\\n     * @param _isFlashWithdraw flag if called by flashWithdraw\\n     * @return ETH amount to withdraw\\n     */\\n    function _withdraw(\\n        address _from,\\n        uint256 _crabAmount,\\n        uint256 _wSqueethAmount,\\n        bool _isFlashWithdraw\\n    ) internal returns (uint256) {\\n        (, uint256 strategyCollateral) = _syncStrategyState();\\n\\n        uint256 strategyShare = _calcCrabRatio(_crabAmount, totalSupply());\\n        uint256 ethToWithdraw = _calcEthToWithdraw(strategyShare, strategyCollateral);\\n\\n        _burnWPowerPerp(_from, _wSqueethAmount, ethToWithdraw, _isFlashWithdraw);\\n        _burn(_from, _crabAmount);\\n\\n        return ethToWithdraw;\\n    }\\n\\n    /**\\n     * @notice hedging function to adjust collateral and debt to be eth delta neutral\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _isStrategySellingWSqueeth auction type, true for sell auction\\n     * @param _limitPrice hedger accepted auction price, should be the max price when auction is sell auction, min price when it is a buy auction\\n     */\\n    function _hedge(\\n        uint256 _auctionTriggerTime,\\n        bool _isStrategySellingWSqueeth,\\n        uint256 _limitPrice\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        require(_isStrategySellingWSqueeth == isSellingAuction, \\\"wrong auction type\\\");\\n\\n        if (isSellingAuction) {\\n            // Receiving ETH and paying wSqueeth\\n            require(auctionWSqueethEthPrice <= _limitPrice, \\\"Auction price > max price\\\");\\n            require(msg.value >= ethProceeds, \\\"Low ETH amount received\\\");\\n\\n            _executeSellAuction(msg.sender, msg.value, wSqueethToAuction, ethProceeds, false);\\n        } else {\\n            require(msg.value == 0, \\\"ETH attached for buy auction\\\");\\n            // Receiving wSqueeth and paying ETH\\n            require(auctionWSqueethEthPrice >= _limitPrice, \\\"Auction price < min price\\\");\\n            _executeBuyAuction(msg.sender, wSqueethToAuction, ethProceeds, false);\\n        }\\n\\n        emit Hedge(\\n            msg.sender,\\n            _isStrategySellingWSqueeth,\\n            _limitPrice,\\n            auctionWSqueethEthPrice,\\n            wSqueethToAuction,\\n            ethProceeds\\n        );\\n    }\\n\\n    /**\\n     * @notice execute arb between auction price and uniswap price\\n     * @param _auctionTriggerTime auction starting time\\n     * @param _minWSqueeth minimum WSqueeth amount the caller willing to receive if hedge auction is selling WSqueeth\\n     * @param _minEth minimum ETH amount the caller is willing to receive if hedge auction is buying WSqueeth\\n     */\\n    function _hedgeOnUniswap(\\n        uint256 _auctionTriggerTime,\\n        uint256 _minWSqueeth,\\n        uint256 _minEth\\n    ) internal {\\n        (\\n            bool isSellingAuction,\\n            uint256 wSqueethToAuction,\\n            uint256 ethProceeds,\\n            uint256 auctionWSqueethEthPrice\\n        ) = _startAuction(_auctionTriggerTime);\\n\\n        if (isSellingAuction) {\\n            _exactOutFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                ethProceeds,\\n                wSqueethToAuction,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_SELL),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        } else {\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                IUniswapV3Pool(ethWSqueethPool).fee(),\\n                wSqueethToAuction,\\n                ethProceeds,\\n                uint8(FLASH_SOURCE.FLASH_HEDGE_BUY),\\n                abi.encodePacked(wSqueethToAuction, ethProceeds, _minWSqueeth, _minEth)\\n            );\\n        }\\n\\n        emit HedgeOnUniswap(msg.sender, isSellingAuction, auctionWSqueethEthPrice, wSqueethToAuction, ethProceeds);\\n    }\\n\\n    /**\\n     * @notice execute sell auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, wSqueeth minted is kept to repay flashswap, otherwise sent to seller\\n     * @param _buyer buyer address\\n     * @param _buyerAmount buyer ETH amount sent\\n     * @param _wSqueethToSell wSqueeth amount to sell\\n     * @param _ethToBuy ETH amount to buy\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeSellAuction(\\n        address _buyer,\\n        uint256 _buyerAmount,\\n        uint256 _wSqueethToSell,\\n        uint256 _ethToBuy,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        if (_isHedgingOnUniswap) {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, true);\\n        } else {\\n            _mintWPowerPerp(_buyer, _wSqueethToSell, _ethToBuy, false);\\n\\n            uint256 remainingEth = _buyerAmount.sub(_ethToBuy);\\n\\n            if (remainingEth > 0) {\\n                payable(_buyer).sendValue(remainingEth);\\n            }\\n        }\\n\\n        emit ExecuteSellAuction(_buyer, _wSqueethToSell, _ethToBuy, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice execute buy auction based on the parameters calculated\\n     * @dev if _isHedgingOnUniswap, ETH proceeds are not sent to seller\\n     * @param _seller seller address\\n     * @param _wSqueethToBuy wSqueeth amount to buy\\n     * @param _ethToSell ETH amount to sell\\n     * @param _isHedgingOnUniswap true if arbing with uniswap price\\n     */\\n    function _executeBuyAuction(\\n        address _seller,\\n        uint256 _wSqueethToBuy,\\n        uint256 _ethToSell,\\n        bool _isHedgingOnUniswap\\n    ) internal {\\n        _burnWPowerPerp(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n\\n        if (!_isHedgingOnUniswap) {\\n            payable(_seller).sendValue(_ethToSell);\\n        }\\n\\n        emit ExecuteBuyAuction(_seller, _wSqueethToBuy, _ethToSell, _isHedgingOnUniswap);\\n    }\\n\\n    /**\\n     * @notice determine auction direction, price, and ensure auction hasn't switched directions\\n     * @param _auctionTriggerTime auction starting time\\n     * @return auction type\\n     * @return WSqueeth amount to sell or buy\\n     * @return ETH to sell/buy\\n     * @return auction WSqueeth/ETH price\\n     */\\n    function _startAuction(uint256 _auctionTriggerTime)\\n        internal\\n        returns (\\n            bool,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        (uint256 strategyDebt, uint256 ethDelta) = _syncStrategyState();\\n        uint256 currentWSqueethPrice = IOracle(oracle).getTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            hedgingTwapPeriod,\\n            true\\n        );\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n        (bool isSellingAuction, ) = _checkAuctionType(strategyDebt, ethDelta, currentWSqueethPrice, feeAdjustment);\\n        uint256 auctionWSqueethEthPrice = _getAuctionPrice(_auctionTriggerTime, currentWSqueethPrice, isSellingAuction);\\n        (bool isStillSellingAuction, uint256 wSqueethToAuction) = _checkAuctionType(\\n            strategyDebt,\\n            ethDelta,\\n            auctionWSqueethEthPrice,\\n            feeAdjustment\\n        );\\n\\n        require(isSellingAuction == isStillSellingAuction, \\\"auction direction changed\\\");\\n\\n        uint256 ethProceeds = wSqueethToAuction.wmul(auctionWSqueethEthPrice);\\n\\n        timeAtLastHedge = block.timestamp;\\n        priceAtLastHedge = currentWSqueethPrice;\\n\\n        return (isSellingAuction, wSqueethToAuction, ethProceeds, auctionWSqueethEthPrice);\\n    }\\n\\n    /**\\n     * @notice sync strategy debt and collateral amount from vault\\n     * @return synced debt amount\\n     * @return synced collateral amount\\n     */\\n    function _syncStrategyState() internal view returns (uint256, uint256) {\\n        (, , uint256 syncedStrategyCollateral, uint256 syncedStrategyDebt) = _getVaultDetails();\\n\\n        return (syncedStrategyDebt, syncedStrategyCollateral);\\n    }\\n\\n    /**\\n     * @notice calculate the fee adjustment factor, which is the amount of ETH owed per 1 wSqueeth minted\\n     * @dev the fee is a based off the index value of squeeth and uses a twap scaled down by the PowerPerp's INDEX_SCALE\\n     * @return the fee adjustment factor\\n     */\\n    function _calcFeeAdjustment() internal view returns (uint256) {\\n        uint256 wSqueethEthPrice = Power2Base._getTwap(\\n            oracle,\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            POWER_PERP_PERIOD,\\n            false\\n        );\\n        uint256 feeRate = IController(powerTokenController).feeRate();\\n        return wSqueethEthPrice.mul(feeRate).div(10000);\\n    }\\n\\n    /**\\n     * @notice calculate amount of wSqueeth to mint and fee paid from deposited amount\\n     * @param _depositedAmount amount of deposited WETH\\n     * @param _strategyDebtAmount amount of strategy debt\\n     * @param _strategyCollateralAmount collateral amount in strategy\\n     * @return amount of minted wSqueeth and ETH fee paid on minted squeeth\\n     */\\n    function _calcWsqueethToMintAndFee(\\n        uint256 _depositedAmount,\\n        uint256 _strategyDebtAmount,\\n        uint256 _strategyCollateralAmount\\n    ) internal view returns (uint256, uint256) {\\n        uint256 wSqueethToMint;\\n        uint256 feeAdjustment = _calcFeeAdjustment();\\n\\n        if (_strategyDebtAmount == 0 && _strategyCollateralAmount == 0) {\\n            require(totalSupply() == 0, \\\"Crab contracts shut down\\\");\\n\\n            uint256 wSqueethEthPrice = IOracle(oracle).getTwap(\\n                ethWSqueethPool,\\n                wPowerPerp,\\n                weth,\\n                hedgingTwapPeriod,\\n                true\\n            );\\n            uint256 squeethDelta = wSqueethEthPrice.wmul(2e18);\\n            wSqueethToMint = _depositedAmount.wdiv(squeethDelta.add(feeAdjustment));\\n        } else {\\n            wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\\n            );\\n        }\\n\\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\\n\\n        return (wSqueethToMint, fee);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on time threshold is allowed\\n     * @return true if time hedging is allowed\\n     * @return auction trigger timestamp\\n     */\\n    function _isTimeHedge() internal view returns (bool, uint256) {\\n        uint256 auctionTriggerTime = timeAtLastHedge.add(hedgeTimeThreshold);\\n\\n        return (block.timestamp >= auctionTriggerTime, auctionTriggerTime);\\n    }\\n\\n    /**\\n     * @notice check if hedging based on price threshold is allowed\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @return true if hedging is allowed\\n     */\\n    function _isPriceHedge(uint256 _auctionTriggerTime) internal view returns (bool) {\\n        if (_auctionTriggerTime < timeAtLastHedge) return false;\\n        uint32 secondsToPriceHedgeTrigger = uint32(block.timestamp.sub(_auctionTriggerTime));\\n        uint256 wSqueethEthPriceAtTriggerTime = IOracle(oracle).getHistoricalTwap(\\n            ethWSqueethPool,\\n            wPowerPerp,\\n            weth,\\n            secondsToPriceHedgeTrigger + hedgingTwapPeriod,\\n            secondsToPriceHedgeTrigger\\n        );\\n        uint256 cachedRatio = wSqueethEthPriceAtTriggerTime.wdiv(priceAtLastHedge);\\n        uint256 priceThreshold = cachedRatio > 1e18 ? (cachedRatio).sub(1e18) : uint256(1e18).sub(cachedRatio);\\n\\n        return priceThreshold >= hedgePriceThreshold;\\n    }\\n\\n    /**\\n     * @notice calculate auction price based on auction direction, start time and wSqueeth price\\n     * @param _auctionTriggerTime timestamp where auction started\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _isSellingAuction auction type (true for selling, false for buying auction)\\n     * @return auction price\\n     */\\n    function _getAuctionPrice(\\n        uint256 _auctionTriggerTime,\\n        uint256 _wSqueethEthPrice,\\n        bool _isSellingAuction\\n    ) internal view returns (uint256) {\\n        uint256 auctionCompletionRatio = block.timestamp.sub(_auctionTriggerTime) >= auctionTime\\n            ? 1e18\\n            : (block.timestamp.sub(_auctionTriggerTime)).wdiv(auctionTime);\\n\\n        uint256 priceMultiplier;\\n        if (_isSellingAuction) {\\n            priceMultiplier = maxPriceMultiplier.sub(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        } else {\\n            priceMultiplier = minPriceMultiplier.add(\\n                auctionCompletionRatio.wmul(maxPriceMultiplier.sub(minPriceMultiplier))\\n            );\\n        }\\n\\n        return _wSqueethEthPrice.wmul(priceMultiplier);\\n    }\\n\\n    /**\\n     * @notice check the direction of auction and the target amount of wSqueeth to hedge\\n     * @param _debt strategy debt\\n     * @param _ethDelta ETH delta (amount of ETH in strategy)\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return auction type(sell or buy) and auction initial target hedge in wSqueeth\\n     */\\n    function _checkAuctionType(\\n        uint256 _debt,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal view returns (bool, uint256) {\\n        uint256 wSqueethDelta = _debt.wmul(2e18).wmul(_wSqueethEthPrice);\\n\\n        (uint256 targetHedge, bool isSellingAuction) = _getTargetHedgeAndAuctionType(\\n            wSqueethDelta,\\n            _ethDelta,\\n            _wSqueethEthPrice,\\n            _feeAdjustment\\n        );\\n\\n        require(targetHedge.wmul(_wSqueethEthPrice).wdiv(_ethDelta) > deltaHedgeThreshold, \\\"strategy is delta neutral\\\");\\n\\n        return (isSellingAuction, targetHedge);\\n    }\\n\\n    /**\\n     * @dev calculate amount of strategy token to mint for depositor\\n     * @param _amount amount of ETH deposited\\n     * @param _strategyCollateralAmount amount of strategy collateral\\n     * @param _crabTotalSupply total supply of strategy token\\n     * @return amount of strategy token to mint\\n     */\\n    function _calcSharesToMint(\\n        uint256 _amount,\\n        uint256 _strategyCollateralAmount,\\n        uint256 _crabTotalSupply\\n    ) internal pure returns (uint256) {\\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\\n\\n        if (_crabTotalSupply != 0) return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(1e18).sub(depositorShare));\\n\\n        return _amount;\\n    }\\n\\n    /**\\n     * @notice calculates the ownership proportion for strategy debt and collateral relative to a total amount of strategy tokens\\n     * @param _crabAmount strategy token amount\\n     * @param _totalSupply strategy total supply\\n     * @return ownership proportion of a strategy token amount relative to the total strategy tokens\\n     */\\n    function _calcCrabRatio(uint256 _crabAmount, uint256 _totalSupply) internal pure returns (uint256) {\\n        return _crabAmount.wdiv(_totalSupply);\\n    }\\n\\n    /**\\n     * @notice calculate ETH to withdraw from strategy given a ownership proportion\\n     * @param _crabRatio crab ratio\\n     * @param _strategyCollateralAmount amount of collateral in strategy\\n     * @return amount of ETH allowed to withdraw\\n     */\\n    function _calcEthToWithdraw(uint256 _crabRatio, uint256 _strategyCollateralAmount) internal pure returns (uint256) {\\n        return _strategyCollateralAmount.wmul(_crabRatio);\\n    }\\n\\n    /**\\n     * @notice determine target hedge and auction type (selling/buying auction)\\n     * @dev target hedge is the amount of WSqueeth the auction needs to sell or buy to be eth delta neutral\\n     * @param _wSqueethDelta WSqueeth delta\\n     * @param _ethDelta ETH delta\\n     * @param _wSqueethEthPrice WSqueeth/ETH price\\n     * @param _feeAdjustment the fee adjustment, the amount of ETH owed per wSqueeth minted\\n     * @return target hedge in wSqueeth\\n     * @return auction type: true if auction is selling WSqueeth, false if buying WSqueeth\\n     */\\n    function _getTargetHedgeAndAuctionType(\\n        uint256 _wSqueethDelta,\\n        uint256 _ethDelta,\\n        uint256 _wSqueethEthPrice,\\n        uint256 _feeAdjustment\\n    ) internal pure returns (uint256, bool) {\\n        return\\n            (_wSqueethDelta > _ethDelta)\\n                ? ((_wSqueethDelta.sub(_ethDelta)).wdiv(_wSqueethEthPrice), false)\\n                : ((_ethDelta.sub(_wSqueethDelta)).wdiv(_wSqueethEthPrice.add(_feeAdjustment)), true);\\n    }\\n}\\n\"\n    },\n    \"contracts/strategy/base/StrategyFlashSwap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport '@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/Path.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';\\nimport '@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol';\\nimport '@uniswap/v3-core/contracts/libraries/TickMath.sol';\\nimport '@uniswap/v3-core/contracts/libraries/SafeCast.sol';\\n\\ncontract StrategyFlashSwap is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(\\n        address _factory\\n    ) {\\n        require(_factory != address(0), \\\"invalid factory address\\\");\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashes\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee);\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay =\\n            amount0Delta > 0\\n                ?  uint256(amount0Delta)\\n                :  uint256(amount1Delta);\\n        \\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _strategyFlash(data.caller, tokenIn, tokenOut, fee, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactInFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountIn, uint256 _amountOutMinimum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenIn, _fee, _tokenOut), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n       \\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum, \\\"amount out less than min\\\");\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call \\n     */\\n    function _exactOutFlashSwap(address _tokenIn, address _tokenOut, uint24 _fee, uint256 _amountOut, uint256 _amountInMaximum, uint8 _callSource, bytes memory _data) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({path: abi.encodePacked(_tokenOut, _fee, _tokenIn), caller: msg.sender, callSource: _callSource, callData: _data})\\n        );\\n        \\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum, \\\"amount in greater than max\\\");\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback. \\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call \\n     * param _callSource function call source\\n     */\\n    function _strategyFlash(address /*_caller*/, address /*_tokenIn*/, address /*_tokenOut*/, uint24 /*_fee*/, uint256 /*_amountToPay*/, bytes memory _callData, uint8 _callSource) internal virtual {}\\n    \\n    /** \\n    * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n    * @param _amountIn amount of token to pay\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token bought (amountOut)\\n    */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n       \\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                _amountIn.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n        \\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /** \\n    * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n    * @param _amountOut amount of token to receive\\n    * @param _recipient recipient for receive\\n    * @param _sqrtPriceLimitX96 price limit\\n    * @return amount of token sold (amountIn)\\n    */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n        \\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) =\\n            _getPool(tokenIn, tokenOut, fee).swap(\\n                _recipient,\\n                zeroForOne,\\n                -_amountOut.toInt256(),\\n                _sqrtPriceLimitX96 == 0\\n                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                    : _sqrtPriceLimitX96,\\n                abi.encode(data)\\n            );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /** \\n    * @notice returns the uniswap pool for the given token pair and fee\\n    * @dev the pool contract may or may not exist\\n    * @param tokenA address of first token \\n    * @param tokenB address of second token \\n    * @param fee fee tier for pool\\n    */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) private view returns (IUniswapV3Pool) {\\n        return IUniswapV3Pool(PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee)));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.0;\\n\\n/// @title Optimized overflow and underflow safe math operations\\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\\nlibrary LowGasSafeMath {\\n    /// @notice Returns x + y, reverts if sum overflows uint256\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x + y) >= x);\\n    }\\n\\n    /// @notice Returns x - y, reverts if underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require((z = x - y) <= x);\\n    }\\n\\n    /// @notice Returns x * y, reverts if overflows\\n    /// @param x The multiplicand\\n    /// @param y The multiplier\\n    /// @return z The product of x and y\\n    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        require(x == 0 || (z = x * y) / x == y);\\n    }\\n\\n    /// @notice Returns x + y, reverts if overflows or underflows\\n    /// @param x The augend\\n    /// @param y The addend\\n    /// @return z The sum of x and y\\n    function add(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x + y) >= x == (y >= 0));\\n    }\\n\\n    /// @notice Returns x - y, reverts if overflows or underflows\\n    /// @param x The minuend\\n    /// @param y The subtrahend\\n    /// @return z The difference of x and y\\n    function sub(int256 x, int256 y) internal pure returns (int256 z) {\\n        require((z = x - y) <= x == (y >= 0));\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/Path.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.6.0;\\n\\nimport './BytesLib.sol';\\n\\n/// @title Functions for manipulating path data for multihop swaps\\nlibrary Path {\\n    using BytesLib for bytes;\\n\\n    /// @dev The length of the bytes encoded address\\n    uint256 private constant ADDR_SIZE = 20;\\n    /// @dev The length of the bytes encoded fee\\n    uint256 private constant FEE_SIZE = 3;\\n\\n    /// @dev The offset of a single token address and pool fee\\n    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;\\n    /// @dev The offset of an encoded pool key\\n    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;\\n    /// @dev The minimum length of an encoding that contains 2 or more pools\\n    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;\\n\\n    /// @notice Returns true iff the path contains two or more pools\\n    /// @param path The encoded swap path\\n    /// @return True if path contains two or more pools, otherwise false\\n    function hasMultiplePools(bytes memory path) internal pure returns (bool) {\\n        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;\\n    }\\n\\n    /// @notice Returns the number of pools in the path\\n    /// @param path The encoded swap path\\n    /// @return The number of pools in the path\\n    function numPools(bytes memory path) internal pure returns (uint256) {\\n        // Ignore the first token address. From then on every fee and token offset indicates a pool.\\n        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);\\n    }\\n\\n    /// @notice Decodes the first pool in path\\n    /// @param path The bytes encoded swap path\\n    /// @return tokenA The first token of the given pool\\n    /// @return tokenB The second token of the given pool\\n    /// @return fee The fee level of the pool\\n    function decodeFirstPool(bytes memory path)\\n        internal\\n        pure\\n        returns (\\n            address tokenA,\\n            address tokenB,\\n            uint24 fee\\n        )\\n    {\\n        tokenA = path.toAddress(0);\\n        fee = path.toUint24(ADDR_SIZE);\\n        tokenB = path.toAddress(NEXT_OFFSET);\\n    }\\n\\n    /// @notice Gets the segment corresponding to the first pool in the path\\n    /// @param path The bytes encoded swap path\\n    /// @return The segment containing all data necessary to target the first pool in the path\\n    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(0, POP_OFFSET);\\n    }\\n\\n    /// @notice Skips a token + fee element from the buffer and returns the remainder\\n    /// @param path The swap path\\n    /// @return The remaining token + fee elements in the path\\n    function skipToken(bytes memory path) internal pure returns (bytes memory) {\\n        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/libraries/SafeCast.sol\": {\n      \"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\"\n    },\n    \"@uniswap/v3-periphery/contracts/libraries/BytesLib.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n/*\\n * @title Solidity Bytes Arrays Utils\\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\\n *\\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\\n */\\npragma solidity >=0.5.0 <0.8.0;\\n\\nlibrary BytesLib {\\n    function slice(\\n        bytes memory _bytes,\\n        uint256 _start,\\n        uint256 _length\\n    ) internal pure returns (bytes memory) {\\n        require(_length + 31 >= _length, 'slice_overflow');\\n        require(_start + _length >= _start, 'slice_overflow');\\n        require(_bytes.length >= _start + _length, 'slice_outOfBounds');\\n\\n        bytes memory tempBytes;\\n\\n        assembly {\\n            switch iszero(_length)\\n                case 0 {\\n                    // Get a location of some free memory and store it in tempBytes as\\n                    // Solidity does for memory variables.\\n                    tempBytes := mload(0x40)\\n\\n                    // The first word of the slice result is potentially a partial\\n                    // word read from the original array. To read it, we calculate\\n                    // the length of that partial word and start copying that many\\n                    // bytes into the array. The first word we copy will start with\\n                    // data we don't care about, but the last `lengthmod` bytes will\\n                    // land at the beginning of the contents of the new array. When\\n                    // we're done copying, we overwrite the full first word with\\n                    // the actual length of the slice.\\n                    let lengthmod := and(_length, 31)\\n\\n                    // The multiplication in the next line is necessary\\n                    // because when slicing multiples of 32 bytes (lengthmod == 0)\\n                    // the following copy loop was copying the origin's length\\n                    // and then ending prematurely not copying everything it should.\\n                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n                    let end := add(mc, _length)\\n\\n                    for {\\n                        // The multiplication in the next line has the same exact purpose\\n                        // as the one above.\\n                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n                    } lt(mc, end) {\\n                        mc := add(mc, 0x20)\\n                        cc := add(cc, 0x20)\\n                    } {\\n                        mstore(mc, mload(cc))\\n                    }\\n\\n                    mstore(tempBytes, _length)\\n\\n                    //update free-memory pointer\\n                    //allocating the array padded to 32 bytes like the compiler does now\\n                    mstore(0x40, and(add(mc, 31), not(31)))\\n                }\\n                //if we want a zero-length slice let's just return a zero-length array\\n                default {\\n                    tempBytes := mload(0x40)\\n                    //zero out the 32 bytes slice we are about to return\\n                    //we need to do it because Solidity does not garbage collect\\n                    mstore(tempBytes, 0)\\n\\n                    mstore(0x40, add(tempBytes, 0x20))\\n                }\\n        }\\n\\n        return tempBytes;\\n    }\\n\\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n        require(_start + 20 >= _start, 'toAddress_overflow');\\n        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\\n        address tempAddress;\\n\\n        assembly {\\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n        }\\n\\n        return tempAddress;\\n    }\\n\\n    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {\\n        require(_start + 3 >= _start, 'toUint24_overflow');\\n        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');\\n        uint24 tempUint;\\n\\n        assembly {\\n            tempUint := mload(add(add(_bytes, 0x3), _start))\\n        }\\n\\n        return tempUint;\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/ShortHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n// Interfaces\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {ISwapRouter} from \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n// Libraries\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ReentrancyGuard} from \\\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\\\";\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * @notice contract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\\n */\\ncontract ShortHelper is IERC721Receiver, ReentrancyGuard {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    IController public immutable controller;\\n    ISwapRouter public immutable router;\\n    IWETH9 public immutable weth;\\n    IShortPowerPerp public immutable shortPowerPerp;\\n    address public immutable wPowerPerp;\\n\\n    /**\\n     * @notice constructor for short helper\\n     * @param _controllerAddr controller address for wPowerPerp\\n     * @param _swapRouter uniswap v3 swap router address\\n     * @param _wethAddr weth address\\n     */\\n    constructor(\\n        address _controllerAddr,\\n        address _swapRouter,\\n        address _wethAddr\\n    ) {\\n        require(_controllerAddr != address(0), \\\"Invalid controller address\\\");\\n        require(_swapRouter != address(0), \\\"Invalid swap router address\\\");\\n        require(_wethAddr != address(0), \\\"Invalid weth address\\\");\\n        IController _controller = IController(_controllerAddr);\\n        router = ISwapRouter(_swapRouter);\\n        wPowerPerp = _controller.wPowerPerp();\\n        IWPowerPerp _wPowerPerp = IWPowerPerp(_controller.wPowerPerp());\\n        IWETH9 _weth = IWETH9(_wethAddr);\\n        _wPowerPerp.approve(_swapRouter, type(uint256).max);\\n        _weth.approve(_swapRouter, type(uint256).max);\\n\\n        // assign immutable variables\\n        shortPowerPerp = IShortPowerPerp(_controller.shortPowerPerp());\\n        weth = _weth;\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint power perp, trade with uniswap v3 and send back premium in eth\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _powerPerpAmount amount of powerPerp to mint/sell\\n     * @param _uniNftId uniswap v3 position token id\\n     */\\n    function openShort(\\n        uint256 _vaultId,\\n        uint256 _powerPerpAmount,\\n        uint256 _uniNftId,\\n        ISwapRouter.ExactInputSingleParams memory _exactInputParams\\n    ) external payable nonReentrant {\\n        if (_vaultId != 0) require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactInputParams.tokenOut == address(weth) && _exactInputParams.tokenIn == wPowerPerp,\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        (uint256 vaultId, uint256 wPowerPerpAmount) = controller.mintPowerPerpAmount{value: msg.value}(\\n            _vaultId,\\n            _powerPerpAmount,\\n            _uniNftId\\n        );\\n        _exactInputParams.amountIn = wPowerPerpAmount;\\n\\n        uint256 amountOut = router.exactInputSingle(_exactInputParams);\\n\\n        // if the recipient is this address: unwrap eth and send back to msg.sender\\n        if (_exactInputParams.recipient == address(this)) {\\n            weth.withdraw(amountOut);\\n            payable(msg.sender).sendValue(amountOut);\\n        }\\n\\n        // this is a newly open vault, transfer to the user.\\n        if (_vaultId == 0) shortPowerPerp.safeTransferFrom(address(this), msg.sender, vaultId);\\n    }\\n\\n    /**\\n     * @notice buy back wPowerPerp with eth on uniswap v3 and close position\\n     * @param _vaultId short wPowerPerp vault id\\n     * @param _wPowerPerpAmount amount of wPowerPerp to burn\\n     * @param _withdrawAmount amount to withdraw\\n     */\\n    function closeShort(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _withdrawAmount,\\n        ISwapRouter.ExactOutputSingleParams memory _exactOutputParams\\n    ) external payable nonReentrant {\\n        require(shortPowerPerp.ownerOf(_vaultId) == msg.sender, \\\"Not allowed\\\");\\n        require(\\n            _exactOutputParams.tokenOut == wPowerPerp && _exactOutputParams.tokenIn == address(weth),\\n            \\\"Wrong swap tokens\\\"\\n        );\\n\\n        // wrap eth to weth\\n        weth.deposit{value: msg.value}();\\n\\n        // pay weth and get wPowerPerp in return.\\n        uint256 amountIn = router.exactOutputSingle(_exactOutputParams);\\n\\n        controller.burnWPowerPerpAmount(_vaultId, _wPowerPerpAmount, _withdrawAmount);\\n\\n        // send back unused eth and withdrawn collateral\\n        weth.withdraw(msg.value.sub(amountIn));\\n        // no eth should be left in the contract, so we send it all back\\n        payable(msg.sender).sendValue(address(this).balance);\\n    }\\n\\n    /**\\n     * @dev only receive eth from weth contract and controller.\\n     */\\n    receive() external payable {\\n        require(msg.sender == address(weth) || msg.sender == address(controller), \\\"can't receive eth\\\");\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\\n\\n/// @title Router token swapping functionality\\n/// @notice Functions for swapping tokens via Uniswap V3\\ninterface ISwapRouter is IUniswapV3SwapCallback {\\n    struct ExactInputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactInputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountIn;\\n        uint256 amountOutMinimum;\\n    }\\n\\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\\n    /// @return amountOut The amount of the received token\\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\\n\\n    struct ExactOutputSingleParams {\\n        address tokenIn;\\n        address tokenOut;\\n        uint24 fee;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n        uint160 sqrtPriceLimitX96;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\\n\\n    struct ExactOutputParams {\\n        bytes path;\\n        address recipient;\\n        uint256 deadline;\\n        uint256 amountOut;\\n        uint256 amountInMaximum;\\n    }\\n\\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\\n    /// @return amountIn The amount of the input token\\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/ControllerTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n* use this contract to confirm that funding is not charged twice if called in same block\\n */\\ncontract ControllerTester{\\n\\n  IController controller;\\n\\n  constructor(address _controller) {\\n    controller = IController(_controller);\\n  }\\n\\n  function testDoubleFunding() external {\\n    controller.applyFunding();\\n    uint256 normalizationFactor1 = controller.getExpectedNormalizationFactor();\\n    controller.applyFunding();\\n    uint256 normalizationFactor2 = controller.getExpectedNormalizationFactor();\\n    require(normalizationFactor1==normalizationFactor2, \\\"funding charged twice\\\");\\n  }\\n}\"\n    },\n    \"contracts/periphery/ControllerHelper.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IWETH9} from \\\"../interfaces/IWETH9.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\nimport {IUniswapV3Pool} from \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// contract\\nimport {UniswapControllerHelper} from \\\"./UniswapControllerHelper.sol\\\";\\nimport {EulerControllerHelper} from \\\"./EulerControllerHelper.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {ControllerHelperDataType} from \\\"./lib/ControllerHelperDataType.sol\\\";\\nimport {ControllerHelperUtil} from \\\"./lib/ControllerHelperUtil.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IERC721Receiver {\\n    using SafeMath for uint256;\\n    using Address for address payable;\\n\\n    bool private immutable isWethToken0;\\n    address private immutable controller;\\n    address private immutable shortPowerPerp;\\n    address private immutable wPowerPerp;\\n    address private immutable weth;\\n    address private immutable nonfungiblePositionManager;\\n\\n    constructor(\\n        address _controller,\\n        address _nonfungiblePositionManager,\\n        address _uniswapFactory,\\n        address _exec,\\n        address _euler,\\n        address _dToken\\n    )\\n        UniswapControllerHelper(_uniswapFactory)\\n        EulerControllerHelper(_exec, _euler, IController(_controller).weth(), _dToken)\\n    {\\n        controller = _controller;\\n        shortPowerPerp = IController(_controller).shortPowerPerp();\\n        wPowerPerp = IController(_controller).wPowerPerp();\\n        weth = IController(_controller).weth();\\n        nonfungiblePositionManager = _nonfungiblePositionManager;\\n\\n        isWethToken0 = IController(_controller).weth() < IController(_controller).wPowerPerp();\\n\\n        IWPowerPerp(IController(_controller).wPowerPerp()).approve(_nonfungiblePositionManager, type(uint256).max);\\n        IWETH9(IController(_controller).weth()).approve(_nonfungiblePositionManager, type(uint256).max);\\n\\n        INonfungiblePositionManager(_nonfungiblePositionManager).setApprovalForAll(_controller, true);\\n    }\\n\\n    /**\\n     * @dev accept erc721 from safeTransferFrom and safeMint after callback\\n     * @return returns received selector\\n     */\\n    function onERC721Received(\\n        address,\\n        address,\\n        uint256,\\n        bytes memory\\n    ) public virtual override returns (bytes4) {\\n        return this.onERC721Received.selector;\\n    }\\n\\n    /**\\n     * @notice receive function to allow ETH transfer to this contract\\n     */\\n    receive() external payable {}\\n\\n    /**\\n     * @notice flash close position and buy long squeeth\\n     * @dev this function\\n     * @param _params ControllerHelperDataType.FlashswapWBurnBuyLongParams struct\\n     */\\n    function flashswapWBurnBuyLong(ControllerHelperDataType.FlashswapWBurnBuyLongParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        require(_params.maxToPay <= _params.collateralToWithdraw.add(msg.value));\\n\\n        wrapInternal(msg.value);\\n\\n        _exactOutFlashSwap(\\n            weth,\\n            wPowerPerp,\\n            _params.poolFee,\\n            _params.wPowerPerpAmountToBurn.add(_params.wPowerPerpAmountToBuy),\\n            _params.maxToPay,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell long wPowerPerp and flashswap mint short position\\n     * @dev flashswap amount = collateral amount - msg.value - ETH from selling long wPowerPerp\\n     * @param _params ControllerHelperDataType.FlashSellLongWMintParams struct\\n     */\\n    function flashswapSellLongWMint(ControllerHelperDataType.FlashSellLongWMintParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        IWPowerPerp(wPowerPerp).transferFrom(msg.sender, address(this), _params.wPowerPerpAmountToSell);\\n        // flashswap and mint short position\\n        uint256 totalAmountIn = _params.wPowerPerpAmountToMint.add(_params.wPowerPerpAmountToSell);\\n        _exactInFlashSwap(\\n            wPowerPerp,\\n            weth,\\n            _params.poolFee,\\n            totalAmountIn,\\n            _params.minToReceive,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT),\\n            abi.encode(_params)\\n        );\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice close short position with user Uniswap v3 LP NFT\\n     * @dev user should approve this contract for Uni NFT transfer\\n     * @param _params ControllerHelperDataType.CloseShortWithUserNftParams struct\\n     */\\n    function closeShortWithUserNft(ControllerHelperDataType.CloseShortWithUserNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        wrapInternal(msg.value);\\n\\n        // close LP position\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: _params.amount0Min,\\n                amount1Min: _params.amount1Min\\n            }),\\n            isWethToken0\\n        );\\n\\n        // if LP position is not fully closed, redeposit in vault or send back to user\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n        // burn vault debt using amounts withdrawn from LP position\\n        _closeShortWithAmountsFromLp(\\n            _params.vaultId,\\n            wPowerPerpAmountInLp,\\n            _params.wPowerPerpAmountToBurn,\\n            _params.collateralToWithdraw,\\n            _params.limitPriceEthPerPowerPerp,\\n            _params.poolFee,\\n            _params.burnExactRemoved\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    function flashloanCloseVaultLpNft(ControllerHelperDataType.FlashloanCloseVaultLpNftParam calldata _params)\\n        external\\n        payable\\n    {\\n        _checkAccess(_params.vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice mint WPowerPerp and LP into Uniswap v3 pool\\n     * @param _params ControllerHelperDataType.MintAndLpParams struct\\n     */\\n    function wMintLp(ControllerHelperDataType.MintAndLpParams calldata _params) external payable {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n        require(msg.value == _params.collateralToDeposit.add(_params.collateralToLp));\\n\\n        wrapInternal(msg.value);\\n\\n        (uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(\\n            controller,\\n            nonfungiblePositionManager,\\n            wPowerPerp,\\n            weth,\\n            _params,\\n            isWethToken0\\n        );\\n\\n        // if openeded new vault, transfer vault NFT to user\\n        if (_params.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), msg.sender, vaultId);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice FLash mint short position, LP in Uni v3, use LP NFT as collateral and withdraw ETH collateral to repay flashloan\\n     * @dev sender can specify the amount of ETH collateral to withdraw in case vault.collateralAmount > ETH to repay for loan\\n     * @param _params ControllerHelperDataType.FlashloanWMintLpDepositNftParams struct\\n     */\\n    function flashloanWMintLpDepositNft(ControllerHelperDataType.FlashloanWMintLpDepositNftParams calldata _params)\\n        external\\n        payable\\n    {\\n        if (_params.vaultId != 0) {\\n            _checkAccess(_params.vaultId);\\n        }\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _params.collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT),\\n            abi.encode(_params)\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice sell all LP wPowerPerp amounts to WETH and send back to user\\n     * @param _params ControllerHelperDataType.ReduceLiquidityAndSellParams struct\\n     */\\n    function reduceLiquidityAndSell(ControllerHelperDataType.ReduceLiquidityAndSellParams calldata _params) external {\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: _params.liquidityPercentage,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            _params.liquidityPercentage\\n        );\\n\\n        if (wPowerPerpAmountInLp > 0) {\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpAmountInLp,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountInLp).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance LP nft through trading\\n     * @param _params ControllerHelperDataType.RebalanceLpWithoutVaultParams struct\\n     */\\n    function rebalanceLpWithoutVault(ControllerHelperDataType.RebalanceLpWithoutVaultParams calldata _params)\\n        external\\n        payable\\n    {\\n        wrapInternal(msg.value);\\n        INonfungiblePositionManager(nonfungiblePositionManager).safeTransferFrom(\\n            msg.sender,\\n            address(this),\\n            _params.tokenId\\n        );\\n        // close LP NFT and get Weth and WPowerPerp amounts\\n        (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n            nonfungiblePositionManager,\\n            ControllerHelperDataType.CloseUniLpParams({\\n                tokenId: _params.tokenId,\\n                liquidity: _params.liquidity,\\n                liquidityPercentage: 1e18,\\n                amount0Min: uint128(_params.amount0Min),\\n                amount1Min: uint128(_params.amount1Min)\\n            }),\\n            isWethToken0\\n        );\\n\\n        ControllerHelperUtil.checkClosedLp(\\n            msg.sender,\\n            controller,\\n            nonfungiblePositionManager,\\n            0,\\n            _params.tokenId,\\n            1e18\\n        );\\n\\n        uint256 wethAmountDesired;\\n        uint256 wPowerPerpAmountDesired;\\n\\n        if (isWethToken0) {\\n            (wethAmountDesired, wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        } else {\\n            (wPowerPerpAmountDesired, wethAmountDesired) = ControllerHelperUtil.getAmountsToLp(\\n                _params.wPowerPerpPool,\\n                _params.wethAmountDesired,\\n                _params.wPowerPerpAmountDesired,\\n                _params.lowerTick,\\n                _params.upperTick,\\n                isWethToken0\\n            );\\n        }\\n\\n        if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {\\n            // if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)\\n            _exactOutFlashSwap(\\n                weth,\\n                wPowerPerp,\\n                _params.poolFee,\\n                wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),\\n                \\\"\\\"\\n            );\\n        } else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {\\n            // if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)\\n            uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);\\n            _exactInFlashSwap(\\n                wPowerPerp,\\n                weth,\\n                _params.poolFee,\\n                wPowerPerpExcess,\\n                _params.limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                \\\"\\\"\\n            );\\n        }\\n\\n        // mint new position\\n        ControllerHelperUtil.lpWPowerPerpPool(\\n            nonfungiblePositionManager,\\n            _params.wPowerPerpPool,\\n            ControllerHelperDataType.LpWPowerPerpPoolParams({\\n                recipient: msg.sender,\\n                amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,\\n                amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,\\n                amount0Min: _params.amount0DesiredMin,\\n                amount1Min: _params.amount1DesiredMin,\\n                lowerTick: _params.lowerTick,\\n                upperTick: _params.upperTick\\n            })\\n        );\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice Rebalance, increase and decrease LP liquidity through minting/burning wPowerPerp in vault\\n     * @param _vaultId vault ID\\n     * @param _collateralToFlashloan collateral amount to flashloan and deposit into vault to be able to withdraw Uni LP NFT\\n     * @param _params array of ControllerHelperDataType.RebalanceLpInVaultParams structs\\n     */\\n    function rebalanceLpInVault(\\n        uint256 _vaultId,\\n        uint256 _collateralToFlashloan,\\n        ControllerHelperDataType.RebalanceLpInVaultParams[] calldata _params\\n    ) external payable {\\n        // check ownership\\n        _checkAccess(_vaultId);\\n\\n        wrapInternal(msg.value);\\n        _flashLoan(\\n            weth,\\n            _collateralToFlashloan,\\n            uint8(ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT),\\n            abi.encode(_vaultId, _params)\\n        );\\n\\n        require(INonfungiblePositionManager(nonfungiblePositionManager).balanceOf(address(this)) == 0);\\n\\n        ControllerHelperUtil.sendBack(weth, wPowerPerp);\\n    }\\n\\n    /**\\n     * @notice checks if the msg.sender is the owener of the vault\\n     * @param _vaultId vault ID\\n     */\\n    function _checkAccess(uint256 _vaultId) internal view {\\n        require(IShortPowerPerp(shortPowerPerp).ownerOf(_vaultId) == msg.sender);\\n    }\\n\\n    /**\\n     * @notice gets the shortAmount that has been minted from a vault\\n     * @param _vaultId vault ID\\n     * @return short amount from vault\\n     */\\n\\n    function _getVaultShortAmount(uint256 _vaultId) internal view returns (uint256) {\\n        VaultLib.Vault memory vault = IController(controller).vaults(_vaultId);\\n\\n        return vault.shortAmount;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address, /*_asset*/\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_W_MINT_LP_DEPOSIT_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanWMintLpDepositNftParams memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanWMintLpDepositNftParams)\\n            );\\n\\n            (uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(\\n                controller,\\n                nonfungiblePositionManager,\\n                wPowerPerp,\\n                weth,\\n                ControllerHelperDataType.MintAndLpParams({\\n                    recipient: address(this),\\n                    wPowerPerpPool: data.wPowerPerpPool,\\n                    vaultId: data.vaultId,\\n                    wPowerPerpAmount: data.wPowerPerpAmount,\\n                    collateralToDeposit: data.collateralToDeposit,\\n                    collateralToLp: data.collateralToLp,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min,\\n                    lowerTick: data.lowerTick,\\n                    upperTick: data.upperTick\\n                }),\\n                isWethToken0\\n            );\\n\\n            // deposit Uni NFT token in vault\\n            IController(controller).depositUniPositionToken(vaultId, uniTokenId);\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                vaultId,\\n                0,\\n                _amount.add(data.collateralToWithdraw)\\n            );\\n\\n            // if openeded new vault, transfer vault NFT to user\\n            if (data.vaultId == 0) IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _initiator, vaultId);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_CLOSE_VAULT_LP_NFT\\n        ) {\\n            ControllerHelperDataType.FlashloanCloseVaultLpNftParam memory data = abi.decode(\\n                _calldata,\\n                (ControllerHelperDataType.FlashloanCloseVaultLpNftParam)\\n            );\\n\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(data.vaultId);\\n\\n            IController(controller).withdrawUniPositionToken(data.vaultId);\\n\\n            (uint256 wPowerPerpAmountInLp, ) = ControllerHelperUtil.closeUniLp(\\n                nonfungiblePositionManager,\\n                ControllerHelperDataType.CloseUniLpParams({\\n                    tokenId: data.tokenId,\\n                    liquidity: data.liquidity,\\n                    liquidityPercentage: data.liquidityPercentage,\\n                    amount0Min: data.amount0Min,\\n                    amount1Min: data.amount1Min\\n                }),\\n                isWethToken0\\n            );\\n\\n            ControllerHelperUtil.checkClosedLp(\\n                _initiator,\\n                controller,\\n                nonfungiblePositionManager,\\n                data.vaultId,\\n                data.tokenId,\\n                data.liquidityPercentage\\n            );\\n\\n            // close short position using amounts collected from closing LP, withdraw collateralToWithdraw + deposited collateralToFlashloan\\n            _closeShortWithAmountsFromLp(\\n                data.vaultId,\\n                wPowerPerpAmountInLp,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw.add(data.collateralToFlashloan),\\n                data.limitPriceEthPerPowerPerp,\\n                data.poolFee,\\n                data.burnExactRemoved\\n            );\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASHLOAN_REBALANCE_LP_IN_VAULT\\n        ) {\\n            (uint256 vaultId, ControllerHelperDataType.RebalanceLpInVaultParams[] memory data) = abi.decode(\\n                _calldata,\\n                (uint256, ControllerHelperDataType.RebalanceLpInVaultParams[])\\n            );\\n\\n            // deposit collateral into vault and withdraw LP NFT\\n            IWETH9(weth).withdraw(_amount);\\n            IController(controller).deposit{value: _amount}(vaultId);\\n            IController(controller).withdrawUniPositionToken(vaultId);\\n            for (uint256 i; i < data.length; i++) {\\n                if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.IncreaseLpLiquidity\\n                ) {\\n                    // increase liquidity in LP position, this can mint wPowerPerp and increase\\n                    ControllerHelperDataType.IncreaseLpLiquidityParams memory increaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.IncreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.increaseLpLiquidity(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        increaseLiquidityParam.wPowerPerpPool,\\n                        vaultId,\\n                        increaseLiquidityParam,\\n                        isWethToken0\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, increaseLiquidityParam.tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DecreaseLpLiquidity\\n                ) {\\n                    // decrease liquidity in LP\\n                    ControllerHelperDataType.DecreaseLpLiquidityParams memory decreaseLiquidityParam = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DecreaseLpLiquidityParams)\\n                    );\\n\\n                    ControllerHelperUtil.closeUniLp(\\n                        nonfungiblePositionManager,\\n                        ControllerHelperDataType.CloseUniLpParams({\\n                            tokenId: decreaseLiquidityParam.tokenId,\\n                            liquidity: decreaseLiquidityParam.liquidity,\\n                            liquidityPercentage: decreaseLiquidityParam.liquidityPercentage,\\n                            amount0Min: decreaseLiquidityParam.amount0Min,\\n                            amount1Min: decreaseLiquidityParam.amount1Min\\n                        }),\\n                        isWethToken0\\n                    );\\n\\n                    // if LP position is not fully closed, redeposit into vault or send back to user\\n                    ControllerHelperUtil.checkClosedLp(\\n                        _initiator,\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        vaultId,\\n                        decreaseLiquidityParam.tokenId,\\n                        decreaseLiquidityParam.liquidityPercentage\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault\\n                ) {\\n                    ControllerHelperDataType.DepositIntoVaultParams memory depositIntoVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositIntoVaultParams)\\n                    );\\n\\n                    // make sure not to fail\\n                    // a user can ensure that the entire weth balance is deposited by using a sufficiently large depositIntoVaultParams.collateralToDeposit\\n                    uint256 currentBalance = IWETH9(weth).balanceOf(address(this));\\n                    if (currentBalance < depositIntoVaultParams.collateralToDeposit)\\n                        depositIntoVaultParams.collateralToDeposit = currentBalance;\\n\\n                    ControllerHelperUtil.mintDepositInVault(\\n                        controller,\\n                        weth,\\n                        vaultId,\\n                        depositIntoVaultParams.wPowerPerpToMint,\\n                        depositIntoVaultParams.collateralToDeposit\\n                    );\\n                } else if (\\n                    // this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.WithdrawFromVault\\n                ) {\\n                    ControllerHelperDataType.withdrawFromVaultParams memory withdrawFromVaultParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.withdrawFromVaultParams)\\n                    );\\n\\n                    uint256 currentBalance = IWPowerPerp(wPowerPerp).balanceOf(address(this));\\n\\n                    if (withdrawFromVaultParams.burnExactRemoved) {\\n                        uint256 shortAmount = _getVaultShortAmount(vaultId);\\n                        if (shortAmount < currentBalance) currentBalance = shortAmount;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            currentBalance,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    } else {\\n                        if (currentBalance < withdrawFromVaultParams.wPowerPerpToBurn)\\n                            withdrawFromVaultParams.wPowerPerpToBurn = currentBalance;\\n                        ControllerHelperUtil.burnWithdrawFromVault(\\n                            controller,\\n                            weth,\\n                            vaultId,\\n                            withdrawFromVaultParams.wPowerPerpToBurn,\\n                            withdrawFromVaultParams.collateralToWithdraw\\n                        );\\n                    }\\n                } else if (data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {\\n                    // this will execute in the use case of fully closing old LP position, and creating new one\\n                    ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.MintAndLpParams)\\n                    );\\n\\n                    uint256 tokenId;\\n                    (vaultId, tokenId) = ControllerHelperUtil.mintAndLp(\\n                        controller,\\n                        nonfungiblePositionManager,\\n                        wPowerPerp,\\n                        weth,\\n                        mintAndLpParams,\\n                        isWethToken0\\n                    );\\n                    // deposit Uni NFT token in vault\\n                    IController(controller).depositUniPositionToken(vaultId, tokenId);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.generalSwap\\n                ) {\\n                    ControllerHelperDataType.GeneralSwapParams memory swapParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.GeneralSwapParams)\\n                    );\\n\\n                    require(\\n                        (swapParams.tokenIn == weth && swapParams.tokenOut == wPowerPerp) ||\\n                            (swapParams.tokenIn == wPowerPerp && swapParams.tokenOut == weth)\\n                    );\\n\\n                    _exactInFlashSwap(\\n                        swapParams.tokenIn,\\n                        swapParams.tokenOut,\\n                        swapParams.poolFee,\\n                        swapParams.amountIn,\\n                        swapParams.limitPrice.mul(swapParams.amountIn).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP),\\n                        \\\"\\\"\\n                    );\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.CollectFees\\n                ) {\\n                    ControllerHelperDataType.CollectFeesParams memory collectFeesParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.CollectFeesParams)\\n                    );\\n\\n                    INonfungiblePositionManager.CollectParams memory collectParams = INonfungiblePositionManager\\n                        .CollectParams({\\n                            tokenId: collectFeesParams.tokenId,\\n                            recipient: address(this),\\n                            amount0Max: collectFeesParams.amount0Max,\\n                            amount1Max: collectFeesParams.amount0Max\\n                        });\\n\\n                    INonfungiblePositionManager(nonfungiblePositionManager).collect(collectParams);\\n                } else if (\\n                    data[i].rebalanceLpInVaultType == ControllerHelperDataType.RebalanceVaultNftType.DepositExistingNft\\n                ) {\\n                    ControllerHelperDataType.DepositExistingNftParams memory depositExistingNftParams = abi.decode(\\n                        data[i].data,\\n                        (ControllerHelperDataType.DepositExistingNftParams)\\n                    );\\n\\n                    IController(controller).depositUniPositionToken(vaultId, depositExistingNftParams.tokenId);\\n                }\\n            }\\n\\n            // remove flashloan amount in ETH from vault + any amount of collateral user want to withdraw (sum <= vault.collateralAmount)\\n            ControllerHelperUtil.burnWithdrawFromVault(controller, weth, vaultId, 0, _amount);\\n        }\\n    }\\n\\n    /**\\n     * @notice uniswap flash swap callback function\\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\\n     * @param _caller address of original function caller\\n     * @param _amountToPay amount to pay back for flashswap\\n     * @param _callData arbitrary data attached to callback\\n     * @param _callSource identifier for which function triggered callback\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal override {\\n        if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_W_BURN\\n        ) {\\n            ControllerHelperDataType.FlashswapWBurnBuyLongParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashswapWBurnBuyLongParams)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.FLASH_SELL_LONG_W_MINT\\n        ) {\\n            ControllerHelperDataType.FlashSellLongWMintParams memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.FlashSellLongWMintParams)\\n            );\\n\\n            if (data.wPowerPerpAmountToMint > 0 || data.collateralToDeposit > 0) {\\n                uint256 vaultId = ControllerHelperUtil.mintDepositInVault(\\n                    controller,\\n                    weth,\\n                    data.vaultId,\\n                    data.wPowerPerpAmountToMint,\\n                    data.collateralToDeposit\\n                );\\n\\n                // this is a newly open vault, transfer to the user\\n                if (data.vaultId == 0)\\n                    IShortPowerPerp(shortPowerPerp).safeTransferFrom(address(this), _caller, vaultId);\\n            }\\n\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH\\n        ) {\\n            IWPowerPerp(wPowerPerp).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP\\n        ) {\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN\\n        ) {\\n            ControllerHelperDataType.SwapExactoutEthWPowerPerpData memory data = abi.decode(\\n                _callData,\\n                (ControllerHelperDataType.SwapExactoutEthWPowerPerpData)\\n            );\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                data.vaultId,\\n                data.wPowerPerpAmountToBurn,\\n                data.collateralToWithdraw\\n            );\\n\\n            IWETH9(weth).transfer(_pool, _amountToPay);\\n        } else if (\\n            ControllerHelperDataType.CALLBACK_SOURCE(_callSource) ==\\n            ControllerHelperDataType.CALLBACK_SOURCE.GENERAL_SWAP\\n        ) {\\n            IERC20(_tokenIn).transfer(_pool, _amountToPay);\\n        }\\n    }\\n\\n    /**\\n     * @notice wrap ETH to WETH\\n     * @param _amount amount to wrap\\n     */\\n    function wrapInternal(uint256 _amount) internal {\\n        if (_amount > 0) IWETH9(weth).deposit{value: _amount}();\\n    }\\n\\n    function _closeShortWithAmountsFromLp(\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount,\\n        uint256 _wPowerPerpAmountToBurn,\\n        uint256 _collateralToWithdraw,\\n        uint256 _limitPriceEthPerPowerPerp,\\n        uint24 _poolFee,\\n        bool burnExactRemoved\\n    ) private {\\n        if (burnExactRemoved) {\\n            // remove exact _wPowerPerpAmount amount withdrawn from LP, unless amount is > short amount in vault\\n            uint256 shortAmount = _getVaultShortAmount(_vaultId);\\n            if (shortAmount < _wPowerPerpAmount) _wPowerPerpAmount = shortAmount;\\n\\n            ControllerHelperUtil.burnWithdrawFromVault(\\n                controller,\\n                weth,\\n                _vaultId,\\n                _wPowerPerpAmount,\\n                _collateralToWithdraw\\n            );\\n        } else {\\n            if (_wPowerPerpAmount < _wPowerPerpAmountToBurn) {\\n                // swap needed wPowerPerp amount to close short position\\n                uint256 wPowerPerpDeficit = _wPowerPerpAmountToBurn.sub(_wPowerPerpAmount);\\n\\n                _exactOutFlashSwap(\\n                    weth,\\n                    wPowerPerp,\\n                    _poolFee,\\n                    wPowerPerpDeficit,\\n                    _limitPriceEthPerPowerPerp.mul(wPowerPerpDeficit).div(1e18),\\n                    uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP_BURN),\\n                    abi.encodePacked(_vaultId, _wPowerPerpAmountToBurn, _collateralToWithdraw)\\n                );\\n            } else {\\n                // if LP have more wPowerPerp amount that amount to burn in vault, sell remaining amount for WETH\\n                ControllerHelperUtil.burnWithdrawFromVault(\\n                    controller,\\n                    weth,\\n                    _vaultId,\\n                    _wPowerPerpAmountToBurn,\\n                    _collateralToWithdraw\\n                );\\n\\n                uint256 wPowerPerpExcess = _wPowerPerpAmount.sub(_wPowerPerpAmountToBurn);\\n                if (wPowerPerpExcess > 0) {\\n                    _exactInFlashSwap(\\n                        wPowerPerp,\\n                        weth,\\n                        _poolFee,\\n                        wPowerPerpExcess,\\n                        _limitPriceEthPerPowerPerp.mul(wPowerPerpExcess).div(1e18),\\n                        uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTIN_WPOWERPERP_ETH),\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        // wrap ETH to WETH\\n        wrapInternal(address(this).balance);\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/UniswapControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\n\\n// lib\\nimport \\\"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/Path.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/TickMath.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/libraries/SafeCast.sol\\\";\\n\\ncontract UniswapControllerHelper is IUniswapV3SwapCallback {\\n    using Path for bytes;\\n    using SafeCast for uint256;\\n    using LowGasSafeMath for uint256;\\n    using LowGasSafeMath for int256;\\n\\n    /// @dev Uniswap factory address\\n    address public immutable factory;\\n\\n    struct SwapCallbackData {\\n        bytes path;\\n        address caller;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    /**\\n     * @dev constructor\\n     * @param _factory uniswap factory address\\n     */\\n    constructor(address _factory) {\\n        require(_factory != address(0));\\n        factory = _factory;\\n    }\\n\\n    /**\\n     * @notice uniswap swap callback function for flashswap\\n     * @param amount0Delta amount of token0\\n     * @param amount1Delta amount of token1\\n     * @param _data callback data encoded as SwapCallbackData struct\\n     */\\n    function uniswapV3SwapCallback(\\n        int256 amount0Delta,\\n        int256 amount1Delta,\\n        bytes calldata _data\\n    ) external override {\\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\\n\\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //ensure that callback comes from uniswap pool\\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\\n\\n        //determine the amount that needs to be repaid as part of the flashswap\\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\\n\\n        //calls the function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\\n        _swapCallback(data.caller, tokenIn, pool, amountToPay, data.callData, data.callSource);\\n    }\\n\\n    /**\\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountIn amount to sell\\n     * @param _amountOutMinimum minimum amount to receive\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactInFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountIn,\\n        uint256 _amountOutMinimum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal returns (uint256) {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountOut = _exactInputInternal(\\n            _amountIn,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountOut >= _amountOutMinimum);\\n\\n        return amountOut;\\n    }\\n\\n    /**\\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\\n     * @param _tokenIn token address to sell\\n     * @param _tokenOut token address to receive\\n     * @param _fee pool fee\\n     * @param _amountOut exact amount to receive\\n     * @param _amountInMaximum maximum amount to sell\\n     * @param _callSource function call source\\n     * @param _data arbitrary data assigned with the call\\n     */\\n    function _exactOutFlashSwap(\\n        address _tokenIn,\\n        address _tokenOut,\\n        uint24 _fee,\\n        uint256 _amountOut,\\n        uint256 _amountInMaximum,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\\n        uint256 amountIn = _exactOutputInternal(\\n            _amountOut,\\n            address(this),\\n            uint160(0),\\n            SwapCallbackData({\\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\\n                caller: msg.sender,\\n                callSource: _callSource,\\n                callData: _data\\n            })\\n        );\\n\\n        //slippage limit check\\n        require(amountIn <= _amountInMaximum);\\n    }\\n\\n    /**\\n     * @notice function to be called by uniswap callback.\\n     * @dev this function should be overridden by the child contract\\n     * param _caller initial strategy function caller\\n     * param _tokenIn token address sold\\n     * param _tokenOut token address bought\\n     * param _fee pool fee\\n     * param _amountToPay amount to pay for the pool second token\\n     * param _callData arbitrary data assigned with the flashswap call\\n     * param _callSource function call source\\n     */\\n    function _swapCallback(\\n        address _caller,\\n        address _tokenIn,\\n        address _pool,\\n        uint256 _amountToPay,\\n        bytes memory _callData,\\n        uint8 _callSource\\n    ) internal virtual {}\\n\\n    /**\\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\\n     * @param _amountIn amount of token to pay\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token bought (amountOut)\\n     */\\n    function _exactInputInternal(\\n        uint256 _amountIn,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0, int256 amount1) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            _amountIn.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountOut based on which token has a lower address\\n        return uint256(-(zeroForOne ? amount1 : amount0));\\n    }\\n\\n    /**\\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\\n     * @param _amountOut amount of token to receive\\n     * @param _recipient recipient for receive\\n     * @param _sqrtPriceLimitX96 price limit\\n     * @return amount of token sold (amountIn)\\n     */\\n    function _exactOutputInternal(\\n        uint256 _amountOut,\\n        address _recipient,\\n        uint160 _sqrtPriceLimitX96,\\n        SwapCallbackData memory data\\n    ) private returns (uint256) {\\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\\n\\n        //uniswap token0 has a lower address than token1\\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\\n        //zeroForOne determines which token is being sold and which is being bought\\n        bool zeroForOne = tokenIn < tokenOut;\\n\\n        //swap on uniswap, including data to trigger call back for flashswap\\n        (int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(_getPool(tokenIn, tokenOut, fee)).swap(\\n            _recipient,\\n            zeroForOne,\\n            -_amountOut.toInt256(),\\n            _sqrtPriceLimitX96 == 0\\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\\n                : _sqrtPriceLimitX96,\\n            abi.encode(data)\\n        );\\n\\n        //determine the amountIn and amountOut based on which token has a lower address\\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\\n            : (uint256(amount1Delta), uint256(-amount0Delta));\\n        // it's technically possible to not receive the full output amount,\\n        // so if no price limit has been specified, require this possibility away\\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\\n\\n        return amountIn;\\n    }\\n\\n    /**\\n     * @notice returns the uniswap pool for the given token pair and fee\\n     * @dev the pool contract may or may not exist\\n     * @param tokenA address of first token\\n     * @param tokenB address of second token\\n     * @param fee fee tier for pool\\n     */\\n    function _getPool(\\n        address tokenA,\\n        address tokenB,\\n        uint24 fee\\n    ) internal view returns (address) {\\n        return PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\\n    }\\n}\\n\"\n    },\n    \"contracts/periphery/EulerControllerHelper.sol\": {\n      \"content\": \"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\n// interface\\nimport {IERC20Detailed} from \\\"../interfaces/IERC20Detailed.sol\\\";\\n\\n// lib\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/// @notice Definition of callback method that deferLiquidityCheck will invoke on your contract\\ninterface IDeferredLiquidityCheck {\\n    function onDeferredLiquidityCheck(bytes memory data) external;\\n}\\n\\ninterface IExec {\\n    function deferLiquidityCheck(address account, bytes memory data) external;\\n}\\n\\ninterface IEulerDToken {\\n    function borrow(uint256 subAccountId, uint256 amount) external;\\n\\n    function repay(uint256 subAccountId, uint256 amount) external;\\n}\\n\\ncontract EulerControllerHelper is IDeferredLiquidityCheck {\\n    using SafeMath for uint256;\\n\\n    address public immutable exec;\\n    address public immutable euler;\\n    address public immutable token;\\n    address public immutable dToken;\\n\\n    struct FlashloanCallbackData {\\n        address caller;\\n        address assetToBorrow;\\n        uint256 amountToBorrow;\\n        uint8 callSource;\\n        bytes callData;\\n    }\\n\\n    constructor(\\n        address _exec,\\n        address _euler,\\n        address _token,\\n        address _dToken\\n    ) {\\n        exec = _exec;\\n        euler = _euler;\\n        token = _token;\\n        dToken = _dToken;\\n    }\\n\\n    function _flashCallback(\\n        address _initiator,\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _calldata\\n    ) internal virtual {}\\n\\n    function onDeferredLiquidityCheck(bytes memory encodedData) external override {\\n        // sanity checks\\n        require(msg.sender == euler);\\n\\n        FlashloanCallbackData memory data = abi.decode(encodedData, (FlashloanCallbackData));\\n\\n        IEulerDToken(dToken).borrow(0, data.amountToBorrow);\\n\\n        _flashCallback(data.caller, data.assetToBorrow, data.amountToBorrow, data.callSource, data.callData);\\n\\n        IERC20Detailed(data.assetToBorrow).approve(euler, data.amountToBorrow);\\n        IEulerDToken(dToken).repay(0, data.amountToBorrow);\\n    }\\n\\n    /**\\n     */\\n    function _flashLoan(\\n        address _asset,\\n        uint256 _amount,\\n        uint8 _callSource,\\n        bytes memory _data\\n    ) internal {\\n        // Disable the liquidity check for \\\"this\\\" and call-back into onDeferredLiquidityCheck:\\n        IExec(exec).deferLiquidityCheck(\\n            address(this),\\n            abi.encode(\\n                FlashloanCallbackData({\\n                    caller: msg.sender,\\n                    assetToBorrow: _asset,\\n                    amountToBorrow: _amount,\\n                    callSource: _callSource,\\n                    callData: _data\\n                })\\n            )\\n        );\\n    }\\n}\\n\"\n    },\n    \"@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Callback for IUniswapV3PoolActions#flash\\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\\ninterface IUniswapV3FlashCallback {\\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniPositionManager.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {INonfungiblePositionManager} from \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\n\\ncontract MockUniPositionManager is ERC721 {\\n    int24 public tickLower;\\n    int24 public tickUpper;\\n    uint128 public liquidity;\\n    address public token0;\\n    address public token1;\\n\\n    uint256 token0ToCollect;\\n    uint256 token1ToCollect;\\n\\n    constructor() ERC721(\\\"Uniswap Position\\\", \\\"UNIP\\\") {}\\n\\n    function mint(address account, uint256 tokenId) external {\\n        _mint(account, tokenId);\\n    }\\n\\n    function setMockedProperties(\\n        address _token0,\\n        address _token1,\\n        int24 _tickLower,\\n        int24 _tickUpper,\\n        uint128 _liquidity\\n    ) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n        tickLower = _tickLower;\\n        tickUpper = _tickUpper;\\n        liquidity = _liquidity;\\n    }\\n\\n    function positions(uint256)\\n        public\\n        view\\n        returns (\\n            uint96, //nonce,\\n            address, //operator,\\n            address, //token0,\\n            address, //token1,\\n            uint24, // fee,\\n            int24, // tickLower,\\n            int24, // tickUpper,\\n            uint128, // liquidity,\\n            uint256, //feeGrowthInside0LastX128,\\n            uint256, //feeGrowthInside1LastX128,\\n            uint128, //tokensOwed0,\\n            uint128 //tokensOwed1\\n        )\\n    {\\n        // return 0 for everything\\n        return (\\n            0, //nonce,\\n            address(0), //operator,\\n            token0, //token0,\\n            token1, //token1,\\n            3000, // fee,\\n            tickLower, // tickLower,\\n            tickUpper, // tickUpper,\\n            liquidity, // liquidity,\\n            0, //feeGrowthInside0LastX128,\\n            0, //feeGrowthInside1LastX128,\\n            0, //tokensOwed0,\\n            0 //tokensOwed1\\n        );\\n    }\\n\\n    function setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1) external {\\n        token0ToCollect = amount0;\\n        token1ToCollect = amount1;\\n    }\\n\\n    // SPDX-License-Identifier: GPL-2.0-or-later\\n    function decreaseLiquidity(\\n        INonfungiblePositionManager.DecreaseLiquidityParams memory /*params*/\\n    ) external view returns (uint256, uint256) {\\n        return (token0ToCollect, token1ToCollect);\\n    }\\n\\n    function collect(INonfungiblePositionManager.CollectParams memory params) external returns (uint256, uint256) {\\n        uint256 cachedAmount0 = token0ToCollect;\\n        uint256 cachedAmount1 = token1ToCollect;\\n        uint256 token0Amount = cachedAmount0 > params.amount0Max ? params.amount0Max : cachedAmount0;\\n        uint256 token1Amount = cachedAmount1 > params.amount1Max ? params.amount1Max : cachedAmount1;\\n        IERC20(token0).transfer(params.recipient, token0Amount);\\n        IERC20(token1).transfer(params.recipient, token1Amount);\\n        token0ToCollect = 0;\\n        token1ToCollect = 0;\\n        return (token0Amount, token1Amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/token/ERC721/ERC721.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Metadata.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"../../introspection/ERC165.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/EnumerableSet.sol\\\";\\nimport \\\"../../utils/EnumerableMap.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\n\\n/**\\n * @title ERC721 Non-Fungible Token Standard basic implementation\\n * @dev see https://eips.ethereum.org/EIPS/eip-721\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {\\n    using SafeMath for uint256;\\n    using Address for address;\\n    using EnumerableSet for EnumerableSet.UintSet;\\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\\n    using Strings for uint256;\\n\\n    // Equals to `bytes4(keccak256(\\\"onERC721Received(address,address,uint256,bytes)\\\"))`\\n    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`\\n    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;\\n\\n    // Mapping from holder address to their (enumerable) set of owned tokens\\n    mapping (address => EnumerableSet.UintSet) private _holderTokens;\\n\\n    // Enumerable mapping from token ids to their owners\\n    EnumerableMap.UintToAddressMap private _tokenOwners;\\n\\n    // Mapping from token ID to approved address\\n    mapping (uint256 => address) private _tokenApprovals;\\n\\n    // Mapping from owner to operator approvals\\n    mapping (address => mapping (address => bool)) private _operatorApprovals;\\n\\n    // Token name\\n    string private _name;\\n\\n    // Token symbol\\n    string private _symbol;\\n\\n    // Optional mapping for token URIs\\n    mapping (uint256 => string) private _tokenURIs;\\n\\n    // Base URI\\n    string private _baseURI;\\n\\n    /*\\n     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231\\n     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e\\n     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3\\n     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc\\n     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465\\n     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5\\n     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e\\n     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde\\n     *\\n     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^\\n     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;\\n\\n    /*\\n     *     bytes4(keccak256('name()')) == 0x06fdde03\\n     *     bytes4(keccak256('symbol()')) == 0x95d89b41\\n     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd\\n     *\\n     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;\\n\\n    /*\\n     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd\\n     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59\\n     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7\\n     *\\n     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;\\n\\n    /**\\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n\\n        // register the supported interfaces to conform to ERC721 via ERC165\\n        _registerInterface(_INTERFACE_ID_ERC721);\\n        _registerInterface(_INTERFACE_ID_ERC721_METADATA);\\n        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-balanceOf}.\\n     */\\n    function balanceOf(address owner) public view virtual override returns (uint256) {\\n        require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n        return _holderTokens[owner].length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721-ownerOf}.\\n     */\\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n        return _tokenOwners.get(tokenId, \\\"ERC721: owner query for nonexistent token\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-name}.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-symbol}.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Metadata-tokenURI}.\\n     */\\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n        string memory _tokenURI = _tokenURIs[tokenId];\\n        string memory base = baseURI();\\n\\n        // If there is no base URI, return the token URI.\\n        if (bytes(base).length == 0) {\\n            return _tokenURI;\\n        }\\n        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).\\n        if (bytes(_tokenURI).length > 0) {\\n            return string(abi.encodePacked(base, _tokenURI));\\n        }\\n        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.\\n        return string(abi.encodePacked(base, tokenId.toString()));\\n    }\\n\\n    /**\\n    * @dev Returns the base URI set via {_setBaseURI}. This will be\\n    * automatically added as a prefix in {tokenURI} to each token's URI, or\\n    * to the token ID if no specific URI is set for that token ID.\\n    */\\n    function baseURI() public view virtual returns (string memory) {\\n        return _baseURI;\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n     */\\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n        return _holderTokens[owner].at(index);\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds\\n        return _tokenOwners.length();\\n    }\\n\\n    /**\\n     * @dev See {IERC721Enumerable-tokenByIndex}.\\n     */\\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n        (uint256 tokenId, ) = _tokenOwners.at(index);\\n        return tokenId;\\n    }\\n\\n    /**\\n     * @dev See {IERC721-approve}.\\n     */\\n    function approve(address to, uint256 tokenId) public virtual override {\\n        address owner = ERC721.ownerOf(tokenId);\\n        require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n        require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),\\n            \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n        );\\n\\n        _approve(to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-getApproved}.\\n     */\\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n        require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n        return _tokenApprovals[tokenId];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        require(operator != _msgSender(), \\\"ERC721: approve to caller\\\");\\n\\n        _operatorApprovals[_msgSender()][operator] = approved;\\n        emit ApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[owner][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC721-transferFrom}.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        //solhint-disable-next-line max-line-length\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n        _transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n        safeTransferFrom(from, to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC721-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {\\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n        _safeTransfer(from, to, tokenId, _data);\\n    }\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n     *\\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _transfer(from, to, tokenId);\\n        require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Returns whether `tokenId` exists.\\n     *\\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n     *\\n     * Tokens start existing when they are minted (`_mint`),\\n     * and stop existing when they are burned (`_burn`).\\n     */\\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n        return _tokenOwners.contains(tokenId);\\n    }\\n\\n    /**\\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n        require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n        address owner = ERC721.ownerOf(tokenId);\\n        return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));\\n    }\\n\\n    /**\\n     * @dev Safely mints `tokenId` and transfers it to `to`.\\n     *\\n     * Requirements:\\n     d*\\n     * - `tokenId` must not exist.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _safeMint(address to, uint256 tokenId) internal virtual {\\n        _safeMint(to, tokenId, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n     */\\n    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {\\n        _mint(to, tokenId);\\n        require(_checkOnERC721Received(address(0), to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n    }\\n\\n    /**\\n     * @dev Mints `tokenId` and transfers it to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must not exist.\\n     * - `to` cannot be the zero address.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _mint(address to, uint256 tokenId) internal virtual {\\n        require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n        require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n        _beforeTokenTransfer(address(0), to, tokenId);\\n\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(address(0), to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Destroys `tokenId`.\\n     * The approval is cleared when the token is burned.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _burn(uint256 tokenId) internal virtual {\\n        address owner = ERC721.ownerOf(tokenId); // internal owner\\n\\n        _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n        // Clear approvals\\n        _approve(address(0), tokenId);\\n\\n        // Clear metadata (if any)\\n        if (bytes(_tokenURIs[tokenId]).length != 0) {\\n            delete _tokenURIs[tokenId];\\n        }\\n\\n        _holderTokens[owner].remove(tokenId);\\n\\n        _tokenOwners.remove(tokenId);\\n\\n        emit Transfer(owner, address(0), tokenId);\\n    }\\n\\n    /**\\n     * @dev Transfers `tokenId` from `from` to `to`.\\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n        require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\"); // internal owner\\n        require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(from, to, tokenId);\\n\\n        // Clear approvals from the previous owner\\n        _approve(address(0), tokenId);\\n\\n        _holderTokens[from].remove(tokenId);\\n        _holderTokens[to].add(tokenId);\\n\\n        _tokenOwners.set(tokenId, to);\\n\\n        emit Transfer(from, to, tokenId);\\n    }\\n\\n    /**\\n     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {\\n        require(_exists(tokenId), \\\"ERC721Metadata: URI set of nonexistent token\\\");\\n        _tokenURIs[tokenId] = _tokenURI;\\n    }\\n\\n    /**\\n     * @dev Internal function to set the base URI for all token IDs. It is\\n     * automatically added as a prefix to the value returned in {tokenURI},\\n     * or to the token ID if {tokenURI} is empty.\\n     */\\n    function _setBaseURI(string memory baseURI_) internal virtual {\\n        _baseURI = baseURI_;\\n    }\\n\\n    /**\\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n     * The call is not executed if the target address is not a contract.\\n     *\\n     * @param from address representing the previous owner of the given token ID\\n     * @param to target address that will receive the tokens\\n     * @param tokenId uint256 ID of the token to be transferred\\n     * @param _data bytes optional data to send along with the call\\n     * @return bool whether the call correctly returned the expected magic value\\n     */\\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)\\n        private returns (bool)\\n    {\\n        if (!to.isContract()) {\\n            return true;\\n        }\\n        bytes memory returndata = to.functionCall(abi.encodeWithSelector(\\n            IERC721Receiver(to).onERC721Received.selector,\\n            _msgSender(),\\n            from,\\n            tokenId,\\n            _data\\n        ), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n        bytes4 retval = abi.decode(returndata, (bytes4));\\n        return (retval == _ERC721_RECEIVED);\\n    }\\n\\n    /**\\n     * @dev Approve `to` to operate on `tokenId`\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function _approve(address to, uint256 tokenId) internal virtual {\\n        _tokenApprovals[tokenId] = to;\\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n     * transferred to `to`.\\n     * - When `from` is zero, `tokenId` will be minted for `to`.\\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/introspection/ERC165.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts may inherit from this and call {_registerInterface} to declare\\n * their support of an interface.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /*\\n     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7\\n     */\\n    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;\\n\\n    /**\\n     * @dev Mapping of interface ids to whether or not it's supported.\\n     */\\n    mapping(bytes4 => bool) private _supportedInterfaces;\\n\\n    constructor () {\\n        // Derived contracts need only register support for their own interfaces,\\n        // we register support for ERC165 itself here\\n        _registerInterface(_INTERFACE_ID_ERC165);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     *\\n     * Time complexity O(1), guaranteed to always use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return _supportedInterfaces[interfaceId];\\n    }\\n\\n    /**\\n     * @dev Registers the contract as an implementer of the interface defined by\\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\\n     * registering its interface id is not required.\\n     *\\n     * See {IERC165-supportsInterface}.\\n     *\\n     * Requirements:\\n     *\\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\\n     */\\n    function _registerInterface(bytes4 interfaceId) internal virtual {\\n        require(interfaceId != 0xffffffff, \\\"ERC165: invalid interface id\\\");\\n        _supportedInterfaces[interfaceId] = true;\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/EnumerableSet.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\\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) { // 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            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\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] = toDeleteIndex + 1; // All indexes are 1-based\\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        require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n        return set._values[index];\\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    // 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    // 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    },\n    \"@openzeppelin/contracts/utils/EnumerableMap.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Library for managing an enumerable variant of Solidity's\\n * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]\\n * type.\\n *\\n * Maps have the following properties:\\n *\\n * - Entries are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Entries are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n *     // Add the library methods\\n *     using EnumerableMap for EnumerableMap.UintToAddressMap;\\n *\\n *     // Declare a set state variable\\n *     EnumerableMap.UintToAddressMap private myMap;\\n * }\\n * ```\\n *\\n * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are\\n * supported.\\n */\\nlibrary EnumerableMap {\\n    // To implement this library for multiple types with as little code\\n    // repetition as possible, we write it in terms of a generic Map type with\\n    // bytes32 keys and values.\\n    // The Map implementation uses private functions, and user-facing\\n    // implementations (such as Uint256ToAddressMap) are just wrappers around\\n    // the underlying Map.\\n    // This means that we can only create new EnumerableMaps for types that fit\\n    // in bytes32.\\n\\n    struct MapEntry {\\n        bytes32 _key;\\n        bytes32 _value;\\n    }\\n\\n    struct Map {\\n        // Storage of map keys and values\\n        MapEntry[] _entries;\\n\\n        // Position of the entry defined by a key in the `entries` array, plus 1\\n        // because index 0 means a key is not in the map.\\n        mapping (bytes32 => uint256) _indexes;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex == 0) { // Equivalent to !contains(map, key)\\n            map._entries.push(MapEntry({ _key: key, _value: value }));\\n            // The entry is stored at length-1, but we add 1 to all indexes\\n            // and use 0 as a sentinel value\\n            map._indexes[key] = map._entries.length;\\n            return true;\\n        } else {\\n            map._entries[keyIndex - 1]._value = value;\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Removes a key-value pair from a map. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\\n        // We read and store the key's index to prevent multiple reads from the same storage slot\\n        uint256 keyIndex = map._indexes[key];\\n\\n        if (keyIndex != 0) { // Equivalent to contains(map, key)\\n            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one\\n            // in the array, and then remove the last entry (sometimes called as 'swap and pop').\\n            // This modifies the order of the array, as noted in {at}.\\n\\n            uint256 toDeleteIndex = keyIndex - 1;\\n            uint256 lastIndex = map._entries.length - 1;\\n\\n            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n            MapEntry storage lastEntry = map._entries[lastIndex];\\n\\n            // Move the last entry to the index where the entry to delete is\\n            map._entries[toDeleteIndex] = lastEntry;\\n            // Update the index for the moved entry\\n            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n            // Delete the slot where the moved entry was stored\\n            map._entries.pop();\\n\\n            // Delete the index for the deleted slot\\n            delete map._indexes[key];\\n\\n            return true;\\n        } else {\\n            return false;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function _contains(Map storage map, bytes32 key) private view returns (bool) {\\n        return map._indexes[key] != 0;\\n    }\\n\\n    /**\\n     * @dev Returns the number of key-value pairs in the map. O(1).\\n     */\\n    function _length(Map storage map) private view returns (uint256) {\\n        return map._entries.length;\\n    }\\n\\n   /**\\n    * @dev Returns the key-value pair stored at position `index` in the map. O(1).\\n    *\\n    * Note that there are no guarantees on the ordering of entries inside the\\n    * array, and it may change when more entries are added or removed.\\n    *\\n    * Requirements:\\n    *\\n    * - `index` must be strictly less than {length}.\\n    */\\n    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {\\n        require(map._entries.length > index, \\\"EnumerableMap: index out of bounds\\\");\\n\\n        MapEntry storage entry = map._entries[index];\\n        return (entry._key, entry._value);\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     */\\n    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)\\n        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, \\\"EnumerableMap: nonexistent key\\\"); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    /**\\n     * @dev Same as {_get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {_tryGet}.\\n     */\\n    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {\\n        uint256 keyIndex = map._indexes[key];\\n        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)\\n        return map._entries[keyIndex - 1]._value; // All indexes are 1-based\\n    }\\n\\n    // UintToAddressMap\\n\\n    struct UintToAddressMap {\\n        Map _inner;\\n    }\\n\\n    /**\\n     * @dev Adds a key-value pair to a map, or updates the value for an existing\\n     * key. O(1).\\n     *\\n     * Returns true if the key was added to the map, that is if it was not\\n     * already present.\\n     */\\n    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {\\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\\n    }\\n\\n    /**\\n     * @dev Removes a value from a set. O(1).\\n     *\\n     * Returns true if the key was removed from the map, that is if it was present.\\n     */\\n    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {\\n        return _remove(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns true if the key is in the map. O(1).\\n     */\\n    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {\\n        return _contains(map._inner, bytes32(key));\\n    }\\n\\n    /**\\n     * @dev Returns the number of elements in the map. O(1).\\n     */\\n    function length(UintToAddressMap storage map) internal view returns (uint256) {\\n        return _length(map._inner);\\n    }\\n\\n   /**\\n    * @dev Returns the element stored at position `index` in the set. O(1).\\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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {\\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\\n        return (uint256(key), address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Tries to returns the value associated with `key`.  O(1).\\n     * Does not revert if `key` is not in the map.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {\\n        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));\\n        return (success, address(uint160(uint256(value))));\\n    }\\n\\n    /**\\n     * @dev Returns the value associated with `key`.  O(1).\\n     *\\n     * Requirements:\\n     *\\n     * - `key` must be in the map.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\\n    }\\n\\n    /**\\n     * @dev Same as {get}, with a custom error message when `key` is not in the map.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryGet}.\\n     */\\n    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {\\n        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/utils/Strings.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` 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        uint256 index = digits - 1;\\n        temp = value;\\n        while (temp != 0) {\\n            buffer[index--] = bytes1(uint8(48 + temp % 10));\\n            temp /= 10;\\n        }\\n        return string(buffer);\\n    }\\n}\\n\"\n    },\n    \"contracts/test/ControllerAccessTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\n\\n/**\\n * use this contract to check that controller has correct access control to mint NFTs\\n * a testing contract is necessary as the before transfer hook calls updateOperator\\n */\\ncontract ControllerAccessTester{\\n    \\n    IShortPowerPerp shortPowerPerp;\\n\\n    constructor(address _shortPowerPerp) {\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n    }\\n    \\n    function mintTest(address _address) external returns (uint256) {\\n        return shortPowerPerp.mintNFT(_address);\\n    }\\n\\n    function updateOperator(uint256 _tokenId, address _operator) external {\\n\\n    }\\n}\"\n    },\n    \"contracts/mocks/MockController.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {IShortPowerPerp} from \\\"../interfaces/IShortPowerPerp.sol\\\";\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport {VaultLib} from \\\"../libs/VaultLib.sol\\\";\\n\\ncontract MockController {\\n    using SafeMath for uint256;\\n    using VaultLib for VaultLib.Vault;\\n    using Address for address payable;\\n\\n    uint256 internal constant secInDay = 86400;\\n\\n    address public quoteCurrency;\\n    address public ethQuoteCurrencyPool;\\n    uint256 public normalizationFactor;\\n    uint256 public feeRate = 0;\\n\\n    /// @dev The token ID vault data\\n    mapping(uint256 => VaultLib.Vault) public vaults;\\n\\n    IWPowerPerp public wPowerPerp;\\n    IShortPowerPerp public shortPowerPerp;\\n\\n    function init(\\n        address _shortPowerPerp,\\n        address _wPowerPerp,\\n        address _ethQuoteCurrencyPool,\\n        address _quoteCurrency\\n    ) public {\\n        require(_shortPowerPerp != address(0), \\\"C5\\\");\\n        require(_wPowerPerp != address(0), \\\"Invalid wPowerPerp address\\\");\\n\\n        shortPowerPerp = IShortPowerPerp(_shortPowerPerp);\\n        wPowerPerp = IWPowerPerp(_wPowerPerp);\\n        ethQuoteCurrencyPool = _ethQuoteCurrencyPool;\\n        quoteCurrency = _quoteCurrency;\\n\\n        normalizationFactor = 1e18;\\n    }\\n\\n    function mintWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _mintAmount,\\n        uint256 /*_nftTokenId*/\\n    ) external payable returns (uint256, uint256) {\\n        uint256 wPowerPerpMinted;\\n\\n        if (_vaultId == 0) _vaultId = _openVault(msg.sender);\\n        if (msg.value > 0) _addEthCollateral(_vaultId, msg.value);\\n        if (_mintAmount > 0) {\\n            wPowerPerpMinted = _addShort(msg.sender, _vaultId, _mintAmount);\\n        }\\n\\n        return (_vaultId, wPowerPerpMinted);\\n    }\\n\\n    function burnWPowerPerpAmount(\\n        uint256 _vaultId,\\n        uint256 _amount,\\n        uint256 _withdrawAmount\\n    ) external {\\n        if (_amount > 0) _removeShort(msg.sender, _vaultId, _amount);\\n        if (_withdrawAmount > 0) _withdrawCollateral(msg.sender, _vaultId, _withdrawAmount);\\n        if (_withdrawAmount > 0) payable(msg.sender).sendValue(_withdrawAmount);\\n    }\\n\\n    function _openVault(address _recipient) internal returns (uint256) {\\n        uint256 vaultId = shortPowerPerp.mintNFT(_recipient);\\n        vaults[vaultId] = VaultLib.Vault({\\n            NftCollateralId: 0,\\n            collateralAmount: 0,\\n            shortAmount: 0,\\n            operator: address(0)\\n        });\\n\\n        return vaultId;\\n    }\\n\\n    function _addEthCollateral(uint256 _vaultId, uint256 _amount) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addEthCollateral(uint128(_amount));\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _withdrawCollateral(\\n        address, /*_account*/\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeEthCollateral(_amount);\\n        vaults[_vaultId] = cachedVault;\\n    }\\n\\n    function _addShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _wPowerPerpAmount\\n    ) internal returns (uint256 amountToMint) {\\n        require(_canModifyVault(_vaultId, _account), \\\"C3\\\");\\n\\n        amountToMint = _wPowerPerpAmount.mul(1e18).div(normalizationFactor);\\n\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.addShort(amountToMint);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.mint(_account, amountToMint);\\n    }\\n\\n    function _removeShort(\\n        address _account,\\n        uint256 _vaultId,\\n        uint256 _amount\\n    ) internal {\\n        VaultLib.Vault memory cachedVault = vaults[_vaultId];\\n        cachedVault.removeShort(_amount);\\n        vaults[_vaultId] = cachedVault;\\n\\n        wPowerPerp.burn(_account, _amount);\\n    }\\n\\n    function _canModifyVault(uint256 _vaultId, address _account) internal view returns (bool) {\\n        return shortPowerPerp.ownerOf(_vaultId) == _account || vaults[_vaultId].operator == _account;\\n    }\\n\\n    function getExpectedNormalizationFactor() external view returns (uint256) {\\n        return normalizationFactor;\\n    }\\n}\\n\"\n    },\n    \"contracts/core/WPowerPerp.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//interface\\nimport {IWPowerPerp} from \\\"../interfaces/IWPowerPerp.sol\\\";\\n\\n//contract\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\n\\n/**\\n * @notice ERC20 Token representing wrapped long power perpetual position\\n * @dev value of power perpetual is expected to go down over time through the impact of funding\\n */\\ncontract WPowerPerp is ERC20, Initializable, IWPowerPerp {\\n    address public controller;\\n    address private immutable deployer;\\n\\n    /**\\n     * @notice long power perpetual constructor\\n     * @param _name token name for ERC20\\n     * @param _symbol token symbol for ERC20\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice init wPowerPerp contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) external initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint wPowerPerp\\n     * @param _account account to mint to\\n     * @param _amount amount to mint\\n     */\\n    function mint(address _account, uint256 _amount) external override onlyController {\\n        _mint(_account, _amount);\\n    }\\n\\n    /**\\n     * @notice burn wPowerPerp\\n     * @param _account account to burn from\\n     * @param _amount amount to burn\\n     */\\n    function burn(address _account, uint256 _amount) external override onlyController {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"@openzeppelin/contracts/proxy/Initializable.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\nimport \\\"../utils/Address.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 a proxied contract can't have 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 {UpgradeableProxy-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 */\\nabstract contract Initializable {\\n\\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        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    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        return !Address.isContract(address(this));\\n    }\\n}\\n\"\n    },\n    \"contracts/core/ShortPowerPerp.sol\": {\n      \"content\": \"//SPDX-License-Identifier: BUSL-1.1\\n\\npragma solidity =0.7.6;\\n\\n//contract\\nimport {ERC721} from \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts/proxy/Initializable.sol\\\";\\nimport {IController} from \\\"../interfaces/IController.sol\\\";\\n\\n/**\\n * @notice ERC721 NFT representing ownership of a vault (short position)\\n */\\ncontract ShortPowerPerp is ERC721, Initializable {\\n    /// @dev tokenId for the next vault opened\\n    uint256 public nextId = 1;\\n\\n    address public controller;\\n    address private immutable deployer;\\n\\n    modifier onlyController() {\\n        require(msg.sender == controller, \\\"Not controller\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice short power perpetual constructor\\n     * @param _name token name for ERC721\\n     * @param _symbol token symbol for ERC721\\n     */\\n    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {\\n        deployer = msg.sender;\\n    }\\n\\n    /**\\n     * @notice initialize short contract\\n     * @param _controller controller address\\n     */\\n    function init(address _controller) public initializer {\\n        require(msg.sender == deployer, \\\"Invalid caller of init\\\");\\n        require(_controller != address(0), \\\"Invalid controller address\\\");\\n        controller = _controller;\\n    }\\n\\n    /**\\n     * @notice mint new NFT\\n     * @dev autoincrement tokenId starts at 1\\n     * @param _recipient recipient address for NFT\\n     */\\n    function mintNFT(address _recipient) external onlyController returns (uint256 tokenId) {\\n        // mint NFT\\n        _safeMint(_recipient, (tokenId = nextId++));\\n    }\\n\\n    function _beforeTokenTransfer(\\n        address, /* from */\\n        address, /* to */\\n        uint256 tokenId\\n    ) internal override {\\n        IController(controller).updateOperator(tokenId, address(0));\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockWSqueeth.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockWPowerPerp is ERC20 {\\n    address public controller;\\n\\n    constructor() ERC20(\\\"Wrapped Power Perp\\\", \\\"WPowerPerp\\\") {}\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockUniswapV3Pool.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\nimport {SafeMath} from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\ninterface IUniswapV3FlashCallback {\\n    function uniswapV3FlashCallback(\\n        uint256 fee0,\\n        uint256 fee1,\\n        bytes calldata data\\n    ) external;\\n}\\n\\ncontract MockUniswapV3Pool {\\n    using SafeMath for uint256;\\n\\n    address public token0;\\n    address public token1;\\n    uint256 public fee;\\n\\n    struct PoolKey {\\n        address token0;\\n        address token1;\\n        uint24 fee;\\n    }\\n\\n    struct Slot0 {\\n        // the current price\\n        uint160 sqrtPriceX96;\\n        // the current tick\\n        int24 tick;\\n        // the most-recently updated index of the observations array\\n        uint16 observationIndex;\\n        // the current maximum number of observations that are being stored\\n        uint16 observationCardinality;\\n        // the next maximum number of observations to store, triggered in observations.write\\n        uint16 observationCardinalityNext;\\n        // the current protocol fee as a percentage of the swap fee taken on withdrawal\\n        // represented as an integer denominator (1/x)%\\n        uint8 feeProtocol;\\n        // whether the pool is locked\\n        bool unlocked;\\n    }\\n\\n    Slot0 public slot0;\\n\\n    function setPoolTokens(address _token0, address _token1) external {\\n        token0 = _token0;\\n        token1 = _token1;\\n    }\\n\\n    function setSlot0Data(uint160 _sqrtPriceX96, int24 _tick) external {\\n        slot0.sqrtPriceX96 = _sqrtPriceX96;\\n        slot0.tick = _tick;\\n    }\\n\\n    function flash(\\n        address recipient,\\n        uint256 amount0,\\n        uint256 amount1,\\n        bytes calldata data\\n    ) external {\\n        // uint128 _liquidity = liquidity;\\n        // require(_liquidity > 0, 'L');\\n\\n        // uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);\\n        // uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);\\n        uint256 fee0 = 0;\\n        uint256 fee1 = 0;\\n\\n        uint256 balance0Before = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1Before = ERC20(token1).balanceOf(address(this));\\n\\n        if (amount0 > 0) ERC20(token0).transfer(recipient, amount0);\\n        if (amount1 > 0) ERC20(token1).transfer(recipient, amount1);\\n\\n        IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);\\n\\n        uint256 balance0After = ERC20(token0).balanceOf(address(this));\\n        uint256 balance1After = ERC20(token1).balanceOf(address(this));\\n\\n        require(balance0Before.add(fee0) <= balance0After, \\\"F0\\\");\\n        require(balance1Before.add(fee1) <= balance1After, \\\"F1\\\");\\n    }\\n\\n    function computeAddress(\\n        address, /*factory*/\\n        PoolKey memory /*key*/\\n    ) internal view returns (address pool) {\\n        return address(this);\\n    }\\n}\\n\"\n    },\n    \"contracts/mocks/MockErc20.sol\": {\n      \"content\": \"// SPDX-License-Identifier: MIT\\n\\npragma solidity =0.7.6;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\ncontract MockErc20 is ERC20 {\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) ERC20(_name, _symbol) {\\n        _setupDecimals(_decimals);\\n    }\\n\\n    function mint(address _account, uint256 _amount) external {\\n        _mint(_account, _amount);\\n    }\\n\\n    function burn(address _account, uint256 _amount) external {\\n        _burn(_account, _amount);\\n    }\\n}\\n\"\n    },\n    \"contracts/import/Uni.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol\\\";\\nimport \\\"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\\\";\\nimport \\\"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\\\";\\n\\ncontract Uni {\\n    // hack: force hardhat to import all the interfaces at compile time\\n}\\n\"\n    },\n    \"@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol\": {\n      \"content\": \"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.7.5;\\npragma abicoder v2;\\n\\n/// @title Quoter Interface\\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\\ninterface IQuoter {\\n    /// @notice Returns the amount out received for a given exact input swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee\\n    /// @param amountIn The amount of the first token to swap\\n    /// @return amountOut The amount of the last token that would be received\\n    function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountIn The desired input amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountOut The amount of `tokenOut` that would be received\\n    function quoteExactInputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountIn,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountOut);\\n\\n    /// @notice Returns the amount in required for a given exact output swap without executing the swap\\n    /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\\n    /// @param amountOut The amount of the last token to receive\\n    /// @return amountIn The amount of first token required to be paid\\n    function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);\\n\\n    /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\\n    /// @param tokenIn The token being swapped in\\n    /// @param tokenOut The token being swapped out\\n    /// @param fee The fee of the token pool to consider for the pair\\n    /// @param amountOut The desired output amount\\n    /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\\n    /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\\n    function quoteExactOutputSingle(\\n        address tokenIn,\\n        address tokenOut,\\n        uint24 fee,\\n        uint256 amountOut,\\n        uint160 sqrtPriceLimitX96\\n    ) external returns (uint256 amountIn);\\n}\\n\"\n    },\n    \"contracts/test/CastingTester.sol\": {\n      \"content\": \"//SPDX-License-Identifier: GPL-2.0-or-later\\n\\npragma solidity =0.7.6;\\n\\nimport {Uint256Casting} from \\\"../libs/Uint256Casting.sol\\\";\\n\\ncontract CastingTester{    \\n    using Uint256Casting for uint256;\\n\\n    function testToUint128(uint256 y) external pure returns (uint128 z) {\\n        return y.toUint128();\\n    }\\n\\n    function testToUint96(uint256 y) external pure returns (uint96 z) {\\n        return y.toUint96();\\n    }\\n\\n    function testToUint32(uint256 y) external pure returns (uint32 z) {\\n        return y.toUint32();\\n    }\\n}\"\n    },\n    \"contracts/test/ABDKTester.sol\": {\n      \"content\": \"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>\\n * Copyright (c) 2019, ABDK Consulting\\n *\\n * All rights reserved.\\n *\\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\\n *\\n * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\\n * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\\n * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by ABDK Consulting.\\n * Neither the name of ABDK Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\\n * THIS SOFTWARE IS PROVIDED BY ABDK CONSULTING ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\\n * IN NO EVENT SHALL ABDK CONSULTING BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n \\npragma solidity =0.7.6;\\n\\nimport {ABDKMath64x64} from \\\"../libs/ABDKMath64x64.sol\\\";\\n\\ncontract ABDKTester{    \\n    using ABDKMath64x64 for int128;\\n    using ABDKMath64x64 for uint256;\\n\\n    function testMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return x.mul(y);\\n    }\\n    \\n    function testNegMul(int128 x, int128 y) external pure returns (int128 z) {\\n        return -x.mul(y);\\n    }\\n\\n    function testMulu(int128 x, uint256 y) external pure returns (uint256 z) {\\n        return x.mulu(y);\\n    }\\n    function testDivu(uint256 x, uint256 y) external pure returns (int128 z) {\\n        return x.divu(y);\\n    }\\n    function testLog_2(int128 x) external pure returns (int128 z) {\\n        return x.log_2();\\n    }\\n    function testExp_2(int128 x) external pure returns (int128 z) {\\n        return x.exp_2();\\n    }\\n}\"\n    }\n  },\n  \"settings\": {\n    \"optimizer\": {\n      \"enabled\": true,\n      \"runs\": 800\n    },\n    \"outputSelection\": {\n      \"*\": {\n        \"*\": [\n          \"abi\",\n          \"evm.bytecode\",\n          \"evm.deployedBytecode\",\n          \"evm.methodIdentifiers\",\n          \"metadata\",\n          \"devdoc\",\n          \"userdoc\",\n          \"storageLayout\",\n          \"evm.gasEstimates\"\n        ],\n        \"\": [\n          \"ast\"\n        ]\n      }\n    },\n    \"metadata\": {\n      \"useLiteralContent\": true\n    }\n  }\n}"
  },
  {
    "path": "packages/hardhat/docs/contract.hbs",
    "content": "# `{{name}}`\n\n{{{natspec.userdoc}}}\n\n{{{natspec.devdoc}}}\n\n{{!-- {{#if ownModifiers}}\n## Modifiers:\n{{#ownModifiers}}\n- `{{name}}({{args}})`\n{{/ownModifiers}}\n{{/if}} --}}\n\n{{#if ownFunctions}}\n## All Functions:\n{{#ownFunctions}}\n{{#if (or (eq visibility \"public\") (eq visibility \"external\"))}}\n- `{{name}}({{args}})`\n{{/if}}\n{{/ownFunctions}}\n{{/if}}\n\n{{#if ownEvents}}\n## All Events:\n{{#ownEvents}}\n- `{{name}}({{args}})`\n{{/ownEvents}}\n{{/if}}\n\n{{!-- {{#ownModifiers}}\n### Modifier `{{name}}({{args}})`\n{{#if natspec.userdoc}}{{natspec.userdoc}}{{/if}}\n{{#if natspec.devdoc}}{{natspec.devdoc}}{{/if}}\n\n{{#if natspec.params}}\n#### Parameters:\n{{#natspec.params}}\n- `{{param}}`: {{description}}\n{{/natspec.params}}\n{{/if}}\n{{/ownModifiers}} --}}\n\n# Functions\n\n{{#ownFunctions}}\n{{#if (or (eq visibility \"public\") (eq visibility \"external\"))}}\n## `{{name}}({{args}}){{#if outputs}} → {{outputs}}{{/if}}`\n{{#if natspec.userdoc}}{{natspec.userdoc}}{{/if}}\n{{#if natspec.devdoc}}{{natspec.devdoc}}{{/if}}\n\n{{#if natspec.params}}\n### Parameters:\n{{#natspec.params}}\n- `{{#lookup ../args.types @index}}{{/lookup}} {{param}}`: {{description}}\n{{/natspec.params}}\n{{/if}}\n{{#if natspec.returns}}\n### Return Values:\n{{#natspec.returns}}\n\n{{!-- param is part of description because we didn't name returned variables --}}\n- `{{#lookup ../args.types @index}}{{/lookup}}` {{param}} {{description}}\n{{/natspec.returns}}\n{{/if}}\n{{/if}}\n{{/ownFunctions}}\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/core/Controller.md",
    "content": "# `Controller`\n\n## All Functions:\n\n- `constructor(address _oracle, address _shortPowerPerp, address _wPowerPerp, address _weth, address _quoteCurrency, address _ethQuoteCurrencyPool, address _wPowerPerpPool, address _uniPositionManager)`\n\n- `getExpectedNormalizationFactor()`\n\n- `getIndex(uint32 _period)`\n\n- `getUnscaledIndex(uint32 _period)`\n\n- `getDenormalizedMark(uint32 _period)`\n\n- `getDenormalizedMarkForFunding(uint32 _period)`\n\n- `isVaultSafe(uint256 _vaultId)`\n\n- `mintPowerPerpAmount(uint256 _vaultId, uint128 _powerPerpAmount, uint256 _uniTokenId)`\n\n- `mintWPowerPerpAmount(uint256 _vaultId, uint128 _wPowerPerpAmount, uint256 _uniTokenId)`\n\n- `deposit(uint256 _vaultId)`\n\n- `depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId)`\n\n- `withdraw(uint256 _vaultId, uint256 _amount)`\n\n- `withdrawUniPositionToken(uint256 _vaultId)`\n\n- `burnWPowerPerpAmount(uint256 _vaultId, uint256 _wPowerPerpAmount, uint256 _withdrawAmount)`\n\n- `burnPowerPerpAmount(uint256 _vaultId, uint256 _powerPerpAmount, uint256 _withdrawAmount)`\n\n- `reduceDebtShutdown(uint256 _vaultId)`\n\n- `reduceDebt(uint256 _vaultId)`\n\n- `liquidate(uint256 _vaultId, uint256 _maxDebtAmount)`\n\n- `updateOperator(uint256 _vaultId, address _operator)`\n\n- `setFeeRecipient(address _newFeeRecipient)`\n\n- `setFeeRate(uint256 _newFeeRate)`\n\n- `pauseAndShutDown()`\n\n- `shutDown()`\n\n- `pause()`\n\n- `unPauseAnyone()`\n\n- `unPauseOwner()`\n\n- `redeemLong(uint256 _wPerpAmount)`\n\n- `redeemShort(uint256 _vaultId)`\n\n- `applyFunding()`\n\n- `donate()`\n\n- `receive()`\n\n## All Events:\n\n- `OpenVault(uint256 vaultId)`\n\n- `CloseVault(uint256 vaultId)`\n\n- `DepositCollateral(uint256 vaultId, uint256 amount, uint128 collateralId)`\n\n- `DepositUniPositionToken(uint256 vaultId, uint256 tokenId)`\n\n- `WithdrawCollateral(uint256 vaultId, uint256 amount, uint128 collateralId)`\n\n- `WithdrawUniPositionToken(uint256 vaultId, uint256 tokenId)`\n\n- `MintShort(uint256 amount, uint256 vaultId)`\n\n- `BurnShort(uint256 amount, uint256 vaultId)`\n\n- `UpdateOperator(uint256 vaultId, address operator)`\n\n- `FeeRateUpdated(uint256 oldFee, uint256 newFee)`\n\n- `FeeRecipientUpdated(address oldFeeRecipient, address newFeeRecipient)`\n\n- `Liquidate(uint256 vaultId, uint256 debtAmount, uint256 collateralPaid)`\n\n- `NormalizationFactorUpdated(uint256 oldNormFactor, uint256 newNormFactor, uint256 timestamp)`\n\n# Functions\n\n## `constructor(address _oracle, address _shortPowerPerp, address _wPowerPerp, address _weth, address _quoteCurrency, address _ethQuoteCurrencyPool, address _wPowerPerpPool, address _uniPositionManager)`\n\nconstructor\n\n### Parameters:\n\n- `address _oracle`: oracle address\n\n- `address _shortPowerPerp`: ERC721 token address representing the short position\n\n- `address _wPowerPerp`: ERC20 token address representing the long position\n\n- `address _weth`: weth address\n\n- `address _quoteCurrency`: quoteCurrency address\n\n- `address _ethQuoteCurrencyPool`: uniswap v3 pool for weth / quoteCurrency\n\n- `address _wPowerPerpPool`: uniswap v3 pool for wPowerPerp / weth\n\n- `address _uniPositionManager`: uniswap v3 position manager address\n\n## `getExpectedNormalizationFactor() → uint256`\n\nreturns the expected normalization factor, if the funding is paid right now\n\ncan be used for on-chain and off-chain calculations\n\n## `getIndex(uint32 _period) → uint256`\n\nget the index price of the powerPerp, scaled down\n\nthe index price is scaled down by INDEX_SCALE in the associated PowerXBase library\n\nthis is the index price used when calculating funding and for collateralization\n\n### Parameters:\n\n- `uint32 _period`: period which you want to calculate twap with\n\n### Return Values:\n\n- `uint32` index price denominated in $USD, scaled by 1e18\n\n## `getUnscaledIndex(uint32 _period) → uint256`\n\nget the expected mark price of powerPerp after funding has been applied\n\nthis is the mark that would be be used for future funding after a new normalization factor is applied\n\n### Parameters:\n\n- `uint32 _period`: period which you want to calculate twap with\n\n### Return Values:\n\n- `uint32` index price denominated in $USD, scaled by 1e18\n\n## `getDenormalizedMark(uint32 _period) → uint256`\n\nget the mark price (after funding) of powerPerp as the twap divided by the normalization factor\n\n### Parameters:\n\n- `uint32 _period`: period of time for the twap in seconds\n\n### Return Values:\n\n- `uint32` mark price denominated in $USD, scaled by 1e18\n\n## `getDenormalizedMarkForFunding(uint32 _period) → uint256`\n\nget the mark price of powerPerp before funding has been applied\n\nthis is the mark that would be used to calculate a new normalization factor if funding was calculated now\n\n### Parameters:\n\n- `uint32 _period`: period which you want to calculate twap with\n\n### Return Values:\n\n- `uint32` mark price denominated in $USD, scaled by 1e18\n\n## `isVaultSafe(uint256 _vaultId) → bool`\n\nreturn if the vault is properly collateralized\n\n### Parameters:\n\n- `uint256 _vaultId`: id of the vault\n\n### Return Values:\n\n- `uint256` true if the vault is properly collateralized\n\n## `mintPowerPerpAmount(uint256 _vaultId, uint128 _powerPerpAmount, uint256 _uniTokenId) → uint256, uint256`\n\ndeposit collateral and mint wPowerPerp (non-rebasing) for specified powerPerp (rebasing) amount\n\n### Parameters:\n\n- `uint256 _vaultId`: vault to mint wPowerPerp in\n\n- `uint128 _powerPerpAmount`: amount of powerPerp to mint\n\n- `uint256 _uniTokenId`: uniswap v3 position token id (additional collateral)\n\n### Return Values:\n\n- `uint256` amount of wPowerPerp minted\n\n## `mintWPowerPerpAmount(uint256 _vaultId, uint128 _wPowerPerpAmount, uint256 _uniTokenId) → uint256`\n\ndeposit collateral and mint wPowerPerp\n\n### Parameters:\n\n- `uint256 _vaultId`: vault to mint wPowerPerp in\n\n- `uint128 _wPowerPerpAmount`: amount of wPowerPerp to mint\n\n- `uint256 _uniTokenId`: uniswap v3 position token id (additional collateral)\n\n## `deposit(uint256 _vaultId)`\n\ndeposit collateral into a vault\n\n### Parameters:\n\n- `uint256 _vaultId`: id of the vault\n\n## `depositUniPositionToken(uint256 _vaultId, uint256 _uniTokenId)`\n\ndeposit uniswap position token into a vault to increase collateral ratio\n\n### Parameters:\n\n- `uint256 _vaultId`: id of the vault\n\n- `uint256 _uniTokenId`: uniswap position token id\n\n## `withdraw(uint256 _vaultId, uint256 _amount)`\n\nwithdraw collateral from a vault\n\n### Parameters:\n\n- `uint256 _vaultId`: id of the vault\n\n- `uint256 _amount`: amount of eth to withdraw\n\n## `withdrawUniPositionToken(uint256 _vaultId)`\n\nwithdraw uniswap v3 position token from a vault\n\n### Parameters:\n\n- `uint256 _vaultId`: id of the vault\n\n## `burnWPowerPerpAmount(uint256 _vaultId, uint256 _wPowerPerpAmount, uint256 _withdrawAmount)`\n\nburn wPowerPerp and remove collateral from a vault\n\n### Parameters:\n\n- `uint256 _vaultId`: id of the vault\n\n- `uint256 _wPowerPerpAmount`: amount of wPowerPerp to burn\n\n- `uint256 _withdrawAmount`: amount of eth to withdraw\n\n## `burnPowerPerpAmount(uint256 _vaultId, uint256 _powerPerpAmount, uint256 _withdrawAmount) → uint256`\n\nburn powerPerp and remove collateral from a vault\n\n### Parameters:\n\n- `uint256 _vaultId`: id of the vault\n\n- `uint256 _powerPerpAmount`: amount of powerPerp to burn\n\n- `uint256 _withdrawAmount`: amount of eth to withdraw\n\n### Return Values:\n\n- `uint256` amount of wPowerPerp burned\n\n## `reduceDebtShutdown(uint256 _vaultId)`\n\nafter the system is shutdown, insolvent vaults need to be have their uniswap v3 token assets withdrawn by force\n\nif a vault has a uniswap v3 position in it, anyone can call to withdraw uniswap v3 token assets, reducing debt and increasing collateral in the vault\n\nthe caller won't get any bounty. this is expected to be used for insolvent vaults in shutdown\n\n### Parameters:\n\n- `uint256 _vaultId`: vault containing uniswap v3 position to liquidate\n\n## `reduceDebt(uint256 _vaultId)`\n\nwithdraw assets from uniswap v3 position, reducing debt and increasing collateral in the vault\n\nthe caller won't get any bounty. this is expected to be used by vault owner\n\n### Parameters:\n\n- `uint256 _vaultId`: target vault\n\n## `liquidate(uint256 _vaultId, uint256 _maxDebtAmount) → uint256`\n\nif a vault is under the 150% collateral ratio, anyone can liquidate the vault by burning wPowerPerp\n\nliquidator can get back (wPowerPerp burned) * (index price) * (normalizationFactor)  * 110% in collateral\n\nnormally can only liquidate 50% of a vault's debt\n\nif a vault is under dust limit after a liquidation can fully liquidate\n\nwill attempt to reduceDebt first, and can earn a bounty if sucessful\n\n### Parameters:\n\n- `uint256 _vaultId`: vault to liquidate\n\n- `uint256 _maxDebtAmount`: max amount of wPowerPerpetual to repay\n\n### Return Values:\n\n- `uint256` amount of wPowerPerp repaid\n\n## `updateOperator(uint256 _vaultId, address _operator)`\n\nauthorize an address to modify the vault\n\ncan be revoke by setting address to 0\n\n### Parameters:\n\n- `uint256 _vaultId`: id of the vault\n\n- `address _operator`: new operator address\n\n## `setFeeRecipient(address _newFeeRecipient)`\n\nset the recipient who will receive the fee\n\nthis should be a contract handling insurance\n\n### Parameters:\n\n- `address _newFeeRecipient`: new fee recipient\n\n## `setFeeRate(uint256 _newFeeRate)`\n\nset the fee rate when user mints\n\nthis function cannot be called if the feeRecipient is still un-set\n\n### Parameters:\n\n- `uint256 _newFeeRate`: new fee rate in basis points. can't be higher than 1%\n\n## `pauseAndShutDown()`\n\npause and then immediately shutdown the system\n\nthis bypasses the check on number of pauses or time based checks, but is irreversible and enables emergency settlement\n\n## `shutDown()`\n\nshutdown the system and enable system settlement\n\n## `pause()`\n\npause the system for up to 24 hours after which any one can unpause\n\ncan only be called for 365 days since the contract was launched or 4 times\n\n## `unPauseAnyone()`\n\nunpause the contract\n\nanyone can unpause the contract after 24 hours\n\n## `unPauseOwner()`\n\nunpause the contract\n\nowner can unpause at any time\n\n## `redeemLong(uint256 _wPerpAmount)`\n\nredeem wPowerPerp for (settlement index value) * normalizationFactor when the system is shutdown\n\n### Parameters:\n\n- `uint256 _wPerpAmount`: amount of wPowerPerp to burn\n\n## `redeemShort(uint256 _vaultId)`\n\nredeem short position when the system is shutdown\n\nshort position is redeemed by valuing the debt at the (settlement index value) * normalizationFactor\n\n### Parameters:\n\n- `uint256 _vaultId`: vault id\n\n## `applyFunding()`\n\nupdate the normalization factor as a way to pay funding\n\n## `donate()`\n\nadd eth into a contract. used in case contract has insufficient eth to pay for settlement transactions\n\n## `receive()`\n\nfallback function to accept eth\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/core/Oracle.md",
    "content": "# `Oracle`\n\nread UniswapV3 pool TWAP prices, and convert to human readable term with (18 decimals)\n\nif ETH price is $3000, both ETH/USDC price and ETH/DAI price will be reported as 3000 * 1e18 by this oracle\n\n## All Functions:\n\n- `getTwap(address _pool, address _base, address _quote, uint32 _period)`\n\n- `getHistoricalTwap(address _pool, address _base, address _quote, uint32 _secondsAgoToStartOfTwap, uint32 _secondsAgoToEndOfTwap)`\n\n- `getTwapSafe(address _pool, address _base, address _quote, uint32 _period)`\n\n- `getMaxPeriod(address _pool)`\n\n- `getTimeWeightedAverageTickSafe(address _pool, uint32 _period)`\n\n# Functions\n\n## `getTwap(address _pool, address _base, address _quote, uint32 _period) → uint256`\n\nget twap converted with base & quote token decimals\n\nif period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \"OLD\"\n\n### Parameters:\n\n- `address _pool`: uniswap pool address\n\n- `address _base`: base currency. to get eth/usd price, eth is base token\n\n- `address _quote`: quote currency. to get eth/usd price, usd is the quote currency\n\n- `uint32 _period`: number of seconds in the past to start calculating time-weighted average\n\n### Return Values:\n\n- `address` price of 1 base currency in quote currency. scaled by 1e18\n\n## `getHistoricalTwap(address _pool, address _base, address _quote, uint32 _secondsAgoToStartOfTwap, uint32 _secondsAgoToEndOfTwap) → uint256`\n\n## `getTwapSafe(address _pool, address _base, address _quote, uint32 _period) → uint256`\n\nget twap converted with base & quote token decimals, never reverts\n\n### Parameters:\n\n- `address _pool`: uniswap pool address\n\n- `address _base`: base currency. to get eth/usd price, eth is base token\n\n- `address _quote`: quote currency. to get eth/usd price, usd is the quote currency\n\n- `uint32 _period`: number of seconds in the past to start calculating time-weighted average\n\n### Return Values:\n\n- `address` price of 1 base currency in quote currency. scaled by 1e18\n\n## `getMaxPeriod(address _pool) → uint32`\n\nget the max period that can be used to request twap\n\n### Parameters:\n\n- `address _pool`: uniswap pool address\n\n### Return Values:\n\n- `address` max period can be used to request twap\n\n## `getTimeWeightedAverageTickSafe(address _pool, uint32 _period) → int24 timeWeightedAverageTick`\n\nget time weighed average tick, not converted to price\n\nthis function will not revert\n\n### Parameters:\n\n- `address _pool`: address of the pool\n\n- `uint32 _period`: period in second that we want to calculate average on\n\n### Return Values:\n\n- `address` timeWeightedAverageTick the time weighted average tick\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/core/ShortPowerPerp.md",
    "content": "# `ShortPowerPerp`\n\nERC721 NFT representing ownership of a vault (short position)\n\n## All Functions:\n\n- `constructor(string _name, string _symbol)`\n\n- `init(address _controller)`\n\n- `mintNFT(address _recipient)`\n\n# Functions\n\n## `constructor(string _name, string _symbol)`\n\nshort power perpetual constructor\n\n### Parameters:\n\n- `string _name`: token name for ERC721\n\n- `string _symbol`: token symbol for ERC721\n\n## `init(address _controller)`\n\ninitialize short contract\n\n### Parameters:\n\n- `address _controller`: controller address\n\n## `mintNFT(address _recipient) → uint256 tokenId`\n\nmint new NFT\n\nautoincrement tokenId starts at 1\n\n### Parameters:\n\n- `address _recipient`: recipient address for NFT\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/core/WPowerPerp.md",
    "content": "# `WPowerPerp`\n\nERC20 Token representing wrapped long power perpetual position\n\nvalue of power perpetual is expected to go down over time through the impact of funding\n\n## All Functions:\n\n- `constructor(string _name, string _symbol)`\n\n- `init(address _controller)`\n\n- `mint(address _account, uint256 _amount)`\n\n- `burn(address _account, uint256 _amount)`\n\n# Functions\n\n## `constructor(string _name, string _symbol)`\n\nlong power perpetual constructor\n\n### Parameters:\n\n- `string _name`: token name for ERC20\n\n- `string _symbol`: token symbol for ERC20\n\n## `init(address _controller)`\n\ninit wPowerPerp contract\n\n### Parameters:\n\n- `address _controller`: controller address\n\n## `mint(address _account, uint256 _amount)`\n\nmint wPowerPerp\n\n### Parameters:\n\n- `address _account`: account to mint to\n\n- `uint256 _amount`: amount to mint\n\n## `burn(address _account, uint256 _amount)`\n\nburn wPowerPerp\n\n### Parameters:\n\n- `address _account`: account to burn from\n\n- `uint256 _amount`: amount to burn\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/core/WSqueeth.md",
    "content": "# `WSqueeth`\n\nthis is the ERC20 contract for long position of Squeeth\n\nthis contract implements IWPowerPerp interface, makes it controllable by Controller.\n\ndecimals of squeeth is chosen as 14.\n\n## Modifiers:\n\n- `onlyController()`\n\n## Functions:\n\n- `decimals() (public)`\n\n- `init(address _controller) (external)`\n\n- `mint(address _account, uint256 _amount) (external)`\n\n- `burn(address _account, uint256 _amount) (external)`\n\n### Modifier `onlyController()`\n\n### Function `decimals() → uint8 public`\n\noverride decimals with 14.\n\n### Function `init(address _controller) external`\n\n### Function `mint(address _account, uint256 _amount) external`\n\n### Function `burn(address _account, uint256 _amount) external`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/external/WETH9.md",
    "content": "# `WETH9`\n\n## All Functions:\n\n- `deposit()`\n\n- `withdraw(uint256 wad)`\n\n- `totalSupply()`\n\n- `approve(address guy, uint256 wad)`\n\n- `transfer(address dst, uint256 wad)`\n\n- `transferFrom(address src, address dst, uint256 wad)`\n\n## All Events:\n\n- `Approval(address src, address guy, uint256 wad)`\n\n- `Transfer(address src, address dst, uint256 wad)`\n\n- `Deposit(address dst, uint256 wad)`\n\n- `Withdrawal(address src, uint256 wad)`\n\n# Functions\n\n## `deposit()`\n\n## `withdraw(uint256 wad)`\n\n## `totalSupply() → uint256`\n\n## `approve(address guy, uint256 wad) → bool`\n\n## `transfer(address dst, uint256 wad) → bool`\n\n## `transferFrom(address src, address dst, uint256 wad) → bool`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/import/Uni.md",
    "content": "# `Uni`\n\n# Functions\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/interfaces/IController.md",
    "content": "# `IController`\n\n## All Functions:\n\n- `vaults(uint256 _vaultId)`\n\n- `shortPowerPerp()`\n\n- `wPowerPerp()`\n\n- `getExpectedNormalizationFactor()`\n\n- `mintPowerPerpAmount(uint256 _vaultId, uint128 _powerPerpAmount, uint256 _uniTokenId)`\n\n- `mintWPowerPerpAmount(uint256 _vaultId, uint128 _wPowerPerpAmount, uint256 _uniTokenId)`\n\n- `deposit(uint256 _vaultId)`\n\n- `withdraw(uint256 _vaultId, uint256 _amount)`\n\n- `burnWPowerPerpAmount(uint256 _vaultId, uint256 _wPowerPerpAmount, uint256 _withdrawAmount)`\n\n- `burnOnPowerPerpAmount(uint256 _vaultId, uint256 _powerPerpAmount, uint256 _withdrawAmount)`\n\n- `applyFunding()`\n\n- `reduceDebtShutdown(uint256 _vaultId)`\n\n# Functions\n\n## `vaults(uint256 _vaultId) → struct VaultLib.Vault`\n\n## `shortPowerPerp() → address`\n\n## `wPowerPerp() → address`\n\n## `getExpectedNormalizationFactor() → uint256`\n\n## `mintPowerPerpAmount(uint256 _vaultId, uint128 _powerPerpAmount, uint256 _uniTokenId) → uint256 vaultId, uint256 wPowerPerpAmount`\n\n## `mintWPowerPerpAmount(uint256 _vaultId, uint128 _wPowerPerpAmount, uint256 _uniTokenId) → uint256 vaultId`\n\n## `deposit(uint256 _vaultId)`\n\nDeposit collateral into a vault\n\n## `withdraw(uint256 _vaultId, uint256 _amount)`\n\nWithdraw collateral from a vault.\n\n## `burnWPowerPerpAmount(uint256 _vaultId, uint256 _wPowerPerpAmount, uint256 _withdrawAmount)`\n\n## `burnOnPowerPerpAmount(uint256 _vaultId, uint256 _powerPerpAmount, uint256 _withdrawAmount) → uint256 wPowerPerpAmount`\n\n## `applyFunding()`\n\nExternal function to update the normalized factor as a way to pay funding.\n\n## `reduceDebtShutdown(uint256 _vaultId)`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/interfaces/IERC20Detailed.md",
    "content": "# `IERC20Detailed`\n\n## All Functions:\n\n- `decimals()`\n\n# Functions\n\n## `decimals() → uint8`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/interfaces/IOracle.md",
    "content": "# `IOracle`\n\n## All Functions:\n\n- `getHistoricalTwap(address _pool, address _base, address _quote, uint32 _period, uint32 _periodToHistoricPrice)`\n\n- `getTwap(address _pool, address _base, address _quote, uint32 _period)`\n\n- `getTwapSafe(address _pool, address _base, address _quote, uint32 _period)`\n\n- `getMaxPeriod(address _pool)`\n\n- `getTimeWeightedAverageTickSafe(address _pool, uint32 _period)`\n\n# Functions\n\n## `getHistoricalTwap(address _pool, address _base, address _quote, uint32 _period, uint32 _periodToHistoricPrice) → uint256`\n\n## `getTwap(address _pool, address _base, address _quote, uint32 _period) → uint256`\n\n## `getTwapSafe(address _pool, address _base, address _quote, uint32 _period) → uint256`\n\n## `getMaxPeriod(address _pool) → uint32`\n\n## `getTimeWeightedAverageTickSafe(address _pool, uint32 _period) → int24 timeWeightedAverageTick`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/interfaces/IShortPowerPerp.md",
    "content": "# `IShortPowerPerp`\n\n## All Functions:\n\n- `nextId()`\n\n- `mintNFT(address recipient)`\n\n# Functions\n\n## `nextId() → uint256`\n\n## `mintNFT(address recipient) → uint256 _newId`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/interfaces/IVaultManagerNFT.md",
    "content": "# `IVaultManagerNFT`\n\n## Functions:\n\n- `mintNFT(address recipient) (external)`\n\n### Function `mintNFT(address recipient) → uint256 _newId external`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/interfaces/IWETH9.md",
    "content": "# `IWETH9`\n\n## All Functions:\n\n- `deposit()`\n\n- `withdraw(uint256 wad)`\n\n# Functions\n\n## `deposit()`\n\n## `withdraw(uint256 wad)`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/interfaces/IWPowerPerp.md",
    "content": "# `IWPowerPerp`\n\n## All Functions:\n\n- `mint(address _account, uint256 _amount)`\n\n- `burn(address _account, uint256 _amount)`\n\n# Functions\n\n## `mint(address _account, uint256 _amount)`\n\n## `burn(address _account, uint256 _amount)`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/libs/OracleLibrary.md",
    "content": "# `OracleLibrary`\n\nprovides functions to integrate with uniswap v3 oracle\n\n## All Functions:\n\n# Functions\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/libs/Power2Base.md",
    "content": "# `Power2Base`\n\n## All Functions:\n\n# Functions\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/libs/VaultLib.md",
    "content": "# `VaultLib`\n\n## All Functions:\n\n# Functions\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/mocks/IUniswapV3FlashCallback.md",
    "content": "# `IUniswapV3FlashCallback`\n\n## All Functions:\n\n- `uniswapV3FlashCallback(uint256 fee0, uint256 fee1, bytes data)`\n\n# Functions\n\n## `uniswapV3FlashCallback(uint256 fee0, uint256 fee1, bytes data)`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/mocks/MockController.md",
    "content": "# `MockController`\n\n## All Functions:\n\n- `init(address _shortPowerPerp, address _wPowerPerp)`\n\n- `mintWPowerPerpAmount(uint256 _vaultId, uint128 _mintAmount, uint256)`\n\n- `burnWPowerPerpAmount(uint256 _vaultId, uint256 _amount, uint256 _withdrawAmount)`\n\n# Functions\n\n## `init(address _shortPowerPerp, address _wPowerPerp)`\n\n## `mintWPowerPerpAmount(uint256 _vaultId, uint128 _mintAmount, uint256) → uint256, uint256`\n\n## `burnWPowerPerpAmount(uint256 _vaultId, uint256 _amount, uint256 _withdrawAmount)`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/mocks/MockErc20.md",
    "content": "# `MockErc20`\n\n## All Functions:\n\n- `constructor(string _name, string _symbol, uint8 _decimals)`\n\n- `mint(address _account, uint256 _amount)`\n\n- `burn(address _account, uint256 _amount)`\n\n# Functions\n\n## `constructor(string _name, string _symbol, uint8 _decimals)`\n\n## `mint(address _account, uint256 _amount)`\n\n## `burn(address _account, uint256 _amount)`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/mocks/MockOracle.md",
    "content": "# `MockOracle`\n\n## All Functions:\n\n- `setPrice(address _pool, uint256 _price)`\n\n- `setAverageTick(address _pool, int24 _poolTick)`\n\n- `getTwapSafe(address _pool, address, address, uint32)`\n\n- `getTimeWeightedAverageTickSafe(address _pool, uint32)`\n\n- `getTwap(address _pool, address, address, uint32)`\n\n- `getMaxPeriod(address)`\n\n# Functions\n\n## `setPrice(address _pool, uint256 _price)`\n\n## `setAverageTick(address _pool, int24 _poolTick)`\n\n## `getTwapSafe(address _pool, address, address, uint32) → uint256`\n\n## `getTimeWeightedAverageTickSafe(address _pool, uint32) → int24`\n\n## `getTwap(address _pool, address, address, uint32) → uint256`\n\n## `getMaxPeriod(address) → uint32`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/mocks/MockShortPowerPerp.md",
    "content": "# `MockShortPowerPerp`\n\n## All Functions:\n\n- `mintNFT(address _recipient)`\n\n- `burnNFT(uint256 _tokenId)`\n\n# Functions\n\n## `mintNFT(address _recipient) → uint256 tokenId`\n\n## `burnNFT(uint256 _tokenId)`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/mocks/MockUniPositionManager.md",
    "content": "# `MockUniPositionManager`\n\n## All Functions:\n\n- `mint(address account, uint256 tokenId)`\n\n- `setMockedProperties(address _token0, address _token1, int24 _tickLower, int24 _tickUpper, uint128 _liquidity)`\n\n- `positions(uint256)`\n\n- `setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1)`\n\n- `decreaseLiquidity(struct INonfungiblePositionManager.DecreaseLiquidityParams)`\n\n- `collect(struct INonfungiblePositionManager.CollectParams params)`\n\n# Functions\n\n## `mint(address account, uint256 tokenId)`\n\n## `setMockedProperties(address _token0, address _token1, int24 _tickLower, int24 _tickUpper, uint128 _liquidity)`\n\n## `positions(uint256) → uint96, address, address, address, uint24, int24, int24, uint128, uint256, uint256, uint128, uint128`\n\n## `setAmount0Amount1ToDecrease(uint256 amount0, uint256 amount1)`\n\n## `decreaseLiquidity(struct INonfungiblePositionManager.DecreaseLiquidityParams) → uint256, uint256`\n\n## `collect(struct INonfungiblePositionManager.CollectParams params) → uint256, uint256`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/mocks/MockUniswapV3Pool.md",
    "content": "# `MockUniswapV3Pool`\n\n## All Functions:\n\n- `setPoolTokens(address _token0, address _token1)`\n\n- `setSlot0Data(uint160 _sqrtPriceX96, int24 _tick)`\n\n- `flash(address recipient, uint256 amount0, uint256 amount1, bytes data)`\n\n# Functions\n\n## `setPoolTokens(address _token0, address _token1)`\n\n## `setSlot0Data(uint160 _sqrtPriceX96, int24 _tick)`\n\n## `flash(address recipient, uint256 amount0, uint256 amount1, bytes data)`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/mocks/MockVaultNFTManager.md",
    "content": "# `MockVaultNFTManager`\n\n## Functions:\n\n- `mintNFT(address _recipient) (external)`\n\n- `burnNFT(uint256 _tokenId) (external)`\n\n### Function `mintNFT(address _recipient) → uint256 tokenId external`\n\n### Function `burnNFT(uint256 _tokenId) external`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/mocks/MockWPowerPerp.md",
    "content": "# `MockWPowerPerp`\n\n## All Functions:\n\n- `mint(address _account, uint256 _amount)`\n\n- `burn(address _account, uint256 _amount)`\n\n# Functions\n\n## `mint(address _account, uint256 _amount)`\n\n## `burn(address _account, uint256 _amount)`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/mocks/MockWSqueeth.md",
    "content": "# `MockWSqueeth`\n\n## Functions:\n\n- `mint(address _account, uint256 _amount) (external)`\n\n- `burn(address _account, uint256 _amount) (external)`\n\n### Function `mint(address _account, uint256 _amount) external`\n\n### Function `burn(address _account, uint256 _amount) external`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/periphery/ShortHelper.md",
    "content": "# `ShortHelper`\n\ncontract simplifies opening a short wPowerPerp position by selling wPowerPerp on uniswap v3 and returning eth to user\n\n## All Functions:\n\n- `constructor(address _controllerAddr, address _swapRouter, address _wethAddr)`\n\n- `openShort(uint256 _vaultId, uint128 _powerPerpAmount, uint256 _uniNftId, struct ISwapRouter.ExactInputSingleParams _exactInputParams)`\n\n- `closeShort(uint256 _vaultId, uint256 _wPowerPerpAmount, uint128 _withdrawAmount, struct ISwapRouter.ExactOutputSingleParams _exactOutputParams)`\n\n- `receive()`\n\n# Functions\n\n## `constructor(address _controllerAddr, address _swapRouter, address _wethAddr)`\n\nconstructor for short helper\n\n### Parameters:\n\n- `address _controllerAddr`: controller address for wPowerPerp\n\n- `address _swapRouter`: uniswap v3 swap router address\n\n- `address _wethAddr`: weth address\n\n## `openShort(uint256 _vaultId, uint128 _powerPerpAmount, uint256 _uniNftId, struct ISwapRouter.ExactInputSingleParams _exactInputParams)`\n\nmint power perp, trade with uniswap v3 and send back premium in eth\n\n### Parameters:\n\n- `uint256 _vaultId`: short wPowerPerp vault id\n\n- `uint128 _powerPerpAmount`: amount of powerPerp to mint/sell\n\n- `uint256 _uniNftId`: uniswap v3 position token id\n\n## `closeShort(uint256 _vaultId, uint256 _wPowerPerpAmount, uint128 _withdrawAmount, struct ISwapRouter.ExactOutputSingleParams _exactOutputParams)`\n\nbuy back wPowerPerp with eth on uniswap v3 and close position\n\n### Parameters:\n\n- `uint256 _vaultId`: short wPowerPerp vault id\n\n- `uint256 _wPowerPerpAmount`: amount of wPowerPerp to mint/sell\n\n- `uint128 _withdrawAmount`: amount to withdraw\n\n## `receive()`\n\nonly receive eth from weth contract and controller.\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/strategy/CrabStrategy.md",
    "content": "# `CrabStrategy`\n\nContract for Crab strategy\n\nCrabStrategy contract\n\n## All Functions:\n\n- `constructor(address _wSqueethController, address _oracle, address _weth, address _uniswapFactory, address _ethWSqueethPool, uint256 _hedgeTimeThreshold, uint256 _hedgePriceThreshold, uint256 _auctionTime, uint256 _minPriceMultiplier, uint256 _maxPriceMultiplier)`\n\n- `receive()`\n\n- `flashDeposit(uint256 _ethToDeposit, uint256 _ethToBorrow)`\n\n- `flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay)`\n\n- `deposit()`\n\n- `withdraw(uint256 _crabAmount, uint256 _wSqueethAmount)`\n\n- `timeHedgeOnUniswap()`\n\n- `priceHedgeOnUniswap(uint256 _auctionTriggerTime)`\n\n- `timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice)`\n\n- `priceHedge(uint256 _auctionTriggerTime, bool _isStrategySellingWSqueeth, uint256 _limitPrice)`\n\n- `checkPriceHedge(uint256 _auctionTriggerTime)`\n\n- `checkTimeHedge()`\n\n- `getWsqueethFromCrabAmount(uint256 _crabAmount)`\n\n## All Events:\n\n- `Deposit(address depositor, uint256 wSqueethAmount, uint256 lpAmount)`\n\n- `Withdraw(address withdrawer, uint256 crabAmount, uint256 wSqueethAmount, uint256 ethWithdrawn)`\n\n- `FlashDeposit(address depositor, uint256 depositedAmount, uint256 borrowedAmount, uint256 totalDepositedAmount, uint256 tradedAmountOut)`\n\n- `FlashWithdraw(address withdrawer, uint256 crabAmount, uint256 wSqueethAmount)`\n\n- `TimeHedgeOnUniswap(address hedger, uint256 hedgeTimestamp, uint256 auctionTriggerTimestamp)`\n\n- `PriceHedgeOnUniswap(address hedger, uint256 hedgeTimestamp, uint256 auctionTriggerTimestamp)`\n\n- `TimeHedge(address hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp)`\n\n- `PriceHedge(address hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionTriggerTimestamp)`\n\n- `Hedge(address hedger, bool auctionType, uint256 hedgerPrice, uint256 auctionPrice, uint256 wSqueethHedgeTargetAmount, uint256 ethHedgetargetAmount)`\n\n- `HedgeOnUniswap(address hedger, bool auctionType, uint256 auctionPrice, uint256 wSqueethHedgeTargetAmount, uint256 ethHedgetargetAmount)`\n\n- `ExecuteSellAuction(address buyer, uint256 wSqueethSold, uint256 ethBought, bool isHedgingOnUniswap)`\n\n- `ExecuteBuyAuction(address seller, uint256 wSqueethBought, uint256 ethSold, bool isHedgingOnUniswap)`\n\n# Functions\n\n## `constructor(address _wSqueethController, address _oracle, address _weth, address _uniswapFactory, address _ethWSqueethPool, uint256 _hedgeTimeThreshold, uint256 _hedgePriceThreshold, uint256 _auctionTime, uint256 _minPriceMultiplier, uint256 _maxPriceMultiplier)`\n\nstrategy constructor\n\nthis will open a vault in the power token contract and store the vault ID\n\n### Parameters:\n\n- `address _wSqueethController`: power token controller address\n\n- `address _oracle`: oracle address\n\n- `address _weth`: weth address\n\n- `address _uniswapFactory`: uniswap factory address\n\n- `address _ethWSqueethPool`: eth:wSqueeth uniswap pool address\n\n- `uint256 _hedgeTimeThreshold`: hedge time threshold (seconds)\n\n- `uint256 _hedgePriceThreshold`: hedge price threshold (0.1*1e18 = 10%)\n\n- `uint256 _auctionTime`: auction duration (seconds)\n\n- `uint256 _minPriceMultiplier`: minimum auction price multiplier (0.9*1e18 = min auction price is 90% of twap)\n\n- `uint256 _maxPriceMultiplier`: maximum auction price multiplier (1.1*1e18 = max auction price is 110% of twap)\n\n## `receive()`\n\nreceive function to allow ETH transfer to this contract\n\n## `flashDeposit(uint256 _ethToDeposit, uint256 _ethToBorrow)`\n\nflash deposit into strategy\n\nthis function sells minted WSqueeth for _ethToBorrow\n\n### Parameters:\n\n- `uint256 _ethToDeposit`: ETH sent from depositor\n\n- `uint256 _ethToBorrow`: ETH to flashswap on uniswap\n\n## `flashWithdraw(uint256 _crabAmount, uint256 _maxEthToPay)`\n\nflash withdraw from strategy\n\nthis function will borrow wSqueeth amount and repay for selling some of the ETH collateral\n\n### Parameters:\n\n- `uint256 _crabAmount`: crab token amount to burn\n\n- `uint256 _maxEthToPay`: maximum ETH to pay\n\n## `deposit() → uint256, uint256`\n\ndeposit ETH into strategy\n\nprovide eth, return wSqueeth and strategy token\n\n### Return Values:\n\n- `` wSqueethToMint minted amount of wSqueeth\n\n- `` depositorCrabAmount minted amount of strategy token\n\n## `withdraw(uint256 _crabAmount, uint256 _wSqueethAmount)`\n\nwithdraw WETH from strategy\n\nprovide strategy tokens and wSqueeth, returns eth\n\n### Parameters:\n\n- `uint256 _crabAmount`: amount of crab token to burn\n\n- `uint256 _wSqueethAmount`: amount of wSqueeth to burn\n\n## `timeHedgeOnUniswap()`\n\nhedge startegy based on time threshold with uniswap arbing\n\n## `priceHedgeOnUniswap(uint256 _auctionTriggerTime)`\n\nhedge startegy based on price threshold with uniswap arbing\n\n## `timeHedge(bool _isStrategySellingWSqueeth, uint256 _limitPrice)`\n\nstrategy hedging based on time threshold\n\nneed to attach msg.value if buying WSqueeth\n\n### Parameters:\n\n- `bool _isStrategySellingWSqueeth`: sell or buy auction, true for sell auction\n\n- `uint256 _limitPrice`: hedger limit auction price, should be the max price when auction is sell auction, min price when it is a buy auction\n\n## `priceHedge(uint256 _auctionTriggerTime, bool _isStrategySellingWSqueeth, uint256 _limitPrice)`\n\nstrategy hedging based on price threshold\n\nneed to attach msg.value if buying WSqueeth\n\n### Parameters:\n\n- `uint256 _auctionTriggerTime`: timestamp where auction started\n\n## `checkPriceHedge(uint256 _auctionTriggerTime) → bool`\n\ncheck if hedging based on price threshold is allowed\n\n### Parameters:\n\n- `uint256 _auctionTriggerTime`: alleged timestamp where auction was triggered\n\n### Return Values:\n\n- `uint256` true if hedging is allowed\n\n## `checkTimeHedge() → bool, uint256`\n\ncheck if hedging based on time threshold is allowed\n\n### Return Values:\n\n- `` isTimeHedgeAllowed true if hedging is allowed\n\n- `` auctionTriggertime auction trigger timestamp\n\n## `getWsqueethFromCrabAmount(uint256 _crabAmount) → uint256`\n\nget wSqueeth debt amount associated with crab token amount\n\n_crabAmount strategy token amount\n\n### Return Values:\n\n- `uint256` wSqueeth amount\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/strategy/base/StrategyBase.md",
    "content": "# `StrategyBase`\n\nbase contract for PowerToken strategy\n\nStrategyBase contract\n\n## All Functions:\n\n- `constructor(address _powerTokenController, address _weth, string _name, string _symbol)`\n\n- `getStrategyVaultId()`\n\n- `getStrategyDebt()`\n\n- `getStrategyCollateral()`\n\n# Functions\n\n## `constructor(address _powerTokenController, address _weth, string _name, string _symbol)`\n\nconstructor for StrategyBase\n\nthis will open a vault in the power token contract and store the vault ID\n\n### Parameters:\n\n- `address _powerTokenController`: power token controller address\n\n- `address _weth`: weth token address\n\n- `string _name`: token name for strategy ERC20 token\n\n- `string _symbol`: token symbol for strategy ERC20 token\n\n## `getStrategyVaultId() → uint256`\n\nget power token strategy vault ID \n\n### Return Values:\n\n- `` vault ID\n\n## `getStrategyDebt() → uint256`\n\nget strategy debt amount\n\n### Return Values:\n\n- `` debt amount\n\n## `getStrategyCollateral() → uint256`\n\nget strategy collateral amount\n\n### Return Values:\n\n- `` collateral amount\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/strategy/base/StrategyFlashSwap.md",
    "content": "# `StrategyFlashSwap`\n\n## All Functions:\n\n- `constructor(address _factory)`\n\n- `uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes _data)`\n\n# Functions\n\n## `constructor(address _factory)`\n\nconstructor\n\n### Parameters:\n\n- `address _factory`: uniswap factory address\n\n## `uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes _data)`\n\nuniswap swap callback function for flashes\n\n### Parameters:\n\n- `int256 amount0Delta`: amount of token0\n\n- `int256 amount1Delta`: amount of token1\n\n- `bytes _data`: callback data encoded as SwapCallbackData struct\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/strategy/base/StrategyMath.md",
    "content": "# `StrategyMath`\n\n## All Functions:\n\n# Functions\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/test/ControllerTester.md",
    "content": "# `ControllerTester`\n\nuse this contract to confirm that funding is not charged twice if called in same block\n\n## All Functions:\n\n- `constructor(address _controller)`\n\n- `testDoubleFunding()`\n\n# Functions\n\n## `constructor(address _controller)`\n\n## `testDoubleFunding()`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/test/OracleTester.md",
    "content": "# `OracleTester`\n\nuse this contract to test how to get twap from exactly 1 timestamp\n\nSince we can't access block.timestamp offchain before sending the tx\n\n## All Functions:\n\n- `constructor(address _oracle)`\n\n- `testGetTwapSince(uint256 _sinceTimestamp, address _pool, address _base, address _quote)`\n\n- `testGetTwapSafeSince(uint256 _sinceTimestamp, address _pool, address _base, address _quote)`\n\n- `testGetWeightedTickSafe(uint256 _sinceTimestamp, address _pool)`\n\n- `testGetHistoricalTwapToNow(uint256 _startTimestamp, address _pool, address _base, address _quote)`\n\n- `testGetHistoricalTwap(uint256 _startTimestamp, uint256 _endTimestamp, address _pool, address _base, address _quote)`\n\n- `testToUint128(uint256 y)`\n\n# Functions\n\n## `constructor(address _oracle)`\n\n## `testGetTwapSince(uint256 _sinceTimestamp, address _pool, address _base, address _quote) → uint256`\n\n## `testGetTwapSafeSince(uint256 _sinceTimestamp, address _pool, address _base, address _quote) → uint256`\n\n## `testGetWeightedTickSafe(uint256 _sinceTimestamp, address _pool) → int24`\n\n## `testGetHistoricalTwapToNow(uint256 _startTimestamp, address _pool, address _base, address _quote) → uint256`\n\n## `testGetHistoricalTwap(uint256 _startTimestamp, uint256 _endTimestamp, address _pool, address _base, address _quote) → uint256`\n\n## `testToUint128(uint256 y) → uint128 z`\n"
  },
  {
    "path": "packages/hardhat/docs/contracts-documentation/test/VaultLibTester.md",
    "content": "# `VaultLibTester`\n\n## All Functions:\n\n- `getUniPositionBalances(address _positionManager, uint256 _tokenId, int24 _squeethPoolTick, bool _isWethToken0)`\n\n- `getLiquidity(uint160 sqrtRatioX96, int24 tickA, int24 tickB, uint256 amount0Desired, uint256 amount1Desired)`\n\n- `getLiquidityForAmount0(uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount0)`\n\n- `getLiquidityForAmount1(uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount1)`\n\n- `getAmountsForLiquidity(uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity)`\n\n# Functions\n\n## `getUniPositionBalances(address _positionManager, uint256 _tokenId, int24 _squeethPoolTick, bool _isWethToken0) → uint256 ethAmount, uint256 squeethAmount`\n\n## `getLiquidity(uint160 sqrtRatioX96, int24 tickA, int24 tickB, uint256 amount0Desired, uint256 amount1Desired) → uint128 liquidity`\n\nexpose this function so it's easier to test vault lib.\n\n## `getLiquidityForAmount0(uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount0) → uint128 liquidity`\n\n## `getLiquidityForAmount1(uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount1) → uint128 liquidity`\n\n## `getAmountsForLiquidity(uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity) → uint256 amount0, uint256 amount1`\n"
  },
  {
    "path": "packages/hardhat/env.example",
    "content": "# Supply an INFURA_KEY to deploy and run scripts\nINFURA_KEY=\n\n# Unit test gas report\nCOINMARKETCAP=\nREPORT_GAS=\n\n# For contract verification\nETHERSCAN_KEY="
  },
  {
    "path": "packages/hardhat/hardhat.config.ts",
    "content": "import \"@nomiclabs/hardhat-waffle\";\nimport \"@nomiclabs/hardhat-etherscan\";\nimport \"@typechain/hardhat\";\nimport \"@float-capital/solidity-coverage\" // fix compiler bug when abi encoder is enabled \nimport \"hardhat-contract-sizer\";\nimport \"hardhat-gas-reporter\";\nimport \"hardhat-prettier\";\nimport \"@tenderly/hardhat-tenderly\";\nimport \"hardhat-deploy\";\nimport \"@eth-optimism/hardhat-ovm\";\nimport \"@nomiclabs/hardhat-ethers\";\nimport { HardhatUserConfig } from \"hardhat/config\";\nimport * as dotenv from 'dotenv'\n\n// Import Tasks\nimport \"./tasks/default\";\nimport './tasks/addSqueethLiquidity'\nimport './tasks/addWethLiquidity'\nimport './tasks/buySqueeth'\nimport './tasks/buyWeth'\nimport './tasks/sellWeth'\nimport './tasks/sellSqueeth'\nimport './tasks/increaseSlot'\n\n// Load env variables\ndotenv.config()\nconst InfuraKey = process.env.INFURA_KEY\nconst fs = require(\"fs\");\n\n/*\n  📡 This is where you configure your deploy configuration for 🏗 scaffold-eth\n\n  check out `packages/scripts/deploy.js` to customize your deployment\n\n  out of the box it will auto deploy anything in the `contracts` folder and named *.sol\n  plus it will use *.args for constructor args\n*/\n\n//\n// Select the network you want to deploy to here:\n//\nconst defaultNetwork = \"localhost\";\n\nfunction mnemonic() {\n  try {\n    return fs.readFileSync(\"./mnemonic.txt\").toString().trim();\n  } catch (e) {\n    if (defaultNetwork !== \"localhost\") {\n      console.log(\n        \"☢️ WARNING: No mnemonic file created for a deploy account. Try `yarn run generate` and then `yarn run account`.\"\n      );\n    }\n  }\n  return \"\";\n}\n\nconst UNISWAP_SETTING = {\n  version: \"0.7.6\",\n  settings: {\n    optimizer: {\n      enabled: true,\n      runs: 800,\n    },\n  },\n};\n\nconst accounts = process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : { mnemonic: mnemonic() }\n\nconst config: HardhatUserConfig = {\n  defaultNetwork,\n  networks: {\n    hardhat: {\n      initialBaseFeePerGas: 0,\n      saveDeployments: false, // only used in cicd to test deployments\n      mining: {\n        auto: true\n      },\n      forking: {\n        enabled: process.env.MAINNET_FORK === 'true',\n        url: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,\n        blockNumber: 14845140\n      },\n      accounts: {\n        accountsBalance: '1000000000000000000000000000'\n      },\n    },\n    localhost: {\n      url: \"http://localhost:8545\",\n      /*\n        notice no mnemonic here? it will just use account 0 of the hardhat node to deploy\n        (you can put in a mnemonic here to set the deployer locally)\n      */\n    },\n    rinkeby: {\n      url: `https://rinkeby.infura.io/v3/${InfuraKey}`, // <---- YOUR INFURA ID! (or it won't work)\n      accounts,\n    },\n    goerli: {\n      url: `https://goerli.infura.io/v3/${InfuraKey}`, // <---- YOUR INFURA ID! (or it won't work)\n      accounts,\n    },\n    kovan: {\n      url: `https://kovan.infura.io/v3/${InfuraKey}`, // <---- YOUR INFURA ID! (or it won't work)\n      accounts,\n    },\n    mainnet: {\n      url: `https://mainnet.infura.io/v3/${InfuraKey}`, // <---- YOUR INFURA ID! (or it won't work)\n      accounts,\n    },\n    ropsten: {\n      url: `https://ropsten.infura.io/v3/${InfuraKey}`, // <---- YOUR INFURA ID! (or it won't work)\n      accounts,\n      gas: 8000000000000000\n    },\n    xdai: {\n      url: \"https://rpc.xdaichain.com/\",\n      gasPrice: 1000000000,\n      accounts,\n    },\n    matic: {\n      url: \"https://rpc-mainnet.maticvigil.com/\",\n      gasPrice: 1000000000,\n      accounts,\n    },\n    rinkebyArbitrum: {\n      url: \"https://rinkeby.arbitrum.io/rpc\",\n      gasPrice: 30000000, // 0.03 gwei\n      gas: 30_000_000,\n      accounts,\n      companionNetworks: {\n        l1: \"rinkeby\",\n      },\n    },\n    localArbitrum: {\n      url: \"http://localhost:8547\",\n      gasPrice: 0,\n      accounts,\n      companionNetworks: {\n        l1: \"localArbitrumL1\",\n      },\n    },\n    localArbitrumL1: {\n      url: \"http://localhost:7545\",\n      gasPrice: 0,\n      accounts,\n      companionNetworks: {\n        l2: \"localArbitrum\",\n      },\n    },\n    kovanOptimism: {\n      url: \"https://kovan.optimism.io\",\n      gasPrice: 0,\n      accounts,\n      ovm: true,\n      companionNetworks: {\n        l1: \"kovan\",\n      },\n    },\n    localOptimism: {\n      url: \"http://localhost:8545\",\n      gasPrice: 0,\n      accounts,\n      ovm: true,\n      companionNetworks: {\n        l1: \"localOptimismL1\",\n      },\n    },\n    localOptimismL1: {\n      url: \"http://localhost:9545\",\n      gasPrice: 0,\n      accounts,\n      companionNetworks: {\n        l2: \"localOptimism\",\n      },\n    },\n    localAvalanche: {\n      url: \"http://localhost:9650/ext/bc/C/rpc\",\n      gasPrice: 225000000000,\n      chainId: 43112,\n      accounts,\n    },\n    fujiAvalanche: {\n      url: \"https://api.avax-test.network/ext/bc/C/rpc\",\n      gasPrice: 225000000000,\n      chainId: 43113,\n      accounts,\n    },\n    mainnetAvalanche: {\n      url: \"https://api.avax.network/ext/bc/C/rpc\",\n      gasPrice: 225000000000,\n      chainId: 43114,\n      accounts,\n    },\n  },\n  solidity: {\n    compilers: [\n      UNISWAP_SETTING,\n    ],\n    overrides: {\n      \"contracts/mocks/MockTimelock.sol\": {\n        version: \"0.8.10\",\n      },\n      \"contracts/strategy/timelock/Timelock.sol\": {\n        version: \"0.8.10\",\n      },\n      \"contracts/strategy/timelock/SafeMath.sol\": {\n        version: \"0.8.10\",\n      }\n    }\n  },\n  ovm: {\n    solcVersion: \"0.7.6\",\n  },\n  namedAccounts: {\n    deployer: {\n      default: 0, // here this will by default take the first account as deployer\n    },\n  },\n  typechain: {\n    outDir: \"typechain\",\n    target: \"ethers-v5\",\n  },\n  gasReporter: {\n    currency: \"USD\",\n    gasPrice: 100,\n    coinmarketcap: process.env.COINMARKETCAP,\n    enabled: process.env.REPORT_GAS === \"true\",\n  },\n  etherscan: {\n    apiKey: process.env.ETHERSCAN_KEY\n  }\n};\n\nexport default config;\n"
  },
  {
    "path": "packages/hardhat/package.json",
    "content": "{\n  \"name\": \"@squeeth/hardhat\",\n  \"version\": \"1.1.0\",\n  \"main\": \"index.js\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@typescript-eslint/parser\": \"^4.29.1\",\n    \"eslint\": \"^7.5.0\",\n    \"eslint-config-airbnb\": \"^18.2.0\",\n    \"eslint-config-prettier\": \"^6.11.0\",\n    \"eslint-plugin-babel\": \"^5.3.1\",\n    \"eslint-plugin-prettier\": \"^3.4.0\",\n    \"sol2uml\": \"^1.1.29\",\n    \"solc-0.7\": \"npm:solc@^0.7.6\",\n    \"solidity-docgen\": \"^0.5.14\",\n    \"typescript\": \"^4.3.5\"\n  },\n  \"dependencies\": {\n    \"@eth-optimism/hardhat-ovm\": \"^0.2.2\",\n    \"@float-capital/solidity-coverage\": \"^0.7.17\",\n    \"@nomiclabs/hardhat-ethers\": \"npm:hardhat-deploy-ethers\",\n    \"@nomiclabs/hardhat-etherscan\": \"^3.0.4\",\n    \"@nomiclabs/hardhat-waffle\": \"^2.0.0\",\n    \"@openzeppelin/contracts\": \"v3.4.2-solc-0.7\",\n    \"@openzeppelin/contracts-upgradeable\": \"v3.4.2-solc-0.7\",\n    \"@tenderly/hardhat-tenderly\": \"^1.0.10\",\n    \"@typechain/ethers-v5\": \"^7.0.1\",\n    \"@typechain/hardhat\": \"^2.3.0\",\n    \"@types/mocha\": \"^9.0.0\",\n    \"@uniswap/v3-core\": \"^1.0.0\",\n    \"@uniswap/v3-periphery\": \"^1.1.1\",\n    \"bignumber.js\": \"^9.0.1\",\n    \"chai\": \"^4.2.0\",\n    \"chalk\": \"^4.1.0\",\n    \"dotenv\": \"^10.0.0\",\n    \"ethereum-waffle\": \"^3.1.1\",\n    \"ethereumjs-util\": \"^7.1.5\",\n    \"ethers\": \"^5.3.0\",\n    \"hardhat\": \"2.10.2\",\n    \"hardhat-contract-sizer\": \"^2.0.3\",\n    \"hardhat-deploy\": \"^0.8.6\",\n    \"hardhat-gas-reporter\": \"^1.0.4\",\n    \"hardhat-prettier\": \"^0.0.1\",\n    \"node-watch\": \"^0.7.0\",\n    \"prettier\": \"^2.3.2\",\n    \"prettier-plugin-solidity\": \"^1.0.0-beta.17\",\n    \"qrcode-terminal\": \"^0.12.0\",\n    \"ramda\": \"^0.27.1\",\n    \"solidity-coverage\": \"^0.7.16\",\n    \"ts-node\": \"^10.2.0\",\n    \"typechain\": \"^5.1.2\"\n  },\n  \"scripts\": {\n    \"chain\": \"hardhat node --network hardhat --no-deploy\",\n    \"test\": \"TS_NODE_TRANSPILE_ONLY=1 npx hardhat test --network hardhat\",\n    \"test:unit\": \"TS_NODE_TRANSPILE_ONLY=1 npx hardhat test --network hardhat test/unit-tests/**.ts test/unit-tests/*/**.ts\",\n    \"test:crab-unit\": \"TS_NODE_TRANSPILE_ONLY=1 npx hardhat test --network hardhat test/unit-tests/strategy/**.ts\",\n    \"test:crab-integration\": \"TS_NODE_TRANSPILE_ONLY=1 npx hardhat test --network hardhat test/integration-tests/crabv2/*.ts\",\n    \"test:e2e\": \"TS_NODE_TRANSPILE_ONLY=1 MAINNET_FORK=true npx hardhat test --network hardhat test/e2e/**.ts test/e2e/*/**.ts\",\n    \"compile\": \"hardhat compile\",\n    \"deploy\": \"hardhat deploy\",\n    \"postdeploy\": \"hardhat run scripts/publish.js\",\n    \"watch\": \"node scripts/watch.js\",\n    \"accounts\": \"hardhat accounts\",\n    \"balance\": \"hardhat balance\",\n    \"send\": \"hardhat send\",\n    \"generate\": \"hardhat generate\",\n    \"account\": \"hardhat account\",\n    \"lint:contracts\": \"prettier --write contracts/**/*.sol\",\n    \"lint:tests\": \"eslint --fix test/**/*.ts --quiet\",\n    \"lint:ts\": \"eslint **/*.ts --fix --quiet\",\n    \"lint\": \"yarn lint:contracts && yarn lint:tests && yarn lint:ts\",\n    \"lint:check:contracts\": \"prettier --check contracts/**/*.sol\",\n    \"lint:check:tests\": \"eslint test/**/*.ts\",\n    \"lint:check:ts\": \"eslint **/*.ts\",\n    \"lint:check\": \"yarn lint:check:contracts && yarn lint:check:tests && yarn lint:check:ts\",\n    \"coverage\": \"hardhat coverage --testfiles 'test/**/*.ts' --network hardhat\",\n    \"docify\": \"node scripts/docs/docify.js\",\n    \"doc:uml:core\": \"sol2uml ./contracts/core -f png -o ./docs/uml/Core.png\",\n    \"doc:control-flow:core\": \"surya graph -m contracts/core/*.sol | dot -Tpng > ./docs/control-flow/Core.png\"\n  },\n  \"resolutions\": {\n    \"assemblyscript\": \"git+https://github.com/AssemblyScript/assemblyscript.git#v0.6\"\n  }\n}"
  },
  {
    "path": "packages/hardhat/scripts/deploy.js",
    "content": "/* eslint no-use-before-define: \"warn\" */\nconst fs = require(\"fs\");\nconst chalk = require(\"chalk\");\nconst { config, ethers, tenderly, run } = require(\"hardhat\");\nconst { utils } = require(\"ethers\");\nconst R = require(\"ramda\");\n\n/*\n\n _______ _________ _______  _______\n(  ____ \\\\__   __/(  ___  )(  ____ )\n| (    \\/   ) (   | (   ) || (    )|\n| (_____    | |   | |   | || (____)|\n(_____  )   | |   | |   | ||  _____)\n      ) |   | |   | |   | || (\n/\\____) |   | |   | (___) || )\n\\_______)   )_(   (_______)|/\n\nThis deploy script is no longer in use, but is left for reference purposes!\n\nscaffold-eth now uses hardhat-deploy to manage deployments, see the /deploy folder\nAnd learn more here: https://www.npmjs.com/package/hardhat-deploy\n\n*/\n\nconst main = async () => {\n  console.log(\"\\n\\n 📡 Deploying...\\n\");\n\n  const yourContract = await deploy(\"YourContract\"); // <-- add in constructor args like line 19 vvvv\n  // use for local token bridging\n  // const mockToken = await deploy(\"MockERC20\") // <-- add in constructor args like line 19 vvvv\n\n  // const yourContract = await ethers.getContractAt('YourContract', \"0xaAC799eC2d00C013f1F11c37E654e59B0429DF6A\") //<-- if you want to instantiate a version of a contract at a specific address!\n  // const secondContract = await deploy(\"SecondContract\")\n\n  // const exampleToken = await deploy(\"ExampleToken\")\n  // const examplePriceOracle = await deploy(\"ExamplePriceOracle\")\n  // const smartContractWallet = await deploy(\"SmartContractWallet\",[exampleToken.address,examplePriceOracle.address])\n\n  /*\n  //If you want to send value to an address from the deployer\n  const deployerWallet = ethers.provider.getSigner()\n  await deployerWallet.sendTransaction({\n    to: \"0x34aA3F359A9D614239015126635CE7732c18fDF3\",\n    value: ethers.utils.parseEther(\"0.001\")\n  })\n  */\n\n  /*\n  //If you want to send some ETH to a contract on deploy (make your constructor payable!)\n  const yourContract = await deploy(\"YourContract\", [], {\n  value: ethers.utils.parseEther(\"0.05\")\n  });\n  */\n\n  /*\n  //If you want to link a library into your contract:\n  // reference: https://github.com/austintgriffith/scaffold-eth/blob/using-libraries-example/packages/hardhat/scripts/deploy.js#L19\n  const yourContract = await deploy(\"YourContract\", [], {}, {\n   LibraryName: **LibraryAddress**\n  });\n  */\n\n  // If you want to verify your contract on tenderly.co (see setup details in the scaffold-eth README!)\n  /*\n  await tenderlyVerify(\n    {contractName: \"YourContract\",\n     contractAddress: yourContract.address\n  })\n  */\n\n  console.log(\n    \" 💾  Artifacts (address, abi, and args) saved to: \",\n    chalk.blue(\"packages/hardhat/artifacts/\"),\n    \"\\n\\n\"\n  );\n};\n\nconst deploy = async (\n  contractName,\n  _args = [],\n  overrides = {},\n  libraries = {}\n) => {\n  console.log(` 🛰  Deploying: ${contractName}`);\n\n  const contractArgs = _args || [];\n  const contractArtifacts = await ethers.getContractFactory(contractName, {\n    libraries,\n  });\n  const deployed = await contractArtifacts.deploy(...contractArgs, overrides);\n  const encoded = abiEncodeArgs(deployed, contractArgs);\n  fs.writeFileSync(`artifacts/${contractName}.address`, deployed.address);\n\n  let extraGasInfo = \"\";\n  if (deployed && deployed.deployTransaction) {\n    const gasUsed = deployed.deployTransaction.gasLimit.mul(\n      deployed.deployTransaction.gasPrice\n    );\n    extraGasInfo = `${utils.formatEther(gasUsed)} ETH, tx hash ${\n      deployed.deployTransaction.hash\n    }`;\n  }\n\n  console.log(\n    \" 📄\",\n    chalk.cyan(contractName),\n    \"deployed to:\",\n    chalk.magenta(deployed.address)\n  );\n  console.log(\" ⛽\", chalk.grey(extraGasInfo));\n\n  await tenderly.persistArtifacts({\n    name: contractName,\n    address: deployed.address,\n  });\n\n  if (!encoded || encoded.length <= 2) return deployed;\n  fs.writeFileSync(`artifacts/${contractName}.args`, encoded.slice(2));\n\n  return deployed;\n};\n\n// ------ utils -------\n\n// abi encodes contract arguments\n// useful when you want to manually verify the contracts\n// for example, on Etherscan\nconst abiEncodeArgs = (deployed, contractArgs) => {\n  // not writing abi encoded args if this does not pass\n  if (\n    !contractArgs ||\n    !deployed ||\n    !R.hasPath([\"interface\", \"deploy\"], deployed)\n  ) {\n    return \"\";\n  }\n  const encoded = utils.defaultAbiCoder.encode(\n    deployed.interface.deploy.inputs,\n    contractArgs\n  );\n  return encoded;\n};\n\n// checks if it is a Solidity file\nconst isSolidity = (fileName) =>\n  fileName.indexOf(\".sol\") >= 0 &&\n  fileName.indexOf(\".swp\") < 0 &&\n  fileName.indexOf(\".swap\") < 0;\n\nconst readArgsFile = (contractName) => {\n  let args = [];\n  try {\n    const argsFile = `./contracts/${contractName}.args`;\n    if (!fs.existsSync(argsFile)) return args;\n    args = JSON.parse(fs.readFileSync(argsFile));\n  } catch (e) {\n    console.log(e);\n  }\n  return args;\n};\n\nfunction sleep(ms) {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// If you want to verify on https://tenderly.co/\nconst tenderlyVerify = async ({ contractName, contractAddress }) => {\n  const tenderlyNetworks = [\n    \"kovan\",\n    \"goerli\",\n    \"mainnet\",\n    \"rinkeby\",\n    \"ropsten\",\n    \"matic\",\n    \"mumbai\",\n    \"xDai\",\n    \"POA\",\n  ];\n  const targetNetwork = process.env.HARDHAT_NETWORK || config.defaultNetwork;\n\n  if (tenderlyNetworks.includes(targetNetwork)) {\n    console.log(\n      chalk.blue(\n        ` 📁 Attempting tenderly verification of ${contractName} on ${targetNetwork}`\n      )\n    );\n\n    await tenderly.persistArtifacts({\n      name: contractName,\n      address: contractAddress,\n    });\n\n    const verification = await tenderly.verify({\n      name: contractName,\n      address: contractAddress,\n      network: targetNetwork,\n    });\n\n    return verification;\n  }\n  console.log(\n    chalk.grey(` 🧐 Contract verification not supported on ${targetNetwork}`)\n  );\n};\n\nmain()\n  .then(() => process.exit(0))\n  .catch((error) => {\n    console.error(error);\n    process.exit(1);\n  });\n"
  },
  {
    "path": "packages/hardhat/scripts/docs/docify.js",
    "content": "const NODE_DIR     = \"node_modules\";\nconst INPUT_DIR    = \"contracts\";\nconst CONFIG_DIR   = \"docs\";\nconst OUTPUT_DIR   = \"docs/contracts-documentation\";\nconst README_FILE  = \"README.md\";\nconst SUMMARY_FILE = \"SUMMARY.md\";\nconst EXCLUDE_LIST = [\"packages\", \"interfaces\", \"mocks\", \"test\", \"external\", \"import\"]\n\nconst fs        = require(\"fs\");\nconst path      = require(\"path\");\nconst spawnSync = require(\"child_process\").spawnSync;\n\nconst relativePath = path.relative(path.dirname(SUMMARY_FILE), OUTPUT_DIR);\n\nfunction exclude(pathName) {\n    for(i = 0; i < EXCLUDE_LIST.length; i++) {\n        if(pathName.includes(EXCLUDE_LIST[i])) {\n            return true;\n        }\n    }\n    return false;\n}\n\nfunction scan(pathName, indentation) {\n    if (!exclude(pathName)) {\n        if (fs.lstatSync(pathName).isDirectory()) {\n            fs.appendFileSync(SUMMARY_FILE, indentation + \"* \" + path.basename(pathName) + \"\\n\");\n            for (const fileName of fs.readdirSync(pathName))\n                scan(pathName + \"/\" + fileName, indentation + \"  \");\n        }\n        else if (pathName.endsWith(\".sol\")) {\n            const text = path.basename(pathName).slice(0, -4);\n            const link = pathName.slice(INPUT_DIR.length, -4);\n            fs.appendFileSync(SUMMARY_FILE, indentation + \"* [\" + text + \"](\" + relativePath + link + \".md)\\n\");\n        }\n    }\n}\n\nfunction fix(pathName) {\n    if (fs.lstatSync(pathName).isDirectory()) {\n        for (const fileName of fs.readdirSync(pathName))\n            fix(pathName + \"/\" + fileName);\n    }\n    else if (pathName.endsWith(\".md\")) {\n        const lines = fs.readFileSync(pathName, {encoding: \"utf8\"}).split(\"\\r\").join(\"\").split(\"\\n\");\n        fs.unlinkSync(pathName)\n        fs.writeFileSync(pathName, lines.filter(line => line.trim().length > 0).join(\"\\n\\n\") + \"\\n\");\n    }\n}\n\nfs.writeFileSync (SUMMARY_FILE, \"# Summary\\n\");\nfs.writeFileSync (\".gitbook.yaml\", \"root: ./\\n\");\nfs.appendFileSync(\".gitbook.yaml\", \"structure:\\n\");\nfs.appendFileSync(\".gitbook.yaml\", \"  readme: \" + README_FILE + \"\\n\");\nfs.appendFileSync(\".gitbook.yaml\", \"  summary: \" + SUMMARY_FILE + \"\\n\");\n\nscan(INPUT_DIR, \"\");\n\nconst args = [\n    NODE_DIR + \"/solidity-docgen/dist/cli.js\",\n    \"--input=\"         + INPUT_DIR,\n    \"--output=\"        + OUTPUT_DIR,\n    \"--templates=\"     + CONFIG_DIR,\n    '--solc-module='   + 'solc-0.7',\n    \"--solc-settings=\" + JSON.stringify({optimizer: {enabled: true, runs: 200},})\n];\n\nconst result = spawnSync(\"node\", args, {stdio: [\"inherit\", \"inherit\", \"pipe\"]});\nif (result.stderr.length > 0)\n    throw new Error(result.stderr);\n\nfix(OUTPUT_DIR);\n"
  },
  {
    "path": "packages/hardhat/scripts/etherscan_verify.sh",
    "content": "# HOW TO USE:\n# Run the following shell script using: KEY=ur_keeeeey ./etherscan_verify.sh\n\n#!/bin/bash\n\netherscanKey=$KEY\n\necho \"Using the current etherscan key: ${etherscanKey}\" \n\n$(npm bin)/hardhat etherscan-verify --api-key $etherscanKey"
  },
  {
    "path": "packages/hardhat/scripts/publish.js",
    "content": "/* eslint-disable prettier/prettier */\nconst fs = require(\"fs\");\nconst chalk = require(\"chalk\");\n\nconst graphDir = \"../subgraph\";\nconst deploymentsDir = \"./deployments\";\nconst publishDir = \"../react-app/src/contracts\";\n\nfunction publishContract(contractName, networkName) {\n  try {\n    let contract = fs.readFileSync(`${deploymentsDir}/${networkName}/${contractName}.json`).toString();\n    contract = JSON.parse(contract);\n    const graphConfigPath = `${graphDir}/config/${networkName}-config.json`;\n    let graphConfig;\n    try {\n      if (fs.existsSync(graphConfigPath)) {\n        graphConfig = fs.readFileSync(graphConfigPath).toString();\n      } else {\n        graphConfig = \"{}\";\n      }\n    } catch (e) {\n      console.log(e);\n    }\n\n    graphConfig = JSON.parse(graphConfig);\n    graphConfig.network = networkName;\n    graphConfig[contractName] = contract.address;\n    graphConfig[`${contractName}-start-block`] = contract.receipt.blockNumber\n\n    console.log(contract.receipt.blockNumber)\n\n    const folderPath = graphConfigPath.replace(`/${networkName}-config.json`, \"\");\n    if (!fs.existsSync(folderPath)) {\n      fs.mkdirSync(folderPath);\n    }\n    fs.writeFileSync(graphConfigPath, JSON.stringify(graphConfig, null, 2));\n    if (!fs.existsSync(`${graphDir}/abis`)) fs.mkdirSync(`${graphDir}/abis`);\n    fs.writeFileSync(`${graphDir}/abis/${contractName}.json`, JSON.stringify(contract.abi, null, 2));\n\n    // Hardhat Deploy writes a file with all ABIs in react-app/src/contracts/contracts.json\n    // If you need the bytecodes and/or you want one file per ABIs, un-comment the following block.\n    // Write the contracts ABI, address and bytecodes in case the front-end needs them\n    // fs.writeFileSync(\n    //   `${publishDir}/${contractName}.address.js`,\n    //   `module.exports = \"${contract.address}\";`\n    // );\n    // fs.writeFileSync(\n    //   `${publishDir}/${contractName}.abi.js`,\n    //   `module.exports = ${JSON.stringify(contract.abi, null, 2)};`\n    // );\n    // fs.writeFileSync(\n    //   `${publishDir}/${contractName}.bytecode.js`,\n    //   `module.exports = \"${contract.bytecode}\";`\n    // );\n\n    return true;\n  } catch (e) {\n    console.log(\"Failed to publish \" + chalk.red(contractName) + \" to the subgraph.\");\n    console.log(e);\n    return false;\n  }\n}\n\nasync function main() {\n  const directories = fs.readdirSync(deploymentsDir);\n  directories.forEach(function (directory) {\n    const files = fs.readdirSync(`${deploymentsDir}/${directory}`);\n    files.forEach(function (file) {\n      if (file.indexOf(\".json\") >= 0) {\n        const contractName = file.replace(\".json\", \"\");\n        publishContract(contractName, directory);\n      }\n    });\n  });\n  console.log(\"✅  Published contracts to the subgraph package.\");\n}\nmain()\n  .then(() => process.exit(0))\n  .catch((error) => {\n    console.error(error);\n    process.exit(1);\n  });\n"
  },
  {
    "path": "packages/hardhat/scripts/start_hardhat_fork.sh",
    "content": "# HOW TO USE:\n# Run the following shell script using: INFURA_KEY=ur_keeeeey ./start_hardhat_fork.sh\n# To stop hardhat fork, run ./stop_hardhat_fork.sh\n\n#!/bin/bash\n\ninfuraKey=$INFURA_KEY\n\necho \"Using the current infura key: ${infuraKey}\" \n\n$(npm bin)/hardhat node --no-deploy --network hardhat --fork https://mainnet.infura.io/v3/$infuraKey"
  },
  {
    "path": "packages/hardhat/scripts/stop_hardhat_fork.sh",
    "content": "#!/bin/bash\n\nkill $(lsof -t -i:8545)"
  },
  {
    "path": "packages/hardhat/scripts/watch.js",
    "content": "const watch = require(\"node-watch\");\nconst { exec } = require(\"child_process\");\n\nconst run = () => {\n  console.log(\"🛠  Compiling & Deploying...\");\n  exec(\"yarn deploy\", function (error, stdout, stderr) {\n    console.log(stdout);\n    if (error) console.log(error);\n    if (stderr) console.log(stderr);\n  });\n};\n\nconsole.log(\"🔬 Watching Contracts...\");\nwatch(\"./contracts\", { recursive: true }, function (evt, name) {\n  console.log(\"%s changed.\", name);\n  run();\n});\nrun();\n"
  },
  {
    "path": "packages/hardhat/tasks/addSqueethLiquidity.ts",
    "content": "import { task, types } from \"hardhat/config\";\nimport \"@nomiclabs/hardhat-waffle\";\nimport { getWETH, getUniswapDeployments } from './utils'\n\nconst tickSpace = 60\n\nconst estimated2xTickDelta = 6960 // 1.0001 ^ 6960 ~= 2. this number need to be dividable by 60\n\n// eslint-disable-next-line\nconst estimated1_5xTickDelta = 4020 // 1.0001 ^ 4020 ~= 1.5 this number need to be dividable by 60\n\n// Example execution\n/**\n  npx hardhat addSqueethLiquidity --network ropsten --wsqueeth-amount 0.0004 --collateral-amount 2 --base-price 3300 --range 2x\n */\ntask(\"addSqueethLiquidity\", \"Add liquidity to wsqueeth pool\")\n  .addParam('wsqueethAmount', 'amount of wsqueeth minting to add liquidity', '10', types.string)\n  .addParam('collateralAmount', 'amount used as collateral to mint squeeth', '6', types.string)\n  .addParam('basePrice', 'estimated wsqueeth/weth price', '0.3', types.string)\n  .addParam('range', 'either full, 1.5x or 2x', '1.5x', types.string)\n  .setAction(async ({\n    wsqueethAmount,\n    collateralAmount,\n    basePrice,\n    range\n  }, hre) => {\n\n  const { getNamedAccounts, ethers, network } = hre;\n  \n  const { deployer } = await getNamedAccounts();\n  const { positionManager, uniswapFactory } = await getUniswapDeployments(ethers, deployer, network.name)\n\n  const controller = await ethers.getContract(\"Controller\", deployer);\n  const wsqueeth = await ethers.getContract(\"WPowerPerp\", deployer);\n  const weth = await getWETH(ethers, deployer, network.name)\n\n  const isWethToken0 = parseInt(weth.address, 16) < parseInt(wsqueeth.address, 16)\n  const token0 = isWethToken0 ? weth.address : wsqueeth.address\n  const token1 = isWethToken0 ? wsqueeth.address : weth.address\n\n  const poolAddr = await uniswapFactory.getPool(token0, token1, 3000)\n  console.log(`Adding liquidity to squeeth pool: ${poolAddr}`)\n\n  const poolContract = await ethers.getContractAt(\"IUniswapV3Pool\", poolAddr)\n  const {tick} = await poolContract.slot0()\n\n  const squeethPriceInETH = parseFloat(basePrice)\n\n  console.log(`estimated Squeeth Price in ETH: ${squeethPriceInETH}`)\n  \n  const liquidityWsqueethAmount = ethers.utils.parseEther(wsqueethAmount) \n  const wethAmount = parseFloat(wsqueethAmount) * squeethPriceInETH\n  const liquidityWethAmount = ethers.utils.parseEther(wethAmount.toString()) \n  \n  let wsqueethBalance = await wsqueeth.balanceOf(deployer)\n  let wethBalance = await weth.balanceOf(deployer)\n\n  if (wethBalance.lt(liquidityWethAmount)) {\n    const tx = await weth.deposit({value: liquidityWethAmount, from: deployer})\n    await ethers.provider.waitForTransaction(tx.hash, 1)\n    wethBalance = await weth.balanceOf(deployer)\n  }\n\n  if (wsqueethBalance.lt(liquidityWsqueethAmount)) {\n    console.log(`Minting ${wsqueethAmount} rSqueeth amount of wsqueeth with ${collateralAmount} ETH`)\n    const tx = await controller.mintWPowerPerpAmount(0, liquidityWsqueethAmount, 0, {value: ethers.utils.parseEther(collateralAmount)}) \n    await ethers.provider.waitForTransaction(tx.hash, 1)\n    wsqueethBalance = await wsqueeth.balanceOf(deployer)\n  }\n\n  // approve weth and wsqueeth to be used by position manager\n  const wethAllowance = await weth.allowance(deployer, positionManager.address)\n  if (wethAllowance.lt(liquidityWethAmount)) {\n    console.log(`Approving weth...`)\n    const tx = await weth.approve(positionManager.address, ethers.constants.MaxUint256)\n    await ethers.provider.waitForTransaction(tx.hash, 1)\n  }\n\n  const wsqueethAllowance = await wsqueeth.allowance(deployer, positionManager.address)\n  if (wsqueethAllowance.lt(liquidityWsqueethAmount)) {\n    console.log(`Approving wsqueeth...`)\n    const tx = await wsqueeth.approve(positionManager.address, ethers.constants.MaxUint256)\n    await ethers.provider.waitForTransaction(tx.hash, 1)\n  }\n\n  let tickLower = 0\n  let tickUpper = 0\n  if (range === 'full') {\n    tickLower = -887220\n    tickUpper = 887220\n  } else {\n    let tickDelta = 0\n    if (range === '2x') {\n      tickDelta = estimated2xTickDelta\n      console.log(`using tick delta for 2x: ${tickDelta}`)\n    } else {\n      // eslint-disable-next-line\n      tickDelta = estimated1_5xTickDelta\n      console.log(`using tick delta for 1.5x: ${tickDelta}`)\n    }\n    const midTick = Math.floor(tick / tickSpace) * tickSpace\n    tickUpper = midTick + tickDelta\n    tickLower = midTick - tickDelta\n    console.log(`Using tick range: ${tickLower} - ${tickUpper}`)\n  }\n\n  const mintParam = {\n    token0,\n    token1,\n    fee: 3000,\n    tickLower,\n    tickUpper,\n    amount0Desired: isWethToken0 ? liquidityWethAmount : liquidityWsqueethAmount,\n    amount1Desired: isWethToken0 ? liquidityWsqueethAmount : liquidityWethAmount,\n    amount0Min: 0,\n    amount1Min: 0,\n    recipient: deployer,// address\n    deadline: Math.floor(Date.now() / 1000 + 86400),// uint256\n  }\n\n  const tx = await positionManager.mint(mintParam)\n  console.log(`mint tx ${tx.hash}`)\n\n});\n\n"
  },
  {
    "path": "packages/hardhat/tasks/addWethLiquidity.ts",
    "content": "import { task, types } from \"hardhat/config\";\nimport \"@nomiclabs/hardhat-waffle\";\nimport { utils, BigNumber } from \"ethers\";\nimport { getWETH, getUniswapDeployments, getUSDC } from './utils'\n\nconst { formatEther, parseEther } = utils\n\n// Example execution\n/**\n npx hardhat addWethLiquidity --network ropsten --weth-amount 0.5 --base-price 3500\n */\ntask(\"addWethLiquidity\", \"Add liquidity to WETH/DAI pool\")\n  .addParam('wethAmount', 'amount weth', '0.5', types.string)\n  .addParam('basePrice', 'estimated wsqueeth/weth price', 3000, types.int)\n  .setAction(async ({\n    wethAmount,\n    basePrice\n  }, hre) => {\n\n  const { getNamedAccounts, ethers, network } = hre;\n\n  if (network.name === 'mainnet') {\n    throw Error('This script is not supposed to be used on mainnet')\n  }\n  \n  const { deployer } = await getNamedAccounts();\n  const { positionManager, uniswapFactory } = await getUniswapDeployments(ethers, deployer, network.name)\n\n  const usdc = await getUSDC(ethers, deployer, network.name)\n  const weth = await getWETH(ethers, deployer, network.name)\n\n  const isWethToken0 = parseInt(weth.address, 16) < parseInt(usdc.address, 16)\n  const token0 = isWethToken0 ? weth.address : usdc.address\n  const token1 = isWethToken0 ? usdc.address : weth.address\n\n  // get current spot price form the pool\n  const poolAddr = await uniswapFactory.getPool(token0, token1, 3000)\n\n  console.log(`Adding liquidity to WETH/DAI pool: ${poolAddr}`)\n  console.log(`WETH Price in USDC: ${basePrice}`)\n  \n  const wethLiquidityAmount = parseEther(wethAmount)\n  let usdcLiquidityAmount = wethLiquidityAmount.mul(basePrice)\n  const usdcDecimals = 6\n  const wethDecimals = 18\n  \n  usdcLiquidityAmount = usdcLiquidityAmount.div(BigNumber.from(10).pow(wethDecimals-usdcDecimals))\n  \n\n  \n  const daiBalance = await usdc.balanceOf(deployer)\n  let wethBalance = await weth.balanceOf(deployer)\n\n  if (wethBalance.lt(wethLiquidityAmount)) {\n    const tx = await weth.deposit({value: wethLiquidityAmount.toString(), from: deployer})\n    await ethers.provider.waitForTransaction(tx.hash, 1)\n    wethBalance = await weth.balanceOf(deployer)\n  }\n\n  if (daiBalance.lt(usdcLiquidityAmount)) {\n    console.log(`Minting ${formatEther(usdcLiquidityAmount)} USDC`)\n    const tx = await usdc.mint(deployer, usdcLiquidityAmount) \n    await ethers.provider.waitForTransaction(tx.hash, 1)\n  }\n\n  // approve weth and wsqueeth to be used by position manager\n  const wethAllowance = await weth.allowance(deployer, positionManager.address)\n  if (wethAllowance.lt(wethLiquidityAmount)) {\n    console.log(`Approving weth...`)\n    const tx = await weth.approve(positionManager.address, ethers.constants.MaxUint256)\n    await ethers.provider.waitForTransaction(tx.hash, 1)\n  }\n\n  const usdcAllowance = await usdc.allowance(deployer, positionManager.address)\n  if (usdcAllowance.lt(usdcLiquidityAmount)) {\n    console.log(`Approving USDC...`)\n    const tx = await usdc.approve(positionManager.address, ethers.constants.MaxUint256)\n    await ethers.provider.waitForTransaction(tx.hash, 1)\n  }\n  \n  const minWeth = 0\n  const minSqueeth = 0\n\n  const mintParam = {\n    token0,\n    token1,\n    fee: 3000,\n    tickLower: -887220,// int24 min tick used when selecting full range\n    tickUpper: 887220,// int24 max tick used when selecting full range\n    amount0Desired: isWethToken0 ? wethLiquidityAmount : usdcLiquidityAmount,\n    amount1Desired: isWethToken0 ? usdcLiquidityAmount : wethLiquidityAmount,\n    amount0Min: isWethToken0 ? minWeth : minSqueeth,\n    amount1Min: isWethToken0 ? minSqueeth : minWeth,\n    recipient: deployer,// address\n    deadline: Math.floor(Date.now() / 1000 + 86400),// uint256\n  }\n\n  await positionManager.mint(mintParam)\n\n});\n\n"
  },
  {
    "path": "packages/hardhat/tasks/buySqueeth.ts",
    "content": "import { task, types } from \"hardhat/config\";\nimport \"@nomiclabs/hardhat-waffle\";\nimport { getUniswapDeployments, getWETH } from \"./utils\";\n\n// Example execution\n/**\n npx hardhat buySqueeth --input '0.1'\n */\ntask(\"buySqueeth\", \"Buy Squeeth from the pool\")\n  .addParam('input', 'amount weth paying', '0.05', types.string)\n  .setAction(async ({input: inputAmount}, hre) => {\n  const { getNamedAccounts, ethers, network } = hre;\n  const { deployer } = await getNamedAccounts();\n  \n  const { swapRouter } = await getUniswapDeployments(ethers, deployer, network.name);\n\n  const squeeth = await ethers.getContract(\"WPowerPerp\", deployer);\n  const weth = await getWETH(ethers, deployer, network.name)\n\n  const inputWETHAmount = ethers.utils.parseEther(inputAmount) \n\n  console.log(weth.address, 'Weth')\n  console.log(squeeth.address, 'squeeth')\n  let wethBalance = await weth.balanceOf(deployer)\n  \n  const squeethBalance = await squeeth.balanceOf(deployer)\n  \n  \n  if (wethBalance.lt(inputWETHAmount)) {\n    console.log(`Minting new WETH`)\n    await weth.deposit({value: inputWETHAmount})\n    wethBalance = await weth.balanceOf(deployer)\n  }\n\n  console.log(`SQU Balance before trade:\\t${ethers.utils.formatUnits(squeethBalance.toString())}`)  \n  console.log(`WETH Balance before trade:\\t${ethers.utils.formatUnits(wethBalance.toString())}`)  \n\n  \n  // await weth.approve(swapRouter.address, ethers.constants.MaxUint256)\n  console.log(`Approve WETH `)\n  \n  const exactInputParam = {\n    tokenIn: weth.address, // address\n    tokenOut: squeeth.address, // address\n    fee: 3000, // uint24\n    recipient: deployer, // address\n    deadline: Math.floor(Date.now() / 1000 + 86400), // uint256\n    amountIn: inputWETHAmount, // uint256\n    amountOutMinimum: 0, // uint256 // no slippage control now\n    sqrtPriceLimitX96: 0, // uint160\n  }\n\n  const tx = await swapRouter.exactInputSingle(exactInputParam)\n  await tx.wait()\n\n  const squeethBalanceAfter = await squeeth.balanceOf(deployer)\n  const wethBalanceAfter = await weth.balanceOf(deployer)\n\n  console.log(`Bought ${ethers.utils.formatUnits(squeethBalanceAfter.sub(squeethBalance))} SQU from Uni Pool`)\n  console.log(`Paid ${ethers.utils.formatUnits(wethBalance.sub(wethBalanceAfter))} WETH to Uni Pool`)\n  \n});\n"
  },
  {
    "path": "packages/hardhat/tasks/buyWeth.ts",
    "content": "import { task, types } from \"hardhat/config\";\nimport \"@nomiclabs/hardhat-waffle\";\nimport { BigNumber } from \"ethers\";\nimport { getUniswapDeployments, getUSDC, getWETH } from \"./utils\";\n\n// Example execution\n/**\n npx hardhat wethWhacker --input '1000' --network ropsten\n */\ntask(\"wethWhacker\", \"Buy Weth from the pool\")\n  .addParam('input', 'amount usdc sending', '1000', types.string)\n  .setAction(async ({ input: inputAmount }, hre) => {\n    const { getNamedAccounts, ethers, network } = hre;\n    const { deployer } = await getNamedAccounts();\n\n    const { swapRouter } = await getUniswapDeployments(ethers, deployer, network.name);\n\n    const usdc = await getUSDC(ethers, deployer, network.name)\n    const weth = await getWETH(ethers, deployer, network.name)\n\n    const usdcDecimals = 6\n    const usdcAmount = BigNumber.from(inputAmount).mul(BigNumber.from(10).pow(usdcDecimals))\n\n    const usdcBalance = await usdc.balanceOf(deployer)\n\n    if (usdcBalance.lt(usdcAmount)) {\n      console.log(`Minting new USDC`)\n      const tx = await usdc.mint(deployer, usdcAmount)\n      await ethers.provider.waitForTransaction(tx.hash, 1)\n    }\n\n    const usdcAllowance = await usdc.allowance(deployer, swapRouter.address)\n    if (usdcAllowance.lt(usdcAmount)) {\n      console.log('Approving USDC')\n      await usdc.approve(swapRouter.address, ethers.constants.MaxUint256)\n    }\n\n    const exactInputParam = {\n      tokenIn: usdc.address, // address\n      tokenOut: weth.address, // address\n      fee: 3000, // uint24\n      recipient: deployer, // address\n      deadline: Math.floor(Date.now() / 1000 + 86400), // uint256\n      amountIn: usdcAmount, // uint256\n      amountOutMinimum: 0, // uint256 // no slippage control now\n      sqrtPriceLimitX96: 0, // uint160\n    }\n\n    await swapRouter.exactInputSingle(exactInputParam)\n    console.log(`Bought WETH from Uni Pool successfully`)\n\n  });\n"
  },
  {
    "path": "packages/hardhat/tasks/default.ts",
    "content": "/* eslint-disable */\nimport { task, types } from 'hardhat/config';\nimport '@nomiclabs/hardhat-waffle';\n\nimport { ethers } from 'ethers';\nimport config from '../hardhat.config';\n\nconst { isAddress, getAddress, formatUnits, parseUnits } = ethers.utils;\n\nconst fs = require('fs');\nconst chalk = require('chalk');\n\nconst DEBUG = false;\n\nfunction debug(text: any) {\n  if (DEBUG) {\n    console.log(text);\n  }\n}\n\ntask('wallet', 'Create a wallet (pk) link', async (_, { ethers }) => {\n  const randomWallet = ethers.Wallet.createRandom();\n  const privateKey = randomWallet._signingKey().privateKey;\n  console.log('🔐 WALLET Generated as ' + randomWallet.address + '');\n  console.log('🔗 http://localhost:3000/pk#' + privateKey);\n});\n\ntask('fundedwallet', 'Create a wallet (pk) link and fund it with deployer?')\n  .addOptionalParam('amount', 'Amount of ETH to send to wallet after generating')\n  .addOptionalParam('url', 'URL to add pk to')\n  .setAction(async (taskArgs, { network, ethers }) => {\n    const randomWallet = ethers.Wallet.createRandom();\n    const privateKey = randomWallet._signingKey().privateKey;\n    console.log('🔐 WALLET Generated as ' + randomWallet.address + '');\n    const url = taskArgs.url ? taskArgs.url : 'http://localhost:3000';\n\n    let localDeployerMnemonic;\n    try {\n      localDeployerMnemonic = fs.readFileSync('./mnemonic.txt');\n      localDeployerMnemonic = localDeployerMnemonic.toString().trim();\n    } catch (e) {\n      /* do nothing - this file isn't always there */\n    }\n\n    const amount = taskArgs.amount ? taskArgs.amount : '0.01';\n    const tx = {\n      to: randomWallet.address,\n      value: ethers.utils.parseEther(amount),\n    };\n\n    // SEND USING LOCAL DEPLOYER MNEMONIC IF THERE IS ONE\n    // IF NOT SEND USING LOCAL HARDHAT NODE:\n    if (localDeployerMnemonic) {\n      let deployerWallet = ethers.Wallet.fromMnemonic(localDeployerMnemonic);\n      deployerWallet = deployerWallet.connect(ethers.provider);\n      console.log(\n        '💵 Sending ' + amount + ' ETH to ' + randomWallet.address + ' using deployer account'\n      );\n      const sendresult = await deployerWallet.sendTransaction(tx);\n      console.log('\\n' + url + '/pk#' + privateKey + '\\n');\n      \n    } else {\n      console.log('💵 Sending ' + amount + ' ETH to ' + randomWallet.address + ' using local node');\n      console.log('\\n' + url + '/pk#' + privateKey + '\\n');\n      return send(ethers.provider.getSigner(), tx);\n    }\n  });\n\ntask('generate', 'Create a mnemonic for builder deploys', async (_, { ethers }) => {\n  const bip39 = require('bip39');\n  const hdkey = require('ethereumjs-wallet/hdkey');\n  const mnemonic = bip39.generateMnemonic();\n  if (DEBUG) console.log('mnemonic', mnemonic);\n  const seed = await bip39.mnemonicToSeed(mnemonic);\n  if (DEBUG) console.log('seed', seed);\n  const hdwallet = hdkey.fromMasterSeed(seed);\n  const wallet_hdpath = \"m/44'/60'/0'/0/\";\n  const account_index = 0;\n  const fullPath = wallet_hdpath + account_index;\n  if (DEBUG) console.log('fullPath', fullPath);\n  const wallet = hdwallet.derivePath(fullPath).getWallet();\n  const privateKey = '0x' + wallet._privKey.toString('hex');\n  if (DEBUG) console.log('privateKey', privateKey);\n  const EthUtil = require('ethereumjs-util');\n  const address = '0x' + EthUtil.privateToAddress(wallet._privKey).toString('hex');\n  console.log('🔐 Account Generated as ' + address + ' and set as mnemonic in packages/hardhat');\n  console.log(\"💬 Use 'yarn run account' to get more information about the deployment account.\");\n\n  fs.writeFileSync('./' + address + '.txt', mnemonic.toString());\n  fs.writeFileSync('./mnemonic.txt', mnemonic.toString());\n});\n\ntask('mineContractAddress', 'Looks for a deployer account that will give leading zeros')\n  .addParam('searchFor', 'String to search for')\n  .setAction(async (taskArgs, { network, ethers }) => {\n    let contract_address = '';\n    let address;\n\n    const bip39 = require('bip39');\n    const hdkey = require('ethereumjs-wallet/hdkey');\n\n    let mnemonic = '';\n    while (contract_address.indexOf(taskArgs.searchFor) != 0) {\n      mnemonic = bip39.generateMnemonic();\n      if (DEBUG) console.log('mnemonic', mnemonic);\n      const seed = await bip39.mnemonicToSeed(mnemonic);\n      if (DEBUG) console.log('seed', seed);\n      const hdwallet = hdkey.fromMasterSeed(seed);\n      const wallet_hdpath = \"m/44'/60'/0'/0/\";\n      const account_index = 0;\n      const fullPath = wallet_hdpath + account_index;\n      if (DEBUG) console.log('fullPath', fullPath);\n      const wallet = hdwallet.derivePath(fullPath).getWallet();\n      const privateKey = '0x' + wallet._privKey.toString('hex');\n      if (DEBUG) console.log('privateKey', privateKey);\n      const EthUtil = require('ethereumjs-util');\n      address = '0x' + EthUtil.privateToAddress(wallet._privKey).toString('hex');\n\n      const rlp = require('rlp');\n      const keccak = require('keccak');\n\n      const nonce = 0x00; // The nonce must be a hex literal!\n      const sender = address;\n\n      const input_arr = [sender, nonce];\n      const rlp_encoded = rlp.encode(input_arr);\n\n      const contract_address_long = keccak('keccak256').update(rlp_encoded).digest('hex');\n\n      contract_address = contract_address_long.substring(24); // Trim the first 24 characters.\n    }\n\n    console.log('⛏  Account Mined as ' + address + ' and set as mnemonic in packages/hardhat');\n    console.log(\n      '📜 This will create the first contract: ' + chalk.magenta('0x' + contract_address)\n    );\n    console.log(\"💬 Use 'yarn run account' to get more information about the deployment account.\");\n\n    fs.writeFileSync('./' + address + '_produces' + contract_address + '.txt', mnemonic.toString());\n    fs.writeFileSync('./mnemonic.txt', mnemonic.toString());\n  });\n\ntask('account', 'Get balance information for the deployment account.', async (_, { ethers }) => {\n  const hdkey = require('ethereumjs-wallet/hdkey');\n  const bip39 = require('bip39');\n  const mnemonic = fs.readFileSync('./mnemonic.txt').toString().trim();\n  if (DEBUG) console.log('mnemonic', mnemonic);\n  const seed = await bip39.mnemonicToSeed(mnemonic);\n  if (DEBUG) console.log('seed', seed);\n  const hdwallet = hdkey.fromMasterSeed(seed);\n  const wallet_hdpath = \"m/44'/60'/0'/0/\";\n  const account_index = 0;\n  const fullPath = wallet_hdpath + account_index;\n  if (DEBUG) console.log('fullPath', fullPath);\n  const wallet = hdwallet.derivePath(fullPath).getWallet();\n  const privateKey = '0x' + wallet._privKey.toString('hex');\n  if (DEBUG) console.log('privateKey', privateKey);\n  const EthUtil = require('ethereumjs-util');\n  const address = '0x' + EthUtil.privateToAddress(wallet._privKey).toString('hex');\n\n  const qrcode = require('qrcode-terminal');\n  qrcode.generate(address);\n  console.log('‍📬 Deployer Account is ' + address);\n  if (!config.networks) {\n    return\n  }\n  for (const n in config.networks) {\n    // console.log(config.networks[n],n)\n    try {\n      const provider = new ethers.providers.JsonRpcProvider((config as any).networks[n].url);\n      const balance = await provider.getBalance(address);\n      console.log(' -- ' + n + ' --  -- -- 📡 ');\n      console.log('   balance: ' + ethers.utils.formatEther(balance));\n      console.log('   nonce: ' + (await provider.getTransactionCount(address)));\n    } catch (e) {\n      if (DEBUG) {\n        console.log(e);\n      }\n    }\n  }\n});\n\nasync function addr(ethers: any, addr: string) {\n  if (isAddress(addr)) {\n    return getAddress(addr);\n  }\n  const accounts = await ethers.provider.listAccounts();\n  if (accounts[addr] !== undefined) {\n    return accounts[addr];\n  }\n  throw `Could not normalize address: ${addr}`;\n}\n\ntask('accounts', 'Prints the list of accounts', async (_, { ethers }) => {\n  const accounts = await ethers.provider.listAccounts();\n  accounts.forEach((account) => console.log(account));\n});\n\ntask('blockNumber', 'Prints the block number', async (_, { ethers }) => {\n  const blockNumber = await ethers.provider.getBlockNumber();\n  console.log(blockNumber);\n});\n\ntask('balance', \"Prints an account's balance\")\n  .addPositionalParam('account', \"The account's address\")\n  .setAction(async (taskArgs, { ethers }) => {\n    const balance = await ethers.provider.getBalance(await addr(ethers, taskArgs.account));\n    console.log(formatUnits(balance, 'ether'), 'ETH');\n  });\n\nfunction send(signer: any, txparams: any) {\n  return signer.sendTransaction(txparams, (error: any, transactionHash: any) => {\n    if (error) {\n      debug(`Error: ${error}`);\n    }\n    debug(`transactionHash: ${transactionHash}`);\n    // checkForReceipt(2, params, transactionHash, resolve)\n  });\n}\n\ntask('send', 'Send ETH')\n  .addParam('from', 'From address or account index')\n  .addOptionalParam('to', 'To address or account index')\n  .addOptionalParam('amount', 'Amount to send in ether')\n  .addOptionalParam('data', 'Data included in transaction')\n  .addOptionalParam('gasPrice', 'Price you are willing to pay in gwei')\n  .addOptionalParam('gasLimit', 'Limit of how much gas to spend')\n\n  .setAction(async (taskArgs, { network, ethers }) => {\n    const from = await addr(ethers, taskArgs.from);\n    debug(`Normalized from address: ${from}`);\n    const fromSigner = await ethers.provider.getSigner(from);\n\n    let to;\n    if (taskArgs.to) {\n      to = await addr(ethers, taskArgs.to);\n      debug(`Normalized to address: ${to}`);\n    }\n\n    const txRequest = {\n      from: await fromSigner.getAddress(),\n      to,\n      value: parseUnits(taskArgs.amount ? taskArgs.amount : '0', 'ether').toHexString(),\n      nonce: await fromSigner.getTransactionCount(),\n      gasPrice: parseUnits(taskArgs.gasPrice ? taskArgs.gasPrice : '1.001', 'gwei').toHexString(),\n      gasLimit: taskArgs.gasLimit ? taskArgs.gasLimit : 24000,\n      chainId: network.config.chainId,\n      data: '',\n    };\n\n    if (taskArgs.data !== undefined) {\n      txRequest.data = taskArgs.data;\n      debug(`Adding data to payload: ${txRequest.data}`);\n    }\n    debug((txRequest.gasPrice as any) / 1000000000 + ' gwei');\n    debug(JSON.stringify(txRequest, null, 2));\n\n    return send(fromSigner, txRequest);\n  });\n"
  },
  {
    "path": "packages/hardhat/tasks/increaseSlot.ts",
    "content": "import { task, types } from \"hardhat/config\";\nimport \"@nomiclabs/hardhat-waffle\";\nimport { getUniswapDeployments, getWETH } from \"./utils\";\n\n/**\n npx hardhat increase-slots --network mainnet --slots 128\n */\ntask(\"increase-slots\", \"Increase Pool slot\")\n  .addParam('slots', 'how many slots to increase', 256, types.int)\n  .setAction(async ({slots}, hre) => {\n\n  const { getNamedAccounts, ethers, network } = hre;\n  \n  const { deployer } = await getNamedAccounts();\n  const { uniswapFactory } = await getUniswapDeployments(ethers, deployer, network.name)\n\n  const wsqueeth = await ethers.getContractAt(\"WPowerPerp\", deployer);\n  const weth = await getWETH(ethers, deployer, network.name)\n\n  const isWethToken0 = parseInt(weth.address, 16) < parseInt(wsqueeth.address, 16)\n  const token0 = isWethToken0 ? weth.address : wsqueeth.address\n  const token1 = isWethToken0 ? wsqueeth.address : weth.address\n  \n  const poolAddr = await uniswapFactory.getPool(token0, token1, 3000)\n  const pool = await ethers.getContractAt(\"IUniswapV3Pool\", poolAddr);\n  console.log(`Squeeth Pool Address: ${pool.address.toString()}`)\n  \n  const { observationCardinalityNext } =  await pool.slot0()\n  console.log(`Current observationCardinalityNext ${observationCardinalityNext.toString()}, adding ${slots} more`)\n\n  const tx = await pool.increaseObservationCardinalityNext(observationCardinalityNext + slots)\n  console.log(`Transaction Hash: ${tx.hash}, tx.nonce ${tx.nonce}`)\n\n});\n"
  },
  {
    "path": "packages/hardhat/tasks/sellSqueeth.ts",
    "content": "import { task, types } from \"hardhat/config\";\nimport \"@nomiclabs/hardhat-waffle\";\nimport { BigNumber } from \"ethers\";\nimport { getUniswapDeployments, getUSDC, getWETH } from \"./utils\";\n\n// Example execution\n/**\n npx hardhat sellSqueeth --input '1000' --network ropsten\n */\ntask(\"sellSqueeth\", \"Sell Weth from the pool\")\n  .addParam('input', 'amount squeeth sending', '1', types.string)\n  .setAction(async ({ input: inputAmount }, hre) => {\n    const { getNamedAccounts, ethers, network } = hre;\n    const { deployer } = await getNamedAccounts();\n\n    const { swapRouter } = await getUniswapDeployments(ethers, deployer, network.name);\n\n    const weth = await getWETH(ethers, deployer, network.name)\n    const squeeth = await ethers.getContract(\"WPowerPerp\", deployer);\n\n    const oSqthDecimal = 18\n    const oSqthAmount = BigNumber.from(inputAmount).mul(BigNumber.from(10).pow(oSqthDecimal))\n\n    const sqthBalance = await squeeth.balanceOf(deployer)\n\n    // if (wethBalance.lt(wethAmount)) {\n    //   console.log(`Minting new USDC`)\n    //   const tx = await usdc.mint(deployer, usdcAmount)\n    //   await ethers.provider.waitForTransaction(tx.hash, 1)\n    // }\n\n    const sqthAllowance = await squeeth.allowance(deployer, squeeth.address)\n    if (sqthAllowance.lt(oSqthAmount)) {\n      console.log('Approving sqth')\n      const tx = await squeeth.approve(swapRouter.address, ethers.constants.MaxUint256)\n      tx.wait()\n    }\n\n    const exactInputParam = {\n      tokenIn: squeeth.address, // address\n      tokenOut: weth.address, // address\n      fee: 3000, // uint24\n      recipient: deployer, // address\n      deadline: Math.floor(Date.now() / 1000 + 86400), // uint256\n      amountIn: oSqthAmount, // uint256\n      amountOutMinimum: 0, // uint256 // no slippage control now\n      sqrtPriceLimitX96: 0, // uint160\n    }\n\n    const tx = await swapRouter.exactInputSingle(exactInputParam)\n    tx.wait()\n    console.log(`Sold oSqth to Uni Pool successfully`)\n\n  });\n"
  },
  {
    "path": "packages/hardhat/tasks/sellWeth.ts",
    "content": "import { task, types } from \"hardhat/config\";\nimport \"@nomiclabs/hardhat-waffle\";\nimport { BigNumber } from \"ethers\";\nimport { getUniswapDeployments, getUSDC, getWETH } from \"./utils\";\n\n// Example execution\n/**\n npx hardhat sellWeth --input '1000' --network ropsten\n */\ntask(\"sellWeth\", \"Sell Weth from the pool\")\n  .addParam('input', 'amount weth sending', '1000', types.string)\n  .setAction(async ({ input: inputAmount }, hre) => {\n    const { getNamedAccounts, ethers, network } = hre;\n    const { deployer } = await getNamedAccounts();\n\n    const { swapRouter } = await getUniswapDeployments(ethers, deployer, network.name);\n\n    const usdc = await getUSDC(ethers, deployer, network.name)\n    const weth = await getWETH(ethers, deployer, network.name)\n\n    const wethDecimals = 18\n    const wethAmount = BigNumber.from(inputAmount).mul(BigNumber.from(10).pow(wethDecimals))\n\n    const wethBalance = await weth.balanceOf(deployer)\n\n    // if (wethBalance.lt(wethAmount)) {\n    //   console.log(`Minting new USDC`)\n    //   const tx = await usdc.mint(deployer, usdcAmount)\n    //   await ethers.provider.waitForTransaction(tx.hash, 1)\n    // }\n\n    const wethAllowance = await weth.allowance(deployer, swapRouter.address)\n    if (wethAllowance.lt(wethAmount)) {\n      console.log('Approving WETH')\n      await weth.approve(swapRouter.address, ethers.constants.MaxUint256)\n    }\n\n    const exactInputParam = {\n      tokenIn: weth.address, // address\n      tokenOut: usdc.address, // address\n      fee: 3000, // uint24\n      recipient: deployer, // address\n      deadline: Math.floor(Date.now() / 1000 + 86400), // uint256\n      amountIn: wethAmount, // uint256\n      amountOutMinimum: 0, // uint256 // no slippage control now\n      sqrtPriceLimitX96: 0, // uint160\n    }\n\n    await swapRouter.exactInputSingle(exactInputParam)\n    console.log(`Sold WETH from Uni Pool successfully`)\n\n  });\n"
  },
  {
    "path": "packages/hardhat/tasks/utils.ts",
    "content": "import { Contract } from \"ethers\"\nimport fs from 'fs'\n\nexport const networkNameToUniRouter = (name: string) => {\n  switch (name) {\n    case 'mainnet': return '0xE592427A0AEce92De3Edee1F18E0157C05861564'\n    case 'rinkebyArbitrum': return '0xE592427A0AEce92De3Edee1F18E0157C05861564'\n    case 'goerli': return '0x833A158dA5ceBc44901211427E9Df936023EC0d3'\n    default: return undefined\n  }\n}\n\nexport const networkNameToUniFactory = (name: string) => {\n  switch (name) {\n    case 'mainnet': return '0x1F98431c8aD98523631AE4a59f267346ea31F984'\n    case 'rinkebyArbitrum': return '0x1F98431c8aD98523631AE4a59f267346ea31F984'\n    case 'goerli': return '0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa'\n    default: return undefined\n  }\n}\n\n// quoter is different from uniswap's official deployment! cause it's QuoterV2\nexport const networkNameToUniQuoter = (name: string) => {\n  switch (name) {\n    case 'mainnet': return '0xC8d3a4e6BB4952E3658CCA5081c358e6935Efa43'\n    case 'rinkebyArbitrum': return undefined\n    case 'goerli': return '0x759442726c06F7938cd2cB63aC9Ae373Dc1dEcf6'\n    default: return undefined\n  }\n}\n\nexport const networkNameToPositionManager = (name: string) => {\n  switch (name) {\n    case 'mainnet': return '0xC36442b4a4522E871399CD717aBDD847Ab11FE88'\n    case 'rinkebyArbitrum': return '0xC36442b4a4522E871399CD717aBDD847Ab11FE88'\n    case 'goerli': return '0x24a66308bab3BEbC2821480adA395BF1C4ff8Bf2'\n    default: return undefined\n  }\n}\n\nexport const networkNameToUSDC = (name: string) => {\n  switch (name) {\n    case 'mainnet': return '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'\n    case 'ropsten': return '0x27415c30d8c87437becbd4f98474f26e712047f4'\n    case 'goerli': return '0x306bf03b689f7d7e5e9D3aAC87a068F16AFF9482'\n    default: return undefined\n  }\n}\n\n\nexport const networkNameToWeth = (name: string) => {\n  switch (name) {\n    case 'mainnet': return '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'\n    case 'ropsten': return '0xc778417e063141139fce010982780140aa0cd5ab'\n    case 'rinkebyArbitrum': return '0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681'\n    case 'goerli': return '0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103'\n    default: return undefined\n  }\n}\n\nexport const networkNameToController = (name: string) => {\n  switch (name) {\n    case 'mainnet': return '0x64187ae08781B09368e6253F9E94951243A493D5'\n    case 'ropsten': return '0x59F0c781a6eC387F09C40FAA22b7477a2950d209'\n    case 'goerli': return '0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508'\n    default: return undefined\n  }\n}\n\nexport const networkNameToExec = (name: string) => {\n  switch (name) {\n    case 'mainnet': return '0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80'\n    case 'ropsten': return '0xF7B8611008Ed073Ef348FE130671688BBb20409d'\n    case 'goerli': return '0x4b62EB6797526491eEf6eF36D3B9960E5d66C394'\n    default: return undefined\n  }\n}\n\nexport const networkNameToEuler = (name: string) => {\n  switch (name) {\n    case 'mainnet': return '0x27182842E098f60e3D576794A5bFFb0777E025d3'\n    case 'ropsten': return '0xfC3DD73e918b931be7DEfd0cc616508391bcc001'\n    case 'goerli': return '0x931172BB95549d0f29e10ae2D079ABA3C63318B3'\n    default: return undefined\n  }\n}\n\nexport const networkNameToDweth = (name: string) => {\n  switch (name) {\n    case 'mainnet': return '0x62e28f054efc24b26A794F5C1249B6349454352C'\n    case 'ropsten': return '0x682b4c36a6D4749Ced8C3abF47AefDFC57A17754'\n    case 'goerli': return '0x356079240635B276A63065478471d89340443C49'\n    default: return undefined\n  }\n}\n\nexport const networkNameToCrab = (name: string) => {\n  switch (name) {\n    case 'mainnet': return '0xf205ad80BB86ac92247638914265887A8BAa437D'\n    case 'ropsten': return '0xbffBD99cFD9d77c49595dFe8eB531715906ca4Cf'\n    case 'goerli': return '0x9a23a941F5e70F6960a0E39B8a3964ef83DCbe91'\n    default: return undefined\n  }\n}\n\nexport const getWETH = async (ethers: any, deployer: string, networkName: string) => {\n  const wethAddr = networkNameToWeth(networkName)\n  if (wethAddr === undefined) {\n    // get from deployed network\n    return ethers.getContract(\"WETH9\", deployer);\n  }\n  // get contract instance at address\n  return ethers.getContractAt('WETH9', wethAddr)\n}\n\nexport const getUSDC = async (ethers: any, deployer: string, networkName: string) => {\n  const usdcAddress = networkNameToUSDC(networkName)\n  if (usdcAddress === undefined) {\n    // use to local deployment as USDC\n    return ethers.getContract(\"MockErc20\", deployer);\n  }\n  // get contract instance at address\n  return ethers.getContractAt('MockErc20', usdcAddress)\n}\n\nexport const getController = async (ethers: any, deployer: string, networkName: string) => {\n  const controllerAddr = networkNameToController(networkName)\n  if (controllerAddr === undefined) {\n    // get from deployed network\n    return ethers.getContract(\"Controller\", deployer);\n  }\n  // get contract instance at address\n  return ethers.getContractAt('Controller', controllerAddr)\n}\n\nexport const getExec = async (deployer: string, networkName: string) => {\n  const execAddr = networkNameToExec(networkName)\n  if (execAddr === undefined) {\n    return ''\n  }\n  // get contract instance at address\n  return execAddr;\n}\n\nexport const getEuler = async (deployer: string, networkName: string) => {\n  const eulerAddr = networkNameToEuler(networkName)\n  if (eulerAddr === undefined) {\n    return ''\n  }\n  // get contract instance at address\n  return eulerAddr\n}\n\nexport const getDwethToken = async (deployer: string, networkName: string) => {\n  const dWethAddr = networkNameToDweth(networkName)\n  if (dWethAddr === undefined) {\n    return ''\n  }\n  // get contract instance at address\n  return dWethAddr\n}\n\nexport const getCrab = (networkName: string) => {\n  const crabAddress = networkNameToCrab(networkName)\n  if (crabAddress === undefined) {\n    return ''\n  }\n  // get contract instance at address\n  return crabAddress\n}\n\n/**\n * \n * @param networkName \n */\nexport const hasUniswapDeployments = (networkName: string) => {\n  if (networkName === 'mainnet') return true\n  if (networkName === 'rinkebyArbitrum') return true\n  if (networkName === 'ropsten') return true\n  if (networkName === 'goerli') return true   // our own uni deployment on goerli with OpynWETH9\n  return false\n}\n\nexport const getUniswapDeployments = async (ethers: any, deployer: string, networkName: string) => {\n  // Get Uniswap Factory\n  let uniswapFactory: Contract\n  if (networkNameToUniFactory(networkName) === undefined) {\n    uniswapFactory = await ethers.getContract(\"UniswapV3Factory\", deployer);\n  } else {\n    uniswapFactory = await ethers.getContractAt('IUniswapV3Factory', networkNameToUniFactory(networkName))\n  }\n\n  // Get Uniswap Factory\n  let swapRouter: Contract\n  if (networkNameToUniRouter(networkName) === undefined) {\n    swapRouter = await ethers.getContract(\"SwapRouter\", deployer);\n  } else {\n    swapRouter = await ethers.getContractAt('ISwapRouter', networkNameToUniRouter(networkName))\n  }\n\n  // Get Position Manager\n  let positionManager: Contract\n  if (networkNameToPositionManager(networkName) === undefined) {\n    positionManager = await ethers.getContract(\"NonfungiblePositionManager\", deployer);\n  } else {\n    positionManager = await ethers.getContractAt('INonfungiblePositionManager', networkNameToPositionManager(networkName))\n  }\n\n  return { positionManager, swapRouter, uniswapFactory }\n}\n\nexport const createArgumentFile = (contract: string, network: string, args: Array<any>) => {\n  const path = `./arguments/${contract}-${network}.js`\n  const content = `module.exports = [${args.map(a => `\"${a}\"`).join(',')}]`\n\n  fs.writeFileSync(path, content);\n}"
  },
  {
    "path": "packages/hardhat/test/calculator.ts",
    "content": "import { BigNumberish } from \"ethers\"\nimport { BigNumber } from \"bignumber.js\"\n\nexport function convertPriceToSqrtX96 (sqrtPriceX96: string) {\n\n  return new BigNumber(sqrtPriceX96).times(sqrtPriceX96).times(1e18).div(new BigNumber(2).pow(96 * 2))\n  \n}\n\n// /**\n//  * token0: USD\n//  * token1: ETH\n//  * @param sqrtPriceX96 \n//  * @returns price of token1 per token0. scaled by 1e18\n//  */\n// function convertSqrtX96ToRawPrice (sqrtPriceX96: string) {\n//   const priceToken1InToken0 = new BigNumber(sqrtPriceX96).times(sqrtPriceX96).times(1e18).div(new BigNumber(2).pow(96 * 2))\n//   // price = sqrtPriceX96 * sqrtPriceX96 * 1e18 >> (96 * 2)\n//   return priceToken1InToken0\n// }\n\n/**\n * token0: USD\n * token1: ETH\n * @param sqrtPriceX96 \n * @returns price of token1 per token0. scaled by 1e18\n */\n function convertRawPriceToSqrtX96 (rawPrice: BigNumber) {\n  const sqrtX96Price = rawPrice.times(new BigNumber(2).pow(96 * 2)).div(1e18).squareRoot()\n  return sqrtX96Price\n}\n\nexport function convertToken1PriceToSqrtX96Price(token1PriceInToken0: string) {\n  const rawPrice = new BigNumber(1e18).div(token1PriceInToken0)\n  return convertRawPriceToSqrtX96(rawPrice)\n}\n\nexport function convertToken0PriceToSqrtX96Price(token1PriceInToken0: string) {\n  const rawPrice = new BigNumber(token1PriceInToken0).times(1e18)\n  return convertRawPriceToSqrtX96(rawPrice)\n}\n\nexport function getTickFromToken0Price(price: string) {\n  return log1_0001(new BigNumber(price).toNumber())\n}\n\nexport function getTickFromNormalPrice(price: string) {\n  return log1_0001(new BigNumber(1).div(price).toNumber())\n}\n\nfunction log1_0001(num: number) { // eslint-disable-line\n  return Math.log2(num) / Math.log2(1.0001)\n}\n\nexport function getSqrtPriceAndTickBySqueethPrice(price1e18: string|BigNumberish, wethIsToken0: boolean) {\n  const humanReadablePrice = new BigNumber(price1e18.toString()).div(1e18)\n  const newToken0Price = wethIsToken0 \n    ? new BigNumber(1).div(humanReadablePrice).toString()\n    : humanReadablePrice \n  const sqrtPrice = convertToken0PriceToSqrtX96Price(newToken0Price.toString()).toFixed(0)\n  const tick =  getTickFromToken0Price(newToken0Price.toString()).toFixed(0)\n  return { tick, sqrtPrice }\n}\n\nexport function getYAmountAboveRange (pa:number, pb: number, liquidity: string) {\n  const sqrtA = new BigNumber(pa).squareRoot()\n  const sqrtB = new BigNumber(pb).squareRoot()\n  return new BigNumber(liquidity).times(sqrtB.minus(sqrtA)).integerValue()\n}\n\nexport function getXAmountBelowRange (pa:number, pb: number, liquidity: string) {\n  const sqrtA = new BigNumber(pa).squareRoot()\n  const sqrtB = new BigNumber(pb).squareRoot()\n  return new BigNumber(liquidity).times(sqrtB.minus(sqrtA)).div(sqrtB.times(sqrtA)).integerValue()\n}\n\nexport function tickToPrice1e18(tick: number) {\n  // calculate x = 1.0001 ^ tick\n  return new BigNumber(1.0001).pow(tick).times(1e18).toFixed(0)\n}"
  },
  {
    "path": "packages/hardhat/test/e2e/crab-Migration.ts",
    "content": "// ALCHEMY_KEY=XXXXXXXXX yarn test:e2e\n// ALCHEMY_KEY=XXXXXXXX yarn test:e2e test/e2e/crab-Migration.ts\n\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { BigNumber, providers } from \"ethers\";\nimport { Controller, CrabStrategy, CrabStrategyV2, CrabMigration, IDToken, WETH9, IEulerExec, Timelock, Oracle, WPowerPerp, IUniswapV3Pool } from \"../../typechain\";\n\nimport { wmul, wdiv, one, getGasPaid } from \"../utils\"\n\ndescribe(\"Crab Migration\", function () {\n    if (!process.env.MAINNET_FORK) return;\n\n    let crabStrategyV1: CrabStrategy;\n    let crabStrategyV2: CrabStrategyV2\n    let crabMigration: CrabMigration;\n    let controller: Controller;\n    let oracle: Oracle;\n    let oSqth: WPowerPerp;\n    let squeethPool: IUniswapV3Pool;\n\n    let weth: WETH9;\n    let dToken: IDToken;\n    let dTokenIncorrect: IDToken;\n    let eulerExec: IEulerExec;\n\n    let provider: providers.JsonRpcProvider;\n    let owner: SignerWithAddress;\n    let random: SignerWithAddress;\n    let d1: SignerWithAddress;\n    let d2: SignerWithAddress;\n    let d3: SignerWithAddress;\n    let d4: SignerWithAddress;\n    let d5: SignerWithAddress;\n\n    let timelock: Timelock;\n\n    let squeethPoolFee: BigNumber\n\n    const eulerMainnetAddress = \"0x27182842E098f60e3D576794A5bFFb0777E025d3\";\n    const eulerExecAddress = \"0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80\";\n    const dTokenAddress = \"0x62e28f054efc24b26A794F5C1249B6349454352C\";\n    const dTokenAddressIncorrect = \"0xB6f48177a096563F861787cFAFE8243c44FEF592\"; // dCVX token\n    const wethAddress = \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\";\n    const crabV1Address = \"0xf205ad80BB86ac92247638914265887A8BAa437D\";\n    const crabV1Whale = \"0x7ba50e6f1fc2bddfaad95b6bb9947949a588a038\";\n    const crabV1Whale2 = \"0x8b08a0a2e1bb7160fa0263abd28cd2d22f18943c\";\n    const crabV1Whale3 = \"0x52b768d3487686fb75902c38f794ffc1843e0a43\";\n    const crabV1Whale4 = \"0x5599b4eaddd319e2f462b27fc8378b0bfad309ca\";\n    const crabV1Whale5 = \"0x1f5be3c931deb102a9e2c489c8abd074a6450e1a\";\n    const squeethControllerAddress = \"0x64187ae08781B09368e6253F9E94951243A493D5\";\n    const oracleAddress = \"0x65D66c76447ccB45dAf1e8044e918fA786A483A1\";\n    const uniswapFactoryAddress = \"0x1F98431c8aD98523631AE4a59f267346ea31F984\";\n    const wethOsqthPoolAddress = \"0x82c427AdFDf2d245Ec51D8046b41c4ee87F0d29C\";\n    const squeethAddress = \"0xf1b99e3e573a1a9c5e6b2ce818b617f0e664e86b\";\n\n    let deposit1Amount: BigNumber\n    let deposit2Amount: BigNumber\n    let deposit3Amount: BigNumber\n    let deposit4Amount: BigNumber\n    let deposit5Amount: BigNumber\n\n    this.beforeAll(\"Prepare accounts\", async () => {\n        const accounts = await ethers.getSigners();\n        const [_owner, _d1, _random, _d2, _d3, _d4, _d5] = accounts;\n        d1 = _d1\n        d2 = _d2\n        d3 = _d3\n        d4 = _d4\n        d5 = _d5\n        random = _random\n        owner = _owner\n        provider = ethers.provider\n    })\n\n    this.beforeAll(\"Setup environment\", async () => {\n        weth = await ethers.getContractAt(\"WETH9\", wethAddress);\n        dToken = await ethers.getContractAt(\"IDToken\", dTokenAddress);\n        dTokenIncorrect = await ethers.getContractAt(\"IDToken\", dTokenAddressIncorrect);\n        eulerExec = await ethers.getContractAt(\"IEulerExec\", eulerExecAddress);\n        crabStrategyV1 = await ethers.getContractAt(\"CrabStrategy\", crabV1Address);\n        controller = await ethers.getContractAt(\"Controller\", squeethControllerAddress);\n        oracle = await ethers.getContractAt(\"Oracle\", oracleAddress);\n        oSqth = await ethers.getContractAt(\"WPowerPerp\", squeethAddress);\n        squeethPool = await ethers.getContractAt(\"IUniswapV3Pool\", wethOsqthPoolAddress);\n\n        squeethPoolFee = BigNumber.from(await squeethPool.fee())\n\n        deposit1Amount = await crabStrategyV1.balanceOf(crabV1Whale);\n        deposit2Amount = await crabStrategyV1.balanceOf(crabV1Whale2);\n        deposit3Amount = await crabStrategyV1.balanceOf(crabV1Whale3);\n        deposit4Amount = await crabStrategyV1.balanceOf(crabV1Whale4);\n        deposit5Amount = await crabStrategyV1.balanceOf(crabV1Whale5);\n\n        // console.log(deposit1Amount.toString(), deposit2Amount.toString(), deposit3Amount.toString(), deposit4Amount.toString(), deposit5Amount.toString())\n\n        // Send Crab shares to d1\n        await provider.send('hardhat_impersonateAccount', [crabV1Whale]);\n        const signer1 = ethers.provider.getSigner(crabV1Whale);\n        await crabStrategyV1.connect(signer1).transfer(d1.address, deposit1Amount);\n        await provider.send('evm_mine', []);\n        await provider.send('hardhat_stopImpersonatingAccount', [crabV1Whale]);\n\n        // Send Crab shares to d2\n        await provider.send('hardhat_impersonateAccount', [crabV1Whale2]);\n        const signer2 = ethers.provider.getSigner(crabV1Whale2);\n        await crabStrategyV1.connect(signer2).transfer(d2.address, deposit2Amount);\n        await provider.send('evm_mine', []);\n        await provider.send('hardhat_stopImpersonatingAccount', [crabV1Whale2]);\n\n        // Send crab shares to d3\n        await provider.send('hardhat_impersonateAccount', [crabV1Whale3]);\n        const signer3 = ethers.provider.getSigner(crabV1Whale3);\n        await crabStrategyV1.connect(signer3).transfer(d3.address, deposit3Amount);\n        await provider.send('evm_mine', []);\n        await provider.send('hardhat_stopImpersonatingAccount', [crabV1Whale3]);\n\n        // Send crab shares to d4\n        await owner.sendTransaction({ to: crabV1Whale4, value: ethers.utils.parseEther('.1') })\n        await provider.send('hardhat_impersonateAccount', [crabV1Whale4]);\n        const signer4 = ethers.provider.getSigner(crabV1Whale4);\n        await crabStrategyV1.connect(signer4).transfer(d4.address, deposit4Amount);\n        await provider.send('evm_mine', []);\n        await provider.send('hardhat_stopImpersonatingAccount', [crabV1Whale4]);\n\n        // Send crab shares to d5\n        await owner.sendTransaction({ to: crabV1Whale5, value: ethers.utils.parseEther('.1') })\n        await provider.send('hardhat_impersonateAccount', [crabV1Whale5]);\n        const signer5 = ethers.provider.getSigner(crabV1Whale5);\n        await crabStrategyV1.connect(signer5).transfer(d5.address, deposit5Amount);\n        await provider.send('evm_mine', []);\n        await provider.send('hardhat_stopImpersonatingAccount', [crabV1Whale5]);\n    })\n\n    this.beforeAll(\"Deploy Incorrect Crab Migration\", async () => {\n        const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n        await expect(MigrationContract.deploy(crabV1Address, wethAddress, eulerExecAddress, dTokenAddressIncorrect, eulerMainnetAddress)).to.be.revertedWith(\"dToken underlying asset should be weth\");\n    })\n\n    this.beforeAll(\"Deploy Crab Migration\", async () => {\n        const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n\n        crabMigration = (await MigrationContract.deploy(crabV1Address, wethAddress, eulerExecAddress, dTokenAddress, eulerMainnetAddress)) as CrabMigration;\n    })\n\n    this.beforeAll(\"Deploy Crab 2\", async () => {\n        const TimelockContract = await ethers.getContractFactory(\"Timelock\");\n        timelock = (await TimelockContract.deploy(owner.address, 3 * 24 * 60 * 60)) as Timelock;\n        const CrabContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n        crabStrategyV2 = (await CrabContract.deploy(\n            squeethControllerAddress,\n            oracleAddress,\n            wethAddress,\n            uniswapFactoryAddress,\n            wethOsqthPoolAddress,\n            timelock.address,\n            crabMigration.address,\n            1,\n            1)) as CrabStrategyV2;\n        await crabMigration.connect(owner).setCrabV2(crabStrategyV2.address);\n    })\n\n    const getV2SqthAndEth = async (share: BigNumber) => {\n        const [, , eth, sqth] = await crabStrategyV2.getVaultDetails();\n        const supply = await crabStrategyV2.totalSupply();\n        const userEth = wdiv(wmul(share, eth), supply)\n        const userSqth = wdiv(wmul(share, sqth), supply)\n\n        return [userEth, userSqth]\n    }\n\n    describe(\"Test Migration\", () => {\n\n        it(\"d1 deposits crabV1 shares\", async () => {\n            const crabV1BalanceBefore = await crabStrategyV1.balanceOf(crabMigration.address);\n\n            await crabStrategyV1.connect(d1).approve(crabMigration.address, deposit1Amount);\n            await crabMigration.connect(d1).depositV1Shares(deposit1Amount);\n\n            const crabV1BalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n            const d1SharesDeposited = await crabMigration.sharesDeposited(d1.address);\n\n            expect(crabV1BalanceBefore).to.be.equal('0');\n            expect(crabV1BalanceAfter).to.be.equal(deposit1Amount);\n            expect(d1SharesDeposited).to.be.equal(deposit1Amount);\n        })\n\n        it(\"d2 deposits crabV1 shares\", async () => {\n            const crabV1BalanceBefore = await crabStrategyV1.balanceOf(crabMigration.address);\n\n            await crabStrategyV1.connect(d2).approve(crabMigration.address, deposit2Amount);\n            await crabMigration.connect(d2).depositV1Shares(deposit2Amount);\n\n            const crabV1BalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n            const d2SharesDeposited = await crabMigration.sharesDeposited(d2.address);\n\n            expect(crabV1BalanceAfter.sub(crabV1BalanceBefore)).to.be.equal(deposit2Amount);\n            expect(d2SharesDeposited).to.be.equal(deposit2Amount);\n        })\n\n        it(\"d2 withdraws too many crabV1 shares\", async () => {\n            await expect(crabMigration.connect(d2).withdrawV1Shares(deposit2Amount.mul(2))).to.be.revertedWith('ds-math-sub-underflow');\n        })\n\n        it(\"d2 withdraws 1/2 of their crabV1 shares\", async () => {\n            const crabV1BalanceBefore = await crabStrategyV1.balanceOf(crabMigration.address);\n\n            await crabMigration.connect(d2).withdrawV1Shares(deposit2Amount.div(2));\n\n            const crabV1BalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n            const d2SharesDeposited = await crabMigration.sharesDeposited(d2.address);\n\n            expect(crabV1BalanceBefore.sub(crabV1BalanceAfter)).to.be.equal(deposit2Amount.div(2));\n            expect(d2SharesDeposited).to.be.equal(deposit2Amount.sub(deposit2Amount.div(2)));\n        })\n\n        it(\"d2 re-deposits their withdrawn shares\", async () => {\n            const crabV1BalanceBefore = await crabStrategyV1.balanceOf(crabMigration.address);\n\n            await crabStrategyV1.connect(d2).approve(crabMigration.address, deposit2Amount.div(2));\n            await crabMigration.connect(d2).depositV1Shares(deposit2Amount.div(2));\n\n            const crabV1BalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n            const d2SharesDeposited = await crabMigration.sharesDeposited(d2.address);\n\n            expect(crabV1BalanceAfter.sub(crabV1BalanceBefore)).to.be.equal(deposit2Amount.div(2));\n            expect(d2SharesDeposited).to.be.equal(deposit2Amount);\n        })\n\n\n        it(\"should not be able to claim until strategy has been migrated\", async () => {\n            await expect(crabMigration.connect(d1).claimV2Shares()).to.be.revertedWith(\"M2\");\n        })\n\n        it(\"Should not be able to flash migrate until strategy is migrated\", async () => {\n            await expect(crabMigration.connect(d3).flashMigrateFromV1toV2(0, await crabStrategyV1.balanceOf(d3.address), squeethPoolFee)).to.be.revertedWith(\"M2\")\n        })\n\n        it(\"batch migrate\", async () => {\n            const crabV1SharesBalanceBefore = await crabStrategyV1.balanceOf(crabMigration.address);\n            const crabV1SupplyBefore = await crabStrategyV1.totalSupply();\n            const crabV2SupplyBefore = await crabStrategyV2.totalSupply();\n            const crabV1VaultDetailsBefore = await crabStrategyV1.getVaultDetails();\n            const crabV2VaultDetailsBefore = await crabStrategyV2.getVaultDetails();\n\n            await crabMigration.batchMigrate(ethers.utils.parseEther(\"1000.0\"));\n\n            // 1. check crab V1 shares in Migration before and after\n            const crabV1SharesBalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n            expect(crabV1SharesBalanceAfter).to.be.equal('0');\n\n            // 2. check that crab v1 total supply has gone down and crab v2 total supply has increased\n            const crabV1SupplyAfter = await crabStrategyV1.totalSupply();\n            const changeInCrabV1Supply = crabV1SupplyBefore.sub(crabV1SupplyAfter);\n            const crabV2SupplyAfter = await crabStrategyV2.totalSupply();\n            const changeInCrabV2Supply = crabV2SupplyAfter.sub(crabV2SupplyBefore);\n\n            expect(changeInCrabV1Supply).to.be.equal(crabV1SharesBalanceBefore);\n            expect(crabV2SupplyBefore).to.be.equal('0');\n            expect(changeInCrabV2Supply).to.be.equal(changeInCrabV1Supply);\n\n            // 3. check that eth taken out of crab v1 matches eth deposited into crab v2\n            const crabV1VaultDetailsAfter = await crabStrategyV1.getVaultDetails();\n            const crabV2VaultDetailsAfter = await crabStrategyV2.getVaultDetails();\n\n            const ethAmountRemovedFromCrabV1 = crabV1VaultDetailsBefore[2].sub(crabV1VaultDetailsAfter[2])\n            const ethAmountDepositedToCrabV2 = crabV2VaultDetailsAfter[2].sub(crabV2VaultDetailsBefore[2]);\n\n            expect(ethAmountDepositedToCrabV2).to.be.equal(ethAmountRemovedFromCrabV1);\n\n            // 4. check that oSqth amt minted in crab v1 matches oSqth amt minted in crab v2\n            const oSqthDebtPaidCrabV1 = crabV1VaultDetailsBefore[3].sub(crabV1VaultDetailsAfter[3])\n            const oSqthMintedCrabV2 = crabV2VaultDetailsAfter[3].sub(crabV2VaultDetailsBefore[3]);\n\n            expect(oSqthDebtPaidCrabV1).to.be.equal(oSqthMintedCrabV2);\n\n            // 5. check that crab v2 is now initialized\n            const isInitialized = await crabStrategyV2.isInitialized();\n            expect(isInitialized).to.be.true;\n        })\n\n        it(\"d1 claims shares\", async () => {\n            const constractSharesBefore = await crabStrategyV2.balanceOf(crabMigration.address);\n            const d1SharesBefore = await crabStrategyV2.balanceOf(d1.address);\n\n            await crabMigration.connect(d1).claimV2Shares();\n\n            // 1. check that shares sent from migration contract equals shares received by user\n            const constractSharesAfter = await crabStrategyV2.balanceOf(crabMigration.address);\n            const d1SharesAfter = await crabStrategyV2.balanceOf(d1.address);\n            const sharesSent = constractSharesBefore.sub(constractSharesAfter);\n\n            expect(d1SharesBefore).to.be.equal('0');\n            expect(d1SharesAfter.sub(d1SharesBefore)).to.be.equal(sharesSent);\n\n            // 2. check that the right amount of shares have been sent. \n            const totalDepositAmount = deposit1Amount.add(deposit2Amount);\n            const expectedSharesSent = deposit1Amount;\n            expect(expectedSharesSent).to.be.equal(sharesSent);\n        })\n\n        it(\"Should not able to claim more than their share\", async () => {\n            const d2sharesInMigrationBefore = await crabMigration.sharesDeposited(d2.address)\n\n            const d2sharesV2ToMigrate = d2sharesInMigrationBefore.add(1);\n\n            await expect(crabMigration.connect(d2).claimAndWithdraw(d2sharesV2ToMigrate, ethers.constants.MaxUint256, squeethPoolFee)).to.be.revertedWith(\"M5\") // Set ETH slippage higher!\n        })\n\n        it(\"d2 Claim and flash withdraw 50 percent of tokens\", async () => {\n            const constractSharesBefore = await crabStrategyV2.balanceOf(crabMigration.address);\n            const d2sharesInMigrationBefore = await crabMigration.sharesDeposited(d2.address);\n            const d2EthBalanceBefore = await provider.getBalance(d2.address);\n\n            const d2sharesV1ToMigrate = wdiv(d2sharesInMigrationBefore, one.mul(2))\n            const d2sharesV2ToMigrate = d2sharesV1ToMigrate\n\n            const [ethToGet, sqthToSell] = await getV2SqthAndEth(d2sharesV2ToMigrate);\n            const sqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n            const ethSpentToBuyBack = wdiv(wmul(wmul(sqthToSell, sqthPrice), BigNumber.from(105)), BigNumber.from(100))\n\n            await crabMigration.connect(d2).claimAndWithdraw(d2sharesV2ToMigrate, ethSpentToBuyBack, squeethPoolFee) // Set ETH slippage higher!\n            const d2sharesInMigrationAfter = await crabMigration.sharesDeposited(d2.address)\n            const constractSharesAfter = await crabStrategyV2.balanceOf(crabMigration.address);\n            const d2EthBalanceAfter = await provider.getBalance(d2.address);\n\n            expect(d2sharesInMigrationAfter).to.be.equal(d2sharesInMigrationBefore.sub(d2sharesV1ToMigrate))\n            expect(constractSharesAfter).to.be.equal(constractSharesBefore.sub(d2sharesV2ToMigrate))\n            // Check if minimum ETH is returned\n            expect(d2EthBalanceAfter.sub(d2EthBalanceBefore).gte(ethToGet.sub(ethSpentToBuyBack))).to.be.true\n        })\n\n        it(\"d2 Claim and flash withdraw 100 percent of the tokens\", async () => {\n            const constractSharesBefore = await crabStrategyV2.balanceOf(crabMigration.address);\n            const d2sharesV2ToMigrate = await crabMigration.sharesDeposited(d2.address)\n            const d2EthBalanceBefore = await provider.getBalance(d2.address);\n\n            const [ethToGet, sqthToSell] = await getV2SqthAndEth(d2sharesV2ToMigrate);\n            const sqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n            const ethSpentToBuyBack = wdiv(wmul(wmul(sqthToSell, sqthPrice), BigNumber.from(105)), BigNumber.from(100))\n\n\n            await crabMigration.connect(d2).claimAndWithdraw(d2sharesV2ToMigrate, ethSpentToBuyBack, squeethPoolFee) // Set ETH slippage higher!\n            const d2sharesInMigrationAfter = await crabMigration.sharesDeposited(d2.address)\n            const constractSharesAfter = await crabStrategyV2.balanceOf(crabMigration.address);\n            const d2EthBalanceAfter = await provider.getBalance(d2.address);\n\n            expect(d2sharesInMigrationAfter).to.be.equal(\"0\")\n            expect(constractSharesAfter).to.be.equal(constractSharesBefore.sub(d2sharesV2ToMigrate))\n            // Check if minimum ETH is returned\n            expect(d2EthBalanceAfter.sub(d2EthBalanceBefore).gte(ethToGet.sub(ethSpentToBuyBack))).to.be.true\n        })\n\n        it(\"d1 should not be able to deposit after migration\", async () => {\n            await expect(crabMigration.connect(d1).depositV1Shares(deposit1Amount)).to.be.revertedWith(\"M1\");\n        })\n\n        it(\"d1 should not be able to withdraw after migration\", async () => {\n            await expect(crabMigration.connect(d1).withdrawV1Shares(deposit1Amount)).to.be.revertedWith(\"M1\");\n        })\n\n    })\n\n    let vaultIdV1: BigNumber\n    let collatV1: BigNumber\n    let collatV2: BigNumber\n    let shortV1: BigNumber\n    let shortV2: BigNumber\n    let crabV1Supply: BigNumber\n    let crabV2Supply: BigNumber\n    let crabV1SharesBefore: BigNumber\n    let crabV2ShareBefore: BigNumber\n    let userEthBalance: BigNumber\n    let crabV2inMigrationBefore: BigNumber\n\n    const initialize = async (address: string) => {\n        vaultIdV1 = await crabStrategyV1.vaultId();\n        [, , collatV1, shortV1] = await crabStrategyV1.getVaultDetails();\n        [, , collatV2, shortV2] = await crabStrategyV2.getVaultDetails();\n        crabV1Supply = await crabStrategyV1.totalSupply()\n        crabV2Supply = await crabStrategyV2.totalSupply()\n        crabV1SharesBefore = await crabStrategyV1.balanceOf(address)\n        crabV2ShareBefore = await crabStrategyV2.balanceOf(address)\n        userEthBalance = await provider.getBalance(address)\n        crabV2inMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n    }\n\n    const increaseCR1 = async (amount: BigNumber) => {\n        // Set ETH to crab contract and use that ETH deposit collat to increase CR1\n        await provider.send(\"hardhat_setBalance\", [crabStrategyV1.address, amount.add(one).toHexString()])\n        await provider.send(\"hardhat_impersonateAccount\", [crabStrategyV1.address]);\n\n        const signer = ethers.provider.getSigner(crabStrategyV1.address);\n        await controller.connect(signer).deposit(vaultIdV1, { value: amount })\n\n        await provider.send(\"hardhat_setBalance\", [crabStrategyV1.address, \"0x0\"])\n        await provider.send('evm_mine', []);\n        await provider.send('hardhat_stopImpersonatingAccount', [crabStrategyV1.address]);\n\n        [, , collatV1, shortV1] = await crabStrategyV1.getVaultDetails();\n        [, , collatV2, shortV2] = await crabStrategyV2.getVaultDetails();\n    }\n\n    const decreaseCR1 = async (amount: BigNumber) => {\n        // Withdraw from crabv1's vault to decrease CR1\n        await provider.send(\"hardhat_setBalance\", [crabStrategyV1.address, ethers.utils.parseEther('10').toHexString()]) // Gas\n        await provider.send(\"hardhat_impersonateAccount\", [crabStrategyV1.address]);\n\n        const signer = ethers.provider.getSigner(crabStrategyV1.address);\n        await controller.connect(signer).withdraw(vaultIdV1, amount)\n\n        await provider.send(\"hardhat_setBalance\", [crabStrategyV1.address, \"0x0\"])\n        await provider.send('evm_mine', []);\n        await provider.send('hardhat_stopImpersonatingAccount', [crabStrategyV1.address]);\n\n        [, , collatV1, shortV1] = await crabStrategyV1.getVaultDetails();\n        [, , collatV2, shortV2] = await crabStrategyV2.getVaultDetails();\n    }\n\n    describe(\"Individual claim after migration\", () => {\n        it(\"Should fail if wrong migration function is called\", async () => {\n            await initialize(d4.address)\n            await increaseCR1(ethers.utils.parseEther('10'))\n            await expect(crabMigration.connect(d4).flashMigrateAndWithdrawFromV1toV2(one, one, 0, one, squeethPoolFee)).to.be.revertedWith(\"M10\");\n            await decreaseCR1(ethers.utils.parseEther('10'))\n            await initialize(d5.address)\n            await decreaseCR1(ethers.utils.parseEther('10'))\n            await expect(crabMigration.connect(d5).flashMigrateFromV1toV2(one, 0, squeethPoolFee)).to.be.revertedWith(\"M9\");\n            await increaseCR1(ethers.utils.parseEther('10'))\n        })\n\n        it(\"Should fail if _ethToBorrow or _withdrawMaxEthToPay is passed as 0\", async () => {\n            await decreaseCR1(ethers.utils.parseEther('10'))\n            await expect(crabMigration.connect(d5).flashMigrateAndWithdrawFromV1toV2(one, one, 0, 0, squeethPoolFee)).to.be.revertedWith(\"M8\");\n            await expect(crabMigration.connect(d5).flashMigrateAndWithdrawFromV1toV2(one, one, one, 0, squeethPoolFee)).to.be.revertedWith(\"M8\");\n            await expect(crabMigration.connect(d5).flashMigrateAndWithdrawFromV1toV2(one, one, 0, one, squeethPoolFee)).to.be.revertedWith(\"M8\");\n            await increaseCR1(ethers.utils.parseEther('10'))\n        })\n\n        it(\"Should migrate d4 when CR1 > CR2\", async () => {\n            let gasPaid = BigNumber.from(0)\n            await initialize(d4.address)\n            await increaseCR1(ethers.utils.parseEther('10'))\n            const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n            const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n            const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n\n            expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n            expect(isFlashMigrate).to.be.true\n            expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n            const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n            const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n            const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n            const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n            gasPaid = await getGasPaid(tx1)\n\n            const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n            gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n            const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n            const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n            const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n            const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n            const userEthBalanceAfter = await provider.getBalance(d4.address)\n            const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n            expect(crabV1SharesAfter).to.be.equal('0')\n            expect(crabV1SharesInMigration).to.be.equal('0')\n            expect(crabV2SharesBefore).to.be.equal('0')\n            expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n            expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n            expect(crabV2SharesInMigrationBefore).to.be.equal('0') // All the shares are migrated\n            expect(crabV2SharesInMigration).to.be.equal('0')\n            expect(squeethBalance).to.be.equal('0')\n        })\n\n        it(\"Should migrate d5 when CR1 < CR2\", async () => {\n            let gasPaid = BigNumber.from(0)\n            await initialize(d5.address)\n            await decreaseCR1(ethers.utils.parseEther('10'))\n            const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n\n\n            expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.false\n            expect(isFlashMigrate).to.be.false\n            expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n\n            const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n            const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n            const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n            const ethToFlashLoan = wdiv(numerator, denominator)\n            const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n            const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n            const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .1% slippage\n            const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n            const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n            const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n            const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n            const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n            const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n            const tx1 = await crabStrategyV1.connect(d5).approve(crabMigration.address, ethers.constants.MaxUint256);\n            gasPaid = await getGasPaid(tx1)\n            // Don't flash deposit and return back ETH. For the sake of simplicity. Flash deposit is already tested in previous tests\n            const tx2 = await crabMigration.connect(d5).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n            gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n            const crabV1SharesAfter = await crabStrategyV1.balanceOf(d5.address)\n            const crabV2SharesAfter = await crabStrategyV2.balanceOf(d5.address)\n            const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n            const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n            const userEthBalanceAfter = await provider.getBalance(d5.address)\n\n\n            expect(crabV1SharesAfter).to.be.equal('0')\n            expect(crabV1SharesInMigration).to.be.equal('0')\n            expect(crabV2SharesInMigration).to.be.equal('0')\n            expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n            expect(squeethBalance).to.be.equal('0')\n            // Can't predict exact because of slippage so should be greater or equal to expected balance\n            expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n        })\n\n        describe(\"Migrate crab with even supply\", async function () {\n            const hedgeTimeThreshold = 86400  // 24h\n            const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n            const auctionTime = 3600\n            const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n            const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n            this.beforeAll(\"Deploy and seed crab V1\", async () => {\n                const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n                crabStrategyV1 = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactoryAddress, wethOsqthPoolAddress, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n                crabStrategyV1.setStrategyCap(ethers.utils.parseEther('100'))\n                const d1Amt = ethers.utils.parseEther('20');\n                const d2Amt = ethers.utils.parseEther('5');\n                const d3Amt = ethers.utils.parseEther('5');\n\n                crabStrategyV1.connect(d1).deposit({ value: d1Amt })\n                crabStrategyV1.connect(d2).deposit({ value: d2Amt })\n                crabStrategyV1.connect(d3).deposit({ value: d3Amt })\n                // crabStrategyV1.connect(d4).deposit({ value: d4Amt })\n\n                oSqth.connect(d1).transfer(random.address, await oSqth.balanceOf(d1.address))\n                oSqth.connect(d2).transfer(random.address, await oSqth.balanceOf(d1.address))\n                oSqth.connect(d3).transfer(random.address, await oSqth.balanceOf(d1.address))\n            })\n\n            this.beforeAll(\"Deploy migration contract and crab v2\", async () => {\n                const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n                crabMigration = (await MigrationContract.deploy(crabStrategyV1.address, wethAddress, eulerExecAddress, dTokenAddress, eulerMainnetAddress)) as CrabMigration;\n\n                const CrabContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n                crabStrategyV2 = (await CrabContract.deploy(\n                    squeethControllerAddress,\n                    oracleAddress,\n                    wethAddress,\n                    uniswapFactoryAddress,\n                    wethOsqthPoolAddress,\n                    timelock.address,\n                    crabMigration.address,\n                    1,\n                    1)) as CrabStrategyV2;\n\n                await crabMigration.connect(owner).setCrabV2(crabStrategyV2.address);\n            })\n\n            it(\"Should have even number of total supply, short and collat\", async () => {\n                const [, , collat, short] = await crabStrategyV1.getVaultDetails()\n                expect(await crabStrategyV1.totalSupply()).to.be.equal(\"30000000000000000012\")\n                expect(collat).to.be.equal(\"30000000000000000000\")\n            })\n\n            it(\"D1 deposit crab v1 shares\", async () => {\n                const shareToDeposit = ethers.utils.parseEther('10')\n\n                await crabStrategyV1.connect(d1).approve(crabMigration.address, shareToDeposit);\n                await crabMigration.connect(d1).depositV1Shares(shareToDeposit);\n\n                const crabV1BalanceMigrationAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n                const crabV1BalanceAfter = await crabStrategyV1.balanceOf(d1.address);\n                const d1SharesDeposited = await crabMigration.sharesDeposited(d1.address);\n\n                expect(crabV1BalanceAfter).to.be.equal(shareToDeposit)\n                expect(crabV1BalanceMigrationAfter).to.be.equal(shareToDeposit);\n                expect(d1SharesDeposited).to.be.equal(shareToDeposit);\n            })\n\n            it(\"Batch migrate\", async () => {\n                await crabMigration.batchMigrate(ethers.utils.parseEther(\"1000.0\"))\n\n                const crabV2SupplyAfter = await crabStrategyV2.totalSupply();\n                const crabV1SharesBalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n                const crabV2SharesBalanceAfter = await crabStrategyV2.balanceOf(crabMigration.address);\n\n                expect(crabV1SharesBalanceAfter).to.be.equal('0')\n                expect(crabV2SupplyAfter).to.be.equal(ethers.utils.parseEther('10'))\n                expect(crabV2SharesBalanceAfter).to.be.equal(ethers.utils.parseEther('10'))\n            })\n\n            it(\"d1 claims shares\", async () => {\n                const d1SharesBefore = await crabStrategyV2.balanceOf(d1.address);\n\n                await crabMigration.connect(d1).claimV2Shares();\n\n                // 1. check that shares sent from migration contract equals shares received by user\n                const constractSharesAfter = await crabStrategyV2.balanceOf(crabMigration.address);\n                const d1SharesAfter = await crabStrategyV2.balanceOf(d1.address);\n\n                expect(d1SharesBefore).to.be.equal('0');\n                expect(d1SharesAfter).to.be.equal(ethers.utils.parseEther('10'));\n                expect(constractSharesAfter).to.be.equal('0')\n            })\n\n            it(\"migrate d2 with CR1 > CR2\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d2.address)\n                await increaseCR1(ethers.utils.parseEther('2'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d2.address)\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d2).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d2).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d2.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d2.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d2.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal('0')\n                expect(squeethBalance).to.be.equal('0')\n            })\n\n            it(\"migrate d3 with CR1 < CR2\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d3.address)\n                await decreaseCR1(ethers.utils.parseEther('2'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.false\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .1% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d3).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n                // Don't flash deposit and return back ETH. For the sake of simplicity. Flash deposit is already tested in previous tests\n                const tx2 = await crabMigration.connect(d3).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d3.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d3.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d3.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                // Can't predict exact because of slippage so should be greater or equal to expected balance\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                expect(squeethBalance).to.be.equal('0')\n            })\n        })\n\n        describe(\"Migrate crab with odd supply\", async function () {\n            const hedgeTimeThreshold = 86400  // 24h\n            const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n            const auctionTime = 3600\n            const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n            const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n            this.beforeAll(\"Deploy and seed crab V1\", async () => {\n                const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n                crabStrategyV1 = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactoryAddress, wethOsqthPoolAddress, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n                crabStrategyV1.setStrategyCap(ethers.utils.parseEther('100'))\n                const d1Amt = ethers.utils.parseEther('20').add(1);\n                const d2Amt = ethers.utils.parseEther('5');\n                const d3Amt = ethers.utils.parseEther('5');\n                const d4Amt = ethers.utils.parseEther('10');\n\n                crabStrategyV1.connect(d1).deposit({ value: d1Amt })\n                crabStrategyV1.connect(d2).deposit({ value: d2Amt })\n                crabStrategyV1.connect(d3).deposit({ value: d3Amt })\n                crabStrategyV1.connect(d4).deposit({ value: d4Amt })\n\n                oSqth.connect(d1).transfer(random.address, await oSqth.balanceOf(d1.address))\n                oSqth.connect(d2).transfer(random.address, await oSqth.balanceOf(d1.address))\n                oSqth.connect(d3).transfer(random.address, await oSqth.balanceOf(d1.address))\n            })\n\n            this.beforeAll(\"Deploy migration contract and crab v2\", async () => {\n                const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n                crabMigration = (await MigrationContract.deploy(crabStrategyV1.address, wethAddress, eulerExecAddress, dTokenAddress, eulerMainnetAddress)) as CrabMigration;\n\n                const CrabContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n                crabStrategyV2 = (await CrabContract.deploy(\n                    squeethControllerAddress,\n                    oracleAddress,\n                    wethAddress,\n                    uniswapFactoryAddress,\n                    wethOsqthPoolAddress,\n                    timelock.address,\n                    crabMigration.address,\n                    1,\n                    1)) as CrabStrategyV2;\n\n                await crabMigration.connect(owner).setCrabV2(crabStrategyV2.address);\n            })\n\n            it(\"Should have even number of total supply, short and collat\", async () => {\n                const [, , collat, short] = await crabStrategyV1.getVaultDetails()\n                expect(await crabStrategyV1.totalSupply()).to.be.equal(\"40000000000000000017\")\n                expect(collat).to.be.equal(\"40000000000000000001\")\n            })\n\n            it(\"D1 deposit crab v1 shares\", async () => {\n                const shareToDeposit = ethers.utils.parseEther('10')\n\n                await crabStrategyV1.connect(d1).approve(crabMigration.address, shareToDeposit);\n                await crabMigration.connect(d1).depositV1Shares(shareToDeposit);\n\n                const crabV1BalanceMigrationAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n                const crabV1BalanceAfter = await crabStrategyV1.balanceOf(d1.address);\n                const d1SharesDeposited = await crabMigration.sharesDeposited(d1.address);\n\n                expect(crabV1BalanceAfter).to.be.equal(shareToDeposit.add(1))\n                expect(crabV1BalanceMigrationAfter).to.be.equal(shareToDeposit);\n                expect(d1SharesDeposited).to.be.equal(shareToDeposit);\n            })\n\n            it(\"Batch migrate\", async () => {\n                await crabMigration.batchMigrate(ethers.utils.parseEther(\"1000.0\"))\n\n                const crabV2SupplyAfter = await crabStrategyV2.totalSupply();\n                const crabV1SharesBalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n                const crabV2SharesBalanceAfter = await crabStrategyV2.balanceOf(crabMigration.address);\n\n                expect(crabV1SharesBalanceAfter).to.be.equal('0')\n                expect(crabV2SupplyAfter).to.be.equal(ethers.utils.parseEther('10'))\n                expect(crabV2SharesBalanceAfter).to.be.equal(ethers.utils.parseEther('10'))\n            })\n\n            it(\"d1 claims shares\", async () => {\n                const d1SharesBefore = await crabStrategyV2.balanceOf(d1.address);\n\n                await crabMigration.connect(d1).claimV2Shares();\n\n                // 1. check that shares sent from migration contract equals shares received by user\n                const constractSharesAfter = await crabStrategyV2.balanceOf(crabMigration.address);\n                const d1SharesAfter = await crabStrategyV2.balanceOf(d1.address);\n\n\n                expect(d1SharesBefore).to.be.equal('0');\n                expect(d1SharesAfter).to.be.equal(ethers.utils.parseEther('10'));\n                expect(constractSharesAfter).to.be.equal('0')\n            })\n\n            it(\"migrate d2 with CR1 > CR2 with flash deposit\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d2.address)\n                await increaseCR1(ethers.utils.parseEther('2'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d2.address)\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const ethToFlashDeposit = excessEth.mul(195).div(100) // Something less than 200%\n\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n                const expectedSupply = crabV2Supply.add(expectedV2Shares)\n                const expectedCollat = collatV2.add(ethNeededForV2)\n                const expectedShort = wdiv(wmul(ethNeededForV2, shortV2), collatV2).add(shortV2)\n\n                const depositShareFromFlashDeposit = wdiv(ethToFlashDeposit, expectedCollat.add(ethToFlashDeposit))\n                const expectedV2SharesFlashDeposit = wdiv(wmul(depositShareFromFlashDeposit, expectedSupply), one.sub(depositShareFromFlashDeposit))\n\n                const oSqthToMintedFlash = wdiv(wmul(ethToFlashDeposit, expectedShort), expectedCollat);\n                const ethToReturned = wmul(oSqthToMintedFlash, oSqthPrice)\n\n                const expectedEth = excessEth.sub(ethToReturned)\n\n\n                const tx1 = await crabStrategyV1.connect(d2).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d2).flashMigrateFromV1toV2(crabV1SharesBefore, ethToFlashDeposit, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2));\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d2.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d2.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d2.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const [, , collat, short] = await crabStrategyV2.getVaultDetails()\n                expect(await crabStrategyV2.totalSupply()).to.be.equal(expectedSupply.add(expectedV2SharesFlashDeposit))\n                expect(collat).to.be.equal(expectedCollat.add(ethToFlashDeposit))\n                expect(short).to.be.equal(expectedShort.add(oSqthToMintedFlash))\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares.add(expectedV2SharesFlashDeposit))\n                expect(crabV2SharesInMigration).to.be.equal('0')\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n            })\n\n            it(\"migrate d3 with CR1 < CR2\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d3.address)\n                await decreaseCR1(ethers.utils.parseEther('2'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.false\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .1% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d3).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n                // Don't flash deposit and return back ETH. For the sake of simplicity. Flash deposit is already tested in previous tests\n                const tx2 = await crabMigration.connect(d3).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d3.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d3.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d3.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                // Can't predict exact because of slippage so should be greater or equal to expected balance\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n            })\n        })\n\n        describe(\"Partial Migration\", async function () {\n            const hedgeTimeThreshold = 86400  // 24h\n            const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n            const auctionTime = 3600\n            const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n            const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n            this.beforeAll(\"Deploy and seed crab V1\", async () => {\n                const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n                crabStrategyV1 = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactoryAddress, wethOsqthPoolAddress, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n                crabStrategyV1.setStrategyCap(ethers.utils.parseEther('100'))\n                const d1Amt = ethers.utils.parseEther('20');\n                const d2Amt = ethers.utils.parseEther('5');\n                const d3Amt = ethers.utils.parseEther('5');\n\n                crabStrategyV1.connect(d1).deposit({ value: d1Amt })\n                crabStrategyV1.connect(d2).deposit({ value: d2Amt })\n                crabStrategyV1.connect(d3).deposit({ value: d3Amt })\n                // crabStrategyV1.connect(d4).deposit({ value: d4Amt })\n\n                oSqth.connect(d1).transfer(random.address, await oSqth.balanceOf(d1.address))\n                oSqth.connect(d2).transfer(random.address, await oSqth.balanceOf(d1.address))\n                oSqth.connect(d3).transfer(random.address, await oSqth.balanceOf(d1.address))\n            })\n\n            this.beforeAll(\"Deploy migration contract and crab v2\", async () => {\n                const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n                crabMigration = (await MigrationContract.deploy(crabStrategyV1.address, wethAddress, eulerExecAddress, dTokenAddress, eulerMainnetAddress)) as CrabMigration;\n\n                const CrabContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n                crabStrategyV2 = (await CrabContract.deploy(\n                    squeethControllerAddress,\n                    oracleAddress,\n                    wethAddress,\n                    uniswapFactoryAddress,\n                    wethOsqthPoolAddress,\n                    timelock.address,\n                    crabMigration.address,\n                    1,\n                    1)) as CrabStrategyV2;\n\n                await crabMigration.connect(owner).setCrabV2(crabStrategyV2.address);\n            })\n\n            it(\"D1 deposit crab v1 shares\", async () => {\n                const shareToDeposit = ethers.utils.parseEther('10')\n\n                await crabStrategyV1.connect(d1).approve(crabMigration.address, shareToDeposit);\n                await crabMigration.connect(d1).depositV1Shares(shareToDeposit);\n\n                const crabV1BalanceMigrationAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n                const crabV1BalanceAfter = await crabStrategyV1.balanceOf(d1.address);\n                const d1SharesDeposited = await crabMigration.sharesDeposited(d1.address);\n\n                expect(crabV1BalanceAfter).to.be.equal(shareToDeposit)\n                expect(crabV1BalanceMigrationAfter).to.be.equal(shareToDeposit);\n                expect(d1SharesDeposited).to.be.equal(shareToDeposit);\n            })\n\n            it(\"Batch migrate\", async () => {\n                await crabMigration.batchMigrate(ethers.utils.parseEther(\"1000.0\"))\n\n                const crabV2SupplyAfter = await crabStrategyV2.totalSupply();\n                const crabV1SharesBalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n                const crabV2SharesBalanceAfter = await crabStrategyV2.balanceOf(crabMigration.address);\n\n                expect(crabV1SharesBalanceAfter).to.be.equal('0')\n                expect(crabV2SupplyAfter).to.be.equal(ethers.utils.parseEther('10'))\n                expect(crabV2SharesBalanceAfter).to.be.equal(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Partial migrate d2 with CR1 > CR2\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d2.address)\n                await increaseCR1(ethers.utils.parseEther('2'))\n\n                const v1CrabToMigrate = crabV1SharesBefore.div(2);\n\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(v1CrabToMigrate)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d2.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d2).approve(crabMigration.address, v1CrabToMigrate);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d2).flashMigrateFromV1toV2(v1CrabToMigrate, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d2.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d2.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d2.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal(v1CrabToMigrate)\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal(crabV2SharesInMigrationBefore) // Should not change balance\n                expect(squeethBalance).to.be.equal('0')\n            })\n\n            it(\"d1 claims shares\", async () => {\n                const d1SharesBefore = await crabStrategyV2.balanceOf(d1.address);\n\n                await crabMigration.connect(d1).claimV2Shares();\n\n                // 1. check that shares sent from migration contract equals shares received by user\n                const constractSharesAfter = await crabStrategyV2.balanceOf(crabMigration.address);\n                const d1SharesAfter = await crabStrategyV2.balanceOf(d1.address);\n\n                expect(d1SharesBefore).to.be.equal('0');\n                expect(d1SharesAfter).to.be.equal(ethers.utils.parseEther('10'));\n                expect(constractSharesAfter).to.be.equal('0')\n            })\n\n            it(\"Partial migrate d2 with CR1 < CR2\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d2.address)\n                await decreaseCR1(ethers.utils.parseEther('2'))\n                const v1CrabToMigrate = crabV1SharesBefore.div(2);\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(v1CrabToMigrate)\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.false\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d2).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n                // Don't flash deposit and return back ETH. For the sake of simplicity. Flash deposit is already tested in previous tests\n                const tx2 = await crabMigration.connect(d2).flashMigrateAndWithdrawFromV1toV2(v1CrabToMigrate, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d2.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d2.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d2.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal(v1CrabToMigrate)\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(crabV2ShareBefore.add(expectedV2Shares))\n                // Can't predict exact because of slippage so should be greater or equal to expected balance\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                expect(squeethBalance).to.be.equal('0')\n            })\n        })\n    })\n\n    /**\n         * Test all possible user flows in crab migration \n         * https://www.notion.so/opynopyn/Crab-user-flows-3f79e0e993994bf7b0b22d081f9d50e9\n         */\n    describe(\"User Flow Testing\", () => {\n        const hedgeTimeThreshold = 86400  // 24h\n        const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n        const auctionTime = 3600\n        const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n        const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n        const deployAndSeedV1 = async () => {\n            const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n            crabStrategyV1 = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactoryAddress, wethOsqthPoolAddress, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n            await crabStrategyV1.setStrategyCap(ethers.utils.parseEther('100'))\n            const d1Amt = ethers.utils.parseEther('20');\n            const d2Amt = ethers.utils.parseEther('10');\n            const d3Amt = ethers.utils.parseEther('8');\n            const d4Amt = ethers.utils.parseEther('10');\n            const d5Amt = ethers.utils.parseEther('27');\n\n\n            await crabStrategyV1.connect(d1).deposit({ value: d1Amt })\n            await crabStrategyV1.connect(d2).deposit({ value: d2Amt })\n            await crabStrategyV1.connect(d3).deposit({ value: d3Amt })\n            await crabStrategyV1.connect(d4).deposit({ value: d4Amt })\n            await crabStrategyV1.connect(d5).deposit({ value: d5Amt })\n            await crabStrategyV1.connect(random).deposit({ value: d1Amt })\n\n            const p1 = oSqth.connect(d1).transfer(random.address, await oSqth.balanceOf(d1.address))\n            const p2 = oSqth.connect(d2).transfer(random.address, await oSqth.balanceOf(d2.address))\n            const p3 = oSqth.connect(d3).transfer(random.address, await oSqth.balanceOf(d3.address))\n            const p4 = oSqth.connect(d4).transfer(random.address, await oSqth.balanceOf(d4.address))\n            const p5 = oSqth.connect(d5).transfer(random.address, await oSqth.balanceOf(d5.address))\n\n            await Promise.all([p1, p2, p3, p4, p5])\n        }\n\n        const deployCrabMigration = async () => {\n            const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n            crabMigration = (await MigrationContract.deploy(crabStrategyV1.address, wethAddress, eulerExecAddress, dTokenAddress, eulerMainnetAddress)) as CrabMigration;\n\n            const CrabContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n            crabStrategyV2 = (await CrabContract.deploy(\n                squeethControllerAddress,\n                oracleAddress,\n                wethAddress,\n                uniswapFactoryAddress,\n                wethOsqthPoolAddress,\n                timelock.address,\n                crabMigration.address,\n                1,\n                1)) as CrabStrategyV2;\n\n            await crabMigration.connect(owner).setCrabV2(crabStrategyV2.address);\n        }\n\n        const depositSharesAndBatchMigrate = async () => {\n            let shareToDeposit = await crabStrategyV1.balanceOf(d1.address)\n            await crabStrategyV1.connect(d1).approve(crabMigration.address, shareToDeposit);\n            await crabMigration.connect(d1).depositV1Shares(shareToDeposit);\n\n            shareToDeposit = await crabStrategyV1.balanceOf(d2.address)\n            await crabStrategyV1.connect(d2).approve(crabMigration.address, shareToDeposit);\n            await crabMigration.connect(d2).depositV1Shares(shareToDeposit);\n\n            await crabMigration.connect(owner).batchMigrate(one.mul(200)) // 200 ETH as cap\n        }\n\n        describe(\"Case 1: batchMigrate() -> 100% withdraw by claim -> flashMigrateAndWithdraw -> flashMigrate\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should withdraw 100% via claim\", async () => {\n                const d1SharesExpected = await crabMigration.sharesDeposited(d1.address)\n                await crabMigration.connect(d1).claimV2Shares()\n                const d1Shares = await crabStrategyV2.balanceOf(d1.address)\n\n                const d2SharesExpected = await crabMigration.sharesDeposited(d2.address)\n                await crabMigration.connect(d2).claimV2Shares()\n                const d2Shares = await crabStrategyV2.balanceOf(d2.address)\n\n                expect(d1Shares).to.be.equal(d1SharesExpected)\n                expect(d2Shares).to.be.equal(d2SharesExpected)\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                expect(crabV2inMigrationBefore).to.be.equal('0') // Will be 0 because of 100% claim\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigrationBefore).to.be.equal('0') // All the shares are migrated\n                expect(crabV2SharesInMigration).to.be.equal('0')\n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n\n        })\n\n        describe(\"Case 2: batchMigrate() -> 100% withdraw by claim -> flashMigrate -> flashMigrateAndWithdraw\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should withdraw 100% via claim\", async () => {\n                const d1SharesExpected = await crabMigration.sharesDeposited(d1.address)\n                await crabMigration.connect(d1).claimV2Shares()\n                const d1Shares = await crabStrategyV2.balanceOf(d1.address)\n\n                const d2SharesExpected = await crabMigration.sharesDeposited(d2.address)\n                await crabMigration.connect(d2).claimV2Shares()\n                const d2Shares = await crabStrategyV2.balanceOf(d2.address)\n\n                expect(d1Shares).to.be.equal(d1SharesExpected)\n                expect(d2Shares).to.be.equal(d2SharesExpected)\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigrationBefore).to.be.equal('0') // All the shares are migrated\n                expect(crabV2SharesInMigration).to.be.equal('0')\n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                expect(crabV2inMigrationBefore).to.be.equal('0') // Will be 0 because of 100% claim\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n        })\n\n        describe(\"Case 3: batchMigrate() -> 50% withdraw by claim -> flashMigrateAndWithdraw -> flashMigrate\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should withdraw 50% via claim\", async () => {\n                const d1SharesExpected = await crabMigration.sharesDeposited(d1.address)\n                await crabMigration.connect(d1).claimV2Shares()\n                const d1Shares = await crabStrategyV2.balanceOf(d1.address)\n\n                expect(d1Shares).to.be.equal(d1SharesExpected)\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                const d2shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2inMigrationBefore).to.be.equal(d2shares) // As d2 did not claim it yet\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal(crabV2inMigrationBefore) // V2 shares should not be given away to Joe Squlark \n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n                const d2shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2SharesInMigrationBefore).to.be.equal(d2shares) // As d2 did not claim it yet\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal(crabV2SharesInMigrationBefore) // D2 shares should not be given away to Joe Squlark \n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n        })\n\n        describe(\"Case 4: batchMigrate() -> 50% withdraw by claim -> flashMigrate -> flashMigrateAndWithdraw\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should withdraw 50% via claim\", async () => {\n                const d1SharesExpected = await crabMigration.sharesDeposited(d1.address)\n                await crabMigration.connect(d1).claimV2Shares()\n                const d1Shares = await crabStrategyV2.balanceOf(d1.address)\n\n                expect(d1Shares).to.be.equal(d1SharesExpected)\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n                const d2shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2SharesInMigrationBefore).to.be.equal(d2shares) // As d2 did not claim it yet\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal(crabV2SharesInMigrationBefore) // D2 shares should not be given away to Joe Squlark \n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                const d2shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2inMigrationBefore).to.be.equal(d2shares) // As d2 did not claim it yet\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal(crabV2inMigrationBefore) // D2 shares should not be given away to Joe Squlark \n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n        })\n\n        describe(\"Case 5: batchMigrate() -> 100% ClaimAndWithdraw -> flashMigrateAndWithdraw -> flashMigrate\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should withdraw 100% via claimAndWithdraw\", async () => {\n                // To enable 100% of the withdraw from d1 and d2\n                await crabStrategyV2.connect(d5).deposit({\n                    value: ethers.utils.parseEther('10')\n                })\n\n                initialize(d1.address)\n                const d1SharesExpected = await crabMigration.sharesDeposited(d1.address)\n                const d1Osqth = wdiv(wmul(d1SharesExpected, shortV2), crabV2Supply)\n                let oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n                const maxEthToPay = wmul(d1Osqth, oSqthPrice).mul(1005).div(1000) // .5% slippage\n\n                await crabMigration.connect(d1).claimAndWithdraw(d1SharesExpected, maxEthToPay, 3000)\n                const d1Shares = await crabStrategyV2.balanceOf(d1.address)\n                expect(d1Shares).to.be.equal(0)\n\n                initialize(d2.address)\n                oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n                const d2SharesExpected = await crabMigration.sharesDeposited(d2.address)\n                const d2Osqth = wdiv(wmul(d1SharesExpected, shortV2), crabV2Supply)\n                const maxEthToPay2 = wmul(d2Osqth, oSqthPrice).mul(1005).div(1000) // .5% slippage\n\n                await crabMigration.connect(d2).claimAndWithdraw(d2SharesExpected, maxEthToPay2, 3000)\n                const d2Shares = await crabStrategyV2.balanceOf(d2.address)\n                expect(d2Shares).to.be.equal(0)\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                expect(crabV2inMigrationBefore).to.be.equal('0') // 100% withdraw\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal(crabV2inMigrationBefore)\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n                expect(crabV2SharesInMigrationBefore).to.be.equal('0') // 100% claim and withdraw\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal(crabV2SharesInMigrationBefore) // D2 shares should not be given away to Joe Squlark \n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n        })\n\n        describe(\"Case 6: batchMigrate() -> 100% ClaimAndWithdraw -> flashMigrate -> flashMigrateAndWithdraw\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should withdraw 100% via claimAndWithdraw\", async () => {\n                // To enable 100% of the withdraw from d1 and d2\n                await crabStrategyV2.connect(d5).deposit({\n                    value: ethers.utils.parseEther('10')\n                })\n\n                initialize(d1.address)\n                const d1SharesExpected = await crabMigration.sharesDeposited(d1.address)\n                const d1Osqth = wdiv(wmul(d1SharesExpected, shortV2), crabV2Supply)\n                let oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n                const maxEthToPay = wmul(d1Osqth, oSqthPrice).mul(1005).div(1000) // .5% slippage\n\n                await crabMigration.connect(d1).claimAndWithdraw(d1SharesExpected, maxEthToPay, 3000)\n                const d1SharesInMigration = await crabMigration.sharesDeposited(d1.address)\n                const d1Shares = await crabStrategyV2.balanceOf(d1.address)\n                expect(d1Shares).to.be.equal(0)\n                expect(d1SharesInMigration).to.be.equal(0)\n\n                initialize(d2.address)\n                oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n                const d2SharesExpected = await crabMigration.sharesDeposited(d2.address)\n                const d2Osqth = wdiv(wmul(d1SharesExpected, shortV2), crabV2Supply)\n                const maxEthToPay2 = wmul(d2Osqth, oSqthPrice).mul(1005).div(1000) // .5% slippage\n\n                await crabMigration.connect(d2).claimAndWithdraw(d2SharesExpected, maxEthToPay2, 3000)\n                const d2SharesInMigration = await crabMigration.sharesDeposited(d1.address)\n                const d2Shares = await crabStrategyV2.balanceOf(d2.address)\n                expect(d2Shares).to.be.equal(0)\n                expect(d2SharesInMigration).to.be.equal(0)\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n                expect(crabV2SharesInMigrationBefore).to.be.equal('0') // 100% claim and withdraw\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal(crabV2SharesInMigrationBefore) // D2 shares should not be given away to Joe Squlark \n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                expect(crabV2inMigrationBefore).to.be.equal('0') // 100% withdraw\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal(crabV2inMigrationBefore)\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n        })\n\n        describe(\"Case 7: batchMigrate() -> 50% ClaimAndWithdraw -> flashMigrateAndWithdraw -> flashMigrate\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should withdraw 50% via claimAndWithdraw\", async () => {\n                initialize(d1.address)\n                const d1SharesExpected = await crabMigration.sharesDeposited(d1.address)\n                const d1Osqth = wdiv(wmul(d1SharesExpected, shortV2), crabV2Supply)\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n                const maxEthToPay = wmul(d1Osqth, oSqthPrice).mul(1005).div(1000) // .5% slippage\n\n                await crabMigration.connect(d1).claimAndWithdraw(d1SharesExpected, maxEthToPay, 3000)\n                const d1Shares = await crabStrategyV2.balanceOf(d1.address)\n                const d1SharesInMigration = await crabMigration.sharesDeposited(d1.address)\n                expect(d1Shares).to.be.equal(0)\n                expect(d1SharesInMigration).to.be.equal(0)\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2inMigrationBefore).to.be.equal(d2Shares) // 100% withdraw\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal(crabV2inMigrationBefore)\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2SharesInMigrationBefore).to.be.equal(d2Shares) // As d2 did not claim it yet\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal(crabV2SharesInMigrationBefore) // D2 shares should not be given away to Joe Squlark \n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n        })\n\n        describe(\"Case 8: batchMigrate() -> 50% ClaimAndWithdraw -> flashMigrate -> flashMigrateAndWithdraw\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should withdraw 50% via claimAndWithdraw\", async () => {\n                initialize(d1.address)\n                const d1SharesExpected = await crabMigration.sharesDeposited(d1.address)\n                const d1Osqth = wdiv(wmul(d1SharesExpected, shortV2), crabV2Supply)\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n                const maxEthToPay = wmul(d1Osqth, oSqthPrice).mul(1005).div(1000) // .5% slippage\n\n                await crabMigration.connect(d1).claimAndWithdraw(d1SharesExpected, maxEthToPay, 3000)\n                const d1Shares = await crabStrategyV2.balanceOf(d1.address)\n                const d1SharesInMigration = await crabMigration.sharesDeposited(d1.address)\n                expect(d1Shares).to.be.equal(0)\n                expect(d1SharesInMigration).to.be.equal(0)\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2SharesInMigrationBefore).to.be.equal(d2Shares) // As d2 did not claim it yet\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal(crabV2SharesInMigrationBefore) // D2 shares should not be given away to Joe Squlark \n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2inMigrationBefore).to.be.equal(d2Shares) // As d2 did not claim it yet\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal(crabV2inMigrationBefore)\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n        })\n\n        describe(\"Case 9: batchMigrate() -> 0% claim -> flashMigrateAndWithdraw -> flashMigrate\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                const d1Shares = await crabMigration.sharesDeposited(d1.address)\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2inMigrationBefore).to.be.equal(d2Shares.add(d1Shares)) // As both d1 and d2 did not claim\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal(crabV2inMigrationBefore)\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n                const d1Shares = await crabMigration.sharesDeposited(d1.address)\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2SharesInMigrationBefore).to.be.equal(d2Shares.add(d1Shares)) // As both d1 and d2 did not claim\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal(crabV2SharesInMigrationBefore) // V2 shares should not be given away to Joe Squlark \n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n        })\n\n        describe(\"Case 10: batchMigrate() -> 0% claim -> flashMigrate -> flashMigrateAndWithdraw\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n                const d1Shares = await crabMigration.sharesDeposited(d1.address)\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2SharesInMigrationBefore).to.be.equal(d2Shares.add(d1Shares)) // As both d1 and d2 did not claim\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal(crabV2SharesInMigrationBefore) // V2 shares should not be given away to Joe Squlark \n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                const d1Shares = await crabMigration.sharesDeposited(d1.address)\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2inMigrationBefore).to.be.equal(d2Shares.add(d1Shares)) // As both d1 and d2 did not claim\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal(crabV2inMigrationBefore)\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n        })\n\n        describe(\"Case 11: batchMigrate() -> flashMigrate -> flashMigrateAndWithdraw -> 100% ClaimWithdraw\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n                const d1Shares = await crabMigration.sharesDeposited(d1.address)\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2SharesInMigrationBefore).to.be.equal(d1Shares.add(d2Shares)) // As d1 and d2 did not claim it yet\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal(crabV2SharesInMigrationBefore) // V2 shares should not be given away to Joe Squlark \n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                const d1Shares = await crabMigration.sharesDeposited(d1.address)\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2inMigrationBefore).to.be.equal(d1Shares.add(d2Shares)) // As both d1 and d2 did not claim\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal(crabV2inMigrationBefore)\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should withdraw 100% via claimAndWithdraw\", async () => {\n                // To enable 100% of the withdraw from d1 and d2\n                await crabStrategyV2.connect(d5).deposit({\n                    value: ethers.utils.parseEther('10')\n                })\n\n                initialize(d1.address)\n                const d1SharesExpected = await crabMigration.sharesDeposited(d1.address)\n                const d1Osqth = wdiv(wmul(d1SharesExpected, shortV2), crabV2Supply)\n                let oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n                const maxEthToPay = wmul(d1Osqth, oSqthPrice).mul(1005).div(1000) // .5% slippage\n\n                await crabMigration.connect(d1).claimAndWithdraw(d1SharesExpected, maxEthToPay, 3000)\n                const d1SharesInMigration = await crabMigration.sharesDeposited(d1.address)\n                const d1Shares = await crabStrategyV2.balanceOf(d1.address)\n                expect(d1Shares).to.be.equal(0)\n                expect(d1SharesInMigration).to.be.equal(0)\n\n                initialize(d2.address)\n                oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n                const d2SharesExpected = await crabMigration.sharesDeposited(d2.address)\n                const d2Osqth = wdiv(wmul(d1SharesExpected, shortV2), crabV2Supply)\n                const maxEthToPay2 = wmul(d2Osqth, oSqthPrice).mul(1005).div(1000) // .5% slippage\n\n                await crabMigration.connect(d2).claimAndWithdraw(d2SharesExpected, maxEthToPay2, 3000)\n                const d2SharesInMigration = await crabMigration.sharesDeposited(d1.address)\n                const d2Shares = await crabStrategyV2.balanceOf(d2.address)\n                expect(d2Shares).to.be.equal(0)\n                expect(d2SharesInMigration).to.be.equal(0)\n            })\n        })\n\n        describe(\"Case 12: batchMigrate() -> flashMigrate -> flashMigrateAndWithdraw -> 100% Claim\", async () => {\n            before(\"Seed V1 and deploy migration\", async () => {\n                await deployAndSeedV1()\n                await deployCrabMigration()\n                await depositSharesAndBatchMigrate()\n            })\n\n            it(\"Should flashMigrate\", async () => {\n                let gasPaid = BigNumber.from(0)\n                await initialize(d4.address)\n                await increaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, , ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                const crabV2SharesBefore = await crabStrategyV2.balanceOf(d4.address)\n                const crabV2SharesInMigrationBefore = await crabStrategyV2.balanceOf(crabMigration.address)\n                const d1Shares = await crabMigration.sharesDeposited(d1.address)\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2SharesInMigrationBefore).to.be.equal(d1Shares.add(d2Shares)) // As d1 and d2 did not claim it yet\n\n\n                expect(wdiv(collatV1, shortV1).gt(wdiv(collatV2, shortV2))).to.be.true\n                expect(isFlashMigrate).to.be.true\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.true\n\n                const excessEth = ethToGetFromV1.sub(ethNeededForV2)\n                const depositShare = wdiv(ethNeededForV2, collatV2.add(ethNeededForV2))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(d4).approve(crabMigration.address, crabV1SharesBefore);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(d4).flashMigrateFromV1toV2(crabV1SharesBefore, 0, squeethPoolFee);\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(d4.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(d4.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(d4.address)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesBefore).to.be.equal('0')\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(userEthBalanceAfter).to.be.equal(userEthBalance.add(excessEth).sub(gasPaid))\n                expect(crabV2SharesInMigration).to.be.equal(crabV2SharesInMigrationBefore) // D2 shares should not be given away to Joe Squlark \n                expect(squeethBalance).to.be.equal('0')\n                await decreaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should flashMigrateAndWithdraw\", async () => {\n                let gasPaid = BigNumber.from(0)\n                const depositor = d3\n                await initialize(depositor.address)\n                await decreaseCR1(ethers.utils.parseEther('10'))\n                const [isFlashMigrate, ethNeededForV2, v1oSqthToPay, ethToGetFromV1] = await crabMigration.flashMigrationDetails(crabV1SharesBefore)\n                expect(isFlashMigrate).to.be.false\n                expect(ethToGetFromV1.gt(ethNeededForV2)).to.be.false\n                const d1Shares = await crabMigration.sharesDeposited(d1.address)\n                const d2Shares = await crabMigration.sharesDeposited(d2.address)\n                expect(crabV2inMigrationBefore).to.be.equal(d1Shares.add(d2Shares)) // 100% withdraw\n\n                const oSqthPrice = await oracle.getTwap(wethOsqthPoolAddress, squeethAddress, wethAddress, 1, false)\n\n                const numerator = ethToGetFromV1.sub(wmul(v1oSqthToPay, oSqthPrice).mul(101).div(100)) // 1% slippage\n                const denominator = one.sub(wdiv(oSqthPrice.mul(101).div(100), wdiv(collatV2, shortV2)))\n                const ethToFlashLoan = wdiv(numerator, denominator)\n                const expectedSqthFromV2 = wdiv(wmul(ethToFlashLoan, shortV2), collatV2)\n                const v1SqthToFlashWithdraw = v1oSqthToPay.sub(expectedSqthFromV2)\n                const maxEthToPay = wmul(v1SqthToFlashWithdraw, oSqthPrice).mul(1005).div(1000) // .5% slippage\n                const ethToGetFromWithdraw = wdiv(wmul(expectedSqthFromV2, collatV1), shortV1)\n                const ethToGetFromFlashWithdraw = wdiv(wmul(v1SqthToFlashWithdraw, collatV1), shortV1).sub(maxEthToPay)\n                const expectedEth = ethToGetFromFlashWithdraw.add(ethToGetFromWithdraw).sub(ethToFlashLoan)\n                const squeethBalance = await oSqth.balanceOf(crabMigration.address)\n\n                const depositShare = wdiv(ethToFlashLoan, collatV2.add(ethToFlashLoan))\n                const expectedV2Shares = wdiv(wmul(depositShare, crabV2Supply), one.sub(depositShare))\n\n                const tx1 = await crabStrategyV1.connect(depositor).approve(crabMigration.address, ethers.constants.MaxUint256);\n                gasPaid = await getGasPaid(tx1)\n\n                const tx2 = await crabMigration.connect(depositor).flashMigrateAndWithdrawFromV1toV2(crabV1SharesBefore, 0, ethToFlashLoan, maxEthToPay, squeethPoolFee)\n                gasPaid = gasPaid.add(await getGasPaid(tx2))\n\n                const crabV1SharesAfter = await crabStrategyV1.balanceOf(depositor.address)\n                const crabV2SharesAfter = await crabStrategyV2.balanceOf(depositor.address)\n                const crabV1SharesInMigration = await crabStrategyV1.balanceOf(crabMigration.address)\n                const crabV2SharesInMigration = await crabStrategyV2.balanceOf(crabMigration.address)\n                const userEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n                expect(crabV1SharesAfter).to.be.equal('0')\n                expect(crabV1SharesInMigration).to.be.equal('0')\n                expect(crabV2SharesInMigration).to.be.equal(crabV2inMigrationBefore)\n                expect(crabV2SharesAfter).to.be.equal(expectedV2Shares)\n                expect(squeethBalance).to.be.equal('0')\n                expect(userEthBalanceAfter.gte(userEthBalance.add(expectedEth).sub(gasPaid))).to.be.true\n                await increaseCR1(ethers.utils.parseEther('10'))\n            })\n\n            it(\"Should withdraw 100% via claim\", async () => {\n                const d1SharesExpected = await crabMigration.sharesDeposited(d1.address)\n                await crabMigration.connect(d1).claimV2Shares()\n                const d1Shares = await crabStrategyV2.balanceOf(d1.address)\n\n                const d2SharesExpected = await crabMigration.sharesDeposited(d2.address)\n                await crabMigration.connect(d2).claimV2Shares()\n                const d2Shares = await crabStrategyV2.balanceOf(d2.address)\n\n                expect(d1Shares).to.be.equal(d1SharesExpected)\n                expect(d2Shares).to.be.equal(d2SharesExpected)\n            })\n        })\n    })\n})"
  },
  {
    "path": "packages/hardhat/test/e2e/periphery/controller-helper.ts",
    "content": "// mainnet fork tests\n// in 1 terminal: npx hardhat node --fork https://mainnet.infura.io/v3/infura_key --fork-block-number 14345140 --no-deploy --network hardhat\n// in 2 terminal: MAINNET_FORK=true npx hardhat test ./test/e2e/periphery/controller-helper.ts\nimport { ethers, network} from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers, BytesLike, BigNumberish, constants } from \"ethers\";\nimport BigNumberJs from 'bignumber.js'\n\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { WETH9, MockErc20, ShortPowerPerp, Controller, Oracle, WPowerPerp, ControllerHelper, INonfungiblePositionManager, SqrtPriceMathPartial} from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor, getNow } from \"../../utils\"\n\nimport {\n  abi as POSITION_MANAGER_ABI,\n  bytecode as POSITION_MANAGER_BYTECODE,\n} from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'\nimport {\n  abi as FACTORY_ABI,\n  bytecode as FACTORY_BYTECODE,\n} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json'\nimport {\n  abi as ROUTER_ABI,\n  bytecode as ROUTER_BYTECODE,\n} from '@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json'\nimport {\n  abi as POOL_ABI,\n  bytecode as POOL_BYTECODE,\n} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Pool.sol/UniswapV3Pool.json'\n\nimport {\n  abi as QUOTER_ABI,\n  bytecode as QUOTER_BYTECODE,\n} from \"@uniswap/v3-periphery/artifacts/contracts/lens/Quoter.sol/Quoter.json\"\n\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\nconst impersonateAddress = async (address: string) => {\n  const hre = require('hardhat');\n  await hre.network.provider.request({\n    method: 'hardhat_impersonateAccount',\n    params: [address],\n  });\n  let signer: any;\n  signer = await ethers.provider.getSigner(address);\n  signer.address = signer._address;\n  signer._signer = signer;\n  return signer;\n};\n\ndescribe(\"ControllerHelper: mainnet fork\", function () {\n  if (!process.env.MAINNET_FORK) return;\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let controllerSigner: SignerWithAddress;\n  // let depositor: JsonRpcSigner\n  let feeRecipient: SignerWithAddress;\n  let usdc: Contract\n  let weth: Contract\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let uniswapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let ethUsdcPool: Contract\n  let controllerHelper: ControllerHelper\n  let shortSqueeth: ShortPowerPerp\n  let quoter: Contract\n\n  this.beforeAll(\"Setup mainnet fork contracts\", async () => {\n    depositor = await impersonateAddress(\"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\");\n    owner = await impersonateAddress('0xDA9dfA130Df4dE4673b89022EE50ff26f6EA73Cf');\n    controllerSigner = await impersonateAddress('0x64187ae08781B09368e6253F9E94951243A493D5');\n    // const usdcContract = await ethers.getContractFactory(\"MockErc20\")\n    usdc = await ethers.getContractAt(\"MockErc20\", \"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\")\n    // const wethContract = await ethers.getContractFactory(\"WETH9\")\n    // weth = await wethContract.attach(\"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\")\n    weth = await ethers.getContractAt(\"WETH9\", \"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\");\n\n    positionManager = await ethers.getContractAt(POSITION_MANAGER_ABI, \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\");\n    uniswapFactory = await ethers.getContractAt(FACTORY_ABI, \"0x1F98431c8aD98523631AE4a59f267346ea31F984\");\n    uniswapRouter = await ethers.getContractAt(ROUTER_ABI, \"0xE592427A0AEce92De3Edee1F18E0157C05861564\");\n\n    controller = (await ethers.getContractAt(\"Controller\", \"0x64187ae08781B09368e6253F9E94951243A493D5\")) as Controller\n    wSqueeth = (await ethers.getContractAt(\"WPowerPerp\", \"0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B\")) as WPowerPerp\n    oracle = (await ethers.getContractAt(\"Oracle\", \"0x65D66c76447ccB45dAf1e8044e918fA786A483A1\")) as Oracle\n    shortSqueeth = (await ethers.getContractAt(\"ShortPowerPerp\", \"0xa653e22A963ff0026292Cc8B67941c0ba7863a38\")) as ShortPowerPerp\n    wSqueethPool = await ethers.getContractAt(POOL_ABI, \"0x82c427AdFDf2d245Ec51D8046b41c4ee87F0d29C\")\n    ethUsdcPool = await ethers.getContractAt(POOL_ABI, \"0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8\");\n    quoter = await ethers.getContractAt(QUOTER_ABI, \"0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6\");\n\n    const TickMathExternal = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathExternalLib = (await TickMathExternal.deploy());\n\n    const SqrtPriceMathPartial = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceMathPartialLib = (await SqrtPriceMathPartial.deploy());\n\n    const ControllerHelperUtil = await ethers.getContractFactory(\"ControllerHelperUtil\", {libraries: {TickMathExternal: TickMathExternalLib.address, SqrtPriceMathPartial: SqrtPriceMathPartialLib.address}});\n    const ControllerHelperUtilLib = (await ControllerHelperUtil.deploy());\n    \n    const ControllerHelperContract = await ethers.getContractFactory(\"ControllerHelper\", {libraries: {ControllerHelperUtil: ControllerHelperUtilLib.address}});\n    controllerHelper = (await ControllerHelperContract.deploy(controller.address, positionManager.address, uniswapFactory.address, \"0x59828FdF7ee634AaaD3f58B19fDBa3b03E2D9d80\", \"0x27182842E098f60e3D576794A5bFFb0777E025d3\", \"0x62e28f054efc24b26A794F5C1249B6349454352C\")) as ControllerHelper;\n  })\n\n  describe(\"Flash mint short position, LP and use LP as collateral\", async () => {\n    it(\"open short, mint, LP oSQTH + ETH, deposit LP NFT and withdraw ETH collateral\", async ()=> {\n      const vaultId = (await shortSqueeth.nextId());\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('50')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralToMint = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n      const flashloanFee = collateralToMint.mul(9).div(1000)\n      const flashloanWMintDepositNftParams = {\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: 0,\n        wPowerPerpAmount: mintWSqueethAmount.toString(),\n        collateralToDeposit: collateralToMint.toString(),\n        collateralToFlashloan: collateralToMint.toString(),\n        collateralToLp: collateralToLp.toString(),\n        collateralToWithdraw: 0,\n        amount0Min: 0,\n        amount1Min: 0,\n        lowerTick: -887220,\n        upperTick: 887220\n      }\n\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await controllerHelper.connect(depositor).flashloanWMintLpDepositNft(flashloanWMintDepositNftParams, {value: collateralToLp.add(ethers.utils.parseUnits('0.01').add(flashloanFee))})\n\n      const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const vaultAfter = await controller.vaults(vaultId)\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n\n      expect(BigNumber.from(vaultAfter.NftCollateralId).eq(tokenId)).to.be.true;\n      expect(position.tickLower === -887220).to.be.true\n      expect(position.tickUpper === 887220).to.be.true\n      expect(vaultAfter.shortAmount.sub(mintWSqueethAmount).lte(1)).to.be.true\n      expect(depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore).lte(10)).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n    })\n\n    it(\"open short, mint, LP oSQTH + ETH, deposit LP NFT and withdraw ETH collateral with too much oSQTH specified\", async ()=> {\n      // this is testing that the vault is minted with ~ the correct amount of oSQTH even if way too much is specified on f/e, which is what we want\n      const vaultId = (await shortSqueeth.nextId());\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('50')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralToMint = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n      const flashloanFee = collateralToMint.mul(9).div(1000)\n      const flashloanWMintDepositNftParams = {\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: 0,\n        wPowerPerpAmount: mintWSqueethAmount.mul(2).toString(),\n        collateralToDeposit: collateralToMint.mul(2).toString(),\n        collateralToFlashloan: collateralToMint.mul(2).toString(),\n        collateralToLp: collateralToLp.toString(),\n        collateralToWithdraw: 0,\n        amount0Min: 0,\n        amount1Min: 0,\n        lowerTick: -887220,\n        upperTick: 887220\n      }\n\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await controllerHelper.connect(depositor).flashloanWMintLpDepositNft(flashloanWMintDepositNftParams, {value: collateralToLp.add(ethers.utils.parseUnits('0.01').add(flashloanFee))})\n\n      const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const vaultAfter = await controller.vaults(vaultId)\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n\n      expect(BigNumber.from(vaultAfter.NftCollateralId).eq(tokenId)).to.be.true;\n      expect(position.tickLower === -887220).to.be.true\n      expect(position.tickUpper === 887220).to.be.true\n      expect(depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore).lte(10)).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n    })\n\n    describe(\"open short in already overcollateralized vault, mint, LP oSQTH only, deposit LP NFT\", async ()=> {\n      before(async () => {\n        const normFactor = await controller.getExpectedNormalizationFactor()\n        const mintWSqueethAmountToLp : BigNumber = ethers.utils.parseUnits('35')\n        const mintRSqueethAmount = mintWSqueethAmountToLp.mul(normFactor).div(one)\n        const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n        const scaledEthPrice = ethPrice.div(10000)\n        const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n        const collateralAmount = debtInEth.mul(3)\n  \n        await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmountToLp, 0, {value: collateralAmount})  \n      })\n\n      it(\"mint short, LP and use it as collateral\", async () => {\n        const vaultId = (await shortSqueeth.nextId()).sub(1);\n        await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address);\n\n        const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n        const mintWSqueethAmount = ethers.utils.parseUnits('5')\n        const collateralToMint = BigNumber.from(0)\n        const collateralToLp = BigNumber.from(0)\n\n        const slot0 = await wSqueethPool.slot0()\n        const currentTick = slot0[1]\n  \n        const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n        const amount0Min = BigNumber.from(0);\n        const amount1Min = BigNumber.from(0);\n  \n        const newTick = isWethToken0 ? 60*((currentTick - currentTick%60)/60 - 1): 60*((currentTick - currentTick%60)/60 + 1)\n\n        const flashloanWMintDepositNftParams = {\n          wPowerPerpPool: wSqueethPool.address,\n          vaultId: vaultId,\n          wPowerPerpAmount: mintWSqueethAmount.toString(),\n          collateralToDeposit: collateralToMint.toString(),\n          collateralToFlashloan: BigNumber.from(0),\n          collateralToLp: collateralToLp.toString(),\n          collateralToWithdraw: 0,\n          amount0Min: 0,\n          amount1Min: 0,\n          lowerTick: isWethToken0 ? -887220 : newTick,\n          upperTick: isWethToken0 ? newTick : 887220,\n          }\n\n        const vaultBefore = await controller.vaults(vaultId)\n\n        await controllerHelper.connect(depositor).flashloanWMintLpDepositNft(flashloanWMintDepositNftParams)\n        \n        const vaultAfter = await controller.vaults(vaultId)\n        const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n        const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n        const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n\n        const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n  \n        expect(BigNumber.from(vaultAfter.NftCollateralId).eq(tokenId)).to.be.true;\n        expect(vaultAfter.shortAmount.sub(mintWSqueethAmount.add(vaultBefore.shortAmount)).abs().lte(10)).to.be.true\n        expect(depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore).lte(10)).to.be.true\n        expect(vaultAfter.collateralAmount.eq(vaultBefore.collateralAmount)).to.be.true\n      })\n    })\n\n    it(\"open short in new vault, mint, LP oSQTH only, deposit LP NFT\", async () => {\n      const vaultId = (await shortSqueeth.nextId());\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('100')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralToMint = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const collateralToFlashloan = collateralToMint.div(2)\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      const slot0 = await wSqueethPool.slot0()\n      const currentTick = slot0[1]\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n\n      const newTick = isWethToken0 ? 60*((currentTick - currentTick%60)/60 - 1): 60*((currentTick - currentTick%60)/60 + 1)\n      \n      const flashloanWMintDepositNftParams = {\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: 0,\n        wPowerPerpAmount: mintWSqueethAmount.toString(),\n        collateralToDeposit: collateralToMint.toString(),\n        collateralToFlashloan: collateralToFlashloan.toString(),\n        collateralToLp: BigNumber.from(0),\n        collateralToWithdraw: 0,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        lowerTick: isWethToken0 ? -887220 : newTick,\n        upperTick: isWethToken0 ? newTick : 887220,\n    }\n\n      await controllerHelper.connect(depositor).flashloanWMintLpDepositNft(flashloanWMintDepositNftParams, {value: collateralToMint.div(2).add(ethers.utils.parseUnits('0.01'))})\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n      const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n\n      expect(BigNumber.from(vaultAfter.NftCollateralId).eq(tokenId)).to.be.true;\n      expect(vaultAfter.shortAmount.sub(mintWSqueethAmount).abs().lte(10)).to.be.true      \n      expect(depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore).lte(10)).to.be.true\n      expect(vaultAfter.collateralAmount.eq(collateralToMint.sub(collateralToFlashloan))).to.be.true\n    })\n\n    it(\"open short, mint with >0 ETH collateral, LP oSQTH + ETH, deposit LP NFT\", async ()=> {\n      const vaultId = (await shortSqueeth.nextId());\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('50')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralToMint = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const collateralToFlashloan = collateralToMint.div(2)\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const flashloanWMintDepositNftParams = {\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: 0,\n        wPowerPerpAmount: mintWSqueethAmount.toString(),\n        collateralToDeposit: collateralToMint.toString(),\n        collateralToFlashloan: collateralToFlashloan.toString(),\n        collateralToLp: collateralToLp.toString(),\n        collateralToWithdraw: 0,\n        amount0Min: 0,\n        amount1Min: 0,\n        lowerTick: -887220,\n        upperTick: 887220\n      }\n\n      await controllerHelper.connect(depositor).flashloanWMintLpDepositNft(flashloanWMintDepositNftParams, {value: collateralToLp.add(collateralToMint.div(2)).add(ethers.utils.parseUnits('0.01'))})\n\n      const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const vaultAfter = await controller.vaults(vaultId)\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n\n      expect(BigNumber.from(vaultAfter.NftCollateralId).eq(tokenId)).to.be.true;\n      expect(position.tickLower === -887220).to.be.true\n      expect(position.tickUpper === 887220).to.be.true\n      expect(vaultAfter.shortAmount.sub(mintWSqueethAmount).lte(1)).to.be.true\n      expect(depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore).lte(10)).to.be.true\n\n      expect(vaultAfter.collateralAmount.sub(collateralToMint.div(2)).lte(1)).to.be.true\n    })\n\n    it(\"existing vault, mint with >0 ETH collateral, LP oSQTH + ETH, deposit LP NFT\", async ()=> {\n      // Make new vault with 2x collateral\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount : BigNumber = ethers.utils.parseUnits('50')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralToDeposit = debtInEth.mul(2)\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralToDeposit})\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n      // Get before context\n      const vaultBefore = await controller.vaults(vaultId)\n      const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n      // Set up for full range LP with half collateral flashloaned\n      const collateralToMint = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const collateralToFlashloan = collateralToMint.div(2)\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n      const flashloanWMintDepositNftParams = {\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: vaultId,\n        wPowerPerpAmount: mintWSqueethAmount.toString(),\n        collateralToDeposit: collateralToMint.toString(),\n        collateralToFlashloan: collateralToFlashloan.toString(),\n        collateralToLp: collateralToLp.toString(),\n        collateralToWithdraw: 0,\n        amount0Min: 0,\n        amount1Min: 0,\n        lowerTick: -887220,\n        upperTick: 887220\n      }\n      // Look at transasction\n      const tx = await controllerHelper.connect(depositor).flashloanWMintLpDepositNft(flashloanWMintDepositNftParams, {value: collateralToLp.add(collateralToMint)})\n      const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n      // Get after context\n      const vaultAfter = await controller.vaults(vaultId)\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(tokenId); \n      const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n\n      expect(BigNumber.from(vaultAfter.NftCollateralId).eq(tokenId)).to.be.true;\n      expect(position.tickLower === -887220).to.be.true\n      expect(position.tickUpper === 887220).to.be.true\n      expect(ownerOfUniNFT === controller.address).to.be.true\n      //expect(vaultAfter.shortAmount.sub(vaultBefore.shortAmount).sub(mintWSqueethAmount).abs().lte(1000)).to.be.true\n      expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).sub((collateralToMint.sub(collateralToFlashloan))).eq(0)).to.be.true\n      expect(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).sub(gasSpent).sub((collateralToMint.sub(collateralToFlashloan))).lte(1)).to.be.true\n    })\n\n    it(\"open short in new vault, mint, LP oSQTH only, deposit LP NFT, no eth added\", async () => {\n      // New vault with 2x collateral\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount : BigNumber = ethers.utils.parseUnits('40')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralToDeposit = debtInEth.mul(2)\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralToDeposit})\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n      // Get before context\n      const vaultBefore = await controller.vaults(vaultId)\n      const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n\n      const slot0 = await wSqueethPool.slot0()\n      const currentTick = slot0[1]\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n\n      const newTick = isWethToken0 ? 60*((currentTick - currentTick%60)/60 - 10): 60*((currentTick - currentTick%60)/60 + 10)\n      \n      // Flashloan to cover complete removal of LP (rearrange collateral ratio formula for 1.5 and add 0.1 ETH safety margin)\n      const flashLoanAmount = (vaultBefore.shortAmount.add(mintWSqueethAmount)).mul(normFactor).mul(ethPrice).mul(3).div(one.mul(one).mul(10000).mul(2)).sub(vaultBefore.collateralAmount).add(ethers.utils.parseUnits('0.1'))\n\n      const flashloanWMintDepositNftParams = {\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: vaultId,\n        wPowerPerpAmount: mintWSqueethAmount,\n        collateralToDeposit: flashLoanAmount,\n        collateralToFlashloan: flashLoanAmount,\n        collateralToLp: 0,\n        collateralToWithdraw: 0,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        lowerTick: isWethToken0 ? -887220 : newTick,\n        upperTick: isWethToken0 ? newTick : 887220,\n    }\n      // Set up for one-sided LP with oSQTH only with half collateral flashloaned\n\n\n      const tx = await controllerHelper.connect(depositor).flashloanWMintLpDepositNft(flashloanWMintDepositNftParams)\n      const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n      // Get after context\n      const vaultAfter = await controller.vaults(vaultId)\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(tokenId); \n      const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n\n      expect(BigNumber.from(vaultAfter.NftCollateralId).eq(tokenId)).to.be.true;\n      expect(position.tickLower === (isWethToken0 ? -887220 : newTick)).to.be.true\n      expect(position.tickUpper === (isWethToken0 ? newTick : 887220)).to.be.true\n      expect(ownerOfUniNFT === controller.address).to.be.true\n      expect(vaultAfter.shortAmount.sub(vaultBefore.shortAmount).sub(mintWSqueethAmount).abs().lte(10)).to.be.true\n      expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).eq(0)).to.be.true\n      expect(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).sub(gasSpent).lte(1)).to.be.true\n    })\n    \n\n    it(\"open short in new vault, mint, LP oSQTH only, deposit LP NFT, some eth added\", async () => {\n      // New vault with 1.5x collateral\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount : BigNumber = ethers.utils.parseUnits('100')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralToDeposit = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralToDeposit})\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n      // Get before context\n      const vaultBefore = await controller.vaults(vaultId)\n      const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n      // Mint full range into vault with no added eth\n      const flashloanWMintDepositNftParams = {\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: vaultId.toString(),\n        wPowerPerpAmount: mintWSqueethAmount.toString(),\n        collateralToDeposit: collateralToDeposit.add(debtInEth).toString(),\n        collateralToFlashloan: debtInEth.toString(),\n        collateralToLp: BigNumber.from(0),\n        collateralToWithdraw: 0,\n        amount0Min: 0,\n        amount1Min: 0,\n        lowerTick: -887220,\n        upperTick: 0\n      }\n      const tx = await controllerHelper.connect(depositor).flashloanWMintLpDepositNft(flashloanWMintDepositNftParams, {value: collateralToDeposit})\n      const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n      // Get after context\n      const vaultAfter = await controller.vaults(vaultId)\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(tokenId); \n      const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n      expect(BigNumber.from(vaultAfter.NftCollateralId).eq(tokenId)).to.be.true;\n      expect(position.tickLower === -887220).to.be.true\n      expect(position.tickUpper === 0).to.be.true\n      expect(ownerOfUniNFT === controller.address).to.be.true\n      expect(vaultAfter.shortAmount.sub(mintWSqueethAmount.mul(2)).abs().lte(10)).to.be.true\n      expect(vaultAfter.collateralAmount.eq(collateralToDeposit.mul(2))).to.be.true\n      expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).sub(collateralToDeposit).eq(0)).to.be.true\n      expect(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).add(gasSpent).add(collateralToDeposit).abs().lte(1)).to.be.true\n \n    })    \n  })\n\n  describe(\"Close LP position in vault: LP have more wPowerPerp than needed amount to burn\", async () => {\n    before(\"open first short position and LP\" , async () => {\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmountToLp : BigNumber = ethers.utils.parseUnits('50')\n      const mintRSqueethAmount = mintWSqueethAmountToLp.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const collateralToLp = mintWSqueethAmountToLp.mul(squeethPrice).div(one)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmountToLp, 0, {value: collateralAmount})\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n\n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : mintWSqueethAmountToLp,\n        amount1Desired: isWethToken0 ? mintWSqueethAmountToLp : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n\n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n    })\n\n    before(\"open short amount more than amount in LP position\" , async () => {\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('35')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controller.address, tokenId)\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, tokenId)\n    })\n\n    it(\"close LP position deposited as collateral in vault\", async () => {\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const uniTokenId =  (await controller.vaults(vaultId)).NftCollateralId;\n      const vaultBefore = await controller.vaults(vaultId); \n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = vaultBefore.shortAmount.mul(scaledEthPrice).div(one)\n      const collateralToFlashloan = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.sub(slippage)).div(one);\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(uniTokenId);\n\n      const flashloanCloseVaultLpNftParam = {\n        vaultId: vaultId,\n        tokenId: uniTokenId,\n        liquidity: positionBefore.liquidity,\n        liquidityPercentage: ethers.utils.parseUnits('1'),\n        wPowerPerpAmountToBurn: vaultBefore.shortAmount.toString(),\n        collateralToFlashloan: collateralToFlashloan.toString(),\n        collateralToWithdraw: BigNumber.from(0),\n        limitPriceEthPerPowerPerp: limitPriceEthPerPowerPerp.toString(),\n        amount0Min: 0,\n        amount1Min: 0,\n        poolFee: 3000,\n        burnExactRemoved: false\n      }\n\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address);\n      await controllerHelper.connect(depositor).flashloanCloseVaultLpNft(flashloanCloseVaultLpNftParam);\n\n      const positionAfter = await (positionManager as INonfungiblePositionManager).positions(uniTokenId);\n      const vaultAfter = await controller.vaults(vaultId); \n\n      expect(positionAfter.tickLower === -887220).to.be.true\n      expect(positionAfter.tickUpper === 887220).to.be.true\n      expect(positionAfter.liquidity.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n    })\n  })\n\n  describe(\"Close LP position in vault: LP have less wPowerPerp than needed amount to burn\", async () => {\n    before(\"open first short position and LP\" , async () => {\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmountToLp : BigNumber = ethers.utils.parseUnits('50')\n      const mintRSqueethAmount = mintWSqueethAmountToLp.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const collateralToLp = mintWSqueethAmountToLp.mul(squeethPrice).div(one)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmountToLp, 0, {value: collateralAmount})\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n\n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : mintWSqueethAmountToLp,\n        amount1Desired: isWethToken0 ? mintWSqueethAmountToLp : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n\n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n    })\n\n    before(\"open short amount more than amount in LP position\" , async () => {\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('55')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controller.address, tokenId)\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, tokenId)\n    })\n\n    it(\"close LP position deposited as collateral in vault\", async () => {\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const uniTokenId =  (await controller.vaults(vaultId)).NftCollateralId;\n      const vaultBefore = await controller.vaults(vaultId); \n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = vaultBefore.shortAmount.mul(scaledEthPrice).div(one)\n      const collateralToFlashloan = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.add(slippage)).div(one);\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(uniTokenId);\n      const flashloanCloseVaultLpNftParam = {\n        vaultId: vaultId,\n        tokenId: uniTokenId,\n        liquidity: positionBefore.liquidity,\n        liquidityPercentage: ethers.utils.parseUnits('1'),\n        wPowerPerpAmountToBurn: vaultBefore.shortAmount.toString(),\n        collateralToFlashloan: collateralToFlashloan.toString(),\n        collateralToWithdraw: BigNumber.from(0),\n        limitPriceEthPerPowerPerp: limitPriceEthPerPowerPerp.toString(),\n        amount0Min: 0,\n        amount1Min: 0,\n        poolFee: 3000,\n        burnExactRemoved: false\n      }\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address);\n      await controllerHelper.connect(depositor).flashloanCloseVaultLpNft(flashloanCloseVaultLpNftParam, {value: ethers.utils.parseUnits('2')});\n      const positionAfter = await (positionManager as INonfungiblePositionManager).positions(uniTokenId);\n      const vaultAfter = await controller.vaults(vaultId); \n\n      expect(positionAfter.tickLower === -887220).to.be.true\n      expect(positionAfter.tickUpper === 887220).to.be.true\n      expect(positionAfter.liquidity.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n    })\n  })\n\n  describe(\"Collect fees from vault and redeposit\", async () => {\n    before(\"open short position and LP\" , async () => {\n      const vaultId = (await shortSqueeth.nextId());\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('50')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralToMint = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const collateralToFlashloan = collateralToMint\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n      const flashloanWMintDepositNftParams = {\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: 0,\n        wPowerPerpAmount: mintWSqueethAmount.toString(),\n        collateralToDeposit: collateralToFlashloan.toString(),\n        collateralToFlashloan: collateralToFlashloan.toString(),\n        collateralToLp: collateralToLp.toString(),\n        collateralToWithdraw: 0,\n        amount0Min: 0,\n        amount1Min: 0,\n        lowerTick: -887220,\n        upperTick: 887220\n      }\n\n      await controllerHelper.connect(depositor).flashloanWMintLpDepositNft(flashloanWMintDepositNftParams, {value: collateralToLp})\n    })\n\n    it(\"swap with pool, collect fees and redeposit uni nft in vault\", async () => {\n      \n      const ethToSell = ethers.utils.parseUnits(\"5\")\n      const swapParamBuy = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        amountIn: ethToSell.toString(),\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0\n      }    \n\n      weth.connect(owner).deposit({value: ethToSell})\n \n      const ownerSqueethBalanceBeforeTrade1 = await wSqueeth.balanceOf(owner.address)\n      const ownerWethBalanceBeforeTrade1 = await weth.balanceOf(owner.address)\n\n      await weth.connect(owner).approve(uniswapRouter.address, constants.MaxUint256)\n\n      await uniswapRouter.connect(owner).exactInputSingle(swapParamBuy)\n\n      const ownerSqueethBalanceAfterTrade1 = await wSqueeth.balanceOf(owner.address)\n      const ownerWethBalanceAfterTrade1 = await weth.balanceOf(owner.address)\n\n      expect(ownerWethBalanceBeforeTrade1.sub(ownerWethBalanceAfterTrade1).eq(ethToSell)).to.be.true\n      // \n      const wSqueethToSell = ownerSqueethBalanceAfterTrade1.sub(ownerSqueethBalanceBeforeTrade1).sub(ethers.utils.parseUnits('0.01'))\n      const swapParamSell = {\n        tokenIn: wSqueeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        amountIn: wSqueethToSell.toString(),\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0\n      }    \n\n      const ownerSqueethBalanceBeforeTrade2 = await wSqueeth.balanceOf(owner.address)\n      await wSqueeth.connect(owner).approve(uniswapRouter.address, constants.MaxUint256)\n      await uniswapRouter.connect(owner).exactInputSingle(swapParamSell)\n      const ownerSqueethBalanceAfterTrade2 = await wSqueeth.balanceOf(owner.address)\n      expect(ownerSqueethBalanceBeforeTrade2.sub(ownerSqueethBalanceAfterTrade2).eq(wSqueethToSell)).to.be.true\n\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const uniTokenId =  (await controller.vaults(vaultId)).NftCollateralId;\n      const vaultBefore = await controller.vaults(vaultId); \n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = vaultBefore.shortAmount.mul(scaledEthPrice).div(one)\n      const collateralToFlashloan = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(uniTokenId);\n\n      const amount0Max = BigNumber.from(2).mul(BigNumber.from(10).pow(18)).sub(1)\n      const amount1Max = BigNumber.from(2).mul(BigNumber.from(10).pow(18)).sub(1)\n\n      const abiCoder = new ethers.utils.AbiCoder\n      const rebalanceLpInVaultParams = [\n      {\n          rebalanceLpInVaultType: BigNumber.from(6),\n          // CollectFees\n          data: abiCoder.encode([\"uint256\", \"uint128\", \"uint128\"], [uniTokenId, amount0Max, amount1Max])\n        },\n        {\n          rebalanceLpInVaultType: BigNumber.from(7),\n          // DepositExistingNftParams\n          data: abiCoder.encode([\"uint256\"], [uniTokenId])\n        }\n      ]\n\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address);\n\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n      const tx = await controllerHelper.connect(depositor).rebalanceLpInVault(vaultId, collateralToFlashloan, rebalanceLpInVaultParams);\n\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n      const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n\n      const positionAfter = await (positionManager as INonfungiblePositionManager).positions(uniTokenId);\n      const vaultAfter = await controller.vaults(vaultId); \n\n      expect(positionAfter.tickLower === -887220).to.be.true\n      expect(positionAfter.tickUpper === 887220).to.be.true\n      expect(positionAfter.liquidity.eq(positionBefore.liquidity)).to.be.true\n      expect(vaultAfter.NftCollateralId==vaultBefore.NftCollateralId).to.be.true\n      expect(depositorSqueethBalanceAfter.gt(depositorSqueethBalanceBefore)).to.be.true\n      expect(depositorEthBalanceAfter.add(gasSpent).gt(depositorEthBalanceBefore)).to.be.true \n\n    })\n  })\n\n  describe(\"Rebalance with vault\", async () => {\n      before(\"Mint new full range LP outside of vault\" , async () => {\n        // Mint 50 squeeth in new vault\n        const normFactor = await controller.getExpectedNormalizationFactor()\n        const mintWSqueethAmount = ethers.utils.parseUnits('50')\n        const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n        const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n        const scaledEthPrice = ethPrice.div(10000)\n        const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n        const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n        const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n        const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n        const batchMintLpParams = {\n          recipient: depositor.address,\n          wPowerPerpPool: wSqueethPool.address,\n          vaultId: 0,\n          wPowerPerpAmount: mintWSqueethAmount,\n          collateralToDeposit: collateralAmount,\n          collateralToLp: collateralToLp,\n          amount0Min: 0,\n          amount1Min: 0,\n          lowerTick: -887220,\n          upperTick: 887220\n        }\n        // Batch mint new full range LP\n        await controllerHelper.connect(depositor).wMintLp(batchMintLpParams, {value: collateralAmount.add(collateralToLp)});\n       })\n\n        \n    it(\"Close vault LP and open new LP with the a different range, same amount of ETH and oSQTH\", async () => {\n      // Get vault and LP info\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const tokenIndex = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndex.sub(1));\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16)\n      // Get current LPpositions\n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: 0,\n        amount1Min: 0,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLPBefore = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLPBefore = (isWethToken0) ? amount0 : amount1;\n      // deposit nft to vault (approve first)\n      await shortSqueeth.connect(depositor).approve(controller.address, vaultId);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n      await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controller.address, true) // approval for controller \n      await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controllerHelper.address, true) // approve controllerHelper\n      // Deposit nft to vault\n      await controller.connect(depositor).depositUniPositionToken(vaultId, tokenId)\n      // Withdraw some ETH from vault (so not purely collateralized with ETH)\n      const withdrawFromVault = wethAmountInLPBefore\n      await controller.connect(depositor).withdraw(vaultId, withdrawFromVault)\n      const vaultBefore = await controller.vaults(vaultId);\n      // Setup for mint of new LP\n      const slot0 = await wSqueethPool.slot0()\n      const currentTick = slot0[1]\n      // Closest 600 tick width around current tick (60 is minimum tick width for 30bps pool)\n      const newTickLower = 60*((currentTick - currentTick%60)/60 - 10)\n      const newTickUpper = 60*((currentTick - currentTick%60)/60 + 10)\n      //const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n      // random additional proceeds from swap\n      const surpriseProceeds = ethers.utils.parseUnits('0.01')\n      // Setup rebalanceVaultNft call\n      const abiCoder = new ethers.utils.AbiCoder\n      const rebalanceLpInVaultParams = [\n        {\n          // Remove liquidity\n          rebalanceLpInVaultType: BigNumber.from(1), // DecreaseLpLiquidity:\n          // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min]\n          data: abiCoder.encode([\"uint256\", 'uint256', 'uint256', 'uint128', 'uint128'],\n           [tokenId, positionBefore.liquidity, BigNumber.from(100).mul(BigNumber.from(10).pow(16)), BigNumber.from(0), BigNumber.from(0)])\n          },\n         {\n           // Mint new LP (add 0.01 oSQTH noise since exact value will not be known)\n           rebalanceLpInVaultType: BigNumber.from(4), // MintNewLP\n           // MintAndLpParams: [recipient, wPowerPerpPool, vaultId, wPowerPerpAmount, collateralToDeposit, collateralToLP, amount0Min, amount1Min, lowerTick, upperTick ]\n           data: abiCoder.encode([\"address\", \"address\", \"uint256\", 'uint256','uint256', 'uint256', 'uint256', 'uint256', 'int24', 'int24'],\n            [controllerHelper.address, wSqueethPool.address, vaultId, wPowerPerpAmountInLPBefore.add(surpriseProceeds), BigNumber.from(0), wethAmountInLPBefore, amount0Min, amount1Min, newTickLower, newTickUpper])\n         }\n      ]\n      // Flashloan to cover complete removal of LP (rearrange collateral ratio formula for 1.5 and add 0.1 ETH safety margin)\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      const flashLoanAmount = (vaultBefore.shortAmount).mul(normFactor).mul(ethPrice).mul(3).div(one.mul(one).mul(10000).mul(2)).sub(vaultBefore.collateralAmount).add(ethers.utils.parseUnits('0.1'))\n      const tx = await controllerHelper.connect(depositor).rebalanceLpInVault(vaultId, flashLoanAmount, rebalanceLpInVaultParams);\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n      const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n      // Get new vault and LP info\n      const vaultAfter = await controller.vaults(vaultId);\n      const tokenIdAfter = vaultAfter.NftCollateralId;\n      const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenIdAfter)\n      const [amount0After, amount1After] = await (positionManager as INonfungiblePositionManager).connect(controllerSigner).callStatic.decreaseLiquidity({\n        tokenId: tokenIdAfter,\n        liquidity: positionAfter.liquidity,\n        amount0Min: 0,\n        amount1Min: 0,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLPAfter = (isWethToken0) ? amount1After : amount0After;\n      const wethAmountInLPAfter = (isWethToken0) ? amount0After : amount1After;\n      // Changes\n      const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n      const depositorSqueethDiff = depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)\n      const vaultEthDiff = vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount)\n      const vaultSqueethDiff = vaultAfter.shortAmount.sub(vaultBefore.shortAmount)\n      const lpEthDiff = wethAmountInLPAfter.sub(wethAmountInLPBefore)\n      const lpSqueethDiff = wPowerPerpAmountInLPAfter.sub(wPowerPerpAmountInLPBefore)\n      // Assertions\n      expect(positionAfter.tickLower === newTickLower).to.be.true\n      expect(positionAfter.tickUpper === newTickUpper).to.be.true\n      expect(vaultAfter.collateralAmount.eq(vaultBefore.collateralAmount)).to.be.true\n      expect(vaultAfter.NftCollateralId==vaultBefore.NftCollateralId).to.be.false\n      // Squeeth preserving\n      expect(depositorSqueethDiff.sub(vaultSqueethDiff).add(lpSqueethDiff).abs().lte(10)).to.be.true\n    })\n  })\n\n  describe(\"Rebalance LP in vault to just weth\", async () => {\n    before(\"Mint new full range LP outside of vault\" , async () => {\n      // Mint 50 squeeth in new vault\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('50')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n      const wMintLpParams = {\n        recipient: depositor.address,\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: 0,\n        wPowerPerpAmount: mintWSqueethAmount,\n        collateralToDeposit: collateralAmount,\n        collateralToLp: collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        lowerTick: -887220,\n        upperTick: 887220\n      }\n      // Batch mint new full range LP\n      await controllerHelper.connect(depositor).wMintLp(wMintLpParams, {value: collateralAmount.add(collateralToLp)});\n     })\n\n      \n  it(\"Close vault LP and open new one-sided LP with just eth \", async () => {\n    // Get vault and LP info\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n    const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n    const vaultId = (await shortSqueeth.nextId()).sub(1);\n    const tokenIndex = await (positionManager as INonfungiblePositionManager).totalSupply();\n    const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndex.sub(1));\n    const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n    const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16)\n    // Get current LPpositions \n    const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n      tokenId: tokenId,\n      liquidity: positionBefore.liquidity,\n      amount0Min: 0,\n      amount1Min: 0,\n      deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n    })\n    const wPowerPerpAmountInLPBefore = (isWethToken0) ? amount1 : amount0;\n    const wethAmountInLPBefore = (isWethToken0) ? amount0 : amount1;\n    // deposit nft to vault (approve first)\n    await shortSqueeth.connect(depositor).approve(controller.address, vaultId);\n    await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n    await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controller.address, true) // approval for controller \n    await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controllerHelper.address, true) // approve controllerHelper\n    // Deposit nft to vault\n    await controller.connect(depositor).depositUniPositionToken(vaultId, tokenId)\n    const vaultBefore = await controller.vaults(vaultId);\n    // Setup for mint of new LP\n    const slot0 = await wSqueethPool.slot0()\n    const currentTick = slot0[1]\n    // Range above current tick\n    const newTickLower = isWethToken0 ? 60*((currentTick - currentTick%60)/60 + 10): 60*((currentTick - currentTick%60)/60 - 20)\n    const newTickUpper = isWethToken0 ? 60*((currentTick - currentTick%60)/60 + 20): 60*((currentTick - currentTick%60)/60 - 10)\n    //const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n    const amount0Min = BigNumber.from(0);\n    const amount1Min = BigNumber.from(0);\n    // Estimate proceeds from liquidating squeeth in LP\n    const ethAmountOutFromSwap = await quoter.connect(depositor).callStatic.quoteExactInputSingle(wSqueeth.address,\n      weth.address,\n      3000,\n      wPowerPerpAmountInLPBefore,\n      0)\n    // Estimate of new LP with 0.01 weth safety margin\n    const safetyEth = ethers.utils.parseUnits('0.01')\n    const safetyWPowerPerp = ethers.utils.parseUnits('0.01')\n    const wethAmountToLP = wethAmountInLPBefore.add(ethAmountOutFromSwap).sub(safetyEth)\n    // Setup rebalanceVaultNft call\n    const abiCoder = new ethers.utils.AbiCoder\n    const rebalanceLpInVaultParams = [\n      {\n        // Liquidate LP\n        rebalanceLpInVaultType: BigNumber.from(1), // DecreaseLpLiquidity:\n        // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min]\n        data: abiCoder.encode([\"uint256\", 'uint256', 'uint256', 'uint128', 'uint128'],\n         [tokenId, positionBefore.liquidity, BigNumber.from(100).mul(BigNumber.from(10).pow(16)), BigNumber.from(0), BigNumber.from(0)])\n        },\n        {\n        // Sell all oSQTH for ETH\n        rebalanceLpInVaultType: BigNumber.from(5), // GeneralSwap:\n          // GeneralSwap: [tokenIn, tokenOut, amountIn, limitPrice]\n          data: abiCoder.encode([\"address\", 'address', 'uint256', 'uint256', 'uint24'],\n           [wSqueeth.address, weth.address, wPowerPerpAmountInLPBefore.sub(safetyWPowerPerp), BigNumber.from(0), 3000])\n          },\n       {\n         // Mint new LP \n         rebalanceLpInVaultType:  BigNumber.from(4), // MintNewLP\n         // lpWPowerPerpPool: [recipient, wPowerPerpPool, vaultId, wPowerPerpAmount, collateralToDeposit, collateralToLP, amount0Min, amount1Min, lowerTick, upperTick ]\n         data: abiCoder.encode([\"address\", \"address\", \"uint256\", 'uint256','uint256', 'uint256', 'uint256', 'uint256', 'int24', 'int24'],\n          [controllerHelper.address, wSqueethPool.address, vaultId, BigNumber.from(0), BigNumber.from(0), wethAmountToLP, amount0Min, amount1Min, newTickLower, newTickUpper])\n       }\n    ]\n    // Flashloan to cover complete removal of LP (rearrange collateral ratio formula for 1.5 and add 0.01 ETH safety margin)\n    const normFactor = await controller.getExpectedNormalizationFactor()\n    const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n    // flashloan amount to cover withdrawn LP\n    const flashLoanAmount = (vaultBefore.shortAmount).mul(normFactor).mul(ethPrice).mul(3).div(one.mul(one).mul(10000).mul(2)).sub(vaultBefore.collateralAmount).add(ethers.utils.parseUnits('0.1'))\n\n    // Rebalance vault\n    const tx = await controllerHelper.connect(depositor).rebalanceLpInVault(vaultId, flashLoanAmount, rebalanceLpInVaultParams)\n    const receipt = await tx.wait()\n    const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n    const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n    const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n    // Get new vault and LP info\n    const vaultAfter = await controller.vaults(vaultId);\n    const tokenIdAfter = vaultAfter.NftCollateralId;\n    const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenIdAfter)\n    const [amount0After, amount1After] = await (positionManager as INonfungiblePositionManager).connect(controllerSigner).callStatic.decreaseLiquidity({\n      tokenId: tokenIdAfter,\n      liquidity: positionAfter.liquidity,\n      amount0Min: 0,\n      amount1Min: 0,\n      deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n    })\n    const wPowerPerpAmountInLPAfter = (isWethToken0) ? amount1After : amount0After;\n    const wethAmountInLPAfter = (isWethToken0) ? amount0After : amount1After;\n    // Changes\n    const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n    const depositorSqueethDiff = depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)\n    const vaultEthDiff = vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount)\n    const vaultSqueethDiff = vaultAfter.shortAmount.sub(vaultBefore.shortAmount)\n    const lpEthDiff = wethAmountInLPAfter.sub(wethAmountInLPBefore)\n    const lpSqueethDiff = wPowerPerpAmountInLPAfter.sub(wPowerPerpAmountInLPBefore)\n    // Assertions\n    expect(flashLoanAmount.gt(0)).to.be.true\n    expect(positionAfter.tickLower === newTickLower).to.be.true\n    expect(positionAfter.tickUpper === newTickUpper).to.be.true\n    expect(vaultAfter.shortAmount.eq(vaultBefore.shortAmount)).to.be.true\n    expect(vaultAfter.collateralAmount.eq(vaultBefore.collateralAmount)).to.be.true\n    expect(vaultAfter.NftCollateralId==vaultBefore.NftCollateralId).to.be.false\n    expect(wPowerPerpAmountInLPAfter.eq(BigNumber.from(0))).to.be.true\n    expect(lpEthDiff.sub(ethAmountOutFromSwap).add(safetyEth).abs().lte(10)).to.be.true\n  })\n\n})\n\n\n\ndescribe(\"Rebalance LP in vault to just weth\", async () => {\n  before(\"Mint new full range LP outside of vault\" , async () => {\n    // Mint 50 squeeth in new vault\n    const normFactor = await controller.getExpectedNormalizationFactor()\n    const mintWSqueethAmount = ethers.utils.parseUnits('50')\n    const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n    const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n    const scaledEthPrice = ethPrice.div(10000)\n    const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n    const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n    const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n    const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n    const wMintLpParams = {\n      recipient: depositor.address,\n      wPowerPerpPool: wSqueethPool.address,\n      vaultId: 0,\n      wPowerPerpAmount: mintWSqueethAmount,\n      collateralToDeposit: collateralAmount,\n      collateralToLp: collateralToLp,\n      amount0Min: 0,\n      amount1Min: 0,\n      lowerTick: -887220,\n      upperTick: 887220\n    }\n    // Batch mint new full range LP\n    await controllerHelper.connect(depositor).wMintLp(wMintLpParams, {value: collateralAmount.add(collateralToLp)});\n   })\n\n\nit(\"Mint more oSQTH, withdraw half eth from LP, deposit some eth into vault and withdraw some eth \", async () => {\n  // Get vault and LP info\n  const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n  const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n  const vaultId = (await shortSqueeth.nextId()).sub(1);\n  const tokenIndex = await (positionManager as INonfungiblePositionManager).totalSupply();\n  const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndex.sub(1));\n  const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n  const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16)\n  // Get current LPpositions \n  const tokenOwner = await (positionManager as INonfungiblePositionManager).connect(depositor).ownerOf(tokenId)\n\n  const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n    tokenId: tokenId,\n    liquidity: positionBefore.liquidity,\n    amount0Min: 0,\n    amount1Min: 0,\n    deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n  })\n  const wPowerPerpAmountInLPBefore = (isWethToken0) ? amount1 : amount0;\n  const wethAmountInLPBefore = (isWethToken0) ? amount0 : amount1;\n  // deposit nft to vault (approve first)\n  await shortSqueeth.connect(depositor).approve(controller.address, vaultId);\n  await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n  await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controller.address, true) // approval for controller \n  await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controllerHelper.address, true) // approve controllerHelper\n  // Deposit nft to vault\n  await controller.connect(depositor).depositUniPositionToken(vaultId, tokenId)\n  const vaultBefore = await controller.vaults(vaultId);\n  // Estimate proceeds from liquidating squeeth in LP\n\n  // Estimate of new LP with 0.05 weth safety margin\n  const safetyEth = ethers.utils.parseUnits('0.05')\n  const wethAmountToDeposit =  wethAmountInLPBefore.div(4).sub(safetyEth)\n  const wethAmountToWithdraw =  wethAmountInLPBefore.div(4).sub(safetyEth)\n  const wPowerPerpAmountToMint = ethers.utils.parseUnits('1')\n  // Setup rebalanceVaultNft call\n  const abiCoder = new ethers.utils.AbiCoder\n  const rebalanceLpInVaultParams = [\n\n      {\n        // Liquidate half of LP \n        rebalanceLpInVaultType: BigNumber.from(1), // DecreaseLpLiquidity:\n        // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min]\n        data: abiCoder.encode([\"uint256\", 'uint256', 'uint256', 'uint128', 'uint128'],\n          [tokenId, positionBefore.liquidity, BigNumber.from(50).mul(BigNumber.from(10).pow(16)), BigNumber.from(0), BigNumber.from(0)])\n      },\n      {\n        // Deposit into vault and mint \n        rebalanceLpInVaultType: BigNumber.from(2), // DepositIntoVault\n        // DepsositIntoVault: [wPowerPerpToMint, collateralToDeposit]\n        data: abiCoder.encode([\"uint256\", 'uint256'],\n          [wPowerPerpAmountToMint, wethAmountToDeposit])\n      }\n  ]\n  // Flashloan to cover complete removal of LP (rearrange collateral ratio formula for 1.5 and add 0.01 ETH safety margin)\n  const normFactor = await controller.getExpectedNormalizationFactor()\n  const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n  const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n  const flashLoanAmount = (vaultBefore.shortAmount.add(wPowerPerpAmountToMint)).mul(normFactor).mul(ethPrice).mul(3).div(one.mul(one).mul(10000).mul(2)).sub(vaultBefore.collateralAmount).add(ethers.utils.parseUnits('0.1'))\n  // Rebalance vault\n  const tx = await controllerHelper.connect(depositor).rebalanceLpInVault(vaultId, flashLoanAmount, rebalanceLpInVaultParams)\n  const receipt = await tx.wait()\n  const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n  const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n  const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n  // Get new vault and LP info\n  const vaultAfter = await controller.vaults(vaultId);\n  const tokenIdAfter = vaultAfter.NftCollateralId;\n  const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenIdAfter)\n  const [amount0After, amount1After] = await (positionManager as INonfungiblePositionManager).connect(controllerSigner).callStatic.decreaseLiquidity({\n    tokenId: tokenIdAfter,\n    liquidity: positionAfter.liquidity,\n    amount0Min: 0,\n    amount1Min: 0,\n    deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n  })\n  const wPowerPerpAmountInLPAfter = (isWethToken0) ? amount1After : amount0After;\n  const wethAmountInLPAfter = (isWethToken0) ? amount0After : amount1After;\n  // Changes\n  const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n  const depositorSqueethDiff = depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)\n  const vaultEthDiff = vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount)\n  const vaultSqueethDiff = vaultAfter.shortAmount.sub(vaultBefore.shortAmount)\n  const lpEthDiff = wethAmountInLPAfter.sub(wethAmountInLPBefore)\n  const lpSqueethDiff = wPowerPerpAmountInLPAfter.sub(wPowerPerpAmountInLPBefore)\n\n\n  // Assertions\n  expect(vaultSqueethDiff.eq(wPowerPerpAmountToMint)).to.be.true\n  expect(vaultEthDiff.eq(wethAmountToDeposit)).to.be.true\n  expect(lpSqueethDiff.add(wPowerPerpAmountInLPBefore.div(2)).lte(10)).to.be.true\n  expect(lpEthDiff.add(wethAmountInLPBefore.div(2)).lte(10)).to.be.true\n  expect(depositorSqueethDiff.sub(wPowerPerpAmountInLPBefore.div(2)).sub(wPowerPerpAmountToMint).lte(10)).to.be.true \n})\n\n})\n\n\n\ndescribe(\"Rebalance LP in vault to just weth\", async () => {\n  before(\"Mint new full range LP outside of vault\" , async () => {\n    // Mint 50 squeeth in new vault\n    const normFactor = await controller.getExpectedNormalizationFactor()\n    const mintWSqueethAmount = ethers.utils.parseUnits('50')\n    const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n    const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n    const scaledEthPrice = ethPrice.div(10000)\n    const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n    const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n    const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n    const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n    const batchMintLpParams = {\n      recipient: depositor.address,\n      wPowerPerpPool: wSqueethPool.address,\n      vaultId: 0,\n      wPowerPerpAmount: mintWSqueethAmount,\n      collateralToDeposit: collateralAmount,\n      collateralToLp: collateralToLp,\n      amount0Min: 0,\n      amount1Min: 0,\n      lowerTick: -887220,\n      upperTick: 887220\n    }\n    // Batch mint new full range LP\n    await controllerHelper.connect(depositor).wMintLp(batchMintLpParams, {value: collateralAmount.add(collateralToLp)});\n   })\n\n\nit(\"Mint more oSQTH, withdraw half eth from LP, deposit some eth into vault and withdraw some eth \", async () => {\n  // Get vault and LP info\n  const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n  const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n  const vaultId = (await shortSqueeth.nextId()).sub(1);\n  const tokenIndex = await (positionManager as INonfungiblePositionManager).totalSupply();\n  const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndex.sub(1));\n  const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n  const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16)\n  // Get current LPpositions \n  const tokenOwner = await (positionManager as INonfungiblePositionManager).connect(depositor).ownerOf(tokenId)\n\n  const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n    tokenId: tokenId,\n    liquidity: positionBefore.liquidity,\n    amount0Min: 0,\n    amount1Min: 0,\n    deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n  })\n  const wPowerPerpAmountInLPBefore = (isWethToken0) ? amount1 : amount0;\n  const wethAmountInLPBefore = (isWethToken0) ? amount0 : amount1;\n  // deposit nft to vault (approve first)\n  await shortSqueeth.connect(depositor).approve(controller.address, vaultId);\n  await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n  await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controller.address, true) // approval for controller \n  await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controllerHelper.address, true) // approve controllerHelper\n  // Deposit nft to vault\n  await controller.connect(depositor).depositUniPositionToken(vaultId, tokenId)\n  const vaultBefore = await controller.vaults(vaultId);\n  // Estimate of new LP with 0.01 weth safety margin\n  const safetyEth = ethers.utils.parseUnits('0.01')\n  const wethAmountToDeposit =  wethAmountInLPBefore.div(4).sub(safetyEth)\n  const wethAmountToWithdraw =  wethAmountInLPBefore.div(4).sub(safetyEth)\n  const wPowerPerpAmountToMint = ethers.utils.parseUnits('1')\n  // Setup rebalanceVaultNft call\n  const abiCoder = new ethers.utils.AbiCoder\n  const rebalanceLpInVaultParams = [\n\n      {\n        // Liquidate half of LP \n        rebalanceLpInVaultType: BigNumber.from(1), // DecreaseLpLiquidity:\n        // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min]\n        data: abiCoder.encode([\"uint256\", 'uint256', 'uint256', 'uint128', 'uint128'],\n          [tokenId, positionBefore.liquidity, BigNumber.from(50).mul(BigNumber.from(10).pow(16)), BigNumber.from(0), BigNumber.from(0)])\n      },\n      {\n        // Deposit into vault and mint \n        rebalanceLpInVaultType: BigNumber.from(2), // DepositIntoVault\n        // DepsositIntoVault: [wPowerPerpToMint, collateralToDeposit]\n        data: abiCoder.encode([\"uint256\", 'uint256'],\n          [wPowerPerpAmountToMint, wethAmountToDeposit])\n      }\n  ]\n  // Flashloan to cover complete removal of LP (rearrange collateral ratio formula for 1.5 and add 0.01 ETH safety margin)\n  const normFactor = await controller.getExpectedNormalizationFactor()\n  const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n  const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n  const flashLoanAmount = (vaultBefore.shortAmount).mul(normFactor).mul(ethPrice).mul(3).div(one.mul(one).mul(10000).mul(2)).sub(vaultBefore.collateralAmount).add(ethers.utils.parseUnits('0.1'))\n\n  // Rebalance vault\n  const tx = await controllerHelper.connect(depositor).rebalanceLpInVault(vaultId, flashLoanAmount, rebalanceLpInVaultParams)\n  const receipt = await tx.wait()\n  const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n  const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n  const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n  // Get new vault and LP info\n  const vaultAfter = await controller.vaults(vaultId);\n  const tokenIdAfter = vaultAfter.NftCollateralId;\n  const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenIdAfter)\n  const [amount0After, amount1After] = await (positionManager as INonfungiblePositionManager).connect(controllerSigner).callStatic.decreaseLiquidity({\n    tokenId: tokenIdAfter,\n    liquidity: positionAfter.liquidity,\n    amount0Min: 0,\n    amount1Min: 0,\n    deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n  })\n  const wPowerPerpAmountInLPAfter = (isWethToken0) ? amount1After : amount0After;\n  const wethAmountInLPAfter = (isWethToken0) ? amount0After : amount1After;\n  // Changes\n  const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n  const depositorSqueethDiff = depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)\n  const vaultEthDiff = vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount)\n  const vaultSqueethDiff = vaultAfter.shortAmount.sub(vaultBefore.shortAmount)\n  const lpEthDiff = wethAmountInLPAfter.sub(wethAmountInLPBefore)\n  const lpSqueethDiff = wPowerPerpAmountInLPAfter.sub(wPowerPerpAmountInLPBefore)\n\n  // Assertions\n  expect(flashLoanAmount.gt(BigNumber.from(0))).to.be.true\n  expect(vaultSqueethDiff.eq(wPowerPerpAmountToMint)).to.be.true\n  expect(vaultEthDiff.eq(wethAmountToDeposit)).to.be.true\n  expect(lpSqueethDiff.add(wPowerPerpAmountInLPBefore.div(2)).lte(10)).to.be.true\n  expect(lpEthDiff.add(wethAmountInLPBefore.div(2)).lte(10)).to.be.true\n  expect(depositorSqueethDiff.sub(wPowerPerpAmountInLPBefore.div(2)).sub(wPowerPerpAmountToMint).abs().lte(10) ) \n})\n\n})\n\ndescribe(\"Rebalance LP in vault to just oSQTH\", async () => {\n  before(\"Mint new full range LP outside of vault\" , async () => {\n    // Mint 50 squeeth in new vault\n    const normFactor = await controller.getExpectedNormalizationFactor()\n    const mintWSqueethAmount = ethers.utils.parseUnits('50')\n    const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n    const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n    const scaledEthPrice = ethPrice.div(10000)\n    const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n    const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n    const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n    const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n    const batchMintLpParams = {\n      recipient: depositor.address,\n      wPowerPerpPool: wSqueethPool.address,\n      vaultId: 0,\n      wPowerPerpAmount: mintWSqueethAmount,\n      collateralToDeposit: collateralAmount,\n      collateralToLp: collateralToLp,\n      amount0Min: 0,\n      amount1Min: 0,\n      lowerTick: -887220,\n      upperTick: 887220\n    }\n    // Batch mint new full range LP\n    await controllerHelper.connect(depositor).wMintLp(batchMintLpParams, {value: collateralAmount.add(collateralToLp)});\n   })\n\n    \nit(\"Close vault LP and open new one-sided LP with just oSQTH \", async () => {\n  // Get vault and LP info\n  const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n  const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n  const vaultId = (await shortSqueeth.nextId()).sub(1);\n  const tokenIndex = await (positionManager as INonfungiblePositionManager).totalSupply();\n  const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndex.sub(1));\n  const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n  const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16)\n  // Get current LP positions \n  const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n    tokenId: tokenId,\n    liquidity: positionBefore.liquidity,\n    amount0Min: 0,\n    amount1Min: 0,\n    deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n  })\n  const wPowerPerpAmountInLPBefore = (isWethToken0) ? amount1 : amount0;\n  const wethAmountInLPBefore = (isWethToken0) ? amount0 : amount1;\n  // deposit nft to vault (approve first)\n  await shortSqueeth.connect(depositor).approve(controller.address, vaultId);\n  await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n  await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controller.address, true) // approval for controller \n  await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controllerHelper.address, true) // approve controllerHelper\n  // Deposit nft to vault\n  await controller.connect(depositor).depositUniPositionToken(vaultId, tokenId)\n  const vaultBefore = await controller.vaults(vaultId);\n  // Setup for mint of new LP\n  const slot0 = await wSqueethPool.slot0()\n  const currentTick = slot0[1]\n  // Range above current tick\n  const newTickLower = isWethToken0 ? 60*((currentTick - currentTick%60)/60 -2): 60*((currentTick - currentTick%60)/60  + 1)\n  const newTickUpper = isWethToken0 ? 60*((currentTick - currentTick%60)/60 -1): 60*((currentTick - currentTick%60)/60 + 2)\n  // No minimum\n  const amount0Min = BigNumber.from(0);\n  const amount1Min = BigNumber.from(0);\n  // Estimate proceeds from liquidating weth in LP\n  const wPowerPerpAmountOutFromSwap = await quoter.connect(depositor).callStatic.quoteExactInputSingle(weth.address,\n    wSqueeth.address,\n    3000,\n    wethAmountInLPBefore,\n    0)\n  // Estimate of new LP with 0.01 wPowerPerp safety margin\n  const wPowerPerpAmountToLp = wPowerPerpAmountInLPBefore.add(wPowerPerpAmountOutFromSwap).sub(ethers.utils.parseUnits('0.1'))\n  // Setup rebalanceVaultNft call\n  const abiCoder = new ethers.utils.AbiCoder\n  const rebalanceLpInVaultParams = [\n    {\n      // Liquidate LP\n      rebalanceLpInVaultType: BigNumber.from(1), // DecreaseLpLiquidity:\n      // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min]\n      data: abiCoder.encode([\"uint256\", 'uint256', 'uint256', 'uint128', 'uint128'],\n       [tokenId, positionBefore.liquidity, BigNumber.from(100).mul(BigNumber.from(10).pow(16)), BigNumber.from(0), BigNumber.from(0)])\n      },\n      {\n      // Sell all weth for oSQTH\n      rebalanceLpInVaultType: BigNumber.from(5), // GeneralSwap:\n        // GeneralSwap: [tokenIn, tokenOut, amountIn, limitPrice, poolFee]\n        data: abiCoder.encode([\"address\", 'address', 'uint256', 'uint256','uint24'],\n         [weth.address, wSqueeth.address, wethAmountInLPBefore, BigNumber.from(0), 3000])\n        },\n     {\n       // Mint new LP \n       rebalanceLpInVaultType:  BigNumber.from(4), // MintNewLP\n       // lpWPowerPerpPool: [recipient, wPowerPerpPool, vaultId, wPowerPerpAmount, collateralToDeposit, collateralToLP, amount0Min, amount1Min, lowerTick, upperTick ]\n       data: abiCoder.encode([\"address\", \"address\", \"uint256\", 'uint256','uint256', 'uint256', 'uint256', 'uint256', 'int24', 'int24'],\n        [controllerHelper.address, wSqueethPool.address, vaultId, wPowerPerpAmountToLp, BigNumber.from(0),  BigNumber.from(0), amount0Min, amount1Min, newTickLower, newTickUpper])\n     }\n  ]\n  // Flashloan to cover complete removal of LP (rearrange collateral ratio formula for 1.5 and add 0.1 ETH safety margin)\n  const normFactor = await controller.getExpectedNormalizationFactor()\n  const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n  const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n\n  const debtValueInEth = ((vaultBefore.shortAmount.add(wPowerPerpAmountToLp)).mul(ethPrice).mul(normFactor).div(one).div(one)).div(10000)\n  // flashloan amount to cover withdrawn LP\n  const flashLoanAmount = (debtValueInEth.mul(3).div(2)).sub(vaultBefore.collateralAmount).add(ethers.utils.parseUnits('0.01'))\n\n  await controllerHelper.connect(depositor).rebalanceLpInVault(vaultId, flashLoanAmount, rebalanceLpInVaultParams);\n  const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n  const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n  // Get new vault and LP info\n  const vaultAfter = await controller.vaults(vaultId);\n  const tokenIdAfter = vaultAfter.NftCollateralId;\n  const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenIdAfter)\n  const [amount0After, amount1After] = await (positionManager as INonfungiblePositionManager).connect(controllerSigner).callStatic.decreaseLiquidity({\n    tokenId: tokenIdAfter,\n    liquidity: positionAfter.liquidity,\n    amount0Min: 0,\n    amount1Min: 0,\n    deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n  })\n  const wPowerPerpAmountInLPAfter = (isWethToken0) ? amount1After : amount0After;\n  const wethAmountInLPAfter = (isWethToken0) ? amount0After : amount1After;\n  // Changes\n  const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n  const depositorSqueethDiff = depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)\n  const vaultEthDiff = vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount)\n  const vaultSqueethDiff = vaultAfter.shortAmount.sub(vaultBefore.shortAmount)\n  const lpEthDiff = wethAmountInLPAfter.sub(wethAmountInLPBefore)\n  const lpSqueethDiff = wPowerPerpAmountInLPAfter.sub(wPowerPerpAmountInLPBefore)\n  // Assertions\n  expect(flashLoanAmount.gte(0)).to.be.true\n  expect(positionAfter.tickLower === newTickLower).to.be.true\n  expect(positionAfter.tickUpper === newTickUpper).to.be.true\n  expect(vaultAfter.shortAmount.eq(vaultBefore.shortAmount)).to.be.true\n  expect(vaultAfter.collateralAmount.eq(vaultBefore.collateralAmount)).to.be.true\n  expect(vaultAfter.NftCollateralId==vaultBefore.NftCollateralId).to.be.false\n  expect(wethAmountInLPAfter.eq(BigNumber.from(0))).to.be.true\n  expect(wPowerPerpAmountInLPAfter.sub(wPowerPerpAmountToLp).abs().lte(10)).to.be.true\n    })\n  })\n\n  describe(\"Increase liquidity in vault with no eth added\", async () => {\n    before(\"Mint new full range LP outside of vault\" , async () => {\n      // Mint 50 squeeth in new vault with 2x collateral ratio\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('50')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3)\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n      const batchMintLpParams = {\n        recipient: depositor.address,\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: 0,\n        wPowerPerpAmount: mintWSqueethAmount,\n        collateralToDeposit: collateralAmount,\n        collateralToLp: collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        lowerTick: -887220,\n        upperTick: 887220\n      }\n      // Batch mint new full range LP\n      await controllerHelper.connect(depositor).wMintLp(batchMintLpParams, {value: collateralAmount.add(collateralToLp)});\n     })\n  \n      \n  it(\"Deposit nft, withdraw collateral from vault, mint, increase liquidity with no eth added\", async () => {\n    // Get vault and LP info\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n    const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n    const vaultId = (await shortSqueeth.nextId()).sub(1);\n    const tokenIndex = await (positionManager as INonfungiblePositionManager).totalSupply();\n    const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndex.sub(1));\n    const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n    const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16)\n    // Get current LP positions \n    const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n      tokenId: tokenId,\n      liquidity: positionBefore.liquidity,\n      amount0Min: 0,\n      amount1Min: 0,\n      deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n    })\n    const wPowerPerpAmountInLPBefore = (isWethToken0) ? amount1 : amount0;\n    const wethAmountInLPBefore = (isWethToken0) ? amount0 : amount1;\n    // deposit nft to vault (approve first)\n    await shortSqueeth.connect(depositor).approve(controller.address, vaultId);\n    await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n    await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controller.address, true) // approval for controller \n    await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controllerHelper.address, true) // approve controllerHelper\n    // Deposit nft to vault\n    await controller.connect(depositor).depositUniPositionToken(vaultId, tokenId)\n    const vaultBefore = await controller.vaults(vaultId);\n    // Double up LP\n    const wPowerPerpAmountToLp = wPowerPerpAmountInLPBefore\n    const wethAmountToLp = wethAmountInLPBefore\n    const wPowerPerpAmountToMint = wPowerPerpAmountToLp\n    // Setup rebalanceVaultNft call\n    const abiCoder = new ethers.utils.AbiCoder\n    // Start with overcollateralized vault with NFT\n    // - Withdraw some eth (WithdrawFromVault)\n    // - Mint some squeeth (DepositIntoVault)\n    // - Increase LP liquidity (IncreaseLpLiquidity)\n    const rebalanceLpInVaultParams = [\n      {\n        // Withdraw from vault\n        rebalanceLpInVaultType: BigNumber.from(3), // WithdrawFromVault\n        // withdrawFromVault: [wPowerPerpToBurn, collateralToWithdraw, burnExactRemoved ]\n        data: abiCoder.encode([\"uint256\", 'uint256', 'bool'],\n         [BigNumber.from(0), wethAmountToLp, false ])\n        },\n      {\n        // Deposit into vault (no deposit)\n        rebalanceLpInVaultType: BigNumber.from(2), // DepositIntoVault\n        // DepsositIntoVault: [wPowerPerpToMint, collateralToDeposit]\n        data: abiCoder.encode([\"uint256\", 'uint256'],\n         [wPowerPerpAmountToMint, BigNumber.from(0)])\n        },\n      {\n        // IncreaseLpLiquidity\n        rebalanceLpInVaultType: BigNumber.from(0), // IncreaseLpLiquidity:\n        // IncreaseLpLiquidityParam: [wPowerPerpPool, tokenId, wPowerPerpAmountToLp, collateralToDeposit, wethAmountToLp, amount0Min, amount1Min]\n        data: abiCoder.encode([\"address\",\"uint256\", 'uint256', 'uint256', 'uint256', 'uint256','uint256'],\n         [wSqueethPool.address, tokenId, wPowerPerpAmountToLp, BigNumber.from(0), wethAmountToLp, BigNumber.from(0), BigNumber.from(0)])\n        }\n    ]\n    // Flashloan to cover complete removal of LP (rearrange collateral ratio formula for 1.5 and add 0.1 ETH safety margin)\n    const normFactor = await controller.getExpectedNormalizationFactor()\n    const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n    const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n\n    const debtValueInEth = ((vaultBefore.shortAmount.add(wPowerPerpAmountToMint)).mul(ethPrice).mul(normFactor).div(one).div(one)).div(10000)\n    // flashloan amount to cover withdrawn LP\n    const flashLoanAmount = (debtValueInEth.mul(3).div(2)).sub((vaultBefore.collateralAmount.sub(wethAmountToLp))).add(ethers.utils.parseUnits('0.01'))\n    const tx = await controllerHelper.connect(depositor).rebalanceLpInVault(vaultId, flashLoanAmount, rebalanceLpInVaultParams);\n    const receipt = await tx.wait()\n    const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n    const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n    const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n    // Get new vault and LP info\n    const vaultAfter = await controller.vaults(vaultId);\n    const tokenIdAfter = vaultAfter.NftCollateralId;\n    const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenIdAfter)\n    const [amount0After, amount1After] = await (positionManager as INonfungiblePositionManager).connect(controllerSigner).callStatic.decreaseLiquidity({\n      tokenId: tokenIdAfter,\n      liquidity: positionAfter.liquidity,\n      amount0Min: 0,\n      amount1Min: 0,\n      deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n    })\n    const wPowerPerpAmountInLPAfter = (isWethToken0) ? amount1After : amount0After;\n    const wethAmountInLPAfter = (isWethToken0) ? amount0After : amount1After;\n    // Changes\n    const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n    const depositorSqueethDiff = depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)\n    const vaultEthDiff = vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount)\n    const vaultSqueethDiff = vaultAfter.shortAmount.sub(vaultBefore.shortAmount)\n    const lpEthDiff = wethAmountInLPAfter.sub(wethAmountInLPBefore)\n    const lpSqueethDiff = wPowerPerpAmountInLPAfter.sub(wPowerPerpAmountInLPBefore)\n    // Assertions\n    // flashloan amount should be positive\n    expect(flashLoanAmount.gte(0)).to.be.true\n    // expect(positionAfter.tickLower === newTickLower).to.be.true\n    expect(vaultSqueethDiff.sub(wPowerPerpAmountToLp).eq(0)).to.be.true\n    // LP eth comes from vault\n    expect(vaultEthDiff.add(lpEthDiff).lte(10)).to.be.true\n    // Nft id unchanged\n    expect(vaultAfter.NftCollateralId==vaultBefore.NftCollateralId).to.be.true\n    // Squeeth convervation\n    expect(lpSqueethDiff.sub(vaultSqueethDiff).add(depositorSqueethDiff).abs().lte(10)).to.be.true\n    // LP amount close to mint\n    expect(lpSqueethDiff.sub(vaultSqueethDiff).lte(ethers.utils.parseUnits('0.1'))).to.be.true\n    })\n    })\n\n\n    describe(\"Rebalance LP in vault: reduce oSQTH < debt, burn, withdraw >0 eth\", async () => {\n      before(\"Mint new full range LP outside of vault\" , async () => {\n        // Mint 50 squeeth in new vault\n        const normFactor = await controller.getExpectedNormalizationFactor()\n        const mintWSqueethAmount = ethers.utils.parseUnits('50')\n        const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n        const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n        const scaledEthPrice = ethPrice.div(10000)\n        const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n        const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n        const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n        const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n        const batchMintLpParams = {\n          recipient: depositor.address,\n          wPowerPerpPool: wSqueethPool.address,\n          vaultId: 0,\n          wPowerPerpAmount: mintWSqueethAmount,\n          collateralToDeposit: collateralAmount,\n          collateralToLp: collateralToLp,\n          amount0Min: 0,\n          amount1Min: 0,\n          lowerTick: -887220,\n          upperTick: 887220\n        }\n        // Batch mint new full range LP\n        await controllerHelper.connect(depositor).wMintLp(batchMintLpParams, {value: collateralAmount.add(collateralToLp)});\n       })\n    \n        \n    it(\"Reduce liquidity in LP, swap oSQTH for eth, deposit eth into vault, mint more oSQTH\", async () => {\n      // Get vault and LP info\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const tokenIndex = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndex.sub(1));\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16)\n      // Get current LP positions \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: 0,\n        amount1Min: 0,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLPBefore = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLPBefore = (isWethToken0) ? amount0 : amount1;\n      // deposit nft to vault (approve first)\n      await shortSqueeth.connect(depositor).approve(controller.address, vaultId);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n      await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controller.address, true) // approval for controller \n      await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controllerHelper.address, true) // approve controllerHelper\n      // Deposit nft to vault\n      await controller.connect(depositor).depositUniPositionToken(vaultId, tokenId)\n      const vaultBefore = await controller.vaults(vaultId);\n      // Swap withdrawn amount (less safety margin)\n      const wPowerPerpToSwap = wPowerPerpAmountInLPBefore.div(2).sub(ethers.utils.parseUnits('0.01'))\n      // Estimate eth amount needed to buy remaining oSQTH\n      const ethAmountFromSwap = await quoter.connect(depositor).callStatic.quoteExactOutputSingle(weth.address,\n        wSqueeth.address,\n        3000,\n        wPowerPerpToSwap,\n        0)\n      const ethAmountToDeposit = ethAmountFromSwap.add(wethAmountInLPBefore.div(2)).sub(ethers.utils.parseUnits('0.01'))\n      // Setup rebalanceLpInVault call\n      const abiCoder = new ethers.utils.AbiCoder\n      const rebalanceLpInVaultParams = [\n        {\n          // Liquidate LP 50%\n          rebalanceLpInVaultType: BigNumber.from(1), // DecreaseLpLiquidity:\n          // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min]\n          data: abiCoder.encode([\"uint256\", 'uint256', 'uint256', 'uint128', 'uint128'],\n           [tokenId, positionBefore.liquidity, BigNumber.from(50).mul(BigNumber.from(10).pow(16)), BigNumber.from(0), BigNumber.from(0)])\n          },\n          {\n            // Swap to eth\n            rebalanceLpInVaultType: BigNumber.from(5), // GeneralSwap:\n            // GeneralSwap: [tokenIn, tokenOut, amountIn, limitPrice, poolFee]\n            data: abiCoder.encode([\"address\", 'address', 'uint256', 'uint256','uint24'],\n            [wSqueeth.address, weth.address,  wPowerPerpToSwap, BigNumber.from(0), 3000])\n          }  ,\n          {\n            // Deposit eth and mint more \n            rebalanceLpInVaultType: BigNumber.from(2), // DepositIntoVault\n            // DepsositIntoVault: [wPowerPerpToMint, collateralToDeposit]\n            data: abiCoder.encode([\"uint256\", 'uint256'],\n             [wPowerPerpToSwap, ethAmountToDeposit.sub(ethers.utils.parseUnits('0.1'))])\n            },\n      ]\n      // Flashloan to cover complete removal of LP (rearrange collateral ratio formula for 1.5 and add 0.1 ETH safety margin)\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n      const flashLoanAmount = (vaultBefore.shortAmount).mul(normFactor).mul(ethPrice).mul(3).div(one.mul(one).mul(10000).mul(2)).sub(vaultBefore.collateralAmount).add(ethers.utils.parseUnits('0.1'))\n      await controllerHelper.connect(depositor).rebalanceLpInVault(vaultId, flashLoanAmount, rebalanceLpInVaultParams)\n      const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n      // Get new vault and LP info\n      const vaultAfter = await controller.vaults(vaultId);\n      const tokenIdAfter = vaultAfter.NftCollateralId;\n      const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenIdAfter)\n      const [amount0After, amount1After] = await (positionManager as INonfungiblePositionManager).connect(controllerSigner).callStatic.decreaseLiquidity({\n        tokenId: tokenIdAfter,\n        liquidity: positionAfter.liquidity,\n        amount0Min: 0,\n        amount1Min: 0,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLPAfter = (isWethToken0) ? amount1After : amount0After;\n      const wethAmountInLPAfter = (isWethToken0) ? amount0After : amount1After;\n      // Changes\n      const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n      const depositorSqueethDiff = depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)\n      const vaultEthDiff = vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount)\n      const vaultSqueethDiff = vaultAfter.shortAmount.sub(vaultBefore.shortAmount)\n      const lpEthDiff = wethAmountInLPAfter.sub(wethAmountInLPBefore)\n      const lpSqueethDiff = wPowerPerpAmountInLPAfter.sub(wPowerPerpAmountInLPBefore)\n      // Assertions\n    \n      // Correct amount minted\n      expect(vaultSqueethDiff.sub(wPowerPerpToSwap).eq(0)).to.be.true\n      // Eth deposited ~= target amount\n      expect(vaultEthDiff.sub(ethAmountToDeposit.sub(ethers.utils.parseUnits('0.1'))).eq(0)).to.be.true\n      // Nft id unchanged\n      expect(vaultAfter.NftCollateralId==vaultBefore.NftCollateralId).to.be.true\n        })\n      })\n    \n      describe(\"Rebalance LP in vault: reduce oSQTH > debt, burn, withdraw >0 eth\", async () => {\n        \n        before(\"Flashmint new LP with 200 oSQTH and withdraw all eth collateral\", async () => {\n          const normFactor = await controller.getExpectedNormalizationFactor()\n          const mintWSqueethAmount = ethers.utils.parseUnits('200')\n          const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n          const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n          const scaledEthPrice = ethPrice.div(10000)\n          const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n          const collateralToDeposit = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n          const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n          const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n          const flashloanWMintDepositNftParams = {\n            wPowerPerpPool: wSqueethPool.address,\n            vaultId: 0,\n            wPowerPerpAmount: mintWSqueethAmount,\n            collateralToDeposit: collateralToDeposit,\n            collateralToFlashloan: 0,\n            collateralToLp: collateralToLp,\n            collateralToWithdraw: 0,\n            amount0Min: 0,\n            amount1Min: 0,\n            lowerTick: -887220,\n            upperTick: 887220\n          }    \n          await controllerHelper.connect(depositor).flashloanWMintLpDepositNft(flashloanWMintDepositNftParams, {value: collateralToLp.add(collateralToDeposit).add(ethers.utils.parseUnits('0.01'))})\n          // Burn half of short amount\n          const wPowerPerpToBurn = mintWSqueethAmount.div(2)\n          const vaultId = (await shortSqueeth.nextId()).sub(1);\n          // Withdraw all vault collateral\n          const collateralToWithdraw = collateralToDeposit\n          await controller.connect(depositor).burnPowerPerpAmount(vaultId, wPowerPerpToBurn, collateralToWithdraw)\n        })\n        \n      it(\"Withdraw oSQTH > vault debt from LP, burn, swap remainder, withdraw >0 eth\", async () => {\n        // Get vault and LP info\n        const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n        const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n        const vaultId = (await shortSqueeth.nextId()).sub(1);\n        const tokenIndex = await (positionManager as INonfungiblePositionManager).totalSupply();\n        const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndex.sub(1));\n        const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n        const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16)\n        // Get current LPpositions \n        const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(controllerSigner).callStatic.decreaseLiquidity({\n          tokenId: tokenId,\n          liquidity: positionBefore.liquidity,\n          amount0Min: 0,\n          amount1Min: 0,\n          deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        })\n\n        // Get current LP positions\n        const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(tokenId)\n        const wPowerPerpAmountInLPBefore = (isWethToken0) ? amount1 : amount0;\n        const wethAmountInLPBefore = (isWethToken0) ? amount0 : amount1;\n        // deposit nft to vault (approve first)\n        await shortSqueeth.connect(depositor).approve(controller.address, vaultId);\n        await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n        await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controller.address, true) // approval for controller \n        await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controllerHelper.address, true) // approve controllerHelper\n\n        const vaultBefore = await controller.vaults(vaultId);\n        // Burn whole debt\n        const wPowerPerpToBurn = vaultBefore.shortAmount\n        // Swap the remaining to eth (80% liquidated) less a safety margin\n        const wPowerPerpAmountToSwap = wPowerPerpAmountInLPBefore.mul(80).div(100).sub(wPowerPerpToBurn).sub(ethers.utils.parseUnits('0.01'))\n\n        // Setup rebalanceVaultNft call\n        const abiCoder = new ethers.utils.AbiCoder\n        const rebalanceLpInVaultParams = [\n          {\n            // Liquidate LP 80%\n            rebalanceLpInVaultType: BigNumber.from(1), // DecreaseLpLiquidity:\n            // DecreaseLpLiquidityParams: [tokenId, liquidity, liquidityPercentage, amount0Min, amount1Min]\n            data: abiCoder.encode([\"uint256\", 'uint256', 'uint256', 'uint128', 'uint128'],\n            [tokenId, positionBefore.liquidity, BigNumber.from(80).mul(BigNumber.from(10).pow(16)), BigNumber.from(0), BigNumber.from(0)])\n          },\n          \n          {\n            // Burn some withdrawn from LP\n            rebalanceLpInVaultType: BigNumber.from(3), // WithdrawFromVault\n            // withdrawFromVault: [wPowerPerpToBurn, collateralToWithdraw, burnExactRemoved ]\n            data: abiCoder.encode([\"uint256\", 'uint256', 'bool'],\n            [wPowerPerpToBurn, BigNumber.from(0), false ])\n          },\n          {\n            // Sell all oSQTH for weth\n            rebalanceLpInVaultType: BigNumber.from(5), // GeneralSwap:\n            // GeneralSwap: [tokenIn, tokenOut, amountIn, limitPrice, poolFee]\n            data: abiCoder.encode([\"address\", 'address', 'uint256', 'uint256','uint24'],\n            [wSqueeth.address, weth.address, wPowerPerpAmountToSwap, BigNumber.from(0), 3000])\n          }  \n        ]\n        // Flashloan to cover complete removal of LP (rearrange collateral ratio formula for 1.5 and add 0.1 ETH safety margin)\n        const normFactor = await controller.getExpectedNormalizationFactor()\n        const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n        const debtValueInEth = (vaultBefore.shortAmount.mul(ethPrice).mul(normFactor).div(one).div(one)).div(10000)\n        // flashloan amount to cover withdrawn LP\n        const flashLoanAmount = (debtValueInEth.mul(3).div(2)).sub(vaultBefore.collateralAmount).add(ethers.utils.parseUnits('0.01'))\n        \n        await controllerHelper.connect(depositor).rebalanceLpInVault(vaultId, flashLoanAmount, rebalanceLpInVaultParams);\n        const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n        const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n        // Get new vault and LP info\n        const vaultAfter = await controller.vaults(vaultId);\n        const tokenIdAfter = vaultAfter.NftCollateralId;\n        const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenIdAfter)\n        const [amount0After, amount1After] = await (positionManager as INonfungiblePositionManager).connect(controllerSigner).callStatic.decreaseLiquidity({\n          tokenId: tokenIdAfter,\n          liquidity: positionAfter.liquidity,\n          amount0Min: 0,\n          amount1Min: 0,\n          deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        })\n        const wPowerPerpAmountInLPAfter = (isWethToken0) ? amount1After : amount0After;\n        const wethAmountInLPAfter = (isWethToken0) ? amount0After : amount1After;\n        // Changes\n        const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n        const depositorSqueethDiff = depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)\n        const vaultEthDiff = vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount)\n        const vaultSqueethDiff = vaultAfter.shortAmount.sub(vaultBefore.shortAmount)\n        const lpEthDiff = wethAmountInLPAfter.sub(wethAmountInLPBefore)\n        const lpSqueethDiff = wPowerPerpAmountInLPAfter.sub(wPowerPerpAmountInLPBefore)\n        // Assertions\n        expect(vaultSqueethDiff.add(wPowerPerpToBurn).eq(0)).to.be.true\n        // LP eth comes from vault\n        expect(vaultEthDiff.eq(BigNumber.from(0))).to.be.true\n        // Nft id unchanged\n        expect(vaultAfter.NftCollateralId==vaultBefore.NftCollateralId).to.be.true\n        // Squeeth convervation\n        expect(wPowerPerpAmountInLPBefore.mul(80).div(100).sub(wPowerPerpToBurn).sub(wPowerPerpAmountToSwap).abs().lte(ethers.utils.parseUnits('0.01'))).to.be.true\n          })\n        })\n\n\n      describe(\"Increase liquidity in vault with some eth added\", async () => {\n        before(\"Mint new full range LP outside of vault\" , async () => {\n          // Mint 50 squeeth in new vault with 2x collateral ratio\n          const normFactor = await controller.getExpectedNormalizationFactor()\n          const mintWSqueethAmount = ethers.utils.parseUnits('50')\n          const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n          const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n          const scaledEthPrice = ethPrice.div(10000)\n          const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n          const collateralAmount = debtInEth.mul(3)\n          const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n          const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n          const batchMintLpParams = {\n            recipient: depositor.address,\n            wPowerPerpPool: wSqueethPool.address,\n            vaultId: 0,\n            wPowerPerpAmount: mintWSqueethAmount,\n            collateralToDeposit: collateralAmount,\n            collateralToLp: collateralToLp,\n            amount0Min: 0,\n            amount1Min: 0,\n            lowerTick: -887220,\n            upperTick: 887220\n          }\n          // Batch mint new full range LP\n          await controllerHelper.connect(depositor).wMintLp(batchMintLpParams, {value: collateralAmount.add(collateralToLp)});\n         })\n      \n          \n      it(\"Deposit nft, withdraw collateral from vault, mint, increase liquidity with some eth added\", async () => {\n        // Get vault and LP info\n        const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n        const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n        const vaultId = (await shortSqueeth.nextId()).sub(1);\n        const tokenIndex = await (positionManager as INonfungiblePositionManager).totalSupply();\n        const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndex.sub(1));\n        const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n        const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16)\n        // Get current LP positions \n        const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n          tokenId: tokenId,\n          liquidity: positionBefore.liquidity,\n          amount0Min: 0,\n          amount1Min: 0,\n          deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        })\n        const wPowerPerpAmountInLPBefore = (isWethToken0) ? amount1 : amount0;\n        const wethAmountInLPBefore = (isWethToken0) ? amount0 : amount1;\n        // deposit nft to vault (approve first)\n        await shortSqueeth.connect(depositor).approve(controller.address, vaultId);\n        await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n        await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controller.address, true) // approval for controller \n        await (positionManager as INonfungiblePositionManager).connect(depositor).setApprovalForAll(controllerHelper.address, true) // approve controllerHelper\n        // Deposit nft to vault\n        await controller.connect(depositor).depositUniPositionToken(vaultId, tokenId)\n        const vault = await controller.vaults(vaultId);\n        // Withdraw some collateral from vault\n        await controller.connect(depositor).burnPowerPerpAmount(vaultId, 0, vault.collateralAmount.sub(wethAmountInLPBefore.div(2)).sub(ethers.utils.parseUnits('0.01')))\n\n        // Withdraw all eth collateral\n        const vaultBefore = await controller.vaults(vaultId);\n        // Double up LP\n        const wPowerPerpAmountToLp = wPowerPerpAmountInLPBefore\n        const wethAmountToLp = wethAmountInLPBefore\n        const wethAmountToWithdraw = wethAmountToLp.div(2)\n        // Setup rebalanceVaultNft call\n        const abiCoder = new ethers.utils.AbiCoder\n        // Start with overcollateralized vault with NFT\n        // - Withdraw some eth (WithdrawFromVault)\n        // - Mint some squeeth (DepositIntoVault)\n        // - Increase LP liquidity (IncreaseLpLiquidity)\n        \n        const rebalanceLpInVaultParams = [\n          {\n            // Withdraw from vault\n            rebalanceLpInVaultType: BigNumber.from(3), // WithdrawFromVault\n            // withdrawFromVault: [wPowerPerpToBurn, collateralToWithdraw, burnExactRemoved ]\n            data: abiCoder.encode([\"uint256\", 'uint256', 'bool'],\n             [BigNumber.from(0), wethAmountToWithdraw, false ])\n            },\n          {\n            // Mint amount to LP\n            rebalanceLpInVaultType: BigNumber.from(2), // DepositIntoVault\n            // DepsositIntoVault: [wPowerPerpToMint, collateralToDeposit]\n            data: abiCoder.encode([\"uint256\", 'uint256'],\n             [wPowerPerpAmountToLp, BigNumber.from(0)])\n            },\n          {\n            // IncreaseLpLiquidity\n            rebalanceLpInVaultType: BigNumber.from(0), // IncreaseLpLiquidity:\n            // IncreaseLpLiquidityParam: [tokenId, wPowerPerpAmountToLp, collateralToDeposit, wethAmountToLp, amount0Min, amount1Min]\n            data: abiCoder.encode([\"address\", \"uint256\", 'uint256', 'uint256', 'uint256', 'uint256','uint256'],\n             [wSqueethPool.address, tokenId, wPowerPerpAmountToLp, BigNumber.from(0), wethAmountToLp, BigNumber.from(0), BigNumber.from(0)])\n            }\n        ]\n        // Flashloan to cover complete removal of LP (rearrange collateral ratio formula for 1.5 and add 0.1 ETH safety margin)\n        const normFactor = await controller.getExpectedNormalizationFactor()\n        const ethPrice = await oracle.getTwap(ethUsdcPool.address, weth.address, usdc.address, 420, true)\n        const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n        const debtValueInEth = ((vaultBefore.shortAmount.add(wPowerPerpAmountToLp)).mul(ethPrice).mul(normFactor).div(one).div(one)).div(10000)\n        // flashloan amount to cover withdrawn LP\n        const flashLoanAmount = (debtValueInEth.mul(3).div(2)).sub(vaultBefore.collateralAmount).add(wethAmountToWithdraw).add(ethers.utils.parseUnits('0.02'))\n        const tx = await controllerHelper.connect(depositor).rebalanceLpInVault(vaultId, flashLoanAmount, rebalanceLpInVaultParams, {value: wethAmountToLp.div(2).add(ethers.utils.parseUnits('0.01'))});\n        const receipt = await tx.wait()\n        const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n        const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n        const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n        // Get new vault and LP info\n        const vaultAfter = await controller.vaults(vaultId);\n        const tokenIdAfter = vaultAfter.NftCollateralId;\n        const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenIdAfter)\n        const [amount0After, amount1After] = await (positionManager as INonfungiblePositionManager).connect(controllerSigner).callStatic.decreaseLiquidity({\n          tokenId: tokenIdAfter,\n          liquidity: positionAfter.liquidity,\n          amount0Min: 0,\n          amount1Min: 0,\n          deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        })\n        const wPowerPerpAmountInLPAfter = (isWethToken0) ? amount1After : amount0After;\n        const wethAmountInLPAfter = (isWethToken0) ? amount0After : amount1After;\n        // Changes\n        const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n        const depositorSqueethDiff = depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)\n        const vaultEthDiff = vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount)\n        const vaultSqueethDiff = vaultAfter.shortAmount.sub(vaultBefore.shortAmount)\n        const lpEthDiff = wethAmountInLPAfter.sub(wethAmountInLPBefore)\n        const lpSqueethDiff = wPowerPerpAmountInLPAfter.sub(wPowerPerpAmountInLPBefore)\n        // console.log('currentTick', currentTick)\n        // console.log('positionAfter.TickLower', positionAfter.tickLower)\n        // console.log('positionAfter.TickUpper', positionAfter.tickUpper)\n        // console.log('wPowerPerpAmountInLPBefore', wPowerPerpAmountInLPBefore.toString())\n        // console.log('wethAmountInLPBefore', wethAmountInLPBefore.toString())\n        // console.log('wPowerPerpAmountInLPAfter', wPowerPerpAmountInLPAfter.toString())\n        // console.log('wethAmountInLPAfter', wethAmountInLPAfter.toString())\n        // console.log('vaultSqueethDiff',vaultSqueethDiff.toString() )\n        // console.log('vaultEthDiff',vaultEthDiff.toString() )\n        // console.log('lpSqueethDiff', lpSqueethDiff.toString())\n        // console.log('lpEthDiff', lpEthDiff.toString())\n        // console.log('depositorSqueethDiff', depositorSqueethDiff.toString())\n        // console.log('vaultBefore.collateralAmount', vaultBefore.collateralAmount.toString())\n        // console.log('vaultBefore.shortAmount', vaultBefore.shortAmount.toString())\n        // console.log('vaultAfter.collateralAmount', vaultAfter.collateralAmount.toString())\n        // console.log('vaultAfter.shortAmount', vaultAfter.shortAmount.toString())\n        // console.log('wethAmountToLp',wethAmountToLp.toString())\n        // console.log('flashloanAmount',flashLoanAmount.toString())\n        // console.log('wPowerPerpAmountInLPBefore', wPowerPerpAmountInLPBefore.toString())\n        // console.log('wPowerPerpAmountToLp', wPowerPerpAmountToLp.toString())\n        // console.log('depositorEthDiff', depositorEthDiff.toString())\n        // console.log('depositorSqueethDiff', depositorSqueethDiff.toString())\n        // console.log('gasSpent', gasSpent.toString())\n\n        // Assertions\n        // Flashloan positive\n        expect(flashLoanAmount.gt(0)).to.be.true\n        // Target eth withdrawn from vault\n        expect((vaultEthDiff.add(wethAmountToWithdraw)).abs().lte(10)).to.be.true\n        // Target squeeth minted\n        expect((vaultSqueethDiff.sub(wPowerPerpAmountToLp)).abs().lte(10)).to.be.true\n        // Nft id unchanged\n        expect(vaultAfter.NftCollateralId==vaultBefore.NftCollateralId).to.be.true\n          })\n        })\n\n\n\n\n})\n"
  },
  {
    "path": "packages/hardhat/test/integration-tests/crabv2/crab-hedging-otc.ts",
    "content": "import BigNumberJs from \"bignumber.js\";\nimport { expect } from \"chai\";\nimport { ethers, network } from \"hardhat\";\n\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { BigNumber, Contract, providers } from \"ethers\";\nimport { Controller, CrabStrategyV2, MockErc20, Timelock, Oracle, WETH9, WPowerPerp } from \"../../../typechain\";\nimport {\n    addSqueethLiquidity,\n    addWethDaiLiquidity,\n    buyWeth,\n    buyWSqueeth,\n    deploySqueethCoreContracts,\n    deployUniswapV3,\n    deployWETHAndDai,\n} from \"../../setup\";\nimport { isSimilar, one, oracleScaleFactor, signTypedData, wdiv, wmul } from \"../../utils\";\n\nBigNumberJs.set({ EXPONENTIAL_AT: 30 });\n\ndescribe(\"Crab V2 flashswap integration test: time based hedging\", function () {\n    const startingEthPrice = 3000;\n    const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one); // 3000 * 1e18\n    const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.mul(11).div(10).div(oracleScaleFactor); // 0.303 * 1e18\n    const scaledStartingSqueethPrice = (startingEthPrice * 1.1) / oracleScaleFactor.toNumber(); // 0.303\n\n    const hedgeTimeThreshold = 86400; // 24h\n    const hedgePriceThreshold = ethers.utils.parseUnits(\"0.01\");\n    const auctionTime = 3600;\n\n    let provider: providers.JsonRpcProvider;\n    let owner: SignerWithAddress;\n    let depositor: SignerWithAddress;\n    let random: SignerWithAddress;\n    let trader: SignerWithAddress;\n    let feeRecipient: SignerWithAddress;\n    let crabMigration: SignerWithAddress;\n    let dai: MockErc20;\n    let weth: WETH9;\n    let positionManager: Contract;\n    let uniswapFactory: Contract;\n    let swapRouter: Contract;\n    let oracle: Oracle;\n    let controller: Controller;\n    let wSqueethPool: Contract;\n    let wSqueeth: WPowerPerp;\n    let crabStrategyV2: CrabStrategyV2;\n    let ethDaiPool: Contract;\n    let timelock: Timelock;\n\n    this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async () => {\n        const accounts = await ethers.getSigners();\n        const [_owner, _depositor, _random, _feeRecipient, _trader, _crabMigration] = accounts;\n        owner = _owner;\n        depositor = _depositor;\n        random = _random;\n        trader = _trader;\n        feeRecipient = _feeRecipient;\n        crabMigration = _crabMigration;\n        provider = ethers.provider;\n\n        const { dai: daiToken, weth: wethToken } = await deployWETHAndDai();\n\n        dai = daiToken;\n        weth = wethToken;\n\n        const uniDeployments = await deployUniswapV3(weth);\n        positionManager = uniDeployments.positionManager;\n        uniswapFactory = uniDeployments.uniswapFactory;\n        swapRouter = uniDeployments.swapRouter;\n\n        // this will not deploy a new pool, only reuse old onces\n        const squeethDeployments = await deploySqueethCoreContracts(\n            weth,\n            dai,\n            positionManager,\n            uniswapFactory,\n            scaledStartingSqueethPrice,\n            startingEthPrice\n        );\n        controller = squeethDeployments.controller;\n        wSqueeth = squeethDeployments.wsqueeth;\n        oracle = squeethDeployments.oracle;\n        // shortSqueeth = squeethDeployments.shortSqueeth\n        wSqueethPool = squeethDeployments.wsqueethEthPool;\n        ethDaiPool = squeethDeployments.ethDaiPool;\n\n        const TimelockContract = await ethers.getContractFactory(\"Timelock\");\n        timelock = (await TimelockContract.deploy(owner.address, 3 * 24 * 60 * 60)) as Timelock;\n\n        const crabStrategyV2Contract = await ethers.getContractFactory(\"CrabStrategyV2\");\n        crabStrategyV2 = (await crabStrategyV2Contract.deploy(\n            controller.address,\n            oracle.address,\n            weth.address,\n            uniswapFactory.address,\n            wSqueethPool.address,\n            timelock.address,\n            crabMigration.address,\n            hedgeTimeThreshold,\n            hedgePriceThreshold\n        )) as CrabStrategyV2;\n    });\n\n    this.beforeAll(\"Seed pool liquidity\", async () => {\n        // add liquidity\n\n        await addWethDaiLiquidity(\n            startingEthPrice,\n            ethers.utils.parseUnits(\"100\"), // eth amount\n            owner.address,\n            dai,\n            weth,\n            positionManager\n        );\n        await provider.send(\"evm_increaseTime\", [600]);\n        await provider.send(\"evm_mine\", []);\n\n        await addSqueethLiquidity(\n            scaledStartingSqueethPrice,\n            \"1000000\",\n            \"2000000\",\n            owner.address,\n            wSqueeth,\n            weth,\n            positionManager,\n            controller\n        );\n        await provider.send(\"evm_increaseTime\", [600]);\n        await provider.send(\"evm_mine\", []);\n    });\n\n    this.beforeAll(\"Initialize strategy\", async () => {\n        const ethToDeposit = ethers.utils.parseUnits(\"20\");\n\n        const normFactor = await controller.normalizationFactor();\n        const currentScaledSquethPrice = await oracle.getTwap(\n            wSqueethPool.address,\n            wSqueeth.address,\n            weth.address,\n            300,\n            false\n        );\n        const feeRate = await controller.feeRate();\n        const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000);\n        const squeethDelta = scaledStartingSqueethPrice1e18.mul(2); // .66*10^18\n        const debtToMint = wdiv(ethToDeposit, squeethDelta.add(ethFeePerWSqueeth));\n        const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one));\n\n        const strategyCap = ethers.utils.parseUnits(\"1000\");\n\n        await crabStrategyV2.connect(crabMigration).initialize(debtToMint, expectedEthDeposit, 1, 1, strategyCap, { value: ethToDeposit });\n        \n        const strategyCapInContract = await crabStrategyV2.strategyCap();\n        expect(strategyCapInContract.eq(strategyCap)).to.be.true;\n\n        await crabStrategyV2.connect(crabMigration).transfer(depositor.address, expectedEthDeposit);\n\n        const totalSupply = await crabStrategyV2.totalSupply();\n        const depositorCrab = await crabStrategyV2.balanceOf(depositor.address);\n        const strategyVault = await controller.vaults(await crabStrategyV2.vaultId());\n        const debtAmount = strategyVault.shortAmount;\n        const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address);\n        const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategyV2.address);\n        const lastHedgeTime = await crabStrategyV2.timeAtLastHedge();\n        const collateralAmount = await strategyVault.collateralAmount;\n\n        expect(isSimilar(totalSupply.toString(), expectedEthDeposit.toString())).to.be.true;\n        expect(isSimilar(depositorCrab.toString(), expectedEthDeposit.toString())).to.be.true;\n        expect(isSimilar(debtAmount.toString(), debtToMint.toString())).to.be.true;\n        expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true;\n    });\n\n    describe(\"Hedging\", async () => {\n        const getOSQTHPrice = () => oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false);\n        const mintAndSell = async (toMint = \"1000\") => {\n            const ethToDeposit = ethers.utils.parseUnits(\"1000\");\n            const wSqueethToMint = ethers.utils.parseUnits(toMint);\n            const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp;\n            await controller.connect(owner).mintWPowerPerpAmount(\"0\", wSqueethToMint, \"0\", { value: ethToDeposit });\n            await buyWeth(\n                swapRouter,\n                wSqueeth,\n                weth,\n                owner.address,\n                await wSqueeth.balanceOf(owner.address),\n                currentBlockTimestamp + 10\n            );\n\n            await provider.send(\"evm_increaseTime\", [86400 + auctionTime / 2]);\n            await provider.send(\"evm_mine\", []);\n        };\n        const delta = async (vault: any) => {\n            // oSQTH price before\n            const oSQTHPriceBefore = await getOSQTHPrice();\n            const oSQTHdelta = wmul(vault.shortAmount.mul(2), oSQTHPriceBefore);\n            const delta:BigNumber = vault.collateralAmount.sub(oSQTHdelta);\n\n            return delta;\n        };\n        const getTypeAndDomainData = () => {\n            const typeData = {\n                Order: [\n                    { type: \"uint256\", name: \"bidId\" },\n                    { type: \"address\", name: \"trader\" },\n                    { type: \"uint256\", name: \"quantity\" },\n                    { type: \"uint256\", name: \"price\" },\n                    { type: \"bool\", name: \"isBuying\" },\n                    { type: \"uint256\", name: \"expiry\" },\n                    { type: \"uint256\", name: \"nonce\" },\n                ],\n            };\n            const domainData = {\n                name: \"CrabOTC\",\n                version: \"2\",\n                chainId: network.config.chainId,\n                verifyingContract: crabStrategyV2.address,\n            };\n            return { typeData, domainData };\n        };\n        it(\"should hedge via OTC using multiple orders while sell oSQTH and updated timeAtLastHedge\", async () => {\n            await mintAndSell();\n            const strategyVaultBefore = await controller.vaults(await crabStrategyV2.vaultId());\n            // vault state before\n            const deltaStart = await delta(strategyVaultBefore);\n            // trader amount to sell oSQTH to change the deltas\n            expect(deltaStart.isNegative()).to.be.false;\n\n            // Calculate new Delta and the trades to make\n            const newDelta = await delta(strategyVaultBefore);\n            const oSQTHPriceAfter = await getOSQTHPrice();\n            const toSell = wdiv(newDelta, oSQTHPriceAfter); // 0.12sqth to sell\n            const toGET = wmul(toSell, oSQTHPriceAfter); // 0.04eth to get\n\n            // make the approvals for the trade\n            await weth.connect(random).deposit({ value: toGET });\n            await weth.connect(random).approve(crabStrategyV2.address, toGET); //0.04eth\n            await weth.connect(trader).deposit({ value: toGET });\n            await weth.connect(trader).approve(crabStrategyV2.address, toGET); //0.04eth\n\n            // get the pre trade balances for the trader\n            const oSQTHTraderBalanceBefore = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceBefore = await weth.balanceOf(trader.address);\n            const oSQTHTraderBalanceBefore_2 = await wSqueeth.balanceOf(random.address);\n            const wethTraderBalanceBefore_2 = await weth.balanceOf(random.address);\n\n            // and prepare the trade\n            const orderHash = {\n                bidId: 0,\n                trader: random.address,\n                quantity: toSell.div(4), // 0.03sqth\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 1\n            };\n            const orderHash1 = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell.div(2),\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 1\n            };\n            const orderHash2 = {\n                bidId: 0,\n                trader: random.address,\n                quantity: toSell.div(4), // 0.03sqth\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 101\n            };\n\n            const { typeData, domainData } = getTypeAndDomainData();\n            const signedOrder = await signTypedData(random, domainData, typeData, orderHash);\n            const signedOrder1 = await signTypedData(trader, domainData, typeData, orderHash1);\n            const signedOrder2 = await signTypedData(random, domainData, typeData, orderHash2);\n\n            // Do the trade\n            await crabStrategyV2.connect(owner).hedgeOTC(toSell, oSQTHPriceAfter, false, [signedOrder, signedOrder1, signedOrder2]);\n\n            // check the delta and the vaults traded quantities\n            const strategyVaultAfter = await controller.vaults(await crabStrategyV2.vaultId());\n            let precision = 4; // the last of 18 digit precision\n            expect(strategyVaultAfter.collateralAmount).be.closeTo(\n                strategyVaultBefore.collateralAmount.add(toGET),\n                precision\n            );\n            expect(strategyVaultAfter.shortAmount).be.closeTo(strategyVaultBefore.shortAmount.add(toSell), precision);\n            expect((await delta(strategyVaultAfter)).toNumber()).be.closeTo(0, precision);\n            // check the delta and the vaults traded quantities\n\n            // check trader balances\n            const oSQTHTraderBalanceAfter = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceAfter = await weth.balanceOf(trader.address);\n            const oSQTHTraderBalanceAfter_2 = await wSqueeth.balanceOf(random.address);\n            const wethTraderBalanceAfter_2 = await weth.balanceOf(random.address);\n            expect(oSQTHTraderBalanceAfter).be.closeTo(oSQTHTraderBalanceBefore.add(toSell.div(2)), precision);\n            expect(wethTraderBalanceAfter).be.closeTo(wethTraderBalanceBefore.sub(toGET.div(2)), precision);\n            expect(oSQTHTraderBalanceAfter_2).be.closeTo(oSQTHTraderBalanceBefore_2.add(toSell.div(2)), precision);\n            expect(wethTraderBalanceAfter_2).be.closeTo(wethTraderBalanceBefore_2.sub(toGET.div(2)), precision);\n\n            // get hedgeBlock to be updated\n            const hedgeBlockNumber = await provider.getBlockNumber();\n            const hedgeBlock = await provider.getBlock(hedgeBlockNumber);\n\n            const timeAtLastHedge = await crabStrategyV2.timeAtLastHedge();\n            const priceAtLastHedge = await crabStrategyV2.priceAtLastHedge();\n\n            expect(timeAtLastHedge.eq(hedgeBlock.timestamp)).to.be.true;\n            expect(priceAtLastHedge).to.eq(oSQTHPriceAfter);\n        });\n        it(\"should hedge via OTC using one order while selling oSQTH\", async () => {\n            // TODO comment and organize like below test\n            const strategyVaultBefore = await controller.vaults(await crabStrategyV2.vaultId());\n            const oSQTHPriceBefore = await oracle.getTwap(\n                wSqueethPool.address,\n                wSqueeth.address,\n                weth.address,\n                600,\n                false\n            );\n            const oSQTHdelta = wmul(strategyVaultBefore.shortAmount.mul(2), oSQTHPriceBefore);\n            const delta = strategyVaultBefore.collateralAmount.sub(oSQTHdelta);\n\n            const ethToDeposit = ethers.utils.parseUnits(\"1000\");\n            const wSqueethToMint = ethers.utils.parseUnits(\"1000\");\n            const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp;\n            await controller.connect(owner).mintWPowerPerpAmount(\"0\", wSqueethToMint, \"0\", { value: ethToDeposit });\n            await buyWeth(\n                swapRouter,\n                wSqueeth,\n                weth,\n                owner.address,\n                await wSqueeth.balanceOf(owner.address),\n                currentBlockTimestamp + 10\n            );\n\n            await provider.send(\"evm_increaseTime\", [86400 + auctionTime / 2]);\n            await provider.send(\"evm_mine\", []);\n\n            const oSQTHPriceAfter = await oracle.getTwap(\n                wSqueethPool.address,\n                wSqueeth.address,\n                weth.address,\n                600,\n                false\n            );\n            const newOSQTHdelta = wmul(strategyVaultBefore.shortAmount.mul(2), oSQTHPriceAfter);\n            const newDelta = strategyVaultBefore.collateralAmount.sub(newOSQTHdelta);\n            const toSell = wdiv(newDelta, oSQTHPriceAfter);\n            const toGET = wmul(toSell, oSQTHPriceAfter);\n\n            const afterOSQTHdelta = wmul(strategyVaultBefore.shortAmount.add(toSell).mul(2), oSQTHPriceAfter);\n            const afterTradeDelta = strategyVaultBefore.collateralAmount.add(toGET).sub(afterOSQTHdelta);\n\n            // expect((await crabStrategyV2.checkTimeHedge())[0]).to.be.true;\n\n            await weth.connect(random).deposit({ value: toGET });\n            await weth.connect(random).approve(crabStrategyV2.address, toGET);\n            const orderHash = {\n                bidId: 0,\n                trader: random.address,\n                quantity: toSell,\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 2,\n            };\n\n            const { typeData, domainData } = getTypeAndDomainData();\n            const signedOrder = await signTypedData(random, domainData, typeData, orderHash);\n\n            await crabStrategyV2.connect(owner).hedgeOTC(toSell, oSQTHPriceAfter, false, [signedOrder]);\n            const strategyVaultAfter = await controller.vaults(await crabStrategyV2.vaultId());\n            let precision = 4;\n            expect(strategyVaultAfter.shortAmount).be.closeTo(strategyVaultBefore.shortAmount.add(toSell), precision);\n            expect(strategyVaultAfter.collateralAmount).be.closeTo(\n                strategyVaultBefore.collateralAmount.add(toGET),\n                precision\n            );\n        });\n        it(\"should hedge via OTC using one order while buying oSQTH delta negative\", async () => {\n            const trader = random;\n            // oSQTH price before\n            const oSQTHPriceBefore = await oracle.getTwap(\n                wSqueethPool.address,\n                wSqueeth.address,\n                weth.address,\n                600,\n                false\n            );\n\n            // vault state before\n            const strategyVaultBefore = await controller.vaults(await crabStrategyV2.vaultId());\n            const oSQTHdelta = wmul(strategyVaultBefore.shortAmount.mul(2), oSQTHPriceBefore);\n            const delta = strategyVaultBefore.collateralAmount.sub(oSQTHdelta);\n\n            const ethToDeposit = ethers.utils.parseUnits(\"1000\");\n            const wSqueethToMint = ethers.utils.parseUnits(\"1000\");\n            const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp;\n\n            // trader amount to sell\n            await controller.connect(trader).mintWPowerPerpAmount(\"0\", wSqueethToMint, \"0\", { value: ethToDeposit });\n\n            // do the trade to offset delta\n            await buyWSqueeth(swapRouter, wSqueeth, weth, owner.address, ethToDeposit, currentBlockTimestamp + 10);\n\n            await provider.send(\"evm_increaseTime\", [86400 + auctionTime / 2]);\n            await provider.send(\"evm_mine\", []);\n\n            const oSQTHPriceAfter = await oracle.getTwap(\n                wSqueethPool.address,\n                wSqueeth.address,\n                weth.address,\n                600,\n                false\n            );\n\n            // Calculate new Delta and the trades to make\n            const newOSQTHdelta = wmul(strategyVaultBefore.shortAmount.mul(2), oSQTHPriceAfter);\n            const newDelta = strategyVaultBefore.collateralAmount.sub(newOSQTHdelta);\n\n            const toGET = wdiv(newDelta.abs(), oSQTHPriceAfter);\n            const toSell = wmul(toGET, oSQTHPriceAfter);\n\n            const afterOSQTHdelta = wmul(strategyVaultBefore.shortAmount.sub(toGET).mul(2), oSQTHPriceAfter);\n            const afterTradeDelta = strategyVaultBefore.collateralAmount.sub(toSell).sub(afterOSQTHdelta);\n\n            // get the pre trade balances for the trader\n            const oSQTHTraderBalanceBefore = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceBefore = await weth.balanceOf(trader.address);\n\n            // make the approvals for the trade and prepare the trade\n            await wSqueeth.connect(trader).approve(crabStrategyV2.address, toGET);\n\n            const orderHash = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toGET,\n                price: oSQTHPriceAfter,\n                isBuying: false,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 3,\n            };\n\n            const { typeData, domainData } = getTypeAndDomainData();\n            // Do the trade\n            const signedOrder = await signTypedData(trader, domainData, typeData, orderHash);\n            await crabStrategyV2.connect(owner).hedgeOTC(toGET, oSQTHPriceAfter, true, [signedOrder]);\n\n            // check the delta and the vaults traded quantities\n            const strategyVaultAfter = await controller.vaults(await crabStrategyV2.vaultId());\n            const afterOSQTHdeltaReal = wmul(strategyVaultAfter.shortAmount.mul(2), oSQTHPriceAfter);\n            const afterTradeDeltaReal = strategyVaultAfter.collateralAmount.sub(afterOSQTHdeltaReal);\n            const precision = 4;\n            expect(afterTradeDeltaReal.toNumber()).be.closeTo(0, precision);\n            expect(strategyVaultAfter.collateralAmount).be.closeTo(\n                strategyVaultBefore.collateralAmount.sub(toSell),\n                precision\n            );\n            expect(strategyVaultAfter.shortAmount).be.closeTo(strategyVaultBefore.shortAmount.sub(toGET), precision);\n\n            // check trader balances\n            const oSQTHTraderBalanceAfter = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceAfter = await weth.balanceOf(trader.address);\n            expect(oSQTHTraderBalanceAfter).be.closeTo(oSQTHTraderBalanceBefore.sub(toGET), precision);\n            expect(wethTraderBalanceAfter).be.closeTo(wethTraderBalanceBefore.add(toSell), precision);\n        });\n        it(\"allows manager to trader fewer quantity than sum of orders\", async () => {\n            let precision = 4;\n            const strategyVaultBefore = await controller.vaults(await crabStrategyV2.vaultId());\n            // vault state before\n            const deltaStart = await delta(strategyVaultBefore);\n            expect(deltaStart.toNumber()).be.closeTo(0, precision);\n            // trader amount to sell oSQTH to change the deltas\n            await mintAndSell();\n\n            // Calculate new Delta and the trades to make\n            const newDelta = await delta(strategyVaultBefore);\n            const oSQTHPriceAfter = await getOSQTHPrice();\n            const toSell = wdiv(newDelta, oSQTHPriceAfter);\n            const toGET = wmul(toSell, oSQTHPriceAfter);\n\n            // make the approvals for the trade\n            await weth.connect(random).deposit({ value: toGET });\n            await weth.connect(random).approve(crabStrategyV2.address, toGET);\n            await weth.connect(trader).deposit({ value: toGET });\n            await weth.connect(trader).approve(crabStrategyV2.address, toGET);\n\n            // get the pre trade balances for the trader\n            const oSQTHTraderBalanceBefore = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceBefore = await weth.balanceOf(trader.address);\n            const oSQTHTraderBalanceBefore_2 = await wSqueeth.balanceOf(random.address);\n            const wethTraderBalanceBefore_2 = await weth.balanceOf(random.address);\n\n            // and prepare the trade\n            const orderHash = {\n                bidId: 0,\n                trader: random.address,\n                quantity: toSell.div(2),\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 4,\n            };\n            // quantity is full and not half. hence more quantity for this case, but manager trades less\n            const orderHash1 = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell,\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 4,\n            };\n\n            const { typeData, domainData } = getTypeAndDomainData();\n            const signedOrder = await signTypedData(random, domainData, typeData, orderHash);\n            const signedOrder1 = await signTypedData(trader, domainData, typeData, orderHash1);\n\n            // Do the trade\n            await crabStrategyV2.connect(owner).hedgeOTC(toSell, oSQTHPriceAfter, false, [signedOrder, signedOrder1]);\n\n            // check the delta and the vaults traded quantities\n            const strategyVaultAfter = await controller.vaults(await crabStrategyV2.vaultId());\n            expect(strategyVaultAfter.collateralAmount).be.closeTo(\n                strategyVaultBefore.collateralAmount.add(toGET),\n                precision\n            );\n            expect(strategyVaultAfter.shortAmount).be.closeTo(strategyVaultBefore.shortAmount.add(toSell), 4);\n            expect((await delta(strategyVaultAfter)).toNumber()).be.closeTo(0, precision);\n            // check the delta and the vaults traded quantities\n\n            // check trader balances\n            const oSQTHTraderBalanceAfter = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceAfter = await weth.balanceOf(trader.address);\n            const oSQTHTraderBalanceAfter_2 = await wSqueeth.balanceOf(random.address);\n            const wethTraderBalanceAfter_2 = await weth.balanceOf(random.address);\n            expect(oSQTHTraderBalanceAfter).be.closeTo(oSQTHTraderBalanceBefore.add(toSell.div(2)), precision);\n            expect(wethTraderBalanceAfter).be.closeTo(wethTraderBalanceBefore.sub(toGET.div(2)), precision);\n            expect(oSQTHTraderBalanceAfter_2).be.closeTo(oSQTHTraderBalanceBefore_2.add(toSell.div(2)), precision);\n            expect(wethTraderBalanceAfter_2).be.closeTo(wethTraderBalanceBefore_2.sub(toGET.div(2)), precision);\n        });\n        it(\"allows manager to trade more quantity than sum of orders\", async () => {\n            let precision = 4;\n            const strategyVaultBefore = await controller.vaults(await crabStrategyV2.vaultId());\n            // vault state before\n            const deltaStart = await delta(strategyVaultBefore);\n            expect(deltaStart.toNumber()).be.closeTo(0, precision);\n            // trader amount to sell oSQTH to change the deltas\n            await mintAndSell();\n\n            // Calculate new Delta and the trades to make\n            const newDelta = await delta(strategyVaultBefore);\n            const oSQTHPriceAfter = await getOSQTHPrice();\n            const toSell = wdiv(newDelta, oSQTHPriceAfter);\n            const toGET = wmul(toSell, oSQTHPriceAfter);\n\n            // make the approvals for the trade\n            await weth.connect(random).deposit({ value: toGET });\n            await weth.connect(random).approve(crabStrategyV2.address, toGET);\n            await weth.connect(trader).deposit({ value: toGET });\n            await weth.connect(trader).approve(crabStrategyV2.address, toGET);\n\n            // get the pre trade balances for the trader\n            const oSQTHTraderBalanceBefore = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceBefore = await weth.balanceOf(trader.address);\n            const oSQTHTraderBalanceBefore_2 = await wSqueeth.balanceOf(random.address);\n            const wethTraderBalanceBefore_2 = await weth.balanceOf(random.address);\n\n            // and prepare the trade\n            const orderHash = {\n                bidId: 0,\n                trader: random.address,\n                quantity: toSell.div(2), // 0.06sqth\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 5,\n            };\n            const orderHash1 = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell.div(2),\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 5,\n            };\n\n            const { typeData, domainData } = getTypeAndDomainData();\n            const signedOrder = await signTypedData(random, domainData, typeData, orderHash);\n            const signedOrder1 = await signTypedData(trader, domainData, typeData, orderHash1);\n\n            // Do the trade\n            await crabStrategyV2\n                .connect(owner)\n                .hedgeOTC(toSell.mul(2), oSQTHPriceAfter, false, [signedOrder, signedOrder1]);\n\n            // check the delta and the vaults traded quantities\n            const strategyVaultAfter = await controller.vaults(await crabStrategyV2.vaultId());\n            expect(strategyVaultAfter.collateralAmount).be.closeTo(\n                strategyVaultBefore.collateralAmount.add(toGET),\n                precision\n            );\n            expect(strategyVaultAfter.shortAmount).be.closeTo(strategyVaultBefore.shortAmount.add(toSell), precision);\n            expect((await delta(strategyVaultAfter)).toNumber()).be.closeTo(0, precision);\n            // check the delta and the vaults traded quantities\n            const oSQTHTraderBalanceAfter = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceAfter = await weth.balanceOf(trader.address);\n            const oSQTHTraderBalanceAfter_2 = await wSqueeth.balanceOf(random.address);\n            const wethTraderBalanceAfter_2 = await weth.balanceOf(random.address);\n            expect(oSQTHTraderBalanceAfter).be.closeTo(oSQTHTraderBalanceBefore.add(toSell.div(2)), precision);\n            expect(wethTraderBalanceAfter).be.closeTo(wethTraderBalanceBefore.sub(toGET.div(2)), precision);\n            expect(oSQTHTraderBalanceAfter_2).be.closeTo(oSQTHTraderBalanceBefore_2.add(toSell.div(2)), precision);\n            expect(wethTraderBalanceAfter_2).be.closeTo(wethTraderBalanceBefore_2.sub(toGET.div(2)), precision);\n        });\n        it(\"allows manager to give buy at a greater price\", async () => {\n            let precision = 4;\n            const strategyVaultBefore = await controller.vaults(await crabStrategyV2.vaultId());\n            // vault state before\n            const deltaStart = await delta(strategyVaultBefore);\n            // -1 is almost 0, -1/10^18\n            expect(deltaStart.toNumber()).be.closeTo(0, precision);\n            // trader amount to sell oSQTH to change the deltas\n            await mintAndSell();\n\n            // Calculate new Delta and the trades to make\n            const newDelta = await delta(strategyVaultBefore);\n            const oSQTHPriceAfter = await getOSQTHPrice();\n            const toSell = wdiv(newDelta, oSQTHPriceAfter);\n            const toGET = wmul(toSell, oSQTHPriceAfter);\n\n            // make the approvals for the trade\n            await weth.connect(random).deposit({ value: toGET });\n            await weth.connect(random).approve(crabStrategyV2.address, toGET);\n            await weth.connect(trader).deposit({ value: toGET });\n            await weth.connect(trader).approve(crabStrategyV2.address, toGET);\n\n            // get the pre trade balances for the trader\n            const oSQTHTraderBalanceBefore = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceBefore = await weth.balanceOf(trader.address);\n            const oSQTHTraderBalanceBefore_2 = await wSqueeth.balanceOf(random.address);\n            const wethTraderBalanceBefore_2 = await weth.balanceOf(random.address);\n\n            // and prepare the trade\n            const orderHash = {\n                bidId: 0,\n                trader: random.address,\n                quantity: toSell.div(2), // 0.06sqth\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 6,\n            };\n            const orderHash1 = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell.div(2),\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 6,\n            };\n\n            const { typeData, domainData } = getTypeAndDomainData();\n            const signedOrder = await signTypedData(random, domainData, typeData, orderHash);\n            const signedOrder1 = await signTypedData(trader, domainData, typeData, orderHash1);\n\n            // Do the trade with 4 percent more price\n            const managerBuyPrice = oSQTHPriceAfter.mul(96).div(100);\n            const newtoGET = wmul(toSell, managerBuyPrice);\n\n            await crabStrategyV2.connect(owner).hedgeOTC(toSell, managerBuyPrice, false, [signedOrder, signedOrder1]);\n\n            // check the delta and the vaults traded quantities\n            const strategyVaultAfter = await controller.vaults(await crabStrategyV2.vaultId());\n            const error = 1; // this is in decimals 18 so technically 0\n            // we traded full collateral sell amount and in return got lesser than oSQTH that desired, hence delta will turn negative\n            expect((await delta(strategyVaultAfter)).toNumber()).to.lessThan(\n                0,\n                \"new delta has not been in the direction of trade\"\n            );\n            expect(strategyVaultAfter.collateralAmount).be.closeTo(\n                strategyVaultBefore.collateralAmount.add(newtoGET),\n                precision\n            );\n            expect(strategyVaultAfter.shortAmount).be.closeTo(strategyVaultBefore.shortAmount.add(toSell), precision);\n            // check the delta and the vaults traded quantities\n            const oSQTHTraderBalanceAfter = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceAfter = await weth.balanceOf(trader.address);\n            const oSQTHTraderBalanceAfter_2 = await wSqueeth.balanceOf(random.address);\n            const wethTraderBalanceAfter_2 = await weth.balanceOf(random.address);\n            expect(oSQTHTraderBalanceAfter).be.closeTo(oSQTHTraderBalanceBefore.add(toSell.div(2)), precision);\n            expect(wethTraderBalanceAfter).be.closeTo(wethTraderBalanceBefore.sub(newtoGET.div(2)), precision);\n            expect(oSQTHTraderBalanceAfter_2).be.closeTo(oSQTHTraderBalanceBefore_2.add(toSell.div(2)), precision);\n            expect(wethTraderBalanceAfter_2).be.closeTo(wethTraderBalanceBefore_2.sub(newtoGET.div(2)), precision);\n\n            // trader amount to sell oSQTH to change the deltas\n            await mintAndSell(\"50\");\n            const dlt = await delta(await controller.vaults(await crabStrategyV2.vaultId()));\n            expect(dlt.toNumber()).to.be.greaterThan(0);\n        });\n        it(\"allows manager to give buy at a greater price and specify a quantity lesser than the same of order amounts\", async () => {\n            const precision = 4; // this is in decimals 18 so technically 0\n            const strategyVaultBefore = await controller.vaults(await crabStrategyV2.vaultId());\n            // vault state before\n            const deltaStart = await delta(strategyVaultBefore);\n            // -1 is almost 0, -1/10^18\n            expect(deltaStart.toNumber()).greaterThanOrEqual(0);\n            // trader amount to sell oSQTH to change the deltas\n            await mintAndSell();\n\n            // Calculate new Delta and the trades to make\n            const newDelta = await delta(strategyVaultBefore);\n            const oSQTHPriceAfter = await getOSQTHPrice();\n            const toSell = wdiv(newDelta, oSQTHPriceAfter);\n            const toGET = wmul(toSell, oSQTHPriceAfter);\n\n            // make the approvals for the trade\n            await weth.connect(random).deposit({ value: toGET });\n            await weth.connect(random).approve(crabStrategyV2.address, toGET);\n            await weth.connect(trader).deposit({ value: toGET });\n            await weth.connect(trader).approve(crabStrategyV2.address, toGET);\n\n            // get the pre trade balances for the trader\n            const oSQTHTraderBalanceBefore = await wSqueeth.balanceOf(random.address);\n            const wethTraderBalanceBefore = await weth.balanceOf(random.address);\n            const oSQTHTraderBalanceBefore_2 = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceBefore_2 = await weth.balanceOf(trader.address);\n\n            // and prepare the trade\n            const orderHash = {\n                bidId: 0,\n                trader: random.address,\n                quantity: toSell.div(2), // 0.06sqth\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 7,\n            };\n            const orderHash1 = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell.div(2),\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 7,\n            };\n\n            const { typeData, domainData } = getTypeAndDomainData();\n            const signedOrder = await signTypedData(random, domainData, typeData, orderHash);\n            const signedOrder1 = await signTypedData(trader, domainData, typeData, orderHash1);\n\n            // Do the trade with 4 percent lesser price\n            const managerBuyPrice = oSQTHPriceAfter.mul(96).div(100);\n            // and only 90% of the total trader quantities. so we swap 50% with the first order and 40% with the next\n            const newToSell = toSell.mul(90).div(100);\n            const firstToGet = wmul(toSell, managerBuyPrice);\n            const secondToGet = wmul(newToSell, managerBuyPrice);\n\n            await crabStrategyV2.connect(owner).hedgeOTC(newToSell, managerBuyPrice, false, [signedOrder, signedOrder1]);\n\n            // check the delta and the vaults traded quantities\n            const strategyVaultAfter = await controller.vaults(await crabStrategyV2.vaultId());\n            // we traded full collateral sell amount and in return got lesser than oSQTH that desired, hence delta will turn negative\n            const afterTradeDelta = (await delta(strategyVaultAfter));\n            expect(afterTradeDelta.lt(newDelta)).to.be.true;\n            expect(strategyVaultAfter.collateralAmount).be.closeTo(\n                strategyVaultBefore.collateralAmount.add(secondToGet),\n                precision\n            );\n            expect(strategyVaultAfter.shortAmount).be.closeTo(\n                strategyVaultBefore.shortAmount.add(newToSell),\n                precision\n            );\n            // check the delta and the vaults traded quantities\n            const oSQTHTraderBalanceAfter = await wSqueeth.balanceOf(random.address);\n            const wethTraderBalanceAfter = await weth.balanceOf(random.address);\n            const oSQTHTraderBalanceAfter_2 = await wSqueeth.balanceOf(trader.address);\n            const wethTraderBalanceAfter_2 = await weth.balanceOf(trader.address);\n            expect(oSQTHTraderBalanceAfter).be.closeTo(oSQTHTraderBalanceBefore.add(toSell.div(2)), precision); // he gets the full managerAmount\n            expect(wethTraderBalanceAfter).be.closeTo(wethTraderBalanceBefore.sub(firstToGet.div(2)), precision); // he gets half of the new price benefits\n\n            const difference = toSell.mul(10).div(100);\n            const second_trader_receives = toSell.div(2).sub(difference); // he gets the full - 10% as manager is trading only 90 %\n            expect(oSQTHTraderBalanceAfter_2).be.closeTo(\n                oSQTHTraderBalanceBefore_2.add(second_trader_receives),\n                precision\n            );\n            expect(wethTraderBalanceBefore_2.sub(wethTraderBalanceAfter_2)).be.closeTo(\n                wmul(second_trader_receives, managerBuyPrice),\n                precision\n            );\n        });\n        it(\"should revert on heding too quickly after the previous hedge and when price is within threshold\", async () => {\n            // this sets the price Threshold to 5% which ensures that the revert is not happening due to price\n            await crabStrategyV2.connect(owner).setHedgePriceThreshold(BigNumber.from(10).pow(16).mul(5));\n\n            // set the time to 1 hr from prev hedge\n            const lastHedge = await crabStrategyV2.timeAtLastHedge();\n            const currentBlockNumber = await provider.getBlockNumber();\n            const currentBlock = await provider.getBlock(currentBlockNumber);\n            await provider.send(\"evm_setNextBlockTimestamp\", [lastHedge.toNumber() + 3600]);\n            await provider.send(\"evm_mine\", []);\n\n            const trader = random;\n\n            // Calculate new Delta and the trades to make\n            const toGet = ethers.utils.parseUnits(\"1\");\n            const toSell = ethers.utils.parseUnits(\"1\");\n\n            // make the approvals for the trade and prepare the trade\n            await wSqueeth.connect(trader).approve(crabStrategyV2.address, toGet);\n            const oSQTHPrice = await getOSQTHPrice();\n            const orderHash = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell,\n                price: oSQTHPrice,\n                isBuying: false,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 8,\n            };\n\n            const { typeData, domainData } = getTypeAndDomainData();\n            // Do the trade\n            const signedOrder = await signTypedData(trader, domainData, typeData, orderHash);\n            await expect(\n                crabStrategyV2.connect(owner).hedgeOTC(toSell, oSQTHPrice, true, [signedOrder])\n            ).to.be.revertedWith(\"C22\");\n        });\n        it(\"should revert when the hedge trade oSQTH price is beyond threshold\", async () => {\n            // set the time to 1 hr from prev hedge\n            await provider.send(\"evm_increaseTime\", [84600 + 3600]);\n            const trader = random;\n\n            // Calculate new Delta and the trades to make\n            const toGet = ethers.utils.parseUnits(\"3.5\");\n            const toSell = ethers.utils.parseUnits(\"1\");\n            const oSQTHPrice = await getOSQTHPrice();\n\n            // make the approvals for the trade and prepare the trade\n            await wSqueeth.connect(trader).approve(crabStrategyV2.address, toGet);\n            const managerBuyPrice = oSQTHPrice.mul(130).div(100);\n\n            const orderHash = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell,\n                price: managerBuyPrice,\n                isBuying: false,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 9,\n            };\n            const { typeData, domainData } = getTypeAndDomainData();\n            // Do the trade\n            const signedOrder = await signTypedData(trader, domainData, typeData, orderHash);\n            // manager cant siphon off money to market makers\n            await expect(\n                crabStrategyV2.connect(owner).hedgeOTC(toSell, managerBuyPrice, true, [signedOrder])\n            ).to.be.revertedWith(\"Price too high relative to Uniswap twap.\");\n        });\n        it(\"should revert if the market maker order has expired\", async () => {\n            // set the time to 1 hr from prev hedge\n            await provider.send(\"evm_increaseTime\", [84600 + 3600]);\n            const trader = random;\n\n            // Calculate new Delta and the trades to make\n            const toGet = ethers.utils.parseUnits(\"3.5\");\n            const toSell = ethers.utils.parseUnits(\"1\");\n            const oSQTHPrice = await getOSQTHPrice();\n\n            // make the approvals for the trade and prepare the trade\n            await wSqueeth.connect(trader).approve(crabStrategyV2.address, toGet);\n\n            const orderHash = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell,\n                price: oSQTHPrice,\n                isBuying: false,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 10,\n            };\n            const { typeData, domainData } = getTypeAndDomainData();\n            // expire the order\n            await provider.send(\"evm_increaseTime\", [700]);\n            // Do the trade\n            const signedOrder = await signTypedData(trader, domainData, typeData, orderHash);\n            await expect(\n                crabStrategyV2.connect(owner).hedgeOTC(toSell, oSQTHPrice, true, [signedOrder])\n            ).to.be.revertedWith(\"C20\");\n        });\n        it(\"reverts when order sign is invalid\", async () => {\n            const trader = random;\n            // vault state before\n            const strategyVaultBefore = await controller.vaults(await crabStrategyV2.vaultId());\n\n            const ethToDeposit = ethers.utils.parseUnits(\"1000\");\n            const wSqueethToMint = ethers.utils.parseUnits(\"1000\");\n            const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp;\n            // trader amount to sell\n            await controller.connect(trader).mintWPowerPerpAmount(\"0\", wSqueethToMint, \"0\", { value: ethToDeposit });\n            // do the trade to offset delta\n            await buyWSqueeth(swapRouter, wSqueeth, weth, owner.address, ethToDeposit, currentBlockTimestamp + 10);\n\n            await provider.send(\"evm_increaseTime\", [86400 + auctionTime / 2]);\n\n            const oSQTHPriceAfter = await oracle.getTwap(\n                wSqueethPool.address,\n                wSqueeth.address,\n                weth.address,\n                600,\n                false\n            );\n\n            // Calculate new Delta and the trades to make\n            const newOSQTHdelta = wmul(strategyVaultBefore.shortAmount.mul(2), oSQTHPriceAfter);\n            const newDelta = strategyVaultBefore.collateralAmount.sub(newOSQTHdelta);\n\n            const toGET = wdiv(newDelta.abs(), oSQTHPriceAfter);\n            const toSell = wmul(toGET, oSQTHPriceAfter);\n\n            // make the approvals for the trade and prepare the trade\n            await wSqueeth.connect(trader).approve(crabStrategyV2.address, toGET);\n\n            const orderHash = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell,\n                price: oSQTHPriceAfter,\n                isBuying: false,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 11,\n            };\n\n            const { typeData, domainData } = getTypeAndDomainData();\n            // Do the trade with wrong order\n            const signedOrder = await signTypedData(depositor, domainData, typeData, orderHash);\n            await expect(\n                crabStrategyV2.connect(owner).hedgeOTC(toSell, oSQTHPriceAfter, true, [signedOrder])\n            ).to.be.revertedWith(\"C19\");\n        });\n        it(\"should revert when the manager Buy price is lesser than the traders price\", async () => {\n            await crabStrategyV2.connect(owner).setHedgePriceThreshold(BigNumber.from(10).pow(16).mul(5));\n            // set the time to 1 hr from prev hedge\n            await provider.send(\"evm_increaseTime\", [84600 + 3600]);\n            const trader = random;\n\n            // Calculate new Delta and the trades to make\n            const toGet = ethers.utils.parseUnits(\"3.125\");\n            const toSell = ethers.utils.parseUnits(\"1\");\n            const oSQTHPrice = await getOSQTHPrice();\n\n            // make the approvals for the trade and prepare the trade\n            await wSqueeth.connect(trader).approve(crabStrategyV2.address, toGet);\n            const orderHash = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell,\n                price: oSQTHPrice,\n                isBuying: false,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 12,\n            };\n            const { typeData, domainData } = getTypeAndDomainData();\n            // Do the trade\n            const signedOrder = await signTypedData(trader, domainData, typeData, orderHash);\n            const managerBuyPrice = oSQTHPrice.mul(99).div(100);\n            await expect(\n                crabStrategyV2.connect(owner).hedgeOTC(toSell, managerBuyPrice, true, [signedOrder])\n            ).to.be.revertedWith(\"C18\");\n        });\n        it(\"manager buy price should be greater than 0\", async () => {\n            // set the time to 1 hr from prev hedge\n            await provider.send(\"evm_increaseTime\", [84600 + 3600]);\n            const trader = random;\n\n            // Calculate new Delta and the trades to make\n            const toGet = ethers.utils.parseUnits(\"3.125\");\n            const toSell = ethers.utils.parseUnits(\"1\");\n\n            // make the approvals for the trade and prepare the trade\n            await wSqueeth.connect(trader).approve(crabStrategyV2.address, toGet);\n\n            const orderHash = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell,\n                price: 1,\n                isBuying: false,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 12,\n            };\n            const { typeData, domainData } = getTypeAndDomainData();\n            // Do the trade\n            const signedOrder = await signTypedData(trader, domainData, typeData, orderHash);\n            const managerBuyPrice = 0;\n            await expect(\n                crabStrategyV2.connect(owner).hedgeOTC(toSell, managerBuyPrice, true, [signedOrder])\n            ).to.be.revertedWith(\"C21\");\n\n            // reverting this back to one percent\n            await crabStrategyV2.connect(owner).setHedgePriceThreshold(BigNumber.from(10).pow(16).mul(1));\n        });\n        it(\"market maker should be able to cancel an order by incrementing its nonce\", async () => {\n            // set the time to 1 hr from prev hedge\n            await provider.send(\"evm_increaseTime\", [84600 + 3600]);\n            const trader = random;\n            const nonce = 67345;\n\n            // Calculate new Delta and the trades to make\n            const toGet = ethers.utils.parseUnits(\"3.125\");\n            const toSell = ethers.utils.parseUnits(\"1\");\n\n            // make the approvals for the trade and prepare the trade\n            await wSqueeth.connect(trader).approve(crabStrategyV2.address, toGet);\n            await crabStrategyV2.connect(trader).setNonceTrue(nonce);\n\n            const orderHash = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell,\n                price: 1,\n                isBuying: false,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: nonce,\n            };\n            const { typeData, domainData } = getTypeAndDomainData();\n            // Do the trade\n            const signedOrder = await signTypedData(trader, domainData, typeData, orderHash);\n            const managerBuyPrice = 1;\n            await expect(\n                crabStrategyV2.connect(owner).hedgeOTC(toSell, managerBuyPrice, true, [signedOrder])\n            ).to.be.revertedWith(\"C27\");\n        });\n        it(\"nonce repeated\", async () => {\n            // set the time to 1 hr from prev hedge\n            await provider.send(\"evm_increaseTime\", [84600 + 3600]);\n            const trader = random;\n\n            // Calculate new Delta and the trades to make\n            const toGet = ethers.utils.parseUnits(\"3.125\");\n            const toSell = ethers.utils.parseUnits(\"1\");\n\n            // make the approvals for the trade and prepare the trade\n            await wSqueeth.connect(trader).approve(crabStrategyV2.address, toGet);\n\n            const orderHash = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell,\n                price: 1,\n                isBuying: false,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 1, // this nonce is used in the first test\n            };\n            const { typeData, domainData } = getTypeAndDomainData();\n            // Do the trade\n            const signedOrder = await signTypedData(trader, domainData, typeData, orderHash);\n            const managerBuyPrice = 1;\n            await expect(\n                crabStrategyV2.connect(owner).hedgeOTC(toSell, managerBuyPrice, true, [signedOrder])\n            ).to.be.revertedWith(\"C27\");\n        });\n        it(\"orders should be arranged in best price first\", async () => {\n            const strategyVaultBefore = await controller.vaults(await crabStrategyV2.vaultId());\n            // vault state before\n            const deltaStart = await delta(strategyVaultBefore);\n            // trader amount to sell oSQTH to change the deltas\n            await mintAndSell();\n\n            // Calculate new Delta and the trades to make\n            const newDelta = await delta(strategyVaultBefore);\n            const oSQTHPriceAfter = await getOSQTHPrice();\n            const toSell = wdiv(newDelta, oSQTHPriceAfter);\n            const toGET = wmul(toSell, oSQTHPriceAfter);\n\n            // make the approvals for the trade\n            await weth.connect(random).deposit({ value: toGET });\n            await weth.connect(random).approve(crabStrategyV2.address, toGET);\n            await weth.connect(trader).deposit({ value: toGET });\n            await weth.connect(trader).approve(crabStrategyV2.address, toGET);\n\n            // and prepare the trade\n            const orderHash = {\n                bidId: 0,\n                trader: random.address,\n                quantity: toSell.div(2),\n                price: oSQTHPriceAfter,\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 13,\n            };\n            const orderHash1 = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell.div(2),\n                price: oSQTHPriceAfter.mul(102).div(100),\n                isBuying: true,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 13,\n            };\n\n            const { typeData, domainData } = getTypeAndDomainData();\n            const signedOrder = await signTypedData(random, domainData, typeData, orderHash);\n            const signedOrder1 = await signTypedData(trader, domainData, typeData, orderHash1);\n\n            // Do the trade\n            await expect(\n                crabStrategyV2.connect(owner).hedgeOTC(toSell, oSQTHPriceAfter, false, [signedOrder, signedOrder1])\n            ).to.be.revertedWith(\"C25\");\n        });\n        it(\"order signed for a different contract i.e EIP 712 attack\", async () => {\n            // set the time to 1 hr from prev hedge\n            await provider.send(\"evm_increaseTime\", [84600 + 3600]);\n            const trader = random;\n\n            // Calculate new Delta and the trades to make\n            const toGet = ethers.utils.parseUnits(\"3.125\");\n            const toSell = ethers.utils.parseUnits(\"1\");\n\n            // make the approvals for the trade and prepare the trade\n            await wSqueeth.connect(trader).approve(crabStrategyV2.address, toGet);\n\n            const orderHash = {\n                bidId: 0,\n                trader: trader.address,\n                quantity: toSell,\n                price: 1,\n                isBuying: false,\n                expiry: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 600,\n                nonce: 909090,\n            };\n            const { typeData, domainData } = getTypeAndDomainData();\n            domainData.verifyingContract = timelock.address;\n            // Do the trade\n            const signedOrder = await signTypedData(trader, domainData, typeData, orderHash);\n            const managerBuyPrice = 1;\n            await expect(\n                crabStrategyV2.connect(owner).hedgeOTC(toSell, managerBuyPrice, true, [signedOrder])\n            ).to.be.revertedWith(\"C19\");\n        });\n        it(\"should allow manager to set thresholds\", async () => {\n            await expect(crabStrategyV2.connect(owner).setHedgingTwapPeriod(120)).to.be.revertedWith(\n                \"C14\"\n            );\n            await crabStrategyV2.connect(owner).setHedgingTwapPeriod(190);\n            expect(await crabStrategyV2.hedgingTwapPeriod()).to.eq(190);\n\n            await expect(crabStrategyV2.connect(owner).setHedgeTimeThreshold(0)).to.be.revertedWith(\n                \"C7\"\n            );\n            await crabStrategyV2.connect(owner).setHedgeTimeThreshold(9000);\n            expect(await crabStrategyV2.hedgeTimeThreshold()).to.eq(9000);\n\n            await expect(\n                crabStrategyV2.connect(owner).setOTCPriceTolerance(BigNumber.from(10).pow(17).mul(3))\n            ).to.be.revertedWith(\"C15\");\n            await crabStrategyV2.connect(owner).setOTCPriceTolerance(BigNumber.from(10).pow(17));\n            expect((await crabStrategyV2.otcPriceTolerance()).eq(BigNumber.from(10).pow(17))).to.be.true;\n        });\n    });\n});"
  },
  {
    "path": "packages/hardhat/test/integration-tests/crabv2/crab-helper.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport BigNumberJs from 'bignumber.js'\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategyV2, ISwapRouter, Timelock, CrabHelper } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity, createUniPool } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({ EXPONENTIAL_AT: 30 })\n\ndescribe(\"Crab V2 integration test: ERC20 deposit and withdrawals\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.mul(11).div(10).div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice * 1.1 / oracleScaleFactor.toNumber() // 0.3\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n  let poolFee: BigNumber;\n  let poolFeePool2: BigNumber\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress;\n  let crabMigration: SignerWithAddress;\n  let liquidator: SignerWithAddress;\n  let feeRecipient: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueethPool2: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategyV2\n  let ethDaiPool: Contract\n  let timelock: Timelock;\n  let crabHelper: CrabHelper;\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async () => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _depositor2, _liquidator, _feeRecipient, _crabMigration] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    depositor2 = _depositor2;\n    liquidator = _liquidator;\n    feeRecipient = _feeRecipient;\n    crabMigration = _crabMigration;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai,\n      positionManager,\n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    wSqueethPool2 = await createUniPool(scaledStartingSqueethPrice, weth, wSqueeth, positionManager, uniswapFactory, 10000) as Contract\n    await wSqueethPool2.increaseObservationCardinalityNext(500) \n  \n    poolFee = await wSqueethPool.fee()\n    poolFeePool2 = await wSqueethPool2.fee()\n\n\n    await controller.connect(owner).setFeeRecipient(feeRecipient.address);\n    await controller.connect(owner).setFeeRate(100)\n\n    const TimelockContract = await ethers.getContractFactory(\"Timelock\");\n    timelock = (await TimelockContract.deploy(owner.address, 3 * 24 * 60 * 60)) as Timelock;\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, timelock.address, crabMigration.address, hedgeTimeThreshold, hedgePriceThreshold)) as CrabStrategyV2;\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async () => {\n    await provider.send(\"evm_increaseTime\", [300])\n    await provider.send(\"evm_mine\", [])\n\n    // add liquidity\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      '1000000',\n      '2000000',\n      owner.address,\n      wSqueeth,\n      weth,\n      positionManager,\n      controller\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      '1000000',\n      '2000000',\n      owner.address,\n      wSqueeth,\n      weth,\n      positionManager,\n      controller,\n      10000\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"Deploy Crab Helper\", async () => {\n    const CrabHelperContract = await ethers.getContractFactory(\"CrabHelper\");\n    crabHelper = (await CrabHelperContract.deploy(crabStrategy.address, swapRouter.address)) as CrabHelper;\n  })\n\n  this.beforeAll(\"Initialize strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits(\"20\");\n\n    const normFactor = await controller.normalizationFactor();\n    const currentScaledSquethPrice = await oracle.getTwap(\n        wSqueethPool.address,\n        wSqueeth.address,\n        weth.address,\n        300,\n        false\n    );\n    const feeRate = await controller.feeRate();\n    const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000);\n    const squeethDelta = scaledStartingSqueethPrice1e18.mul(2); // .66*10^18\n    const debtToMint = wdiv(ethToDeposit, squeethDelta.add(ethFeePerWSqueeth));\n    const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one));\n\n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n\n    await crabStrategy.connect(crabMigration).initialize(debtToMint, expectedEthDeposit, 1, 1, strategyCap, { value: ethToDeposit });\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n\n});\n\n  describe(\"Deposit USDC into strategy\", async () => {\n    const usdcAmount = startingEthPrice1e18\n    const ethToDeposit = ethers.utils.parseUnits('1.5')\n\n    beforeEach(async () => {\n      await dai.mint(depositor2.address, usdcAmount.toString())\n      await dai.connect(depositor2).approve(crabHelper.address, usdcAmount.toString())\n    })\n\n    it(\"Should fail if it minimum ETH is not swapped in ERC20 transfer\", async () => {\n      await expect(crabHelper.connect(depositor2).flashDepositERC20(ethToDeposit, usdcAmount, ethers.utils.parseEther('1'), 3000, poolFee, dai.address)).to.be.revertedWith(\"Too little received\")\n    })\n\n    it(\"Should deposit USDC into strategy\", async () => {\n      const usdcBalanceBefore = await dai.balanceOf(depositor2.address)\n      const crabBalanceBefore = await crabStrategy.balanceOf(depositor2.address)\n\n      await expect(crabHelper.connect(depositor2).flashDepositERC20(ethToDeposit, usdcAmount, 0, 3000, poolFee, dai.address)).to.emit(crabHelper, \"FlashDepositERC20\")\n\n      const usdcBalanceAfter = await dai.balanceOf(depositor2.address)\n      const crabBalanceAfter = await crabStrategy.balanceOf(depositor2.address)\n\n      expect(usdcBalanceBefore.sub(usdcAmount)).to.be.equal(usdcBalanceAfter)\n      expect(crabBalanceAfter.gt(crabBalanceBefore)).to.be.true\n    })\n  })\n\n  describe(\"Withdraw USDC from strategy\", async () => {\n    const usdcAmount = startingEthPrice1e18\n    const ethToDeposit = ethers.utils.parseUnits('1.5')\n    let crabBalance = BigNumber.from(0)\n\n    beforeEach(\"Deposit into strategy\", async () => {\n      await dai.mint(depositor2.address, usdcAmount.toString())\n      await dai.connect(depositor2).approve(crabHelper.address, usdcAmount.toString())\n      await crabHelper.connect(depositor2).flashDepositERC20(ethToDeposit, usdcAmount, 0, 3000, poolFee, dai.address)\n      crabBalance = await crabStrategy.balanceOf(depositor2.address)\n    })\n\n    afterEach(\"Clean up deposit\", async () => {\n      const _crb = await crabStrategy.balanceOf(depositor2.address)\n      if (_crb.gt(0)) {\n        await crabStrategy.connect(depositor2).flashWithdraw(_crb, ethToDeposit, poolFee)\n      }\n    })\n\n    it(\"Should fail if it minimum USDC out is not swapped in ERC20 transfer\", async () => {\n      await crabStrategy.connect(depositor2).approve(crabHelper.address, crabBalance)\n      await expect(crabHelper.connect(depositor2).flashWithdrawERC20(crabBalance, ethToDeposit, dai.address, usdcAmount.mul(2), 3000, poolFee)).to.be.revertedWith(\"Too little received\")\n    })\n\n    it(\"Should withdraw USDC from strategy\", async () => {\n      const usdcBalanceBefore = await dai.balanceOf(depositor2.address)\n\n      const minUsdToGet = usdcAmount.div(2)\n      await expect(crabHelper.connect(depositor2).flashWithdrawERC20(crabBalance, ethToDeposit.mul(2), dai.address, minUsdToGet, 3000, poolFee)).to.emit(crabHelper, \"FlashWithdrawERC20\")\n\n      const usdcBalanceAfter = await dai.balanceOf(depositor2.address)\n      const crabBalanceAfter = await crabStrategy.balanceOf(depositor2.address)\n\n      expect(usdcBalanceAfter.gte(usdcBalanceBefore.add(minUsdToGet))).to.be.true\n      expect(crabBalanceAfter).to.be.equal(\"0\")\n    })\n  })\n\n  describe(\"Deposit USDC into strategy in 1% pool\", async () => {\n    const usdcAmount = startingEthPrice1e18\n    const ethToDeposit = ethers.utils.parseUnits('1.5')\n\n    beforeEach(async () => {\n      await dai.mint(depositor2.address, usdcAmount.toString())\n      await dai.connect(depositor2).approve(crabHelper.address, usdcAmount.toString())\n    })\n\n    it(\"Should fail if it minimum ETH is not swapped in ERC20 transfer\", async () => {\n      await expect(crabHelper.connect(depositor2).flashDepositERC20(ethToDeposit, usdcAmount, ethers.utils.parseEther('1'), 3000, poolFeePool2, dai.address)).to.be.revertedWith(\"Too little received\")\n    })\n\n    it(\"Should deposit USDC into strategy\", async () => {\n      const usdcBalanceBefore = await dai.balanceOf(depositor2.address)\n      const crabBalanceBefore = await crabStrategy.balanceOf(depositor2.address)\n\n      await expect(crabHelper.connect(depositor2).flashDepositERC20(ethToDeposit, usdcAmount, 0, 3000, poolFeePool2, dai.address)).to.emit(crabHelper, \"FlashDepositERC20\")\n\n      const usdcBalanceAfter = await dai.balanceOf(depositor2.address)\n      const crabBalanceAfter = await crabStrategy.balanceOf(depositor2.address)\n\n      expect(usdcBalanceBefore.sub(usdcAmount)).to.be.equal(usdcBalanceAfter)\n      expect(crabBalanceAfter.gt(crabBalanceBefore)).to.be.true\n    })\n  })\n\n  describe(\"Withdraw USDC from strategy in 1%\", async () => {\n    const usdcAmount = startingEthPrice1e18\n    const ethToDeposit = ethers.utils.parseUnits('1.5')\n    let crabBalance = BigNumber.from(0)\n\n    beforeEach(\"Deposit into strategy\", async () => {\n      await dai.mint(depositor2.address, usdcAmount.toString())\n      await dai.connect(depositor2).approve(crabHelper.address, usdcAmount.toString())\n      await crabHelper.connect(depositor2).flashDepositERC20(ethToDeposit, usdcAmount, 0, 3000, poolFeePool2, dai.address)\n      crabBalance = await crabStrategy.balanceOf(depositor2.address)\n    })\n\n    afterEach(\"Clean up deposit\", async () => {\n      const _crb = await crabStrategy.balanceOf(depositor2.address)\n      if (_crb.gt(0)) {\n        await crabStrategy.connect(depositor2).flashWithdraw(_crb, ethToDeposit.mul(102).div(100), poolFeePool2)\n      }\n    })\n\n    it(\"Should fail if it minimum USDC out is not swapped in ERC20 transfer\", async () => {\n      await crabStrategy.connect(depositor2).approve(crabHelper.address, crabBalance)\n      await expect(crabHelper.connect(depositor2).flashWithdrawERC20(crabBalance, ethToDeposit.mul(102).div(100), dai.address, usdcAmount.mul(2), 3000, poolFeePool2)).to.be.revertedWith(\"Too little received\")\n    })\n\n    it(\"Should withdraw USDC from strategy\", async () => {\n      const usdcBalanceBefore = await dai.balanceOf(depositor2.address)\n\n      const minUsdToGet = usdcAmount.div(2)\n      await expect(crabHelper.connect(depositor2).flashWithdrawERC20(crabBalance, ethToDeposit.mul(2), dai.address, minUsdToGet, 3000, poolFeePool2)).to.emit(crabHelper, \"FlashWithdrawERC20\")\n\n      const usdcBalanceAfter = await dai.balanceOf(depositor2.address)\n      const crabBalanceAfter = await crabStrategy.balanceOf(depositor2.address)\n\n      expect(usdcBalanceAfter.gte(usdcBalanceBefore.add(minUsdToGet))).to.be.true\n      expect(crabBalanceAfter).to.be.equal(\"0\")\n    })\n  })\n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/crabv2/crab-liquidation-dust.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport BigNumberJs from 'bignumber.js'\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategyV2, ISwapRouter, Timelock } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({ EXPONENTIAL_AT: 30 })\n\ndescribe(\"Crab V2 integration test: crab vault dust liquidation with excess collateral\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n  let poolFee: BigNumber;\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress;\n  let liquidator: SignerWithAddress;\n  let crabMigration: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategyV2\n  let ethDaiPool: Contract\n  let timelock: Timelock\n\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async () => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _depositor2, _liquidator, _crabMigration] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    depositor2 = _depositor2;\n    liquidator = _liquidator;\n    crabMigration = _crabMigration;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai,\n      positionManager,\n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    poolFee = await wSqueethPool.fee()\n\n    const TimelockContract = await ethers.getContractFactory(\"Timelock\");\n    timelock = (await TimelockContract.deploy(owner.address, 3 * 24 * 60 * 60)) as Timelock;\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, timelock.address, crabMigration.address, hedgeTimeThreshold, hedgePriceThreshold)) as CrabStrategyV2;\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async () => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      '1000000',\n      '2000000',\n      owner.address,\n      wSqueeth,\n      weth,\n      positionManager,\n      controller\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"Initialize strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('0.51')\n    const msgvalue = ethers.utils.parseUnits('0.51')\n    const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, true)\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n    const normFactor = await controller.normalizationFactor()\n    const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n    const feeRate = await controller.feeRate()\n    const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)\n    const squeethDelta = scaledStartingSqueethPrice1e18.mul(2);\n    const debtToMint = wdiv(ethToDeposit, (squeethDelta.add(ethFeePerWSqueeth)));\n    const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n\n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n\n    await crabStrategy.connect(crabMigration).initialize(debtToMint, ethToDeposit, 0, 0, strategyCap, { value: msgvalue });\n\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n\n    await crabStrategy.connect(crabMigration).transfer(depositor.address, ethToDeposit);\n    await wSqueeth.connect(crabMigration).transfer(depositor.address, debtToMint);\n    \n    const [operator, nftId, collateralAmount, debtAmount] = await crabStrategy.getVaultDetails()\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n    const lastHedgeTime = await crabStrategy.timeAtLastHedge()\n\n    expect(totalSupply.eq(ethToDeposit)).to.be.true\n    expect(depositorCrab.eq(ethToDeposit)).to.be.true\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString())).to.be.true\n    expect(isSimilar((depositorSqueethBalance.sub(depositorSqueethBalanceBefore)).toString(), (debtToMint).toString())).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n\n  })\n\n  describe(\"liquidate vault\", async () => {\n    before('push weth price higher to make crab vault liquidatable', async () => {\n      const poolWethBalance = await weth.balanceOf(ethDaiPool.address)\n\n      const maxDai = poolWethBalance.mul(startingEthPrice).mul(5)\n\n      const exactOutputParam = {\n        tokenIn: dai.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"15\"),\n        amountInMaximum: maxDai,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await dai.connect(owner).mint(owner.address, maxDai,)\n      await dai.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)\n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('push squeeth price higher', async () => {\n      // set squeeth price higher by buying 15% of squeeth in the pool\n      const poolSqueethBalance = await wSqueeth.balanceOf(wSqueethPool.address)\n\n      const maxWeth = poolSqueethBalance.mul(scaledStartingSqueethPrice1e18).mul(5).div(one)\n\n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"150000\"),\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(owner).deposit({ value: maxWeth })\n      await weth.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)\n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('prepare liquidator to liquidate strategy', async () => {\n      await provider.send(\"evm_increaseTime\", [600]) // increase time by 600 sec\n      await provider.send(\"evm_mine\", [])\n\n      const vaultId = await crabStrategy.vaultId();\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      const vaultBefore = await controller.vaults(vaultId)\n\n      const mintAmount = vaultBefore.shortAmount\n      const collateralRequired = mintAmount.mul(newEthPrice).mul(2).div(oracleScaleFactor).div(one).mul(2)\n\n      // mint squeeth to liquidate vault0!\n      await controller.connect(liquidator).mintWPowerPerpAmount(0, mintAmount, 0, { value: collateralRequired })\n    })\n\n    it(\"should liquidate crab vault using a full dust (0 collateral >0 debt remain)\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.false\n\n      const newSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n\n      const vaultBefore = await controller.vaults(vaultId)\n\n      // state before liquidation\n      const liquidatorSqueethBefore = await wSqueeth.balanceOf(liquidator.address)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount\n\n      await controller.connect(liquidator).liquidate(vaultId, wSqueethAmountToLiquidate);\n\n      const normFactor = await controller.normalizationFactor()\n      const collateralToGet = newSqueethPrice.mul(wSqueethAmountToLiquidate).div(one).mul(11).div(10)\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const liquidatorSqueethAfter = await wSqueeth.balanceOf(liquidator.address)\n\n      // expect(collateralToGet.eq(liquidatorBalanceAfter.sub(liquidatorBalanceBefore))).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(liquidatorSqueethBefore.sub(liquidatorSqueethAfter))).to.be.true\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.equal\n      expect(vaultAfter.collateralAmount.gt(BigNumber.from(0))).to.be.equal\n\n    })\n\n    it(\"should revert if user flash deposits post liquidation due to AS, because of amount specified of 0\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralBefore = vaultBefore.collateralAmount\n      const debtBefore = vaultBefore.shortAmount\n\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      const msgvalue = ethers.utils.parseUnits('15')\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n\n      expect(strategyCollateralAmountBefore.eq(collateralBefore)).to.be.true\n      expect(strategyDebtAmountBefore.eq(debtBefore)).to.be.true\n\n      await expect(crabStrategy.connect(depositor2).flashDeposit(ethToDeposit, poolFee, { value: msgvalue })).to.be.revertedWith(\"AS\")\n    })\n\n    it(\"should let user deposit post liquidation, with only ETH, and mint no squeeth for them\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralBefore = vaultBefore.collateralAmount\n      const debtBefore = vaultBefore.shortAmount\n      const msgvalue = ethers.utils.parseUnits('1')\n      const totalSupplyBefore = (await crabStrategy.totalSupply())\n\n      const expectedRatio = one.mul(msgvalue).div(collateralBefore.add(msgvalue))\n      const expectedCrabMint = expectedRatio.mul(totalSupplyBefore).div(one.sub(expectedRatio))\n\n      expect(totalSupplyBefore.gt(BigNumber.from(0))).to.be.true\n      expect(collateralBefore.gt(BigNumber.from(0))).to.be.true\n      expect(debtBefore.eq(BigNumber.from(0))).to.be.true\n\n      const userEthBalanceBefore = await provider.getBalance(depositor2.address)\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor2.address);\n      const userSqueethBalanceBefore = await wSqueeth.balanceOf(depositor2.address)\n\n      await crabStrategy.connect(depositor2).deposit({ value: msgvalue })\n\n      const userEthBalanceAfter = await provider.getBalance(depositor2.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor2.address);\n      const userSqueethBalanceAfter = await wSqueeth.balanceOf(depositor2.address)\n      const [strategyOperatorAfter, strategyNftIdAfter, strategyCollateralAmountAfter, strategyDebtAmountAfter] = await crabStrategy.getVaultDetails()\n      const totalSupplyAfter = (await crabStrategy.totalSupply())\n\n      // expect((userEthBalanceBefore.sub(userEthBalanceAfter)).eq(msgvalue)).to.be.true\n      expect(userSqueethBalanceBefore.eq(userSqueethBalanceAfter)).to.be.true\n      expect(isSimilar((userCrabBalanceAfter.sub(userCrabBalanceBefore)).toString(), (expectedCrabMint).toString())).to.be.true\n      expect(strategyDebtAmountAfter.eq(debtBefore)).to.be.true\n      expect(strategyCollateralAmountAfter.eq(collateralBefore.add(msgvalue))).to.be.true\n      expect(isSimilar((totalSupplyAfter.sub(totalSupplyBefore)).toString(), (expectedCrabMint).toString())).to.be.true\n    })\n\n    it(\"depositor should revert trying to flashWithdraw with AS due to amount of wSqueeth to buy being 0\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio, strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay, wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethToWithdraw.mul(10).div(10)\n\n      await expect(crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay, poolFee)).to.be.revertedWith(\"AS\")\n\n    })\n\n    it(\"depositor should be able to withdraw and get some ETH, without any wSqueeth\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n      const userEthBalanceBefore = await provider.getBalance(depositor.address)\n      const userSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const expectedWithdrawal = vaultBefore.collateralAmount.sub(ethers.utils.parseUnits(\"1\"))\n      const collateralBefore = vaultBefore.collateralAmount\n      const debtBefore = vaultBefore.shortAmount\n      const totalSupplyBefore = await crabStrategy.totalSupply()\n      const expectedShareWithdrawal = collateralBefore.mul(userCrabBalanceBefore).div(totalSupplyBefore)\n\n      expect(isSimilar(expectedWithdrawal.toString(), expectedShareWithdrawal.toString())).to.be.true\n\n      await crabStrategy.connect(depositor).withdraw(userCrabBalanceBefore)\n\n      const userEthBalanceAfter = await provider.getBalance(depositor.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor.address);\n      const userSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const [strategyOperatorAfter, strategyNftIdAfter, strategyCollateralAmountAfter, strategyDebtAmountAfter] = await crabStrategy.getVaultDetails()\n\n      const debtAfter = vaultBefore.shortAmount\n      const totalSupplyAfter = await crabStrategy.totalSupply()\n\n      // expect(isSimilar((userEthBalanceAfter.sub(userEthBalanceBefore)).toString(),(expectedShareWithdrawal).toString())).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(userSqueethBalanceAfter.eq(userSqueethBalanceBefore)).to.be.true\n      // expect(strategyCollateralAmountBefore.sub(strategyCollateralAmountAfter).eq(userEthBalanceAfter.sub(userEthBalanceBefore))).to.be.true\n      expect(debtAfter.eq(debtBefore)).to.be.true\n      expect(isSimilar((totalSupplyBefore.sub(totalSupplyAfter)).toString(), (userCrabBalanceBefore).toString())).to.be.true\n    })\n  })\n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/crabv2/crab-liquidation-flashswap.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport BigNumberJs from 'bignumber.js'\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategyV2, ISwapRouter, Timelock } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({ EXPONENTIAL_AT: 30 })\n\ndescribe(\"Crab V2 flashswap integration test: crab vault liquidation\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.mul(11).div(10).div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice * 1.1 / oracleScaleFactor.toNumber() // 0.3\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n  let poolFee: BigNumber\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress;\n  let crabMigration: SignerWithAddress;\n  let liquidator: SignerWithAddress;\n  let feeRecipient: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategyV2\n  let ethDaiPool: Contract\n  let timelock: Timelock;\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async () => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _depositor2, _liquidator, _feeRecipient, _crabMigration] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    depositor2 = _depositor2;\n    liquidator = _liquidator;\n    feeRecipient = _feeRecipient;\n    crabMigration = _crabMigration;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai,\n      positionManager,\n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    poolFee = await wSqueethPool.fee()\n\n    await controller.connect(owner).setFeeRecipient(feeRecipient.address);\n    await controller.connect(owner).setFeeRate(100)\n\n    const TimelockContract = await ethers.getContractFactory(\"Timelock\");\n    timelock = (await TimelockContract.deploy(owner.address, 3 * 24 * 60 * 60)) as Timelock;\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, timelock.address, crabMigration.address, hedgeTimeThreshold, hedgePriceThreshold)) as CrabStrategyV2;\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async () => {\n    await provider.send(\"evm_increaseTime\", [300])\n    await provider.send(\"evm_mine\", [])\n\n    // add liquidity\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      '1000000',\n      '2000000',\n      owner.address,\n      wSqueeth,\n      weth,\n      positionManager,\n      controller\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n  })\n\n  this.beforeAll(\"Initialize strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('20')\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n    const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n    const feeRate = await controller.feeRate()\n    const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n    const squeethDelta = scaledStartingSqueethPrice1e18.mul(2);\n    const debtToMint = wdiv(ethToDeposit, (squeethDelta.add(ethFeePerWSqueeth)));\n    const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n\n    await crabStrategy.connect(crabMigration).initialize(debtToMint, expectedEthDeposit, 0, 0, strategyCap, { value: ethToDeposit });\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n\n    await crabStrategy.connect(crabMigration).transfer(depositor.address, expectedEthDeposit);\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n    const debtAmount = strategyVault.shortAmount\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n\n    expect(isSimilar(totalSupply.toString(),(expectedEthDeposit).toString())).to.be.true\n    expect(isSimilar(depositorCrab.toString(), expectedEthDeposit.toString())).to.be.true\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString())).to.be.true\n    expect(depositorSqueethBalance.eq(depositorSqueethBalanceBefore)).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n  })\n\n  describe(\"liquidate vault\", async () => {\n    before('push weth price higher to make crab vault liquidatable', async () => {\n      // set weth price higher by buying 25% of weth in the pool\n      const poolWethBalance = await weth.balanceOf(ethDaiPool.address)\n\n      const maxDai = poolWethBalance.mul(startingEthPrice).mul(5)\n\n      const exactOutputParam = {\n        tokenIn: dai.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"20\"),\n        amountInMaximum: maxDai,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await dai.connect(owner).mint(owner.address, maxDai,)\n      await dai.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)\n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('push squeeth price higher', async () => {\n      // set squeeth price higher by buying 25% of squeeth in the pool\n      const poolSqueethBalance = await wSqueeth.balanceOf(wSqueethPool.address)\n\n      const maxWeth = poolSqueethBalance.mul(scaledStartingSqueethPrice1e18).mul(5).div(one)\n\n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"200000\"),\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(owner).deposit({ value: maxWeth })\n      await weth.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)\n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('prepare liquidator to liquidate strategy', async () => {\n      await provider.send(\"evm_increaseTime\", [600]) // increase time by 600 sec\n      await provider.send(\"evm_mine\", [])\n\n      const vaultId = await crabStrategy.vaultId();\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      const vaultBefore = await controller.vaults(vaultId)\n\n      const mintAmount = vaultBefore.shortAmount\n      const collateralRequired = mintAmount.mul(newEthPrice).mul(2).div(oracleScaleFactor).div(one).mul(2)\n\n      // mint squeeth to liquidate vault0!\n      await controller.connect(liquidator).mintPowerPerpAmount(0, mintAmount, 0, { value: collateralRequired })\n    })\n\n    it(\"should liquidate crab vault\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      const newSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const vaultBefore = await controller.vaults(vaultId)\n      const wSqueethVaultBefore = vaultBefore.shortAmount\n      const collateralBefore = vaultBefore.collateralAmount\n\n      const collatRatio = collateralBefore.mul(one).div(wSqueethVaultBefore.mul(normFactor).mul(newEthPrice).div(one).div(one).div(oracleScaleFactor))\n\n      expect(isVaultSafe).to.be.false\n\n      // state before liquidation\n      const liquidatorSqueethBefore = await wSqueeth.balanceOf(liquidator.address)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount.div(2)\n\n      await controller.connect(liquidator).liquidate(vaultId, wSqueethAmountToLiquidate);\n\n      const collateralToGet = newSqueethPrice.mul(wSqueethAmountToLiquidate).div(one).mul(11).div(10)\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const liquidatorSqueethAfter = await wSqueeth.balanceOf(liquidator.address)\n\n      expect(isSimilar((vaultBefore.shortAmount.div(2)).toString(), (vaultAfter.shortAmount).toString())).to.be.true\n      expect(vaultAfter.shortAmount.gt(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.gt(BigNumber.from(0))).to.be.true\n      // expect(collateralToGet.eq(liquidatorBalanceAfter.sub(liquidatorBalanceBefore))).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(liquidatorSqueethBefore.sub(liquidatorSqueethAfter))).to.be.true\n    })\n\n    it(\"should let user deposit post liquidation and update vault state and provide correct wSqueeth and crab tokens\", async () => {\n\n      //                               (userEthDeposit * strategyDebtBeforeDeposit) \n      //  wSqueethToMint =  ----------------------------------------------------------------------------------------\n      //                    (strategyCollateralBeforeDeposit + strategyDebtBeforeDeposit*squeethEthPrice*fee%)\n\n\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      const newSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const vaultBefore = await controller.vaults(vaultId)\n      const wSqueethVaultBefore = vaultBefore.shortAmount\n      const collateralBefore = vaultBefore.collateralAmount\n\n      const collatRatio = collateralBefore.mul(one).div(wSqueethVaultBefore.mul(normFactor).mul(newEthPrice).div(one).div(one).div(oracleScaleFactor))\n\n      const debtBefore = vaultBefore.shortAmount\n      const ratio = debtBefore.mul(one).div(collateralBefore)\n\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      const msgvalue = ethers.utils.parseUnits('15')\n      const totalSupplyBefore = (await crabStrategy.totalSupply())\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor2.address))\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await crabStrategy.connect(depositor2).flashDeposit(ethToDeposit, poolFee, { value: msgvalue })\n\n      const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n      const debtToMint = ethToDeposit.mul(debtBefore).div(collateralBefore.add(debtBefore.mul(ethFeePerWSqueeth).div(one)))\n      const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n      const depositorShare = one.mul(expectedEthDeposit).div(collateralBefore.add(expectedEthDeposit))\n      const crabMintAmount = totalSupplyBefore.mul(depositorShare).div(one.sub(depositorShare))\n\n      const strategyVaultAfter = await controller.vaults(vaultId)\n      const strategyDebtAmountAfter = strategyVaultAfter.shortAmount\n      const strategyCollateralAmountAfter = strategyVaultAfter.collateralAmount\n      const depositorCrabAfter = (await crabStrategy.balanceOf(depositor2.address))\n      const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor2.address)\n      const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n      const totalSupplyAfter = (await crabStrategy.totalSupply())\n      // const depositorEthBalanceAfter = await provider.getBalance(depositor2.address)\n\n      expect(isSimilar((strategyCollateralAmountAfter.sub(collateralBefore)).toString(), (expectedEthDeposit).toString())).to.be.true\n      expect(isSimilar(strategyDebtAmountAfter.toString(), (debtBefore.add(debtToMint)).toString())).to.be.true\n      expect(isSimilar((strategyDebtAmountAfter.sub(debtBefore)).toString(), (debtToMint).toString())).to.be.true\n      expect(isSimilar((totalSupplyAfter.sub(totalSupplyBefore)).toString(), (crabMintAmount).toString())).to.be.true\n      expect((depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)).eq(BigNumber.from(0))).to.be.true\n      expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n      expect(isSimilar((depositorCrabAfter.sub(depositorCrabBefore)).toString(), (crabMintAmount).toString())).to.be.true\n    })\n\n    it(\"depositor should withdraw correct amount of ETH collateral\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtAmountBefore = strategyVault.shortAmount\n      const strategyCollateralAmountBefore = strategyVault.collateralAmount\n      const userEthBalanceBefore = await provider.getBalance(depositor.address)\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio, strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay, wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethCostOfDebtToRepay.mul(101).div(100)\n\n      await crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay, poolFee)\n\n      const userEthBalanceAfter = await provider.getBalance(depositor.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor.address);\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralAfter = vaultBefore.collateralAmount\n      const debtAfter = vaultBefore.shortAmount\n\n      expect(isSimilar(userEthBalanceAfter.sub(userEthBalanceBefore).toString(), ethToWithdraw.toString(), 2)).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(collateralAfter.eq(strategyCollateralAmountBefore.sub(userCollateral))).to.be.true\n      // use isSimilar to prevent last digits rounding error\n      expect(isSimilar(strategyDebtAmountBefore.sub(debtAfter).toString(), debtToRepay.toString(), 10)).to.be.true\n    })\n\n    it(\"depositor2 should withdraw correct amount of ETH collateral\", async () => {\n\n\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor2.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtAmountBefore = strategyVault.shortAmount\n      const strategyCollateralAmountBefore = strategyVault.collateralAmount\n      const userEthBalanceBefore = await provider.getBalance(depositor2.address)\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio, strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay, wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethCostOfDebtToRepay.mul(11).div(10)\n\n      await crabStrategy.connect(depositor2).flashWithdraw(userCrabBalanceBefore, maxEthToPay, poolFee)\n\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const userEthBalanceAfter = await provider.getBalance(depositor2.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor2.address);\n      const strategyDebtAmountAfter = strategyVaultAfter.shortAmount\n      const strategyCollateralAmountAfter = strategyVaultAfter.collateralAmount\n\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralAfter = vaultBefore.collateralAmount\n      const debtAfter = vaultBefore.shortAmount\n\n      expect(isSimilar(userEthBalanceAfter.sub(userEthBalanceBefore).toString(), ethToWithdraw.toString(), 2)).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(collateralAfter.eq(strategyCollateralAmountBefore.sub(userCollateral))).to.be.true\n      expect(strategyDebtAmountBefore.sub(debtAfter).eq(debtToRepay)).to.be.true\n      expect(strategyDebtAmountAfter.eq(BigNumber.from(0))).to.be.true\n      expect(strategyCollateralAmountAfter.eq(BigNumber.from(0))).to.be.true\n    })\n  })\n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/crabv2/crab-liquidation-full.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport BigNumberJs from 'bignumber.js'\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategyV2, ISwapRouter, Timelock } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({ EXPONENTIAL_AT: 30 })\n\ndescribe(\"Crab V2 integration test: crab vault full liquidation and shutdown of contracts\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n  let poolFee: BigNumber\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress;\n  let liquidator: SignerWithAddress;\n  let crabMigration: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategyV2\n  let ethDaiPool: Contract\n  let timelock: Timelock\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async () => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _depositor2, _liquidator, _crabMigration] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    depositor2 = _depositor2;\n    liquidator = _liquidator;\n    crabMigration = _crabMigration; \n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai,\n      positionManager,\n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    poolFee = await wSqueethPool.fee()\n\n    const TimelockContract = await ethers.getContractFactory(\"Timelock\");\n    timelock = (await TimelockContract.deploy(owner.address, 3 * 24 * 60 * 60)) as Timelock;\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, timelock.address, crabMigration.address, hedgeTimeThreshold, hedgePriceThreshold)) as CrabStrategyV2;\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async () => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      '1000000',\n      '2000000',\n      owner.address,\n      wSqueeth,\n      weth,\n      positionManager,\n      controller\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"Initialize strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('20')\n    const msgvalue = ethers.utils.parseUnits('20')\n    const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, true)\n\n    const squeethDelta = ethPrice.mul(2).div(1e4);\n    const debtToMint = wdiv(ethToDeposit, squeethDelta);\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n\n    await crabStrategy.connect(crabMigration).initialize(debtToMint, ethToDeposit, 0, 0, strategyCap, { value: msgvalue })\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n\n\n    await crabStrategy.connect(crabMigration).transfer(depositor.address, ethToDeposit);\n    await wSqueeth.connect(crabMigration).transfer(depositor.address, debtToMint);\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, debtAmount] = await crabStrategy.getVaultDetails()\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n\n    expect(totalSupply.eq(ethToDeposit)).to.be.true\n    expect(depositorCrab.eq(ethToDeposit)).to.be.true\n    // these had to be adjusted - it seems the eth price is a bit different than expected maybe? but only in coverage???\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString(), 3)).to.be.true\n    expect(isSimilar((depositorSqueethBalance.sub(depositorSqueethBalanceBefore)).toString(), (debtToMint).toString(), 3)).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n\n  })\n\n  describe(\"liquidate vault\", async () => {\n    before('push weth price higher to make crab vault liquidatable', async () => {\n      const poolWethBalance = await weth.balanceOf(ethDaiPool.address)\n\n      const maxDai = poolWethBalance.mul(startingEthPrice).mul(20)\n\n      const exactOutputParam = {\n        tokenIn: dai.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"50\"),\n        amountInMaximum: maxDai,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await dai.connect(owner).mint(owner.address, maxDai,)\n      await dai.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)\n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('push squeeth price higher', async () => {\n      // set squeeth price higher by buying 50% of squeeth in the pool\n      const poolSqueethBalance = await wSqueeth.balanceOf(wSqueethPool.address)\n\n      const maxWeth = poolSqueethBalance.mul(scaledStartingSqueethPrice1e18).mul(20).div(one)\n\n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"500000\"),\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(owner).deposit({ value: maxWeth })\n      await weth.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)\n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('prepare liquidator to liquidate strategy', async () => {\n      await provider.send(\"evm_increaseTime\", [600]) // increase time by 600 sec\n      await provider.send(\"evm_mine\", [])\n\n      const vaultId = await crabStrategy.vaultId();\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      const vaultBefore = await controller.vaults(vaultId)\n\n      const mintAmount = vaultBefore.shortAmount\n      const collateralRequired = mintAmount.mul(newEthPrice).mul(2).div(oracleScaleFactor).div(one).mul(2)\n\n      // mint squeeth to liquidate vault0!\n      await controller.connect(liquidator).mintWPowerPerpAmount(0, mintAmount, 0, { value: collateralRequired })\n    })\n\n    it(\"should liquidate crab vault using a full insolvent liquidation (0 collateral 0 debt remain)\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.false\n\n      const vaultBefore = await controller.vaults(vaultId)\n\n      // state before liquidation\n      const liquidatorSqueethBefore = await wSqueeth.balanceOf(liquidator.address)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount\n\n      await controller.connect(liquidator).liquidate(vaultId, wSqueethAmountToLiquidate);\n\n      const collateralToGet = vaultBefore.collateralAmount\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const liquidatorSqueethAfter = await wSqueeth.balanceOf(liquidator.address)\n\n      // expect(collateralToGet.eq(liquidatorBalanceAfter.sub(liquidatorBalanceBefore))).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(liquidatorSqueethBefore.sub(liquidatorSqueethAfter))).to.be.true\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.equal\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.equal\n\n    })\n\n    it(\"should NOT let user flash deposit post liquidation\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralBefore = vaultBefore.collateralAmount\n      const debtBefore = vaultBefore.shortAmount\n\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      // const ethToBorrow = ethers.utils.parseUnits('10')\n      const msgvalue = ethers.utils.parseUnits('15')\n      const totalSupplyBefore = (await crabStrategy.totalSupply())\n\n      expect(totalSupplyBefore.gt(BigNumber.from(0))).to.be.true\n      expect(collateralBefore.eq(BigNumber.from(0))).to.be.true\n      expect(debtBefore.eq(BigNumber.from(0))).to.be.true\n\n      await expect(crabStrategy.connect(depositor2).flashDeposit(ethToDeposit, poolFee, { value: msgvalue })).to.be.revertedWith(\"C26\")\n    })\n\n    it(\"should NOT let user deposit post liquidation\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralBefore = vaultBefore.collateralAmount\n      const debtBefore = vaultBefore.shortAmount\n\n      const msgvalue = ethers.utils.parseUnits('15')\n      const totalSupplyBefore = (await crabStrategy.totalSupply())\n\n      expect(totalSupplyBefore.gt(BigNumber.from(0))).to.be.true\n      expect(collateralBefore.eq(BigNumber.from(0))).to.be.true\n      expect(debtBefore.eq(BigNumber.from(0))).to.be.true\n\n      await expect(crabStrategy.connect(depositor2).deposit({ value: msgvalue })).to.be.revertedWith(\"C26\")\n    })\n\n    it(\"depositor should revert trying to flashWithdraw with AS due to amount of wSqueeth to buy being 0\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio, strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay, wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethCostOfDebtToRepay.mul(11).div(10)\n\n      await expect(crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay, poolFee)).to.be.revertedWith(\"AS\")\n\n    })\n\n    it(\"depositor withdraw and get 0\", async () => {\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n      const userEthBalanceBefore = await provider.getBalance(depositor.address)\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const userSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await crabStrategy.connect(depositor).withdraw(userCrabBalanceBefore)\n\n      const userEthBalanceAfter = await provider.getBalance(depositor.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor.address);\n      const userSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralAfter = vaultBefore.collateralAmount\n      const debtAfter = vaultBefore.shortAmount\n      const totalSupplyAfter = await crabStrategy.totalSupply()\n\n      // expect(userEthBalanceAfter.sub(userEthBalanceBefore).eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(userSqueethBalanceAfter.sub(userSqueethBalanceBefore).eq(BigNumber.from(0))).to.be.true\n      expect(collateralAfter.eq(strategyCollateralAmountBefore.sub(userCollateral))).to.be.true\n      expect(collateralAfter.eq(BigNumber.from(0))).to.be.true\n      expect(debtAfter.eq(BigNumber.from(0))).to.be.true\n      expect(totalSupplyAfter.eq(BigNumber.from(0))).to.be.true\n    })\n  })\n})\n"
  },
  {
    "path": "packages/hardhat/test/integration-tests/crabv2/crab-shutdown.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers, Signer } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport BigNumberJs from 'bignumber.js'\nimport { randomBytes } from \"ethers/lib/utils\";\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategyV2, ISwapRouter, Timelock } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({ EXPONENTIAL_AT: 30 })\n\ndescribe(\"Crab V2 integration test: Shutdown of Squeeth Power Perp contracts\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n  let poolFee: BigNumber\n  \n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress\n  let random: SignerWithAddress;\n  let crabMigration: SignerWithAddress; \n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategyV2\n  let ethDaiPool: Contract\n  let shutdownPrice: BigNumber\n  let timelock: Timelock\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async () => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _depositor2, _random, _crabMigration] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    depositor2 = _depositor2;\n    random = _random;\n    crabMigration = _crabMigration;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai,\n      positionManager,\n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    poolFee = await wSqueethPool.fee()\n\n    const TimelockContract = await ethers.getContractFactory(\"Timelock\");\n    timelock = (await TimelockContract.deploy(owner.address, 3 * 24 * 60 * 60)) as Timelock;\n\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, timelock.address, crabMigration.address, hedgeTimeThreshold, hedgePriceThreshold)) as CrabStrategyV2;\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async () => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n    await provider.send(\"evm_increaseTime\", [300])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      '1000000',\n      '2000000',\n      owner.address,\n      wSqueeth,\n      weth,\n      positionManager,\n      controller\n    )\n    await provider.send(\"evm_increaseTime\", [300])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"Initialize strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('20')\n    const msgvalue = ethers.utils.parseUnits('20')\n    const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, true)\n\n    const squeethDelta = ethPrice.mul(2).div(1e4);\n    const debtToMint = wdiv(ethToDeposit, squeethDelta);\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n\n    await crabStrategy.connect(crabMigration).initialize(debtToMint, ethToDeposit, 0, 0, strategyCap, { value: msgvalue })\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n\n    await crabStrategy.connect(crabMigration).transfer(depositor.address, ethToDeposit);\n    await wSqueeth.connect(crabMigration).transfer(depositor.address, debtToMint);\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, debtAmount] = await crabStrategy.getVaultDetails()\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n\n\n    expect(depositorCrab.eq(ethToDeposit)).to.be.true\n    // these had to be adjusted - it seems the eth price is a bit different than expected maybe? but only in coverage???\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString(), 3)).to.be.true\n    expect(isSimilar((depositorSqueethBalance.sub(depositorSqueethBalanceBefore)).toString(), (debtToMint).toString(), 3)).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n\n  })\n\n  describe(\"Try to redeemShutdown from contracts before shutdown\", async () => {\n\n    it(\"should revert if calling redeemShutdown before contracts are shutdown\", async () => {\n      await expect(crabStrategy.connect(random).redeemShortShutdown()).to.be.revertedWith(\"C3\")\n    })\n  })\n\n  describe(\"Shutdown core contracts and check results\", async () => {\n    before('push eth price higher', async () => {\n      const poolWethBalance = await weth.balanceOf(ethDaiPool.address)\n\n      const maxDai = poolWethBalance.mul(startingEthPrice).mul(20)\n\n      const exactOutputParam = {\n        tokenIn: dai.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"5\"),\n        amountInMaximum: maxDai,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await dai.connect(owner).mint(owner.address, maxDai,)\n      await dai.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)\n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('push squeeth price higher', async () => {\n      const poolSqueethBalance = await wSqueeth.balanceOf(wSqueethPool.address)\n\n      const maxWeth = poolSqueethBalance.mul(scaledStartingSqueethPrice1e18).mul(20).div(one)\n\n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"50000\"),\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(owner).deposit({ value: maxWeth })\n      await weth.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)\n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n      await provider.send(\"evm_increaseTime\", [600]) // increase time by 600 sec\n      await provider.send(\"evm_mine\", [])\n\n    })\n\n    it(\"should NOT let user withdrawShutdown shutdown model, pre redeemShortShutdown\", async () => {\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      await expect(crabStrategy.connect(depositor).withdrawShutdown(userCrabBalanceBefore)).to.be.revertedWith(\"C12\")\n    })\n\n    it('shutdown contracts', async () => {\n      await controller.connect(owner).shutDown()\n      const isShutdown = await controller.isShutDown()\n      expect(isShutdown).to.be.true\n\n    })\n\n    it(\"should NOT let user withdrawShutdown post shutdown, pre redeemShortShutdown\", async () => {\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      await expect(crabStrategy.connect(depositor).withdrawShutdown(userCrabBalanceBefore)).to.be.revertedWith(\"C13\")\n    })\n\n    it(\"anyone should be able to call redeemShortShutdown\", async () => {\n      shutdownPrice = await controller.indexForSettlement()\n\n      const vaultId = await crabStrategy.vaultId();\n\n      const vaultBefore = await controller.vaults(vaultId)\n\n      // state before liquidation\n      const crabSqueethBalanceBefore = await wSqueeth.balanceOf(crabStrategy.address)\n      const crabEthBalanceBefore = await provider.getBalance(crabStrategy.address)\n      const crabDebtBefore = vaultBefore.shortAmount\n      const crabCollateralBefore = vaultBefore.collateralAmount\n\n      const normFactor = await controller.normalizationFactor()\n      await crabStrategy.connect(random).redeemShortShutdown()\n\n      const vaultAfter = await controller.vaults(vaultId)\n\n      const debtValueInEthBefore = crabDebtBefore.mul(normFactor).mul(shutdownPrice).div(one).div(one)\n      const expectedEthWithdrawn = crabCollateralBefore.sub(debtValueInEthBefore)\n\n      const crabSqueethBalanceAfter = await wSqueeth.balanceOf(crabStrategy.address)\n      const crabEthBalanceAfter = await provider.getBalance(crabStrategy.address)\n      const crabDebtAfter = vaultAfter.shortAmount\n      const crabCollateralAfter = vaultAfter.collateralAmount\n\n      expect(expectedEthWithdrawn.eq(crabEthBalanceAfter.sub(crabEthBalanceBefore))).to.be.true\n      expect(vaultAfter.shortAmount.isZero()).to.be.true\n      expect(vaultAfter.collateralAmount.isZero()).to.be.true\n\n    })\n\n    it(\"should NOT let user flash deposit post shutdown\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralBefore = vaultBefore.collateralAmount\n      const debtBefore = vaultBefore.shortAmount\n\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      // const ethToBorrow = ethers.utils.parseUnits('10')\n      const msgvalue = ethers.utils.parseUnits('15')\n      const totalSupplyBefore = (await crabStrategy.totalSupply())\n\n      expect(totalSupplyBefore.gt(BigNumber.from(0))).to.be.true\n      expect(collateralBefore.eq(BigNumber.from(0))).to.be.true\n      expect(debtBefore.eq(BigNumber.from(0))).to.be.true\n\n      await expect(crabStrategy.connect(depositor2).flashDeposit(ethToDeposit, poolFee, { value: msgvalue })).to.be.revertedWith(\"C26\")\n    })\n\n    it(\"should NOT let user deposit post shutdown\", async () => {\n      const msgvalue = ethers.utils.parseUnits('15')\n\n      await expect(crabStrategy.connect(depositor2).deposit({ value: msgvalue })).to.be.revertedWith(\"C26\")\n    })\n\n    it(\"depositor should revert trying to flashWithdraw with AS due to amount of wSqueeth to buy being 0\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio, strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay, wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethCostOfDebtToRepay.mul(11).div(10)\n\n      await expect(crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay, poolFee)).to.be.revertedWith(\"AS\")\n\n    })\n\n    it(\"depositor should revert trying to withdraw post shutdown\", async () => {\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n\n      await expect(crabStrategy.connect(depositor).withdraw(userCrabBalanceBefore)).to.be.revertedWith(\"C0\")\n\n    })\n\n    it(\"depositor withdraw when calling withdrawShutdown and get correct proceeds\", async () => {\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const strategyCollateralAmountBefore = await provider.getBalance(crabStrategy.address)\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyVaultCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n\n      const userEthBalanceBefore = await provider.getBalance(depositor.address)\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const userSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await crabStrategy.connect(depositor).withdrawShutdown(userCrabBalanceBefore)\n\n      const userEthBalanceAfter = await provider.getBalance(depositor.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor.address);\n      const userSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const vaultCollateralAfter = vaultAfter.collateralAmount\n      const vaultDebtAfter = vaultAfter.shortAmount\n      const totalSupplyAfter = await crabStrategy.totalSupply()\n      const strategyCollateralAmountAfter = await provider.getBalance(crabStrategy.address)\n\n\n      expect(strategyVaultCollateralAmountBefore.eq(BigNumber.from(0))).to.be.true\n      expect(strategyDebtAmountBefore.eq(BigNumber.from(0))).to.be.true\n      // expect(userEthBalanceAfter.sub(userEthBalanceBefore).eq(userCollateral)).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(userSqueethBalanceAfter.sub(userSqueethBalanceBefore).eq(BigNumber.from(0))).to.be.true\n      expect(vaultCollateralAfter.eq(BigNumber.from(0))).to.be.true\n      expect(vaultDebtAfter.eq(BigNumber.from(0))).to.be.true\n      expect(strategyCollateralAmountBefore.sub(strategyCollateralAmountAfter).eq(userCollateral)).to.be.true\n      expect(crabTotalSupply.sub(totalSupplyAfter).eq(userCrabBalanceBefore)).to.be.true\n    })\n  })\n})\n"
  },
  {
    "path": "packages/hardhat/test/integration-tests/crabv2/crab-timelock.ts",
    "content": "import { ethers } from \"hardhat\";\nimport { expect } from \"chai\";\nimport { Contract, providers } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport BigNumberJs from \"bignumber.js\";\nimport {\n    WETH9,\n    MockErc20,\n    Controller,\n    Oracle,\n    WPowerPerp,\n    CrabStrategyV2,\n    Timelock,\n    StrategyBase,\n} from \"../../../typechain\";\nimport {\n    deployUniswapV3,\n    deploySqueethCoreContracts,\n    deployWETHAndDai,\n} from \"../../setup\";\nimport { oracleScaleFactor } from \"../../utils\";\n\nBigNumberJs.set({ EXPONENTIAL_AT: 30 });\n\ndescribe(\"Crab v2 Integration test: Timelock\", function () {\n    const startingEthPrice = 3000;\n    const scaledStartingSqueethPrice = (startingEthPrice * 1.1) / oracleScaleFactor.toNumber(); // 0.3\n\n    const hedgeTimeThreshold = 86400; // 24h\n    const hedgePriceThreshold = ethers.utils.parseUnits(\"0.01\");\n    const abi = new ethers.utils.AbiCoder();\n    const signature = \"transferVault(address)\";\n    const twoDays = 2 * 24 * 60 * 60;\n\n    let provider: providers.JsonRpcProvider;\n    let owner: SignerWithAddress;\n    let depositor: SignerWithAddress;\n    let depositor2: SignerWithAddress;\n    let depositor3: SignerWithAddress;\n    let crabMigration: SignerWithAddress;\n    let liquidator: SignerWithAddress;\n    let feeRecipient: SignerWithAddress;\n    let dai: MockErc20;\n    let weth: WETH9;\n    let positionManager: Contract;\n    let uniswapFactory: Contract;\n    let swapRouter: Contract;\n    let oracle: Oracle;\n    let controller: Controller;\n    let wSqueethPool: Contract;\n    let wSqueeth: WPowerPerp;\n    let crabStrategy: CrabStrategyV2;\n    let ethDaiPool: Contract;\n    let timelock: Timelock;\n\n    this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async () => {\n        const accounts = await ethers.getSigners();\n        const [_owner, _depositor, _depositor2, _liquidator, _feeRecipient, _depositor3, _crabMigration] = accounts;\n        owner = _owner;\n        depositor = _depositor;\n        depositor2 = _depositor2;\n        liquidator = _liquidator;\n        feeRecipient = _feeRecipient;\n        depositor3 = _depositor3;\n        crabMigration = _crabMigration;\n        provider = ethers.provider;\n\n        const { dai: daiToken, weth: wethToken } = await deployWETHAndDai();\n\n        dai = daiToken;\n        weth = wethToken;\n\n        const uniDeployments = await deployUniswapV3(weth);\n        positionManager = uniDeployments.positionManager;\n        uniswapFactory = uniDeployments.uniswapFactory;\n        swapRouter = uniDeployments.swapRouter;\n\n        // this will not deploy a new pool, only reuse old onces\n        const squeethDeployments = await deploySqueethCoreContracts(\n            weth,\n            dai,\n            positionManager,\n            uniswapFactory,\n            scaledStartingSqueethPrice,\n            startingEthPrice\n        );\n        controller = squeethDeployments.controller;\n        wSqueeth = squeethDeployments.wsqueeth;\n        oracle = squeethDeployments.oracle;\n        // shortSqueeth = squeethDeployments.shortSqueeth\n        wSqueethPool = squeethDeployments.wsqueethEthPool;\n        ethDaiPool = squeethDeployments.ethDaiPool;\n\n        await controller.connect(owner).setFeeRecipient(feeRecipient.address);\n        await controller.connect(owner).setFeeRate(100);\n\n        const TimelockContract = await ethers.getContractFactory(\"Timelock\");\n        timelock = (await TimelockContract.deploy(owner.address, twoDays)) as Timelock;\n\n        const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n        crabStrategy = (await CrabStrategyContract.deploy(\n            controller.address,\n            oracle.address,\n            weth.address,\n            uniswapFactory.address,\n            wSqueethPool.address,\n            timelock.address,\n            crabMigration.address,\n            hedgeTimeThreshold,\n            hedgePriceThreshold\n        )) as CrabStrategyV2;\n    });\n\n    this.beforeAll(\"Seed pool liquidity\", async () => {\n        await provider.send(\"evm_increaseTime\", [1500]);\n        await provider.send(\"evm_mine\", []);\n    });\n    before(\"Initialize strategy\", async () => {\n        const strategyCap = ethers.utils.parseUnits(\"1000\");\n\n        await crabStrategy.connect(crabMigration).initialize(ethers.utils.parseUnits(\"0.2\"), ethers.utils.parseUnits(\"0.2\"), 0, 0, strategyCap, { value: ethers.utils.parseUnits(\"1\") });\n        const strategyCapInContract = await crabStrategy.strategyCap();\n        expect(strategyCapInContract.eq(strategyCap)).to.be.true;\n\n    });\n\n    describe(\"Transfer vault with timelock\", async () => {\n        let txHash = \"\";\n        let eta = 0;\n        let currentBlockNumber = 0;\n        let currentBlockTimestamp = 0;\n        let data = \"\";\n\n        this.beforeAll(async () => {\n            currentBlockNumber = await provider.getBlockNumber();\n            const currentBlock = await provider.getBlock(currentBlockNumber);\n            eta = currentBlock.timestamp + twoDays + 300;\n            currentBlockTimestamp = currentBlock.timestamp;\n\n            data = abi.encode([\"address\"], [depositor2.address]);\n\n            txHash = ethers.utils.keccak256(\n                abi.encode(\n                    [\"address\", \"uint256\", \"string\", \"bytes\", \"uint256\"],\n                    [crabStrategy.address, \"0\", signature, data, eta]\n                )\n            );\n            await timelock.connect(owner).queueTransaction(crabStrategy.address, 0, signature, data, eta);\n        });\n\n        it(\"Should transfer vault\", async () => {\n            await provider.send(\"evm_setNextBlockTimestamp\", [eta + 100]);\n\n            expect(\n                await timelock.connect(owner).executeTransaction(crabStrategy.address, 0, signature, data, eta)\n            ).to.emit(crabStrategy.address, \"VaultTransferred\");\n            expect((await crabStrategy.strategyCap()).eq(0)).to.be.true;\n        });\n\n        it(\"Should not allow user to deposit post vault transfer\", async () => {\n            await expect(\n                crabStrategy.connect(depositor2).deposit({ value: ethers.utils.parseUnits(\"1\") })\n            ).to.be.revertedWith(\"C16\");\n        });\n\n        it(\"Should not allow user to withdraw post vault transfer\", async () => {\n            const depositorCrabBefore = await crabStrategy.balanceOf(depositor3.address);\n            const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor3.address);\n\n            await wSqueeth.connect(depositor3).approve(crabStrategy.address, depositorSqueethBalanceBefore);\n            await expect(crabStrategy.connect(depositor).withdraw(depositorCrabBefore)).to.be.revertedWith(\"C20\");\n        });\n    });\n});\n"
  },
  {
    "path": "packages/hardhat/test/integration-tests/crabv2/strategy-flow.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport BigNumberJs from 'bignumber.js'\n\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategyV2, Timelock } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity, createUniPool } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({ EXPONENTIAL_AT: 30 })\n\ndescribe(\"Crab V2 integration test: flash deposit - deposit - withdraw\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n  let poolFee: BigNumber\n  let poolFeePool2: BigNumber\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress;\n  let crabMigration: SignerWithAddress; \n  let feeRecipient: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueethPool2: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategyV2\n  let ethDaiPool: Contract\n  let timelock: Timelock\n\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async () => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _depositor2, _feeRecipient, _crabMigration] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    depositor2 = _depositor2;\n    crabMigration = _crabMigration;\n    feeRecipient = _feeRecipient\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai,\n      positionManager,\n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    wSqueethPool2 = await createUniPool(scaledStartingSqueethPrice, weth, wSqueeth, positionManager, uniswapFactory, 10000) as Contract\n    await wSqueethPool2.increaseObservationCardinalityNext(500) \n  \n    poolFee = await wSqueethPool.fee()\n    poolFeePool2 = await wSqueethPool2.fee()\n\n    await controller.connect(owner).setFeeRecipient(feeRecipient.address);\n    await controller.connect(owner).setFeeRate(100)\n\n    const TimelockContract = await ethers.getContractFactory(\"Timelock\");\n    timelock = (await TimelockContract.deploy(owner.address, 3 * 24 * 60 * 60)) as Timelock;\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, timelock.address, crabMigration.address, hedgeTimeThreshold, hedgePriceThreshold)) as CrabStrategyV2;\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async () => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n    \n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      '1000000',\n      '2000000',\n      owner.address,\n      wSqueeth,\n      weth,\n      positionManager,\n      controller,\n      10000\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      '1000000',\n      '2000000',\n      owner.address,\n      wSqueeth,\n      weth,\n      positionManager,\n      controller\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"initialize contract\", async () => { \n    const strategyCap = ethers.utils.parseUnits(\"20\")\n\n    const ethToDeposit = ethers.utils.parseUnits('20')\n\n    const normFactor = await controller.normalizationFactor()\n    const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n    const feeRate = await controller.feeRate()\n    const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)\n    const squeethDelta = scaledStartingSqueethPrice1e18.mul(2);\n    const debtToMint = wdiv(ethToDeposit, (squeethDelta.add(ethFeePerWSqueeth)));\n    const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n\n    await crabStrategy.connect(crabMigration).initialize(debtToMint, expectedEthDeposit, 0, 0, strategyCap, { value: ethToDeposit });\n  })\n\n  describe(\"deposit above strategy cap\", async () => {\n    it(\"should revert if depositing an amount that puts the strategy above the cap\", async () => {\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      const msgvalue = ethers.utils.parseUnits('10')\n\n      await expect(\n        crabStrategy.connect(depositor).flashDeposit(ethToDeposit, poolFee, { value: msgvalue })\n      ).to.be.revertedWith(\"C16\");\n    })\n  })\n\n  describe(\"flash deposit - deposit - withdraw - flash withdraw\", async () => {\n    it(\"should let the owner set the cap\", async () => {\n      const strategyCap = ethers.utils.parseUnits(\"1000\")\n      await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n      const strategyCapInContract = await crabStrategy.strategyCap()\n      expect(strategyCapInContract.eq(strategyCap)).to.be.true\n    })\n\n    it(\"should revert flash depositing if not enough ETH\", async () => {\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      const msgvalue = ethers.utils.parseUnits('10')\n\n      await expect(\n        crabStrategy.connect(depositor).flashDeposit(ethToDeposit, poolFee, { value: msgvalue })\n      ).to.be.revertedWith(\"function call failed to execute\");\n    })\n\n    it(\"should flash deposit correct amount and mint correct shares amount in 0.3% pool\", async () => {\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      const msgvalue = ethers.utils.parseUnits('10.1')\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await crabStrategy.connect(depositor).flashDeposit(ethToDeposit, poolFee,{ value: msgvalue })\n\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)\n      const squeethDelta = scaledStartingSqueethPrice1e18.mul(2);\n      const debtToMint = wdiv(ethToDeposit, (squeethDelta.add(ethFeePerWSqueeth)));\n      const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n\n      const totalSupply = (await crabStrategy.totalSupply())\n      const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const debtAmount = strategyVault.shortAmount\n      const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n      const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n      const collateralAmount = await strategyVault.collateralAmount\n\n      expect(isSimilar(totalSupply.toString(), (expectedEthDeposit.mul(2)).toString())).to.be.true\n      expect(isSimilar(depositorCrab.toString(), (expectedEthDeposit).toString())).to.be.true\n      expect(isSimilar(debtAmount.toString(), debtToMint.mul(2).toString())).to.be.true\n      expect(depositorSqueethBalance.eq(depositorSqueethBalanceBefore)).to.be.true\n      expect(strategyContractSqueeth.eq(0)).to.be.true\n    })\n\n    it(\"should deposit and mint correct LP and return the correct amount of wSqueeth debt per crab strategy token\", async () => {\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const collateralBefore = strategyVault.collateralAmount\n      const debtBefore = strategyVault.shortAmount\n      const totalSupplyBefore = await crabStrategy.totalSupply()\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor.address))\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      const ethToDeposit = BigNumber.from(20).mul(one)\n\n      await crabStrategy.connect(depositor).deposit({ value: ethToDeposit });\n\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)\n      const debtToMint = ethToDeposit.mul(debtBefore).div(collateralBefore.add(debtBefore.mul(ethFeePerWSqueeth).div(one)))\n      const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n      const depositorShare = one.mul(expectedEthDeposit).div(collateralBefore.add(expectedEthDeposit))\n      const crabMintAmount = totalSupplyBefore.mul(depositorShare).div(one.sub(depositorShare))\n\n      const expectedMintedWsqueeth = wmul(debtToMint, normFactor)\n      const totalCrabAfter = (await crabStrategy.totalSupply())\n      const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const debtAmount = strategyVaultAfter.shortAmount\n      const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n      const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n      const depositorWSqueethDebt = await crabStrategy.getWsqueethFromCrabAmount(depositorCrab)\n\n      expect(isSimilar(totalCrabAfter.sub(totalSupplyBefore).toString(), crabMintAmount.toString())).to.be.true\n      expect(isSimilar((depositorCrab.sub(depositorCrabBefore)).toString(), (crabMintAmount).toString())).to.be.true\n      expect(isSimilar(debtAmount.sub(debtBefore).toString(), (debtToMint).toString())).to.be.true\n      expect(isSimilar(depositorSqueethBalance.sub(depositorSqueethBalanceBefore).toString(), expectedMintedWsqueeth.toString())).to.be.true\n      expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n      expect(depositorWSqueethDebt.eq(depositorSqueethBalance))\n    })\n\n    it(\"should flash deposit correct amount and mint correct shares amount in 1% pool\", async () => {\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      const msgvalue = ethers.utils.parseUnits('10.2')\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor2.address)\n      const totalSupplyBefore = await crabStrategy.totalSupply()\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor2.address))\n      const debtBefore = strategyVault.shortAmount\n      const collateralBefore = strategyVault.collateralAmount\n\n      await crabStrategy.connect(depositor2).flashDeposit(ethToDeposit, poolFeePool2,{ value: msgvalue })\n\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)\n      const debtToMint = ethToDeposit.mul(debtBefore).div(collateralBefore)\n      const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n      const depositorShare = one.mul(ethToDeposit).div(collateralBefore.add(ethToDeposit))\n      const crabMintAmount = totalSupplyBefore.mul(depositorShare).div(one.sub(depositorShare))\n\n      const totalSupply = (await crabStrategy.totalSupply())\n      const depositorCrab = (await crabStrategy.balanceOf(depositor2.address))\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const debtAmount = strategyVaultAfter.shortAmount\n      const depositorSqueethBalance = await wSqueeth.balanceOf(depositor2.address)\n      const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n      const collateralAmount = await strategyVault.collateralAmount\n\n      expect(isSimilar(totalSupply.sub(totalSupplyBefore).toString(), (ethToDeposit).toString(), 2)).to.be.true\n      expect(isSimilar((depositorCrab.sub(depositorCrabBefore)).toString(), (crabMintAmount).toString(), 2)).to.be.true\n      expect(isSimilar(debtAmount.sub(debtBefore).toString(), (debtToMint).toString(), 2)).to.be.true\n      expect(depositorSqueethBalance.eq(depositorSqueethBalanceBefore)).to.be.true\n      expect(strategyContractSqueeth.eq(0)).to.be.true\n    })\n\n\n    it(\"should withdraw correct amount of ETH\", async () => {\n      // some rounding\n      const crabToBurn = (await crabStrategy.balanceOf(depositor.address)).div(2).mul(99).div(100)\n      const wSqueethToBurn = await crabStrategy.getWsqueethFromCrabAmount(crabToBurn)\n      const depositorWSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtBefore = strategyVault.shortAmount\n      const strategyCollateralBefore = strategyVault.collateralAmount\n      const totalCrabBefore = await crabStrategy.totalSupply()\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor.address))\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n\n      const expectedCrabPercentage = wdiv(crabToBurn, totalCrabBefore)\n      const expectedEthToWithdraw = wmul(strategyCollateralBefore, expectedCrabPercentage)\n\n      await wSqueeth.connect(depositor).approve(crabStrategy.address, wSqueethToBurn)\n      await crabStrategy.connect(depositor).withdraw(crabToBurn);\n\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAfter = strategyVaultAfter.shortAmount\n      const totalCrabAfter = await crabStrategy.totalSupply()\n      const depositorCrabAfter = (await crabStrategy.balanceOf(depositor.address))\n      const depositorWSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(depositorCrabAfter.eq(depositorCrabBefore.sub(crabToBurn))).to.be.true\n      expect(totalCrabAfter.eq(totalCrabBefore.sub(crabToBurn))).to.be.true\n      expect(strategyCollateralAfter.eq(strategyCollateralBefore.sub(expectedEthToWithdraw))).to.be.true\n      expect(strategyDebtAfter.eq(strategyDebtBefore.sub(wSqueethToBurn))).to.be.true\n      expect(depositorWSqueethBalanceBefore.sub(depositorWSqueethBalanceAfter).eq(wSqueethToBurn)).to.be.true\n      expect(isSimilar(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).toString(), expectedEthToWithdraw.toString(), 3)).to.be.true // 0.002605896 diff\n    })\n\n    it(\"should revert if slippage is too high\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtAmountBefore = strategyVault.shortAmount\n      const strategyCollateralAmountBefore = strategyVault.collateralAmount\n\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio, strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay, wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethToWithdraw.mul(9).div(10)\n\n      await expect(\n        crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay, poolFee)\n      ).to.be.revertedWith(\"amount in greater than max\");\n    })\n\n    it(\"should flash withdraw correct amount of ETH collateral in main pool (0.3%)\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtAmountBefore = strategyVault.shortAmount\n      const strategyCollateralAmountBefore = strategyVault.collateralAmount\n      const userEthBalanceBefore = await provider.getBalance(depositor.address)\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio, strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay, wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethCostOfDebtToRepay.mul(11).div(10)\n\n      await crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay, poolFee)\n\n      const userEthBalanceAfter = await provider.getBalance(depositor.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor.address);\n\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralAfter = vaultBefore.collateralAmount\n      const debtAfter = vaultBefore.shortAmount\n\n      expect(isSimilar(userEthBalanceAfter.sub(userEthBalanceBefore).toString(), ethToWithdraw.toString(), 2)).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(collateralAfter.eq(strategyCollateralAmountBefore.sub(userCollateral))).to.be.true\n      // TODO: fix this\n      // expect(isSimilar(strategyDebtAmountBefore.sub(debtAfter).toString(), debtToRepay.toString(), 20)).to.be.true\n    })\n    it(\"should flash withdraw correct amount of ETH collateral in secondary pool (1%)\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor2.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtAmountBefore = strategyVault.shortAmount\n      const strategyCollateralAmountBefore = strategyVault.collateralAmount\n      const userEthBalanceBefore = await provider.getBalance(depositor2.address)\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio, strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay, wSqueethPrice.mul(101).div(100))\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethCostOfDebtToRepay.mul(11).div(10)\n\n      await crabStrategy.connect(depositor2).flashWithdraw(userCrabBalanceBefore, maxEthToPay, poolFeePool2)\n\n      const userEthBalanceAfter = await provider.getBalance(depositor2.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor2.address);\n\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralAfter = vaultBefore.collateralAmount\n      const debtAfter = vaultBefore.shortAmount\n\n      expect(isSimilar(userEthBalanceAfter.sub(userEthBalanceBefore).toString(), ethToWithdraw.toString(), 2)).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(collateralAfter.eq(strategyCollateralAmountBefore.sub(userCollateral))).to.be.true\n      // TODO: fix this\n      // expect(isSimilar(strategyDebtAmountBefore.sub(debtAfter).toString(), debtToRepay.toString(), 20)).to.be.true\n    })\n  })\n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/liquidation.ts",
    "content": "import { ethers } from \"hardhat\"\nimport BigNumberJs from 'bignumber.js'\nimport { Contract, BigNumber, constants } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { expect } from \"chai\";\nimport { Controller, INonfungiblePositionManager, ISwapRouter, IUniswapV3Pool, MockErc20, Oracle, VaultLibTester, ShortPowerPerp, WETH9, WPowerPerp, LiquidationHelper } from \"../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addSqueethLiquidity, addWethDaiLiquidity } from '../setup'\nimport { isSimilar, getNow, one, oracleScaleFactor } from \"../utils\";\nimport { getSqrtPriceAndTickBySqueethPrice } from \"../calculator\";\n\nconst TICK_SPACE = 60\n\n// make sure .toString won't return string like 3.73e+22\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\ndescribe(\"Liquidation Integration Test\", function () {\n  let oracle: Oracle;\n  let dai: MockErc20\n  let weth: WETH9\n  let squeeth: WPowerPerp\n  let shortSqueeth: ShortPowerPerp\n  let positionManager: INonfungiblePositionManager\n  let controller: Controller\n  let liquidationHelper: LiquidationHelper\n  let swapRouter: Contract\n\n  const provider = ethers.provider\n  let squeethPool: Contract\n  let ethDaiPool: Contract\n\n  let vaultLib: VaultLibTester\n\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.div(oracleScaleFactor) // 0.3 * 1e18\n  \n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n  \n  let liquidityProvider: SignerWithAddress\n  let seller0: SignerWithAddress\n  let seller1: SignerWithAddress\n  let seller2: SignerWithAddress\n  let seller3: SignerWithAddress\n  let seller4: SignerWithAddress\n  let seller5: SignerWithAddress\n  let seller6: SignerWithAddress\n  let liquidator: SignerWithAddress\n\n  const humanReadableMintAmount = '100'\n\n  // vault0: normal vault to be liquidated\n  let vault0Id: BigNumber\n  const vault0Collateral = ethers.utils.parseUnits('45.1')\n  const vault0MintAmount = ethers.utils.parseUnits(humanReadableMintAmount)\n  \n  // vault1: normal vault need to be fully liquidated, don't have enough collateral to payout all debt\n  let vault1Id: BigNumber\n  const vault1Collateral = ethers.utils.parseUnits('0.91') // almost perfect amount of collateral given the price is 3000\n  const vault1MintAmount = ethers.utils.parseUnits('2')\n\n  // vault2: normal vault need to be fully liquidated, have enough collateral to payout all debt\n  let vault2Id: BigNumber\n  const vault2MintAmount = ethers.utils.parseUnits('1')\n  const vault2Collateral = ethers.utils.parseUnits('0.7') // enough collateral can pay out liquidator, but still underwater if price is up to 6000\n\n  // vault3: with NFT; safe after reduceDebt\n  let vault3Id: BigNumber\n  let vault3LPTokenId: number\n  const vault3Collateral = ethers.utils.parseUnits('45.1')\n  const vault3MintAmount = ethers.utils.parseUnits(humanReadableMintAmount)\n\n  // vault4: with NFT; safe after reduceDebt (same as vault 3, for user to save)\n  let vault4Id: BigNumber\n  let vault4LPTokenId: number\n  const vault4Collateral = ethers.utils.parseUnits('45.1')\n  const vault4MintAmount = ethers.utils.parseUnits(humanReadableMintAmount)\n  \n  // vault5: with NFT; not safe after reduceDebt, can be liquidated when price 8x\n  // can only be liquidated by 50% in each tx. \n  let vault5Id: BigNumber\n  let vault5LPTokenId: number\n  const vault5Collateral = ethers.utils.parseUnits('45.1')\n  const vault5MintAmount = ethers.utils.parseUnits(humanReadableMintAmount)\n\n  // vault6: with NFT full eth; not safe after reduceDebt, C21, have enough collateral to pay all debt\n  let vault6Id: BigNumber\n  const vault6MintAmount = ethers.utils.parseUnits('1')\n  const vault6Collateral = ethers.utils.parseUnits('0.2')\n  const vault6UniEthAmount = ethers.utils.parseUnits('0.5')\n  let vault6LPTokenId: number\n\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners()\n    liquidityProvider = accounts[0]\n    seller0 = accounts[1]\n    seller1 = accounts[2]\n    seller2 = accounts[3]\n    seller3 = accounts[4]\n    seller4 = accounts[5]\n    seller5 = accounts[6]\n    seller6 = accounts[7]\n    liquidator = accounts[9]\n  })\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n  \n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    const coreDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      uniDeployments.positionManager, \n      uniDeployments.uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n\n    positionManager = (uniDeployments.positionManager) as INonfungiblePositionManager\n    swapRouter = uniDeployments.swapRouter\n\n    squeeth = coreDeployments.wsqueeth\n    shortSqueeth = coreDeployments.shortSqueeth\n    controller = coreDeployments.controller\n    squeethPool = coreDeployments.wsqueethEthPool\n    ethDaiPool = coreDeployments.ethDaiPool\n    oracle = coreDeployments.oracle\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const TickMathExternal = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMathExternal.deploy());\n\n    const VaultTester = await ethers.getContractFactory(\"VaultLibTester\", {libraries: {TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n    vaultLib = (await VaultTester.deploy()) as VaultLibTester;\n\n    const LiqHelperFactory = await ethers.getContractFactory(\"LiquidationHelper\", {libraries: {TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n\n    liquidationHelper = await LiqHelperFactory.deploy(\n        controller.address,\n        oracle.address,\n        squeeth.address,\n        weth.address,\n        dai.address,\n        ethDaiPool.address,\n        squeethPool.address,\n        positionManager.address\n      ) as LiquidationHelper;\n  })\n\n  this.beforeAll('Add liquidity to both pools', async() => {\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '5',\n      '30', \n      liquidityProvider.address, \n      squeeth, \n      weth, \n      positionManager, \n      controller\n    )\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('10'), // eth amount\n      liquidityProvider.address,\n      dai,\n      weth,\n      positionManager\n    )\n  })\n\n  this.beforeAll('Prepare vault0 (normal)', async() => {\n    vault0Id = await shortSqueeth.nextId()\n\n    \n    await controller.connect(seller0).mintPowerPerpAmount(0, vault0MintAmount, 0, {value: vault0Collateral})\n  })\n\n  this.beforeAll('Prepare vault1 (normal)', async() => {\n    vault1Id = await shortSqueeth.nextId()\n    await controller.connect(seller1).mintPowerPerpAmount(0, vault1MintAmount, 0, {value: vault1Collateral})\n  })\n\n  this.beforeAll('Prepare vault2 (normal)', async() => {\n    vault2Id = await shortSqueeth.nextId()\n    await controller.connect(seller2).mintPowerPerpAmount(0, vault2MintAmount, 0, {value: vault2Collateral})\n  })\n\n  this.beforeAll('Prepare vault3 (with nft), dealing with cases when it\\'s safe after saving', async() => {\n    vault3Id = await shortSqueeth.nextId()\n\n    \n    await controller.connect(seller3).mintPowerPerpAmount(0, vault3MintAmount, 0, {value: vault3Collateral})\n\n    vault3LPTokenId = await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      humanReadableMintAmount,\n      '45.1',\n      liquidityProvider.address,\n      squeeth,\n      weth,\n      positionManager,\n      controller\n    )\n    await (positionManager as INonfungiblePositionManager).connect(liquidityProvider).transferFrom(liquidityProvider.address, seller3.address, vault3LPTokenId)\n    await (positionManager as INonfungiblePositionManager).connect(seller3).approve(controller.address, vault3LPTokenId)\n\n    await controller.connect(seller3).depositUniPositionToken(vault3Id, vault3LPTokenId)\n    const vault = await controller.vaults(vault3Id)\n    expect(vault.NftCollateralId === vault3LPTokenId).to.be.true\n  })\n\n  this.beforeAll('Prepare vault4 (with nft), dealing with cases when it\\'s safe after saving', async() => {\n    // vault4 is identical to vault3\n    vault4Id = await shortSqueeth.nextId()\n\n    await controller.connect(seller4).mintPowerPerpAmount(0, vault4MintAmount, 0, {value: vault4Collateral})\n\n    vault4LPTokenId = await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      humanReadableMintAmount,\n      '45.1',\n      liquidityProvider.address,\n      squeeth,\n      weth,\n      positionManager,\n      controller\n    )\n    await (positionManager as INonfungiblePositionManager).connect(liquidityProvider).transferFrom(liquidityProvider.address, seller4.address, vault4LPTokenId)\n    await (positionManager as INonfungiblePositionManager).connect(seller4).approve(controller.address, vault4LPTokenId)\n\n    await controller.connect(seller4).depositUniPositionToken(vault4Id, vault4LPTokenId)\n    const vault = await controller.vaults(vault4Id)\n    expect(vault.NftCollateralId === vault4LPTokenId).to.be.true\n  })\n\n  this.beforeAll('Prepare vault5 (with nft), for liquidation', async() => {\n    vault5Id = await shortSqueeth.nextId()\n\n    await controller.connect(seller5).mintPowerPerpAmount(0, vault5MintAmount, 0, {value: vault5Collateral})\n\n    vault5LPTokenId = await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      humanReadableMintAmount,\n      '45.1',\n      liquidityProvider.address,\n      squeeth,\n      weth,\n      positionManager,\n      controller\n    )\n    await positionManager.connect(liquidityProvider).transferFrom(liquidityProvider.address, seller5.address, vault5LPTokenId)\n    await positionManager.connect(seller5).approve(controller.address, vault5LPTokenId)\n\n    await controller.connect(seller5).depositUniPositionToken(vault5Id, vault5LPTokenId)\n    const vault = await controller.vaults(vault5Id)\n    expect(vault.NftCollateralId === vault5LPTokenId).to.be.true\n  })\n\n  this.beforeAll('Prepare vault6 (with all eth nft), for liquidation', async() => {\n    vault6Id = await shortSqueeth.nextId()\n\n    const isWethToken0 = parseInt(weth.address, 16) < parseInt(squeeth.address, 16) \n\n    // create a uni position that's [1000, 2000], so it's now all eth\n    const scaledPrice2000 = BigNumber.from('2000').mul(one).div(oracleScaleFactor)\n    const scaledPrice1000 = BigNumber.from('1000').mul(one).div(oracleScaleFactor)\n    const { tick: tick1000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice1000, isWethToken0)\n    const { tick: tick2000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice2000, isWethToken0)\n    const tickUpper = isWethToken0 ? tick1000 : tick2000;\n    const tickLower = isWethToken0 ? tick2000 : tick1000;\n    const tickUpperToUse = Math.ceil(parseInt(tickUpper, 10) / TICK_SPACE) * TICK_SPACE\n    const tickLowerToUse = Math.ceil(parseInt(tickLower, 10) / TICK_SPACE) * TICK_SPACE\n    const token0 = isWethToken0 ? weth.address : squeeth.address\n    const token1 = isWethToken0 ? squeeth.address : weth.address\n\n    // uni position is all ETH\n    const mintParam = {\n      token0,\n      token1,\n      fee: 3000,\n      tickLower: tickLowerToUse,\n      tickUpper: tickUpperToUse,\n      amount0Desired: isWethToken0 ? vault6UniEthAmount : 0,\n      amount1Desired: isWethToken0 ? 0 : vault6UniEthAmount,\n      amount0Min: 0,\n      amount1Min: 0,\n      recipient: seller6.address,\n      deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n    }\n\n    await weth.connect(seller6).deposit({value: vault6UniEthAmount})\n    await weth.connect(seller6).approve(positionManager.address, constants.MaxUint256)\n    const tx = await positionManager.connect(seller6).mint(mintParam)\n\n    const receipt = await tx.wait();\n    vault6LPTokenId = (receipt.events?.find(event => event.event === 'IncreaseLiquidity'))?.args?.tokenId.toNumber();\n\n    await positionManager.connect(seller6).approve(controller.address, vault6LPTokenId)\n\n    await controller.connect(seller6).mintPowerPerpAmount(0, vault6MintAmount, vault6LPTokenId, {value: vault6Collateral})\n    const vault = await controller.vaults(vault6Id)\n    expect(vault.NftCollateralId === vault6LPTokenId).to.be.true\n  })\n\n  describe('Liquidate normal vault when price is 2x', async( )=> {\n    before('push squeeth price higher 2x', async() => {\n      // set squeeth price higher by buying half of squeeth in the pool\n      const poolSqueethBalance = await squeeth.balanceOf(squeethPool.address)\n\n      const maxWeth = poolSqueethBalance.mul(scaledStartingSqueethPrice1e18).mul(5).div(one)\n      \n      // how much squeeth to buy to make the price 2x\n      const newPoolSqueethBalance = new BigNumberJs(poolSqueethBalance.toString()).div(Math.SQRT2).integerValue().toString()\n      const squeethToBuy = poolSqueethBalance.sub(newPoolSqueethBalance)\n      \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: liquidityProvider.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: squeethToBuy,\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(liquidityProvider).deposit({value: maxWeth})\n      await weth.connect(liquidityProvider).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(liquidityProvider).exactOutputSingle(exactOutputParam)\n\n      // make sure price is set correctly\n      await provider.send(\"evm_increaseTime\", [10]) // increase time by 10 sec\n      await provider.send(\"evm_mine\", [])\n      const newSqueethPrice = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 1, true)\n      expect(isSimilar(newSqueethPrice.toString(), (scaledStartingSqueethPrice1e18.mul(2)).toString())).to.be.true\n    })\n    before('push weth price higher 2x', async() => {\n      // set weth price higher by buying half of weth in the pool\n      const poolWethBalance = await weth.balanceOf(ethDaiPool.address)\n\n      const maxDai = poolWethBalance.mul(startingEthPrice).mul(5)\n\n      const newPoolBalance = new BigNumberJs(poolWethBalance.toString()).div(Math.SQRT2).integerValue().toString()\n      const amountWethToBuy = poolWethBalance.sub(newPoolBalance)\n\n      const exactOutputParam = {\n        tokenIn: dai.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: liquidityProvider.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: amountWethToBuy,\n        amountInMaximum: maxDai,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await dai.connect(liquidityProvider).mint(liquidityProvider.address, maxDai, )\n      await dai.connect(liquidityProvider).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(liquidityProvider).exactOutputSingle(exactOutputParam)\n\n      // make sure price is set correctly\n      await provider.send(\"evm_increaseTime\", [10]) // increase time by 10 sec\n      await provider.send(\"evm_mine\", [])\n      const newWethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 1, false)\n      expect(isSimilar(newWethPrice.toString(), startingEthPrice1e18.mul(2).toString())).to.be.true\n    })\n    before('increase block time to make sure TWAP is updated', async() => {\n      await provider.send(\"evm_increaseTime\", [3600]) // increase time by 60 mins\n      await provider.send(\"evm_mine\", [])\n\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 3600, false)\n      const newSqueethPrice = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 3600, false)\n      expect(isSimilar(newEthPrice.toString(), newSqueethPrice.mul(oracleScaleFactor).toString(), 3)).to.be.true\n    })\n\n    before('prepare liquidator to liquidate vault 0 and vault 1', async() => {\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      const vaultBefore = await controller.vaults(vault0Id)\n      \n      const mintAmount = vaultBefore.shortAmount.mul(2)\n      const collateralRequired = mintAmount.mul(newEthPrice).mul(2).div(oracleScaleFactor).div(one).mul(2)\n\n      // mint squeeth to liquidate vault0!\n      await controller.connect(liquidator).mintPowerPerpAmount(0, mintAmount, 0, {value: collateralRequired})\n      \n    })\n    \n    it(\"liquidate vault 0\", async () => {\n\n      const newSqueethPrice = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 600, false)\n\n      const vaultBefore = await controller.vaults(vault0Id)\n      \n      // state before liquidation\n      const liquidatorSqueethBefore = await squeeth.balanceOf(liquidator.address)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount.div(2)\n\n      const result = await liquidationHelper.checkLiquidation(vault0Id);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      await controller.connect(liquidator).liquidate(vault0Id, wSqueethAmountToLiquidate);\n      \n      const collateralToGet = newSqueethPrice.mul(wSqueethAmountToLiquidate).div(one).mul(11).div(10)\n\n      const vaultAfter = await controller.vaults(vault0Id)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const liquidatorSqueethAfter = await squeeth.balanceOf(liquidator.address)\n\n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.true\n      expect(maxWPowerPerpAmount.eq((vaultBefore.shortAmount).div(2))).to.be.true\n      expect(isSimilar(collateralToReceive.toString(), collateralToGet.toString())).to.be.true\n      \n      // expect(collateralToGet.eq(liquidatorBalanceAfter.sub(liquidatorBalanceBefore))).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(liquidatorSqueethBefore.sub(liquidatorSqueethAfter))).to.be.true\n    })\n\n    it('should revert if trying to leave vault1 a dust vault', async() => {\n      const vaultBefore = await controller.vaults(vault1Id)\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount.div(2)\n      await expect(controller.connect(liquidator).liquidate(vault1Id, wSqueethAmountToLiquidate)).to.be.revertedWith('C22')\n    })\n\n    it(\"fully liquidate vault 1, get the full collateral amount from the vault\", async () => {\n      const vaultBefore = await controller.vaults(vault1Id)\n      \n      // state before liquidation\n      const liquidatorSqueethBefore = await squeeth.balanceOf(liquidator.address)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n\n      // liquidate the full vault\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount\n\n      const result = await liquidationHelper.checkLiquidation(vault1Id);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      await controller.connect(liquidator).liquidate(vault1Id, wSqueethAmountToLiquidate);\n      const vaultAfter = await controller.vaults(vault1Id)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const liquidatorSqueethAfter = await squeeth.balanceOf(liquidator.address)\n\n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.true\n      expect(maxWPowerPerpAmount.eq((vaultBefore.shortAmount))).to.be.true\n      expect(isSimilar(collateralToReceive.toString(), (vaultBefore.collateralAmount).toString())).to.be.true\n\n      // expect(vaultBefore.collateralAmount.eq(liquidatorBalanceAfter.sub(liquidatorBalanceBefore))).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(liquidatorSqueethBefore.sub(liquidatorSqueethAfter))).to.be.true\n    })\n\n    it(\"fully liquidate vault 2, get expected payout\", async () => {      \n      const vaultBefore = await controller.vaults(vault2Id)\n      \n      // state before liquidation\n      const liquidatorSqueethBefore = await squeeth.balanceOf(liquidator.address)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n\n      // liquidate the full vault\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount\n\n      const result = await liquidationHelper.checkLiquidation(vault2Id);\n      const isUnsafe = result[0]\n      const isLiquidatableAfterReducingDebt = result[1]\n      const minWPowerPerpAmount = result[2]\n      const collateralToReceive = result[3]\n\n      await controller.connect(liquidator).liquidate(vault2Id, wSqueethAmountToLiquidate);\n      const vaultAfter = await controller.vaults(vault2Id)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const liquidatorSqueethAfter = await squeeth.balanceOf(liquidator.address)\n\n      const newSqueethPrice = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 600, false)\n      const collateralToGet = newSqueethPrice.mul(wSqueethAmountToLiquidate).div(one).mul(11).div(10)\n      \n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.true\n      expect(minWPowerPerpAmount.eq(vaultBefore.shortAmount)).to.be.true\n      expect(isSimilar(collateralToReceive.toString(), (collateralToGet).toString())).to.be.true\n\n      // expect(collateralToGet.eq(liquidatorBalanceAfter.sub(liquidatorBalanceBefore))).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(liquidatorSqueethBefore.sub(liquidatorSqueethAfter))).to.be.true\n      expect(vaultAfter.shortAmount.isZero()).to.be.true\n      expect(vaultAfter.collateralAmount.gt(0)).to.be.true\n    })\n    \n    it('should revert when trying to liquidate vault 6 (nft vault underwater) but leave dust behind', async() => {\n      const vaultBefore = await controller.vaults(vault6Id)\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount.sub(1)\n\n      const result = await liquidationHelper.checkLiquidation(vault6Id);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount] = result;\n\n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.true\n      expect(maxWPowerPerpAmount.eq((vaultBefore.shortAmount))).to.be.true\n\n      await expect(controller.connect(liquidator).liquidate(vault6Id, wSqueethAmountToLiquidate)).to.be.revertedWith('C22');\n    })\n\n    it(\"fully liquidate vault 6, redeem nft and liquidate\", async () => {\n      const vaultBefore = await controller.vaults(vault6Id)\n      \n      // state before liquidation\n      const liquidatorSqueethBefore = await squeeth.balanceOf(liquidator.address)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n\n      // liquidate the full vault\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount\n\n      const result = await liquidationHelper.checkLiquidation(vault6Id);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      await controller.connect(liquidator).liquidate(vault6Id, wSqueethAmountToLiquidate);\n      const vaultAfter = await controller.vaults(vault6Id)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const liquidatorSqueethAfter = await squeeth.balanceOf(liquidator.address)\n\n      const newSqueethPrice = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 600, false)\n      const collateralToGet = newSqueethPrice.mul(wSqueethAmountToLiquidate).div(one).mul(11).div(10)\n      \n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.true\n      expect(maxWPowerPerpAmount.eq((vaultBefore.shortAmount))).to.be.true\n      expect(isSimilar(collateralToReceive.toString(), (collateralToGet).toString())).to.be.true\n\n      // expect(collateralToGet.eq(liquidatorBalanceAfter.sub(liquidatorBalanceBefore))).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(liquidatorSqueethBefore.sub(liquidatorSqueethAfter))).to.be.true\n      expect(vaultAfter.shortAmount.isZero()).to.be.true\n      expect(vaultAfter.collateralAmount.gt(0)).to.be.true\n    })\n\n    it(\"should revert when trying to liquidate a safe vault\", async () => {\n      const vaultBefore = await controller.vaults(vault3Id)\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount.div(2)\n\n      const result = await liquidationHelper.checkLiquidation(vault6Id);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      expect(isUnsafe).to.be.false\n      expect(isLiquidatableAfterReducingDebt).to.be.false\n      expect(maxWPowerPerpAmount.eq(BigNumber.from(0))).to.be.true\n      expect(collateralToReceive.eq(BigNumber.from(0))).to.be.true\n      \n      await expect(controller.connect(liquidator).liquidate(vault3Id, wSqueethAmountToLiquidate)).to.be.revertedWith('C12')\n    })\n  })\n\n  describe('Save vault with uni nft when price is 4x', async( )=> {\n    before('push squeeth price higher 2x', async() => {\n      // set squeeth price higher by buying half of squeeth in the pool\n      const poolSqueethBalance = await squeeth.balanceOf(squeethPool.address)\n\n      const maxWeth = poolSqueethBalance.mul(scaledStartingSqueethPrice1e18).mul(5).div(one)\n      \n      // how much squeeth to buy to make the price 2x\n      const newPoolSqueethBalance = new BigNumberJs(poolSqueethBalance.toString()).div(Math.SQRT2).integerValue().toString()\n      const squeethToBuy = poolSqueethBalance.sub(newPoolSqueethBalance)\n      \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: liquidityProvider.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: squeethToBuy,\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(liquidityProvider).deposit({value: maxWeth})\n      await weth.connect(liquidityProvider).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(liquidityProvider).exactOutputSingle(exactOutputParam)\n\n      // make sure price is set correctly\n      await provider.send(\"evm_increaseTime\", [10]) // increase time by 10 sec\n      await provider.send(\"evm_mine\", [])\n      const newSqueethPrice = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 1, false)\n      expect(isSimilar(newSqueethPrice.toString(), scaledStartingSqueethPrice1e18.mul(4).toString())).to.be.true\n\n    })\n    before('push weth price higher 2x', async() => {\n      // set weth price higher by buying half of weth in the pool\n      const poolWethBalance = await weth.balanceOf(ethDaiPool.address)\n\n      const maxDai = poolWethBalance.mul(startingEthPrice).mul(5)\n\n      const newPoolBalance = new BigNumberJs(poolWethBalance.toString()).div(Math.SQRT2).integerValue().toString()\n      const amountWethToBuy = poolWethBalance.sub(newPoolBalance)\n\n      const exactOutputParam = {\n        tokenIn: dai.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: liquidityProvider.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: amountWethToBuy,\n        amountInMaximum: maxDai,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await dai.connect(liquidityProvider).mint(liquidityProvider.address, maxDai, )\n      await dai.connect(liquidityProvider).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(liquidityProvider).exactOutputSingle(exactOutputParam)\n\n      // make sure price is set correctly\n      await provider.send(\"evm_increaseTime\", [10]) // increase time by 10 sec\n      await provider.send(\"evm_mine\", [])\n      const newWethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 1, false)\n      expect(isSimilar(newWethPrice.toString(), startingEthPrice1e18.mul(4).toString())).to.be.true\n    })\n    before('increase block time to make sure TWAP is updated', async() => {\n      await provider.send(\"evm_increaseTime\", [3600]) // increase time by 60 mins\n      await provider.send(\"evm_mine\", [])\n\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 3600, false)\n      const newSqueethPrice = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 3600, false)\n      expect(isSimilar(newEthPrice.toString(), newSqueethPrice.mul(oracleScaleFactor).toString(), 3)).to.be.true\n    })\n    it(\"calling liquidation now will save vault 3 and get bounty\", async () => {\n      const newSqueethPrice = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 600, false)\n      // price has 4x, eth amount should have doubled in the nft\n      // squeeth amount should be cut in half\n      // get net worth of nft\n      const { tick } = await (squeethPool as IUniswapV3Pool).slot0()\n      const isWethToken0 = parseInt(weth.address, 16) < parseInt(squeeth.address, 16)\n      const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(positionManager.address, vault3LPTokenId, tick, isWethToken0)\n      \n      const vaultBefore = await controller.vaults(vault3Id)\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount.sub(wPowerPerpAmount).div(2)\n      const liquidatorEthBalance = await provider.getBalance(liquidator.address)\n\n      const result = await liquidationHelper.checkLiquidation(vault3Id);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      // hack: increase liquidity so the fee info got updated\n      await positionManager.connect(liquidityProvider).increaseLiquidity({\n        tokenId: vault3LPTokenId,\n        amount0Desired: 10000,\n        amount1Desired: 10000,\n        amount0Min: 1,\n        amount1Min: 1,\n        deadline: (await getNow(provider)) + 1000\n      })\n      const { tokensOwed0, tokensOwed1 }  = await positionManager.positions(vault3LPTokenId)\n      const ethFeeAmount = isWethToken0 ? tokensOwed0 : tokensOwed1\n      const squeethFeeAmount = isWethToken0 ? tokensOwed1 : tokensOwed0\n\n      const totalEthFromUniPosition = ethAmount.add(ethFeeAmount)\n      const totalWSqueethFromUniPosition = wPowerPerpAmount.add(squeethFeeAmount)\n\n      await controller.connect(liquidator).liquidate(vault3Id, wSqueethAmountToLiquidate)\n\n      const liquidatorEthAfter = await provider.getBalance(liquidator.address)\n      const vaultAfter = await controller.vaults(vault3Id)\n      \n      // paying a 2% bounty on top of total value withdrawn from NFT.\n      const withdrawWSqueethInEth = newSqueethPrice.mul(totalWSqueethFromUniPosition).div(one)\n      const bounty = withdrawWSqueethInEth.add(totalEthFromUniPosition).mul(2).div(100);\n      \n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.false\n      expect(maxWPowerPerpAmount.eq(BigNumber.from(0))).to.be.true\n\n      expect(isSimilar(collateralToReceive.toString(), (bounty).toString(), 3)).to.be.true\n\n      // expect(isSimilar(liquidatorEthAfter.sub(liquidatorEthBalance).toString(), bounty.toString())).to.be.true      \n      expect(vaultAfter.NftCollateralId === 0).to.be.true\n\n      expect(isSimilar(vaultBefore.collateralAmount.add(totalEthFromUniPosition).sub(bounty).toString(), vaultAfter.collateralAmount.toString(), 2)).to.be.true\n\n      // the debt in the vault is reduced by squeethAmount.\n      expect(isSimilar(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).toString(), totalWSqueethFromUniPosition.toString())).to.be.true\n    })\n\n    it(\"seller4 can save his own vault\", async () => {\n      // increase time to make sure time since last update > 0, so view function won't revert\n      await provider.send(\"evm_increaseTime\", [10])\n      await provider.send(\"evm_mine\", [])\n\n      expect(await controller.isVaultSafe(vault4Id)).to.be.false\n      await controller.connect(seller4).reduceDebt(vault4Id)\n\n      // increase time to make sure time since last update > 0, so view function won't revert\n      await provider.send(\"evm_increaseTime\", [10])\n      await provider.send(\"evm_mine\", [])\n      const vaultAfter = await controller.vaults(vault4Id)\n      expect(vaultAfter.NftCollateralId === 0).to.be.true\n      expect(await controller.isVaultSafe(vault4Id)).to.be.true\n    })\n  })\n\n  describe('Liquidate vault with uni nft when price is 8x', async( )=> {\n    before('push squeeth price higher 2x', async() => {\n      // set squeeth price higher by buying half of squeeth in the pool\n      const poolSqueethBalance = await squeeth.balanceOf(squeethPool.address)\n      const poolWethBalance = await weth.balanceOf(squeethPool.address)\n\n      // calculate max weth with 1.5x buffer\n      const maxWeth = new BigNumberJs(poolWethBalance.toString()).times(Math.SQRT2 - 1).times(2).integerValue().toString()\n\n      // how much squeeth to buy to make the price 2x\n      const newPoolSqueethBalance = new BigNumberJs(poolSqueethBalance.toString()).div(Math.SQRT2).integerValue().toString()\n      const squeethToBuy = poolSqueethBalance.sub(newPoolSqueethBalance)\n      \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: liquidityProvider.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: squeethToBuy,\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(liquidityProvider).deposit({value: maxWeth})\n      await weth.connect(liquidityProvider).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(liquidityProvider).exactOutputSingle(exactOutputParam)\n\n      // make sure price is set correctly\n      await provider.send(\"evm_increaseTime\", [10]) // increase time by 10 sec\n      await provider.send(\"evm_mine\", [])\n      const newSqueethPrice = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 1, false)\n      expect(isSimilar(newSqueethPrice.toString(), scaledStartingSqueethPrice1e18.mul(8).toString())).to.be.true\n\n    })\n    before('push weth price higher 2x', async() => {\n      // set weth price higher by buying half of weth in the pool\n      const poolWethBalance = await weth.balanceOf(ethDaiPool.address)\n      const poolDaiBalance = await dai.balanceOf(ethDaiPool.address)\n      \n      // calculate max dai to spend with 1.5x buffer\n      const maxDai = new BigNumberJs(poolDaiBalance.toString()).times(Math.SQRT2 - 1).times(1.5).integerValue().toString()\n\n      const newPoolBalance = new BigNumberJs(poolWethBalance.toString()).div(Math.SQRT2).integerValue().toString()\n      const amountWethToBuy = poolWethBalance.sub(newPoolBalance)\n\n      const exactOutputParam = {\n        tokenIn: dai.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: liquidityProvider.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: amountWethToBuy,\n        amountInMaximum: maxDai,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await dai.connect(liquidityProvider).mint(liquidityProvider.address, maxDai, )\n      await dai.connect(liquidityProvider).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(liquidityProvider).exactOutputSingle(exactOutputParam)\n\n      // make sure price is set correctly\n      await provider.send(\"evm_increaseTime\", [10]) // increase time by 10 sec\n      await provider.send(\"evm_mine\", [])\n      const newWethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 1, false)\n      expect(isSimilar(newWethPrice.toString(), startingEthPrice1e18.mul(8).toString())).to.be.true\n    })\n    before('increase block time to make sure TWAP is updated', async() => {\n      await provider.send(\"evm_increaseTime\", [3600]) // increase time by 60 mins\n      await provider.send(\"evm_mine\", [])\n\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 3600, false)\n      const newSqueethPrice = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 3600, false)\n      expect(isSimilar(newEthPrice.toString(), newSqueethPrice.mul(oracleScaleFactor).toString(), 3)).to.be.true\n    })\n    it(\"calling liquidation now will save vault5 + liquidate half of the remaining debt\", async () => {\n      const newSqueethPrice = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 600, false)\n\n      const { tick } = await (squeethPool as IUniswapV3Pool).slot0()\n      const isWethToken0 = parseInt(weth.address, 16) < parseInt(squeeth.address, 16)\n      const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(positionManager.address, vault5LPTokenId, tick, isWethToken0)\n      \n      // hack: increase liquidity so the fee info got updated\n      await positionManager.connect(liquidityProvider).increaseLiquidity({\n        tokenId: vault5LPTokenId,\n        amount0Desired: 10000,\n        amount1Desired: 10000,\n        amount0Min: 1,\n        amount1Min: 1,\n        deadline: (await getNow(provider)) + 1000\n      })\n      const { tokensOwed0, tokensOwed1 }  = await positionManager.positions(vault5LPTokenId)\n      const ethFeeAmount = isWethToken0 ? tokensOwed0 : tokensOwed1\n      const squeethFeeAmount = isWethToken0 ? tokensOwed1 : tokensOwed0\n\n      // total amount of eth and wsqueeth we can get out of the position nft\n      const totalEthFromUniPosition = ethAmount.add(ethFeeAmount)\n      const totalWSqueethFromUniPosition = wPowerPerpAmount.add(squeethFeeAmount)\n\n      const vaultBefore = await controller.vaults(vault5Id)\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount.sub(totalWSqueethFromUniPosition).div(2)\n      const liquidatorEthBalance = await provider.getBalance(liquidator.address)\n\n      const result = await liquidationHelper.checkLiquidation(vault5Id);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      await controller.connect(liquidator).liquidate(vault5Id, wSqueethAmountToLiquidate)\n\n      const liquidatorEthAfter = await provider.getBalance(liquidator.address)\n      const vaultAfter = await controller.vaults(vault5Id)\n      \n      const reward = newSqueethPrice.mul(wSqueethAmountToLiquidate).div(one).mul(11).div(10)\n\n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.true\n\n      // the estimation is not exactly the same but only off by a very small amount.\n      expect(isSimilar(maxWPowerPerpAmount.toString(), wSqueethAmountToLiquidate.toString(), 10)).to.be.true\n      expect(isSimilar(collateralToReceive.toString(), reward.toString(), 3)).to.be.true\n\n      expect(isSimilar(liquidatorEthAfter.sub(liquidatorEthBalance).toString(), reward.toString())).to.be.true      \n      expect(vaultAfter.NftCollateralId === 0).to.be.true\n\n      expect(isSimilar(vaultBefore.collateralAmount.add(totalEthFromUniPosition).sub(reward).toString(), vaultAfter.collateralAmount.toString())).to.be.true\n\n      // the debt in the vault is reduced by squeethAmount.\n      expect(isSimilar(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).toString(), totalWSqueethFromUniPosition.add(wSqueethAmountToLiquidate).toString())).to.be.true\n    })\n  })\n  \n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/oracle-attack.ts",
    "content": "import { ethers } from \"hardhat\"\nimport BigNumberJs from 'bignumber.js'\nimport { BigNumber } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { expect } from \"chai\";\nimport { Controller, INonfungiblePositionManager, MockErc20, ShortPowerPerp, WETH9, WPowerPerp, IUniswapV3Pool, ISwapRouter } from \"../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addSqueethLiquidity, addWethDaiLiquidity } from '../setup'\nimport { isSimilar, getNow, one, oracleScaleFactor } from \"../utils\";\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\ndescribe(\"Testing system stability during extreme market conditions\", function () {\n  const provider = ethers.provider\n\n  let dai: MockErc20\n  let weth: WETH9\n  let wsqueeth: WPowerPerp\n  let shortSqueeth: ShortPowerPerp\n  let positionManager: INonfungiblePositionManager\n  let controller: Controller\n  \n  let wethPool: IUniswapV3Pool\n  let swapRouter: ISwapRouter\n  \n  \n  const startingEthPrice = 3000\n  \n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n  \n  let liquidityProvider: SignerWithAddress\n  let seller: SignerWithAddress\n  let attacker: SignerWithAddress\n\n  const humanReadableMintAmount = '100'\n\n  const collateralRatio = 2\n  const mintAmount = ethers.utils.parseUnits(humanReadableMintAmount)\n  const depositAmount = mintAmount.mul(startingEthPrice).mul(collateralRatio).div(oracleScaleFactor)\n  \n  const minCollatRatio1e18 = one.mul(3).div(2)\n  const minCollateral = mintAmount.mul(startingEthPrice).mul(minCollatRatio1e18).div(oracleScaleFactor).div(one)\n  \n  let vault0Id: BigNumber\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners()\n    liquidityProvider = accounts[0]\n    seller = accounts[1]\n    attacker = accounts[8]\n  })\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n  \n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    const coreDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      uniDeployments.positionManager, \n      uniDeployments.uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n\n    positionManager = (uniDeployments.positionManager) as INonfungiblePositionManager\n\n    wsqueeth = coreDeployments.wsqueeth\n    shortSqueeth = coreDeployments.shortSqueeth\n    controller = coreDeployments.controller\n    \n    wethPool = coreDeployments.ethDaiPool as IUniswapV3Pool\n    swapRouter = uniDeployments.swapRouter as ISwapRouter\n  })\n\n  this.beforeAll('Add liquidity to both pools', async() => {\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '5',\n      '30', \n      liquidityProvider.address, \n      wsqueeth, \n      weth, \n      positionManager, \n      controller\n    )\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('10'), // eth amount\n      liquidityProvider.address,\n      dai,\n      weth,\n      positionManager\n    )\n\n    // increase time by 10 minutes to make sure we have at least 300 seconds of history\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n  })\n\n  this.beforeAll('Prepare vault with collateral ratio = 2.', async() => {\n    vault0Id = await shortSqueeth.nextId()\n\n    await controller.connect(seller).mintPowerPerpAmount(0, mintAmount, 0, {value: depositAmount})\n  })\n\n  describe('Scenario: ETH/DAI price spikes 100%', async( )=> {\n    // an attacker may push the eth/dai price up to liquidate other's vaults\n    // this is a simulation of how much the TWAP can resist this kind of attack\n\n    before('set eth price to 2x', async() => {\n      \n      // set weth price higher by buying weth from the pool\n      const poolWethBalance = await weth.balanceOf(wethPool.address)\n      const poolDaiBalance = await dai.balanceOf(wethPool.address)\n\n      // calculate max weth with 1.5x buffer\n      const maxDai = new BigNumberJs(poolDaiBalance.toString()).times(Math.SQRT2 - 1).times(2).integerValue().toString()\n\n      // how much squeeth to buy to make the price 2x\n      const newPoolWethBalance = new BigNumberJs(poolWethBalance.toString()).div(Math.SQRT2).integerValue().toString()\n      const wethToBuy = poolWethBalance.sub(newPoolWethBalance)\n      \n      const exactOutputParam = {\n        tokenIn: dai.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: attacker.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: wethToBuy,\n        amountInMaximum: maxDai,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await dai.connect(attacker).mint(attacker.address, maxDai)\n      await dai.connect(attacker).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(attacker).exactOutputSingle(exactOutputParam)\n\n      await provider.send(\"evm_increaseTime\", [1]) // increase time by 1 sec\n      await provider.send(\"evm_mine\", [])\n    })\n\n    describe('1 second after eth price spikes (similar to the state created by flashloan)', async() => {\n      it('index price is updated if requesting with period 1', async() => {\n        const newIndexPrice = await controller.getUnscaledIndex(1)\n        const expectedIndex = BigNumber.from(startingEthPrice).mul(2).pow(2).mul(one)\n        // index is about 6000^2\n        expect(isSimilar(newIndexPrice.toString(), expectedIndex.toString(), 3)).to.be.true\n      })\n      it('vaults remains safe because of TWAP', async() => {\n        const isSafeVault = await controller.isVaultSafe(vault0Id)\n        expect(isSafeVault).to.be.true\n      })\n      it('can still mint with the same amount of collateral (because of TWAP)', async() => {\n        await controller.connect(attacker).mintPowerPerpAmount(0, mintAmount, 0, {value: depositAmount})\n      })\n      it('should revert when trying to mint the same amount with smaller collateral', async() => {\n        await expect(\n          controller.connect(attacker).mintPowerPerpAmount(0, mintAmount, 0, {value: minCollateral})\n        ).to.be.revertedWith('C24')\n      })\n    })\n\n    describe('3 minutes after eth price spiked', async() => {\n      before('increase time', async() => {\n        await provider.send(\"evm_increaseTime\", [180])\n        await provider.send(\"evm_mine\", [])\n      })\n      it('index price is updated if requesting with period 180', async() => {\n        const newIndexPrice = await controller.getUnscaledIndex(180)\n        const expectedIndex = BigNumber.from(startingEthPrice).mul(2).pow(2).mul(one)\n        expect(isSimilar(newIndexPrice.toString(), expectedIndex.toString(), 3)).to.be.true\n      })\n      it('vaults becomes unsafe', async() => {\n        const isSafeVault = await controller.isVaultSafe(vault0Id)\n        expect(isSafeVault).to.be.false\n      })\n      it('should revert when trying to mint with same amount of collateral as before', async() => {\n        await expect(\n          controller.connect(attacker).mintPowerPerpAmount(0, mintAmount, 0, {value: depositAmount})\n        ).to.be.revertedWith('C24')\n      })\n    })\n\n    after('Push eth price back to normal', async() => {\n      // set weth price back: set price of dai 2x\n      // this is the same operation by reverse dai and weth\n      const poolWethBalance = await weth.balanceOf(wethPool.address)\n      const poolDaiBalance = await dai.balanceOf(wethPool.address)\n\n      // calculate max weth with 1.5x buffer\n      const maxWeth = new BigNumberJs(poolWethBalance.toString()).times(Math.SQRT2 - 1).times(2).integerValue().toString()\n\n      // how much squeeth to buy to make the price 2x\n      const newPoolDaiBalance = new BigNumberJs(poolDaiBalance.toString()).div(Math.SQRT2).integerValue().toString()\n      const daiToBuy = poolDaiBalance.sub(newPoolDaiBalance)\n      \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: dai.address,\n        fee: 3000,\n        recipient: attacker.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: daiToBuy,\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(attacker).deposit({value: maxWeth})\n      await weth.connect(attacker).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(attacker).exactOutputSingle(exactOutputParam)\n\n      await provider.send(\"evm_increaseTime\", [600]) // increase time by 10 minutes\n      await provider.send(\"evm_mine\", [])\n    })\n  })\n\n  describe('Scenario: ETH/DAI price crashes 50%', async( )=> {\n    before('set eth price to 50%', async() => {\n      \n      // set weth price back: set price of dai 2x\n      // this is the same operation by reverse dai and weth\n      const poolWethBalance = await weth.balanceOf(wethPool.address)\n      const poolDaiBalance = await dai.balanceOf(wethPool.address)\n\n      // calculate max weth with 1.5x buffer\n      const maxWeth = new BigNumberJs(poolWethBalance.toString()).times(Math.SQRT2 - 1).times(2).integerValue().toString()\n\n      // how much squeeth to buy to make the price 2x\n      const newPoolDaiBalance = new BigNumberJs(poolDaiBalance.toString()).div(Math.SQRT2).integerValue().toString()\n      const daiToBuy = poolDaiBalance.sub(newPoolDaiBalance)\n      \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: dai.address,\n        fee: 3000,\n        recipient: attacker.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: daiToBuy,\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(attacker).deposit({value: maxWeth})\n      await weth.connect(attacker).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(attacker).exactOutputSingle(exactOutputParam)\n\n      await provider.send(\"evm_increaseTime\", [1]) // increase time by 1 sec\n      await provider.send(\"evm_mine\", [])\n    })\n\n    describe('1 second after eth price crash (Similar to the state created by flashloan)', async() => {\n      it('index price is updated if requesting with period 1', async() => {\n        const newIndexPrice = await controller.getUnscaledIndex(1)\n        const expectedIndex = BigNumber.from(startingEthPrice).div(2).pow(2).mul(one)\n        // index is about 1500^2\n        expect(isSimilar(newIndexPrice.toString(), expectedIndex.toString(), 2)).to.be.true\n      })\n      it('vaults is still safe (because price moves down)', async() => {\n        const isSafeVault = await controller.isVaultSafe(vault0Id)\n        expect(isSafeVault).to.be.true\n      })\n      it('should revert if trying to mint more squeeth', async() => {\n        // attack only put in the old min collateral\n        const attackMintAmount = mintAmount.mul(101).div(100)\n        \n        await expect(\n          controller.connect(attacker).mintPowerPerpAmount(0, attackMintAmount, 0, {value: minCollateral})\n        ).to.be.revertedWith('C24')\n      })\n    })\n\n    describe('1 minutes after eth price crashed', async() => {\n      before('increase time', async() => {\n        await provider.send(\"evm_increaseTime\", [60])\n        await provider.send(\"evm_mine\", [])\n      })\n      it('index price is updated if requesting with period 60', async() => {\n        const newIndexPrice = await controller.getUnscaledIndex(60)\n        const expectedIndex = BigNumber.from(startingEthPrice).div(2).pow(2).mul(one)\n        // index is about 1500^2\n        expect(isSimilar(newIndexPrice.toString(), expectedIndex.toString(), 2)).to.be.true\n      })\n      \n      it('will be able to mint more squeeth', async() => {\n        // attack only put in the old min collateral\n        const attackMintSuperHighAmount = mintAmount.mul(120).div(100)\n        await expect(controller.connect(attacker).mintPowerPerpAmount(0, attackMintSuperHighAmount, 0, {value: minCollateral})).to.be.revertedWith('C24')\n\n        const attackMintAmount = mintAmount.mul(110).div(100)\n        await controller.connect(attacker).mintPowerPerpAmount(0, attackMintAmount, 0, {value: minCollateral})\n      })\n    })\n    \n  })\n})\n"
  },
  {
    "path": "packages/hardhat/test/integration-tests/oracle_integration.ts",
    "content": "import { ethers, getNamedAccounts } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract } from \"ethers\";\nimport { Controller, Oracle, WETH9, WPowerPerp } from \"../../typechain\";\nimport { isSimilar } from '../utils'\nimport { deployUniswapV3, deploySqueethCoreContracts, addSqueethLiquidity, deployWETHAndDai } from '../setup'\n\ndescribe(\"Oracle Integration Test\", function () {\n  let oracle: Oracle;\n  let dai: Contract\n  let weth: WETH9\n  let squeeth: WPowerPerp\n  let squeethPool: Contract\n  let ethDaiPool: Contract\n  let positionManager: Contract\n  let controller: Controller\n  const startingPrice = 3000\n  const provider = ethers.provider\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n  \n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n\n    // this will not deploy a new pool, only reuse old onces\n    const coreDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      uniDeployments.positionManager, \n      uniDeployments.uniswapFactory,\n      startingPrice,\n      startingPrice\n    )\n\n    positionManager = uniDeployments.positionManager\n\n    squeeth = coreDeployments.wsqueeth\n    controller = coreDeployments.controller\n    squeethPool = coreDeployments.wsqueethEthPool\n    ethDaiPool = coreDeployments.ethDaiPool\n    oracle = coreDeployments.oracle\n  })\n\n  describe('Get TWAP right after setup', async( )=> {\n    describe(\"TWAP for squeeth/eth\", async () => {\n      this.beforeEach(async () => {\n        await provider.send(\"evm_increaseTime\", [10])\n        await provider.send(\"evm_mine\", [])\n      })\n  \n      it(\"fetch initial price\", async () => {\n        const price = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 1, false)\n        expect(isSimilar(price.toString(), (startingPrice * 1e18).toString())).to.be.true\n      })\n      it(\"fetch price twap for last 10 seconds\", async () => {\n        const price = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 10, false)\n        expect(isSimilar(price.toString(), (startingPrice * 1e18).toString())).to.be.true\n      })\n      it(\"should revert while requesting twap with price too old\", async () => {\n        await expect(\n          oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 600, false)\n        ).to.be.revertedWith(\"OLD\");\n      })  \n    })\n  \n    describe(\"TWAP for eth/dai\", async () => {  \n      it(\"fetch initial price\", async () => {\n        const price = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 1, false)\n        expect(isSimilar(price.toString(), (startingPrice * 1e18).toString())).to.be.true\n      })\n      it(\"fetch price twap for last 10 seconds\", async () => {\n        const price = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 10, false)\n        expect(isSimilar(price.toString(), (startingPrice * 1e18).toString())).to.be.true\n      })  \n      it(\"should revert while requesting twap with price too old\", async () => {\n        await expect(\n          oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n        ).to.be.revertedWith(\"OLD\");\n      })  \n    })\n  })\n\n  describe('Get TWAP right after 10 mins', async( )=> {\n    it('go 10 mins', async() => {\n      await provider.send(\"evm_increaseTime\", [600]) // go 10 minutes\n    })\n    it(\"fetch squeeth twap for last 10 mins\", async () => {\n      const price = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 600, false)\n      expect(isSimilar(price.toString(), (startingPrice * 1e18).toString())).to.be.true\n    })  \n    it(\"fetch eth twap for last 10 mins\", async () => {\n      const price = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      expect(isSimilar(price.toString(), (startingPrice * 1e18).toString())).to.be.true\n    })  \n  })\n\n  describe('Adding liquidity mess up things', async() => {\n    it('add liquidity', async() => {\n      const { deployer } = await getNamedAccounts();\n      await addSqueethLiquidity(3000, '0.001', '10', deployer, squeeth, weth, positionManager, controller)\n    })\n    it(\"fetch squeeth twap for last 10 mins\", async () => {\n      const price = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 600, false)\n      expect(isSimilar(price.toString(), (startingPrice * 1e18).toString())).to.be.true\n    })\n  })\n})\n"
  },
  {
    "path": "packages/hardhat/test/integration-tests/periphery/controller-helper.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers, constants } from \"ethers\";\nimport BigNumberJs from 'bignumber.js'\n\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { WETH9, MockErc20, ShortPowerPerp, Controller, Oracle, WPowerPerp, ControllerHelper, INonfungiblePositionManager, SqrtPriceMathPartial} from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity } from '../../setup'\nimport { one, oracleScaleFactor, getNow } from \"../../utils\"\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\ndescribe(\"Controller helper integration test\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let feeRecipient: SignerWithAddress;\n  let tester: SignerWithAddress\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let ethDaiPool: Contract\n  let controllerHelper: ControllerHelper\n  let shortSqueeth: ShortPowerPerp\n  let swapRouter: Contract\n  let quoter: Contract\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _feeRecipient, _tester ] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    feeRecipient = _feeRecipient\n    tester = _tester;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n    quoter = uniDeployments.quoter\n\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      positionManager, \n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n    \n    const TickMathExternal = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathExternalLib = (await TickMathExternal.deploy());\n\n    const SqrtPriceMathPartial = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceMathPartialLib = (await SqrtPriceMathPartial.deploy());\n\n    const ControllerHelperUtil = await ethers.getContractFactory(\"ControllerHelperUtil\", {libraries: {TickMathExternal: TickMathExternalLib.address, SqrtPriceMathPartial: SqrtPriceMathPartialLib.address}});\n    const ControllerHelperUtilLib = (await ControllerHelperUtil.deploy());\n    \n    const ControllerHelperContract = await ethers.getContractFactory(\"ControllerHelper\", {libraries: {ControllerHelperUtil: ControllerHelperUtilLib.address}});\n    controllerHelper = (await ControllerHelperContract.deploy(controller.address, positionManager.address, uniswapFactory.address, constants.AddressZero, constants.AddressZero, constants.AddressZero)) as ControllerHelper;\n  })\n  \n  this.beforeAll(\"Seed pool liquidity\", async() => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '1000000',\n      '2000000', \n      owner.address, \n      wSqueeth, \n      weth, \n      positionManager, \n      controller\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n  })\n\n  describe(\"Mint short with flash deposit\", async () => {\n    it(\"mint + sell using 100% of proceeds as collateral (with some additional ETH sent)\", async () => {      \n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('10')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      // we do this just to have the the exactInputSingle static call not revert so we can estimated price impact and ethAmountOut\n      await controller.connect(owner).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n      const swapParam = {\n        tokenIn: wSqueeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        amountIn: mintWSqueethAmount,\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0\n      }    \n      await wSqueeth.connect(owner).approve(swapRouter.address, constants.MaxUint256)\n      const ethAmountOut = await swapRouter.connect(owner).callStatic.exactInputSingle(swapParam)\n      const vaultId = await shortSqueeth.nextId();\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const value = collateralAmount.sub(ethAmountOut.mul(one.sub(slippage)).div(one))\n      const controllerBalanceBefore = await provider.getBalance(controller.address)\n      const squeethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const vaultBefore = await controller.vaults(vaultId)\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const ethToReceive = (mintWSqueethAmount.mul(squeethPrice).div(one)).mul(one.sub(slippage)).div(one)\n      const params = {\n        vaultId: 0,\n        collateralToDeposit: collateralAmount.toString(),\n        wPowerPerpAmountToMint: mintWSqueethAmount.toString(),\n        minToReceive: ethToReceive.toString(),\n        wPowerPerpAmountToSell: BigNumber.from(0),\n        poolFee: 3000\n      }\n\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const tx = await controllerHelper.connect(depositor).flashswapSellLongWMint(params, {value: value});\n\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n      const controllerBalanceAfter = await provider.getBalance(controller.address)\n      const squeethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const vaultAfter = await controller.vaults(vaultId)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(controllerBalanceBefore.add(collateralAmount).eq(controllerBalanceAfter)).to.be.true\n      expect(squeethBalanceBefore.eq(squeethBalanceAfter)).to.be.true\n      expect(vaultBefore.collateralAmount.add(collateralAmount).eq(vaultAfter.collateralAmount)).to.be.true\n      expect(vaultBefore.shortAmount.add(mintWSqueethAmount).eq(vaultAfter.shortAmount)).to.be.true\n      expect(depositorEthBalanceAfter.add(gasSpent).eq(depositorEthBalanceBefore.sub(collateralAmount.sub(ethAmountOut)))).to.be.true\n    })\n\n    it(\"flash mint sell 100% proceeds with zero additional eth\", async () => {      \n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('10')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const controllerBalanceBefore = await provider.getBalance(controller.address)\n      const squeethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const depositorBalanceInitial = await provider.getBalance(depositor.address)\n      // Deposit enough collateral for 10 wSqueeth but don't mint anything\n      await controller.connect(depositor).mintWPowerPerpAmount(0, 0, 0, {value: collateralAmount})\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const vaultBefore = await controller.vaults(vaultId)\n\n      await wSqueeth.connect(depositor).approve(swapRouter.address, constants.MaxUint256)\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n\n      await wSqueeth.connect(depositor).approve(swapRouter.address, constants.MaxUint256)\n      // Get expected proceeds of sale of wSqeeth \n\n      const ethAmountOutFromSwap = await quoter.connect(tester).callStatic.quoteExactInputSingle(wSqueeth.address,\n           weth.address,\n           3000,\n           mintWSqueethAmount,\n           0)\n\n      const params = {\n        vaultId: vaultId.toString(),\n        collateralToDeposit: ethAmountOutFromSwap.toString(), // deposit 100% of proceeds of swap as collateral\n        wPowerPerpAmountToMint: mintWSqueethAmount.toString(),\n        minToReceive: BigNumber.from(0),\n        wPowerPerpAmountToSell: BigNumber.from(0),\n        poolFee: 3000\n      }\n      // flash mint with zero additional eth\n\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const tx = await controllerHelper.connect(depositor).flashswapSellLongWMint(params);\n\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n      const controllerBalanceAfter = await provider.getBalance(controller.address)\n      const squeethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const vaultAfter = await controller.vaults(vaultId)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n      \n      // no long squeeth\n      expect(squeethBalanceBefore.eq(squeethBalanceAfter)).to.be.true\n      // 100% of sale proceeds added to collateral\n      expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).sub(ethAmountOutFromSwap).eq(BigNumber.from(0))).to.be.true\n      // target short amount minted\n      expect(vaultBefore.shortAmount.add(mintWSqueethAmount).eq(vaultAfter.shortAmount)).to.be.true\n      // depositor balance reduced by collateral\n      expect(depositorEthBalanceAfter.add(gasSpent).eq(depositorEthBalanceBefore)).to.be.true\n    })\n\n    it(\"flash mint sell, use 50% proceeds as collateral with 0 additional eth\", async () => {      \n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('10')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const controllerBalanceBefore = await provider.getBalance(controller.address)\n      const squeethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      // Deposit enough collateral for 10 wSqueeth but don't mint anything\n      await controller.connect(depositor).mintWPowerPerpAmount(0, 0, 0, {value: collateralAmount})\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const vaultBefore = await controller.vaults(vaultId)\n      await wSqueeth.connect(depositor).approve(swapRouter.address, constants.MaxUint256)\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n\n      await wSqueeth.connect(owner).approve(swapRouter.address, constants.MaxUint256)\n\n      // Get expected proceeds of sale of wSqeeth \n      const ethAmountOutFromSwap = await quoter.connect(tester).callStatic.quoteExactInputSingle(wSqueeth.address,\n           weth.address,\n           3000,\n           mintWSqueethAmount,\n           0)\n\n      const collatToDeposit = ethAmountOutFromSwap.div(2)\n      // we have to do this because of rounding\n      const collatToReceive = ethAmountOutFromSwap.sub(collatToDeposit)\n\n      const params = {\n        vaultId: vaultId.toString(),\n        collateralToDeposit: collatToDeposit.toString(), // deposit 100% of proceeds of swap as collateral\n        wPowerPerpAmountToMint: mintWSqueethAmount.toString(),\n        minToReceive: BigNumber.from(0),\n        wPowerPerpAmountToSell: BigNumber.from(0),\n        poolFee: 3000\n      }\n      // flash mint with zero additional eth\n      \n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const tx = await controllerHelper.connect(depositor).flashswapSellLongWMint(params);\n\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n      const controllerBalanceAfter = await provider.getBalance(controller.address)\n      const squeethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const vaultAfter = await controller.vaults(vaultId)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n      \n      // no long squeeth\n      expect(squeethBalanceBefore.eq(squeethBalanceAfter)).to.be.true\n      // 100% of sale proceeds added to collateral\n      expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).sub(ethAmountOutFromSwap.div(2)).eq(BigNumber.from(0))).to.be.true\n      // target short amount minted\n      expect(vaultBefore.shortAmount.add(mintWSqueethAmount).eq(vaultAfter.shortAmount)).to.be.true\n      // depositor balance reduced by collateral\n      expect(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).eq(collatToReceive.sub(gasSpent))).to.be.true\n\n    })\n\n    it(\"flash mint sell 0% proceeds with 0 additional eth\", async () => {      \n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('10')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const controllerBalanceBefore = await provider.getBalance(controller.address)\n      const squeethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      // Deposit enough collateral for 10 wSqueeth but don't mint anything\n      await controller.connect(depositor).mintWPowerPerpAmount(0, 0, 0, {value: collateralAmount})\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const vaultBefore = await controller.vaults(vaultId)\n      await wSqueeth.connect(depositor).approve(swapRouter.address, constants.MaxUint256)\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n\n      await wSqueeth.connect(owner).approve(swapRouter.address, constants.MaxUint256)\n      // Get expected proceeds of sale of wSqeeth \n      const ethAmountOutFromSwap = await quoter.connect(tester).callStatic.quoteExactInputSingle(wSqueeth.address,\n           weth.address,\n           3000,\n           mintWSqueethAmount,\n           0)\n\n      const params = {\n        vaultId: vaultId.toString(),\n        collateralToDeposit: BigNumber.from(0), // deposit 100% of proceeds of swap as collateral\n        wPowerPerpAmountToMint: mintWSqueethAmount.toString(),\n        minToReceive: BigNumber.from(0),\n        wPowerPerpAmountToSell: BigNumber.from(0),\n        poolFee: 3000\n      }\n\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      // flash mint with zero additional eth\n      const tx = await controllerHelper.connect(depositor).flashswapSellLongWMint(params);\n\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n      const controllerBalanceAfter = await provider.getBalance(controller.address)\n      const squeethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const vaultAfter = await controller.vaults(vaultId)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n      \n      // no long squeeth\n      expect(squeethBalanceBefore.eq(squeethBalanceAfter)).to.be.true\n      // 100% of sale proceeds added to collateral\n      expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).eq(BigNumber.from(0))).to.be.true\n      // target short amount minted\n      expect(vaultBefore.shortAmount.add(mintWSqueethAmount).eq(vaultAfter.shortAmount)).to.be.true\n      expect(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).eq(ethAmountOutFromSwap.sub(gasSpent))).to.be.true\n\n    })\n  })\n  describe(\"Flash close short position\", async () => {\n\n    it(\"flash close short position and buy long with no added eth\", async () => {\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const longBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      await weth.connect(owner).approve(swapRouter.address, constants.MaxUint256)\n\n      const squeethCanBuy = await quoter.connect(tester).callStatic.quoteExactInputSingle(weth.address,\n        wSqueeth.address,\n        3000,\n        vaultBefore.collateralAmount,\n        0)\n\n      const squeethToBuy = squeethCanBuy.sub(vaultBefore.shortAmount)\n\n      const params = {\n        vaultId,\n        wPowerPerpAmountToBurn: vaultBefore.shortAmount.toString(),\n        wPowerPerpAmountToBuy: squeethToBuy.toString(),\n        collateralToWithdraw: vaultBefore.collateralAmount.toString(),\n        maxToPay: vaultBefore.collateralAmount.toString(),\n        poolFee: 3000\n      }\n\n      await controllerHelper.connect(depositor).flashswapWBurnBuyLong(params);\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const longBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n\n      expect(longBalanceBefore.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n      expect(longBalanceAfter.sub(longBalanceBefore).eq(squeethToBuy)).to.be.true\n    })\n\n    it(\"partially close position where ETH is needed to attach to hit the target CR\", async () => {\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('10')\n\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n      const longBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n      const vaultBefore = await controller.vaults(vaultId)\n\n      const shortToCover = vaultBefore.shortAmount.div(4)\n      // 180% CR target after covering 25% of position\n      const targetCollateralizationRatio = BigNumber.from(10).pow(18).mul(9).div(5)\n      const remainingShort = vaultBefore.shortAmount.sub(shortToCover)\n\n      // Get expected cost of buy of wSqeeth \n      const ethToPay = await quoter.connect(tester).callStatic.quoteExactOutputSingle(weth.address,\n        wSqueeth.address,\n        3000,\n        vaultBefore.shortAmount,\n        0)\n\n      const ethToAttach = targetCollateralizationRatio.mul(remainingShort).div(one).mul(normFactor).div(one).mul(scaledEthPrice).div(one).add(ethToPay).sub(vaultBefore.collateralAmount)\n      const collateralToWithdraw = ethToPay.sub(ethToAttach)\n\n      const params = {\n        vaultId,\n        wPowerPerpAmountToBurn: shortToCover.toString(),\n        wPowerPerpAmountToBuy: 0,\n        collateralToWithdraw: collateralToWithdraw.toString(),  //need to withdraw some collateral to hit the target cr\n        maxToPay: ethToPay.toString(),\n        poolFee: 3000\n      }\n\n      const tx = await controllerHelper.connect(depositor).flashswapWBurnBuyLong(params, {value: ethToAttach});\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const longBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n\n      expect(vaultAfter.shortAmount.eq(remainingShort)).to.be.true\n      expect(vaultAfter.collateralAmount.eq(vaultBefore.collateralAmount.sub(collateralToWithdraw))).to.be.true\n      expect(longBalanceAfter.eq(longBalanceBefore)).to.be.true\n    })\n\n    it(\"partially close position where ETH withdrawn to hit the target CR\", async () => {\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('10')\n\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      // 300% CR\n      const collateralAmount = debtInEth.mul(3).add(ethers.utils.parseUnits('0.01'))\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n      const longBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n      const vaultBefore = await controller.vaults(vaultId)\n\n      const shortToCover = vaultBefore.shortAmount.div(4)\n      // 200% CR target after covering 25% of position\n      const targetCollateralizationRatio = BigNumber.from(10).pow(18).mul(2)\n      const remainingShort = vaultBefore.shortAmount.sub(shortToCover)\n\n      // Get expected cost of buy of wSqeeth \n      const ethToPay = await quoter.connect(tester).callStatic.quoteExactOutputSingle(weth.address,\n        wSqueeth.address,\n        3000,\n        vaultBefore.shortAmount,\n        0)\n                                          \n      const collateralToWithdraw = vaultBefore.collateralAmount.sub(targetCollateralizationRatio.mul(remainingShort).div(one).mul(normFactor).div(one).mul(scaledEthPrice).div(one))\n\n      const params = {\n        vaultId,\n        wPowerPerpAmountToBurn: shortToCover.toString(),\n        wPowerPerpAmountToBuy: 0,\n        collateralToWithdraw: collateralToWithdraw.toString(),  //need to withdraw some collateral to hit the target cr\n        maxToPay: ethToPay.toString(),\n        poolFee: 3000\n      }\n\n      const tx = await controllerHelper.connect(depositor).flashswapWBurnBuyLong(params);\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const longBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n\n      expect(vaultAfter.shortAmount.eq(remainingShort)).to.be.true\n      expect(vaultAfter.collateralAmount.eq(vaultBefore.collateralAmount.sub(collateralToWithdraw))).to.be.true\n      expect(longBalanceAfter.eq(longBalanceBefore)).to.be.true\n    })\n\n    it(\"full close position using 100% of ETH collateral to buy long + extra user added ETH\", async () => {\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('10')\n      const ethToAttach = ethers.utils.parseUnits('2')\n\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n      const longBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n\n      const vaultBefore = await controller.vaults(vaultId)\n      // Get expected proceeds of sale of wSqeeth \n      const squeethCanBuy = await quoter.connect(tester).callStatic.quoteExactInputSingle(weth.address,\n        wSqueeth.address,\n        3000,\n        vaultBefore.collateralAmount.add(ethToAttach),\n        0)\n\n      const squeethToBuy = squeethCanBuy.sub(vaultBefore.shortAmount)\n\n      const params = {\n        vaultId,\n        wPowerPerpAmountToBurn: vaultBefore.shortAmount.toString(),\n        wPowerPerpAmountToBuy: squeethToBuy.toString(),\n        collateralToWithdraw: vaultBefore.collateralAmount.toString(),\n        maxToPay: vaultBefore.collateralAmount.add(ethToAttach).toString(),\n        poolFee: 3000\n      }\n\n      const tx = await controllerHelper.connect(depositor).flashswapWBurnBuyLong(params, {value: ethToAttach});\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const longBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n      expect(longBalanceAfter.sub(longBalanceBefore).eq(squeethToBuy)).to.be.true\n    })\n    it(\"fully close position, buying 0 extra, returning residual ETH in vault after cost to close to user \", async () => {\n\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('10')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n      const longBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n\n      const vaultBefore = await controller.vaults(vaultId)\n      // Get expected proceeds of sale of wSqeeth \n      const ethAmountToSwap = await quoter.connect(tester).callStatic.quoteExactOutputSingle(weth.address,\n        wSqueeth.address,\n        3000,\n        vaultBefore.shortAmount,\n        0)\n      const params = {\n        vaultId,\n        wPowerPerpAmountToBurn: vaultBefore.shortAmount.toString(),\n        wPowerPerpAmountToBuy: BigNumber.from(0),\n        collateralToWithdraw: vaultBefore.collateralAmount.toString(),\n        maxToPay: ethAmountToSwap.toString(),\n        poolFee: 3000\n      }\n      // ** May be good to have some explicit revert msgs here\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const tx = await controllerHelper.connect(depositor).flashswapWBurnBuyLong(params);\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n      \n      const vaultAfter = await controller.vaults(vaultId)\n      const longBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n      expect(longBalanceAfter.eq(longBalanceBefore)).to.be.true\n      expect(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).eq(vaultBefore.collateralAmount.sub(ethAmountToSwap).sub(gasSpent))).to.be.true\n    })\n    it(\"fully close position, buying some but less than residual collateral\", async () => {\n\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('10')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n      const longBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n\n      const vaultBefore = await controller.vaults(vaultId)\n      \n      \n      // Get expected proceeds of sale of wSqeeth \n      const ethAmountToSwap = await quoter.connect(tester).callStatic.quoteExactOutputSingle(weth.address,\n        wSqueeth.address,\n        3000,\n        vaultBefore.shortAmount,\n        0)\n\n      const excessEthFromCollateral = vaultBefore.collateralAmount.sub(ethAmountToSwap)\n\n      const squeethToBuy = await quoter.connect(tester).callStatic.quoteExactInputSingle(weth.address,\n        wSqueeth.address,\n        3000,\n        excessEthFromCollateral.div(2),\n        0)\n\n      const residualCollateral = vaultBefore.collateralAmount.sub(excessEthFromCollateral.div(2))\n\n      const params = {\n        vaultId,\n        wPowerPerpAmountToBurn: vaultBefore.shortAmount.toString(),\n        wPowerPerpAmountToBuy: squeethToBuy,\n        collateralToWithdraw: vaultBefore.collateralAmount.toString(),\n        maxToPay: vaultBefore.collateralAmount.toString(),\n        poolFee: 3000\n      }\n      // ** May be good to have some explicit revert msgs here\n      await controllerHelper.connect(depositor).flashswapWBurnBuyLong(params);\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const longBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n      expect(longBalanceAfter.eq(longBalanceBefore.add(squeethToBuy))).to.be.true\n      expect(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).eq(residualCollateral))\n    })\n\n  })\n\n  describe(\"Batch mint and LP\", async () => {\n    it(\"Batch mint and LP\", async () => {\n      const vaultId = (await shortSqueeth.nextId());\n\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('15')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n      const vaultBefore = await controller.vaults(vaultId)\n      const tokenIndexBefore = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const params = {\n        recipient: depositor.address,\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: 0,\n        wPowerPerpAmount: mintWSqueethAmount,\n        collateralToDeposit: collateralAmount,\n        collateralToLp: collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        lowerTick: -887220,\n        upperTick: 887220\n      }\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n      const tx = await controllerHelper.connect(depositor).wMintLp(params, {value: collateralAmount.add(collateralToLp)});\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(tokenId); \n      const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: position.liquidity,\n        amount0Min: 0,\n        amount1Min: 0,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n\n      expect(position.tickLower === -887220).to.be.true\n      expect(position.tickUpper === 887220).to.be.true\n      expect(ownerOfUniNFT === depositor.address).to.be.true\n      expect(tokenIndexAfter.sub(tokenIndexBefore).eq(BigNumber.from(1))).to.be.true\n      expect(vaultBefore.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultBefore.collateralAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(collateralAmount)).to.be.true\n      //uniswap rounding of LP often gives 1 wei less than expected (uniswap takes the 1 wei, but only gives credit for 1 wei less in the LP share)\n      expect((depositorEthBalanceBefore.sub(depositorEthBalanceAfter).sub(collateralAmount).sub(wethAmountInLP).sub(gasSpent)).abs().lte(1)).to.be.true\n      //not sure why there is a shortfall here, maybe rounding, testing less than 5bps difference from expected\n      expect((vaultAfter.shortAmount.sub(wPowerPerpAmountInLP)).mul(one).div(wPowerPerpAmountInLP).abs().lte(BigNumber.from(10).pow(14).mul(5))).to.be.true\n\n      //not sure why there is a shortfall here, maybe rounding, testing less than 5bps difference from expected\n      expect(wethAmountInLP.sub(collateralToLp).mul(one).div(collateralToLp).abs().lte(BigNumber.from(10).pow(14).mul(5))).to.be.true\n      expect(wPowerPerpAmountInLP.sub(mintWSqueethAmount).mul(one).div(mintWSqueethAmount).abs().lte(BigNumber.from(10).pow(14).mul(5))).to.be.true\n      \n    })\n\n    it(\"Batch mint and LP - existing vault >0 LP collateral with >0 ETH collateral added\", async () => {\n      // Make empty vault\n      await controller.connect(depositor).mintWPowerPerpAmount(0, 0, 0, {value: 0})\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n  \n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('15')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n      const vaultBefore = await controller.vaults(vaultId)\n      const tokenIndexBefore = await (positionManager as INonfungiblePositionManager).totalSupply();\n  \n      const params = {\n        recipient: depositor.address,\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: vaultId,\n        wPowerPerpAmount: mintWSqueethAmount, \n        collateralToDeposit: collateralAmount,\n        collateralToLp: collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        lowerTick: -887220,\n        upperTick: 887220\n      }\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const tx = await controllerHelper.connect(depositor).wMintLp(params, {value: collateralAmount.add(collateralToLp)});\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(tokenId); \n      const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n  \n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: position.liquidity,\n        amount0Min: 0,\n        amount1Min: 0,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n\n      expect(position.tickLower === -887220).to.be.true\n      expect(position.tickUpper === 887220).to.be.true\n      expect(ownerOfUniNFT === depositor.address).to.be.true\n      expect(tokenIndexAfter.sub(tokenIndexBefore).eq(BigNumber.from(1))).to.be.true\n      expect(vaultBefore.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultBefore.collateralAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(collateralAmount)).to.be.true\n      //uniswap rounding of LP often gives some wei less than expected (uniswap takes the wei, but only gives credit for less wei in the LP share)\n      expect((depositorEthBalanceBefore.sub(depositorEthBalanceAfter).sub(collateralAmount).sub(wethAmountInLP).sub(gasSpent)).abs().lte(1)).to.be.true\n\n      //not sure why there is a shortfall here, maybe rounding, testing less than 5bps difference from expected\n      expect((vaultAfter.shortAmount.sub(wPowerPerpAmountInLP)).mul(one).div(wPowerPerpAmountInLP).abs().lte(BigNumber.from(10).pow(14).mul(5))).to.be.true\n\n      //not sure why there is a shortfall here, maybe rounding, testing less than 5bps difference from expected\n      expect(wethAmountInLP.sub(collateralToLp).mul(one).div(collateralToLp).abs().lte(BigNumber.from(10).pow(14).mul(5))).to.be.true\n      expect(wPowerPerpAmountInLP.sub(mintWSqueethAmount).mul(one).div(mintWSqueethAmount).abs().lte(BigNumber.from(10).pow(14).mul(5))).to.be.true\n  \n    })\n\n    it(\"Batch mint and LP - existing vault >0 LP collateral with >0 ETH collateral added, one sided LP with just oSQTH\", async () => {\n\n      // Make empty vault\n      await controller.connect(depositor).mintWPowerPerpAmount(0, 0, 0, {value: 0})\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n      // Get before context\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const mintWSqueethAmount = ethers.utils.parseUnits('15')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one)\n      const vaultBefore = await controller.vaults(vaultId)\n      const tokenIndexBefore = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n      const slot0 = await wSqueethPool.slot0()\n      const currentTick = slot0[1]\n      // Set up for mint\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n\n      // Closest 60 tick width above or below current tick (60 is minimum tick width for 30bps pool)\n\n      const newTickLower = isWethToken0 ? 60*((currentTick - currentTick%60)/60 - 2): 60*((currentTick - currentTick%60)/60 + 1)\n      const newTickUpper = isWethToken0 ? 60*((currentTick - currentTick%60)/60 - 1): 60*((currentTick - currentTick%60)/60 + 2)\n\n      const params = {\n        recipient: depositor.address,\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: vaultId,\n        wPowerPerpAmount: mintWSqueethAmount, \n        collateralToDeposit: collateralAmount,\n        collateralToLp: BigNumber.from(0),\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        lowerTick: newTickLower,\n        upperTick: newTickUpper\n      }\n      const tx = await controllerHelper.connect(depositor).wMintLp(params, {value: collateralAmount});\n\n\n      // Look at transaction\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n      // Get after context\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n      const vaultAfter = await controller.vaults(vaultId)\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(tokenId); \n      const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n  \n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: position.liquidity,\n        amount0Min: 0,\n        amount1Min: 0,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n\n      expect(position.tickLower === newTickLower).to.be.true\n      expect(position.tickUpper === newTickUpper).to.be.true\n      expect(ownerOfUniNFT === depositor.address).to.be.true\n      expect(tokenIndexAfter.sub(tokenIndexBefore).eq(BigNumber.from(1))).to.be.true\n      expect(vaultBefore.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultBefore.collateralAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(collateralAmount)).to.be.true\n      // One side LP - weth should be zero\n      expect(wPowerPerpAmountInLP.sub(mintWSqueethAmount).abs().lte(10)).to.be.true\n      expect(wethAmountInLP.eq(BigNumber.from(0))).to.be.true\n      //uniswap rounding of LP often gives some wei less than expected (uniswap takes the wei, but only gives credit for less wei in the LP share)\n      expect((depositorEthBalanceBefore.sub(depositorEthBalanceAfter).sub(collateralAmount).sub(wethAmountInLP).sub(gasSpent)).abs().lte(1)).to.be.true\n      expect((vaultAfter.shortAmount.sub(wPowerPerpAmountInLP)).abs().lte(1)).to.be.true\n  \n    })\n\n    it(\"Batch mint and LP - existing vault >0 LP collateral with >0 ETH collateral added, one sided LP with just weth\", async () => {\n\n      // Make empty vault\n      await controller.connect(depositor).mintWPowerPerpAmount(0, 0, 0, {value: 0})\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address)\n      // // Get before context\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      const collateralToLp = ethers.utils.parseUnits('15').mul(squeethPrice).div(one)\n      const vaultBefore = await controller.vaults(vaultId)\n      const tokenIndexBefore = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n      const slot0 = await wSqueethPool.slot0()\n      const currentTick = slot0[1]\n      // Set up for mint\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n\n      // Closest 60 tick width above or below current tick\n      const newTickLower = isWethToken0 ? 60*((currentTick - currentTick%60)/60 + 1): 60*((currentTick - currentTick%60)/60 - 2)\n      const newTickUpper = isWethToken0 ? 60*((currentTick - currentTick%60)/60 + 2): 60*((currentTick - currentTick%60)/60 - 1)\n      // Mint parameters for new tick\n      const params = {\n        recipient: depositor.address,\n        wPowerPerpPool: wSqueethPool.address,\n        vaultId: vaultId,\n        wPowerPerpAmount: BigNumber.from(0), \n        collateralToDeposit: BigNumber.from(0),\n        collateralToLp: collateralToLp,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        lowerTick: newTickLower,\n        upperTick: newTickUpper,\n      }\n\n      const tx = await controllerHelper.connect(depositor).wMintLp(params, {value: collateralToLp});\n      // Look at transaction\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n      // Get after context\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n      const vaultAfter = await controller.vaults(vaultId)\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(tokenId); \n      const position = await (positionManager as INonfungiblePositionManager).positions(tokenId)\n  \n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: position.liquidity,\n        amount0Min: 0,\n        amount1Min: 0,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n\n      // console.log('position.tickLower', position.tickLower)\n      // console.log('position.tickUpper', position.tickUpper)\n      // console.log('ownerOfUniNFT', ownerOfUniNFT)\n      // console.log('depositor.address', depositor.address)\n      // console.log('wPowerPerpAmountInLP',wPowerPerpAmountInLP)\n      // console.log('wethAmountInLP',wethAmountInLP)\n      // console.log('vaultBefore.shortAmount',vaultBefore.shortAmount)\n      // console.log('vaultBefore.collateralAmount',vaultBefore.collateralAmount)\n      // console.log('vaultAfter.shortAmount',vaultAfter.shortAmount)\n      // console.log('vaultAfter.collateralAmount',vaultAfter.collateralAmount)\n      // console.log('depositorEthBalanceBefore',depositorEthBalanceBefore)\n      // console.log('depositorEthBalanceAfter',depositorEthBalanceAfter)\n      // console.log('collateralAmount',collateralAmount)\n      // console.log('gasSpent',gasSpent)\n      // console.log('depositorEthBalanceAfter',depositorEthBalanceAfter)\n      // console.log('collateralToLp',collateralToLp)\n      // console.log('mintWSqueethAmount',mintWSqueethAmount)\n      // console.log('tokenIndexBefore',tokenIndexBefore)\n      // console.log('tokenIndexAfter',tokenIndexAfter)\n\n      expect(position.tickLower === newTickLower).to.be.true\n      expect(position.tickUpper === newTickUpper).to.be.true\n      expect(ownerOfUniNFT === depositor.address).to.be.true\n      expect(tokenIndexAfter.sub(tokenIndexBefore).eq(BigNumber.from(1))).to.be.true\n      expect(vaultBefore.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultBefore.collateralAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n      // One side LP - weth should be zero\n      expect(wethAmountInLP.sub(collateralToLp).abs().lte(10)).to.be.true\n      expect(wPowerPerpAmountInLP.eq(0)).to.be.true\n      expect((depositorEthBalanceBefore.sub(depositorEthBalanceAfter).sub(wethAmountInLP).sub(gasSpent)).abs().lte(1)).to.be.true\n      // expect(wethAmountInLP.sub(collateralToLp).mul(one).div(collateralToLp).eq(0)).to.be.true\n      expect(wethAmountInLP.sub(collateralToLp).abs().lte(10)).to.be.true\n    })\n\n  })\n\n  describe(\"Sell long and flash mint short\", async () => {\n    before(async () => {\n      let normFactor = await controller.normalizationFactor()\n      let mintWSqueethAmount = ethers.utils.parseUnits('10')\n      let mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      let ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      let scaledEthPrice = ethPrice.div(10000)\n      let debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      let collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n      expect((await wSqueeth.balanceOf(depositor.address)).gte(mintWSqueethAmount)).to.be.true\n\n      // minting mintWSqueethAmount to a tester address to get later how much should ETH to get for flahswap mintWSqueethAmount\n      normFactor = await controller.normalizationFactor()\n      mintWSqueethAmount = ethers.utils.parseUnits('150')\n      mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      scaledEthPrice = ethPrice.div(10000)\n      debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      await controller.connect(tester).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n      expect((await wSqueeth.balanceOf(tester.address)).gte(mintWSqueethAmount)).to.be.true\n    })\n\n    it(\"Sell long and flashswap mint short positon where a refund of ETH due\", async () => {\n      const longBalance = await wSqueeth.balanceOf(depositor.address);\n      const normFactor = await controller.normalizationFactor()\n      // this account has a large oSQTH position, so need to \n      const mintWSqueethAmount = ethers.utils.parseUnits('10')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const totalSqueethToSell = longBalance.add(mintWSqueethAmount)\n      const swapParam = {\n        tokenIn: wSqueeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        amountIn: totalSqueethToSell,\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0\n      }    \n \n      await wSqueeth.connect(tester).approve(swapRouter.address, constants.MaxUint256)\n      const ethAmountOutFromFlashSwap = await swapRouter.connect(tester).callStatic.exactInputSingle(swapParam)\n\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const value = collateralAmount.sub(ethAmountOutFromFlashSwap.mul(one.sub(slippage)).div(one))\n\n      const params = {\n        vaultId: 0,\n        wPowerPerpAmountToMint: mintWSqueethAmount,\n        collateralToDeposit: collateralAmount,\n        wPowerPerpAmountToSell: longBalance,\n        minToReceive: BigNumber.from(0),\n        poolFee: 3000\n      }\n      await wSqueeth.connect(depositor).approve(controllerHelper.address, longBalance)\n\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n      const tx = await controllerHelper.connect(depositor).flashswapSellLongWMint(params)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      // this was looking at a previous vault and was incorrect, updating the vault id here fixes it (or remove the sub(1) and keep it earlier)\n      const vaultAfter = await controller.vaults(vaultId)\n\n      expect((await wSqueeth.balanceOf(depositor.address)).eq(BigNumber.from(0))).to.be.true;\n      expect(vaultAfter.shortAmount.eq(mintWSqueethAmount)).to.be.true\n      expect(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).eq(ethAmountOutFromFlashSwap.sub(collateralAmount).sub(gasSpent))).to.be.true\n    })\n\n\n\n  })\n\n  describe(\"Sell long and flash mint short\", async () => {\n    before(async () => {\n      let normFactor = await controller.normalizationFactor()\n      let mintWSqueethAmount = ethers.utils.parseUnits('10')\n      let mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      let ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      let scaledEthPrice = ethPrice.div(10000)\n      let debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      let collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n      expect((await wSqueeth.balanceOf(depositor.address)).gte(mintWSqueethAmount)).to.be.true\n\n      // minting mintWSqueethAmount to a tester address to get later how much should ETH to get for flahswap mintWSqueethAmount\n      normFactor = await controller.normalizationFactor()\n      mintWSqueethAmount = ethers.utils.parseUnits('150')\n      mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      scaledEthPrice = ethPrice.div(10000)\n      debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      await controller.connect(tester).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n      expect((await wSqueeth.balanceOf(tester.address)).gte(mintWSqueethAmount)).to.be.true\n    })\n\n    it(\"Sell long and flash mint short with excess eth needed to attach\", async () => {\n      const longBalance = await wSqueeth.balanceOf(depositor.address);\n      const normFactor = await controller.normalizationFactor()\n      // this account has a large oSQTH position, so need to \n      const mintWSqueethAmount = ethers.utils.parseUnits('90')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const totalSqueethToSell = longBalance.add(mintWSqueethAmount)\n      const swapParam = {\n        tokenIn: wSqueeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        amountIn: totalSqueethToSell,\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0\n      }    \n \n      await wSqueeth.connect(tester).approve(swapRouter.address, constants.MaxUint256)\n      const ethAmountOutFromFlashSwap = await swapRouter.connect(tester).callStatic.exactInputSingle(swapParam)\n\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const value = collateralAmount.sub(ethAmountOutFromFlashSwap.mul(one.sub(slippage)).div(one))\n            \n      const params = {\n        vaultId: 0,\n        wPowerPerpAmountToMint: mintWSqueethAmount,\n        collateralToDeposit: collateralAmount,\n        wPowerPerpAmountToSell: longBalance,\n        minToReceive: BigNumber.from(0),\n        poolFee: 3000\n      }\n      await wSqueeth.connect(depositor).approve(controllerHelper.address, longBalance)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n      const tx = await controllerHelper.connect(depositor).flashswapSellLongWMint(params, {value: value})\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      // this was looking at a previous vault and was incorrect, updating the vault id here fixes it (or remove the sub(1) and keep it earlier)\n      const vaultAfter = await controller.vaults(vaultId)\n\n      expect((await wSqueeth.balanceOf(depositor.address)).eq(BigNumber.from(0))).to.be.true;\n      expect(vaultAfter.shortAmount.eq(mintWSqueethAmount)).to.be.true      \n      expect(depositorEthBalanceBefore.sub(depositorEthBalanceAfter).eq(gasSpent.add(collateralAmount.sub(ethAmountOutFromFlashSwap)))).to.be.true\n    })\n\n\n\n  })\n\n  describe(\"Close position with user wallet NFT: LP wPowerPerp amount is less than vault short amount\", async () => {\n    let tokenId: BigNumber;\n    let mintWSqueethAmount : BigNumber = ethers.utils.parseUnits('10')\n\n    before(\"open short and LP\" , async () => {\n      const normFactor = await controller.normalizationFactor()\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      // doing this way explicitly forces us to LP with less than the vault balance \n      // before it was just using the exact amount = the vault debt and probably passing because of rounding?\n      // alternatively could be done like the next test where we create a new vault that we close against\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one).div(2)\n      const wSqueethToLp = mintWSqueethAmount.div(2)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n  \n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : wSqueethToLp,\n        amount1Desired: isWethToken0 ? wSqueethToLp : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n  \n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      const tx = await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n      const receipt = await tx.wait();\n      tokenId = (receipt.events?.find(event => event.event === 'IncreaseLiquidity'))?.args?.tokenId;  \n    })\n\n    it(\"Close position with NFT from user\", async () => {\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const vaultBefore = await controller.vaults(vaultId)\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n      const liquidityPercentage = BigNumber.from(1).mul(BigNumber.from(10).pow(18))\n\n      const wPowerPerpAmountToWithdraw = wPowerPerpAmountInLP.mul(liquidityPercentage).div(one)\n      const wethAmountToWithdraw = wethAmountInLP.mul(liquidityPercentage).div(one)\n\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.add(slippage)).div(one);\n\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address);\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controllerHelper.address, tokenId); \n      await controllerHelper.connect(depositor).closeShortWithUserNft({\n        vaultId, \n        tokenId,\n        liquidity: positionBefore.liquidity,\n        liquidityPercentage: liquidityPercentage,\n        wPowerPerpAmountToBurn: mintWSqueethAmount, \n        collateralToWithdraw: vaultBefore.collateralAmount, \n        limitPriceEthPerPowerPerp,\n        amount0Min: BigNumber.from(0), \n        amount1Min:BigNumber.from(0),\n        burnExactRemoved: false,\n        poolFee: 3000\n      })\n\n      const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n      const vaultAfter = await controller.vaults(vaultId);\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(positionAfter.liquidity.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n\n      if(wPowerPerpAmountToWithdraw.lt(mintWSqueethAmount)) {\n        const ethToBuySqueeth = (mintWSqueethAmount.sub(wPowerPerpAmountToWithdraw)).mul(squeethPrice).div(one); \n        const remainingETHFromLp = wethAmountToWithdraw.sub(ethToBuySqueeth);\n        //might be good to check actual slippage here instead of <= 0.01, which is kinda arbitrary, but i tried doing it and its hard because need to simulate two transactions remove liquidity + swap\n        // can do by simulating the swap before adding liquidity as I do later, but haven't implemented it for now\n        expect(Number(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).sub(vaultBefore.collateralAmount.add(remainingETHFromLp)).div(one).toString()) <= 0.01).to.be.true\n      }\n      else if (wPowerPerpAmountToWithdraw.gt(mintWSqueethAmount)) {\n        const wPowerPerpAmountToSell = wPowerPerpAmountToWithdraw.sub(mintWSqueethAmount);\n        const ethToGet = wPowerPerpAmountToSell.mul(squeethPrice).div(one);\n\n        expect(Number(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).sub(vaultBefore.collateralAmount.add(ethToGet).add(wethAmountToWithdraw)).div(one).toString()) <= 0.01).to.be.true\n      }\n    })\n  })\n\n  describe(\"Close position with user wallet NFT: LP wPowerPerp amount is less than vault short amount and burn only the exact amount (so only partially closes and doesnt trade)\", async () => {\n    let tokenId: BigNumber;\n    let mintWSqueethAmount : BigNumber = ethers.utils.parseUnits('10')\n\n    before(\"open short and LP\" , async () => {\n      const normFactor = await controller.normalizationFactor()\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      // doing this way explicitly forces us to LP with less than the vault balance \n      // before it was just using the exact amount = the vault debt and probably passing because of rounding?\n      // alternatively could be done like the next test where we create a new vault that we close against\n      const collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one).div(2)\n      const wSqueethToLp = mintWSqueethAmount.div(2)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n  \n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : wSqueethToLp,\n        amount1Desired: isWethToken0 ? wSqueethToLp : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n  \n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      const tx = await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n      const receipt = await tx.wait();\n      tokenId = (receipt.events?.find(event => event.event === 'IncreaseLiquidity'))?.args?.tokenId;  \n    })\n\n    it(\"Close position with NFT from user, burning the exact oSQTH removed\", async () => {\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const vaultBefore = await controller.vaults(vaultId)\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n      const liquidityPercentage = BigNumber.from(1).mul(BigNumber.from(10).pow(18))\n\n      const wPowerPerpAmountToWithdraw = wPowerPerpAmountInLP.mul(liquidityPercentage).div(one)\n      const wethAmountToWithdraw = wethAmountInLP.mul(liquidityPercentage).div(one)\n\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.add(slippage)).div(one);\n\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address);\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controllerHelper.address, tokenId); \n\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      const tx = await controllerHelper.connect(depositor).closeShortWithUserNft({\n        vaultId, \n        tokenId,\n        liquidity: positionBefore.liquidity,\n        liquidityPercentage: liquidityPercentage,\n        wPowerPerpAmountToBurn: BigNumber.from(0), \n        collateralToWithdraw: BigNumber.from(0), \n        limitPriceEthPerPowerPerp,\n        amount0Min: BigNumber.from(0), \n        amount1Min:BigNumber.from(0),\n        burnExactRemoved: true,\n        poolFee: 3000\n      })\n\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n      const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n      const vaultAfter = await controller.vaults(vaultId);\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n      const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n\n      expect(positionAfter.liquidity.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.shortAmount.eq(vaultBefore.shortAmount.sub(wPowerPerpAmountInLP))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(vaultBefore.collateralAmount)).to.be.true\n      expect(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).eq(wethAmountInLP.sub(gasSpent))).to.be.true\n      expect(depositorSqueethBalanceAfter.eq(depositorSqueethBalanceBefore)).to.be.true\n    })\n  })\n\n  describe(\"Close second position with user wallet NFT from 1st short: (remove 100% liquidity) LP wPowerPerp amount is more than vault short amount\", async () => {\n    let tokenId: BigNumber;\n    let mintWSqueethAmount: BigNumber;\n\n    before(\"open first short position and LP\" , async () => {\n      const normFactor = await controller.normalizationFactor()\n      const mintWSqueethAmountToLp : BigNumber = ethers.utils.parseUnits('20')\n      const mintRSqueethAmount = mintWSqueethAmountToLp.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const collateralToLp = mintWSqueethAmountToLp.mul(squeethPrice).div(one)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmountToLp, 0, {value: collateralAmount})\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n\n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : mintWSqueethAmountToLp,\n        amount1Desired: isWethToken0 ? mintWSqueethAmountToLp : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n\n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      const tx = await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n      const receipt = await tx.wait();\n      tokenId = (receipt.events?.find(event => event.event === 'IncreaseLiquidity'))?.args?.tokenId;  \n    })\n\n    before(\"open short amount less than amount in LP position\" , async () => {\n      const normFactor = await controller.normalizationFactor()\n      mintWSqueethAmount = ethers.utils.parseUnits('10')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n    })\n\n    it(\"Close position with NFT from user\", async () => {\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const vaultBefore = await controller.vaults(vaultId)\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n      const liquidityPercentage = BigNumber.from(1).mul(BigNumber.from(10).pow(18))\n\n      const wPowerPerpAmountToWithdraw = wPowerPerpAmountInLP.mul(liquidityPercentage).div(one)\n      const wethAmountToWithdraw = wethAmountInLP.mul(liquidityPercentage).div(one)\n      \n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.sub(slippage)).div(one);\n\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address);\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controllerHelper.address, tokenId); \n      await controllerHelper.connect(depositor).closeShortWithUserNft({\n        vaultId, \n        tokenId,\n        liquidity: positionBefore.liquidity,\n        liquidityPercentage: liquidityPercentage,\n        wPowerPerpAmountToBurn: mintWSqueethAmount, \n        collateralToWithdraw: vaultBefore.collateralAmount, \n        limitPriceEthPerPowerPerp, \n        amount0Min: BigNumber.from(0), \n        amount1Min:BigNumber.from(0),\n        burnExactRemoved: false,\n        poolFee: 3000\n      })\n\n      const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n      const vaultAfter = await controller.vaults(vaultId);\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(positionAfter.liquidity.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n\n      if(wPowerPerpAmountToWithdraw.lt(mintWSqueethAmount)) {\n        const ethToBuySqueeth = (mintWSqueethAmount.sub(wPowerPerpAmountToWithdraw)).mul(squeethPrice).div(one); \n        const remainingETHFromLp = wethAmountToWithdraw.sub(ethToBuySqueeth);\n\n        expect(Number(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).sub(vaultBefore.collateralAmount.add(remainingETHFromLp)).div(one).toString()) <= 0.01).to.be.true\n      }\n      else if (wPowerPerpAmountToWithdraw.gt(mintWSqueethAmount)) {\n        const wPowerPerpAmountToSell = wPowerPerpAmountToWithdraw.sub(mintWSqueethAmount);\n        const ethToGet = wPowerPerpAmountToSell.mul(squeethPrice).div(one);\n\n        expect(Number(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).sub(vaultBefore.collateralAmount.add(ethToGet).add(wethAmountToWithdraw)).div(one).toString()) <= 0.01).to.be.true\n      }\n\n    })\n  })\n\n  describe(\"Close second position with user wallet NFT from 1st short: (remove 100% liquidity) LP wPowerPerp amount is more than vault short amount, but flag burning exact removed, which shouldn't trade\", async () => {\n    let tokenId: BigNumber;\n    let mintWSqueethAmount: BigNumber;\n\n    before(\"open first short position and LP\" , async () => {\n      const normFactor = await controller.normalizationFactor()\n      const mintWSqueethAmountToLp : BigNumber = ethers.utils.parseUnits('20')\n      const mintRSqueethAmount = mintWSqueethAmountToLp.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const collateralToLp = mintWSqueethAmountToLp.mul(squeethPrice).div(one)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmountToLp, 0, {value: collateralAmount})\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n\n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : mintWSqueethAmountToLp,\n        amount1Desired: isWethToken0 ? mintWSqueethAmountToLp : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n\n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      const tx = await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n      const receipt = await tx.wait();\n      tokenId = (receipt.events?.find(event => event.event === 'IncreaseLiquidity'))?.args?.tokenId;  \n    })\n\n    before(\"open short amount equal to amount in LP position\" , async () => {\n      const normFactor = await controller.normalizationFactor()\n      mintWSqueethAmount = ethers.utils.parseUnits('20')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n    })\n\n    it(\"Close position with NFT from user\", async () => {\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const vaultBefore = await controller.vaults(vaultId)\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n      const liquidityPercentage = BigNumber.from(1).mul(BigNumber.from(10).pow(18))\n\n      const wPowerPerpAmountToWithdraw = wPowerPerpAmountInLP.mul(liquidityPercentage).div(one)\n      const wethAmountToWithdraw = wethAmountInLP.mul(liquidityPercentage).div(one)\n      \n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.sub(slippage)).div(one);\n\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address);\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controllerHelper.address, tokenId);\n      \n      const tx = await controllerHelper.connect(depositor).closeShortWithUserNft({\n        vaultId, \n        tokenId,\n        liquidity: positionBefore.liquidity,\n        liquidityPercentage: liquidityPercentage,\n        wPowerPerpAmountToBurn: mintWSqueethAmount, \n        collateralToWithdraw: BigNumber.from(0), \n        limitPriceEthPerPowerPerp: limitPriceEthPerPowerPerp, \n        amount0Min: BigNumber.from(0), \n        amount1Min:BigNumber.from(0),\n        burnExactRemoved: true,\n        poolFee: 3000\n      })\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n      // State after\n      const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n      const vaultAfter = await controller.vaults(vaultId);\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n      const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n      expect(positionAfter.liquidity.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.shortAmount.abs().lte(10)).to.be.true\n      expect(vaultAfter.collateralAmount.eq(vaultBefore.collateralAmount)).to.be.true\n      expect((depositorEthDiff.sub(wethAmountInLP).add(gasSpent)).abs().lte(ethers.utils.parseUnits('0.01'))).to.be.true\n    })\n  })\n\n  describe(\"Close second position with user wallet NFT from 1st short: (remove 60% liquidity) LP wPowerPerp amount is more than vault short amount\", async () => {\n    let tokenId: BigNumber;\n    let mintWSqueethAmount: BigNumber;\n\n    before(\"open first short position and LP\" , async () => {\n      const normFactor = await controller.normalizationFactor()\n      const mintWSqueethAmountToLp : BigNumber = ethers.utils.parseUnits('20')\n      const mintRSqueethAmount = mintWSqueethAmountToLp.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const collateralToLp = mintWSqueethAmountToLp.mul(squeethPrice).div(one)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmountToLp, 0, {value: collateralAmount})\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n\n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : mintWSqueethAmountToLp,\n        amount1Desired: isWethToken0 ? mintWSqueethAmountToLp : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n\n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      const tx = await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n      const receipt = await tx.wait();\n      tokenId = (receipt.events?.find(event => event.event === 'IncreaseLiquidity'))?.args?.tokenId;  \n    })\n\n    before(\"open short amount less than amount in LP position\" , async () => {\n      const normFactor = await controller.normalizationFactor()\n      mintWSqueethAmount = ethers.utils.parseUnits('10')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n    })\n\n    it(\"Close position with NFT from user\", async () => {\n      const vaultId = (await shortSqueeth.nextId()).sub(1);\n      const vaultBefore = await controller.vaults(vaultId)\n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n      const liquidityPercentage = BigNumber.from(6).mul(BigNumber.from(10).pow(17))\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n\n      const wPowerPerpAmountToWithdraw = wPowerPerpAmountInLP.mul(liquidityPercentage).div(one)\n      const wethAmountToWithdraw = wethAmountInLP.mul(liquidityPercentage).div(one)\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.sub(slippage)).div(one);\n\n      await controller.connect(depositor).updateOperator(vaultId, controllerHelper.address);\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controllerHelper.address, tokenId); \n      \n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n      await controllerHelper.connect(depositor).closeShortWithUserNft({\n        vaultId, \n        tokenId,\n        liquidity: positionBefore.liquidity,\n        liquidityPercentage: liquidityPercentage,\n        wPowerPerpAmountToBurn: mintWSqueethAmount, \n        collateralToWithdraw: vaultBefore.collateralAmount, \n        limitPriceEthPerPowerPerp, \n        amount0Min: BigNumber.from(0), \n        amount1Min:BigNumber.from(0),\n        burnExactRemoved: false,\n        poolFee: 3000\n      })\n\n      const positionAfter = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n      const vaultAfter = await controller.vaults(vaultId);\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(positionAfter.liquidity.sub(positionBefore.liquidity.div(2)).lte(1)).to.be.true\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true\n      \n      if(wPowerPerpAmountToWithdraw.lt(mintWSqueethAmount)) {\n        const ethToBuySqueeth = (mintWSqueethAmount.sub(wPowerPerpAmountToWithdraw)).mul(squeethPrice).div(one); \n        const remainingETHFromLp = wethAmountToWithdraw.sub(ethToBuySqueeth);\n\n        expect(Number(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).sub(vaultBefore.collateralAmount.add(remainingETHFromLp)).div(one).toString()) <= 0.01).to.be.true\n      }\n      else if (wPowerPerpAmountToWithdraw.gt(mintWSqueethAmount)) {\n        const wPowerPerpAmountToSell = wPowerPerpAmountToWithdraw.sub(mintWSqueethAmount);\n        const ethToGet = wPowerPerpAmountToSell.mul(squeethPrice).div(one);\n\n        expect(Number(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).sub(vaultBefore.collateralAmount.add(ethToGet).add(wethAmountToWithdraw)).div(one).toString()) <= 0.01).to.be.true\n      }\n\n    })\n  })\n\n  describe(\"Withdraw to ETH\", async () => {\n    let collateralToLp: BigNumber;\n    let mintWSqueethAmount: BigNumber;\n    let ethAmountOut: BigNumber;\n\n    before(\"open position and LP\", async () => {\n      const normFactor = await controller.normalizationFactor()\n      mintWSqueethAmount = ethers.utils.parseUnits('35')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      // we do this to ensure we use the maximum wSqueethAmount for LPing, which makes the expect statements easier\n      collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one).mul(2)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n  \n      await controller.connect(owner).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n\n      const swapParam = {\n        tokenIn: wSqueeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        amountIn: mintWSqueethAmount,\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0\n      }    \n      await wSqueeth.connect(owner).approve(swapRouter.address, constants.MaxUint256)\n      ethAmountOut = await swapRouter.connect(owner).callStatic.exactInputSingle(swapParam)\n\n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : mintWSqueethAmount,\n        amount1Desired: isWethToken0 ? mintWSqueethAmount : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n  \n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n    })\n\n    it(\"sell all to ETH\", async () => {\n      const tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.sub(slippage)).div(one);\n      const params = {\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        liquidityPercentage: BigNumber.from(1).mul(BigNumber.from(10).pow(18)),\n        amount0Min: 0,\n        amount1Min: 0,\n        limitPriceEthPerPowerPerp: limitPriceEthPerPowerPerp,\n        poolFee: 3000\n      }\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controllerHelper.address, tokenId);\n\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const tx = await controllerHelper.connect(depositor).reduceLiquidityAndSell(params);\n\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n      const depositorEthBalanceAfter= await provider.getBalance(depositor.address)\n\n      // 1 wei difference due to uniswap rounding\n      expect(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).add(gasSpent).sub(wethAmountInLP.add(ethAmountOut)).abs().lte(1)).to.be.true\n    })\n  })\n\n  describe(\"Rebalance LP through trading amounts\", async () => {\n    let collateralToLp: BigNumber;\n    let mintWSqueethAmount: BigNumber;\n    let squeethAmountOut: BigNumber;\n\n    before(\"open position and LP\", async () => {\n      const normFactor = await controller.normalizationFactor()\n      mintWSqueethAmount = ethers.utils.parseUnits('35')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      // we want to LP with all of the ETH collateral which can be guaranteed by using less vs what is expected\n      collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one).mul(4).div(5)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n\n      await weth.connect(owner).deposit({value: collateralToLp})\n\n      const swapParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        amountIn: collateralToLp,\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0\n      }    \n      await weth.connect(owner).approve(swapRouter.address, constants.MaxUint256)\n      squeethAmountOut = await swapRouter.connect(owner).callStatic.exactInputSingle(swapParam)\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n  \n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : mintWSqueethAmount,\n        amount1Desired: isWethToken0 ? mintWSqueethAmount : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n  \n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n    })\n\n    it(\"rebalance to decrease WETH amount and LP only oSQTH\", async () => {\n      let tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const oldTokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const oldPosition = await (positionManager as INonfungiblePositionManager).positions(oldTokenId);\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.add(slippage)).div(one);\n\n      const slot0 = await wSqueethPool.slot0()\n      const currentTick = slot0[1]\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n\n      const newTick = isWethToken0 ? 60*((currentTick - currentTick%60)/60 - 1): 60*((currentTick - currentTick%60)/60 + 1)\n\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n      //uniswap LPing often will give 1 wei less than expected, with the price of oSQTH need to do more than 1 wei due to rounding up the amount owed \n      const wPowerPerpDesired = wPowerPerpAmountInLP.sub(10).add(squeethAmountOut)\n\n      const params = {\n        wPowerPerpPool: wSqueethPool.address,\n        tokenId: oldTokenId,\n        ethAmountToLp: BigNumber.from(0),\n        liquidity: oldPosition.liquidity,\n        wPowerPerpAmountDesired: wPowerPerpDesired,\n        wethAmountDesired: ethers.utils.parseUnits('0'),\n        amount0DesiredMin: BigNumber.from(0),\n        amount1DesiredMin: BigNumber.from(0),\n        limitPriceEthPerPowerPerp,\n        amount0Min: BigNumber.from(0),\n        amount1Min: BigNumber.from(0),\n        lowerTick: isWethToken0 ? -887220 : newTick,\n        upperTick: isWethToken0 ? newTick : 887220,\n        poolFee: 3000\n      }\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controllerHelper.address, oldTokenId);\n      await controllerHelper.connect(depositor).rebalanceLpWithoutVault(params);\n\n      tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const newTokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const newPosition = await (positionManager as INonfungiblePositionManager).positions(newTokenId);\n      const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(newTokenId); \n\n      const [amount0New, amount1New] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: newTokenId,\n        liquidity: newPosition.liquidity,\n        amount0Min: BigNumber.from(0),\n        amount1Min: BigNumber.from(0),\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n\n      const wPowerPerpAmountInNewLp = (isWethToken0) ? amount1New : amount0New;\n      const wethAmountInNewLp = (isWethToken0) ? amount0New : amount1New;\n\n      expect(ownerOfUniNFT === depositor.address).to.be.true;\n      expect(wPowerPerpAmountInNewLp.sub(wPowerPerpDesired).lte(10)).to.be.true\n      expect(wethAmountInNewLp.eq(BigNumber.from(0))).to.be.true\n    })\n\n\n  })\n\n\n  describe(\"Rebalance LP through trading amounts (amount desired less than amount in LP)\", async () => {\n    let collateralToLp: BigNumber;\n    let mintWSqueethAmount: BigNumber;\n    let squeethAmountOut: BigNumber;\n\n    before(\"open position and LP\", async () => {\n      const normFactor = await controller.normalizationFactor()\n      mintWSqueethAmount = ethers.utils.parseUnits('35')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      // we want to LP with all of the ETH collateral which can be guaranteed by using less vs what is expected\n      collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one).mul(4).div(5)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n\n      await weth.connect(owner).deposit({value: collateralToLp})\n\n      const swapParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        amountIn: collateralToLp,\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0\n      }    \n      await weth.connect(owner).approve(swapRouter.address, constants.MaxUint256)\n      squeethAmountOut = await swapRouter.connect(owner).callStatic.exactInputSingle(swapParam)\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n  \n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : mintWSqueethAmount,\n        amount1Desired: isWethToken0 ? mintWSqueethAmount : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n  \n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n    })\n\n    it(\"rebalance to decrease WETH amount and LP only oSQTH (amount desired < amount in LP)\", async () => {\n      let tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const oldTokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const oldPosition = await (positionManager as INonfungiblePositionManager).positions(oldTokenId);\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.add(slippage)).div(one);\n\n      const slot0 = await wSqueethPool.slot0()\n      const currentTick = slot0[1]\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n\n      const newTick = isWethToken0 ? 60*((currentTick - currentTick%60)/60 - 10): 60*((currentTick - currentTick%60)/60 + 10)\n\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n      //uniswap LPing often will give 1 wei less than expected, with the price of oSQTH need to do more than 1 wei due to rounding up the amount owed \n      const wPowerPerpDesired = wPowerPerpAmountInLP.sub(ethers.utils.parseUnits('0.01'))\n\n      const params = {\n        wPowerPerpPool: wSqueethPool.address,\n        tokenId: oldTokenId,\n        ethAmountToLp: BigNumber.from(0),\n        liquidity: oldPosition.liquidity,\n        wPowerPerpAmountDesired: wPowerPerpDesired,\n        wethAmountDesired: ethers.utils.parseUnits('0'),\n        amount0DesiredMin: BigNumber.from(0),\n        amount1DesiredMin: BigNumber.from(0),\n        limitPriceEthPerPowerPerp: BigNumber.from(0),\n        amount0Min: BigNumber.from(0),\n        amount1Min: BigNumber.from(0),\n        lowerTick: isWethToken0 ? -887220 : newTick,\n        upperTick: isWethToken0 ? newTick : 887220,\n        poolFee: 3000\n      }\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controllerHelper.address, oldTokenId);\n      await controllerHelper.connect(depositor).rebalanceLpWithoutVault(params);\n\n      tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const newTokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const newPosition = await (positionManager as INonfungiblePositionManager).positions(newTokenId);\n      const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(newTokenId); \n\n      const [amount0New, amount1New] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: newTokenId,\n        liquidity: newPosition.liquidity,\n        amount0Min: BigNumber.from(0),\n        amount1Min: BigNumber.from(0),\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n\n      const wPowerPerpAmountInNewLp = (isWethToken0) ? amount1New : amount0New;\n      const wethAmountInNewLp = (isWethToken0) ? amount0New : amount1New;\n\n      expect(ownerOfUniNFT === depositor.address).to.be.true;\n      expect(wPowerPerpAmountInNewLp.sub(wPowerPerpDesired).lte(10)).to.be.true\n      expect(wethAmountInNewLp.eq(BigNumber.from(0))).to.be.true\n    })\n\n\n  })\n\n\n  describe(\"Rebalance LP through trading amounts (amount desired less than amount in LP)\", async () => {\n    let collateralToLp: BigNumber;\n    let mintWSqueethAmount: BigNumber;\n    let squeethAmountOut: BigNumber;\n\n    before(\"open position and LP\", async () => {\n      const normFactor = await controller.normalizationFactor()\n      mintWSqueethAmount = ethers.utils.parseUnits('35')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      // we want to LP with all of the ETH collateral which can be guaranteed by using less vs what is expected\n      collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one).mul(4).div(5)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n\n      await weth.connect(owner).deposit({value: collateralToLp})\n\n      const swapParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        amountIn: collateralToLp,\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0\n      }    \n      await weth.connect(owner).approve(swapRouter.address, constants.MaxUint256)\n      squeethAmountOut = await swapRouter.connect(owner).callStatic.exactInputSingle(swapParam)\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n  \n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : mintWSqueethAmount,\n        amount1Desired: isWethToken0 ? mintWSqueethAmount : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n  \n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n    })\n\n    it(\"rebalance to decrease WETH amount and LP only oSQTH (amount desired < amount in LP)\", async () => {\n      let tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const oldTokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const oldPosition = await (positionManager as INonfungiblePositionManager).positions(oldTokenId);\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.add(slippage)).div(one);\n\n      const slot0 = await wSqueethPool.slot0()\n      const currentTick = slot0[1]\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n\n      const newTick = isWethToken0 ? 60*((currentTick - currentTick%60)/60 - 10): 60*((currentTick - currentTick%60)/60 + 10)\n\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n      const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n      const wPowerPerpAmountInLP = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLP = (isWethToken0) ? amount0 : amount1;\n      // uniswap LPing often will give 1 wei less than expected, with the price of oSQTH need to do more than 1 wei due to rounding up the amount owed \n      const wPowerPerpDesired = wPowerPerpAmountInLP.sub(ethers.utils.parseUnits('0.01'))\n      // weth needed to by additional oSQTH\n      const wethAmountOut = await quoter.connect(tester).callStatic.quoteExactInputSingle(wSqueeth.address,\n        weth.address,\n        3000,\n        wPowerPerpAmountInLP.sub(wPowerPerpDesired),\n        0)\n      const params = {\n        wPowerPerpPool: wSqueethPool.address,\n        tokenId: oldTokenId,\n        ethAmountToLp: BigNumber.from(0),\n        liquidity: oldPosition.liquidity,\n        wPowerPerpAmountDesired: wPowerPerpDesired,\n        wethAmountDesired: ethers.utils.parseUnits('0'),\n        amount0DesiredMin: BigNumber.from(0),\n        amount1DesiredMin: BigNumber.from(0),\n        limitPriceEthPerPowerPerp: BigNumber.from(0),\n        amount0Min: BigNumber.from(0),\n        amount1Min: BigNumber.from(0),\n        lowerTick: isWethToken0 ? -887220 : newTick,\n        upperTick: isWethToken0 ? newTick : 887220,\n        poolFee: 3000\n      }\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controllerHelper.address, oldTokenId);\n      const tx = await  controllerHelper.connect(depositor).rebalanceLpWithoutVault(params);\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n      tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const newTokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const newPosition = await (positionManager as INonfungiblePositionManager).positions(newTokenId);\n      const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(newTokenId); \n\n      const [amount0New, amount1New] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: newTokenId,\n        liquidity: newPosition.liquidity,\n        amount0Min: BigNumber.from(0),\n        amount1Min: BigNumber.from(0),\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n\n      const wPowerPerpAmountInNewLp = (isWethToken0) ? amount1New : amount0New;\n      const wethAmountInNewLp = (isWethToken0) ? amount0New : amount1New;\n      const depositorEthBalanceAfter = await ethers.provider.getBalance(depositor.address)\n      // Changes\n      const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n      expect(ownerOfUniNFT === depositor.address).to.be.true;\n      expect(wPowerPerpAmountInNewLp.sub(wPowerPerpDesired).lte(10)).to.be.true\n      expect(wethAmountInNewLp.eq(BigNumber.from(0))).to.be.true\n      expect(wethAmountInLP.add(wethAmountOut).sub(gasSpent).sub(depositorEthDiff).lte(ethers.utils.parseUnits('0.01'))).to.be.true\n    })\n\n\n  })\n\n  describe(\"Rebalance LP through trading amounts (swap excess squeeth)\", async () => {\n    let collateralToLp: BigNumber;\n    let mintWSqueethAmount: BigNumber;\n    let squeethAmountOut: BigNumber;\n\n    before(\"open position and LP\", async () => {\n      const normFactor = await controller.normalizationFactor()\n      mintWSqueethAmount = ethers.utils.parseUnits('35')\n      const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n      const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n      const scaledEthPrice = ethPrice.div(10000)\n      const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n      const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n      // we want to LP with all of the ETH collateral which can be guaranteed by using less vs what is expected\n      collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one).mul(4).div(5)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n\n      await weth.connect(owner).deposit({value: collateralToLp})\n\n      const swapParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        amountIn: collateralToLp,\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0\n      }    \n      await weth.connect(owner).approve(swapRouter.address, constants.MaxUint256)\n      squeethAmountOut = await swapRouter.connect(owner).callStatic.exactInputSingle(swapParam)\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const token0 = isWethToken0 ? weth.address : wSqueeth.address\n      const token1 = isWethToken0 ? wSqueeth.address : weth.address\n  \n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? collateralToLp : mintWSqueethAmount,\n        amount1Desired: isWethToken0 ? mintWSqueethAmount : collateralToLp,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: depositor.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n  \n      await weth.connect(depositor).deposit({value: collateralToLp})\n      await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n      await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n      await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n    })\n\n\n    it(\"rebalance to only eth (sell excess oSQTH)\", async () => {\n      let tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const oldTokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const oldPosition = await (positionManager as INonfungiblePositionManager).positions(oldTokenId);\n      const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n      const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n      const limitPriceEthPerPowerPerp = squeethPrice.mul(one.add(slippage)).div(one);\n\n      const slot0 = await wSqueethPool.slot0()\n      const currentTick = slot0[1]\n\n      const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n      const amount0Min = BigNumber.from(0);\n      const amount1Min = BigNumber.from(0);\n\n      const newTick = isWethToken0 ? 60*((currentTick - currentTick%60)/60 - 1): 60*((currentTick - currentTick%60)/60 + 1)\n\n      const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n      const depositorEthBalanceBefore = await ethers.provider.getBalance(depositor.address)\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n      const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: tokenId,\n        liquidity: positionBefore.liquidity,\n        amount0Min: amount0Min,\n        amount1Min: amount1Min,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n  })\n      const wPowerPerpAmountInLp = (isWethToken0) ? amount1 : amount0;\n      const wethAmountInLp = (isWethToken0) ? amount0 : amount1;\n      //uniswap LPing often will give 1 wei less than expected, with the price of oSQTH need to do more than 1 wei due to rounding up the amount owed \n      const wPowerPerpDesired = wPowerPerpAmountInLp.div(2)\n\n      // Proceeds of sale of LP wPowerPerp\n      const wethAmountOut = await quoter.connect(tester).callStatic.quoteExactInputSingle(wSqueeth.address,\n        weth.address,\n        3000,\n        wPowerPerpAmountInLp.sub(wPowerPerpDesired),\n        0)\n\n      const params = {\n        wPowerPerpPool: wSqueethPool.address,\n        tokenId: oldTokenId,\n        ethAmountToLp: BigNumber.from(0),\n        liquidity: oldPosition.liquidity,\n        wPowerPerpAmountDesired: wPowerPerpDesired,\n        wethAmountDesired: ethers.utils.parseUnits('0'),\n        amount0DesiredMin: BigNumber.from(0),\n        amount1DesiredMin: BigNumber.from(0),\n        limitPriceEthPerPowerPerp: BigNumber.from(0),\n        amount0Min: BigNumber.from(0),\n        amount1Min: BigNumber.from(0),\n        lowerTick: isWethToken0 ? -887220 : newTick,\n        upperTick: isWethToken0 ? newTick : 887220,\n        poolFee: 3000\n      }\n\n      await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controllerHelper.address, oldTokenId);\n      const tx = await  controllerHelper.connect(depositor).rebalanceLpWithoutVault(params);\n      const receipt = await tx.wait()\n      const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n      const depositorSqueethBalanceAfter= await wSqueeth.balanceOf(depositor.address)\n\n\n      tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n      const newTokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n      const newPosition = await (positionManager as INonfungiblePositionManager).positions(newTokenId);\n      const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(newTokenId); \n\n      const [amount0New, amount1New] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n        tokenId: newTokenId,\n        liquidity: newPosition.liquidity,\n        amount0Min: BigNumber.from(0),\n        amount1Min: BigNumber.from(0),\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n      })\n\n      const wPowerPerpAmountInNewLp = (isWethToken0) ? amount1New : amount0New;\n      const wethAmountInNewLp = (isWethToken0) ? amount0New : amount1New;\n      const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n      const depositorSqueethDiff = depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)\n      const vaultSqueethDiff = wPowerPerpAmountInNewLp.sub(wPowerPerpAmountInLp)\n      const vaultEthDiff = wethAmountInNewLp.sub(wethAmountInLp)\n      expect(ownerOfUniNFT === depositor.address).to.be.true;\n      expect(wPowerPerpAmountInNewLp.sub(wPowerPerpDesired).lte(10)).to.be.true\n      expect(wethAmountInNewLp.eq(BigNumber.from(0))).to.be.true\n      expect(wPowerPerpAmountInNewLp.sub(wPowerPerpAmountInLp.div(2)).abs().lte(10)).to.be.true\n      // Depositor gets weth in LP + weth proceeds from selling squeeth\n      expect((depositorEthDiff.sub(wethAmountInLp).sub(wethAmountOut).add(gasSpent)).abs().lte(ethers.utils.parseUnits('0.01'))).to.be.true\n    })\n\n\n    describe(\"Rebalance LP through trading amounts (swap excess squeeth)\", async () => {\n      let collateralToLp: BigNumber;\n      let mintWSqueethAmount: BigNumber;\n      let squeethAmountOut: BigNumber;\n  \n      before(\"open position and LP\", async () => {\n        const normFactor = await controller.normalizationFactor()\n        mintWSqueethAmount = ethers.utils.parseUnits('35')\n        const mintRSqueethAmount = mintWSqueethAmount.mul(normFactor).div(one)\n        const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 420, true)\n        const scaledEthPrice = ethPrice.div(10000)\n        const debtInEth = mintRSqueethAmount.mul(scaledEthPrice).div(one)\n        const collateralAmount = debtInEth.mul(3).div(2).add(ethers.utils.parseUnits('0.01'))\n        const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, true)\n        // we want to LP with all of the ETH collateral which can be guaranteed by using less vs what is expected\n        collateralToLp = mintWSqueethAmount.mul(squeethPrice).div(one).mul(4).div(5)\n  \n        await controller.connect(depositor).mintWPowerPerpAmount(0, mintWSqueethAmount, 0, {value: collateralAmount})\n  \n        await weth.connect(owner).deposit({value: collateralToLp})\n  \n        const swapParam = {\n          tokenIn: weth.address,\n          tokenOut: wSqueeth.address,\n          fee: 3000,\n          recipient: owner.address,\n          deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n          amountIn: collateralToLp,\n          amountOutMinimum: 0,\n          sqrtPriceLimitX96: 0\n        }    \n        await weth.connect(owner).approve(swapRouter.address, constants.MaxUint256)\n        squeethAmountOut = await swapRouter.connect(owner).callStatic.exactInputSingle(swapParam)\n  \n        const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n        const token0 = isWethToken0 ? weth.address : wSqueeth.address\n        const token1 = isWethToken0 ? wSqueeth.address : weth.address\n    \n        const mintParam = {\n          token0,\n          token1,\n          fee: 3000,\n          tickLower: -887220,// int24 min tick used when selecting full range\n          tickUpper: 887220,// int24 max tick used when selecting full range\n          amount0Desired: isWethToken0 ? collateralToLp : mintWSqueethAmount,\n          amount1Desired: isWethToken0 ? mintWSqueethAmount : collateralToLp,\n          amount0Min: 0,\n          amount1Min: 0,\n          recipient: depositor.address,\n          deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n        }\n    \n        await weth.connect(depositor).deposit({value: collateralToLp})\n        await weth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)\n        await wSqueeth.connect(depositor).approve(positionManager.address, ethers.constants.MaxUint256)  \n        await (positionManager as INonfungiblePositionManager).connect(depositor).mint(mintParam)\n      })\n  \n  \n      it(\"rebalance to decrease WETH amount and LP only oSQTH (sell excess weth)\", async () => {\n        let tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n        const oldTokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n        const oldPosition = await (positionManager as INonfungiblePositionManager).positions(oldTokenId);\n\n        const squeethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 420, true)\n        const slippage = BigNumber.from(3).mul(BigNumber.from(10).pow(16))\n        const limitPriceEthPerPowerPerp = squeethPrice.mul(one.add(slippage)).div(one);\n        const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n  \n        const slot0 = await wSqueethPool.slot0()\n        const currentTick = slot0[1]\n  \n        const isWethToken0 : boolean = parseInt(weth.address, 16) < parseInt(wSqueeth.address, 16) \n        const amount0Min = BigNumber.from(0);\n        const amount1Min = BigNumber.from(0);\n  \n        const newTick = isWethToken0 ? 60*((currentTick - currentTick%60)/60 + 1): 60*((currentTick - currentTick%60)/60 - 1)\n  \n        const tokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n        const positionBefore = await (positionManager as INonfungiblePositionManager).positions(tokenId);\n  \n        await (positionManager as INonfungiblePositionManager).connect(depositor).approve(positionManager.address, tokenId); \n        const [amount0, amount1] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n          tokenId: tokenId,\n          liquidity: positionBefore.liquidity,\n          amount0Min: amount0Min,\n          amount1Min: amount1Min,\n          deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n    })\n        const wPowerPerpAmountInLp = (isWethToken0) ? amount1 : amount0;\n        const wethAmountInLp = (isWethToken0) ? amount0 : amount1;\n        // expected amount from swap\n\n        const wethAmountOut = await quoter.connect(tester).callStatic.quoteExactInputSingle(wSqueeth.address,\n        weth.address,\n        3000,\n        wPowerPerpAmountInLp,\n        0)\n        \n        //uniswap LPing often will give 1 wei less than expected, with the price of oSQTH need to do more than 1 wei due to rounding up the amount owed \n        const params = {\n          wPowerPerpPool: wSqueethPool.address,\n          tokenId: oldTokenId,\n          ethAmountToLp: BigNumber.from(0),\n          liquidity: oldPosition.liquidity,\n          wPowerPerpAmountDesired: ethers.utils.parseUnits('0'),\n          wethAmountDesired: wethAmountInLp,\n          amount0DesiredMin: BigNumber.from(0),\n          amount1DesiredMin: BigNumber.from(0),\n          limitPriceEthPerPowerPerp: BigNumber.from(0),\n          amount0Min: BigNumber.from(0),\n          amount1Min: BigNumber.from(0),\n          lowerTick: isWethToken0 ? newTick: -887220,\n          upperTick: isWethToken0 ? 887220: newTick,\n          poolFee: 3000\n        }\n  \n        await (positionManager as INonfungiblePositionManager).connect(depositor).approve(controllerHelper.address, oldTokenId);\n        const tx = await  controllerHelper.connect(depositor).rebalanceLpWithoutVault(params);\n        const receipt = await tx.wait()\n        const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)\n\n        const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n\n        tokenIndexAfter = await (positionManager as INonfungiblePositionManager).totalSupply();\n        const newTokenId = await (positionManager as INonfungiblePositionManager).tokenByIndex(tokenIndexAfter.sub(1));\n        const newPosition = await (positionManager as INonfungiblePositionManager).positions(newTokenId);\n        const ownerOfUniNFT = await (positionManager as INonfungiblePositionManager).ownerOf(newTokenId); \n  \n        const [amount0New, amount1New] = await (positionManager as INonfungiblePositionManager).connect(depositor).callStatic.decreaseLiquidity({\n          tokenId: newTokenId,\n          liquidity: newPosition.liquidity,\n          amount0Min: BigNumber.from(0),\n          amount1Min: BigNumber.from(0),\n          deadline: Math.floor(await getNow(ethers.provider) + 8640000),\n        })\n  \n        const wPowerPerpAmountInNewLp = (isWethToken0) ? amount1New : amount0New;\n        const wethAmountInNewLp = (isWethToken0) ? amount0New : amount1New;\n        const depositorEthDiff = depositorEthBalanceAfter.sub(depositorEthBalanceBefore)\n        // console.log('wPowerPerpAmountInLP',wPowerPerpAmountInLp.toString())\n        // console.log('wethAmountInLp', wethAmountInLp.toString())\n        // console.log('wPowerPerpAmountInNewLp',wPowerPerpAmountInNewLp.toString())\n        // console.log('wethAmountInNewLp', wethAmountInNewLp.toString())\n        // console.log('depositor address', depositor.address);\n        // console.log('depositorEthBalanceBefore', depositorEthBalanceBefore.toString());\n        // console.log('depositorEthBalanceAfter', depositorEthBalanceAfter.toString());\n        // console.log('depositorEthDiff', depositorEthBalanceAfter.sub(depositorEthBalanceBefore).toString());\n        // console.log('wethAmountOut', wethAmountOut.toString());\n        // console.log('gasSpent', gasSpent.toString())\n        expect(ownerOfUniNFT === depositor.address).to.be.true;\n        // Sold all wPowerPerp in LP\n        expect(wPowerPerpAmountInNewLp.lte(10)).to.be.true\n        // weth stays the same\n        expect((wethAmountInNewLp.sub(wethAmountInLp)).abs().lte(10)).to.be.true\n        // squeeth sold for approximately the right amount of eth\n        expect((depositorEthDiff.sub(wethAmountOut).sub(gasSpent)).lte(ethers.utils.parseUnits('0.01'))).to.be.true\n      })\n  \n  \n    })\n\n  })\n\n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/short_helper_integration.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\n\nimport { ethers, getNamedAccounts } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, providers, constants } from \"ethers\";\nimport { Controller, ShortPowerPerp, WPowerPerp, ShortHelper, WETH9, IUniswapV3Pool } from \"../../typechain\";\n\nimport { deployUniswapV3, deploySqueethCoreContracts, addSqueethLiquidity, deployWETHAndDai } from '../setup'\nimport { getNow, one, oracleScaleFactor } from \"../utils\";\n\ndescribe(\"ShortHelper Integration Test\", function () {\n  const startingEthPrice = 3000\n  const startingScaledSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber()\n\n  let shortHelper: ShortHelper\n  // peer contracts\n  let squeeth: WPowerPerp\n  let shortPowerPerp: ShortPowerPerp\n  let controller: Controller\n  let swapRouter: Contract\n  let weth: WETH9\n\n  let poolAddress: string\n\n  // accounts\n  let seller1: SignerWithAddress\n  let seller2: SignerWithAddress\n  let random: SignerWithAddress\n  let provider: providers.JsonRpcProvider;\n\n  let seller1VaultId = 0;\n  let seller2VaultId = 0; \n\n  const squeethAmount = ethers.utils.parseEther('10')\n  const collateralAmount = ethers.utils.parseEther('20')\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners();\n    const [,_seller1, _seller2, _random] = accounts;\n    seller1 = _seller1\n    seller2 = _seller2\n    random = _random\n    provider = ethers.provider\n  })\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n\n    const { dai, weth: wethToken } = await deployWETHAndDai()\n\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth);\n\n    const coreDeployments = await deploySqueethCoreContracts(weth, dai, uniDeployments.positionManager, uniDeployments.uniswapFactory)\n\n    const { deployer } = await getNamedAccounts();\n    \n    // init uniswap pool: price = 3000, seed with 0.005 squeeth (30 eth as collateral)\n    await addSqueethLiquidity(\n      startingScaledSqueethPrice, \n      '50',\n      '30', \n      deployer, \n      coreDeployments.wsqueeth, \n      weth, \n      uniDeployments.positionManager, \n      coreDeployments.controller, \n    )\n\n    swapRouter = uniDeployments.swapRouter\n    // positionManager = uniDeployments.positionManager\n    squeeth = coreDeployments.wsqueeth\n    shortPowerPerp = coreDeployments.shortSqueeth\n    controller = coreDeployments.controller\n    poolAddress = coreDeployments.wsqueethEthPool.address \n    \n  })\n\n  describe('Basic settings', async() => {\n    describe('deployment', async() => {\n      it('should revert if argument address is invalid', async() => {\n        const ShortHelperFactory = await ethers.getContractFactory(\"ShortHelper\");\n        await expect(ShortHelperFactory.deploy(\n          constants.AddressZero, swapRouter.address, weth.address\n        )).to.be.revertedWith('Invalid controller address');\n\n        await expect(ShortHelperFactory.deploy(\n          controller.address, constants.AddressZero, weth.address\n        )).to.be.revertedWith('Invalid swap router address');\n\n        await expect(ShortHelperFactory.deploy(\n          controller.address, swapRouter.address, constants.AddressZero\n        )).to.be.revertedWith('Invalid weth address');\n      })\n      it('should deploy ShortHelper', async () => {\n        const ShortHelperFactory = await ethers.getContractFactory(\"ShortHelper\");\n\n        // deploy short helper\n        shortHelper = (await ShortHelperFactory.deploy(controller.address, swapRouter.address, weth.address)) as ShortHelper\n    \n        expect(await shortHelper.shortPowerPerp()).to.be.eq(shortPowerPerp.address, \"shortPosition address mismatch\")\n        expect(await shortHelper.controller()).to.be.eq(controller.address, \"controller address mismatch\")\n        expect(await shortHelper.router()).to.be.eq(swapRouter.address, \"swapRouter address mismatch\")\n        expect(await shortHelper.weth()).to.be.eq(weth.address, \"weth address mismatch\")\n      })\n    })\n    \n  })\n\n  describe('Create short position', async() => {\n    \n    it ('should revert if trying to open a vault with non-weth address and squeeth for swap', async () => {\n\n      const exactInputParam = {\n        tokenIn: squeeth.address,\n        tokenOut: random.address,\n        fee: 3000,\n        recipient: seller1.address,\n        deadline: await getNow(provider) + 86400,\n        amountIn: squeethAmount,\n        amountOutMinimum: 0, // no slippage control now\n        sqrtPriceLimitX96: 0,\n      }\n  \n      await expect(shortHelper.connect(seller1).openShort(0, squeethAmount, 0, exactInputParam, {value: collateralAmount} )).to.be.revertedWith(\"Wrong swap tokens\")\n    })\n    \n    it ('should revert if trying to open a vault with weth address and non-squeeth for swap', async () => {\n\n      const exactInputParam = {\n        tokenIn: random.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: seller1.address,\n        deadline: await getNow(provider) + 86400,\n        amountIn: squeethAmount,\n        amountOutMinimum: 0, // no slippage control now\n        sqrtPriceLimitX96: 0,\n      }\n  \n      await expect(shortHelper.connect(seller1).openShort(0, squeethAmount, 0, exactInputParam, {value: collateralAmount} )).to.be.revertedWith(\"Wrong swap tokens\")\n    })\n\n    it('should revert is slippage is too high', async() => {\n      const expectedOutIfNoSlippage = squeethAmount.mul(startingEthPrice).div(oracleScaleFactor)\n\n      const exactInputParam = {\n        tokenIn: squeeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: shortHelper.address, // specify shortHelper as recipient to unwrap weth.\n        deadline: await getNow(provider) + 86400,\n        amountIn: 0,\n        amountOutMinimum: expectedOutIfNoSlippage,\n        sqrtPriceLimitX96: 0,\n      }\n      await expect(shortHelper.connect(seller2).openShort(seller2VaultId, squeethAmount, 0, exactInputParam, {\n        value: collateralAmount\n      })).to.be.revertedWith('Too little received')\n    })\n\n    it('should revert if end price is lower than limit', async() => {\n      \n      // set the min price to be same as current price\n      const pool = await ethers.getContractAt('IUniswapV3Pool', poolAddress) as IUniswapV3Pool\n      const { sqrtPriceX96 } = await pool.slot0()\n      \n      const exactInputParam = {\n        tokenIn: squeeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: shortHelper.address, // specify shortHelper as recipient to unwrap weth.\n        deadline: await getNow(provider) + 86400,\n        amountIn: 0,\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: sqrtPriceX96,\n      }\n\n      const largeSqueethAMount = ethers.utils.parseEther('10')\n\n      await expect(shortHelper.connect(seller1).openShort(0, largeSqueethAMount, 0, exactInputParam, {\n        value: collateralAmount\n      })).to.be.revertedWith('SPL')\n      \n    })\n\n    it ('should open new vault and sell squeeth, receive weth in return', async () => {\n\n      const exactInputParam = {\n        tokenIn: squeeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: seller1.address,\n        deadline: await getNow(provider) + 86400,\n        amountIn: squeethAmount,\n        amountOutMinimum: 0, // no slippage control now\n        sqrtPriceLimitX96: 0,\n      }\n  \n      const nftBalanceBefore = await shortPowerPerp.balanceOf(seller1.address)\n      const poolSqueethBefore = await squeeth.balanceOf(poolAddress)\n      const sellerWethBefore = await weth.balanceOf(seller1.address)\n      const poolWethBefore = await weth.balanceOf(poolAddress)\n      seller1VaultId = (await shortPowerPerp.nextId()).toNumber()\n      // mint and trade\n      await shortHelper.connect(seller1).openShort(0, squeethAmount, 0, exactInputParam, {value: collateralAmount} )\n  \n      const normalizationFactor = await controller.normalizationFactor()\n      const wSqueethAmount = squeethAmount.mul(one).div(normalizationFactor)\n\n      const nftBalanceAfter = await shortPowerPerp.balanceOf(seller1.address)\n      const poolSqueethAfter = await squeeth.balanceOf(poolAddress)\n      const sellerWethAfter = await weth.balanceOf(seller1.address)\n      const poolWethAfter = await weth.balanceOf(poolAddress)\n  \n      expect(nftBalanceAfter.eq(nftBalanceBefore.add(1))).to.be.true\n      expect(poolSqueethAfter.toString()).to.be.eq(poolSqueethBefore.add(wSqueethAmount), \"squeeth mismatch\")\n      expect(poolWethBefore.sub(poolWethAfter).toString()).to.be.eq(sellerWethAfter.sub(sellerWethBefore), \"weth mismatch\")\n    })\n\n    it('should add ShortHelper as an operator', async() =>{\n      // it needs to set the ShortHelper as an operator to allow interactions past minting a new vault\n      \n      await controller.connect(seller1).updateOperator(seller1VaultId,shortHelper.address)\n      const vault = await controller.vaults(seller1VaultId)\n      expect(vault.operator).to.be.eq(shortHelper.address, \"Operator not set correctly\")\n    })\n\n    it('should reset operator when vault transferred', async() =>{\n      \n      const nftOwnerBefore = await shortPowerPerp.ownerOf(seller1VaultId)\n      const vaultBefore = await controller.vaults(seller1VaultId)\n      await shortPowerPerp.connect(seller1).functions[\"safeTransferFrom(address,address,uint256)\"](seller1.address, seller2.address, seller1VaultId)\n      \n      const nftOwnerAfter = await shortPowerPerp.ownerOf(seller1VaultId)\n\n      const vaultAfter = await controller.vaults(seller1VaultId)\n      expect(vaultBefore.operator).to.be.eq(shortHelper.address, \"Operator was not set correctly to short helper\")\n      expect(vaultAfter.operator).to.be.eq(ethers.constants.AddressZero, \"Operator didn't get reset on transfer\")\n      expect(nftOwnerBefore).to.be.eq(seller1.address, \"Nft was not owned by seller1 before transfer\")\n      expect(nftOwnerAfter).to.be.eq(seller2.address, \"Nft is not owned by seller2 after transfer\")\n\n      await shortPowerPerp.connect(seller2).functions[\"safeTransferFrom(address,address,uint256)\"](seller2.address, seller1.address, seller1VaultId)\n      const nftOwnerFinal = await shortPowerPerp.ownerOf(seller1VaultId)\n\n      expect(nftOwnerFinal).to.be.eq(seller1.address, \"Nft is not owned by seller1 after final transfer\")\n\n      await controller.connect(seller1).updateOperator(seller1VaultId,shortHelper.address)\n      const vault = await controller.vaults(seller1VaultId)\n      expect(vault.operator).to.be.eq(shortHelper.address, \"Operator not set correctly\")\n\n    })\n\n    it ('should add collateral to an existing vault and sell squeeth, receive weth in return', async () => {\n      \n      const exactInputParam = {\n        tokenIn: squeeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: seller1.address,\n        deadline: await getNow(provider) + 86400,\n        amountIn: squeethAmount,\n        amountOutMinimum: 0, // no slippage control now\n        sqrtPriceLimitX96: 0,\n      }\n  \n      const nftBalanceBefore = await shortPowerPerp.balanceOf(seller1.address)\n      const poolSqueethBefore = await squeeth.balanceOf(poolAddress)\n      const sellerWethBefore = await weth.balanceOf(seller1.address)\n      const poolWethBefore = await weth.balanceOf(poolAddress)\n\n      // mint and trade\n      await shortHelper.connect(seller1).openShort(seller1VaultId, squeethAmount, 0, exactInputParam, {value: collateralAmount} )\n  \n      const normalizationFactor = await controller.normalizationFactor()\n      const wSqueethAmount = squeethAmount.mul(ethers.utils.parseUnits('1')).div(normalizationFactor)\n\n      const nftBalanceAfter = await shortPowerPerp.balanceOf(seller1.address)\n      const poolSqueethAfter = await squeeth.balanceOf(poolAddress)\n      const sellerWethAfter = await weth.balanceOf(seller1.address)\n      const poolWethAfter = await weth.balanceOf(poolAddress)\n  \n      expect(nftBalanceAfter.eq(nftBalanceBefore)).to.be.true\n      expect(poolSqueethAfter.toString()).to.be.eq(poolSqueethBefore.add(wSqueethAmount), \"squeeth mismatch\")\n      expect(poolWethBefore.sub(poolWethAfter).toString()).to.be.eq(sellerWethAfter.sub(sellerWethBefore), \"weth mismatch\")\n    })\n\n    it ('should revert if a random address tries to mint and sell squeeth on someone elses vault', async () => {\n      const attackAmount = squeethAmount.div(10)\n      const exactInputParam = {\n        tokenIn: squeeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: seller2.address,\n        deadline: await getNow(provider) + 86400,\n        amountIn: attackAmount,\n        amountOutMinimum: 0, // no slippage control now\n        sqrtPriceLimitX96: 0,\n      }\n  \n      await expect(shortHelper.connect(seller2).openShort(seller1VaultId, attackAmount, 0, exactInputParam, {value: 0} )).to.be.revertedWith(\"Not allowed\")\n    })\n\n    it ('should revert if collateral amount put down is dust', async () => {\n      const smallSqueethAmount = ethers.utils.parseEther('0.1')\n      const smallCollateralAmount = ethers.utils.parseEther('0.2')\n      \n      const exactInputParam = {\n        tokenIn: squeeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: shortHelper.address, // specify shortHelper as recipient to unwrap weth.\n        deadline: await getNow(provider) + 86400,\n        amountIn: 0, // should be replaced by real wsqueeth minted\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0,\n      }\n  \n      await expect(shortHelper.connect(seller2).openShort(0, smallSqueethAmount, 0, exactInputParam, {\n          value: smallCollateralAmount, \n        }\n      )).to.be.revertedWith('C22')\n\n    })\n\n    it ('should revert if user does not put enough collateral', async () => {\n      const exactInputParam = {\n        tokenIn: squeeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: shortHelper.address,\n        deadline: await getNow(provider) + 86400,\n        amountIn: 0, // should be replaced by real wsqueeth minted\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0,\n      }\n  \n      await expect(shortHelper.connect(seller2).openShort(0, squeethAmount, 0, exactInputParam, {\n          value: collateralAmount.div(5),  // not enough collateral\n        }\n      )).to.be.revertedWith('C24')\n\n    })\n\n    it ('should open new vault and sell squeeth, receive eth at the end', async () => {\n      \n      const exactInputParam = {\n        tokenIn: squeeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: shortHelper.address, // specify shortHelper as recipient to unwrap weth.\n        deadline: await getNow(provider) + 86400,\n        amountIn: squeethAmount,\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0,\n      }\n  \n      const nftBalanceBefore = await shortPowerPerp.balanceOf(seller2.address)\n      const poolSqueethBefore = await squeeth.balanceOf(poolAddress)\n      const sellerEthBefore = await provider.getBalance(seller2.address)\n      const poolWethBefore = await weth.balanceOf(poolAddress)\n  \n      seller2VaultId = (await shortPowerPerp.nextId()).toNumber()\n\n      // mint and trade\n      await shortHelper.connect(seller2).openShort(0, squeethAmount, 0, exactInputParam, {\n          value: collateralAmount\n        }\n      )\n\n      const normalizationFactor = await controller.normalizationFactor()\n      const wSqueethAmount = squeethAmount.mul(one).div(normalizationFactor)\n\n      const nftBalanceAfter = await shortPowerPerp.balanceOf(seller2.address)\n      const poolSqueethAfter = await squeeth.balanceOf(poolAddress)\n      const sellerEthAfter = await provider.getBalance(seller2.address)\n      const poolWethAfter = await weth.balanceOf(poolAddress)\n  \n      expect(nftBalanceAfter.eq(nftBalanceBefore.add(1))).to.be.true\n      expect(poolSqueethAfter.toString()).to.be.eq(poolSqueethBefore.add(wSqueethAmount), \"squeeth mismatch\")\n      // expect(poolWethBefore.sub(poolWethAfter).toString()).to.be.eq(\n      //   sellerEthAfter.add(collateralAmount).sub(sellerEthBefore), \"weth mismatch\"\n      // )\n    })\n\n    it ('should revert if trying to short more from the current vault', async () => {\n      \n      await controller.connect(seller2).updateOperator(seller2VaultId, shortHelper.address)\n      \n      const exactInputParam = {\n        tokenIn: squeeth.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: shortHelper.address,\n        deadline: await getNow(provider) + 86400,\n        amountIn: 0, // should be replaced by real wsqueeth minted\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0,\n      }\n  \n      await expect(shortHelper.connect(seller2).openShort(seller2VaultId, squeethAmount.mul(5), 0, exactInputParam)).to.be.revertedWith('C24')\n    })\n\n  })\n\n  describe('Checking eth payable reverts', async() => {\n    it ('should revert if ETH is sent from a contract other than weth or the controller', async () => {\n      await expect(seller1.sendTransaction({to: shortHelper.address, value:1})).to.be.revertedWith(\"can't receive eth\")\n    })\n  })\n\n  describe('Close short position', async() => {\n    \n    it ('should revert if a random user to withdraw ETH from someone elses vault', async () => {\n      const buyBackSqueethAmount = ethers.utils.parseEther('0.0000001')\n      const withdrawCollateralAmount = ethers.utils.parseEther('2.5')\n\n      // max amount to buy back 0.1 squeeth\n      const amountInMaximum = ethers.utils.parseEther('5')\n  \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: shortHelper.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: buyBackSqueethAmount,\n        amountInMaximum,\n        sqrtPriceLimitX96: 0,\n      }\n  \n      // short helper already added as operator for seller1\n      // buy and close\n      await expect(shortHelper.connect(seller2).closeShort(seller1VaultId, buyBackSqueethAmount, withdrawCollateralAmount, exactOutputParam, {\n          value: amountInMaximum // max amount used to buy back eth\n        }\n      )).to.be.revertedWith(\"Not allowed\")\n    })\n\n    it ('should revert if trying to partially close a position using squeeth and not weth', async () => {\n      const buyBackSqueethAmount = ethers.utils.parseEther('0.0005')\n      const withdrawCollateralAmount = ethers.utils.parseEther('10')\n\n      // max amount to buy back 0.1 squeeth\n      const amountInMaximum = ethers.utils.parseEther('5')\n  \n      const exactOutputParam = {\n        tokenIn: random.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: shortHelper.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: buyBackSqueethAmount,\n        amountInMaximum,\n        sqrtPriceLimitX96: 0,\n      }\n  \n      // buy and close\n      await expect(shortHelper.connect(seller1).closeShort(seller1VaultId, buyBackSqueethAmount, withdrawCollateralAmount, exactOutputParam, {\n          value: amountInMaximum // max amount used to buy back eth\n        }\n      )).to.be.revertedWith('Wrong swap tokens')\n    })\n\n    it ('should revert if trying to partially close a position using weth and non-squeeth', async () => {\n      const buyBackSqueethAmount = ethers.utils.parseEther('0.0005')\n      const withdrawCollateralAmount = ethers.utils.parseEther('10')\n\n      // max amount to buy back 0.1 squeeth\n      const amountInMaximum = ethers.utils.parseEther('5')\n  \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: random.address,\n        fee: 3000,\n        recipient: shortHelper.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: buyBackSqueethAmount,\n        amountInMaximum,\n        sqrtPriceLimitX96: 0,\n      }\n  \n      // buy and close\n      await expect(shortHelper.connect(seller1).closeShort(seller1VaultId, buyBackSqueethAmount, withdrawCollateralAmount, exactOutputParam, {\n          value: amountInMaximum // max amount used to buy back eth\n        }\n      )).to.be.revertedWith('Wrong swap tokens')\n    })\n\n    it('should revert if slippage is too high', async() => {      \n      const vaultToClose = await controller.vaults(seller1VaultId)\n      const buyBackSqueethAmount = vaultToClose.shortAmount\n      const withdrawCollateralAmount = vaultToClose.collateralAmount\n      const maxWethToPay = squeethAmount.mul(startingEthPrice).div(oracleScaleFactor)\n\n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: shortHelper.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: buyBackSqueethAmount,\n        amountInMaximum: maxWethToPay,\n        sqrtPriceLimitX96: 0,\n      }    \n      \n      // revert with STF cuz the short helper won't have enough weth to pay for it\n      await expect(shortHelper.connect(seller1).closeShort(seller1VaultId, buyBackSqueethAmount, withdrawCollateralAmount, exactOutputParam, {\n          value: maxWethToPay, \n        }\n      )).to.be.revertedWith('STF')\n    })\n\n    it('should revert if end price is too high', async() => {  \n      const pool = await ethers.getContractAt('IUniswapV3Pool', poolAddress) as IUniswapV3Pool\n      const { sqrtPriceX96 } = await pool.slot0()\n      \n      const vaultToClose = await controller.vaults(seller2VaultId)\n      const buyBackSqueethAmount = vaultToClose.shortAmount\n      const withdrawCollateralAmount = vaultToClose.collateralAmount\n\n      // max amount to buy back squeeth\n      const amountInMaximum = ethers.utils.parseEther('10')\n  \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: shortHelper.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: buyBackSqueethAmount,\n        amountInMaximum,\n        sqrtPriceLimitX96: sqrtPriceX96, // set the limit as current price\n      }    \n      \n      await controller.connect(seller2).updateOperator(seller2VaultId, shortHelper.address)\n      await expect(shortHelper.connect(seller2).closeShort(seller2VaultId, buyBackSqueethAmount, withdrawCollateralAmount, exactOutputParam, {\n          value: amountInMaximum\n        }\n      )).to.be.revertedWith('SPL')\n      \n    })\n\n    it ('should revert when leaving vault with dust collateral and debt', async () => {\n      const vault = await controller.vaults(seller1VaultId)\n      \n      const buyBackWsqueethAmount = vault.shortAmount.sub(10) // leaving 10 wei wsqueeth\n      \n      // leaving the vault with 1 wei less than 0.5\n      const withdrawCollateralAmount = vault.collateralAmount.sub(ethers.utils.parseEther('0.5')).add(1)\n      \n      const amountInMaximum = ethers.utils.parseEther('20')\n  \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: shortHelper.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: buyBackWsqueethAmount,\n        amountInMaximum,\n        sqrtPriceLimitX96: 0,\n      }\n  \n      await expect(shortHelper.connect(seller1)\n        .closeShort(seller1VaultId, buyBackWsqueethAmount, withdrawCollateralAmount, exactOutputParam, {value: amountInMaximum}\n      )).to.be.revertedWith('C22')  \n    })\n\n    it ('should revert if remove too much collateral vs debt bought back', async () => {\n      const vault = await controller.vaults(seller1VaultId)\n      \n      const buyBackWsqueethAmount = 10\n      \n      const withdrawCollateralAmount = vault.collateralAmount.sub(ethers.utils.parseEther('0.5'))\n      \n      const amountInMaximum = ethers.utils.parseEther('0.02')\n  \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: shortHelper.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: buyBackWsqueethAmount,\n        amountInMaximum,\n        sqrtPriceLimitX96: 0,\n      }\n  \n      await expect(shortHelper.connect(seller1)\n        .closeShort(seller1VaultId, buyBackWsqueethAmount, withdrawCollateralAmount, exactOutputParam, {value: amountInMaximum}\n      )).to.be.revertedWith('C24')  \n    })\n    \n    it ('should partially close a short position and get back eth', async () => {\n      const buyBackSqueethAmount = ethers.utils.parseEther('0.0005')\n      const withdrawCollateralAmount = ethers.utils.parseEther('10')\n\n      // max amount to buy back 0.1 squeeth\n      const amountInMaximum = ethers.utils.parseEther('5')\n  \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: shortHelper.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: buyBackSqueethAmount,\n        amountInMaximum,\n        sqrtPriceLimitX96: 0,\n      }\n  \n      // short helper already added as operator for seller1\n\n      const nftBalanceBefore = await shortPowerPerp.balanceOf(seller1.address)\n      const poolSqueethBefore = await squeeth.balanceOf(poolAddress)\n      const sellerEthBefore = await provider.getBalance(seller1.address)\n      const poolWethBefore = await weth.balanceOf(poolAddress)\n\n      // buy and close\n      await shortHelper.connect(seller1).closeShort(seller1VaultId, buyBackSqueethAmount, withdrawCollateralAmount, exactOutputParam, {\n          value: amountInMaximum // max amount used to buy back eth\n        }\n      )\n  \n      const nftBalanceAfter = await shortPowerPerp.balanceOf(seller1.address)\n      const poolSqueethAfter = await squeeth.balanceOf(poolAddress)\n      const sellerEthAfter = await provider.getBalance(seller1.address)\n      const poolWethAfter = await weth.balanceOf(poolAddress)\n  \n      expect(nftBalanceAfter.eq(nftBalanceBefore)).to.be.true\n      expect(poolSqueethAfter.toString()).to.be.eq(poolSqueethBefore.sub(buyBackSqueethAmount), \"squeeth mismatch\")\n      // expect(poolWethAfter.sub(poolWethBefore).toString()).to.be.eq(\n      //   sellerEthBefore.add(withdrawCollateralAmount).sub(sellerEthAfter), \"weth mismatch\"\n      // )\n    })\n\n    it ('should fully close a short position and get back eth', async () => {\n      const vaultToClose = await controller.vaults(seller2VaultId)\n      const buyBackSqueethAmount = vaultToClose.shortAmount\n      const withdrawCollateralAmount = vaultToClose.collateralAmount\n\n      // max amount to buy back 0.1 squeeth\n      const amountInMaximum = ethers.utils.parseEther('10')\n  \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: shortHelper.address,\n        deadline: await getNow(provider) + 86400,\n        amountOut: buyBackSqueethAmount,\n        amountInMaximum,\n        sqrtPriceLimitX96: 0,\n      }    \n      // add short helper as operator\n      await controller.connect(seller2).updateOperator(seller2VaultId, shortHelper.address)\n\n      const nftBalanceBefore = await shortPowerPerp.balanceOf(seller2.address)\n      const poolSqueethBefore = await squeeth.balanceOf(poolAddress)\n      const sellerEthBefore = await provider.getBalance(seller2.address)\n      const poolWethBefore = await weth.balanceOf(poolAddress)\n\n      // buy and close\n      await shortHelper.connect(seller2).closeShort(seller2VaultId, buyBackSqueethAmount, withdrawCollateralAmount, exactOutputParam, {\n          value: amountInMaximum // max amount used to buy back eth\n        }\n      )\n  \n      const nftBalanceAfter = await shortPowerPerp.balanceOf(seller2.address)\n      const poolSqueethAfter = await squeeth.balanceOf(poolAddress)\n      const sellerEthAfter = await provider.getBalance(seller2.address)\n      const poolWethAfter = await weth.balanceOf(poolAddress)\n  \n      expect(nftBalanceAfter.eq(nftBalanceBefore)).to.be.true // nft amount stay the same\n      expect(poolSqueethAfter.toString()).to.be.eq(poolSqueethBefore.sub(buyBackSqueethAmount), \"squeeth mismatch\")\n      // expect(poolWethAfter.sub(poolWethBefore).toString()).to.be.eq(\n      //   sellerEthBefore.add(withdrawCollateralAmount).sub(sellerEthAfter), \"weth mismatch\"\n      // )\n    })\n\n  })\n});\n"
  },
  {
    "path": "packages/hardhat/test/integration-tests/strategy/crab-flashswap-liquidation.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport BigNumberJs from 'bignumber.js'\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategy, ISwapRouter } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\ndescribe(\"Crab flashswap integration test: crab vault liquidation\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.mul(11).div(10).div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice*1.1 / oracleScaleFactor.toNumber() // 0.3\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress;\n  let liquidator: SignerWithAddress;\n  let feeRecipient: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategy\n  let ethDaiPool: Contract\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _depositor2, _liquidator, _feeRecipient ] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    depositor2 = _depositor2;\n    liquidator = _liquidator;\n    feeRecipient = _feeRecipient;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      positionManager, \n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    await controller.connect(owner).setFeeRecipient(feeRecipient.address);\n    await controller.connect(owner).setFeeRate(100)\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n    \n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n    await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async() => {\n    await provider.send(\"evm_increaseTime\", [300])\n    await provider.send(\"evm_mine\", [])\n\n    // add liquidity\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '1000000',\n      '2000000', \n      owner.address, \n      wSqueeth, \n      weth, \n      positionManager, \n      controller\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n  })\n\n  this.beforeAll(\"Deposit into strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('20')\n    const msgvalue = ethers.utils.parseUnits('10.2')\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n    await crabStrategy.connect(depositor).flashDeposit(ethToDeposit, {value: msgvalue})\n    \n    const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n    const feeRate = await controller.feeRate()\n    const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n    const squeethDelta = scaledStartingSqueethPrice1e18.mul(2);\n    const debtToMint = wdiv(ethToDeposit, (squeethDelta.add(ethFeePerWSqueeth)));\n    const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n    const debtAmount = strategyVault.shortAmount\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n    const lastHedgeTime = await crabStrategy.timeAtLastHedge()\n    const currentBlockNumber = await provider.getBlockNumber()\n    const currentBlock = await provider.getBlock(currentBlockNumber)\n    const timeStamp = currentBlock.timestamp\n    const collateralAmount = await strategyVault.collateralAmount\n\n    expect(isSimilar(totalSupply.toString(),(expectedEthDeposit).toString())).to.be.true\n    expect(isSimilar(depositorCrab.toString(),expectedEthDeposit.toString())).to.be.true\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString())).to.be.true\n    expect(depositorSqueethBalance.eq(depositorSqueethBalanceBefore)).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n    expect(lastHedgeTime.eq(timeStamp)).to.be.true\n  })\n\n  describe(\"liquidate vault\", async () => {\n    before('push weth price higher to make crab vault liquidatable', async() => {\n      // set weth price higher by buying 25% of weth in the pool\n      const poolWethBalance = await weth.balanceOf(ethDaiPool.address)\n\n      const maxDai = poolWethBalance.mul(startingEthPrice).mul(5)\n\n      const exactOutputParam = {\n        tokenIn: dai.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"20\"),\n        amountInMaximum: maxDai,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await dai.connect(owner).mint(owner.address, maxDai, )\n      await dai.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('push squeeth price higher', async() => {\n      // set squeeth price higher by buying 25% of squeeth in the pool\n      const poolSqueethBalance = await wSqueeth.balanceOf(wSqueethPool.address)\n\n      const maxWeth = poolSqueethBalance.mul(scaledStartingSqueethPrice1e18).mul(5).div(one)\n            \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"200000\"),\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(owner).deposit({value: maxWeth})\n      await weth.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('prepare liquidator to liquidate strategy', async() => {\n      await provider.send(\"evm_increaseTime\", [600]) // increase time by 600 sec\n      await provider.send(\"evm_mine\", [])\n\n      const vaultId = await crabStrategy.vaultId();\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      const vaultBefore = await controller.vaults(vaultId)\n      \n      const mintAmount = vaultBefore.shortAmount\n      const collateralRequired = mintAmount.mul(newEthPrice).mul(2).div(oracleScaleFactor).div(one).mul(2)\n\n      // mint squeeth to liquidate vault0!\n      await controller.connect(liquidator).mintPowerPerpAmount(0, mintAmount, 0, {value: collateralRequired})\n    })\n\n    it(\"should liquidate crab vault\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      const newSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const vaultBefore = await controller.vaults(vaultId)\n      const wSqueethVaultBefore = vaultBefore.shortAmount\n      const collateralBefore = vaultBefore.collateralAmount\n\n      const collatRatio = collateralBefore.mul(one).div(wSqueethVaultBefore.mul(normFactor).mul(newEthPrice).div(one).div(one).div(oracleScaleFactor))\n      \n      expect(isVaultSafe).to.be.false\n\n      // state before liquidation\n      const liquidatorSqueethBefore = await wSqueeth.balanceOf(liquidator.address)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount.div(2)\n\n      await controller.connect(liquidator).liquidate(vaultId, wSqueethAmountToLiquidate);\n      \n      const collateralToGet = newSqueethPrice.mul(wSqueethAmountToLiquidate).div(one).mul(11).div(10)\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const liquidatorSqueethAfter = await wSqueeth.balanceOf(liquidator.address)\n\n      expect(isSimilar((vaultBefore.shortAmount.div(2)).toString(),(vaultAfter.shortAmount).toString())).to.be.true\n      expect(vaultAfter.shortAmount.gt(BigNumber.from(0))).to.be.true\n      expect(vaultAfter.collateralAmount.gt(BigNumber.from(0))).to.be.true\n      // expect(collateralToGet.eq(liquidatorBalanceAfter.sub(liquidatorBalanceBefore))).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(liquidatorSqueethBefore.sub(liquidatorSqueethAfter))).to.be.true\n    })\n\n    it(\"should let user deposit post liquidation and update vault state and provide correct wSqueeth and crab tokens\", async () => {\n      \n      //                               (userEthDeposit * strategyDebtBeforeDeposit) \n      //  wSqueethToMint =  ----------------------------------------------------------------------------------------\n      //                    (strategyCollateralBeforeDeposit + strategyDebtBeforeDeposit*squeethEthPrice*fee%)\n\n      \n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      const normFactor = await controller.getExpectedNormalizationFactor()\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      const newSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const vaultBefore = await controller.vaults(vaultId)\n      const wSqueethVaultBefore = vaultBefore.shortAmount\n      const collateralBefore = vaultBefore.collateralAmount\n\n      const collatRatio = collateralBefore.mul(one).div(wSqueethVaultBefore.mul(normFactor).mul(newEthPrice).div(one).div(one).div(oracleScaleFactor))\n\n      const debtBefore = vaultBefore.shortAmount\n      const ratio = debtBefore.mul(one).div(collateralBefore)\n\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      const msgvalue = ethers.utils.parseUnits('15')  \n      const totalSupplyBefore = (await crabStrategy.totalSupply())\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor2.address))\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await crabStrategy.connect(depositor2).flashDeposit(ethToDeposit, {value: msgvalue})      \n      \n      const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n      const debtToMint = ethToDeposit.mul(debtBefore).div(collateralBefore.add(debtBefore.mul(ethFeePerWSqueeth).div(one)))\n      const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n      const depositorShare = one.mul(expectedEthDeposit).div(collateralBefore.add(expectedEthDeposit))\n      const crabMintAmount = totalSupplyBefore.mul(depositorShare).div(one.sub(depositorShare))\n\n      const strategyVaultAfter = await controller.vaults(vaultId)\n      const strategyDebtAmountAfter = strategyVaultAfter.shortAmount\n      const strategyCollateralAmountAfter = strategyVaultAfter.collateralAmount\n      const depositorCrabAfter = (await crabStrategy.balanceOf(depositor2.address))\n      const depositorSqueethBalanceAfter = await wSqueeth.balanceOf(depositor2.address)\n      const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n      const totalSupplyAfter = (await crabStrategy.totalSupply())\n      // const depositorEthBalanceAfter = await provider.getBalance(depositor2.address)\n\n      expect(isSimilar((strategyCollateralAmountAfter.sub(collateralBefore)).toString(),(expectedEthDeposit).toString())).to.be.true\n      expect(isSimilar(strategyDebtAmountAfter.toString(),(debtBefore.add(debtToMint)).toString())).to.be.true\n      expect(isSimilar((strategyDebtAmountAfter.sub(debtBefore)).toString(),(debtToMint).toString())).to.be.true      \n      expect(isSimilar((totalSupplyAfter.sub(totalSupplyBefore)).toString(),(crabMintAmount).toString())).to.be.true\n      expect((depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore)).eq(BigNumber.from(0))).to.be.true\n      expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n      expect(isSimilar((depositorCrabAfter.sub(depositorCrabBefore)).toString(),(crabMintAmount).toString())).to.be.true\n    })\n\n    it(\"depositor should withdraw correct amount of ETH collateral\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtAmountBefore = strategyVault.shortAmount\n      const strategyCollateralAmountBefore = strategyVault.collateralAmount\n      const userEthBalanceBefore = await provider.getBalance(depositor.address)\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio,strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay,wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethCostOfDebtToRepay.mul(101).div(100)\n\n      await crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay)\n\n      const userEthBalanceAfter = await provider.getBalance(depositor.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor.address);\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralAfter = vaultBefore.collateralAmount\n      const debtAfter = vaultBefore.shortAmount\n\n      expect(isSimilar(userEthBalanceAfter.sub(userEthBalanceBefore).toString(), ethToWithdraw.toString(),2)).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(collateralAfter.eq(strategyCollateralAmountBefore.sub(userCollateral))).to.be.true\n      // use isSimilar to prevent last digits rounding error\n      expect(isSimilar(strategyDebtAmountBefore.sub(debtAfter).toString(), debtToRepay.toString(), 10)).to.be.true\n    })\n\n    it(\"depositor2 should withdraw correct amount of ETH collateral\", async () => {\n      \n      \n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor2.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtAmountBefore = strategyVault.shortAmount\n      const strategyCollateralAmountBefore = strategyVault.collateralAmount\n      const userEthBalanceBefore = await provider.getBalance(depositor2.address)\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio,strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay,wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethCostOfDebtToRepay.mul(11).div(10)\n\n      await crabStrategy.connect(depositor2).flashWithdraw(userCrabBalanceBefore, maxEthToPay)\n\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const userEthBalanceAfter = await provider.getBalance(depositor2.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor2.address);\n      const strategyDebtAmountAfter = strategyVaultAfter.shortAmount\n      const strategyCollateralAmountAfter = strategyVaultAfter.collateralAmount\n\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralAfter = vaultBefore.collateralAmount\n      const debtAfter = vaultBefore.shortAmount\n\n      expect(isSimilar(userEthBalanceAfter.sub(userEthBalanceBefore).toString(), ethToWithdraw.toString(),2)).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(collateralAfter.eq(strategyCollateralAmountBefore.sub(userCollateral))).to.be.true\n      expect(strategyDebtAmountBefore.sub(debtAfter).eq(debtToRepay)).to.be.true\n      expect(strategyDebtAmountAfter.eq(BigNumber.from(0))).to.be.true\n      expect(strategyCollateralAmountAfter.eq(BigNumber.from(0))).to.be.true\n    })\n  })\n})\n"
  },
  {
    "path": "packages/hardhat/test/integration-tests/strategy/crab-hedge-uniswap-price-based.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport BigNumberJs from 'bignumber.js'\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategy } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity, buyWSqueeth, buyWeth } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\nconst calcPriceMulAndAuctionPrice = (isNegativeTargetHedge: boolean, maxPriceMultiplier: BigNumber, minPriceMultiplier: BigNumber, auctionExecution: BigNumber, currentWSqueethPrice: BigNumber) : [BigNumber, BigNumber] => {\n  let priceMultiplier: BigNumber\n  let auctionWSqueethEthPrice: BigNumber\n\n  if(isNegativeTargetHedge) {\n    priceMultiplier = maxPriceMultiplier.sub(wmul(auctionExecution, maxPriceMultiplier.sub(minPriceMultiplier)))\n    auctionWSqueethEthPrice = wmul(currentWSqueethPrice, priceMultiplier);\n  } \n  else {\n    priceMultiplier = minPriceMultiplier.add(wmul(auctionExecution, maxPriceMultiplier.sub(minPriceMultiplier)))\n    auctionWSqueethEthPrice = wmul(currentWSqueethPrice, priceMultiplier);\n  }\n\n  return [priceMultiplier, auctionWSqueethEthPrice]\n}\n\ndescribe(\"Crab flashswap integration test: uniswap price based hedging\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.mul(11).div(10).div(oracleScaleFactor) // 0.303 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice*1.1 / oracleScaleFactor.toNumber() // 0.303\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let feeRecipient: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategy\n  let ethDaiPool: Contract\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _feeRecipient ] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    feeRecipient = _feeRecipient;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      positionManager, \n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    await controller.connect(owner).setFeeRecipient(feeRecipient.address);\n    await controller.connect(owner).setFeeRate(100)\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n    \n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n    await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async() => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '1000000',\n      '2000000', \n      owner.address, \n      wSqueeth, \n      weth, \n      positionManager, \n      controller\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"Deposit into strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('20')\n    const msgvalue = ethers.utils.parseUnits('10.1')\n\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n    await crabStrategy.connect(depositor).flashDeposit(ethToDeposit, {value: msgvalue})\n    \n    const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n    const feeRate = await controller.feeRate()\n    const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n    const squeethDelta = scaledStartingSqueethPrice1e18.mul(2);\n    const debtToMint = wdiv(ethToDeposit, (squeethDelta.add(ethFeePerWSqueeth)));\n    const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n    const debtAmount = strategyVault.shortAmount\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n    const lastHedgeTime = await crabStrategy.timeAtLastHedge()\n    const currentBlockNumber = await provider.getBlockNumber()\n    const currentBlock = await provider.getBlock(currentBlockNumber)\n    const timeStamp = currentBlock.timestamp\n    const collateralAmount = await strategyVault.collateralAmount\n\n    expect(isSimilar(totalSupply.toString(),(expectedEthDeposit).toString())).to.be.true\n    expect(isSimilar(depositorCrab.toString(),(expectedEthDeposit).toString())).to.be.true\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString())).to.be.true\n    expect(depositorSqueethBalance.eq(depositorSqueethBalanceBefore)).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n    expect(lastHedgeTime.eq(timeStamp)).to.be.true\n  })\n\n  describe(\"Sell auction\", async () => {\n    before(async () => {\n      // change pool price\n      const ethToDeposit = ethers.utils.parseUnits('10000')\n      const wSqueethToMint = ethers.utils.parseUnits('10000')\n      const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp\n      await controller.connect(owner).mintWPowerPerpAmount(\"0\", wSqueethToMint, \"0\", {value: ethToDeposit})\n      await buyWeth(swapRouter, wSqueeth, weth, owner.address, (await wSqueeth.balanceOf(owner.address)), currentBlockTimestamp + 10)\n    })\n\n    it(\"it should be eligible for a hedge after time has passed for twap to update but will revert due to hedge sign change\", async () => {      \n      // advance time for twap to update\n      await provider.send(\"evm_increaseTime\", [600])\n      await provider.send(\"evm_mine\", [])  \n  \n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n      \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n  \n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n  \n      // set next block timestamp     \n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n    \n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.true;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.false;\n  \n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n  \n      expect(isSellAuction).to.be.true\n  \n      await expect(\n        crabStrategy.connect(depositor).priceHedgeOnUniswap(auctionTriggerTimer, ethers.utils.parseUnits('0.01'), BigNumber.from('0'))\n      ).to.be.revertedWith(\"auction direction changed\");\n    })    \n  \n    it(\"should revert if not positive PnL\", async () => {\n      const auctionTriggerTimer = (await provider.getBlock(await provider.getBlockNumber())).timestamp\n\n      // advanced more time to avoid traget hedge sign change\n      await provider.send(\"evm_increaseTime\", [auctionTime/3])\n      await provider.send(\"evm_mine\", [])        \n      \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 100;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n    \n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.false;\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.true;\n  \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      \n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n  \n      expect(isSellAuction).to.be.true\n  \n      await expect(\n        crabStrategy.connect(depositor).priceHedgeOnUniswap(auctionTriggerTimer, ethers.utils.parseUnits('0.01'), ethers.utils.parseUnits('0'))\n      ).to.be.revertedWith(\"ds-math-sub-underflow\");\n    })\n\n    it(\"it should revert if PnL is less than min wsqueeth\", async () => {\n      // advance time so hedge sign doesn't switch\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp - (auctionTime / 3)\n\n      await provider.send(\"evm_increaseTime\", [auctionTime/2])\n      await provider.send(\"evm_mine\", [])  \n            \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      // set next block timestamp     \n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n      const hedgeBlockTimestamp = hedgeBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n   \n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n\n      expect(isSellAuction).to.be.true\n\n        \n      await expect(\n        crabStrategy.connect(depositor).priceHedgeOnUniswap(auctionTriggerTimer, ethers.utils.parseUnits('10'), ethers.utils.parseUnits('0'))\n      ).to.be.revertedWith(\"profit is less than min wSqueeth\");\n    })\n\n    it(\"it should allow a hedge based on price\", async () => {\n      // advance time so hedge sign doesn't switch\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp - (auctionTime / 3)\n\n      await provider.send(\"evm_increaseTime\", [auctionTime/2])\n      await provider.send(\"evm_mine\", [])  \n            \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      // set next block timestamp     \n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n      const hedgeBlockTimestamp = hedgeBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n   \n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n  \n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n\n      expect(isSellAuction).to.be.true\n\n      await crabStrategy.connect(depositor).priceHedgeOnUniswap(auctionTriggerTimer, ethers.utils.parseUnits('0.01'), ethers.utils.parseUnits('0'))\n              \n      const currentWSqueethPriceAfter = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAmountAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAmountAfter = strategyVaultAfter.shortAmount\n      const timeAtLastHedgeAfter = await crabStrategy.timeAtLastHedge()\n      const priceAtLastHedgeAfter = await crabStrategy.priceAtLastHedge()\n      expect(isSimilar(strategyDebtAmountAfter.sub(strategyDebt).toString(), secondTargetHedge.abs().toString())).to.be.true\n      expect(isSimilar(strategyCollateralAmountAfter.sub(ethDelta).toString(), expectedEthDeposited.toString())).to.be.true\n      expect(timeAtLastHedgeAfter.eq(hedgeBlockTimestamp)).to.be.true\n      expect(priceAtLastHedgeAfter.eq(currentWSqueethPriceAfter)).to.be.true \n    })\n    \n    it(\"should revert price hedging if the price threshold has not been reached\", async () => {        \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n  \n      await expect(\n        crabStrategy.connect(depositor).priceHedgeOnUniswap(hedgeBlockTimestamp, ethers.utils.parseUnits('0.01'), BigNumber.from('0'))\n      ).to.be.revertedWith(\"Price hedging not allowed\");\n    })\n  })\n\n  describe(\"Buy auction\", async () => {\n    before(async () => {\n      const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp\n      await buyWSqueeth(swapRouter, wSqueeth, weth, owner.address, ethers.utils.parseUnits('10000'), currentBlockTimestamp + 10)\n    })\n\n    it(\"should revert if not positive PnL\", async () => {\n      // advance time for twap to update\n      await provider.send(\"evm_increaseTime\", [600])\n      await provider.send(\"evm_mine\", []) \n            \n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n      \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      // set next block timestamp     \n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.true;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.false;\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n\n      expect(isSellAuction).to.be.false\n\n      await expect(\n        crabStrategy.connect(depositor).priceHedgeOnUniswap(auctionTriggerTimer, 0, ethers.utils.parseUnits('0.0001'))\n      ).to.be.revertedWith(\"ds-math-sub-underflow\");\n    })\n\n    it(\"it should revert if profit is less than min ETH\", async () => {\n      const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp\n      await buyWSqueeth(swapRouter, wSqueeth, weth, owner.address, ethers.utils.parseUnits('10000'), currentBlockTimestamp + 10)\n\n      // advance time so hedge sign doesn't switch\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n\n      await provider.send(\"evm_increaseTime\", [auctionTime])\n      await provider.send(\"evm_mine\", [])  \n            \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      const normFactor = await controller.getExpectedNormalizationFactor()\n\n      const collatToDeposit = one.mul(normFactor).mul(2).mul(startingEthPrice).div(oracleScaleFactor).div(one)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(\"0\", ethers.utils.parseUnits(\"3\"), \"0\", {value: collatToDeposit.mul(10)})\n      const senderWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      await wSqueeth.connect(depositor).approve(crabStrategy.address, senderWsqueethBalanceBefore)\n\n      // set next block timestamp     \n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n      const hedgeBlockTimestamp = hedgeBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n\n      expect(isSellAuction).to.be.false\n\n      await expect(\n        crabStrategy.connect(depositor).priceHedgeOnUniswap(auctionTriggerTimer, 0, ethers.utils.parseUnits('5'))\n      ).to.be.revertedWith(\"profit is less than min ETH\");\n    })    \n    \n    it(\"it should allow a hedge based on price\", async () => {\n      // advance time so hedge sign doesn't switch\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp - auctionTime\n            \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      const normFactor = await controller.getExpectedNormalizationFactor()\n\n\n      const collatToDeposit = one.mul(normFactor).mul(2).mul(startingEthPrice).div(oracleScaleFactor).div(one)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(\"0\", ethers.utils.parseUnits(\"3\"), \"0\", {value: collatToDeposit.mul(10)})\n      const senderWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      await wSqueeth.connect(depositor).approve(crabStrategy.address, senderWsqueethBalanceBefore)\n\n      // set next block timestamp     \n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n      const hedgeBlockTimestamp = hedgeBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice)\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n\n      expect(isSellAuction).to.be.false\n\n      await crabStrategy.connect(depositor).priceHedgeOnUniswap(auctionTriggerTimer, 0, ethers.utils.parseUnits('0.001'))\n              \n      const currentWSqueethPriceAfter = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAmountAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAmountAfter = strategyVaultAfter.shortAmount\n      const timeAtLastHedgeAfter = await crabStrategy.timeAtLastHedge()\n      const priceAtLastHedgeAfter = await crabStrategy.priceAtLastHedge()\n\n      expect(isSimilar(strategyDebtAmountAfter.sub(strategyDebt).toString(), secondTargetHedge.mul(-1).toString())).to.be.true\n      expect(isSimilar(strategyCollateralAmountAfter.sub(ethDelta).toString(), (expectedEthProceeds.mul(-1)).toString())).to.be.true\n      expect(timeAtLastHedgeAfter.eq(hedgeBlockTimestamp)).to.be.true\n      expect(priceAtLastHedgeAfter.eq(currentWSqueethPriceAfter)).to.be.true \n    })    \n  })\n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/strategy/crab-hedge-uniswap-time-based.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport BigNumberJs from 'bignumber.js'\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategy } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity, buyWeth } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\nconst calcPriceMulAndAuctionPrice = (isNegativeTargetHedge: boolean, maxPriceMultiplier: BigNumber, minPriceMultiplier: BigNumber, auctionExecution: BigNumber, currentWSqueethPrice: BigNumber) : [BigNumber, BigNumber] => {\n  let priceMultiplier: BigNumber\n  let auctionWSqueethEthPrice: BigNumber\n\n  if(isNegativeTargetHedge) {\n    priceMultiplier = maxPriceMultiplier.sub(wmul(auctionExecution, maxPriceMultiplier.sub(minPriceMultiplier)))\n    auctionWSqueethEthPrice = wmul(currentWSqueethPrice, priceMultiplier);\n  } \n  else {\n    priceMultiplier = minPriceMultiplier.add(wmul(auctionExecution, maxPriceMultiplier.sub(minPriceMultiplier)))\n    auctionWSqueethEthPrice = wmul(currentWSqueethPrice, priceMultiplier);\n  }\n\n  return [priceMultiplier, auctionWSqueethEthPrice]\n}\n\ndescribe(\"Crab flashswap integration test: uniswap time based hedging\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.mul(12).div(10).div(oracleScaleFactor) // 0.303 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice*1.2 / oracleScaleFactor.toNumber() // 0.303\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let feeRecipient: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategy\n  let ethDaiPool: Contract\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _feeRecipient] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    feeRecipient = _feeRecipient;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      positionManager, \n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    await controller.connect(owner).setFeeRecipient(feeRecipient.address);\n    await controller.connect(owner).setFeeRate(100)\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n    \n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n    await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async() => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '1000000',\n      '2000000', \n      owner.address, \n      wSqueeth, \n      weth, \n      positionManager, \n      controller\n    )\n\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"Deposit into strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('20')\n    const msgvalue = ethers.utils.parseUnits('10.1')\n\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n    await crabStrategy.connect(depositor).flashDeposit(ethToDeposit, {value: msgvalue})\n    \n    const normFactor = await controller.normalizationFactor()\n    const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n    const feeRate = await controller.feeRate()\n    const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n    const squeethDelta = scaledStartingSqueethPrice1e18.mul(2);\n    const debtToMint = wdiv(ethToDeposit, (squeethDelta.add(ethFeePerWSqueeth)));\n    const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n    const debtAmount = strategyVault.shortAmount\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n    const lastHedgeTime = await crabStrategy.timeAtLastHedge()\n    const currentBlockNumber = await provider.getBlockNumber()\n    const currentBlock = await provider.getBlock(currentBlockNumber)\n    const timeStamp = currentBlock.timestamp\n    const collateralAmount = await strategyVault.collateralAmount\n\n    expect(isSimilar(totalSupply.toString(),(expectedEthDeposit).toString())).to.be.true\n    expect(isSimilar(depositorCrab.toString(),(expectedEthDeposit).toString())).to.be.true\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString())).to.be.true\n    expect(depositorSqueethBalance.eq(depositorSqueethBalanceBefore)).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n    expect(lastHedgeTime.eq(timeStamp)).to.be.true\n  })\n\n  describe(\"Sell auction\", async () => {\n    it(\"should revert time hedging if the time threshold has not been reached\", async () => {  \n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])  \n      expect((timeAtLastHedge.add(hedgeTimeThreshold)).gt(hedgeBlockTimestamp)).to.be.true\n  \n      await expect(\n        crabStrategy.connect(depositor).timeHedgeOnUniswap(ethers.utils.parseUnits('0.01'), ethers.utils.parseUnits('0.0001'))\n      ).to.be.revertedWith(\"Time hedging is not allowed\");\n    })  \n\n    it(\"should revert hedging if strategy is delta neutral\", async () => {  \n          \n      await provider.send(\"evm_increaseTime\", [hedgeTimeThreshold])\n      await provider.send(\"evm_mine\", [])\n\n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])  \n        \n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)\n\n      expect(targetHedge.abs().eq(BigNumber.from(0)) || isSimilar(initialWSqueethDelta.toString(), ethDelta.toString())).to.be.true\n      await expect(\n        crabStrategy.connect(depositor).timeHedgeOnUniswap(ethers.utils.parseUnits('0.01'), ethers.utils.parseUnits('0.0001'))\n      ).to.be.revertedWith(\"strategy is delta neutral\");\n    })\n\n    it(\"should revert hedging if target hedge sign change (auction change from selling to buying)\", async () => {\n      // change pool price for auction to be sell auction\n      const ethToDeposit = ethers.utils.parseUnits('1000')\n      const wSqueethToMint = ethers.utils.parseUnits('1000')\n      const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp\n      await controller.connect(owner).mintWPowerPerpAmount(\"0\", wSqueethToMint, \"0\", {value: ethToDeposit})\n      await buyWeth(swapRouter, wSqueeth, weth, owner.address, (await wSqueeth.balanceOf(owner.address)), currentBlockTimestamp + 10)\n\n      await provider.send(\"evm_increaseTime\", [600])\n      await provider.send(\"evm_mine\", [])              \n\n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])      \n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)        \n      const isSellAuction = targetHedge.isNegative()\n\n      expect(isSellAuction).to.be.true\n\n      await expect(\n        crabStrategy.connect(depositor).timeHedgeOnUniswap(ethers.utils.parseUnits('0.01'), ethers.utils.parseUnits('0.0001'))\n      ).to.be.revertedWith(\"auction direction changed\");\n    })\n\n    it(\"should revert if not positive PnL\", async () => {\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      const hedgeTimeTolerance = await crabStrategy.hedgeTimeThreshold()      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeTolerance)\n      \n      // advanced more time to avoid traget hedge sign change\n      await provider.send(\"evm_increaseTime\", [auctionTime/3])\n      await provider.send(\"evm_mine\", [])        \n      \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n  \n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.true;\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.false;\n  \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      \n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n\n      expect(isSellAuction).to.be.true\n      expect(expectedAuctionWSqueethEthPrice.lt(currentWSqueethPrice)).to.be.true\n\n      await expect(\n        crabStrategy.connect(depositor).timeHedgeOnUniswap(ethers.utils.parseUnits('0.01'), ethers.utils.parseUnits('0.0001'))\n      ).to.be.revertedWith(\"ds-math-sub-underflow\");\n    })\n\n    it(\"hedge on uniswap based on time threshold\", async () => {\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      const hedgeTimeTolerance = await crabStrategy.hedgeTimeThreshold()      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeTolerance)\n      \n      // advanced more time to avoid traget hedge sign change\n      await provider.send(\"evm_increaseTime\", [auctionTime])\n      await provider.send(\"evm_mine\", [])        \n      \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 100;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n  \n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.true;\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.false;\n  \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      \n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n  \n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n\n      expect(isSellAuction).to.be.true\n\n      const depositorWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await crabStrategy.connect(depositor).timeHedgeOnUniswap(ethers.utils.parseUnits('0.01'), ethers.utils.parseUnits('0.0001'));\n\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtAfter = strategyVaultAfter.shortAmount\n      const depositorWsqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const ethDeltaAfter = strategyVault.collateralAmount\n\n      expect(isSimilar(expectedEthDeposited.toString(), strategyVaultAfter.collateralAmount.toString()))\n      expect(isSimilar((secondTargetHedge.mul(-1)).toString(),(strategyDebtAfter.sub(strategyDebt)).toString()))\n      expect(isSimilar((expectedEthProceeds).toString(),ethDeltaAfter.sub(ethDelta).toString()))\n      expect(depositorWsqueethBalanceAfter.gt(depositorWsqueethBalanceBefore)).to.be.true\n    })\n  })\n\n  describe(\"Buy auction\", async () => {\n    before(async () => {\n      // change pool price for auction to be sell auction\n      const ethToDeposit = ethers.utils.parseUnits('1000')\n      const wSqueethToMint = ethers.utils.parseUnits('1000')\n      const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp\n      await controller.connect(owner).mintWPowerPerpAmount(\"0\", wSqueethToMint, \"0\", {value: ethToDeposit})\n      await buyWeth(swapRouter, wSqueeth, weth, owner.address, (await wSqueeth.balanceOf(owner.address)), currentBlockTimestamp + 10)\n    })\n    it(\"should revert time hedging if the time threshold has not been reached\", async () => {  \n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])  \n      expect((timeAtLastHedge.add(hedgeTimeThreshold)).gt(hedgeBlockTimestamp)).to.be.true\n  \n      await expect(\n        crabStrategy.connect(depositor).timeHedgeOnUniswap(ethers.utils.parseUnits('0.01'), ethers.utils.parseUnits('0.0001'))\n      ).to.be.revertedWith(\"Time hedging is not allowed\");\n    })  \n\n    it(\"should revert hedging if target hedge sign change (auction change from buying to selling)\", async () => {\n      await provider.send(\"evm_increaseTime\", [hedgeTimeThreshold + 1])\n      await provider.send(\"evm_mine\", [])\n\n      await provider.send(\"evm_increaseTime\", [10])\n      await provider.send(\"evm_mine\", [])              \n\n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])      \n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)        \n      const isSellAuction = targetHedge.isNegative()\n\n      expect(isSellAuction).to.be.false\n\n      await expect(\n        crabStrategy.connect(depositor).timeHedgeOnUniswap(ethers.utils.parseUnits('0.01'), ethers.utils.parseUnits('0.0001'))\n      ).to.be.revertedWith(\"auction direction changed\");\n    })\n\n    it(\"should revert if not positive PnL\", async () => {\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      const hedgeTimeTolerance = await crabStrategy.hedgeTimeThreshold()      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeTolerance)\n      \n      // advanced more time to avoid traget hedge sign change\n      await provider.send(\"evm_increaseTime\", [auctionTime/3])\n      await provider.send(\"evm_mine\", [])        \n      \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 100;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n  \n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.true;\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.false;\n  \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      \n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n\n      expect(isSellAuction).to.be.false\n      expect(expectedAuctionWSqueethEthPrice.lt(currentWSqueethPrice)).to.be.true\n\n      await expect(\n        crabStrategy.connect(depositor).timeHedgeOnUniswap(ethers.utils.parseUnits('0.01'), ethers.utils.parseUnits('0.0001'))\n      ).to.be.revertedWith(\"ds-math-sub-underflow\");\n    })\n\n    it(\"hedge based on time on uniswap\", async () => {      \n      // advanced more time to avoid traget hedge sign change\n      await provider.send(\"evm_increaseTime\", [auctionTime])\n      await provider.send(\"evm_mine\", [])        \n      \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 100;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n    \n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.true;\n  \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n  \n      expect(isSellAuction).to.be.false\n  \n      const depositorWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n      \n      await crabStrategy.connect(depositor).timeHedgeOnUniswap(ethers.utils.parseUnits('0.01'), ethers.utils.parseUnits('0.0001'));\n      \n      const depositorWsqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n  \n      expect(depositorEthBalanceAfter.gte(depositorEthBalanceBefore)).to.be.true\n      expect(depositorWsqueethBalanceAfter.eq(depositorWsqueethBalanceBefore)).to.be.true\n    })\n  })\n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/strategy/crab-hedging-price-based.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport BigNumberJs from 'bignumber.js'\n\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategy } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity, buyWSqueeth, buyWeth } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\nconst calcPriceMulAndAuctionPrice = (isNegativeTargetHedge: boolean, maxPriceMultiplier: BigNumber, minPriceMultiplier: BigNumber, auctionExecution: BigNumber, currentWSqueethPrice: BigNumber) : [BigNumber, BigNumber] => {\n  let priceMultiplier: BigNumber\n  let auctionWSqueethEthPrice: BigNumber\n\n  if(isNegativeTargetHedge) {\n    priceMultiplier = maxPriceMultiplier.sub(wmul(auctionExecution, maxPriceMultiplier.sub(minPriceMultiplier)))\n    auctionWSqueethEthPrice = wmul(currentWSqueethPrice, priceMultiplier);\n  } \n  else {\n    priceMultiplier = minPriceMultiplier.add(wmul(auctionExecution, maxPriceMultiplier.sub(minPriceMultiplier)))\n    auctionWSqueethEthPrice = wmul(currentWSqueethPrice, priceMultiplier);\n  }\n\n  return [priceMultiplier, auctionWSqueethEthPrice]\n}\n\ndescribe(\"Crab flashswap integration test: price based hedging\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.mul(11).div(10).div(oracleScaleFactor) // 0.303 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice*1.1 / oracleScaleFactor.toNumber() // 0.303\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n  let initialTimestamp : number\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let feeRecipient: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategy\n  let ethDaiPool: Contract\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _feeRecipient] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    feeRecipient = _feeRecipient;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      positionManager, \n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    await controller.connect(owner).setFeeRecipient(feeRecipient.address);\n    await controller.connect(owner).setFeeRate(100)\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n    \n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n    await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n\n    // Record time stamp at initialization\n    const currentBlockNumber = await provider.getBlockNumber()\n    const currentBlock = await provider.getBlock(currentBlockNumber)\n    initialTimestamp = currentBlock.timestamp\n\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async() => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '1000000',\n      '2000000', \n      owner.address, \n      wSqueeth, \n      weth, \n      positionManager, \n      controller\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"Deposit into strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('20')\n    const msgvalue = ethers.utils.parseUnits('10.1')\n\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n    await crabStrategy.connect(depositor).flashDeposit(ethToDeposit, {value: msgvalue})\n    \n    const normFactor = await controller.normalizationFactor()\n    const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n    const feeRate = await controller.feeRate()\n    const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n    const squeethDelta = scaledStartingSqueethPrice1e18.mul(2);\n    const debtToMint = wdiv(ethToDeposit, (squeethDelta.add(ethFeePerWSqueeth)));\n    const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n    const debtAmount = strategyVault.shortAmount\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n    const lastHedgeTime = await crabStrategy.timeAtLastHedge()\n    const currentBlockNumber = await provider.getBlockNumber()\n    const currentBlock = await provider.getBlock(currentBlockNumber)\n    const timeStamp = currentBlock.timestamp\n    const collateralAmount = await strategyVault.collateralAmount\n\n    expect(isSimilar(totalSupply.toString(),(expectedEthDeposit).toString())).to.be.true\n    expect(isSimilar(depositorCrab.toString(),(expectedEthDeposit).toString())).to.be.true\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString())).to.be.true\n    expect(depositorSqueethBalance.eq(depositorSqueethBalanceBefore)).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n    expect(lastHedgeTime.eq(timeStamp)).to.be.true\n  })\n\n  describe(\"Sell auction\", async () => {\n    before(async () => {\n      \n      // ensure that we have a twap of 600s\n      await provider.send(\"evm_increaseTime\", [600])\n      await provider.send(\"evm_mine\", [])\n    })\n\n    it(\"should revert price hedging if the time threshold has not been reached\", async () => {  \n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])  \n      expect((timeAtLastHedge.add(hedgeTimeThreshold)).gt(hedgeBlockTimestamp)).to.be.true\n  \n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)\n      const isSellAuction = targetHedge.isNegative()\n      await expect(\n        crabStrategy.connect(depositor).priceHedge(hedgeBlockTimestamp, isSellAuction, 0, {value: 1})\n      ).to.be.revertedWith(\"Price hedging not allowed\");\n    })\n    \n    it(\"price hedging should not immediately be eligible for a hedge\", async () => {\n      // change pool price\n      const ethToDeposit = ethers.utils.parseUnits('10000')\n      const wSqueethToMint = ethers.utils.parseUnits('10000')\n      const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp\n      await controller.connect(owner).mintWPowerPerpAmount(\"0\", wSqueethToMint, \"0\", {value: ethToDeposit})\n      await buyWeth(swapRouter, wSqueeth, weth, owner.address, (await wSqueeth.balanceOf(owner.address)), currentBlockTimestamp + 10)\n\n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      \n      expect(priceDeviation.lt(hedgePriceThreshold))\n\n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])   \n      \n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.false;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.false;\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)  \n\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n\n      await expect(\n        crabStrategy.connect(depositor).priceHedge(auctionTriggerTimer, isSellAuction, expectedAuctionWSqueethEthPrice, {value: expectedEthProceeds})\n      ).to.be.revertedWith(\"Price hedging not allowed\");\n    })\n    \n    it(\"it should be eligible for a hedge after time has passed for twap to update but will revert due to hedge sign change\", async () => {\n      // advance time for twap to update\n      await provider.send(\"evm_increaseTime\", [600])\n      await provider.send(\"evm_mine\", [])  \n\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n      \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      // set next block timestamp     \n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.true;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.false;\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)  \n\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n\n      expect(isSellAuction).to.be.true\n\n      await expect(\n        crabStrategy.connect(depositor).priceHedge(auctionTriggerTimer, isSellAuction, expectedAuctionWSqueethEthPrice, {value: expectedEthProceeds.add(1)})\n      ).to.be.revertedWith(\"auction direction changed\");\n    })    \n\n    it(\"it should revert if hedger specifies the wrong direction\", async () => {\n      // advance time so hedge sign doesn't switch\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n\n      await provider.send(\"evm_increaseTime\", [auctionTime/2])\n      await provider.send(\"evm_mine\", [])  \n      \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n\n      // set next block timestamp     \n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n      const hedgeBlockTimestamp = hedgeBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)  \n\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n\n      expect(isSellAuction).to.be.true\n\n      await expect(\n        crabStrategy.connect(depositor).priceHedge(auctionTriggerTimer, !isSellAuction, expectedAuctionWSqueethEthPrice, {value: expectedEthProceeds.add(1)})\n      ).to.be.revertedWith(\"wrong auction type\");\n    })\n    \n    it(\"it should allow a hedge based on price\", async () => {\n      // advance time so hedge sign doesn't switch\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n\n      await provider.send(\"evm_increaseTime\", [auctionTime/2])\n      await provider.send(\"evm_mine\", [])  \n            \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      // set next block timestamp     \n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n      const hedgeBlockTimestamp = hedgeBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n   \n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n  \n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n\n      expect(isSellAuction).to.be.true\n\n      const senderWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      // this fails when running yarn test but not as an individial test as expectedEthProceeds and secondTargetHedge is off by 1wei in yarn test but not in single test run\n      // any ideas?\n      await crabStrategy.connect(depositor).priceHedge(auctionTriggerTimer, isSellAuction, expectedAuctionWSqueethEthPrice, {value: expectedEthProceeds.add(1)})\n              \n      const currentWSqueethPriceAfter = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAmountAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAmountAfter = strategyVaultAfter.shortAmount\n      const senderWsqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const timeAtLastHedgeAfter = await crabStrategy.timeAtLastHedge()\n      const priceAtLastHedgeAfter = await crabStrategy.priceAtLastHedge()\n\n      expect(isSimilar(senderWsqueethBalanceAfter.sub(senderWsqueethBalanceBefore).toString(), secondTargetHedge.mul(-1).toString())).to.be.true\n      expect(isSimilar(strategyDebtAmountAfter.sub(strategyDebt).toString(), secondTargetHedge.mul(-1).toString())).to.be.true\n      expect(isSimilar(strategyCollateralAmountAfter.sub(ethDelta).toString(), expectedEthDeposited.toString())).to.be.true\n      expect(timeAtLastHedgeAfter.eq(hedgeBlockTimestamp)).to.be.true\n      expect(priceAtLastHedgeAfter.eq(currentWSqueethPriceAfter)).to.be.true \n    })    \n  })\n\n  describe(\"Buy auction\", async () => {\n    before(async () => {\n      const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp\n      await buyWSqueeth(swapRouter, wSqueeth, weth, owner.address, ethers.utils.parseUnits('7500'), currentBlockTimestamp + 10)\n    })\n\n    it(\"should not immediately be eligible for a hedge\", async () => {\n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      \n      expect(priceDeviation.lt(hedgePriceThreshold))\n\n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])  \n      \n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.false;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.false;\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n\n      const senderWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      await wSqueeth.connect(depositor).approve(crabStrategy.address, senderWsqueethBalanceBefore)\n\n      await expect(\n        crabStrategy.connect(depositor).priceHedge(auctionTriggerTimer, isSellAuction, expectedAuctionWSqueethEthPrice)\n      ).to.be.revertedWith(\"Price hedging not allowed\");\n    })    \n\n    it(\"it should be eligible for a hedge after time has passed for twap to update but will revert due to hedge sign change\", async () => {\n      // advance time for twap to update\n      await provider.send(\"evm_increaseTime\", [600])\n      await provider.send(\"evm_mine\", []) \n      \n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n      \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      // set next block timestamp     \n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.true;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.false;\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n\n      expect(isSellAuction).to.be.false\n\n      await expect(\n        crabStrategy.connect(depositor).priceHedge(auctionTriggerTimer, isSellAuction, expectedAuctionWSqueethEthPrice)\n      ).to.be.revertedWith(\"auction direction changed\");\n    })    \n\n    it(\"it should revert if hedger specifies the wrong direction\", async () => {\n      // advance time so hedge sign doesn't switch\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n\n      await provider.send(\"evm_increaseTime\", [auctionTime/2])\n      await provider.send(\"evm_mine\", [])  \n            \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      // set next block timestamp     \n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n      const hedgeBlockTimestamp = hedgeBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n\n      expect(isSellAuction).to.be.false\n\n      await expect(\n        crabStrategy.connect(depositor).priceHedge(auctionTriggerTimer, !isSellAuction,expectedAuctionWSqueethEthPrice)\n      ).to.be.revertedWith(\"wrong auction type\");\n    })\n    \n    it(\"it should revert if eth is attached to a buy auction\", async () => {      \n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n      \n      await provider.send(\"evm_increaseTime\", [auctionTime/2])\n      await provider.send(\"evm_mine\", [])  \n\n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      // set next block timestamp     \n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n      const hedgeBlockTimestamp = hedgeBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.true;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.false;\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n\n      expect(isSellAuction).to.be.false\n\n      await expect(\n        crabStrategy.connect(depositor).priceHedge(auctionTriggerTimer, isSellAuction, expectedAuctionWSqueethEthPrice, {value: 1})\n      ).to.be.revertedWith(\"ETH attached for buy auction\");\n    })   \n\n    it(\"it should revert if the limit price is breached\", async () => {      \n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n      \n      await provider.send(\"evm_increaseTime\", [auctionTime/2])\n      await provider.send(\"evm_mine\", [])  \n      \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      // set next block timestamp     \n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n      const hedgeBlockTimestamp = hedgeBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.true;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.false;\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      \n      expect(isSellAuction).to.be.false\n\n      await expect(\n        crabStrategy.connect(depositor).priceHedge(auctionTriggerTimer, isSellAuction, expectedAuctionWSqueethEthPrice.mul(2))\n      ).to.be.revertedWith(\"Auction price < min price\");\n    })  \n\n    it(\"it should allow a hedge based on price\", async () => {\n      // advance time so hedge sign doesn't switch\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const auctionTriggerTimer = currentBlock.timestamp\n\n      await provider.send(\"evm_increaseTime\", [auctionTime/2])\n      await provider.send(\"evm_mine\", [])  \n            \n      const priceAtLastHedge = await crabStrategy.priceAtLastHedge()\n      \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const priceChange = one.mul(currentWSqueethPrice).div(priceAtLastHedge)\n      const priceDeviation = priceChange.gt(one) ? priceChange.sub(one): one.sub(priceChange)\n      const canPriceHedge = await crabStrategy.checkPriceHedge(auctionTriggerTimer)\n\n      expect(priceDeviation.gt(hedgePriceThreshold))\n      expect(canPriceHedge).to.be.true\n\n      const normFactor = await controller.getExpectedNormalizationFactor()\n\n      const collatToDeposit = one.mul(normFactor).mul(2).mul(startingEthPrice).div(oracleScaleFactor).div(one)\n\n      await controller.connect(depositor).mintWPowerPerpAmount(\"0\", ethers.utils.parseUnits(\"3\"), \"0\", {value: collatToDeposit.mul(10)})\n      const senderWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      await wSqueeth.connect(depositor).approve(crabStrategy.address, senderWsqueethBalanceBefore)\n\n      // set next block timestamp     \n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n      const hedgeBlockTimestamp = hedgeBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice)\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n\n      expect(isSellAuction).to.be.false\n\n      await crabStrategy.connect(depositor).priceHedge(auctionTriggerTimer, isSellAuction, expectedAuctionWSqueethEthPrice)\n              \n      const currentWSqueethPriceAfter = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const senderWsqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAmountAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAmountAfter = strategyVaultAfter.shortAmount\n      const timeAtLastHedgeAfter = await crabStrategy.timeAtLastHedge()\n      const priceAtLastHedgeAfter = await crabStrategy.priceAtLastHedge()\n\n      expect(isSimilar(senderWsqueethBalanceAfter.sub(senderWsqueethBalanceBefore).toString(), secondTargetHedge.mul(-1).toString())).to.be.true\n      expect(isSimilar(strategyDebtAmountAfter.sub(strategyDebt).toString(), secondTargetHedge.mul(-1).toString())).to.be.true\n      expect(isSimilar(strategyCollateralAmountAfter.sub(ethDelta).toString(), (expectedEthProceeds.mul(-1)).toString())).to.be.true\n      expect(timeAtLastHedgeAfter.eq(hedgeBlockTimestamp)).to.be.true\n      expect(priceAtLastHedgeAfter.eq(currentWSqueethPriceAfter)).to.be.true \n    })\n\n    it(\"it should not allow a hedge based on a time before previous hedge\", async () => {\n\n      // Set trigger time just after initialization \n      const auctionTriggerTimer = initialTimestamp + 600\n      // Set up hedge            \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n      const hedgeBlockTimestamp = hedgeBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)      \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(wmul(strategyDebt, BigNumber.from(2).mul(one)), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice)\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n\n      // try to hedge at timestamp before last hedge\n      await expect( \n         crabStrategy.connect(depositor).priceHedge(auctionTriggerTimer, isSellAuction, expectedAuctionWSqueethEthPrice)\n      ).to.be.revertedWith(\"Price hedging not allowed\") \n      })\n  })\n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/strategy/crab-hedging-time-based.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport BigNumberJs from 'bignumber.js'\n\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategy } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity, buyWSqueeth, buyWeth } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\nconst calcPriceMulAndAuctionPrice = (isNegativeTargetHedge: boolean, maxPriceMultiplier: BigNumber, minPriceMultiplier: BigNumber, auctionExecution: BigNumber, currentWSqueethPrice: BigNumber) : [BigNumber, BigNumber] => {\n  let priceMultiplier: BigNumber\n  let auctionWSqueethEthPrice: BigNumber\n\n  if(isNegativeTargetHedge) {\n    priceMultiplier = maxPriceMultiplier.sub(wmul(auctionExecution, maxPriceMultiplier.sub(minPriceMultiplier)))\n    auctionWSqueethEthPrice = wmul(currentWSqueethPrice, priceMultiplier);\n  } \n  else {\n    priceMultiplier = minPriceMultiplier.add(wmul(auctionExecution, maxPriceMultiplier.sub(minPriceMultiplier)))\n    auctionWSqueethEthPrice = wmul(currentWSqueethPrice, priceMultiplier);\n  }\n\n  return [priceMultiplier, auctionWSqueethEthPrice]\n}\n\ndescribe(\"Crab flashswap integration test: time based hedging\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.mul(11).div(10).div(oracleScaleFactor) // 0.303 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice*1.1 / oracleScaleFactor.toNumber() // 0.303\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let random: SignerWithAddress;\n  let feeRecipient: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategy\n  let ethDaiPool: Contract\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _random, _feeRecipient ] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    random = _random;\n    feeRecipient = _feeRecipient;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      positionManager, \n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n    \n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n    await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async() => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '1000000',\n      '2000000', \n      owner.address, \n      wSqueeth, \n      weth, \n      positionManager, \n      controller\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"Deposit into strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('20')\n    const msgvalue = ethers.utils.parseUnits('10.1')\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n    await crabStrategy.connect(depositor).flashDeposit(ethToDeposit, {value: msgvalue})\n    \n    const normFactor = await controller.normalizationFactor()\n    const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n    const feeRate = await controller.feeRate()\n    const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n    const squeethDelta = scaledStartingSqueethPrice1e18.mul(2);\n    const debtToMint = wdiv(ethToDeposit, (squeethDelta.add(ethFeePerWSqueeth)));\n    const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n    const debtAmount = strategyVault.shortAmount\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n    const lastHedgeTime = await crabStrategy.timeAtLastHedge()\n    const currentBlockNumber = await provider.getBlockNumber()\n    const currentBlock = await provider.getBlock(currentBlockNumber)\n    const timeStamp = currentBlock.timestamp\n    const collateralAmount = await strategyVault.collateralAmount\n\n    expect(isSimilar(totalSupply.toString(),(expectedEthDeposit).toString())).to.be.true\n    expect(isSimilar(depositorCrab.toString(),(expectedEthDeposit).toString())).to.be.true\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString())).to.be.true\n    expect(depositorSqueethBalance.eq(depositorSqueethBalanceBefore)).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n    expect(lastHedgeTime.eq(timeStamp)).to.be.true\n  })\n\n  describe(\"Sell auction\", async () => {\n    it(\"should revert time hedging if the time threshold has not been reached\", async () => {  \n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])  \n      expect((timeAtLastHedge.add(hedgeTimeThreshold)).gt(hedgeBlockTimestamp)).to.be.true\n  \n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, true)\n      const strategyDebt = await strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)\n      const isSellAuction = targetHedge.isNegative()\n      await expect(\n        crabStrategy.connect(depositor).timeHedge(isSellAuction, 0, {value: 1})\n      ).to.be.revertedWith(\"Time hedging is not allowed\");\n    })  \n\n    it(\"should revert hedging if strategy is delta neutral\", async () => {  \n      \n          \n      await provider.send(\"evm_increaseTime\", [hedgeTimeThreshold])\n      await provider.send(\"evm_mine\", [])\n\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeThreshold)\n      \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])  \n      \n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n      \n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)  \n\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n\n      expect(targetHedge.abs().eq(BigNumber.from(0)) || isSimilar(initialWSqueethDelta.toString(), ethDelta.toString())).to.be.true\n      await expect(\n        crabStrategy.connect(depositor).timeHedge(isSellAuction, expectedAuctionWSqueethEthPrice, {value: 1})\n      ).to.be.revertedWith(\"strategy is delta neutral\");\n    })\n    \n    it(\"should revert hedging if target hedge sign change (auction change from selling to buying)\", async () => {\n      // change pool price for auction to be sell auction\n      const ethToDeposit = ethers.utils.parseUnits('1000')\n      const wSqueethToMint = ethers.utils.parseUnits('1000')\n      const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp\n      await controller.connect(owner).mintWPowerPerpAmount(\"0\", wSqueethToMint, \"0\", {value: ethToDeposit})\n      await buyWeth(swapRouter, wSqueeth, weth, owner.address, (await wSqueeth.balanceOf(owner.address)), currentBlockTimestamp + 10)\n\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeThreshold)\n\n      // advanced more time to avoid traget hedge sign change\n      await provider.send(\"evm_increaseTime\", [600])\n      await provider.send(\"evm_mine\", [])              \n\n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])      \n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)  \n\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n\n      expect(isSellAuction).to.be.true\n\n      await expect(\n        crabStrategy.connect(depositor).timeHedge(isSellAuction, expectedAuctionWSqueethEthPrice, {value: expectedEthProceeds.add(1)})\n      ).to.be.revertedWith(\"auction direction changed\");\n    })\n    \n    it(\"should revert hedging if sent ETH to sell for WSqueeth is not enough\", async () => {      \n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeThreshold)\n\n      // advanced more time to avoid traget hedge sign change\n      await provider.send(\"evm_increaseTime\", [auctionTime/2])\n      await provider.send(\"evm_mine\", [])      \n\n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 100;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])      \n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)  \n\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n\n      expect(isSellAuction).to.be.true\n\n      await expect(\n        crabStrategy.connect(depositor).timeHedge(isSellAuction, expectedAuctionWSqueethEthPrice, {value: expectedEthProceeds.sub(1)})\n      ).to.be.revertedWith(\"Low ETH amount received\");\n    })\n\n    it(\"should revert if hedger specifies wrong direction\", async () => {\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeThreshold)\n\n      // advanced more time to avoid traget hedge sign change\n      await provider.send(\"evm_increaseTime\", [10])\n      await provider.send(\"evm_mine\", [])              \n\n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])  \n      \n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)  \n\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n      \n      const isStrategySellingWSqueeth = false\n      expect(isSellAuction).to.be.true\n\n      await expect(\n        crabStrategy.connect(depositor).timeHedge(isStrategySellingWSqueeth, expectedAuctionWSqueethEthPrice, {value: expectedEthProceeds.add(1)})\n      ).to.be.revertedWith(\"wrong auction type\");\n    }) \n\n    it(\"should revert if hedger specifies a limit price that is low\", async () => {\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeThreshold)\n\n      // advanced more time to avoid traget hedge sign change\n      await provider.send(\"evm_increaseTime\", [10])\n      await provider.send(\"evm_mine\", [])              \n\n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 1;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp]) \n      \n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)  \n\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n\n      expect(isSellAuction).to.be.true\n\n      await expect(\n        crabStrategy.connect(depositor).timeHedge(isSellAuction, expectedAuctionWSqueethEthPrice.div(2), {value: expectedEthProceeds.add(1)})\n      ).to.be.revertedWith(\"Auction price > max price\");\n    }) \n\n    it(\"should hedge by selling WSqueeth for ETH and update timestamp and price at hedge\", async () => {\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeThreshold)\n              \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 100;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.false;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.true;\n\n      let currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledSquethPrice = (await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 300, false))\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledSquethPrice.mul(feeRate).div(10000)\n\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice.add(ethFeePerWSqueeth))        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice.add(ethFeePerWSqueeth))\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n      const expectedEthDeposited = expectedEthProceeds.sub(wmul(ethFeePerWSqueeth, secondTargetHedge.abs()))\n\n      expect(isSellAuction).to.be.true\n\n      expect(isSellAuction).to.be.true\n\n      const senderWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n        \n      await crabStrategy.connect(depositor).timeHedge(isSellAuction, expectedAuctionWSqueethEthPrice, {value: expectedEthProceeds.add(1)})\n      \n      const hedgeBlockNumber = await provider.getBlockNumber()\n      const hedgeBlock = await provider.getBlock(hedgeBlockNumber)\n\n      currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const senderWsqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAmountAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAmountAfter = strategyVaultAfter.shortAmount\n      const timeAtLastHedgeAfter = await crabStrategy.timeAtLastHedge()\n      const priceAtLastHedgeAfter = await crabStrategy.priceAtLastHedge()\n\n      expect(senderWsqueethBalanceAfter.gt(senderWsqueethBalanceBefore)).to.be.true\n      expect(isSimilar(senderWsqueethBalanceAfter.sub(senderWsqueethBalanceBefore).toString(), secondTargetHedge.abs().toString())).to.be.true\n      expect(isSimilar(strategyDebtAmountAfter.sub(strategyDebt).toString(), secondTargetHedge.abs().toString())).to.be.true\n      expect(isSimilar(strategyCollateralAmountAfter.sub(ethDelta).toString(), expectedEthDeposited.toString())).to.be.true\n      expect(timeAtLastHedgeAfter.eq(hedgeBlock.timestamp)).to.be.true\n      expect(priceAtLastHedgeAfter.eq(currentWSqueethPrice)).to.be.true \n    })\n  })\n\n  describe(\"Buy auction\", async () => {\n    before(async () => {\n      \n      \n      await provider.send(\"evm_increaseTime\", [hedgeTimeThreshold + 1])\n      await provider.send(\"evm_mine\", [])\n\n      // change pool price\n      const currentBlockTimestamp = (await provider.getBlock(await provider.getBlockNumber())).timestamp\n      await buyWSqueeth(swapRouter, wSqueeth, weth, owner.address, ethers.utils.parseUnits('10000'), currentBlockTimestamp + 10)\n      // set depositor balance to 0\n      await wSqueeth.connect(depositor).transfer(random.address, await wSqueeth.balanceOf(depositor.address))\n    })\n\n    it(\"should revert when the limit price is too high\", async () => {\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeThreshold)\n      \n      // advanced more time to avoid traget hedge sign change\n      await provider.send(\"evm_increaseTime\", [auctionTime/2])\n      await provider.send(\"evm_mine\", [])     \n      \n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 10;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n        \n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.false;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.true;\n\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)\n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n\n      expect(isSellAuction).to.be.false\n\n      const senderWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await wSqueeth.connect(depositor).approve(crabStrategy.address, senderWsqueethBalanceBefore)\n\n      await expect(\n        crabStrategy.connect(depositor).timeHedge(isSellAuction, expectedAuctionWSqueethEthPrice.mul(2))\n      ).to.be.revertedWith(\"Auction price < min price\");\n    })\n\n    it(\"should revert hedging when eth is attached to a buy hedge\", async () => {\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeThreshold)\n              \n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 10;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n        \n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.false;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.true;\n\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)\n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n\n      expect(isSellAuction).to.be.false\n\n      const senderWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await wSqueeth.connect(depositor).approve(crabStrategy.address, senderWsqueethBalanceBefore)\n\n      await expect(\n        crabStrategy.connect(depositor).timeHedge(isSellAuction, expectedAuctionWSqueethEthPrice, {value: 1})\n      ).to.be.revertedWith(\"ETH attached for buy auction\");\n    })\n\n\n    it(\"should revert hedging when WSqueeth seller have less amount that target hedge\", async () => {\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeThreshold)\n              \n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 10;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n      \n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n        \n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.false;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.true;\n\n      const currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)\n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n\n      expect(isSellAuction).to.be.false\n\n      const senderWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await wSqueeth.connect(depositor).approve(crabStrategy.address, senderWsqueethBalanceBefore)\n\n      await expect(\n        crabStrategy.connect(depositor).timeHedge(isSellAuction, expectedAuctionWSqueethEthPrice)\n      ).to.be.revertedWith(\"ERC20: transfer amount exceeds balance\");\n    })\n\n    it(\"should hedge by buying WSqueeth for ETH \", async () => {\n      const timeAtLastHedge = await crabStrategy.timeAtLastHedge()\n      \n      const auctionTriggerTimer = timeAtLastHedge.add(hedgeTimeThreshold)\n\n      // advanced more time to avoid traget hedge sign change\n      await provider.send(\"evm_increaseTime\", [auctionTime/2])\n      await provider.send(\"evm_mine\", [])                \n              \n      // set next block timestamp\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const hedgeBlockTimestamp = currentBlock.timestamp + 100;\n      await provider.send(\"evm_setNextBlockTimestamp\", [hedgeBlockTimestamp])\n\n      const auctionTimeElapsed = BigNumber.from(hedgeBlockTimestamp).sub(auctionTriggerTimer)\n\n      expect(await crabStrategy.checkPriceHedge(auctionTriggerTimer)).to.be.false;\n      expect((await crabStrategy.checkTimeHedge())[0]).to.be.true;\n\n      let currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const ethDelta = strategyVault.collateralAmount\n      const strategyDebt = strategyVault.shortAmount\n      const initialWSqueethDelta = wmul(strategyDebt.mul(2), currentWSqueethPrice)\n      const targetHedge = wdiv(initialWSqueethDelta.sub(ethDelta), currentWSqueethPrice)        \n      const isSellAuction = targetHedge.isNegative()\n      const auctionExecution = (auctionTimeElapsed.gte(BigNumber.from(auctionTime))) ? one : wdiv(auctionTimeElapsed, BigNumber.from(auctionTime))\n      const result = calcPriceMulAndAuctionPrice(isSellAuction, maxPriceMultiplier, minPriceMultiplier, auctionExecution, currentWSqueethPrice)\n      const expectedAuctionWSqueethEthPrice = result[1]\n      const finalWSqueethDelta = wmul(strategyDebt.mul(2), expectedAuctionWSqueethEthPrice)\n      const secondTargetHedge = wdiv(finalWSqueethDelta.sub(ethDelta), expectedAuctionWSqueethEthPrice)\n      const expectedEthProceeds = wmul(secondTargetHedge.abs(), expectedAuctionWSqueethEthPrice)\n\n      expect(isSellAuction).to.be.false\n\n      let collatToDeposit = wdiv(wmul(secondTargetHedge.abs(), ethDelta), strategyDebt) \n      if(collatToDeposit.lt(ethers.utils.parseUnits('0.5'))) {\n        collatToDeposit = ethers.utils.parseUnits('1')\n      }\n      await controller.connect(depositor).mintWPowerPerpAmount(\"0\", secondTargetHedge.abs(), \"0\", {value: collatToDeposit.add(collatToDeposit.mul(2).div(3))})\n      const senderWsqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await provider.send(\"evm_increaseTime\", [50])\n\n      await wSqueeth.connect(depositor).approve(crabStrategy.address, senderWsqueethBalanceBefore)\n      await crabStrategy.connect(depositor).timeHedge(isSellAuction, expectedAuctionWSqueethEthPrice)\n\n      currentWSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      const senderWsqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAmountAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAmountAfter = strategyVaultAfter.shortAmount\n      \n      expect(isSimilar(senderWsqueethBalanceBefore.sub(senderWsqueethBalanceAfter).toString(), secondTargetHedge.toString())).to.be.true\n      expect(isSimilar(strategyDebt.sub(strategyDebtAmountAfter).toString(), secondTargetHedge.toString())).to.be.true\n      expect(isSimilar(ethDelta.sub(strategyCollateralAmountAfter).toString(), expectedEthProceeds.abs().toString())).to.be.true\n    })\n  })\n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/strategy/crab-liquidation-dust.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport BigNumberJs from 'bignumber.js'\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategy, ISwapRouter } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\ndescribe(\"Crab integration test: crab vault dust liquidation with excess collateral\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress;\n  let liquidator: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategy\n  let ethDaiPool: Contract\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _depositor2, _liquidator ] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    depositor2 = _depositor2;\n    liquidator = _liquidator;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      positionManager, \n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n  \n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n    await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async() => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '1000000',\n      '2000000', \n      owner.address, \n      wSqueeth, \n      weth, \n      positionManager, \n      controller\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"Deposit into strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('0.51')\n    const msgvalue = ethers.utils.parseUnits('0.51')\n    const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, true)\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n    await crabStrategy.connect(depositor).deposit({value: msgvalue})\n    const [operator, nftId, collateralAmount, debtAmount] = await crabStrategy.getVaultDetails()\n\n    const normFactor = await controller.normalizationFactor()\n    const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n    const feeRate = await controller.feeRate()\n    const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)\n    const squeethDelta = scaledStartingSqueethPrice1e18.mul(2);\n    const debtToMint = wdiv(ethToDeposit, (squeethDelta.add(ethFeePerWSqueeth)));\n    const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n    const lastHedgeTime = await crabStrategy.timeAtLastHedge()\n    const currentBlockNumber = await provider.getBlockNumber()\n    const currentBlock = await provider.getBlock(currentBlockNumber)\n    const timeStamp = currentBlock.timestamp\n\n    expect(totalSupply.eq(ethToDeposit)).to.be.true\n    expect(depositorCrab.eq(ethToDeposit)).to.be.true\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString())).to.be.true\n    expect(isSimilar((depositorSqueethBalance.sub(depositorSqueethBalanceBefore)).toString(),(debtToMint).toString())).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n    expect(lastHedgeTime.eq(timeStamp)).to.be.true\n    \n  })\n\n  describe(\"liquidate vault\", async () => {\n    before('push weth price higher to make crab vault liquidatable', async() => {\n      const poolWethBalance = await weth.balanceOf(ethDaiPool.address)\n\n      const maxDai = poolWethBalance.mul(startingEthPrice).mul(5)\n\n      const exactOutputParam = {\n        tokenIn: dai.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"15\"),\n        amountInMaximum: maxDai,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await dai.connect(owner).mint(owner.address, maxDai, )\n      await dai.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('push squeeth price higher', async() => {\n      // set squeeth price higher by buying 15% of squeeth in the pool\n      const poolSqueethBalance = await wSqueeth.balanceOf(wSqueethPool.address)\n\n      const maxWeth = poolSqueethBalance.mul(scaledStartingSqueethPrice1e18).mul(5).div(one)\n            \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"150000\"),\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(owner).deposit({value: maxWeth})\n      await weth.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('prepare liquidator to liquidate strategy', async() => {\n      await provider.send(\"evm_increaseTime\", [600]) // increase time by 600 sec\n      await provider.send(\"evm_mine\", [])\n\n      const vaultId = await crabStrategy.vaultId();\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      const vaultBefore = await controller.vaults(vaultId)\n      \n      const mintAmount = vaultBefore.shortAmount\n      const collateralRequired = mintAmount.mul(newEthPrice).mul(2).div(oracleScaleFactor).div(one).mul(2)\n\n      // mint squeeth to liquidate vault0!\n      await controller.connect(liquidator).mintWPowerPerpAmount(0, mintAmount, 0, {value: collateralRequired})\n    })\n\n    it(\"should liquidate crab vault using a full dust (0 collateral >0 debt remain)\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.false\n\n      const newSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 600, false)\n      \n      const vaultBefore = await controller.vaults(vaultId)\n\n      // state before liquidation\n      const liquidatorSqueethBefore = await wSqueeth.balanceOf(liquidator.address)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount\n\n      await controller.connect(liquidator).liquidate(vaultId, wSqueethAmountToLiquidate);\n      \n      const normFactor = await controller.normalizationFactor()\n      const collateralToGet = newSqueethPrice.mul(wSqueethAmountToLiquidate).div(one).mul(11).div(10)\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const liquidatorSqueethAfter = await wSqueeth.balanceOf(liquidator.address)\n      \n      // expect(collateralToGet.eq(liquidatorBalanceAfter.sub(liquidatorBalanceBefore))).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(liquidatorSqueethBefore.sub(liquidatorSqueethAfter))).to.be.true\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.equal\n      expect(vaultAfter.collateralAmount.gt(BigNumber.from(0))).to.be.equal\n      \n    })\n\n    it(\"should revert if user flash deposits post liquidation due to AS, because of amount specified of 0\", async () => {\n        const vaultId = await crabStrategy.vaultId();\n        const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n        expect(isVaultSafe).to.be.true\n  \n        const vaultBefore = await controller.vaults(vaultId)\n        const collateralBefore = vaultBefore.collateralAmount\n        const debtBefore = vaultBefore.shortAmount\n  \n        const ethToDeposit = ethers.utils.parseUnits('20')\n        const msgvalue = ethers.utils.parseUnits('15')  \n        const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n      \n        expect(strategyCollateralAmountBefore.eq(collateralBefore)).to.be.true\n        expect(strategyDebtAmountBefore.eq(debtBefore)).to.be.true\n  \n        await expect(crabStrategy.connect(depositor2).flashDeposit(ethToDeposit, {value: msgvalue})).to.be.revertedWith(\"AS\")\n    })\n\n    it(\"should let user deposit post liquidation, with only ETH, and mint no squeeth for them\", async () => {\n        const vaultId = await crabStrategy.vaultId();\n        const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n        expect(isVaultSafe).to.be.true\n  \n        const vaultBefore = await controller.vaults(vaultId)\n        const collateralBefore = vaultBefore.collateralAmount\n        const debtBefore = vaultBefore.shortAmount\n        const msgvalue = ethers.utils.parseUnits('1')\n        const totalSupplyBefore = (await crabStrategy.totalSupply())\n\n        const expectedRatio = one.mul(msgvalue).div(collateralBefore.add(msgvalue))\n        const expectedCrabMint = expectedRatio.mul(totalSupplyBefore).div(one.sub(expectedRatio))\n\n        expect(totalSupplyBefore.gt(BigNumber.from(0))).to.be.true\n        expect(collateralBefore.gt(BigNumber.from(0))).to.be.true\n        expect(debtBefore.eq(BigNumber.from(0))).to.be.true\n\n        const userEthBalanceBefore = await provider.getBalance(depositor2.address)\n        const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor2.address);\n        const userSqueethBalanceBefore = await wSqueeth.balanceOf(depositor2.address)\n\n        await crabStrategy.connect(depositor2).deposit({value: msgvalue})\n\n        const userEthBalanceAfter = await provider.getBalance(depositor2.address)\n        const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor2.address);\n        const userSqueethBalanceAfter = await wSqueeth.balanceOf(depositor2.address)\n        const [strategyOperatorAfter, strategyNftIdAfter, strategyCollateralAmountAfter, strategyDebtAmountAfter] = await crabStrategy.getVaultDetails()\n        const totalSupplyAfter = (await crabStrategy.totalSupply())\n\n        // expect((userEthBalanceBefore.sub(userEthBalanceAfter)).eq(msgvalue)).to.be.true\n        expect(userSqueethBalanceBefore.eq(userSqueethBalanceAfter)).to.be.true        \n        expect(isSimilar((userCrabBalanceAfter.sub(userCrabBalanceBefore)).toString(),(expectedCrabMint).toString())).to.be.true\n        expect(strategyDebtAmountAfter.eq(debtBefore)).to.be.true\n        expect(strategyCollateralAmountAfter.eq(collateralBefore.add(msgvalue))).to.be.true\n        expect(isSimilar((totalSupplyAfter.sub(totalSupplyBefore)).toString(),(expectedCrabMint).toString())).to.be.true  \n      })\n\n    it(\"depositor should revert trying to flashWithdraw with AS due to amount of wSqueeth to buy being 0\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio,strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay,wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethToWithdraw.mul(10).div(10)\n\n      await expect( crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay)).to.be.revertedWith(\"AS\")\n\n    })\n\n    it(\"depositor should be able to withdraw and get some ETH, without any wSqueeth\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n      const userEthBalanceBefore = await provider.getBalance(depositor.address)\n      const userSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n      \n      const vaultBefore = await controller.vaults(vaultId)\n      const expectedWithdrawal = vaultBefore.collateralAmount.sub(ethers.utils.parseUnits(\"1\"))\n      const collateralBefore = vaultBefore.collateralAmount\n      const debtBefore = vaultBefore.shortAmount\n      const totalSupplyBefore = await crabStrategy.totalSupply()\n      const expectedShareWithdrawal = collateralBefore.mul(userCrabBalanceBefore).div(totalSupplyBefore)\n\n      expect(isSimilar(expectedWithdrawal.toString(), expectedShareWithdrawal.toString())).to.be.true\n\n      await crabStrategy.connect(depositor).withdraw(userCrabBalanceBefore)\n\n      const userEthBalanceAfter = await provider.getBalance(depositor.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor.address);\n      const userSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const [strategyOperatorAfter, strategyNftIdAfter, strategyCollateralAmountAfter, strategyDebtAmountAfter] = await crabStrategy.getVaultDetails()\n\n      const debtAfter = vaultBefore.shortAmount\n      const totalSupplyAfter = await crabStrategy.totalSupply()\n\n      // expect(isSimilar((userEthBalanceAfter.sub(userEthBalanceBefore)).toString(),(expectedShareWithdrawal).toString())).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(userSqueethBalanceAfter.eq(userSqueethBalanceBefore)).to.be.true\n      // expect(strategyCollateralAmountBefore.sub(strategyCollateralAmountAfter).eq(userEthBalanceAfter.sub(userEthBalanceBefore))).to.be.true\n      expect(debtAfter.eq(debtBefore)).to.be.true\n      expect(isSimilar((totalSupplyBefore.sub(totalSupplyAfter)).toString(),(userCrabBalanceBefore).toString())).to.be.true\n    })\n  })\n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/strategy/crab-liquidation-full.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport BigNumberJs from 'bignumber.js'\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategy, ISwapRouter } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\ndescribe(\"Crab integration test: crab vault full liquidation and shutdown of contracts\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress;\n  let liquidator: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategy\n  let ethDaiPool: Contract\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _depositor2, _liquidator ] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    depositor2 = _depositor2;\n    liquidator = _liquidator;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      positionManager, \n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n  \n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n    await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async() => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '1000000',\n      '2000000', \n      owner.address, \n      wSqueeth, \n      weth, \n      positionManager, \n      controller\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"Deposit into strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('20')\n    const msgvalue = ethers.utils.parseUnits('20')\n    const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, true)\n\n    const squeethDelta = ethPrice.mul(2).div(1e4);\n    const debtToMint = wdiv(ethToDeposit, squeethDelta);\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n    await crabStrategy.connect(depositor).deposit({value: msgvalue})\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, debtAmount] = await crabStrategy.getVaultDetails()\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n    const lastHedgeTime = await crabStrategy.timeAtLastHedge()\n    const currentBlockNumber = await provider.getBlockNumber()\n    const currentBlock = await provider.getBlock(currentBlockNumber)\n    const timeStamp = currentBlock.timestamp\n\n    expect(totalSupply.eq(ethToDeposit)).to.be.true\n    expect(depositorCrab.eq(ethToDeposit)).to.be.true\n    // these had to be adjusted - it seems the eth price is a bit different than expected maybe? but only in coverage???\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString(),3)).to.be.true\n    expect(isSimilar((depositorSqueethBalance.sub(depositorSqueethBalanceBefore)).toString(),(debtToMint).toString(),3)).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n    expect(lastHedgeTime.eq(timeStamp)).to.be.true\n    \n  })\n\n  describe(\"liquidate vault\", async () => {\n    before('push weth price higher to make crab vault liquidatable', async() => {\n      const poolWethBalance = await weth.balanceOf(ethDaiPool.address)\n\n      const maxDai = poolWethBalance.mul(startingEthPrice).mul(20)\n\n      const exactOutputParam = {\n        tokenIn: dai.address,\n        tokenOut: weth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"50\"),\n        amountInMaximum: maxDai,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await dai.connect(owner).mint(owner.address, maxDai, )\n      await dai.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('push squeeth price higher', async() => {\n      // set squeeth price higher by buying 50% of squeeth in the pool\n      const poolSqueethBalance = await wSqueeth.balanceOf(wSqueethPool.address)\n\n      const maxWeth = poolSqueethBalance.mul(scaledStartingSqueethPrice1e18).mul(20).div(one)\n            \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"500000\"),\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(owner).deposit({value: maxWeth})\n      await weth.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n    })\n\n    before('prepare liquidator to liquidate strategy', async() => {\n      await provider.send(\"evm_increaseTime\", [600]) // increase time by 600 sec\n      await provider.send(\"evm_mine\", [])\n\n      const vaultId = await crabStrategy.vaultId();\n      const newEthPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, false)\n      const vaultBefore = await controller.vaults(vaultId)\n      \n      const mintAmount = vaultBefore.shortAmount\n      const collateralRequired = mintAmount.mul(newEthPrice).mul(2).div(oracleScaleFactor).div(one).mul(2)\n\n      // mint squeeth to liquidate vault0!\n      await controller.connect(liquidator).mintWPowerPerpAmount(0, mintAmount, 0, {value: collateralRequired})\n    })\n\n    it(\"should liquidate crab vault using a full insolvent liquidation (0 collateral 0 debt remain)\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.false\n\n      const vaultBefore = await controller.vaults(vaultId)\n      \n      // state before liquidation\n      const liquidatorSqueethBefore = await wSqueeth.balanceOf(liquidator.address)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n\n      const wSqueethAmountToLiquidate = vaultBefore.shortAmount\n\n      await controller.connect(liquidator).liquidate(vaultId, wSqueethAmountToLiquidate);\n      \n      const collateralToGet = vaultBefore.collateralAmount\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const liquidatorSqueethAfter = await wSqueeth.balanceOf(liquidator.address)\n      \n      // expect(collateralToGet.eq(liquidatorBalanceAfter.sub(liquidatorBalanceBefore))).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(liquidatorSqueethBefore.sub(liquidatorSqueethAfter))).to.be.true\n      expect(vaultAfter.shortAmount.eq(BigNumber.from(0))).to.be.equal\n      expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.equal\n      \n    })\n\n    it(\"should NOT let user flash deposit post liquidation\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralBefore = vaultBefore.collateralAmount\n      const debtBefore = vaultBefore.shortAmount\n\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      // const ethToBorrow = ethers.utils.parseUnits('10')\n      const msgvalue = ethers.utils.parseUnits('15')  \n      const totalSupplyBefore = (await crabStrategy.totalSupply())\n\n      expect(totalSupplyBefore.gt(BigNumber.from(0))).to.be.true\n      expect(collateralBefore.eq(BigNumber.from(0))).to.be.true\n      expect(debtBefore.eq(BigNumber.from(0))).to.be.true\n\n      await expect(crabStrategy.connect(depositor2).flashDeposit(ethToDeposit, {value: msgvalue})).to.be.revertedWith(\"Crab contracts shut down\")\n    })\n\n    it(\"should NOT let user deposit post liquidation\", async () => {\n        const vaultId = await crabStrategy.vaultId();\n        const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n        expect(isVaultSafe).to.be.true\n  \n        const vaultBefore = await controller.vaults(vaultId)\n        const collateralBefore = vaultBefore.collateralAmount\n        const debtBefore = vaultBefore.shortAmount\n  \n        const msgvalue = ethers.utils.parseUnits('15')  \n        const totalSupplyBefore = (await crabStrategy.totalSupply())\n  \n        expect(totalSupplyBefore.gt(BigNumber.from(0))).to.be.true\n        expect(collateralBefore.eq(BigNumber.from(0))).to.be.true\n        expect(debtBefore.eq(BigNumber.from(0))).to.be.true\n  \n        await expect(crabStrategy.connect(depositor2).deposit({value: msgvalue})).to.be.revertedWith(\"Crab contracts shut down\")\n      })\n\n    it(\"depositor should revert trying to flashWithdraw with AS due to amount of wSqueeth to buy being 0\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio,strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay,wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethCostOfDebtToRepay.mul(11).div(10)\n\n      await expect( crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay)).to.be.revertedWith(\"AS\")\n\n    })\n\n    it(\"depositor withdraw and get 0\", async () => {\n      \n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n      const userEthBalanceBefore = await provider.getBalance(depositor.address)\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const userSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await crabStrategy.connect(depositor).withdraw(userCrabBalanceBefore)\n\n      const userEthBalanceAfter = await provider.getBalance(depositor.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor.address);\n      const userSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralAfter = vaultBefore.collateralAmount\n      const debtAfter = vaultBefore.shortAmount\n      const totalSupplyAfter = await crabStrategy.totalSupply()\n\n      // expect(userEthBalanceAfter.sub(userEthBalanceBefore).eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(userSqueethBalanceAfter.sub(userSqueethBalanceBefore).eq(BigNumber.from(0))).to.be.true\n      expect(collateralAfter.eq(strategyCollateralAmountBefore.sub(userCollateral))).to.be.true\n      expect(collateralAfter.eq(BigNumber.from(0))).to.be.true\n      expect(debtAfter.eq(BigNumber.from(0))).to.be.true\n      expect(totalSupplyAfter.eq(BigNumber.from(0))).to.be.true\n    })\n  })\n})\n"
  },
  {
    "path": "packages/hardhat/test/integration-tests/strategy/crab-shutdown.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers, Signer } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport BigNumberJs from 'bignumber.js'\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategy, ISwapRouter } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\nimport { randomBytes } from \"ethers/lib/utils\";\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\ndescribe(\"Crab integration test: Shutdown of Squeeth Power Perp contracts\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress\n  let random: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let swapRouter: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategy\n  let ethDaiPool: Contract\n  let shutdownPrice: BigNumber\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _depositor2, _random ] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    depositor2 = _depositor2;\n    random = _random;\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n    swapRouter = uniDeployments.swapRouter\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      positionManager, \n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n  \n    const strategyCap = ethers.utils.parseUnits(\"1000\")\n    await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n    const strategyCapInContract = await crabStrategy.strategyCap()\n    expect(strategyCapInContract.eq(strategyCap)).to.be.true\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async() => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n    await provider.send(\"evm_increaseTime\", [300])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '1000000',\n      '2000000', \n      owner.address, \n      wSqueeth, \n      weth, \n      positionManager, \n      controller\n    )\n    await provider.send(\"evm_increaseTime\", [300])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  this.beforeAll(\"Deposit into strategy\", async () => {\n    const ethToDeposit = ethers.utils.parseUnits('20')\n    const msgvalue = ethers.utils.parseUnits('20')\n    const ethPrice = await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 600, true)\n\n    const squeethDelta = ethPrice.mul(2).div(1e4);\n    const debtToMint = wdiv(ethToDeposit, squeethDelta);\n    const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n    await crabStrategy.connect(depositor).deposit({value: msgvalue})\n\n    const totalSupply = (await crabStrategy.totalSupply())\n    const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n    const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, debtAmount] = await crabStrategy.getVaultDetails()\n    const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n    const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n    const lastHedgeTime = await crabStrategy.timeAtLastHedge()\n    const currentBlockNumber = await provider.getBlockNumber()\n    const currentBlock = await provider.getBlock(currentBlockNumber)\n    const timeStamp = currentBlock.timestamp\n\n    expect(totalSupply.eq(ethToDeposit)).to.be.true\n    expect(depositorCrab.eq(ethToDeposit)).to.be.true\n    // these had to be adjusted - it seems the eth price is a bit different than expected maybe? but only in coverage???\n    expect(isSimilar(debtAmount.toString(), debtToMint.toString(),3)).to.be.true\n    expect(isSimilar((depositorSqueethBalance.sub(depositorSqueethBalanceBefore)).toString(),(debtToMint).toString(),3)).to.be.true\n    expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n    expect(lastHedgeTime.eq(timeStamp)).to.be.true\n    \n  })\n\n  describe(\"Try to redeemShutdown from contracts before shutdown\", async () => {\n\n    it(\"should revert if calling redeemShutdown before contracts are shutdown\", async () => {\n      await expect(crabStrategy.connect(random).redeemShortShutdown()).to.be.revertedWith(\"C3\")\n    })\n  })\n\n  describe(\"Shutdown core contracts and check results\", async () => {\n    before('push eth price higher', async() => {\n        const poolWethBalance = await weth.balanceOf(ethDaiPool.address)\n\n        const maxDai = poolWethBalance.mul(startingEthPrice).mul(20)\n  \n        const exactOutputParam = {\n          tokenIn: dai.address,\n          tokenOut: weth.address,\n          fee: 3000,\n          recipient: owner.address,\n          deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n          amountOut: ethers.utils.parseUnits(\"5\"),\n          amountInMaximum: maxDai,\n          sqrtPriceLimitX96: 0,\n        }\n  \n        await dai.connect(owner).mint(owner.address, maxDai, )\n        await dai.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)      \n        await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n      })\n\n    before('push squeeth price higher', async() => {\n      const poolSqueethBalance = await wSqueeth.balanceOf(wSqueethPool.address)\n\n      const maxWeth = poolSqueethBalance.mul(scaledStartingSqueethPrice1e18).mul(20).div(one)\n            \n      const exactOutputParam = {\n        tokenIn: weth.address,\n        tokenOut: wSqueeth.address,\n        fee: 3000,\n        recipient: owner.address,\n        deadline: (await provider.getBlock(await provider.getBlockNumber())).timestamp + 86400,\n        amountOut: ethers.utils.parseUnits(\"50000\"),\n        amountInMaximum: maxWeth,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await weth.connect(owner).deposit({value: maxWeth})\n      await weth.connect(owner).approve(swapRouter.address, ethers.constants.MaxUint256)      \n      await (swapRouter as ISwapRouter).connect(owner).exactOutputSingle(exactOutputParam)\n      await provider.send(\"evm_increaseTime\", [600]) // increase time by 600 sec\n      await provider.send(\"evm_mine\", [])\n\n    })\n\n    it(\"should NOT let user withdrawShutdown pre shutdown, pre redeemShortShutdown\", async () => {\n        const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n        await expect(crabStrategy.connect(depositor).withdrawShutdown(userCrabBalanceBefore)).to.be.revertedWith(\"Squeeth contracts not shut down\")\n      })\n\n    it('shutdown contracts', async() => {\n        await controller.connect(owner).shutDown()\n        const isShutdown = await controller.isShutDown()\n        expect(isShutdown).to.be.true      \n  \n    })\n\n    it(\"should NOT let user withdrawShutdown post shutdown, pre redeemShortShutdown\", async () => {\n        const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n        await expect(crabStrategy.connect(depositor).withdrawShutdown(userCrabBalanceBefore)).to.be.revertedWith(\"Crab must redeemShortShutdown\")\n      })\n\n    it(\"anyone should be able to call redeemShortShutdown\", async () => {\n      shutdownPrice = await controller.indexForSettlement()\n  \n      const vaultId = await crabStrategy.vaultId();\n\n      const vaultBefore = await controller.vaults(vaultId)\n      \n      // state before liquidation\n      const crabSqueethBalanceBefore = await wSqueeth.balanceOf(crabStrategy.address)\n      const crabEthBalanceBefore = await provider.getBalance(crabStrategy.address)\n      const crabDebtBefore = vaultBefore.shortAmount\n      const crabCollateralBefore = vaultBefore.collateralAmount\n\n      const normFactor = await controller.normalizationFactor()\n      await crabStrategy.connect(random).redeemShortShutdown()\n      \n      const vaultAfter = await controller.vaults(vaultId)\n\n      const debtValueInEthBefore = crabDebtBefore.mul(normFactor).mul(shutdownPrice).div(one).div(one)\n      const expectedEthWithdrawn = crabCollateralBefore.sub(debtValueInEthBefore)\n\n      const crabSqueethBalanceAfter = await wSqueeth.balanceOf(crabStrategy.address)\n      const crabEthBalanceAfter = await provider.getBalance(crabStrategy.address)\n      const crabDebtAfter = vaultAfter.shortAmount\n      const crabCollateralAfter = vaultAfter.collateralAmount\n\n      expect(expectedEthWithdrawn.eq(crabEthBalanceAfter.sub(crabEthBalanceBefore))).to.be.true\n      expect(vaultAfter.shortAmount.isZero()).to.be.true\n      expect(vaultAfter.collateralAmount.isZero()).to.be.true\n      \n    })\n\n    it(\"should NOT let user flash deposit post shutdown\", async () => {\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralBefore = vaultBefore.collateralAmount\n      const debtBefore = vaultBefore.shortAmount\n\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      // const ethToBorrow = ethers.utils.parseUnits('10')\n      const msgvalue = ethers.utils.parseUnits('15')  \n      const totalSupplyBefore = (await crabStrategy.totalSupply())\n\n      expect(totalSupplyBefore.gt(BigNumber.from(0))).to.be.true\n      expect(collateralBefore.eq(BigNumber.from(0))).to.be.true\n      expect(debtBefore.eq(BigNumber.from(0))).to.be.true\n\n      await expect(crabStrategy.connect(depositor2).flashDeposit(ethToDeposit, {value: msgvalue})).to.be.revertedWith(\"Crab contracts shut down\")\n    })\n\n    it(\"should NOT let user deposit post shutdown\", async () => { \n        const msgvalue = ethers.utils.parseUnits('15')  \n  \n        await expect(crabStrategy.connect(depositor2).deposit({value: msgvalue})).to.be.revertedWith(\"Crab contracts shut down\")\n      })\n\n    it(\"depositor should revert trying to flashWithdraw with AS due to amount of wSqueeth to buy being 0\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio,strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay,wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethCostOfDebtToRepay.mul(11).div(10)\n\n      await expect( crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay)).to.be.revertedWith(\"AS\")\n\n    })\n\n    it(\"depositor should revert trying to withdraw post shutdown\", async () => {\n        const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n\n        await expect( crabStrategy.connect(depositor).withdraw(userCrabBalanceBefore)).to.be.revertedWith(\"C0\")\n  \n      })\n\n    it(\"depositor withdraw when calling withdrawShutdown and get correct proceeds\", async () => {\n      \n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const strategyCollateralAmountBefore = await provider.getBalance(crabStrategy.address)\n      const [strategyOperatorBefore, strategyNftIdBefore, strategyVaultCollateralAmountBefore, strategyDebtAmountBefore] = await crabStrategy.getVaultDetails()\n\n      const userEthBalanceBefore = await provider.getBalance(depositor.address)\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const userSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await crabStrategy.connect(depositor).withdrawShutdown(userCrabBalanceBefore)\n\n      const userEthBalanceAfter = await provider.getBalance(depositor.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor.address);\n      const userSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const vaultCollateralAfter = vaultAfter.collateralAmount\n      const vaultDebtAfter = vaultAfter.shortAmount\n      const totalSupplyAfter = await crabStrategy.totalSupply()\n      const strategyCollateralAmountAfter = await provider.getBalance(crabStrategy.address)\n\n\n      expect(strategyVaultCollateralAmountBefore.eq(BigNumber.from(0))).to.be.true\n      expect(strategyDebtAmountBefore.eq(BigNumber.from(0))).to.be.true\n      // expect(userEthBalanceAfter.sub(userEthBalanceBefore).eq(userCollateral)).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(userSqueethBalanceAfter.sub(userSqueethBalanceBefore).eq(BigNumber.from(0))).to.be.true\n      expect(vaultCollateralAfter.eq(BigNumber.from(0))).to.be.true\n      expect(vaultDebtAfter.eq(BigNumber.from(0))).to.be.true\n      expect(strategyCollateralAmountBefore.sub(strategyCollateralAmountAfter).eq(userCollateral)).to.be.true\n      expect(crabTotalSupply.sub(totalSupplyAfter).eq(userCrabBalanceBefore)).to.be.true\n    })\n  })\n})\n"
  },
  {
    "path": "packages/hardhat/test/integration-tests/strategy/strategy-flow.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Contract, BigNumber, providers } from \"ethers\";\nimport BigNumberJs from 'bignumber.js'\n\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { WETH9, MockErc20, Controller, Oracle, WPowerPerp, CrabStrategy } from \"../../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addWethDaiLiquidity, addSqueethLiquidity } from '../../setup'\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\ndescribe(\"Crab integration test: flash deposit - deposit - withdraw\", function () {\n  const startingEthPrice = 3000\n  const startingEthPrice1e18 = BigNumber.from(startingEthPrice).mul(one) // 3000 * 1e18\n  const scaledStartingSqueethPrice1e18 = startingEthPrice1e18.div(oracleScaleFactor) // 0.3 * 1e18\n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n\n\n  const hedgeTimeThreshold = 86400  // 24h\n  const hedgePriceThreshold = ethers.utils.parseUnits('0.01')\n  const auctionTime = 3600\n  const minPriceMultiplier = ethers.utils.parseUnits('0.95')\n  const maxPriceMultiplier = ethers.utils.parseUnits('1.05')\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let feeRecipient: SignerWithAddress;\n  let dai: MockErc20\n  let weth: WETH9\n  let positionManager: Contract\n  let uniswapFactory: Contract\n  let oracle: Oracle\n  let controller: Controller\n  let wSqueethPool: Contract\n  let wSqueeth: WPowerPerp\n  let crabStrategy: CrabStrategy\n  let ethDaiPool: Contract\n\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _feeRecipient ] = accounts;\n    owner = _owner;\n    depositor = _depositor;\n    feeRecipient = _feeRecipient\n    provider = ethers.provider\n\n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    positionManager = uniDeployments.positionManager\n    uniswapFactory = uniDeployments.uniswapFactory\n\n    // this will not deploy a new pool, only reuse old onces\n    const squeethDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      positionManager, \n      uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n    controller = squeethDeployments.controller\n    wSqueeth = squeethDeployments.wsqueeth\n    oracle = squeethDeployments.oracle\n    // shortSqueeth = squeethDeployments.shortSqueeth\n    wSqueethPool = squeethDeployments.wsqueethEthPool\n    ethDaiPool = squeethDeployments.ethDaiPool\n\n    await controller.connect(owner).setFeeRecipient(feeRecipient.address);\n    await controller.connect(owner).setFeeRate(100)\n\n    const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n    crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, uniswapFactory.address, wSqueethPool.address, hedgeTimeThreshold, hedgePriceThreshold, auctionTime, minPriceMultiplier, maxPriceMultiplier)) as CrabStrategy;\n  })\n\n  this.beforeAll(\"Seed pool liquidity\", async() => {\n    // add liquidity\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('100'), // eth amount\n      owner.address,\n      dai,\n      weth,\n      positionManager\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '1000000',\n      '2000000', \n      owner.address, \n      wSqueeth, \n      weth, \n      positionManager, \n      controller\n    )\n    await provider.send(\"evm_increaseTime\", [600])\n    await provider.send(\"evm_mine\", [])\n\n  })\n\n  describe(\"deposit above strategy cap\", async () => {\n    it(\"should revert if depositing an amount that puts the strategy above the cap\", async () => {      \n      const ethToDeposit = ethers.utils.parseUnits('20')\n      const msgvalue = ethers.utils.parseUnits('10')\n\n      await expect(\n        crabStrategy.connect(depositor).flashDeposit(ethToDeposit, {value: msgvalue})\n      ).to.be.revertedWith(\"Deposit exceeds strategy cap\");\n    })\n  })\n\n  describe(\"flash deposit - deposit - withdraw - flash withdraw\", async () => {\n    it(\"should let the owner set the cap\", async () => {      \n      const strategyCap = ethers.utils.parseUnits(\"1000\")\n      await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n      const strategyCapInContract = await crabStrategy.strategyCap()\n      expect(strategyCapInContract.eq(strategyCap)).to.be.true\n    })\n\n    it(\"should revert flash depositing if not enough ETH\", async () => {      \n      const ethToDeposit = ethers.utils.parseUnits('20')\n      const msgvalue = ethers.utils.parseUnits('10')\n\n      await expect(\n        crabStrategy.connect(depositor).flashDeposit(ethToDeposit, {value: msgvalue})\n      ).to.be.revertedWith(\"function call failed to execute\");\n    })\n\n    it(\"should flash deposit correct amount and mint correct shares amount\", async () => {\n      const ethToDeposit = ethers.utils.parseUnits('20')\n      const msgvalue = ethers.utils.parseUnits('10.1')\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      await crabStrategy.connect(depositor).flashDeposit(ethToDeposit, {value: msgvalue})\n      \n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)\n      const squeethDelta = scaledStartingSqueethPrice1e18.mul(2);\n      const debtToMint = wdiv(ethToDeposit, (squeethDelta.add(ethFeePerWSqueeth)));\n      const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n  \n      const totalSupply = (await crabStrategy.totalSupply())\n      const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const debtAmount = strategyVault.shortAmount\n      const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n      const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n      const lastHedgeTime = await crabStrategy.timeAtLastHedge()\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const timeStamp = currentBlock.timestamp\n      const collateralAmount = await strategyVault.collateralAmount\n  \n      expect(isSimilar(totalSupply.toString(),(expectedEthDeposit).toString())).to.be.true\n      expect(isSimilar(depositorCrab.toString(),(expectedEthDeposit).toString())).to.be.true\n      expect(isSimilar(debtAmount.toString(), debtToMint.toString())).to.be.true\n      expect(depositorSqueethBalance.eq(depositorSqueethBalanceBefore)).to.be.true\n      expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n      expect(lastHedgeTime.eq(timeStamp)).to.be.true\n    })\n\n    it(\"should deposit and mint correct LP and return the correct amount of wSqueeth debt per crab strategy token\", async () => {\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const collateralBefore = strategyVault.collateralAmount\n      const debtBefore = strategyVault.shortAmount\n      const totalSupplyBefore = await crabStrategy.totalSupply()\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor.address))\n      const depositorSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      const ethToDeposit = BigNumber.from(20).mul(one)\n      \n      await crabStrategy.connect(depositor).deposit({value: ethToDeposit});\n\n      const normFactor = await controller.normalizationFactor()\n      const currentScaledEthPrice = (await oracle.getTwap(ethDaiPool.address, weth.address, dai.address, 300, false)).div(oracleScaleFactor)\n      const feeRate = await controller.feeRate()\n      const ethFeePerWSqueeth = currentScaledEthPrice.mul(normFactor).mul(feeRate).div(10000).div(one)\n      const debtToMint = ethToDeposit.mul(debtBefore).div(collateralBefore.add(debtBefore.mul(ethFeePerWSqueeth).div(one)))\n      const expectedEthDeposit = ethToDeposit.sub(debtToMint.mul(ethFeePerWSqueeth).div(one))\n      const depositorShare = one.mul(expectedEthDeposit).div(collateralBefore.add(expectedEthDeposit))\n      const crabMintAmount = totalSupplyBefore.mul(depositorShare).div(one.sub(depositorShare))\n\n      const expectedMintedWsqueeth = wmul(debtToMint,normFactor)\n      const totalCrabAfter = (await crabStrategy.totalSupply())\n      const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const debtAmount = strategyVaultAfter.shortAmount\n      const depositorSqueethBalance = await wSqueeth.balanceOf(depositor.address)\n      const strategyContractSqueeth = await wSqueeth.balanceOf(crabStrategy.address)\n      const depositorWSqueethDebt = await crabStrategy.getWsqueethFromCrabAmount(depositorCrab)\n\n      expect(isSimilar(totalCrabAfter.sub(totalSupplyBefore).toString(),crabMintAmount.toString())).to.be.true\n      expect(isSimilar((depositorCrab.sub(depositorCrabBefore)).toString(),(crabMintAmount).toString())).to.be.true\n      expect(isSimilar(debtAmount.sub(debtBefore).toString(),(debtToMint).toString())).to.be.true\n      expect(isSimilar(depositorSqueethBalance.sub(depositorSqueethBalanceBefore).toString(), expectedMintedWsqueeth.toString())).to.be.true\n      expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n      expect(depositorWSqueethDebt.eq(depositorSqueethBalance))    \n    })\n\n    it(\"should withdraw correct amount of ETH\", async () => {\n      // some rounding\n      const crabToBurn = (await crabStrategy.balanceOf(depositor.address)).div(2).mul(99).div(100)\n      const wSqueethToBurn = await crabStrategy.getWsqueethFromCrabAmount(crabToBurn)\n      const depositorWSqueethBalanceBefore = await wSqueeth.balanceOf(depositor.address)\n\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtBefore = strategyVault.shortAmount\n      const strategyCollateralBefore = strategyVault.collateralAmount\n      const totalCrabBefore = await crabStrategy.totalSupply()\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor.address))\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n\n      const expectedCrabPercentage = wdiv(crabToBurn, totalCrabBefore)\n      const expectedEthToWithdraw = wmul(strategyCollateralBefore, expectedCrabPercentage)\n\n      await wSqueeth.connect(depositor).approve(crabStrategy.address, wSqueethToBurn)\n      await crabStrategy.connect(depositor).withdraw(crabToBurn);  \n\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAfter = strategyVaultAfter.shortAmount\n      const totalCrabAfter = await crabStrategy.totalSupply()\n      const depositorCrabAfter = (await crabStrategy.balanceOf(depositor.address))\n      const depositorWSqueethBalanceAfter = await wSqueeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(depositorCrabAfter.eq(depositorCrabBefore.sub(crabToBurn))).to.be.true\n      expect(totalCrabAfter.eq(totalCrabBefore.sub(crabToBurn))).to.be.true\n      expect(strategyCollateralAfter.eq(strategyCollateralBefore.sub(expectedEthToWithdraw))).to.be.true\n      expect(strategyDebtAfter.eq(strategyDebtBefore.sub(wSqueethToBurn))).to.be.true\n      expect(depositorWSqueethBalanceBefore.sub(depositorWSqueethBalanceAfter).eq(wSqueethToBurn)).to.be.true\n      expect(isSimilar(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).toString(), expectedEthToWithdraw.toString(), 3)).to.be.true // 0.002605896 diff\n    })\n\n    it(\"should revert if slippage is too high\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtAmountBefore = strategyVault.shortAmount\n      const strategyCollateralAmountBefore = strategyVault.collateralAmount\n\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio,strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay,wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethToWithdraw.mul(9).div(10)\n\n      await expect(\n        crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay)\n      ).to.be.revertedWith(\"amount in greater than max\");\n    })\n\n    it(\"should flash withdraw correct amount of ETH collateral\", async () => {\n      const wSqueethPrice = await oracle.getTwap(wSqueethPool.address, wSqueeth.address, weth.address, 1, false)\n\n      const userCrabBalanceBefore = await crabStrategy.balanceOf(depositor.address);\n      const crabTotalSupply = await crabStrategy.totalSupply()\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtAmountBefore = strategyVault.shortAmount\n      const strategyCollateralAmountBefore = strategyVault.collateralAmount\n      const userEthBalanceBefore = await provider.getBalance(depositor.address)\n      const crabRatio = wdiv(userCrabBalanceBefore, crabTotalSupply);\n      const debtToRepay = wmul(crabRatio,strategyDebtAmountBefore);\n      const ethCostOfDebtToRepay = wmul(debtToRepay, wSqueethPrice)\n      const userCollateral = wmul(crabRatio, strategyCollateralAmountBefore)\n      const ethToWithdraw = userCollateral.sub(ethCostOfDebtToRepay);\n      const maxEthToPay = ethCostOfDebtToRepay.mul(11).div(10)\n\n      await crabStrategy.connect(depositor).flashWithdraw(userCrabBalanceBefore, maxEthToPay)\n\n      const userEthBalanceAfter = await provider.getBalance(depositor.address)\n      const userCrabBalanceAfter = await crabStrategy.balanceOf(depositor.address);\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtAmountAfter = strategyVaultAfter.shortAmount\n      const strategyCollateralAmountAfter = strategyVaultAfter.collateralAmount\n\n      const vaultId = await crabStrategy.vaultId();\n      const isVaultSafe = await controller.isVaultSafe((await crabStrategy.vaultId()))\n      expect(isVaultSafe).to.be.true\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const collateralAfter = vaultBefore.collateralAmount\n      const debtAfter = vaultBefore.shortAmount\n\n      expect(isSimilar(userEthBalanceAfter.sub(userEthBalanceBefore).toString(), ethToWithdraw.toString(),2)).to.be.true\n      expect(userCrabBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(userCrabBalanceBefore.sub(userCrabBalanceAfter).eq(userCrabBalanceBefore)).to.be.true\n      expect(collateralAfter.eq(strategyCollateralAmountBefore.sub(userCollateral))).to.be.true\n      expect(strategyDebtAmountBefore.sub(debtAfter).eq(debtToRepay)).to.be.true\n      expect(strategyDebtAmountAfter.eq(BigNumber.from(0))).to.be.true\n      expect(strategyCollateralAmountAfter.eq(BigNumber.from(0))).to.be.true\n    })  \n  })\n})"
  },
  {
    "path": "packages/hardhat/test/integration-tests/uni-position-collateral.ts",
    "content": "import { ethers } from \"hardhat\"\nimport BigNumberJs from 'bignumber.js'\nimport { Contract, BigNumber, constants, utils } from \"ethers\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { expect } from \"chai\";\nimport { Controller, INonfungiblePositionManager, MockErc20, VaultLibTester, ShortPowerPerp, WETH9, WPowerPerp, IUniswapV3Factory } from \"../../typechain\";\nimport { deployUniswapV3, deploySqueethCoreContracts, deployWETHAndDai, addSqueethLiquidity, addWethDaiLiquidity, createUniPool } from '../setup'\nimport { isSimilar, getNow, one, oracleScaleFactor } from \"../utils\";\nimport { getSqrtPriceAndTickBySqueethPrice } from \"../calculator\";\n\nconst TICK_SPACE = 60\n\n// make sure .toString won't return string like 3.73e+22\nBigNumberJs.set({EXPONENTIAL_AT: 30})\n\ndescribe(\"Uniswap Position token integration test\", function () {\n  let dai: MockErc20\n  let weth: WETH9\n  let squeeth: WPowerPerp\n  let shortSqueeth: ShortPowerPerp\n  let positionManager: INonfungiblePositionManager\n  let uniFactory: IUniswapV3Factory\n  let controller: Controller\n  \n  let squeethPool: Contract\n  \n  let vaultLib: VaultLibTester\n\n  const startingEthPrice = 3000\n  let isWethToken0: boolean\n  \n  const scaledStartingSqueethPrice = startingEthPrice / oracleScaleFactor.toNumber() // 0.3\n  \n  let liquidityProvider: SignerWithAddress\n  let seller: SignerWithAddress\n\n  const humanReadableMintAmount = '100'\n  const depositAmount = ethers.utils.parseUnits('45.1')\n  const mintAmount = ethers.utils.parseUnits(humanReadableMintAmount)\n\n  // vault0: uni position token has both eth and squeeth\n  let vault0Id: BigNumber\n  let vault0LPTokenId: number\n\n  // vault1: uni position token has only squeeth\n  let vault1Id: BigNumber\n  let vault1LPTokenId: number\n  let vault1LpWSqueethAmount: BigNumber\n  \n\n  // vault2: uni position token has only eth\n  let vault2Id: BigNumber\n  let vault2LPTokenId: number\n  const vault2LpEthAmount = utils.parseEther('10')\n\n  // vault3: uni position token has only eth\n  let vault3LPTokenId: number\n  const vault3LpEthAmount = utils.parseEther('10')\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners()\n    liquidityProvider = accounts[0]\n    seller = accounts[1]\n  })\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n  \n    const { dai: daiToken, weth: wethToken } = await deployWETHAndDai()\n\n    dai = daiToken\n    weth = wethToken\n\n    const uniDeployments = await deployUniswapV3(weth)\n    const coreDeployments = await deploySqueethCoreContracts(\n      weth,\n      dai, \n      uniDeployments.positionManager, \n      uniDeployments.uniswapFactory,\n      scaledStartingSqueethPrice,\n      startingEthPrice\n    )\n\n    positionManager = (uniDeployments.positionManager) as INonfungiblePositionManager\n    uniFactory = uniDeployments.uniswapFactory as IUniswapV3Factory\n\n    squeeth = coreDeployments.wsqueeth\n    shortSqueeth = coreDeployments.shortSqueeth\n    controller = coreDeployments.controller\n    squeethPool = coreDeployments.wsqueethEthPool\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const TickMathExternal = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMathExternal.deploy());\n\n    const VaultTester = await ethers.getContractFactory(\"VaultLibTester\", {libraries: {TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n    vaultLib = (await VaultTester.deploy()) as VaultLibTester;\n  })\n\n  this.beforeAll('Add liquidity to both pools', async() => {\n    await addSqueethLiquidity(\n      scaledStartingSqueethPrice, \n      '5',\n      '30', \n      liquidityProvider.address, \n      squeeth, \n      weth, \n      positionManager, \n      controller\n    )\n\n    await addWethDaiLiquidity(\n      startingEthPrice,\n      ethers.utils.parseUnits('10'), // eth amount\n      liquidityProvider.address,\n      dai,\n      weth,\n      positionManager\n    )\n  })\n\n  this.beforeAll('Prepare vault0 (normal)', async() => {\n    vault0Id = await shortSqueeth.nextId()\n\n    await controller.connect(seller).mintPowerPerpAmount(0, mintAmount, 0, {value: depositAmount})\n\n    vault0LPTokenId = await addSqueethLiquidity(\n      scaledStartingSqueethPrice,\n      humanReadableMintAmount,\n      '45.1',\n      liquidityProvider.address,\n      squeeth,\n      weth,\n      positionManager,\n      controller\n    )\n    await (positionManager as INonfungiblePositionManager).connect(liquidityProvider).transferFrom(liquidityProvider.address, seller.address, vault0LPTokenId)\n    await (positionManager as INonfungiblePositionManager).connect(seller).approve(controller.address, vault0LPTokenId)\n\n    await controller.connect(seller).depositUniPositionToken(vault0Id, vault0LPTokenId)\n    const vault = await controller.vaults(vault0Id)\n    expect(vault.NftCollateralId === vault0LPTokenId).to.be.true\n  })\n\n  this.beforeAll('Prepare vault1 (all squeeth)', async() => {\n    vault1Id = await shortSqueeth.nextId()\n\n    isWethToken0 = parseInt(weth.address, 16) < parseInt(squeeth.address, 16) \n\n    // create a uni position that's [4000, 5000], so it's now all squeeth\n    const scaledPrice5000 = BigNumber.from('5000').mul(one).div(oracleScaleFactor)\n    const scaledPrice4000 = BigNumber.from('4000').mul(one).div(oracleScaleFactor)\n    const { tick: tick4000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice4000, isWethToken0)\n    const { tick: tick5000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice5000, isWethToken0)\n    const tickUpper = isWethToken0 ? tick4000 : tick5000;\n    const tickLower = isWethToken0 ? tick5000 : tick4000;\n    const tickUpperToUse = Math.ceil(parseInt(tickUpper, 10) / TICK_SPACE) * TICK_SPACE\n    const tickLowerToUse = Math.ceil(parseInt(tickLower, 10) / TICK_SPACE) * TICK_SPACE\n    const token0 = isWethToken0 ? weth.address : squeeth.address\n    const token1 = isWethToken0 ? squeeth.address : weth.address\n\n    // put all wsqueeth balance into this LP token\n    vault1LpWSqueethAmount = await squeeth.balanceOf(seller.address)\n\n    // uni position is all wsqueeth\n    const mintParam = {\n      token0,\n      token1,\n      fee: 3000,\n      tickLower: tickLowerToUse,\n      tickUpper: tickUpperToUse,\n      amount0Desired: isWethToken0 ? 0 : vault1LpWSqueethAmount,\n      amount1Desired: isWethToken0 ? vault1LpWSqueethAmount : 0,\n      amount0Min: 0,\n      amount1Min: 0,\n      recipient: seller.address,\n      deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n    }\n\n    await squeeth.connect(seller).approve(positionManager.address, constants.MaxUint256)\n    const tx = await positionManager.connect(seller).mint(mintParam)\n\n    const receipt = await tx.wait();\n    vault1LPTokenId = (receipt.events?.find(event => event.event === 'IncreaseLiquidity'))?.args?.tokenId.toNumber();\n\n    await positionManager.connect(seller).approve(controller.address, vault1LPTokenId)\n\n    await controller.connect(seller).mintPowerPerpAmount(0, mintAmount, vault1LPTokenId, {value: depositAmount})\n    const vault = await controller.vaults(vault1Id)\n    expect(vault.NftCollateralId === vault1LPTokenId).to.be.true\n  })\n\n  this.beforeAll('Prepare vault2 (all eth)', async() => {\n    vault2Id = await shortSqueeth.nextId()\n\n    // create a uni position that's [1000, 2000], so it's now all eth\n    const scaledPrice2000 = BigNumber.from('2000').mul(one).div(oracleScaleFactor)\n    const scaledPrice1000 = BigNumber.from('1000').mul(one).div(oracleScaleFactor)\n    const { tick: tick1000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice1000, isWethToken0)\n    const { tick: tick2000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice2000, isWethToken0)\n    const tickUpper = isWethToken0 ? tick1000 : tick2000;\n    const tickLower = isWethToken0 ? tick2000 : tick1000;\n    const tickUpperToUse = Math.ceil(parseInt(tickUpper, 10) / TICK_SPACE) * TICK_SPACE\n    const tickLowerToUse = Math.ceil(parseInt(tickLower, 10) / TICK_SPACE) * TICK_SPACE\n    const token0 = isWethToken0 ? weth.address : squeeth.address\n    const token1 = isWethToken0 ? squeeth.address : weth.address\n\n    // uni position is all ETH\n    const mintParam = {\n      token0,\n      token1,\n      fee: 3000,\n      tickLower: tickLowerToUse,\n      tickUpper: tickUpperToUse,\n      amount0Desired: isWethToken0 ? vault2LpEthAmount : 0,\n      amount1Desired: isWethToken0 ? 0 : vault2LpEthAmount,\n      amount0Min: 0,\n      amount1Min: 0,\n      recipient: seller.address,\n      deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n    }\n\n    await weth.connect(seller).deposit({value: vault2LpEthAmount})\n    await weth.connect(seller).approve(positionManager.address, constants.MaxUint256)\n    const tx = await positionManager.connect(seller).mint(mintParam)\n\n    const receipt = await tx.wait();\n    vault2LPTokenId = (receipt.events?.find(event => event.event === 'IncreaseLiquidity'))?.args?.tokenId.toNumber();\n\n    await positionManager.connect(seller).approve(controller.address, vault2LPTokenId)\n\n    await controller.connect(seller).mintPowerPerpAmount(0, mintAmount, vault2LPTokenId, {value: depositAmount})\n    const vault = await controller.vaults(vault2Id)\n    expect(vault.NftCollateralId === vault2LPTokenId).to.be.true\n  })\n\n  describe('Can not deposit a 0 liquidity uni nft in to vault', async( )=> {\n    \n    it(\"should revert if a user tries to deposit a uni nft with 0 liquidity\", async () => {\n      // create a uni position that's [1000, 2000], so it's now all eth\n      const scaledPrice2000 = BigNumber.from('2000').mul(one).div(oracleScaleFactor)\n      const scaledPrice1000 = BigNumber.from('1000').mul(one).div(oracleScaleFactor)\n      const { tick: tick1000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice1000, isWethToken0)\n      const { tick: tick2000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice2000, isWethToken0)\n      const tickUpper = isWethToken0 ? tick1000 : tick2000;\n      const tickLower = isWethToken0 ? tick2000 : tick1000;\n      const tickUpperToUse = Math.ceil(parseInt(tickUpper, 10) / TICK_SPACE) * TICK_SPACE\n      const tickLowerToUse = Math.ceil(parseInt(tickLower, 10) / TICK_SPACE) * TICK_SPACE\n      const token0 = isWethToken0 ? weth.address : squeeth.address\n      const token1 = isWethToken0 ? squeeth.address : weth.address\n  \n      // uni position is all ETH\n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: tickLowerToUse,\n        tickUpper: tickUpperToUse,\n        amount0Desired: isWethToken0 ? vault3LpEthAmount : 0,\n        amount1Desired: isWethToken0 ? 0 : vault3LpEthAmount,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: seller.address,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n      \n      await weth.connect(seller).deposit({value: vault3LpEthAmount})\n      await weth.connect(seller).approve(positionManager.address, constants.MaxUint256)\n  \n      const tx = await positionManager.connect(seller).mint(mintParam)\n  \n      const receipt = await tx.wait();\n      vault3LPTokenId = (receipt.events?.find(event => event.event === 'IncreaseLiquidity'))?.args?.tokenId.toNumber();\n  \n      const {liquidity: nftLiquidity} = await positionManager.positions(vault3LPTokenId)\n\n      const decreaseLiquidityParams = {\n        tokenId: vault3LPTokenId,\n        liquidity: nftLiquidity,\n        amount0Min: 0,\n        amount1Min: 0,\n        deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n      }\n        \n      await positionManager.connect(seller).decreaseLiquidity(decreaseLiquidityParams)\n\n      await positionManager.connect(seller).approve(controller.address, vault3LPTokenId)\n  \n      await expect(controller.connect(seller).mintPowerPerpAmount(0, 0, vault3LPTokenId)).to.be.revertedWith(\"C25\")\n    })\n  })\n  describe('Save vault with uni position token', async( )=> {\n    \n    it(\"seller can redeem an Uni Position token for weth and wSqueeth to reduce debt in vault0\", async () => {\n\n      // get net worth of uni position token\n      const poolContract = await ethers.getContractAt(\"IUniswapV3Pool\", squeethPool.address)\n      \n      const {tick} = await poolContract.slot0()\n\n      const vaultBefore = await controller.vaults(vault0Id)\n\n      // the result we get from here is not accurate\n      const {ethAmount, wPowerPerpAmount} = await vaultLib.getUniPositionBalances(positionManager.address, vault0LPTokenId, tick, isWethToken0)\n\n      const wsqueethBefore = await squeeth.balanceOf(seller.address)\n\n      await controller.connect(seller).reduceDebt(vault0Id)\n\n      const wsqueethAfter = await squeeth.balanceOf(seller.address)\n\n      const vaultAfter = await controller.vaults(vault0Id)\n\n      const wsqueethBurned = vaultBefore.shortAmount.sub(vaultAfter.shortAmount)\n      const wsqueethReceived = wsqueethAfter.sub(wsqueethBefore)\n      \n      expect(vaultAfter.NftCollateralId === 0).to.be.true\n      expect(isSimilar(vaultBefore.collateralAmount.add(ethAmount).toString(), vaultAfter.collateralAmount.toString())).to.be.true\n      expect(isSimilar(wsqueethBurned.add(wsqueethReceived).toString(), wPowerPerpAmount.toString())).to.be.true\n    })\n    it(\"seller can redeem an Uni Position token for wSqueeth to reduce debt in vault1\", async () => {\n      const vaultBefore = await controller.vaults(vault1Id)\n\n      const wsqueethBefore = await squeeth.balanceOf(seller.address)\n      \n      await controller.connect(seller).reduceDebt(vault1Id)\n      \n      const wsqueethAfter = await squeeth.balanceOf(seller.address)\n\n      const vaultAfter = await controller.vaults(vault1Id)\n      expect(vaultAfter.NftCollateralId === 0).to.be.true\n\n      const expectedAmountInVault = vault1LpWSqueethAmount.gt(vaultBefore.shortAmount) \n        ? BigNumber.from(0)\n        : vaultBefore.shortAmount.sub(vault1LpWSqueethAmount)\n      \n      const expectedWSqueethReceived = vault1LpWSqueethAmount.gt(vaultBefore.shortAmount) \n        ? vault1LpWSqueethAmount.sub(vaultBefore.shortAmount)\n        : BigNumber.from(0)\n\n      // collateral is the same\n      expect(vaultBefore.collateralAmount.eq(vaultAfter.collateralAmount)).to.be.true\n      expect(isSimilar(expectedAmountInVault.toString(), vaultAfter.shortAmount.toString())).to.be.true\n      expect(isSimilar(wsqueethAfter.sub(wsqueethBefore).toString(), expectedWSqueethReceived.toString(), 4)).to.be.true\n\n    })\n    it(\"seller can redeem an Uni Position token for eth to reduce debt in vault2\", async () => {\n      const vaultBefore = await controller.vaults(vault2Id)\n\n      await controller.connect(seller).reduceDebt(vault2Id)\n      \n      const vaultAfter = await controller.vaults(vault2Id)\n      // short amount is the same\n      expect(isSimilar(vaultBefore.collateralAmount.add(vault2LpEthAmount).toString() ,vaultAfter.collateralAmount.toString())).to.be.true\n      expect(vaultBefore.shortAmount.eq(vaultAfter.shortAmount)).to.be.true\n      expect(vaultAfter.NftCollateralId === 0).to.be.true\n    })\n  })\n\n  describe('deposit LP token with diff fee tier', async() => {\n    let newPoolLPTokenId: number\n    // use fee tier of 0.05% instead of 1% because 0.05% has smaller tick space (10)\n    // which works with our existing script\n    const newFeeTier = 500\n    before('create new pool with fee tier = 0.05%', async() => {\n      await createUniPool(scaledStartingSqueethPrice, squeeth, weth, positionManager, uniFactory, newFeeTier)\n    })\n    before('add liquidity to the new pool', async() => {\n      newPoolLPTokenId = await addSqueethLiquidity(\n        scaledStartingSqueethPrice,\n        humanReadableMintAmount,\n        '45.1',\n        liquidityProvider.address,\n        squeeth,\n        weth,\n        positionManager,\n        controller,\n        newFeeTier\n      )\n    })\n    it('should revert depositing lp token into the vault with the wrong fee tier', async() => {\n      await (positionManager as INonfungiblePositionManager).connect(liquidityProvider).transferFrom(liquidityProvider.address, seller.address, newPoolLPTokenId)\n      await (positionManager as INonfungiblePositionManager).connect(seller).approve(controller.address, newPoolLPTokenId)\n      await expect(controller.connect(seller).mintWPowerPerpAmount(0, 0, newPoolLPTokenId)).to.be.revertedWith(\"C26\")    \n    })\n  })\n})\n"
  },
  {
    "path": "packages/hardhat/test/setup.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { Contract, BigNumber } from \"ethers\";\nimport { BigNumber as BigNumberJs} from \"bignumber.js\"\n\nimport {\n  abi as SWAP_ROUTER_ABI,\n  bytecode as SWAP_ROUTER_BYTECODE,\n} from '@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json'\nimport {\n  abi as POSITION_MANAGER_ABI,\n  bytecode as POSITION_MANAGER_BYTECODE,\n} from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'\nimport {\n  abi as FACTORY_ABI,\n  bytecode as FACTORY_BYTECODE,\n} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json'\nimport {\n  abi as QUOTER_ABI,\n  bytecode as QUOTER_BYTECODE,\n} from \"@uniswap/v3-periphery/artifacts/contracts/lens/Quoter.sol/Quoter.json\"\nimport { Controller, Oracle, ShortPowerPerp, WETH9, WPowerPerp, MockErc20, INonfungiblePositionManager, ABDKMath64x64 } from \"../typechain\";\nimport { convertToken0PriceToSqrtX96Price, convertToken1PriceToSqrtX96Price } from \"./calculator\";\nimport { getNow } from './utils'\n\nexport const deployWETHAndDai = async() => {\n  const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n  const dai = (await MockErc20Contract.deploy(\"Dai\", \"Dai\", 18)) as MockErc20;\n\n  const WETH9Contract = await ethers.getContractFactory(\"WETH9\");\n  const weth = (await WETH9Contract.deploy()) as WETH9;\n\n  return { dai, weth }\n}\n\n/**\n * Deploy Uniswap factory, swapRouter, nftPositionManager and WETH9\n * @returns \n */\nexport const deployUniswapV3 = async(weth: Contract) => {\n  const accounts = await ethers.getSigners();\n  \n  // Deploy UniswapV3Factory\n  const UniswapV3FactoryFactory = new ethers.ContractFactory(FACTORY_ABI, FACTORY_BYTECODE, accounts[0]);\n  const uniswapFactory = await UniswapV3FactoryFactory.deploy();\n\n  // Deploy UniswapV3SwapRouter\n  const SwapRouterFactory = new ethers.ContractFactory(SWAP_ROUTER_ABI, SWAP_ROUTER_BYTECODE, accounts[0]);\n  const swapRouter = await SwapRouterFactory.deploy(uniswapFactory.address, weth.address);\n\n  // tokenDescriptor is only used to query tokenURI() on NFT. Don't need that in our deployment\n  const tokenDescriptorAddress = ethers.constants.AddressZero\n  // Deploy NonfungibleTokenManager\n  const positionManagerFactory = new ethers.ContractFactory(POSITION_MANAGER_ABI, POSITION_MANAGER_BYTECODE, accounts[0]);\n  const positionManager = await positionManagerFactory.deploy(uniswapFactory.address, weth.address, tokenDescriptorAddress);\n\n  const quoterFactory = new ethers.ContractFactory(QUOTER_ABI, QUOTER_BYTECODE, accounts[0]);\n  const quoter = await quoterFactory.deploy(uniswapFactory.address, weth.address);\n\n\n  return { positionManager, uniswapFactory, swapRouter, quoter }\n}\n\n\n/**\n * Create uniswap pool.\n * @param tokenBPriceInA \n * @param tokenA \n * @param tokenB \n * @param positionManager \n * @param univ3Factory \n * @returns {Contract}\n */\nexport const createUniPool = async(\n  tokenBPriceInA: number, \n  tokenA: Contract, \n  tokenB: Contract,\n  positionManager: Contract,\n  univ3Factory: Contract,\n  feeTier = 3000 // default fee = 0.3%\n): Promise<Contract> => {\n  const isTokenAToken0 = parseInt(tokenA.address, 16) < parseInt(tokenB.address, 16)\n\n  const tokenADecimals = await tokenA.decimals()\n  const tokenBDecimals = await tokenB.decimals()\n  \n  let rawPrice = tokenBPriceInA\n\n  if (tokenBDecimals > tokenADecimals) {\n    const diff = tokenBDecimals - tokenADecimals\n    rawPrice /= 10 ** diff\n  } else {\n    const diff = tokenADecimals - tokenBDecimals\n    rawPrice *= 10 ** diff\n  }\n\n  const sqrtX96Price = isTokenAToken0 \n    ? convertToken1PriceToSqrtX96Price(rawPrice.toString()).toFixed(0)\n    : convertToken0PriceToSqrtX96Price(rawPrice.toString()).toFixed(0)\n\n  const token0Addr = isTokenAToken0 ? tokenA.address : tokenB.address\n  const token1Addr = isTokenAToken0 ? tokenB.address : tokenA.address\n  \n  const poolAddrFirstTry = await univ3Factory.getPool(token0Addr, token1Addr, feeTier)\n  if (poolAddrFirstTry !== ethers.constants.AddressZero) {\n    return ethers.getContractAt(\"IUniswapV3Pool\", poolAddrFirstTry);\n  }\n\n  await positionManager.createAndInitializePoolIfNecessary(\n    token0Addr,\n    token1Addr,\n    feeTier,\n    sqrtX96Price\n  )\n\n  // avoid poolAddr being address(0) because requested too fast after last transaction. \n  let poolAddr: string \n  while(true) {\n    await delay(5000)\n    poolAddr = await univ3Factory.getPool(token0Addr, token1Addr, feeTier)\n    if (poolAddr !== ethers.constants.AddressZero) break;\n  }\n\n  const pool = await ethers.getContractAt(\"IUniswapV3Pool\", poolAddr);\n\n  return pool\n}\n\n/**\n * Get pool address, given 2 tokens\n * @param tokenA \n * @param tokenB \n * @param univ3Factory \n * @returns \n */\nexport const getPoolAddress = async (\n  tokenA: Contract, \n  tokenB: Contract,\n  univ3Factory: Contract,\n  fee = 3000\n) => {\n  const isTokenAToken0 = parseInt(tokenA.address, 16) < parseInt(tokenB.address, 16)\n\n  const token0Addr = isTokenAToken0 ? tokenA.address : tokenB.address\n  const token1Addr = isTokenAToken0 ? tokenB.address : tokenA.address\n  const poolAddr = await univ3Factory.getPool(token0Addr, token1Addr, fee)\n  return poolAddr as string\n} \n\n/**\n * Deploy controller, squeeth token and vaultNFT\n * @returns \n */\n export const deploySqueethCoreContracts= async(weth: Contract, dai: Contract, positionManager: Contract, uniswapFactory: Contract, wsqueethEthPrice?: number, ethDaiPrice?: number ) => {\n  // const { deployer } = await getNamedAccounts();\n\n  const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n  const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n\n  const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n  const TickMathLibrary = (await TickMath.deploy());\n\n  const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n  const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n  const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n\n  const OracleContract = await ethers.getContractFactory(\"Oracle\");\n  const oracle = (await OracleContract.deploy()) as Oracle;\n\n  const NFTContract = await ethers.getContractFactory(\"ShortPowerPerp\");\n  const shortSqueeth = (await NFTContract.deploy('short Squeeth', 'sSQU')) as ShortPowerPerp;\n\n  const WPowerPerpContract = await ethers.getContractFactory(\"WPowerPerp\");\n  const wsqueeth = (await WPowerPerpContract.deploy('Wrapped Squeeth', 'wSQU')) as WPowerPerp;\n\n  // 1 squeeth is 3000 eth\n  const squeethPriceInEth = wsqueethEthPrice || 0.3\n  const wsqueethEthPool = await createUniPool(squeethPriceInEth, weth, wsqueeth, positionManager, uniswapFactory) as Contract\n  // 1 weth is 3000 dai\n  const ethPriceInDai = ethDaiPrice || 3000\n  const ethDaiPool = await createUniPool(ethPriceInDai, dai, weth, positionManager, uniswapFactory) as Contract\n\n  await wsqueethEthPool.increaseObservationCardinalityNext(500) \n  await ethDaiPool.increaseObservationCardinalityNext(500) \n\n  const controller = (await ControllerContract.deploy(oracle.address, \n    shortSqueeth.address, \n    wsqueeth.address,\n    weth.address, \n    dai.address, \n    ethDaiPool.address, \n    wsqueethEthPool.address, \n    positionManager.address,\n    3000,\n  )) as Controller;\n  \n  await shortSqueeth.init(controller.address);\n  await wsqueeth.init(controller.address);\n  \n  return { controller, wsqueeth, shortSqueeth, ethDaiPool, wsqueethEthPool, oracle }\n}\n\nexport const addSqueethLiquidity = async(\n  squeethPriceInETH: number, \n  initLiquiditySqueethAmount: string, \n  collateralAmount: string,\n  deployer: string,\n  squeeth: WPowerPerp, \n  weth: WETH9,\n  positionManager: Contract,\n  controller: Controller,\n  feeTier = 3000\n  ) => {\n\n    const isWethToken0 = parseInt(weth.address, 16) < parseInt(squeeth.address, 16)\n\n    const token0 = isWethToken0 ? weth.address : squeeth.address\n    const token1 = isWethToken0 ? squeeth.address : weth.address\n    \n    const liquiditySqueethAmount = ethers.utils.parseEther(initLiquiditySqueethAmount) \n    const wethAmount = parseFloat(initLiquiditySqueethAmount) * squeethPriceInETH\n    const liquidityWethAmount = ethers.utils.parseEther(wethAmount.toString()) \n\n    let wsqueethBalance = await squeeth.balanceOf(deployer)\n    let wethBalance = await weth.balanceOf(deployer)\n    const is3000Fee = feeTier===3000 \n\n    if (wethBalance.lt(liquidityWethAmount)) {\n      await weth.deposit({value: liquidityWethAmount, from: deployer})\n      wethBalance = await weth.balanceOf(deployer)\n    }\n  \n    if (wsqueethBalance.lt(liquiditySqueethAmount)) {\n      // use {collateralAmount} eth to mint squeeth\n      await controller.mintWPowerPerpAmount(0, liquiditySqueethAmount.sub(wsqueethBalance), 0, {value: ethers.utils.parseEther(collateralAmount)}) \n      wsqueethBalance = await squeeth.balanceOf(deployer)\n    }\n\n    await weth.approve(positionManager.address, ethers.constants.MaxUint256)\n    await squeeth.approve(positionManager.address, ethers.constants.MaxUint256)\n    \n    const liquidityWSqueethAmount = wsqueethBalance\n\n    const mintParam = {\n      token0,\n      token1,\n      fee: feeTier,\n      tickLower: is3000Fee ? -887220: -887200,// int24 min tick used when selecting full range\n      tickUpper: is3000Fee ? 887220: 887200,// int24 max tick used when selecting full range\n      amount0Desired: isWethToken0 ? liquidityWethAmount : liquidityWSqueethAmount,\n      amount1Desired: isWethToken0 ? liquidityWSqueethAmount : liquidityWethAmount,\n      amount0Min: 1,\n      amount1Min: 1,\n      recipient: deployer,// address\n      deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n    }\n\n    const tx = await (positionManager as INonfungiblePositionManager).mint(mintParam)\n    const receipt = await tx.wait();\n    const tokenId : BigNumber = (receipt.events?.find(event => event.event === 'IncreaseLiquidity'))?.args?.tokenId;\n\n    return tokenId.toNumber()\n}\n\nexport const addWethDaiLiquidity = async(\n  ethPrice: number, \n  ethAmount: BigNumber, \n  deployer: string,\n  dai: MockErc20, \n  weth: WETH9,\n  positionManager: Contract,\n  feeTier = 3000\n  ) => {\n\n    const isWethToken0 = parseInt(weth.address, 16) < parseInt(dai.address, 16)\n\n    const token0 = isWethToken0 ? weth.address : dai.address\n    const token1 = isWethToken0 ? dai.address : weth.address\n    \n    const daiAmount = new BigNumberJs(ethAmount.toString()).multipliedBy(ethPrice)\n    \n    const daiBalance = new BigNumberJs((await dai.balanceOf(deployer)).toString())\n    const wethBalance = new BigNumberJs((await weth.balanceOf(deployer)).toString())\n\n    if (wethBalance.isLessThan(ethAmount.toString())) {\n      await weth.deposit({value: ethAmount.toString(), from: deployer})\n    }\n  \n    if (daiBalance.lt(daiAmount)) {\n      await dai.mint(deployer,daiAmount.toString() ) \n    }\n\n    await dai.approve(positionManager.address, ethers.constants.MaxUint256)\n    await weth.approve(positionManager.address, ethers.constants.MaxUint256)\n    \n    const mintParam = {\n      token0,\n      token1,\n      fee: feeTier,\n      tickLower: -887220,// int24 min tick used when selecting full range\n      tickUpper: 887220,// int24 max tick used when selecting full range\n      amount0Desired: isWethToken0 ? ethAmount.toString() : daiAmount.toString(),\n      amount1Desired: isWethToken0 ? daiAmount.toString() : ethAmount.toString(),\n      amount0Min: 1,\n      amount1Min: 1,\n      recipient: deployer,// address\n      deadline: Math.floor(await getNow(ethers.provider) + 8640000),// uint256\n    }\n\n    const tx = await (positionManager as INonfungiblePositionManager).mint(mintParam)\n    const receipt = await tx.wait();\n    const tokenId : BigNumber = (receipt.events?.find(event => event.event === 'IncreaseLiquidity'))?.args?.tokenId;\n\n    return tokenId.toNumber()\n}\n\nexport const removeAllLiquidity = async(tokenId: number, positionManager: any) => {\n  const res = await positionManager.positions(tokenId)\n  const liquidity = res.liquidity as BigNumber\n  const burnParam = {\n    tokenId,\n    liquidity,\n    amount0Min: 0,\n    amount1Min: 0,\n    deadline: Math.floor(await getNow(ethers.provider) + 8640000)\n  }\n  await (positionManager as INonfungiblePositionManager).decreaseLiquidity(burnParam)\n}\n\nfunction delay(ms: number) {\n  return new Promise( resolve => setTimeout(resolve, ms) );\n}\n\nexport const buyWSqueeth = async(router: Contract, wsqueeth: Contract, weth: Contract, recipient: string, amountIn: BigNumber, deadline: number) => {\n  const swapParam = {\n    tokenIn: weth.address,\n    tokenOut: wsqueeth.address,\n    fee: 3000,\n    recipient,\n    deadline,\n    amountIn,\n    amountOutMinimum: 0,\n    sqrtPriceLimitX96: 0\n  }\n  \n  await weth.deposit({value: amountIn});\n  await weth.approve(router.address, amountIn);\n\n  await router.exactInputSingle(swapParam);\n}\n\nexport const buyWeth = async(router: Contract, wsqueeth: Contract, weth: Contract, recipient: string, amountIn: BigNumber, deadline: number) => {\n  const swapParam = {\n    tokenIn: wsqueeth.address,\n    tokenOut: weth.address,\n    fee: 3000,\n    recipient,\n    deadline,\n    amountIn,\n    amountOutMinimum: 0,\n    sqrtPriceLimitX96: 0\n  }\n  \n  await wsqueeth.approve(router.address, amountIn);\n\n  await router.exactInputSingle(swapParam);\n}"
  },
  {
    "path": "packages/hardhat/test/unit-tests/abdk-math.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { BigNumber } from \"ethers\";\nimport { ABDKTester, ABDKMath64x64 } from \"../../typechain\";\nimport { isSimilar } from \"../utils\";\n\n\n\ndescribe(\"ABDKMath64x64 testing\", function () {\n\n  let abdkTester: ABDKTester\n  const two = BigNumber.from(2)\n\n\n  before('deploy contract', async() => {\n    const abtkContract = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await abtkContract.deploy()) as ABDKMath64x64;\n  \n    const abdkTesterContract = await ethers.getContractFactory(\"ABDKTester\", {libraries: {ABDKMath64x64: ABDKLibrary.address}});\n    abdkTester = (await abdkTesterContract.deploy()) as ABDKTester;\n\n  })\n\n  describe(\"ABDK reverts and underflow results as expected\", async () => {\n    \n    it(\"mul should revert if x * y is above MAX_64x64 due to overflow\", async () => {\n        // max = 2^127 - 1\n        await expect(abdkTester.testMul(two.pow(96),two.pow(96))).to.be.revertedWith(\"MUL-OVUF\")\n    })\n\n    it(\"mul should revert if x * y below MIN_64x64 from underflow\", async () => {\n        // min = -2^127\n        await expect(abdkTester.testNegMul(two.pow(96),two.pow(96))).to.be.revertedWith(\"MUL-OVUF\")\n    })\n    \n    it(\"mulu should revert if x<0\", async () => {\n        const x = two.mul(-1)\n        await expect(abdkTester.testMulu(x,two)).to.be.revertedWith(\"MULU-X0\")\n    })\n\n    // it(\"mulu should revert if overflows uint128\", async () => {\n    //     const x = two.pow(65)\n    //     const y = two.pow(256).sub(1)\n    //     await expect(abdkTester.testMulu(x,y)).to.be.revertedWith(\"MULU-OF2\")\n    // })\n\n    it(\"mulu should revert if overflows int128\", async () => {\n        const x = two.pow(100)\n        const y = two.pow(240)\n        await expect(abdkTester.testMulu(x,y)).to.be.revertedWith(\"MULU-OF1\")\n    })\n\n    it(\"divu should revert if y = 0\", async () => {\n        await expect(abdkTester.testDivu(1,0)).to.be.revertedWith(\"DIVU-INF\")\n    })\n\n    it(\"divu should revert when result x>2^128 and result > 2^128\", async () => {\n        const x = two.pow(255)\n        const y = two.pow(1)\n\n        await expect(abdkTester.testDivu(x,y)).to.be.revertedWith(\"DIVUU-OF1\")\n    })\n\n    it(\"divu should revert when calculating division for x=2^127 with y=2^64, reverting when casting uint128 to int128 above MAX_64x64\", async () => {\n        const x = two.pow(127)\n        const y = two.pow(64)\n\n        await expect(abdkTester.testDivu(x,y)).to.be.revertedWith(\"DIVU-OF\")\n    })\n\n    it(\"divu should revert when calculating division for x=2^127 with y=2^64, reverting when overflowing uint128\", async () => {\n        const x = two.pow(128)\n        const y = two.pow(64)\n\n        await expect(abdkTester.testDivu(x,y)).to.be.revertedWith(\"DIVUU-OF2\")\n    })\n\n    it(\"log_2 should revert when calling with a negative x\", async () => {\n        await expect(abdkTester.testLog_2(-1)).to.be.revertedWith(\"LOG_2-X0\")\n    })\n\n    it(\"exp_2 should revert when calling with larger than 2^70\", async () => {\n        const x = two.pow(70).add(1)\n        \n        await expect(abdkTester.testExp_2(x)).to.be.revertedWith(\"EXP_2-OF\")\n    })\n\n    it(\"exp_2 should return 0 when calling with less than -2^70\", async () => {\n        const x = two.pow(70).add(1)\n        \n        const result = await abdkTester.testExp_2(x.mul(-1))\n        expect(result.eq(0)).to.be.true\n    })\n\n  })\n\n  describe(\"ABDK calculates as expected\", async () => {    \n    it(\"mulu should return 0 if y = 0\", async () => {\n        const result = await abdkTester.testMulu(1,0)\n        expect(result.eq(0)).to.be.true\n    })\n\n    it(\"mulu should correctly calculate multiplication for 1.1 fixed and uint256 1e18, returing 1.1e18\", async () => {\n        const x64 = two.pow(64)\n        const x = x64.mul(11).div(10) // 1.1 in fixed point\n        const y = ethers.utils.parseUnits(\"1\")\n\n        const expectedResult = y.mul(11).div(10)\n\n        const result = await abdkTester.testMulu(x,y)\n\n        expect(isSimilar(result.toString(),expectedResult.toString())).to.be.true\n    })\n\n    it(\"divu should correctly calculate division for x=2^75 with y=2^50, returing 2^25 * 2^64\", async () => {\n        const x = two.pow(75)\n        const y = two.pow(50)\n        const x64 = two.pow(64)\n        const expectedResult = x.mul(x64).div(y)\n\n        const result = await abdkTester.testDivu(x,y)\n        expect(result.eq(expectedResult)).to.be.true\n    })\n\n    it(\"divu should correctly calculate division for x=2^129 with y=2^128, returing 2^1 * 2^64\", async () => {\n        const x = two.pow(129)\n        const y = two.pow(128)\n        const x64 = two.pow(64)\n        const expectedResult = x.mul(x64).div(y)\n\n        const result = await abdkTester.testDivu(x,y)\n        expect(result.eq(expectedResult)).to.be.true\n    })\n\n    it(\"divu should correctly calculate division for x=2^127-1 with y=2^64\", async () => {\n        const x = two.pow(127).sub(1)\n        const y = two.pow(64)\n        const x64 = two.pow(64)\n        const expectedResult = x.mul(x64).div(y)\n\n        const result = await abdkTester.testDivu(x,y)\n        expect(result.eq(expectedResult)).to.be.true\n    })\n\n    it(\"divu should correctly calculate division for x=2^255 with y=2^230\", async () => {\n        const x = two.pow(255)\n        const y = two.pow(230)\n        const x64 = two.pow(64)\n        const expectedResult = x.mul(x64).div(y)\n\n        const result = await abdkTester.testDivu(x,y)\n        expect(result.eq(expectedResult)).to.be.true\n    })\n\n    it(\"divu should correctly calculate division for x=2^255 with y=2^5\", async () => {\n        const x = two.pow(194)\n        const y = two.pow(135)\n        const x64 = two.pow(64)\n        const expectedResult = x.mul(x64).div(y)\n\n        const result = await abdkTester.testDivu(x,y)\n        expect(result.eq(expectedResult)).to.be.true\n    })\n\n    it(\"divu should correctly calculate log2 for x=5*2^5\", async () => {\n        const x = two.pow(70).mul(5)\n        const x64 = two.pow(64)\n        const xInHuman = x.div(x64)\n        const expectedResult = (Math.log2(xInHuman.toNumber())).toString()\n        const expectedResultIn1e18 = ethers.utils.parseUnits(expectedResult)\n        const expectedResulInX64 = expectedResultIn1e18.mul(two.pow(64)).div(ethers.utils.parseUnits(\"1\"))\n\n        const result = await abdkTester.testLog_2(x)        \n        \n        expect(isSimilar(result.toString(),expectedResulInX64.toString())).to.be.true\n    })\n\n  })\n})"
  },
  {
    "path": "packages/hardhat/test/unit-tests/casting.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { CastingTester } from \"../../typechain\";\n\ndescribe(\"Casting Library tests\", function () {\n\n  let tester: CastingTester\n\n  before('deploy contract', async() => {\n    const CastingTesterFactory = await ethers.getContractFactory(\"CastingTester\");\n    tester = (await CastingTesterFactory.deploy()) as CastingTester;\n  })\n\n  describe(\"Math checks for overflow\", async () => {\n    it(\"should revert if casting oversize uint256 to uint128 overflows\", async () => {\n      await expect(tester.testToUint128(ethers.constants.MaxUint256)).to.be.revertedWith(\"OF128\")\n    })\n\n    it(\"should revert if casting oversize uint256 to uint96 overflows\", async () => {\n      await expect(tester.testToUint96(ethers.constants.MaxUint256)).to.be.revertedWith(\"OF96\")\n    })\n\n    it(\"should revert if casting oversize uint256 to uint32 overflows\", async () => {\n      await expect(tester.testToUint32(ethers.constants.MaxUint256)).to.be.revertedWith(\"OF32\")\n    })\n  })\n})"
  },
  {
    "path": "packages/hardhat/test/unit-tests/controller-funding.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { BigNumber, providers, utils } from \"ethers\";\nimport { getNow, isSimilar, one, oracleScaleFactor } from \"../utils\";\nimport { Controller, MockWPowerPerp, MockShortPowerPerp, MockOracle, MockUniswapV3Pool, MockErc20, MockUniPositionManager, ABDKMath64x64} from \"../../typechain\";\n\nconst squeethETHPrice = BigNumber.from('3030').mul(one).div(oracleScaleFactor)\nconst ethUSDPrice = BigNumber.from('3000').mul(one)\nconst scaledEthPrice = ethUSDPrice.div(oracleScaleFactor)\n\nconst mintAmount = BigNumber.from('100').mul(one)\nconst collateralAmount = BigNumber.from('50').mul(one)\n\ndescribe(\"Controller Funding tests\", function () {\n  let squeeth: MockWPowerPerp;\n  let shortSqueeth: MockShortPowerPerp;\n  let controller: Controller;\n  let squeethEthPool: MockUniswapV3Pool;\n  let ethUSDPool: MockUniswapV3Pool;\n  let uniPositionManager: MockUniPositionManager\n  let oracle: MockOracle;\n  let weth: MockErc20;\n  let usdc: MockErc20;\n  let provider: providers.JsonRpcProvider;\n  let seller1: SignerWithAddress\n  let random: SignerWithAddress\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_seller1, _random] = accounts;\n    seller1 = _seller1\n    random = _random\n    provider = ethers.provider\n\n    await provider.send(\"evm_setAutomine\", [true]);\n  })\n\n  this.beforeAll(\"Setup environment\", async () => {\n    const MockSQUContract = await ethers.getContractFactory(\"MockWPowerPerp\");\n    squeeth = (await MockSQUContract.deploy()) as MockWPowerPerp;\n\n    const NFTContract = await ethers.getContractFactory(\"MockShortPowerPerp\");\n    shortSqueeth = (await NFTContract.deploy()) as MockShortPowerPerp;\n\n    const OracleContract = await ethers.getContractFactory(\"MockOracle\");\n    oracle = (await OracleContract.deploy()) as MockOracle;\n\n    const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n    weth = (await MockErc20Contract.deploy(\"WETH\", \"WETH\", 18)) as MockErc20;\n    usdc = (await MockErc20Contract.deploy(\"USDC\", \"USDC\", 6)) as MockErc20;\n\n    const MockUniswapV3PoolContract = await ethers.getContractFactory(\"MockUniswapV3Pool\");\n    squeethEthPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n    ethUSDPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n\n    const MockPositionManager = await ethers.getContractFactory(\"MockUniPositionManager\");\n    uniPositionManager = (await MockPositionManager.deploy()) as MockUniPositionManager;\n\n    await squeethEthPool.setPoolTokens(weth.address, squeeth.address);\n    await ethUSDPool.setPoolTokens(weth.address, usdc.address);\n\n\n    await oracle.connect(random).setPrice(squeethEthPool.address , squeethETHPrice) // eth per 1 squeeth\n    await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPrice)  // usdc per 1 eth\n  });\n\n  describe(\"Deployment\", async () => {\n    it(\"Deployment\", async function () {\n\n      const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n      const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n    \n      const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n      const TickMathLibrary = (await TickMath.deploy());\n  \n      const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n      const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n  \n      const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n        controller = (await ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, weth.address, usdc.address, ethUSDPool.address, squeethEthPool.address, uniPositionManager.address, 3000)) as Controller;\n    });\n  });\n\n  describe('Funding actions', async() => {\n    describe('Normalization Factor tests', () => {\n      let mark: BigNumber\n      let index: BigNumber\n      let fundingPeriod: BigNumber\n\n      before(async () => {  \n        fundingPeriod = await controller.FUNDING_PERIOD()\n\n        await controller.applyFunding()\n        mark = await controller.getDenormalizedMarkForFunding(1)\n        index = await controller.getIndex(1)\n      })\n  \n      it('should apply the correct normalization factor for funding', async() => {\n        const now = await getNow(provider)\n        const normalizationFactorBefore = await controller.normalizationFactor()\n        const secondsElapsed = 10800 // 3hrs\n        const multiplier = getNormFactorMultiplier(mark, index, secondsElapsed, fundingPeriod)\n        const expectedNormalizationFactor = normalizationFactorBefore.mul(multiplier).div(one)\n\n        await provider.send(\"evm_setNextBlockTimestamp\", [now + secondsElapsed]) \n\n        await controller.connect(seller1).applyFunding()       \n        const normalizationFactorAfter = await controller.normalizationFactor()\n        // use isSimilar because sometimes the expectedNormFactor will be a little bit off, \n        // maybe caused by inconsistent process time by hardhat\n        expect(isSimilar(expectedNormalizationFactor.toString(), normalizationFactorAfter.toString(), 14)).to.be.true\n      })\n      it('normalization factor changes should be bounded above', async() => {\n\n        // Get norm factor\n        const normalizationFactorBefore = await controller.normalizationFactor()\n        const now = await getNow(provider)\n\n        // Set very low mark price\n        const squeethETHPriceNew = ethers.utils.parseUnits('2000').div(oracleScaleFactor)\n        const ethUSDPriceNew = ethers.utils.parseUnits('3000')\n\n        // Set prices\n        await oracle.connect(random).setPrice(squeethEthPool.address , squeethETHPriceNew) // eth per 1 squeeth\n        await oracle.connect(random).setPrice(ethUSDPool.address, ethUSDPriceNew)  // usdc per 1 eth\n\n        // Get new mark and index\n        mark = await controller.getDenormalizedMarkForFunding(1)\n        index = await controller.getIndex(1)\n\n        // + 3 hours \n        const secondsElapsed = 10800\n\n        await provider.send(\"evm_setNextBlockTimestamp\", [now + secondsElapsed]) // (3/24) * 60*60 = 3600s = 3 hour\n        await controller.connect(seller1).applyFunding()   \n        \n        // Get new new norm factor\n        const normalizationFactorAfter = await controller.normalizationFactor()\n\n        // Mark should be bounded 4/5, 5/4\n        const scaledEthUSDPrice = ethUSDPriceNew.div(oracleScaleFactor)\n        const expectedFloorMark = scaledEthUSDPrice.mul(scaledEthUSDPrice).mul(4).div(5).div(one)\n\n        // Expected bounded norm factor\n        const multiplier = getNormFactorMultiplier(expectedFloorMark, index, secondsElapsed, fundingPeriod)\n        const expectedNormalizationFactor = normalizationFactorBefore.mul(multiplier).div(one)\n\n        // use isSimilar because sometimes the expectedNormFactor will be a little bit off, \n        // maybe caused by inconsistent process time by hardhat\n        expect(isSimilar(expectedNormalizationFactor.toString(), normalizationFactorAfter.toString(), 15)).to.be.true\n      })\n      it('normalization factor changes should be bounded below', async() => {\n\n        // Get norm factor\n        const normalizationFactorBefore = await controller.normalizationFactor()\n        const now = await getNow(provider)\n\n        // Set very high mark price\n        const squeethETHPriceNew = ethers.utils.parseUnits('6000').div(oracleScaleFactor)\n        const ethUSDPriceNew = ethers.utils.parseUnits('3000')\n\n        // Set prices\n        await oracle.connect(random).setPrice(squeethEthPool.address , squeethETHPriceNew) // eth per 1 squeeth\n        await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPriceNew)  // usdc per 1 eth\n\n        // Get new mark and index\n        mark = await controller.getDenormalizedMarkForFunding(1)\n        index = await controller.getIndex(1)  \n\n        // + 3 hours\n        const secondsElapsed = 10800 // 3hrs\n\n        await provider.send(\"evm_setNextBlockTimestamp\", [now + secondsElapsed]) \n        await controller.connect(seller1).applyFunding()   \n        \n        // Get new new norm factor\n        const normalizationFactorAfter = await controller.normalizationFactor()\n\n        // Mark should be bounded 4/5, 5/4\n        const scaledEthUSDPrice = ethUSDPriceNew.div(oracleScaleFactor)\n        const expectedCeilMark = scaledEthUSDPrice.mul(scaledEthUSDPrice).mul(14).div(10).div(one)\n\n        // Expected bounded norm factor\n        const multiplier = getNormFactorMultiplier(expectedCeilMark, index, secondsElapsed, fundingPeriod)\n        const expectedNormalizationFactor = normalizationFactorBefore.mul(multiplier).div(one)\n\n        expect(isSimilar(expectedNormalizationFactor.toString(), normalizationFactorAfter.toString(), 14)).to.be.true\n      })\n      it('calling apply funding with little time elapsed should not affect norm factor', async() => {\n        await oracle.connect(random).setPrice(squeethEthPool.address , squeethETHPrice) // eth per 1 squeeth\n        await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPrice)  // usdc per 1 eth\n        \n        await controller.applyFunding()\n        const normFactor0 = await controller.normalizationFactor()\n        const timestamp0 = await getNow(provider)\n        \n        const timestamp1 = await timestamp0 + 10\n        await provider.send(\"evm_setNextBlockTimestamp\", [timestamp1]) \n        await controller.applyFunding()\n        const normFactor1 = await controller.normalizationFactor()\n\n        const timestamp2 = await timestamp1 + 10\n        await provider.send(\"evm_setNextBlockTimestamp\", [timestamp2]) \n        await controller.applyFunding()\n        const normFactor2 = await controller.normalizationFactor()\n\n        // update should be < 1.0001\n        expect(isSimilar(normFactor0.toString(), normFactor1.toString(), 4)).to.be.true\n        expect(isSimilar(normFactor0.toString(), normFactor2.toString(), 4)).to.be.true\n      })\n    })\n\n    describe('Funding collateralization tests', () => {\n      const collatRatio = ethers.utils.parseUnits('1.5')\n      let fundingPeriod: BigNumber\n\n      describe('mint', async() => {\n        let vaultId: BigNumber\n        let maxSqueethToMint: BigNumber\n        const secondsElapsed = 21600 // 6 hours\n\n        before('prepare a vault', async() => {\n          fundingPeriod = await controller.FUNDING_PERIOD()\n\n          // set prices back\n          await oracle.connect(random).setPrice(squeethEthPool.address , squeethETHPrice) // eth per 1 squeeth\n          await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPrice)  // usdc per 1 eth\n          await controller.applyFunding()\n          \n          vaultId = await shortSqueeth.nextId()\n          // mint max amount of rSqueeth\n          maxSqueethToMint = collateralAmount.mul(one).mul(one).div(collatRatio).div(scaledEthPrice)\n\n          await controller.connect(seller1).mintPowerPerpAmount(0, maxSqueethToMint, 0, {value: collateralAmount})\n\n          // advance time\n        })\n        it('should revert if minting too much squeeth after funding', async() => {\n          const mark = await controller.getDenormalizedMarkForFunding(1)\n          const index = await controller.getIndex(1)\n\n          const now = await getNow(provider)\n    \n          const newVault = await controller.vaults(vaultId)\n          const shortAmount = newVault.shortAmount\n          const collateral = newVault.collateralAmount\n  \n          const normalizationFactorBefore = await controller.normalizationFactor()\n  \n          const multiplier = getNormFactorMultiplier(mark, index, secondsElapsed, fundingPeriod)\n          const expectedNormalizationFactor = normalizationFactorBefore.mul(multiplier).div(one)\n\n          const currentRSqueeth = shortAmount.mul(expectedNormalizationFactor).div(one)\n          const maxShortRSqueeth = one.mul(one).mul(collateral).div(scaledEthPrice).div(collatRatio)\n\n          const expectedAmountCanMint = maxShortRSqueeth.sub(currentRSqueeth)\n\n          await provider.send(\"evm_setNextBlockTimestamp\", [now + secondsElapsed])\n          await expect(controller.connect(seller1).mintPowerPerpAmount(vaultId, expectedAmountCanMint.mul(10001).div(10000), 0, {value: 0})).to.be.revertedWith(\n            'C24'\n          )\n        })\n\n        it('should mint more wSqueeth after funding', async() => {\n          const mark = await controller.getDenormalizedMarkForFunding(1)\n          const index = await controller.getIndex(1)\n\n  \n          const multiplier = getNormFactorMultiplier(mark, index, secondsElapsed, fundingPeriod)\n\n          // 1 squeeth - 1squeeth * 0.99\n\n          const expectedAmountCanMint = maxSqueethToMint.sub(maxSqueethToMint.mul(multiplier).div(one))\n\n          // set next block to be 1 seconds after last block, so the max we can mint is almost the same\n          const now = await getNow(provider)\n          await provider.send(\"evm_setNextBlockTimestamp\", [now + 1])\n          await controller.connect(seller1).mintPowerPerpAmount(vaultId, expectedAmountCanMint, 0 ,{value: 0}) \n        })\n      })\n      \n      describe('withdraw', async () => {\n        let vaultId: BigNumber\n        let maxCollatToRemove: BigNumber\n\n        before('prepare a vault and stimulate time passes', async() => {\n          fundingPeriod = await controller.FUNDING_PERIOD()\n\n          vaultId = await shortSqueeth.nextId()  \n          // put vaultId as 0 to open vault\n          await controller.connect(seller1).mintPowerPerpAmount(0, mintAmount,0, {value: collateralAmount})\n          const now = await getNow(provider)\n  \n          const markPrice = await controller.getDenormalizedMarkForFunding(1)\n          const indexPrice = await controller.getIndex(1)\n          const newVault = await controller.vaults(vaultId)\n          const shortAmount = newVault.shortAmount\n          const collateral = newVault.collateralAmount\n\n          const normalizationFactorBefore = await controller.normalizationFactor()\n\n          const secondsElapsed = 10800\n          const multiplier = getNormFactorMultiplier(markPrice, indexPrice, secondsElapsed, fundingPeriod)\n          const expectedNormalizationFactor = normalizationFactorBefore.mul(multiplier).div(one)\n\n          const collatRequired = shortAmount.mul(expectedNormalizationFactor).mul(scaledEthPrice).mul(collatRatio).div(one.mul(one).mul(one))\n          maxCollatToRemove = collateral.sub(collatRequired)\n\n          await provider.send(\"evm_setNextBlockTimestamp\", [now + secondsElapsed])\n        })\n        it('should revert when trying to withdraw too much collateral', async() =>{\n          await expect((controller.connect(seller1).withdraw(vaultId, maxCollatToRemove.mul(1001).div(1000)))).to.be.revertedWith(\n            'C24'\n          )\n        })\n\n        it('should be able to withdraw more collateral after funding', async() => {\n          const userEthBalanceBefore = await provider.getBalance(seller1.address)\n          \n          // set next block to be 1 seconds after last block, so the max we can withdraw is almost the same\n          const now = await getNow(provider)\n          await provider.send(\"evm_setNextBlockTimestamp\", [now + 1])\n\n          await controller.connect(seller1).withdraw(vaultId, maxCollatToRemove) \n  \n          const newAfterVault = await controller.vaults(vaultId)\n          const newCollateralAmount = newAfterVault.collateralAmount\n          const userEthBalanceAfter = await provider.getBalance(seller1.address)\n          \n          expect(maxCollatToRemove.eq(collateralAmount.sub(newCollateralAmount))).to.be.true\n          expect(userEthBalanceAfter.eq(userEthBalanceBefore.add(maxCollatToRemove)))      \n        })\n      })\n    })\n\n    describe('Extreme cases for normalization factor', async() => {\n      let fundingPeriod: BigNumber\n\n      before('get funding period', async() => {\n        fundingPeriod = await controller.FUNDING_PERIOD()\n      })\n\n\n      it('should get capped normalization factor when mark = 0 ', async() => {\n        // Get norm factor\n        const normalizationFactorBefore = await controller.normalizationFactor()\n        const now = await getNow(provider)\n\n        // Set very low mark price\n        const squeethETHPriceNew = 0\n        const ethUSDPriceNew = ethers.utils.parseUnits('3000')\n\n        // Set prices\n        await oracle.connect(random).setPrice(squeethEthPool.address , squeethETHPriceNew) // eth per 1 squeeth\n        await oracle.connect(random).setPrice(ethUSDPool.address, ethUSDPriceNew)  // usdc per 1 eth\n        const index = await controller.getIndex(1)\n\n        // + 3 hours \n        const secondsElapsed = 10800\n        await provider.send(\"evm_setNextBlockTimestamp\", [now + secondsElapsed]) \n        await controller.connect(seller1).applyFunding()   \n\n        // Get new new norm factor\n        const normalizationFactorAfter = await controller.normalizationFactor()\n\n        // Mark should be bounded 4/5, 5/4\n        const scaledEthUSDPrice = ethUSDPriceNew.div(oracleScaleFactor)\n        const expectedFloorMark = scaledEthUSDPrice.mul(scaledEthUSDPrice).mul(4).div(5).div(one)\n\n        // Expected bounded norm factor\n        const multiplier = getNormFactorMultiplier(expectedFloorMark, index, secondsElapsed, fundingPeriod)\n        const expectedNormalizationFactor = normalizationFactorBefore.mul(multiplier).div(one)\n\n        expect(isSimilar(expectedNormalizationFactor.toString(), normalizationFactorAfter.toString(), 15)).to.be.true\n      })\n      it('should get capped normalization factor if eth price crashes', async() => {\n        // Get norm factor\n        const normalizationFactorBefore = await controller.normalizationFactor()\n        const now = await getNow(provider)\n\n        // Set very low index price\n        const squeethETHPriceNew = ethers.utils.parseUnits('3000').div(oracleScaleFactor)\n        const ethUSDPriceNew = ethers.utils.parseUnits('0.0001')\n\n        // Set prices\n        await oracle.connect(random).setPrice(squeethEthPool.address , squeethETHPriceNew) // eth per 1 squeeth\n        await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPriceNew)  // usdc per 1 eth\n\n        const index = await controller.getIndex(1)  \n\n        // + 3 hours\n        const secondsElapsed = 10800 // 3hrs\n        await provider.send(\"evm_setNextBlockTimestamp\", [now + secondsElapsed]) \n        await controller.connect(random).applyFunding()   \n\n        // Get new new norm factor\n        const normalizationFactorAfter = await controller.normalizationFactor()\n\n        // Mark should be bounded 4/5, 5/4\n        const scaledEthUSDPrice = ethUSDPriceNew.div(oracleScaleFactor)\n        const expectedCeilMark = scaledEthUSDPrice.mul(scaledEthUSDPrice).mul(14).div(10).div(one)\n        \n\n        // Expected bounded norm factor\n        const multiplier = getNormFactorMultiplier(expectedCeilMark, index, secondsElapsed, fundingPeriod)\n        const expectedNormalizationFactor = normalizationFactorBefore.mul(multiplier).div(one)\n\n        expect(isSimilar(expectedNormalizationFactor.toString(), normalizationFactorAfter.toString(), 14)).to.be.true\n\n        // norm factor after - norm factor before should be bounded, even now index is 0\n        expect(normalizationFactorAfter.sub(normalizationFactorBefore).lt(one))        \n      })\n      it('calling applying funding every 12 hours * 2 times, should result in an equal norm factor vs calling 1 time after 24hours', async() => {\n        const initialTime = await getNow(provider)\n        const secsInOneDay  = 86400\n\n        const day0Initial = await initialTime + secsInOneDay\n\n        const normFactor = await controller.normalizationFactor()\n        await oracle.connect(random).setPrice(squeethEthPool.address , squeethETHPrice.mul(normFactor).div(one))\n        await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPrice)\n\n        await provider.send(\"evm_setNextBlockTimestamp\", [day0Initial]) \n        await provider.send(\"evm_mine\", [])\n\n        const expNormFactor0 = await controller.getExpectedNormalizationFactor()\n        const expectedWsqueethPrice0 = squeethETHPrice.mul(expNormFactor0).div(one)\n        \n        await controller.applyFunding()\n        await oracle.setPrice(squeethEthPool.address, expectedWsqueethPrice0)\n\n        // norm0 => norm1 is applying funding once in 24 hr\n        const normFactor0 = await controller.normalizationFactor()\n\n        // update wsqueeth / eth price to make sure denorm mark is the same\n        const day0 = await getNow(provider)\n        \n        const day1 = await day0 + secsInOneDay\n        await provider.send(\"evm_setNextBlockTimestamp\", [day1]) \n        await provider.send(\"evm_mine\", []) \n\n        const expNormFactor1 = await controller.getExpectedNormalizationFactor()\n        const expectedWsqueethPrice1 = squeethETHPrice.mul(expNormFactor1).div(one)\n        \n        await controller.applyFunding()\n        await oracle.setPrice(squeethEthPool.address, expectedWsqueethPrice1)\n        \n        const normFactor1 = await controller.normalizationFactor()\n        const day1ChangeRatio = normFactor1.mul(one).div(normFactor0)\n        \n        // norm1 => norm2 is applying funding twice in 24 hr\n        const day1AndHalf = await day1 + secsInOneDay/2\n        await provider.send(\"evm_setNextBlockTimestamp\", [day1AndHalf]) \n        await provider.send(\"evm_mine\", []) \n\n        const expNormFactor = await controller.getExpectedNormalizationFactor()\n        const expectedWsqueethPrice2 = squeethETHPrice.mul(expNormFactor).div(one)\n        \n        await controller.applyFunding()\n        await oracle.setPrice(squeethEthPool.address, expectedWsqueethPrice2)\n\n        const day2 = await day1 + secsInOneDay\n        await provider.send(\"evm_setNextBlockTimestamp\", [day2])\n        await provider.send(\"evm_mine\", []) \n        const expNormFactor2 = await controller.getExpectedNormalizationFactor()\n        const expectedWsqueethPrice3 = squeethETHPrice.mul(expNormFactor2).div(one)\n        \n        await controller.applyFunding()\n        await oracle.setPrice(squeethEthPool.address, expectedWsqueethPrice3)\n\n        const normFactor2 = await controller.normalizationFactor()\n        const day2ChangeRatio = normFactor2.mul(one).div(normFactor1)\n        \n        expect(isSimilar(day2ChangeRatio.toString(),day1ChangeRatio.toString())).to.be.true\n      })\n    })\n  })\n  \n});\n\nfunction getNormFactorMultiplier(mark: BigNumber, index:BigNumber, secondsElapsed: number, fundingPeriod: BigNumber) {\n  \n  const ratio =   parseFloat(utils.formatEther(index.mul(one).div(mark)))\n  const r = secondsElapsed/(fundingPeriod.toNumber())\n  const exponent = Math.log2(ratio)*r\n\n  return BigNumber.from(ethers.utils.parseUnits((2**exponent).toString()))\n}"
  },
  {
    "path": "packages/hardhat/test/unit-tests/controller-lptoken-collateral.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { BigNumber } from \"ethers\";\nimport { parseEther } from \"ethers/lib/utils\";\nimport { Controller, MockWPowerPerp, MockShortPowerPerp, MockOracle, MockUniswapV3Pool, MockErc20, MockUniPositionManager, VaultLibTester, IWETH9, LiquidationHelper, ABDKMath64x64 } from \"../../typechain\";\nimport { getSqrtPriceAndTickBySqueethPrice } from \"../calculator\";\nimport { oracleScaleFactor, one } from \"../utils\";\n\n// use the same price at first, so there's no funding.\nconst squeethETHPrice = BigNumber.from('3000').mul(one)\nconst scaledSqueethPrice = squeethETHPrice.div(oracleScaleFactor)\n\n\n// eth dai price\nconst ethDaiPrice = BigNumber.from('3000').mul(one)\n\n\ndescribe(\"Controller: Uni LP tokens collateralization\", function () {\n  let squeeth: MockWPowerPerp;\n  let shortSqueeth: MockShortPowerPerp;\n  let controller: Controller;\n  let squeethEthPool: MockUniswapV3Pool;\n  let ethDaiPool: MockUniswapV3Pool;\n  let uniPositionManager: MockUniPositionManager\n  let oracle: MockOracle;\n  let weth: IWETH9;\n  let dai: MockErc20;\n  let vaultLib: VaultLibTester\n  let liquidationHelper: LiquidationHelper\n  let seller1: SignerWithAddress\n  let random: SignerWithAddress\n  let liquidator: SignerWithAddress\n\n  let daiIsToken0InEthPool: boolean\n  let wethIsToken0InSqueethPool: boolean\n\n  const provider = ethers.provider\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners();\n    const [,_seller1, _random, _liquidator] = accounts;\n    seller1 = _seller1\n    random = _random\n    liquidator = _liquidator\n  })\n\n  this.beforeAll(\"Setup environment\", async () => {\n    const MockSQUContract = await ethers.getContractFactory(\"MockWPowerPerp\");\n    squeeth = (await MockSQUContract.deploy()) as MockWPowerPerp;\n\n    const NFTContract = await ethers.getContractFactory(\"MockShortPowerPerp\");\n    shortSqueeth = (await NFTContract.deploy()) as MockShortPowerPerp;\n\n    const OracleContract = await ethers.getContractFactory(\"MockOracle\");\n    oracle = (await OracleContract.deploy()) as MockOracle;\n\n    const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n    dai = (await MockErc20Contract.deploy(\"Dai\", \"Dai\", 18)) as MockErc20;\n\n    const WETH9Contract = await ethers.getContractFactory(\"WETH9\");\n    weth = (await WETH9Contract.deploy()) as IWETH9;\n\n    const MockUniswapV3PoolContract = await ethers.getContractFactory(\"MockUniswapV3Pool\");\n    squeethEthPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n    ethDaiPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n\n    const MockPositionManager = await ethers.getContractFactory(\"MockUniPositionManager\");\n    uniPositionManager = (await MockPositionManager.deploy()) as MockUniPositionManager;\n\n    // mint weth and squeeth to position manager\n    await weth.connect(random).deposit({value: parseEther('500')})\n    await weth.connect(random).transfer(uniPositionManager.address, parseEther('500'))\n    await squeeth.connect(random).mint(uniPositionManager.address, parseEther('500'))\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const TickMathExternal = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMathExternal.deploy());\n\n    const VaultTester = await ethers.getContractFactory(\"VaultLibTester\", {libraries: {TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n    vaultLib = (await VaultTester.deploy()) as VaultLibTester;\n\n    // set token0 and token1 for squeeth/eth pool\n    wethIsToken0InSqueethPool = parseInt(weth.address, 16) < parseInt(squeeth.address, 16)\n    if (wethIsToken0InSqueethPool) {\n      await squeethEthPool.setPoolTokens(weth.address, squeeth.address);\n    } else {\n      await squeethEthPool.setPoolTokens(squeeth.address, weth.address);\n    }\n\n    daiIsToken0InEthPool = parseInt(dai.address, 16) < parseInt(weth.address, 16)\n    if (daiIsToken0InEthPool)  {\n      await ethDaiPool.setPoolTokens(dai.address, weth.address);\n    } else {\n      await ethDaiPool.setPoolTokens(weth.address, dai.address);\n    }\n    await oracle.connect(random).setPrice(squeethEthPool.address, scaledSqueethPrice)\n\n    await oracle.connect(random).setPrice(ethDaiPool.address, ethDaiPrice)\n\n    const { tick } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0InSqueethPool)\n    await oracle.setAverageTick(squeethEthPool.address, tick)\n  });\n\n  this.beforeAll(\"Deploy Controller\", async () => {\n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n  \n    const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMath.deploy());\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n    controller = (await ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, weth.address, dai.address, ethDaiPool.address, squeethEthPool.address, uniPositionManager.address, 3000)) as Controller;\n\n    const LiqHelperFactory = await ethers.getContractFactory(\"LiquidationHelper\", {libraries: {TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n    liquidationHelper = await LiqHelperFactory.deploy(\n        controller.address,\n        oracle.address,\n        squeeth.address,\n        weth.address,\n        dai.address,\n        ethDaiPool.address,\n        squeethEthPool.address,\n        uniPositionManager.address\n      ) as LiquidationHelper;\n  })\n\n  describe(\"Vault1 and Vault2: Basic Flow\", function () {\n\n    let vaultId: BigNumber;\n    const uniNFTId = 1;\n    const mintAmount = ethers.utils.parseUnits('100')\n    const collateralAmount = ethers.utils.parseUnits('45')\n\n    let token0: string\n    let token1: string\n    \n      before(\"Open vault and mint perfect amount of squeeth\", async () => {\n        vaultId = await shortSqueeth.nextId()\n        await controller.connect(seller1).mintPowerPerpAmount(0, mintAmount, 0, {value: collateralAmount})\n        // mint uni nft for users\n        await uniPositionManager.mint(seller1.address, uniNFTId)\n        \n        // mint 2nd nft for user to test reverting\n        const nextUniNFTId = 2\n        await controller.connect(seller1).mintPowerPerpAmount(0, mintAmount, 0, {value: collateralAmount})\n        // mint uni nft for users\n        await uniPositionManager.mint(seller1.address, nextUniNFTId)\n      });\n\n      before('Prepare shared variables', async() => {\n        token0 = wethIsToken0InSqueethPool ? weth.address : squeeth.address\n        token1 = wethIsToken0InSqueethPool ? squeeth.address : weth.address\n      })\n\n      it('should revert when trying to deposit a LP token to vault 0', async() => {\n        await expect(controller.connect(seller1).depositUniPositionToken(0, 0)).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n\n      it('should revert when trying to deposit a LP token to non-existent vault', async() => {\n        await expect(controller.connect(seller1).depositUniPositionToken(100, 0)).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n\n      it('should revert when trying to deposit a LP token from a different pool', async ()=> {\n        // set token0 and token to dai and squeeth\n        await uniPositionManager.connect(seller1).approve(controller.address, uniNFTId)\n        await uniPositionManager.setMockedProperties(dai.address, squeeth.address, 0, 0, 1)\n\n        await expect(controller.connect(seller1).depositUniPositionToken(vaultId, uniNFTId)).to.be.revertedWith('C23')\n      })\n\n      it('should revert when trying to deposit a LP token with id 0', async ()=> {\n        await uniPositionManager.mint(seller1.address, 0)\n\n        // infinite price range\n        const nftTickUpper = 887220\n        const nftTickLower = -887220\n        const { sqrtPrice: sqrtX96Price, tick: currentTick } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0InSqueethPool)\n\n        // how much to stimulate as LP deposit\n        const ethLiquidityAmount = ethers.utils.parseUnits('30')\n        const squeethLiquidityAmount = ethers.utils.parseUnits('100')\n\n        // nft ticks\n        const liquidity = await vaultLib.getLiquidity(\n          sqrtX96Price,\n          nftTickLower,\n          nftTickUpper,\n          wethIsToken0InSqueethPool ? ethLiquidityAmount : squeethLiquidityAmount,\n          wethIsToken0InSqueethPool ? squeethLiquidityAmount: ethLiquidityAmount,\n        )\n        \n        await squeethEthPool.setSlot0Data(sqrtX96Price, currentTick)\n        await uniPositionManager.setMockedProperties(token0, token1, nftTickLower, nftTickUpper, liquidity)\n\n        await uniPositionManager.connect(seller1).approve(controller.address, 0)\n        await expect(controller.connect(seller1).depositUniPositionToken(vaultId, 0)).to.be.revertedWith('C23')\n      })\n\n      it('should revert when depositor do not own the NFT', async ()=> {\n        const tokenId = 77;\n        await uniPositionManager.mint(random.address, tokenId)\n\n        // infinite price range\n        const nftTickUpper = 887220\n        const nftTickLower = -887220\n        const { sqrtPrice: sqrtX96Price, tick: currentTick } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0InSqueethPool)\n\n        // how much to stimulate as LP deposit\n        const ethLiquidityAmount = ethers.utils.parseUnits('30')\n        const squeethLiquidityAmount = ethers.utils.parseUnits('100')\n\n        // nft ticks\n        const liquidity = await vaultLib.getLiquidity(\n          sqrtX96Price,\n          nftTickLower,\n          nftTickUpper,\n          wethIsToken0InSqueethPool ? ethLiquidityAmount : squeethLiquidityAmount,\n          wethIsToken0InSqueethPool ? squeethLiquidityAmount: ethLiquidityAmount,\n        )\n        \n        await squeethEthPool.setSlot0Data(sqrtX96Price, currentTick)\n        await uniPositionManager.setMockedProperties(token0, token1, nftTickLower, nftTickUpper, liquidity)\n\n        await expect(controller.connect(seller1).depositUniPositionToken(vaultId, tokenId)).to.be.revertedWith('ERC721: transfer caller is not owner nor approved')\n      })\n\n      it('should revert when a random address tries to add a NFT to a vault they are not owner or operator of', async ()=> {\n        const tokenId = 77;\n        await expect(controller.connect(random).depositUniPositionToken(vaultId, tokenId)).to.be.revertedWith('C20')\n      })\n\n      it('should revert when trying to deposit a 0 liquidity NFT', async ()=> {\n        // infinite price range\n        const nftTickUpper = 887220\n        const nftTickLower = -887220\n        const { sqrtPrice: sqrtX96Price, tick: currentTick } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0InSqueethPool)\n\n        // how much to stimulate as LP deposit\n        const ethLiquidityAmount = ethers.utils.parseUnits('0')\n        const squeethLiquidityAmount = ethers.utils.parseUnits('0')\n\n        // nft ticks\n        const liquidity = await vaultLib.getLiquidity(\n          sqrtX96Price,\n          nftTickLower,\n          nftTickUpper,\n          wethIsToken0InSqueethPool ? ethLiquidityAmount : squeethLiquidityAmount,\n          wethIsToken0InSqueethPool ? squeethLiquidityAmount: ethLiquidityAmount,\n        )\n        \n        await squeethEthPool.setSlot0Data(sqrtX96Price, currentTick)\n        await uniPositionManager.setMockedProperties(token0, token1, nftTickLower, nftTickUpper, liquidity)\n\n        // // deposit NFT\n        await uniPositionManager.connect(seller1).approve(controller.address, uniNFTId)\n\n        await expect(controller.connect(seller1).depositUniPositionToken(vaultId, uniNFTId)).to.be.revertedWith(\"C25\")\n      \n      })\n\n\n      it('should deposit and NFT to an existing vault.', async() => {\n        // infinite price range\n        const nftTickUpper = 887220\n        const nftTickLower = -887220\n        const { sqrtPrice: sqrtX96Price, tick: currentTick } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0InSqueethPool)\n\n        // how much to stimulate as LP deposit\n        const ethLiquidityAmount = ethers.utils.parseUnits('30')\n        const squeethLiquidityAmount = ethers.utils.parseUnits('100')\n\n        // nft ticks\n        const liquidity = await vaultLib.getLiquidity(\n          sqrtX96Price,\n          nftTickLower,\n          nftTickUpper,\n          wethIsToken0InSqueethPool ? ethLiquidityAmount : squeethLiquidityAmount,\n          wethIsToken0InSqueethPool ? squeethLiquidityAmount: ethLiquidityAmount,\n        )\n        \n        await squeethEthPool.setSlot0Data(sqrtX96Price, currentTick)\n        await uniPositionManager.setMockedProperties(token0, token1, nftTickLower, nftTickUpper, liquidity)\n\n        // // deposit NFT\n        await uniPositionManager.connect(seller1).approve(controller.address, uniNFTId)\n        const ownerBefore = await uniPositionManager.ownerOf(uniNFTId);\n\n        await controller.connect(seller1).depositUniPositionToken(vaultId, uniNFTId)\n        \n        const ownerAfter = await uniPositionManager.ownerOf(uniNFTId);  \n        expect(ownerBefore === seller1.address).to.be.true\n        expect(ownerAfter === controller.address).to.be.true      \n      })\n\n      it('should revert if a user tries to deposit a second nft.', async() => {\n        \n        const newUniNFTId = 2\n        \n        // infinite price range\n        const nftTickUpper = 887220\n        const nftTickLower = -887220\n        const { sqrtPrice: sqrtX96Price, tick: currentTick } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0InSqueethPool)\n\n        // how much to stimulate as LP deposit\n        const ethLiquidityAmount = ethers.utils.parseUnits('30')\n        const squeethLiquidityAmount = ethers.utils.parseUnits('100')\n\n        // nft ticks\n        const liquidity = await vaultLib.getLiquidity(\n          sqrtX96Price,\n          nftTickLower,\n          nftTickUpper,\n          wethIsToken0InSqueethPool ? ethLiquidityAmount : squeethLiquidityAmount,\n          wethIsToken0InSqueethPool ? squeethLiquidityAmount: ethLiquidityAmount,\n        )\n        \n        await squeethEthPool.setSlot0Data(sqrtX96Price, currentTick)\n        await uniPositionManager.setMockedProperties(token0, token1, nftTickLower, nftTickUpper, liquidity)\n\n        // // deposit NFT\n        await uniPositionManager.connect(seller1).approve(controller.address, newUniNFTId)\n\n        await expect(controller.connect(seller1).depositUniPositionToken(vaultId, newUniNFTId)).to.be.revertedWith(\"V1\")        \n      })\n\n      it('should revert if vault id is 0', async() => {\n        await expect(controller.connect(seller1).withdrawUniPositionToken(0)).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n\n      it('should revert if vault id is too high', async() => {\n        await expect(controller.connect(seller1).withdrawUniPositionToken(100)).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n\n      it('should revert if non owner withdraws the nft', async () => {\n        await expect(controller.connect(random).withdrawUniPositionToken(vaultId)).to.be.revertedWith(\"C20\")\n      })\n\n      it('should withdraw the nft successfully', async () => {\n        const ownerBefore = await uniPositionManager.ownerOf(uniNFTId);\n\n        await controller.connect(seller1).withdrawUniPositionToken(vaultId)\n\n        const ownerAfter = await uniPositionManager.ownerOf(uniNFTId);        \n        expect(ownerBefore === controller.address).to.be.true\n        expect(ownerAfter === seller1.address).to.be.true\n      })\n\n      it('should revert when trying to withdraw from a empty vault', async () => {\n        await expect(controller.connect(seller1).withdrawUniPositionToken(vaultId)).to.be.revertedWith('V2')\n      })\n\n      it('should deposit an NFT to an existing vault using _openDepositMint', async() => {\n\n        // // deposit NFT\n        await uniPositionManager.connect(seller1).approve(controller.address, uniNFTId)\n        const ownerBefore = await uniPositionManager.ownerOf(uniNFTId);\n\n        await controller.connect(seller1).mintPowerPerpAmount(0, mintAmount, uniNFTId)\n        \n        const ownerAfter = await uniPositionManager.ownerOf(uniNFTId);  \n        expect(ownerBefore === seller1.address).to.be.true\n        expect(ownerAfter === controller.address).to.be.true      \n      })\n\n  })\n\n  describe('Vault3: Basic Collateralization checks', async() => {\n    let vaultId: BigNumber;\n    const uniNFTId = 3;\n    const mintAmount = ethers.utils.parseUnits('100')\n    const collateralAmount = ethers.utils.parseUnits('45')\n\n    let token0: string\n    let token1: string\n\n    describe('Case: price is at the same', async () => {\n      let currentTick: string;\n      before(\"open vault and mint perfect amount of squeeth\", async () => {\n        vaultId = await shortSqueeth.nextId()\n        await controller.connect(seller1).mintPowerPerpAmount(0, mintAmount,0, {value: collateralAmount})\n        await uniPositionManager.mint(seller1.address, uniNFTId)\n      });\n  \n      before('prepare shared variables', async() => {\n        token0 = wethIsToken0InSqueethPool ? weth.address : squeeth.address\n        token1 = wethIsToken0InSqueethPool ? squeeth.address : weth.address\n      })\n  \n      before('deposit NFT into the vault', async() => {\n        await uniPositionManager.connect(seller1).approve(controller.address, uniNFTId)\n        await controller.connect(seller1).depositUniPositionToken(vaultId, uniNFTId)\n      })\n\n      before('set LP token properties', async() => {\n        \n        const { sqrtPrice: sqrtX96Price, tick } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0InSqueethPool)\n        currentTick = tick\n\n        // how much to stimulate as LP deposit\n        const ethLiquidityAmount = ethers.utils.parseUnits('30')\n        const squeethLiquidityAmount = ethers.utils.parseUnits('100')\n\n        // infinite price range\n        const nftTickUpper = 887220\n        const nftTickLower = -887220\n\n        // nft ticks\n        const liquidity = await vaultLib.getLiquidity(\n          sqrtX96Price,\n          nftTickLower,\n          nftTickUpper,\n          wethIsToken0InSqueethPool ? ethLiquidityAmount : squeethLiquidityAmount,\n          wethIsToken0InSqueethPool ? squeethLiquidityAmount: ethLiquidityAmount,\n        )\n        \n        await squeethEthPool.setSlot0Data(sqrtX96Price, currentTick)\n        await uniPositionManager.setMockedProperties(token0, token1, nftTickLower, nftTickUpper, liquidity)\n      })\n\n      it('should be able to mint more squeeth after lp deposit', async() => {\n\n        const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, uniNFTId, currentTick, wethIsToken0InSqueethPool)\n        const equivalentCollateral = ethAmount.add(wPowerPerpAmount.mul(ethDaiPrice))\n        const vaultBefore = await controller.vaults(vaultId)\n        \n        const squeethToMint = equivalentCollateral.div(ethDaiPrice).mul(2).div(3)\n        \n        await controller.connect(seller1).mintPowerPerpAmount(vaultId, squeethToMint, 0)\n        const vaultAfter = await controller.vaults(vaultId)\n        \n        // burn the minted amount \n        const wSqueethMinted = vaultAfter.shortAmount.sub(vaultBefore.shortAmount)\n        await controller.connect(seller1).burnWPowerPerpAmount(vaultId, wSqueethMinted, 0)\n      })\n  \n      it('should be able to remove all collateral after lp token deposit, because the lp token is worth 2x the debt amount.', async() => {\n        await controller.connect(seller1).withdraw(vaultId, collateralAmount)\n        const vaultAfter = await controller.vaults(vaultId)\n        expect(vaultAfter.NftCollateralId === uniNFTId).to.be.true\n        expect(vaultAfter.collateralAmount.isZero()).to.be.true\n      })\n  \n      it('should revert if trying to remove LP token from the vault.', async() => {\n        await expect(controller.connect(seller1).withdrawUniPositionToken(vaultId)).to.be.revertedWith('C24')\n      })\n\n      it('update nft property to stimulate losses in Uni LP', async() => {\n        const { sqrtPrice: sqrtX96Price } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0InSqueethPool)\n        // how much to stimulate as LP deposit\n        const ethLiquidityAmount = ethers.utils.parseUnits('0.3')\n        const squeethLiquidityAmount = ethers.utils.parseUnits('1')\n        const nftTickUpper = 887220\n        const nftTickLower = -887220\n        const liquidity = await vaultLib.getLiquidity(\n          sqrtX96Price,\n          nftTickLower,\n          nftTickUpper,\n          wethIsToken0InSqueethPool ? ethLiquidityAmount : squeethLiquidityAmount,\n          wethIsToken0InSqueethPool ? squeethLiquidityAmount: ethLiquidityAmount,\n        )\n        \n        await squeethEthPool.setSlot0Data(sqrtX96Price, currentTick)\n        await uniPositionManager.setMockedProperties(token0, token1, nftTickLower, nftTickUpper, liquidity)\n      })\n\n      it('should revert when effective collateral after withdraw < dust limit', async() => {\n        it('should revert if trying to remove LP token from the vault.', async() => {\n          const vault = await controller.vaults(vaultId)\n          await expect(controller.connect(seller1).withdraw(vaultId, vault.collateralAmount)).to.be.revertedWith('C22')\n        })\n      })\n\n      // only got NFT left in the vault\n    })\n    describe('Case: price increase, vault should go underwater', async() => {\n      let newTick: string;\n      let newSqueethPrice: BigNumber\n      before(\"assume we start LPing when price was 3000. with range 2000 - 4000\", async () => {\n        // the let's assume price range is only 2000 -> 4000, so if squeeth price > 4000\n        // we will only have eth left in LP token.\n        // old price was 3000\n        \n        const { sqrtPrice: oldSqrtPrice } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0InSqueethPool)\n\n        // fix deposit eth amount at 30\n\n        const ethLiquidityAmount = ethers.utils.parseUnits('30')\n        const scaledPrice4000 = BigNumber.from('4000').mul(one).div(oracleScaleFactor)\n        const scaledPrice2000 = BigNumber.from('2000').mul(one).div(oracleScaleFactor)\n\n        const { tick: tick4000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice4000, wethIsToken0InSqueethPool)\n        const { sqrtPrice: sqrtPrice2000, tick: tick2000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice2000, wethIsToken0InSqueethPool)\n\n        // get approximate liquidity value, with 30 eth deposit\n        const liquidity = wethIsToken0InSqueethPool\n          ? await vaultLib.getLiquidityForAmount0(oldSqrtPrice, sqrtPrice2000, ethLiquidityAmount.toString())\n          : await vaultLib.getLiquidityForAmount1(oldSqrtPrice, sqrtPrice2000, ethLiquidityAmount.toString())\n        \n        const tickUpper = wethIsToken0InSqueethPool ? tick2000 : tick4000;\n        const tickLower = wethIsToken0InSqueethPool ? tick4000 : tick2000;\n\n        await uniPositionManager.setMockedProperties(token0, token1, tickLower, tickUpper, liquidity) // use the same liquidity\n      })\n      before('set price to 4500', async() => {\n        const ethPrice = BigNumber.from('4500').mul(one)\n        newSqueethPrice = ethPrice.div(oracleScaleFactor)\n        const { tick, sqrtPrice: newSqrtPrice } = getSqrtPriceAndTickBySqueethPrice(newSqueethPrice, wethIsToken0InSqueethPool)\n        // update prices in pool and oracle.\n        newTick = tick\n        await squeethEthPool.setSlot0Data(newSqrtPrice, newTick)\n        await oracle.setPrice(squeethEthPool.address, newSqueethPrice)\n        await oracle.setAverageTick(squeethEthPool.address, newTick)\n\n        \n        await oracle.setPrice(ethDaiPool.address, ethPrice)\n      })\n      it('should become underwater if squeeth price increase, and LP token has no enough eth to cover short position.', async () => {\n        const result = await vaultLib.getUniPositionBalances(uniPositionManager.address, uniNFTId, newTick, wethIsToken0InSqueethPool)\n        // LP token worth 0 squeeth\n        expect(result.wPowerPerpAmount.isZero()).to.be.true\n        // not enough eth value in LP token!\n        const requiredCollateral = mintAmount.mul(newSqueethPrice).mul(3).div(2)\n        expect(result.ethAmount.lt(requiredCollateral)).to.be.true\n        \n        await expect(controller.connect(seller1).withdraw(vaultId, 0)).to.be.revertedWith('C24')\n      })\n      it('should be able to liquidate the NFT', async() => {\n        const vaultBefore = await controller.vaults(vaultId)\n        const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, uniNFTId, newTick, wethIsToken0InSqueethPool)\n        \n        // mint squeeth for liquidator\n        const liquidationAmount = vaultBefore.shortAmount.sub(wPowerPerpAmount).div(2)\n        const ethCollateral = liquidationAmount.mul(newSqueethPrice).div(one).mul(2) // with 2 collateral ratio\n        await controller.connect(liquidator).mintPowerPerpAmount(0, liquidationAmount, 0, {value: ethCollateral})\n\n        expect(vaultBefore.NftCollateralId === 0).to.be.false\n\n        const token0ToSet = wethIsToken0InSqueethPool ? ethAmount : wPowerPerpAmount\n        const token1ToSet = wethIsToken0InSqueethPool ? wPowerPerpAmount : ethAmount\n        await uniPositionManager.setAmount0Amount1ToDecrease(token0ToSet, token1ToSet)\n\n        const balanceBefore = await provider.getBalance(liquidator.address)\n\n        // liquidate the vault\n        const tx = await controller.connect(liquidator).liquidate(vaultId, liquidationAmount)\n        const vaultAfter = await controller.vaults(vaultId)\n        const balanceAfter = await provider.getBalance(liquidator.address)\n        \n        const reward = liquidationAmount.mul(newSqueethPrice).div(one).mul(11).div(10)\n        \n        // expect(balanceAfter.sub(balanceBefore).eq(reward)).to.be.true\n        expect(vaultAfter.NftCollateralId === 0).to.be.true // nft is liquidated\n        expect(vaultAfter.shortAmount.eq(vaultBefore.shortAmount.sub(liquidationAmount))).to.be.true\n        expect(vaultAfter.collateralAmount.eq(vaultBefore.collateralAmount.add(ethAmount).sub(reward))).to.be.true\n      })\n    })\n    describe('Case: price decrease, vault should above water', async() => {\n      let newTick:string\n      before('set price to 1500', async() => {\n        const ethPrice = BigNumber.from('1500').mul(one)\n        const newScaledSqueethPrice = ethPrice.div(oracleScaleFactor)\n        const { tick, sqrtPrice: newSqrtPrice } = getSqrtPriceAndTickBySqueethPrice(newScaledSqueethPrice, wethIsToken0InSqueethPool)\n        newTick = tick \n        // update prices in pool and oracle.\n        await squeethEthPool.setSlot0Data(newSqrtPrice, newTick)\n        await oracle.setPrice(squeethEthPool.address , newScaledSqueethPrice)\n        await oracle.setAverageTick(squeethEthPool.address, newTick)\n\n        await oracle.setPrice(ethDaiPool.address , ethPrice)\n      })\n      it('should be able to collateralize the vault', async () => {\n\n        const result = await vaultLib.getUniPositionBalances(uniPositionManager.address, uniNFTId, newTick, wethIsToken0InSqueethPool)\n\n        const token0ToSet = wethIsToken0InSqueethPool ? result.ethAmount : result.wPowerPerpAmount\n        const token1ToSet = wethIsToken0InSqueethPool ? result.wPowerPerpAmount : result.ethAmount\n        await uniPositionManager.setAmount0Amount1ToDecrease(token0ToSet, token1ToSet)\n\n        // LP token worth 0 eth\n        expect(result.ethAmount.isZero()).to.be.true\n        expect(result.wPowerPerpAmount.gt(mintAmount)).to.be.true\n        \n        const vaultBefore = await controller.vaults(vaultId)\n        await controller.connect(seller1).mintPowerPerpAmount(vaultId, 10, 0)\n        const vaultAfter = await controller.vaults(vaultId)\n        expect(vaultAfter.shortAmount.gt(vaultBefore.shortAmount)).to.be.true\n      })\n      it('should revert when trying to liquidate the NFT', async() => {\n        const liquidationAmount = ethers.utils.parseUnits('50')\n        await expect(controller.connect(liquidator).liquidate(vaultId, liquidationAmount)).to.be.revertedWith(\n          'C12'\n        )\n      })\n    })\n  });\n\n  describe('Vault4: Saving vault by burning NFT', async() => {\n    // We use the exact setup as Vault2:\n    // open vault => mint squeeth => add uni NFT => withdraw all collateral from the vault\n    // so the price scenario should be identical, we're just testing saving vaults here.\n    let vaultId: BigNumber;\n    const uniNFTId = 4;\n    const mintAmount = ethers.utils.parseUnits('100')\n    const collateralAmount = ethers.utils.parseUnits('45')\n\n    let token0: string\n    let token1: string\n    \n    describe('Case: price is at the same', async () => {\n\n      let currentTick: string;\n\n      before('set price back to 3000', async() => {\n        const { tick, sqrtPrice: newSqrtPrice } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice.toString(), wethIsToken0InSqueethPool)\n        const newTick = tick \n        // update prices in pool and oracle.\n        await squeethEthPool.setSlot0Data(newSqrtPrice, newTick)\n        await oracle.setPrice(squeethEthPool.address , scaledSqueethPrice)\n\n        await oracle.setPrice(ethDaiPool.address , ethDaiPrice)\n        await oracle.setAverageTick(squeethEthPool.address, newTick)\n      })\n      \n      before(\"open vault and mint perfect amount of squeeth\", async () => {\n        vaultId = await shortSqueeth.nextId()\n        await controller.connect(seller1).mintPowerPerpAmount(0, mintAmount,0, {value: collateralAmount})\n        await uniPositionManager.mint(seller1.address, uniNFTId)\n      });\n  \n      before('prepare shared variables', async() => {\n        token0 = wethIsToken0InSqueethPool ? weth.address : squeeth.address\n        token1 = wethIsToken0InSqueethPool ? squeeth.address : weth.address\n      })\n  \n      before('deposit NFT into the vault', async() => {\n        await uniPositionManager.connect(seller1).approve(controller.address, uniNFTId)\n        await controller.connect(seller1).depositUniPositionToken(vaultId, uniNFTId)\n      })\n\n      before('set LP token properties', async() => {\n        const { sqrtPrice: sqrtX96Price, tick } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0InSqueethPool)\n        currentTick = tick\n\n        // how much to stimulate as LP deposit\n        const ethLiquidityAmount = ethers.utils.parseUnits('30')\n        const squeethLiquidityAmount = ethers.utils.parseUnits('100')\n\n        // infinite price range\n        const nftTickUpper = 887220\n        const nftTickLower = -887220\n\n        // nft ticks\n        const liquidity = await vaultLib.getLiquidity(\n          sqrtX96Price,\n          nftTickLower,\n          nftTickUpper,\n          wethIsToken0InSqueethPool ? ethLiquidityAmount : squeethLiquidityAmount,\n          wethIsToken0InSqueethPool ? squeethLiquidityAmount: ethLiquidityAmount,\n        )\n        \n        await squeethEthPool.setSlot0Data(sqrtX96Price, currentTick)\n        await uniPositionManager.setMockedProperties(token0, token1, nftTickLower, nftTickUpper, liquidity)\n      })\n\n      it('should be able to remove all collateral after lp token deposit, because the lp token is worth 2x the debt amount.', async() => {\n        await controller.connect(seller1).withdraw(vaultId, collateralAmount)\n        const vaultAfter = await controller.vaults(vaultId)\n        expect(vaultAfter.NftCollateralId === uniNFTId).to.be.true\n        expect(vaultAfter.collateralAmount.isZero()).to.be.true\n        // only got NFT left in the vault\n      })\n  \n      it('should revert when calling from random address', async() => {\n        await expect(controller.connect(random).reduceDebt(vaultId)).to.be.revertedWith('C20')\n      })\n    })\n    describe('Case: price increase, vault should go underwater and people can save it', async() => {\n      let newTick: string;\n      let newSqueethPrice: BigNumber\n      before(\"assume we start LPing when price was 3000. with range 2000 - 4000\", async () => {\n        // the let's assume price range is only 2000 -> 4000, so if squeeth price > 4000\n        // we will only have eth left in LP token.\n        // old price was 3000\n        const { sqrtPrice: oldSqrtPrice } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0InSqueethPool)\n        \n        const scaledPrice4000 = BigNumber.from('4000').mul(one).div(oracleScaleFactor).toString()\n        const scaledPrice2000 = BigNumber.from('2000').mul(one).div(oracleScaleFactor).toString()\n\n        // fix deposit eth amount at 30\n        const ethLiquidityAmount = ethers.utils.parseUnits('30')\n\n        const { tick: tick4000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice4000, wethIsToken0InSqueethPool)\n        const { sqrtPrice: sqrtPrice2000, tick: tick2000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice2000, wethIsToken0InSqueethPool)\n\n        // get approximate liquidity value, with 30 eth deposit\n        const liquidity = wethIsToken0InSqueethPool\n          ? await vaultLib.getLiquidityForAmount0(oldSqrtPrice, sqrtPrice2000, ethLiquidityAmount.toString())\n          : await vaultLib.getLiquidityForAmount1(oldSqrtPrice, sqrtPrice2000, ethLiquidityAmount.toString())\n        \n        const tickUpper = wethIsToken0InSqueethPool ? tick2000 : tick4000;\n        const tickLower = wethIsToken0InSqueethPool ? tick4000 : tick2000;\n\n        await uniPositionManager.setMockedProperties(token0, token1, tickLower, tickUpper, liquidity) // use the same liquidity\n      })\n      before('set price to 5000', async() => {\n        newSqueethPrice = BigNumber.from('5000').mul(one)     \n        const newScaledSqueethPrice = newSqueethPrice.div(oracleScaleFactor)\n\n        const { tick, sqrtPrice: newSqrtPrice } = getSqrtPriceAndTickBySqueethPrice(newScaledSqueethPrice, wethIsToken0InSqueethPool)\n        // update prices in pool and oracle.\n        newTick = tick\n        await squeethEthPool.setSlot0Data(newSqrtPrice, newTick)\n        await oracle.setPrice(squeethEthPool.address, newScaledSqueethPrice.mul(one))\n        await oracle.setAverageTick(squeethEthPool.address, newTick)\n\n        // set eth dai pool price to 5000\n        await oracle.setPrice(ethDaiPool.address, newSqueethPrice)\n      })\n      it('should become underwater if squeeth price increase, and LP token has no enough eth', async () => {\n        const result = await vaultLib.getUniPositionBalances(uniPositionManager.address, uniNFTId, newTick, wethIsToken0InSqueethPool)\n        // LP token worth 0 squeeth\n        expect(result.wPowerPerpAmount.isZero()).to.be.true\n        // not enough eth value in LP token!\n        const requiredCollateral = mintAmount.mul(newSqueethPrice).mul(3).div(2)\n        expect(result.ethAmount.lt(requiredCollateral)).to.be.true\n        \n        await expect(controller.connect(seller1).withdraw(vaultId, 0)).to.be.revertedWith('C24')\n      })\n      before('set NFT redemption amount', async () => {\n        const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, uniNFTId, newTick, wethIsToken0InSqueethPool)\n        const token0ToSet = wethIsToken0InSqueethPool ? ethAmount : wPowerPerpAmount\n        const token1ToSet = wethIsToken0InSqueethPool ? wPowerPerpAmount : ethAmount\n        await uniPositionManager.setAmount0Amount1ToDecrease(token0ToSet, token1ToSet)\n      })\n      it('should be able to reduce the debt by calling liquidate', async() => {\n        const vaultBefore = await controller.vaults(vaultId)\n        const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, uniNFTId, newTick, wethIsToken0InSqueethPool)\n        // save the vault\n        await controller.connect(seller1).liquidate(vaultId, 0)\n        \n        const vaultAfter = await controller.vaults(vaultId)\n        expect(vaultAfter.NftCollateralId === 0).to.be.true // nft is redeemed\n        expect(vaultAfter.shortAmount.eq(vaultBefore.shortAmount.sub(wPowerPerpAmount))).to.be.true\n        expect(vaultAfter.collateralAmount.eq(vaultBefore.collateralAmount.add(ethAmount))).to.be.true\n      })\n    })\n    \n    describe('Case: the nft worth more wsqueeth than minted', async() => {\n      /**\n       * Scenario: the vault is safe when price is 4500\n       * Deposit NFT: range order\n       * \n       */\n      const oldEthPrice = BigNumber.from('5000').mul(one).div(oracleScaleFactor)\n      let newTick: string\n      const newNFTId = 5\n\n      before('set LP token properties: range order [10000 - 15000]', async() => {\n        const vault = await controller.vaults(vaultId)\n\n        // assume there's a NFT has wSqueethAmount value of 110% * shortAmount\n        const wsqueethLiquidityAmount = vault.shortAmount.mul(11).div(10);\n\n        const scaledSqueethPrice10000 = BigNumber.from('10000').mul(one).div(oracleScaleFactor)\n        const scaledSqueethPrice15000 = BigNumber.from('15000').mul(one).div(oracleScaleFactor)\n\n        const { sqrtPrice: sqrtPrice10000, tick: tick10000 } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice10000, wethIsToken0InSqueethPool)\n        const { sqrtPrice: sqrtPrice1500, tick: tick15000 } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice15000, wethIsToken0InSqueethPool)\n\n        // get approximate liquidity value, with fixed wsqueeth amount\n        const liquidity = wethIsToken0InSqueethPool\n          ? await vaultLib.getLiquidityForAmount1(sqrtPrice1500, sqrtPrice10000, wsqueethLiquidityAmount.toString())\n          : await vaultLib.getLiquidityForAmount0(sqrtPrice1500, sqrtPrice10000, wsqueethLiquidityAmount.toString())\n        \n        const tickUpper = wethIsToken0InSqueethPool ? tick10000 : tick15000;\n        const tickLower = wethIsToken0InSqueethPool ? tick15000 : tick10000;\n\n        await uniPositionManager.setMockedProperties(token0, token1, tickLower, tickUpper, liquidity) // use the same liquidity\n      })\n\n      before('deposit NFT into the vault, withdraw some collateral', async() => {\n        await uniPositionManager.mint(seller1.address, newNFTId)\n        await uniPositionManager.connect(seller1).approve(controller.address, newNFTId)\n        await controller.connect(seller1).depositUniPositionToken(vaultId, newNFTId)\n\n        const vault = await controller.vaults(vaultId)\n        const totalCollateralRequired = vault.shortAmount.mul(oldEthPrice).div(one).mul(3).div(2)\n\n        // nft is equivalent as 110% short amount * index\n        const nftEquivalentEthValue = vault.shortAmount.mul(11).div(10).mul(oldEthPrice).div(one)\n\n        const minEthRequired = totalCollateralRequired.sub(nftEquivalentEthValue)\n        const maxWithdrawableEth = vault.collateralAmount.sub(minEthRequired)\n\n        await controller.connect(seller1).withdraw(vaultId, maxWithdrawableEth)\n      })\n\n      before('set price to 8000', async() => {\n        const newSqueethPrice = BigNumber.from('8000').mul(one)\n        \n        const scaledNewSqueethPrice = newSqueethPrice.div(oracleScaleFactor)\n        const { tick, sqrtPrice: newSqrtPrice } = getSqrtPriceAndTickBySqueethPrice(scaledNewSqueethPrice, wethIsToken0InSqueethPool)\n        // update prices in pool and oracle.\n        newTick = tick\n        await squeethEthPool.setSlot0Data(newSqrtPrice, newTick)\n        await oracle.setPrice(squeethEthPool.address, scaledNewSqueethPrice)\n        await oracle.setAverageTick(squeethEthPool.address, newTick)\n\n        // set eth price to 8000\n        await oracle.setPrice(ethDaiPool.address, newSqueethPrice)\n      })\n\n      before('set NFT redemption amount', async () => {\n        const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, uniNFTId, newTick, wethIsToken0InSqueethPool)\n        const token0ToSet = wethIsToken0InSqueethPool ? ethAmount : wPowerPerpAmount\n        const token1ToSet = wethIsToken0InSqueethPool ? wPowerPerpAmount : ethAmount\n        await uniPositionManager.setAmount0Amount1ToDecrease(token0ToSet, token1ToSet)\n      })\n\n      it('anyone can safe the vault, the owner will receive extra wsqueeth withdrawn from Uniswap', async() => {\n        // the vault should be underwater now\n        \n        await expect(controller.connect(seller1).mintPowerPerpAmount(vaultId, 1, 0)).to.be.revertedWith('C24')\n        const vaultBefore = await controller.vaults(vaultId)\n        const { wPowerPerpAmount: nftSqueethAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, newNFTId, newTick, wethIsToken0InSqueethPool)\n\n        const ownerWSqueethBefore = await squeeth.balanceOf(seller1.address)\n\n        const result = await liquidationHelper.checkLiquidation(vaultId);\n        const isUnsafe = result[0]\n        const isLiquidatableAfterReducingDebt = result[1]\n        const maxWPowerPerpAmount = result[2]  \n\n        await controller.connect(seller1).reduceDebt(vaultId)\n        const vaultAfter = await controller.vaults(vaultId)\n\n        const ownerWSqueethAfter = await squeeth.balanceOf(seller1.address)\n\n        const wsqueethExcess = nftSqueethAmount.sub(vaultBefore.shortAmount)\n\n        expect(isUnsafe).to.be.true\n        expect(isLiquidatableAfterReducingDebt).to.be.false\n        expect(maxWPowerPerpAmount.eq(BigNumber.from(0))).to.be.true\n\n        expect(ownerWSqueethAfter.sub(ownerWSqueethBefore).eq(wsqueethExcess)).to.be.true\n        expect(vaultAfter.NftCollateralId === 0).to.be.true\n        expect(vaultAfter.shortAmount.isZero()).to.be.true\n      })\n      it('calling reduceDebt will not take effect if the vault has not nft', async() => {\n        \n        const vaultBefore = await controller.vaults(vaultId)\n        await controller.connect(seller1).reduceDebt(vaultId)\n        const vaultAfter = await controller.vaults(vaultId)\n\n        expect(vaultAfter.collateralAmount.eq(vaultBefore.collateralAmount)).to.be.true\n        expect(vaultAfter.shortAmount.eq(vaultBefore.shortAmount)).to.be.true\n      })\n    })\n  });\n\n  describe('Vault5: test combined actions', async() => {\n    let vaultId: BigNumber;\n    const uniNFTId = 99;\n\n    const testDepositAmount = ethers.utils.parseUnits('10')\n\n    before('prepare vault and nft for user', async() => {\n      vaultId = await shortSqueeth.nextId()\n      await controller.connect(seller1).mintPowerPerpAmount(0, 0, 0, {value: testDepositAmount})\n\n      await uniPositionManager.mint(seller1.address, uniNFTId)\n      await uniPositionManager.connect(seller1).approve(controller.address, uniNFTId)\n    })\n\n    it('should just deposit lp token and mint if deposit amount is 0', async() => {\n      const testMintWAmount = ethers.utils.parseUnits('0.001')\n      const vaultBefore = await controller.vaults(vaultId)\n      await controller.connect(seller1).mintWPowerPerpAmount(vaultId, testMintWAmount, uniNFTId)\n      const vaultAfter = await controller.vaults(vaultId)\n\n      expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).isZero()).to.be.true\n      expect(vaultAfter.shortAmount.sub(vaultBefore.shortAmount).eq(testMintWAmount)).to.be.true\n      expect(vaultAfter.NftCollateralId === uniNFTId).to.be.true\n\n      // withdraw nft\n      await controller.connect(seller1).withdrawUniPositionToken(vaultId)\n    })\n\n    it('should just deposit lp token and deposit eth if mint amount is 0', async() => {\n      const vaultBefore = await controller.vaults(vaultId)\n      await uniPositionManager.connect(seller1).approve(controller.address, uniNFTId)        \n      await controller.connect(seller1).mintWPowerPerpAmount(vaultId, 0, uniNFTId, {value: testDepositAmount})\n      const vaultAfter = await controller.vaults(vaultId)\n\n      expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).eq(testDepositAmount)).to.be.true\n      expect(vaultAfter.shortAmount.sub(vaultBefore.shortAmount).isZero()).to.be.true\n      expect(vaultAfter.NftCollateralId === uniNFTId).to.be.true\n\n      await controller.connect(seller1).withdrawUniPositionToken(vaultId)\n    })\n    it('should do nothing but deposit uni nft if both deposit and mint amount are 0', async() => {\n      const vaultBefore = await controller.vaults(vaultId)\n      await uniPositionManager.connect(seller1).approve(controller.address, uniNFTId)     \n      await controller.connect(seller1).mintWPowerPerpAmount(vaultId, 0, uniNFTId)\n      const vaultAfter = await controller.vaults(vaultId)\n\n      expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).isZero()).to.be.true\n      expect(vaultAfter.shortAmount.sub(vaultBefore.shortAmount).isZero()).to.be.true\n      expect(vaultAfter.NftCollateralId === uniNFTId).to.be.true\n\n      await controller.connect(seller1).withdrawUniPositionToken(vaultId)\n    })\n  })\n});\n"
  },
  {
    "path": "packages/hardhat/test/unit-tests/controller-pause-time.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport {providers } from \"ethers\";\nimport { Controller, MockWPowerPerp, MockShortPowerPerp, MockOracle, MockUniswapV3Pool, MockErc20, MockUniPositionManager, WETH9, ABDKMath64x64 } from '../../typechain'\nimport { oracleScaleFactor } from \"../utils\";\n\nconst squeethETHPrice = ethers.utils.parseUnits('3010')\nconst ethUSDPrice = ethers.utils.parseUnits('3000')\n\n\ndescribe(\"Controller\", function () {\n  let squeeth: MockWPowerPerp;\n  let shortSqueeth: MockShortPowerPerp;\n  let controller: Controller;\n  let squeethEthPool: MockUniswapV3Pool;\n  let ethUSDPool: MockUniswapV3Pool;\n  let uniPositionManager: MockUniPositionManager\n  let oracle: MockOracle;\n  let weth: WETH9;\n  let usdc: MockErc20;\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress\n  let random: SignerWithAddress\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _random] = accounts;\n    random = _random\n    owner = _owner\n    provider = ethers.provider\n  })\n\n  this.beforeAll(\"Setup environment\", async () => {\n    const MockSQUContract = await ethers.getContractFactory(\"MockWPowerPerp\");\n    squeeth = (await MockSQUContract.deploy()) as MockWPowerPerp;\n\n    const NFTContract = await ethers.getContractFactory(\"MockShortPowerPerp\");\n    shortSqueeth = (await NFTContract.deploy()) as MockShortPowerPerp;\n\n    const OracleContract = await ethers.getContractFactory(\"MockOracle\");\n    oracle = (await OracleContract.deploy()) as MockOracle;\n\n    const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n    usdc = (await MockErc20Contract.deploy(\"USDC\", \"USDC\", 6)) as MockErc20;\n\n    const WETHContract = await ethers.getContractFactory(\"WETH9\");\n    weth = (await WETHContract.deploy()) as WETH9;\n\n    const MockUniswapV3PoolContract = await ethers.getContractFactory(\"MockUniswapV3Pool\");\n    squeethEthPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n    ethUSDPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n\n    const MockPositionManager = await ethers.getContractFactory(\"MockUniPositionManager\");\n    uniPositionManager = (await MockPositionManager.deploy()) as MockUniPositionManager;\n\n    await squeethEthPool.setPoolTokens(weth.address, squeeth.address);\n    await ethUSDPool.setPoolTokens(weth.address, usdc.address);\n\n    await oracle.connect(random).setPrice(squeethEthPool.address , squeethETHPrice) // eth per 1 squeeth\n    await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPrice)  // usdc per 1 eth\n    \n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n  \n    const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMath.deploy());\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n  controller = (await ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, weth.address, usdc.address, ethUSDPool.address, squeethEthPool.address, uniPositionManager.address, 3000)) as Controller;\n  });\n  \n  describe(\"Time bound pausing\", function () {\n    const settlementPrice = '6500';\n\n    describe(\"Pause the system\", async () => {\n      let pausesLeft = 4;\n      it(\"Should allow owner to pause the system\", async () => {\n        await controller.connect(owner).pause()\n        pausesLeft-=1;\n        expect(await controller.isSystemPaused()).to.be.true;\n        expect((await controller.pausesLeft()).eq(pausesLeft)).to.be.true \n\n        // how to ensure that all variables are updated ie lastPauseTime, need block.timestamp here\n      });\n      it(\"Should allow the owner to un-pause\", async () => {\n        await controller.connect(owner).unPauseOwner()\n        expect(await controller.isSystemPaused()).to.be.false \n        expect((await controller.pausesLeft()).eq(pausesLeft)).to.be.true \n\n      });\n      it(\"Should revert when the owner tries to re-pause after 183 days\", async () => {\n        await provider.send(\"evm_increaseTime\", [86400*183])\n        await provider.send(\"evm_mine\", [])\n        await expect(\n          controller.connect(owner).pause()\n        ).to.be.revertedWith(\"C17\");\n      });\n\n    });  \n    describe(\"Shut down the system\", async () => {\n      it(\"Should allow the system to be shutdown and paused atomically even after 183 days\", async () => {\n        const ethPrice = ethers.utils.parseUnits(settlementPrice)\n        await oracle.connect(random).setPrice(ethUSDPool.address , ethPrice) // eth per 1 squeeth\n        await controller.connect(owner).shutDown()\n        const snapshot = await controller.indexForSettlement();\n        expect(snapshot.toString()).to.be.eq(ethPrice.div(oracleScaleFactor))\n        expect(await controller.isShutDown()).to.be.true;\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/hardhat/test/unit-tests/controller-shutdown.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { Controller, MockWPowerPerp, MockShortPowerPerp, MockOracle, MockUniswapV3Pool, MockErc20, MockUniPositionManager, WETH9, ABDKMath64x64 } from '../../typechain'\nimport { oracleScaleFactor } from \"../utils\";\n\nconst squeethETHPrice = ethers.utils.parseUnits('3010')\nconst ethUSDPrice = ethers.utils.parseUnits('3000')\n\n\ndescribe(\"Controller\", function () {\n  let squeeth: MockWPowerPerp;\n  let shortSqueeth: MockShortPowerPerp;\n  let controller: Controller;\n  let squeethEthPool: MockUniswapV3Pool;\n  let ethUSDPool: MockUniswapV3Pool;\n  let uniPositionManager: MockUniPositionManager\n  let oracle: MockOracle;\n  let weth: WETH9;\n  let usdc: MockErc20;\n  let owner: SignerWithAddress\n  let random: SignerWithAddress\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _random] = accounts;\n    random = _random\n    owner = _owner\n  })\n\n  this.beforeAll(\"Setup environment\", async () => {\n    const MockSQUContract = await ethers.getContractFactory(\"MockWPowerPerp\");\n    squeeth = (await MockSQUContract.deploy()) as MockWPowerPerp;\n\n    const NFTContract = await ethers.getContractFactory(\"MockShortPowerPerp\");\n    shortSqueeth = (await NFTContract.deploy()) as MockShortPowerPerp;\n\n    const OracleContract = await ethers.getContractFactory(\"MockOracle\");\n    oracle = (await OracleContract.deploy()) as MockOracle;\n\n    const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n    usdc = (await MockErc20Contract.deploy(\"USDC\", \"USDC\", 6)) as MockErc20;\n\n    const WETHContract = await ethers.getContractFactory(\"WETH9\");\n    weth = (await WETHContract.deploy()) as WETH9;\n\n    const MockUniswapV3PoolContract = await ethers.getContractFactory(\"MockUniswapV3Pool\");\n    squeethEthPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n    ethUSDPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n\n    const MockPositionManager = await ethers.getContractFactory(\"MockUniPositionManager\");\n    uniPositionManager = (await MockPositionManager.deploy()) as MockUniPositionManager;\n\n    await squeethEthPool.setPoolTokens(weth.address, squeeth.address);\n    await ethUSDPool.setPoolTokens(weth.address, usdc.address);\n\n    await oracle.connect(random).setPrice(squeethEthPool.address , squeethETHPrice) // eth per 1 squeeth\n    await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPrice)  // usdc per 1 eth\n    \n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n  \n    const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMath.deploy());\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n  controller = (await ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, weth.address, usdc.address, ethUSDPool.address, squeethEthPool.address, uniPositionManager.address, 3000)) as Controller;\n  });\n  \n  describe(\"Time bound pausing\", function () {\n    const settlementPrice = '6500';\n\n    describe(\"Pause the system and then shutdown\", async () => {\n      it(\"Should allow owner to pause the system\", async () => {\n        await controller.connect(owner).pause()\n        expect(await controller.isSystemPaused()).to.be.true;\n      });\n      it(\"Should allow the system to be shutdown when paused\", async () => {\n        const isPausedBefore = await controller.isSystemPaused();\n        const ethPrice = ethers.utils.parseUnits(settlementPrice)\n        expect(await controller.isSystemPaused()).to.be.true\n        await oracle.connect(random).setPrice(ethUSDPool.address , ethPrice) // eth per 1 squeeth\n        await controller.connect(owner).shutDown()\n        const snapshot = await controller.indexForSettlement();\n        expect(snapshot.toString()).to.be.eq(ethPrice.div(oracleScaleFactor))\n        expect(isPausedBefore).to.be.true\n        expect(await controller.isSystemPaused()).to.be.true\n        expect(await controller.isShutDown()).to.be.true;\n      });\n    });\n  });\n});"
  },
  {
    "path": "packages/hardhat/test/unit-tests/controller-vaults.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { BigNumber, providers } from \"ethers\";\nimport { one, oracleScaleFactor } from \"../utils\";\nimport { Controller, MockWPowerPerp, MockShortPowerPerp, MockOracle, MockUniswapV3Pool, MockErc20, MockUniPositionManager, VaultLibTester, ABDKMath64x64 } from \"../../typechain\";\nimport { getSqrtPriceAndTickBySqueethPrice } from \"../calculator\";\n\n// use the same price to make sure we're not paying funding (at first)\nconst initSquEthPrice = BigNumber.from('3000').mul(one).div(oracleScaleFactor)\nconst initEthUSDPrice = BigNumber.from('3000').mul(one)\n\nconst mintAmount = BigNumber.from('100').mul(one)\nconst collateralAmount = BigNumber.from('45').mul(one)\n\ndescribe(\"Simple Vault state tests\", function () {\n  let squeeth: MockWPowerPerp;\n  let shortSqueeth: MockShortPowerPerp;\n  let controller: Controller;\n  let vaultLib: VaultLibTester\n  let squeethEthPool: MockUniswapV3Pool;\n  let ethUSDPool: MockUniswapV3Pool;\n  let uniPositionManager: MockUniPositionManager\n  let oracle: MockOracle;\n  let weth: MockErc20;\n  let usdc: MockErc20;\n  let provider: providers.JsonRpcProvider;\n  let seller1: SignerWithAddress\n  let random: SignerWithAddress\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_seller1, _random] = accounts;\n    seller1 = _seller1\n    random = _random\n    provider = ethers.provider\n\n    await provider.send(\"evm_setAutomine\", [true]);\n  })\n\n  this.beforeAll(\"Setup environment\", async () => {\n    const MockSQUContract = await ethers.getContractFactory(\"MockWPowerPerp\");\n    squeeth = (await MockSQUContract.deploy()) as MockWPowerPerp;\n\n    const NFTContract = await ethers.getContractFactory(\"MockShortPowerPerp\");\n    shortSqueeth = (await NFTContract.deploy()) as MockShortPowerPerp;\n\n    const OracleContract = await ethers.getContractFactory(\"MockOracle\");\n    oracle = (await OracleContract.deploy()) as MockOracle;\n\n    const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n    weth = (await MockErc20Contract.deploy(\"WETH\", \"WETH\", 18)) as MockErc20;\n    usdc = (await MockErc20Contract.deploy(\"USDC\", \"USDC\", 6)) as MockErc20;\n\n    const MockUniswapV3PoolContract = await ethers.getContractFactory(\"MockUniswapV3Pool\");\n    squeethEthPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n    ethUSDPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n\n    const MockPositionManager = await ethers.getContractFactory(\"MockUniPositionManager\");\n    uniPositionManager = (await MockPositionManager.deploy()) as MockUniPositionManager;\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const TickMathExternal = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMathExternal.deploy());\n\n    const VaultLibFactory = await ethers.getContractFactory(\"VaultLibTester\", {libraries: {TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n    vaultLib = (await VaultLibFactory.deploy()) as VaultLibTester;\n\n\n    await squeethEthPool.setPoolTokens(weth.address, squeeth.address);\n    await ethUSDPool.setPoolTokens(weth.address, usdc.address);\n\n    await oracle.connect(random).setPrice(squeethEthPool.address , initSquEthPrice) // eth per 1 squeeth\n    await oracle.connect(random).setPrice(ethUSDPool.address , initEthUSDPrice)  // usdc per 1 eth\n  });\n\n  describe(\"Deployment\", async () => {\n    it(\"Deployment\", async function () {\n      const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n      const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n    \n      const TickMathExternal = await ethers.getContractFactory(\"TickMathExternal\")\n      const TickMathLibrary = (await TickMathExternal.deploy());\n    \n      const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n      const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n  \n      const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n      controller = (await ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, weth.address, usdc.address, ethUSDPool.address, squeethEthPool.address, uniPositionManager.address, 3000)) as Controller;\n    });\n  });\n\n  describe('isVaultSafe tests on vaults with no nft', async() => {\n    let vaultId: BigNumber\n    it('should return true if vault does not exist', async() => {\n      expect((await controller.isVaultSafe(1))).to.be.true\n    })\n    it('should return true if vault has no short', async() => {\n      vaultId = await shortSqueeth.nextId()\n      await controller.connect(seller1).mintPowerPerpAmount(0, 0, 0, {value: collateralAmount})\n      expect((await controller.isVaultSafe(vaultId))).to.be.true\n    })\n    it('should be able to mint perfect amount of wsqueeth', async() => {\n      await controller.connect(seller1).mintPowerPerpAmount(vaultId, mintAmount, 0)\n      expect((await controller.isVaultSafe(vaultId))).to.be.true\n    })\n    it('moving the price up should make the vault insolvent', async() => {\n      const newEthPrice = BigNumber.from('3001').mul(one)\n      await oracle.setPrice(ethUSDPool.address , newEthPrice)\n      expect((await controller.isVaultSafe(vaultId))).to.be.false\n    })\n    it('funding should make the vault back to safe as time goes by', async() => {\n      const markPrice = BigNumber.from('3030').mul(one).div(oracleScaleFactor)\n      await oracle.setPrice(squeethEthPool.address , markPrice)\n      await provider.send(\"evm_increaseTime\", [1.04*86400]) // increase time by 1.04 days\n      await provider.send(\"evm_mine\", [])\n      expect((await controller.isVaultSafe(vaultId))).to.be.true\n    })\n  })\n\n  describe('isVaultSafe tests on vaults with nft', async() => {\n      let wethIsToken0: boolean\n      let vaultId: BigNumber\n      const uniNFTId = 1\n\n      let token0: string\n      let token1: string\n\n      \n      before('prepare global variables', async() => {\n        wethIsToken0 = parseInt(weth.address, 16) < parseInt(squeeth.address, 16)\n        token0 = wethIsToken0 ? weth.address : squeeth.address\n        token1 = wethIsToken0 ? squeeth.address : weth.address\n      })\n      \n      before(\"set lp token properties\", async () => {\n        // the let's assume price range is only 2000 -> 4000, so if squeeth price > 4000\n        // we will only have eth left in LP token.\n        const { sqrtPrice: oldSqrtPrice } = getSqrtPriceAndTickBySqueethPrice(initSquEthPrice, wethIsToken0)\n\n        // fix deposit eth amount at 30\n        const ethLiquidityAmount = ethers.utils.parseUnits('30')\n\n        const scaledPrice4000 = BigNumber.from('4000').mul(one).div(oracleScaleFactor)\n        const scaledPrice2000 = BigNumber.from('2000').mul(one).div(oracleScaleFactor)\n\n        const { tick: tick4000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice4000, wethIsToken0)\n        const { sqrtPrice: sqrtPrice2000, tick: tick2000 } = getSqrtPriceAndTickBySqueethPrice(scaledPrice2000, wethIsToken0)\n\n        // get approximate liquidity value, with 30 eth deposit\n        const liquidity = wethIsToken0\n          ? await vaultLib.getLiquidityForAmount0(oldSqrtPrice, sqrtPrice2000, ethLiquidityAmount.toString())\n          : await vaultLib.getLiquidityForAmount1(oldSqrtPrice, sqrtPrice2000, ethLiquidityAmount.toString())\n        \n        const tickUpper = wethIsToken0 ? tick2000 : tick4000;\n        const tickLower = wethIsToken0 ? tick4000 : tick2000;\n\n        await uniPositionManager.setMockedProperties(token0, token1, tickLower, tickUpper, liquidity) // use the same liquidity\n      })\n      \n      before('create vault with nft', async() => {\n        \n\n        await uniPositionManager.mint(seller1.address, uniNFTId)\n        await uniPositionManager.connect(seller1).approve(controller.address, uniNFTId)\n\n        vaultId = await shortSqueeth.nextId()\n        const { tick } = getSqrtPriceAndTickBySqueethPrice(initSquEthPrice, wethIsToken0)\n        await oracle.connect(random).setPrice(squeethEthPool.address , initSquEthPrice)\n        await oracle.connect(random).setPrice(ethUSDPool.address , initEthUSDPrice)\n        await oracle.setAverageTick(squeethEthPool.address, tick)\n\n\n        const { wPowerPerpAmount, ethAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, uniNFTId, tick, wethIsToken0)\n        \n        const equivalentCollateral = wPowerPerpAmount.mul(initEthUSDPrice).div(one).div(oracleScaleFactor).add(ethAmount)\n        \n        const totalMintAmount = equivalentCollateral.mul(one).mul(2).div(3).div(initEthUSDPrice).mul(oracleScaleFactor)\n        await controller.mintPowerPerpAmount(0, totalMintAmount, uniNFTId, {value: 0})\n      })\n      it('should become underwater if squeeth price increase, and LP is all eth', async()=>{\n        // set oracle to 4500\n        const newEthPrice = BigNumber.from('4500').mul(one)\n        const newSqueethPrice = newEthPrice.div(oracleScaleFactor)\n        \n        const { tick } = getSqrtPriceAndTickBySqueethPrice(newSqueethPrice, wethIsToken0)\n\n        await oracle.connect(random).setPrice(ethUSDPool.address , newEthPrice)\n        await oracle.connect(random).setPrice(squeethEthPool.address , newSqueethPrice)\n        await oracle.setAverageTick(squeethEthPool.address, tick)\n\n        \n        const result = await vaultLib.getUniPositionBalances(uniPositionManager.address, uniNFTId, tick, wethIsToken0)\n\n        expect(result.wPowerPerpAmount.isZero()).to.be.true\n        expect(await controller.isVaultSafe(vaultId)).to.be.false\n      })\n      it('should become underwater if squeeth price decrease, and LP is all squeeth', async()=>{\n        // set oracle to 1500\n        const newEthPrice = BigNumber.from('1500').mul(one)\n        const newSqueethPrice = newEthPrice.div(oracleScaleFactor)\n        \n        const { tick } = getSqrtPriceAndTickBySqueethPrice(newSqueethPrice, wethIsToken0)\n\n        await oracle.connect(random).setPrice(ethUSDPool.address , newEthPrice)\n        await oracle.connect(random).setPrice(squeethEthPool.address , newSqueethPrice)\n        await oracle.setAverageTick(squeethEthPool.address, tick)\n\n        const result = await vaultLib.getUniPositionBalances(uniPositionManager.address, uniNFTId, tick, wethIsToken0)\n        \n        expect(result.ethAmount.isZero()).to.be.true\n        expect(await controller.isVaultSafe(vaultId)).to.be.true\n      })\n  })\n});\n"
  },
  {
    "path": "packages/hardhat/test/unit-tests/controller.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { BigNumber, providers, constants } from \"ethers\";\nimport { Controller, MockWPowerPerp, MockShortPowerPerp, MockOracle, MockUniswapV3Pool, MockErc20, MockUniPositionManager, VaultLibTester, WETH9, ControllerTester, ABDKMath64x64} from '../../typechain'\nimport { isEmptyVault } from '../vault-utils'\nimport { isSimilar, oracleScaleFactor, one, getNow } from \"../utils\";\nimport { getSqrtPriceAndTickBySqueethPrice } from \"../calculator\";\n\nconst squeethETHPrice = BigNumber.from('3010').mul(one)\nconst scaledSqueethPrice = squeethETHPrice.div(oracleScaleFactor)\n\nconst ethUSDPrice = BigNumber.from('3000').mul(one)\nconst scaledEthPrice = ethUSDPrice.div(oracleScaleFactor)\n\ndescribe(\"Controller\", function () {\n  let squeeth: MockWPowerPerp;\n  let shortSqueeth: MockShortPowerPerp;\n  let controller: Controller;\n  let controllerTester: ControllerTester\n  let squeethEthPool: MockUniswapV3Pool;\n  let ethUSDPool: MockUniswapV3Pool;\n  let uniPositionManager: MockUniPositionManager\n  let oracle: MockOracle;\n  let weth: WETH9;\n  let usdc: MockErc20;\n  let vaultLib: VaultLibTester\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress\n  let seller1: SignerWithAddress\n  let seller2: SignerWithAddress\n  let seller3: SignerWithAddress\n  let seller4: SignerWithAddress // use for burnRSqueeth tests\n  let seller5: SignerWithAddress // settle short vault with nft in it\n  let seller6: SignerWithAddress // settle short vault with one-sided nft in it\n  let seller7: SignerWithAddress // settle short vault with 0 short\n  let seller8: SignerWithAddress // fail to settle short vault with nft in it, but able to reduceDebt\n  let random: SignerWithAddress\n  let feeRecipient: SignerWithAddress\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner,_seller1, _seller2, _seller3, _seller4, _seller5, _seller6, _seller7, _seller8, _random, _feeRecipient] = accounts;\n    \n    seller1 = _seller1\n    seller2 = _seller2\n    seller3 = _seller3\n    seller4 = _seller4\n    seller5 = _seller5\n    seller6 = _seller6\n    seller7 = _seller7\n    seller8 = _seller8\n    \n    random = _random\n    owner = _owner\n    feeRecipient = _feeRecipient\n    provider = ethers.provider\n  })\n\n  this.beforeAll(\"Setup environment\", async () => {\n    const MockSQUContract = await ethers.getContractFactory(\"MockWPowerPerp\");\n    squeeth = (await MockSQUContract.deploy()) as MockWPowerPerp;\n\n    const NFTContract = await ethers.getContractFactory(\"MockShortPowerPerp\");\n    shortSqueeth = (await NFTContract.deploy()) as MockShortPowerPerp;\n\n    const OracleContract = await ethers.getContractFactory(\"MockOracle\");\n    oracle = (await OracleContract.deploy()) as MockOracle;\n\n    const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n    usdc = (await MockErc20Contract.deploy(\"USDC\", \"USDC\", 6)) as MockErc20;\n\n    const WETHContract = await ethers.getContractFactory(\"WETH9\");\n    weth = (await WETHContract.deploy()) as WETH9;\n\n    const MockUniswapV3PoolContract = await ethers.getContractFactory(\"MockUniswapV3Pool\");\n    squeethEthPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n    ethUSDPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n\n    const MockPositionManager = await ethers.getContractFactory(\"MockUniPositionManager\");\n    uniPositionManager = (await MockPositionManager.deploy()) as MockUniPositionManager;\n\n\n\n    await squeethEthPool.setPoolTokens(weth.address, squeeth.address);\n    await ethUSDPool.setPoolTokens(weth.address, usdc.address);\n\n\n    await oracle.connect(random).setPrice(squeethEthPool.address , scaledSqueethPrice) // eth per 1 squeeth\n\n    // the oracle should return the exact ETH / USDC price (without scale)\n    await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPrice)  // usdc per 1 eth\n\n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const TickMathExternal = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMathExternal.deploy());\n\n    const VaultTester = await ethers.getContractFactory(\"VaultLibTester\", {libraries: {TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n    vaultLib = (await VaultTester.deploy()) as VaultLibTester;\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n    \n    controller = (await ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, weth.address, usdc.address, ethUSDPool.address, squeethEthPool.address, uniPositionManager.address, 3000)) as Controller;\n  });\n\n  it(\"Should revert when oracle is address(0)\", async () => {\n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n\n    const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMath.deploy());\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n\n    await expect(\n      ControllerContract.deploy(ethers.constants.AddressZero, shortSqueeth.address, squeeth.address, weth.address, usdc.address, ethUSDPool.address, squeethEthPool.address, uniPositionManager.address, 3000)\n    ).to.be.revertedWith(\"C4\");\n  });\n\n  it(\"Should revert when shortSqueeth is address(0)\", async () => {\n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n\n    const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMath.deploy());\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n\n    await expect(\n      ControllerContract.deploy(oracle.address, ethers.constants.AddressZero, squeeth.address, weth.address, usdc.address, ethUSDPool.address, squeethEthPool.address, uniPositionManager.address, 3000)\n    ).to.be.revertedWith(\"C5\");\n  });\n\n  it(\"Should revert when powerperp is address(0)\", async () => {\n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n\n    const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMath.deploy());\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n\n    await expect(\n      ControllerContract.deploy(oracle.address, shortSqueeth.address, ethers.constants.AddressZero, weth.address, usdc.address, ethUSDPool.address, squeethEthPool.address, uniPositionManager.address, 3000)\n    ).to.be.revertedWith(\"C6\");\n  });\n\n  it(\"Should revert when weth is address(0)\", async () => {\n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n\n    const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMath.deploy());\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n\n    await expect(\n      ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, ethers.constants.AddressZero, usdc.address, ethUSDPool.address, squeethEthPool.address, uniPositionManager.address, 3000)\n    ).to.be.revertedWith(\"C7\");\n  });\n  \n  it(\"Should revert when quote currency is address(0)\", async () => {\n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n\n    const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMath.deploy());\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n\n    await expect(\n      ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, weth.address, ethers.constants.AddressZero, ethUSDPool.address, squeethEthPool.address, uniPositionManager.address, 3000)\n    ).to.be.revertedWith(\"C8\");\n  });\n\n  it(\"Should revert when ethUSDPool is address(0)\", async () => {\n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n\n    const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMath.deploy());\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n\n    await expect(\n      ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, weth.address, usdc.address, ethers.constants.AddressZero, squeethEthPool.address, uniPositionManager.address, 3000)\n    ).to.be.revertedWith(\"C9\");\n  });\n\n  it(\"Should revert when squeethEthPool is address(0)\", async () => {\n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n\n    const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMath.deploy());\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n\n    await expect(\n      ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, weth.address, usdc.address, ethUSDPool.address, ethers.constants.AddressZero, uniPositionManager.address, 3000)\n    ).to.be.revertedWith(\"C10\");\n  });\n\n  it(\"Should revert when uniPositionManager is address(0)\", async () => {\n    const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n    const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n\n    const TickMath = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMath.deploy());\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n\n    await expect(\n      ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, weth.address, usdc.address, ethUSDPool.address, squeethEthPool.address, ethers.constants.AddressZero, 3000)\n    ).to.be.revertedWith(\"C11\");\n  });\n\n  describe(\"Deployment\", async () => {\n    it(\"Check controller deployment\", async () => {\n      const squeethAddr = await controller.wPowerPerp();\n      const nftAddr = await controller.shortPowerPerp();\n\n      expect(squeethAddr).to.be.eq(\n        squeeth.address,\n        \"squeeth address mismatch\"\n      );\n      expect(nftAddr).to.be.eq(shortSqueeth.address, \"nft address mismatch\");\n    });\n\n    it(\"Controller tester deployment\", async function () {\n      const ControllerTesterContract = await ethers.getContractFactory(\"ControllerTester\");\n      controllerTester = (await ControllerTesterContract.deploy(controller.address)) as ControllerTester;\n    });\n  });\n\n  describe(\"Owner only functions\", async () => {\n    it(\"Should revert if trying to set fee rate before setting fee recipient\", async () => {\n      await expect(controller.connect(owner).setFeeRate(100)).to.be.revertedWith('C14')\n    });\n\n    it(\"Should revert if trying to set address(0) as fee recipient\", async () => {\n      await expect(controller.connect(owner).setFeeRecipient(constants.AddressZero)).to.be.revertedWith(\"C13\");\n    });\n\n    it(\"Should set the fee recipient\", async () => {\n      await controller.connect(owner).setFeeRecipient(feeRecipient.address);\n      expect((await controller.feeRecipient()) === feeRecipient.address).to.be.true\n    });\n\n    it(\"Should revert if trying to set fee rate that is too high\", async () => {\n      await expect(controller.connect(owner).setFeeRate(500)).to.be.revertedWith(\"C15\")\n    });\n\n    it(\"Should revert if set fee rate is call by random address\", async () => {\n      await expect(controller.connect(random).setFeeRate(500)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    });\n\n    it(\"Should revert if set fee recipient is call by random address\", async () => {\n      await expect(controller.connect(random).setFeeRecipient(constants.AddressZero)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    });\n  });\n\n  describe(\"Basic actions\", function () {\n\n    let vaultId: BigNumber;\n\n    describe('#Read basic properties', async() => {\n      \n      it('should be able to get normalization factor', async() => {\n        const normFactor = await controller.normalizationFactor()\n        const expectedNormFactor = await controller.getExpectedNormalizationFactor()\n        // norm factor should be init as 1e18\n        expect(normFactor.eq(one)).to.be.true\n        // expected norm factor should be smaller than 1, cuz time has pass since function started\n        expect(expectedNormFactor.lt(normFactor)).to.be.true\n\n\n        // update block.timestamp in solidity\n        await provider.send(\"evm_increaseTime\", [30])\n        await provider.send(\"evm_mine\", [])\n        // expected norm factor should go down again\n        const expectedNormFactorAfter = await controller.getExpectedNormalizationFactor()\n        expect(expectedNormFactorAfter.lt(expectedNormFactor)).to.be.true\n      })\n      \n      it('should allow anyone to call applyFunding and update funding', async()=>{\n        const normFactor = await controller.normalizationFactor()\n        const expectedNormFactor = await controller.getExpectedNormalizationFactor()\n        \n        await controller.connect(random).applyFunding()\n\n        const normFactorAfterFunding = await controller.normalizationFactor()\n        expect(isSimilar(expectedNormFactor.toString(),normFactorAfterFunding.toString())).to.be.true\n        expect(normFactor.gt(normFactorAfterFunding)).to.be.true\n        \n      })\n\n      it('should not update funding two times in one block', async()=>{        \n        await controllerTester.connect(random).testDoubleFunding()\n      })\n\n      it('should be able to get index and mark price and mark price used for funding', async() => {\n        // update block.timestamp in solidity\n        await provider.send(\"evm_increaseTime\", [30])\n        await provider.send(\"evm_mine\", [])\n        \n        const markPrice = await controller.getDenormalizedMark(30)\n        const markPriceForFunding = await controller.getDenormalizedMarkForFunding(30)\n\n        expect(isSimilar(markPrice.toString(), scaledSqueethPrice.mul(scaledEthPrice).div(one).toString())).to.be.true\n        expect(isSimilar(markPriceForFunding.toString(), scaledSqueethPrice.mul(scaledEthPrice).div(one).toString())).to.be.true\n        expect(markPrice.gt(markPriceForFunding)).to.be.true\n\n        const index = await controller.getIndex(30)\n        expect(index.eq(scaledEthPrice.mul(scaledEthPrice).div(one))).to.be.true\n      })\n\n      it('should be able to get unscaled index price', async() => {\n\n        const index = await controller.getUnscaledIndex(30)\n        expect(index.eq(ethUSDPrice.mul(ethUSDPrice).div(one))).to.be.true\n      })\n\n\n      it('should revert when sending eth to controller from an EOA', async() => {\n        await expect(random.sendTransaction({to: controller.address, value:1})).to.be.revertedWith('C19')\n      })\n    })\n\n    describe(\"#Mint: Open vault\", async () => {\n      it(\"Should be able to open vaults\", async () => {\n        vaultId = await shortSqueeth.nextId()\n        const nftBalanceBefore = await shortSqueeth.balanceOf(seller1.address)\n        await controller.connect(seller1).mintPowerPerpAmount(0, 0, 0) // putting vaultId = 0 to open vault\n\n        // total short position nft should increase\n        const nftBalanceAfter = await shortSqueeth.balanceOf(seller1.address)\n        expect(nftBalanceAfter.eq(nftBalanceBefore.add(1))).is.true;\n\n        // the newly created vault should be empty\n        const vault = await controller.vaults(vaultId)\n        expect(isEmptyVault(vault)).to.be.true\n      });\n    });\n\n    describe(\"#Deposit: Deposit collateral\", async () => {\n      it(\"Should revert when trying to deposit to vault 0\", async() => {\n        await expect(controller.connect(seller1).deposit(0)).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n      it(\"Should revert when trying to access non-existent vault\", async() => {\n        await expect(controller.connect(seller1).deposit(100, {value: 100})).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n      it(\"Should revert when trying to use mint to deposit to non-existent vault\", async() => {\n        await expect(controller.connect(seller1).mintPowerPerpAmount(999, 0, 0, {value: 100})).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n\n      it(\"Should revert when trying to use mint to deposit to a vault where msg.sender is not owner or operator\", async() => {\n        const depositAmount = ethers.utils.parseUnits('45')\n\n        await expect(controller.connect(random).deposit(vaultId,{value: depositAmount})).to.be.revertedWith(\n          'C20'\n        )\n      })\n\n      it(\"Should be able to deposit collateral\", async () => {\n        const depositAmount = ethers.utils.parseUnits('45')\n        const controllerBalanceBefore = await provider.getBalance(controller.address)\n        const vaultBefore = await controller.vaults(vaultId)\n        \n        await controller.connect(seller1).deposit(vaultId,{value: depositAmount})\n        \n        const controllerBalanceAfter = await provider.getBalance(controller.address)\n        const vaultAfter = await controller.vaults(vaultId)\n        \n        expect(controllerBalanceBefore.add(depositAmount).eq(controllerBalanceAfter)).to.be.true\n        expect(vaultBefore.collateralAmount.add(depositAmount).eq(vaultAfter.collateralAmount)).to.be.true\n      });\n      it(\"Should be able to deposit 0 collateral\", async () => {\n        const vaultBefore = await controller.vaults(vaultId)\n        await controller.connect(seller1).deposit(vaultId)\n        const vaultAfter = await controller.vaults(vaultId)\n        \n        expect(vaultBefore.collateralAmount.eq(vaultAfter.collateralAmount)).to.be.true\n      });\n    });\n\n    describe(\"#Mint: Mint Squeeth\", async () => {\n      it(\"Should revert if not called by owner\", async () => {\n        const mintAmount = ethers.utils.parseUnits('100')\n        \n        await expect(controller.connect(random).mintPowerPerpAmount(vaultId, mintAmount, 0)).to.be.revertedWith(\n          'C20'\n        )\n      });\n      it(\"Should revert when trying to mint to non-existent vault\", async() => {\n        await expect(controller.connect(seller1).mintPowerPerpAmount(999, 10, 0)).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n      it(\"Should be able to mint squeeth\", async () => {\n        const mintAmount = ethers.utils.parseUnits('100')\n        \n        const vaultBefore = await controller.vaults(vaultId)\n        const squeethBalanceBefore = await squeeth.balanceOf(seller1.address)\n        \n        await controller.connect(seller1).mintPowerPerpAmount(vaultId, mintAmount, 0)\n\n        const squeethBalanceAfter = await squeeth.balanceOf(seller1.address)\n        const vaultAfter = await controller.vaults(vaultId)\n        const normFactor = await controller.normalizationFactor()\n\n        expect(vaultBefore.shortAmount.add(mintAmount.mul(one).div(normFactor)).eq(vaultAfter.shortAmount)).to.be.true\n        expect(squeethBalanceBefore.add(mintAmount.mul(one).div(normFactor)).eq(squeethBalanceAfter)).to.be.true\n      });\n      \n      it(\"Should revert when minting more than allowed\", async () => {\n        const mintAmount = ethers.utils.parseUnits('100')        \n        await expect(controller.connect(seller1).mintPowerPerpAmount(vaultId, mintAmount, 0)).to.be.revertedWith(\n          'C24'\n        )\n      });\n\n    });\n\n    describe(\"#Burn: Burn Squeeth\", async () => {\n      it(\"Should revert when trying to burn for vault 0\", async() => {\n        await expect(controller.connect(seller1).burnPowerPerpAmount(0, 0, 0)).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n      it(\"Should revert when trying to burn wrapped amount for vault 0\", async() => {\n        await expect(controller.connect(seller1).burnWPowerPerpAmount(0, 0, 0)).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n\n      it(\"Should revert when trying to burn for non-existent vault\", async() => {\n        await expect(controller.connect(seller1).burnPowerPerpAmount(100, 0, 0)).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n      it(\"Should revert when trying to burn wrapped amount for non-existent vault\", async() => {\n        await expect(controller.connect(seller1).burnWPowerPerpAmount(100, 0, 0)).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n      it(\"Should revert if trying to burn more than minted\", async () => {\n        const vault = await controller.vaults(vaultId)\n        await expect(controller.connect(seller1).burnWPowerPerpAmount(vaultId, vault.shortAmount.add(1), 0)).to.be.revertedWith('SafeMath: subtraction overflow')\n      });\n      // todo: add another case to test burning someone else squeeth while being a seller\n      it(\"Should revert if trying to burn without having squeeth\", async () => {\n        const vault = await controller.vaults(vaultId)\n        await squeeth.connect(seller1).transfer(random.address, 1)\n        await expect(controller.connect(seller1).burnWPowerPerpAmount(vaultId, vault.shortAmount, 0)).to.be.revertedWith(\n          'ERC20: burn amount exceeds balance'\n        )\n        await squeeth.mint(seller1.address, 1)\n      });\n      it('should revert if vault after burning is underwater', async() => {\n        const vault = await controller.vaults(vaultId)\n        await expect(controller.connect(seller1).burnWPowerPerpAmount(vaultId, vault.shortAmount.div(2), vault.collateralAmount)).to.be.revertedWith('C24')\n      })\n      it('should revert if vault after burning is dust', async() => {\n        const vault = await controller.vaults(vaultId)\n        await expect(controller.connect(seller1).burnWPowerPerpAmount(vaultId, vault.shortAmount.sub(1), vault.collateralAmount.sub(1))).to.be.revertedWith('C22')\n      })\n\n      it(\"Should revert if trying to withdraw and put make vault underwater\", async () => {\n        const vault = await controller.vaults(vaultId)\n        await expect(controller.connect(seller1).withdraw(vaultId, vault.collateralAmount)).to.be.revertedWith('C24')\n      })\n\n      it('Should revert if a random account tries to burn squeeth for vault1', async() => {\n        await squeeth.mint(random.address, 1000)\n        await expect(controller.connect(random).burnWPowerPerpAmount(vaultId, 1000, 0)).to.be.revertedWith(\"C20\")\n      })\n\n      it('should revert when non-owner try to burn and withdraw from vault', async() => {\n        await expect(controller.connect(random).burnWPowerPerpAmount(vaultId, 0, 1000)).to.be.revertedWith('C20')\n      })\n      \n      it(\"Should be able to burn squeeth\", async () => {\n        const vaultBefore = await controller.vaults(vaultId)\n        const burnAmount = vaultBefore.shortAmount;\n        const squeethBalanceBefore = await squeeth.balanceOf(seller1.address)\n        const withdrawAmount = 5\n\n        await controller.connect(seller1).burnWPowerPerpAmount(vaultId, burnAmount, withdrawAmount)\n\n        const squeethBalanceAfter = await squeeth.balanceOf(seller1.address)\n        const vaultAfter = await controller.vaults(vaultId)\n\n        expect(vaultBefore.shortAmount.sub(burnAmount).eq(vaultAfter.shortAmount)).to.be.true\n        expect(vaultBefore.collateralAmount.sub(withdrawAmount).eq(vaultAfter.collateralAmount)).to.be.true\n        expect(squeethBalanceBefore.sub(burnAmount).eq(squeethBalanceAfter)).to.be.true\n      });\n    });\n\n    describe(\"#Withdraw: Remove Collateral\", async () => {\n      it(\"Should revert when trying to remove from vault 0\", async() => {\n        await expect(controller.connect(seller1).withdraw(0, 0)).to.be.revertedWith(\n          'ERC721: owner query for nonexistent token'\n        )\n      })\n      it(\"Should revert if caller is not the owner\", async () => {\n        const vault = await controller.vaults(vaultId)\n        await expect(controller.connect(random).withdraw(vaultId, vault.collateralAmount)).to.be.revertedWith(\n          'C20'\n        )\n      })\n      it(\"Should revert if trying to remove more collateral than deposited\", async () => {\n        const vault = await controller.vaults(vaultId)\n        await expect(controller.connect(seller1).burnWPowerPerpAmount(vaultId, 0, vault.collateralAmount.add(1))).to.be.revertedWith('SafeMath: subtraction overflow')\n      })\n\n      it('should revert if trying to remove collateral which produce a vault dust', async() => {\n        // mint little wsqueeth\n        const mintAmount = 1000\n        await controller.connect(seller1).mintWPowerPerpAmount(vaultId, mintAmount, 0)\n\n        const vault = await controller.vaults(vaultId)\n        await expect(controller.connect(seller1).burnWPowerPerpAmount(vaultId, 0, vault.collateralAmount.sub(2))).to.be.revertedWith('C24')\n        \n        // burn the minted amount\n        await controller.connect(seller1).burnWPowerPerpAmount(vaultId, mintAmount, 0)\n      })\n      \n      it(\"Should be able to remove collateral\", async () => {\n        const vaultBefore = await controller.vaults(vaultId)\n        const withdrawAmount = vaultBefore.collateralAmount.div(2)\n        const userBalanceBefore = await provider.getBalance(seller1.address)\n        const controllerBalanceBefore = await provider.getBalance(controller.address)\n        \n        await controller.connect(seller1).withdraw(vaultId, withdrawAmount)\n        \n        const userBalanceAfter = await provider.getBalance(seller1.address)\n        const controllerBalanceAfter = await provider.getBalance(controller.address)\n        const vaultAfter = await controller.vaults(vaultId)\n\n        expect(controllerBalanceBefore.sub(withdrawAmount).eq(controllerBalanceAfter)).to.be.true\n        // expect(userBalanceAfter.sub(userBalanceBefore).eq(withdrawAmount)).to.be.true\n        expect(vaultBefore.collateralAmount.sub(withdrawAmount).eq(vaultAfter.collateralAmount)).to.be.true\n      });\n      it(\"Should close the vault when it's empty\", async () => {\n        const vaultBefore = await controller.vaults(vaultId)\n        const withdrawAmount = vaultBefore.collateralAmount\n        const nftBalanceBefore = await shortSqueeth.balanceOf(seller1.address)\n        const burnAmount = vaultBefore.shortAmount\n        const controllerBalanceBefore = await provider.getBalance(controller.address)\n        \n        await controller.connect(seller1).burnWPowerPerpAmount(vaultId, burnAmount, withdrawAmount)\n        \n        const controllerBalanceAfter = await provider.getBalance(controller.address)\n        const nftBalanceAfter = await shortSqueeth.balanceOf(seller1.address)\n\n        expect(controllerBalanceBefore.sub(withdrawAmount).eq(controllerBalanceAfter)).to.be.true\n        expect(nftBalanceAfter.eq(nftBalanceBefore)).to.be.true // nft is not burned\n      });\n    });\n  });\n\n  describe('Combined actions', async() => {\n\n    let vaultId: BigNumber\n\n    describe('Open, deposit and mint', () => {\n      it('should revert if the vault has too little collateral', async() => {\n        const mintAmount = ethers.utils.parseUnits('0.1')\n        const collateralAmount = ethers.utils.parseUnits('0.45')\n        await expect(controller.connect(random).mintPowerPerpAmount(0, mintAmount, 0, {value: collateralAmount}))\n          .to.be.revertedWith('C22')\n      })\n      it('should open vault, deposit and mint in the same tx', async() => {\n        vaultId = await shortSqueeth.nextId()\n        const mintAmount = ethers.utils.parseUnits('100')\n        const collateralAmount = ethers.utils.parseUnits('45') \n\n        const controllerBalanceBefore = await provider.getBalance(controller.address)\n        const nftBalanceBefore = await shortSqueeth.balanceOf(seller1.address)\n        const squeethBalanceBefore = await squeeth.balanceOf(seller1.address)\n\n        // put vaultId as 0 to open vault\n        await controller.connect(seller1).mintPowerPerpAmount(0, mintAmount, 0, {value: collateralAmount})\n\n        const normFactor = await controller.normalizationFactor()\n        const controllerBalanceAfter = await provider.getBalance(controller.address)\n        const nftBalanceAfter = await shortSqueeth.balanceOf(seller1.address)\n        const squeethBalanceAfter = await squeeth.balanceOf(seller1.address)\n        const newVault = await controller.vaults(vaultId)\n\n        expect(nftBalanceBefore.add(1).eq(nftBalanceAfter)).to.be.true\n        expect(controllerBalanceBefore.add(collateralAmount).eq(controllerBalanceAfter)).to.be.true\n        expect(squeethBalanceBefore.add(mintAmount.mul(one).div(normFactor)).eq(squeethBalanceAfter)).to.be.true\n\n        expect(newVault.collateralAmount.eq(collateralAmount)).to.be.true\n        expect(newVault.shortAmount.eq(mintAmount.mul(one).div(normFactor))).to.be.true\n      })\n    })\n\n    describe('Deposit and mint with mintWPowerPerpAmount', () => {\n      \n      it('Should revert if a random address tries to deposit collateral using mintWPowerPerpAmount', async() => {\n        // mint some other squeeth in vault 2.\n        const collateralAmount = ethers.utils.parseUnits('4.5')\n\n        await expect(controller.connect(random).mintWPowerPerpAmount(vaultId, 0, 0, {value: collateralAmount})).to.be.revertedWith(\"C20\")\n      })\n\n      it('Should revert if a random address tries to deposit a Uni NFT using mintWPowerPerpAmount', async() => {\n        // mint some other squeeth in vault 2.\n        const uniTokenId = 100\n        \n        await expect(controller.connect(random).mintWPowerPerpAmount(vaultId, 0, uniTokenId)).to.be.revertedWith(\"C20\")\n      })\n      \n      it('should deposit and mint in the same tx', async() => {\n        // mint some other squeeth in vault 2.\n        const normFactor = await controller.normalizationFactor()\n        const mintRSqueethAmount = ethers.utils.parseUnits('1')\n        const mintWSqueethAmount = mintRSqueethAmount.mul(one).div(normFactor)\n        const collateralAmount = ethers.utils.parseUnits('4.5')\n\n        const controllerBalanceBefore = await provider.getBalance(controller.address)\n        const squeethBalanceBefore = await squeeth.balanceOf(seller1.address)\n        const vaultBefore = await controller.vaults(vaultId)\n\n        await controller.connect(seller1).mintWPowerPerpAmount(vaultId, mintWSqueethAmount, 0, {value: collateralAmount})\n\n        const controllerBalanceAfter = await provider.getBalance(controller.address)\n        const squeethBalanceAfter = await squeeth.balanceOf(seller1.address)\n        const vaultAfter = await controller.vaults(vaultId)\n\n        expect(controllerBalanceBefore.add(collateralAmount).eq(controllerBalanceAfter)).to.be.true\n        expect(squeethBalanceBefore.add(mintWSqueethAmount).eq(squeethBalanceAfter)).to.be.true\n\n        expect(vaultBefore.collateralAmount.add(collateralAmount).eq(vaultAfter.collateralAmount)).to.be.true\n        expect(vaultBefore.shortAmount.add(mintWSqueethAmount).eq(vaultAfter.shortAmount)).to.be.true\n      })\n\n      it('should just mint if deposit amount is 0', async() => {\n        const testMintWAmount = ethers.utils.parseUnits('0.001')\n        const vaultBefore = await controller.vaults(vaultId)        \n        await controller.connect(seller1).mintWPowerPerpAmount(vaultId, testMintWAmount, 0)\n        const vaultAfter = await controller.vaults(vaultId)\n\n        expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).isZero()).to.be.true\n        expect(vaultAfter.shortAmount.sub(vaultBefore.shortAmount).eq(testMintWAmount)).to.be.true\n      })\n      it('should just deposit if mint amount is 0', async() => {\n        \n        const testDepositAmount = ethers.utils.parseUnits('0.1')\n        const vaultBefore = await controller.vaults(vaultId)        \n        await controller.connect(seller1).mintWPowerPerpAmount(vaultId, 0, 0, {value: testDepositAmount})\n        const vaultAfter = await controller.vaults(vaultId)\n\n        expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).eq(testDepositAmount)).to.be.true\n        expect(vaultAfter.shortAmount.sub(vaultBefore.shortAmount).isZero()).to.be.true\n      })\n      it('should do nothing if both deposit and mint amount are 0', async() => {\n        const vaultBefore = await controller.vaults(vaultId)        \n        await controller.connect(seller1).mintWPowerPerpAmount(vaultId, 0, 0)\n        const vaultAfter = await controller.vaults(vaultId)\n\n        expect(vaultAfter.collateralAmount.sub(vaultBefore.collateralAmount).isZero()).to.be.true\n        expect(vaultAfter.shortAmount.sub(vaultBefore.shortAmount).isZero()).to.be.true\n      })\n    })\n\n    describe('Deposit and mint By operator', () => {\n      it('should not allow a non owner to update an operator', async () => {        \n        await expect(controller.connect(seller2).updateOperator(vaultId, random.address)).to.be.revertedWith(\"C20\")\n      })      \n      it('should add an operator', async () => {\n        await controller.connect(seller1).updateOperator(vaultId, random.address)\n        const vault = await controller.vaults(vaultId)\n        expect(vault.operator).to.be.eq(random.address)\n      })\n      it('should deposit and mint in the same tx', async() => {\n        // mint some other squeeth in vault 2.\n        const mintAmount = ethers.utils.parseUnits('100')\n        const collateralAmount = ethers.utils.parseUnits('45')\n\n        const controllerBalanceBefore = await provider.getBalance(controller.address)\n        const squeethBalanceBefore = await squeeth.balanceOf(random.address)\n        const vaultBefore = await controller.vaults(vaultId)\n\n        await controller.connect(random).mintPowerPerpAmount(vaultId, mintAmount, 0, {value: collateralAmount})\n\n        const controllerBalanceAfter = await provider.getBalance(controller.address)\n        const squeethBalanceAfter = await squeeth.balanceOf(random.address)\n        const vaultAfter = await controller.vaults(vaultId)\n        const normFactor = await controller.normalizationFactor()\n\n        expect(controllerBalanceBefore.add(collateralAmount).eq(controllerBalanceAfter)).to.be.true\n        expect(squeethBalanceBefore.add(mintAmount.mul(one).div(normFactor)).eq(squeethBalanceAfter)).to.be.true\n\n        expect(vaultBefore.collateralAmount.add(collateralAmount).eq(vaultAfter.collateralAmount)).to.be.true\n        expect(vaultBefore.shortAmount.add(mintAmount.mul(one).div(normFactor)).eq(vaultAfter.shortAmount)).to.be.true\n      })\n      it('should not allow an operator to update the operator associated with an account', async () => {\n        const vault = await controller.vaults(vaultId)\n        expect(vault.operator).to.be.eq(random.address)\n        await expect(controller.connect(random).updateOperator(vaultId, seller2.address)).to.be.revertedWith(\"C20\")\n      })\n    })\n\n    describe('Burn and withdraw', () => {\n      let seller4VaultId: BigNumber\n      before('mint squeeth for seller4 to withdraw', async() => {\n        seller4VaultId = await shortSqueeth.nextId()\n        const mintRAmount = ethers.utils.parseUnits('100')\n        const collateralAmount = ethers.utils.parseUnits('45')\n        await controller.connect(seller4).mintPowerPerpAmount(0, mintRAmount, 0, {value: collateralAmount})\n      })\n\n      it('should burn and withdraw with burnRPowerPerp', async() => {\n        const vaultBefore = await controller.vaults(seller4VaultId)\n        \n        // the real rSqueeth amount will decrease after funding.\n        const burnRSqueethAmount = ethers.utils.parseUnits('100').div(2)\n        const withdrawCollateralAmount = ethers.utils.parseUnits('45').div(2)\n\n        const controllerBalanceBefore = await provider.getBalance(controller.address)\n        const wsqueethBalanceBefore = await squeeth.balanceOf(seller4.address)\n\n        await controller.connect(seller4).burnPowerPerpAmount(seller4VaultId, burnRSqueethAmount, withdrawCollateralAmount)\n\n        const controllerBalanceAfter = await provider.getBalance(controller.address)\n        const wsqueethBalanceAfter = await squeeth.balanceOf(seller4.address)\n        const vaultAfter = await controller.vaults(seller4VaultId)        \n        const normFactor = await controller.normalizationFactor()\n\n        expect(controllerBalanceBefore.sub(withdrawCollateralAmount).eq(controllerBalanceAfter)).to.be.true\n        expect(wsqueethBalanceBefore.sub(burnRSqueethAmount.mul(one).div(normFactor)).eq(wsqueethBalanceAfter)).to.be.true\n\n        expect(vaultBefore.collateralAmount.sub(withdrawCollateralAmount).eq(vaultAfter.collateralAmount)).to.be.true\n        expect(vaultBefore.shortAmount.sub(burnRSqueethAmount.mul(one).div(normFactor)).eq(vaultAfter.shortAmount)).to.be.true\n      })\n      after('clean up vault4', async() => {\n        const vault = await controller.vaults(seller4VaultId)\n        await controller.connect(seller4).burnWPowerPerpAmount(seller4VaultId, vault.shortAmount, vault.collateralAmount)\n      })\n    })\n  })\n\n  describe('Deposit and withdraw with Fee', async() => {\n    let vaultId: BigNumber\n    it('should be able to set fee rate', async() => {\n      // set 1% fee\n      await controller.connect(owner).setFeeRate(100)\n      expect((await controller.feeRate()).eq(100)).to.be.true\n    })\n    it('should revert if vault is unable to pay fee amount from attach amount or vault collateral', async() => {\n      vaultId = await shortSqueeth.nextId()\n      const powerPerpToMint = ethers.utils.parseUnits('0.5')\n      await expect(controller.connect(random).mintPowerPerpAmount(0, powerPerpToMint, 0)).to.be.revertedWith('SafeMath: subtraction overflow')\n\n    })\n    it('should charge fee on mintPowerPerpAmount from deposit amount', async() => {\n      vaultId = await shortSqueeth.nextId()\n\n      const normFactor = await controller.normalizationFactor()\n\n      const powerPerpToMint = ethers.utils.parseUnits('0.5')\n      const collateralDeposited = ethers.utils.parseUnits('0.55')\n      const powerPerpInEth =  scaledSqueethPrice.mul(powerPerpToMint).mul(normFactor).div(one).div(one)\n      const expectedFee = powerPerpInEth.div(100)\n      const totalEthAttached = expectedFee.add(collateralDeposited)\n    \n      const feeRecipientBalanceBefore = await provider.getBalance(feeRecipient.address)\n\n      await controller.connect(random).mintPowerPerpAmount(0, powerPerpToMint, 0, { value: totalEthAttached })\n\n      const feeRecipientBalanceAfter = await provider.getBalance(feeRecipient.address)\n      const vault = await controller.vaults(vaultId)\n\n      expect(isSimilar(vault.collateralAmount.toString(),collateralDeposited.toString())).to.be.true\n      expect(isSimilar((feeRecipientBalanceAfter.sub(feeRecipientBalanceBefore)).toString(),(expectedFee.toString()))).to.be.true\n\n    })\n\n    it('should charge fee on mintPowerPerpAmount from vault collateral', async() => {\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const normFactor = await controller.normalizationFactor()\n\n      const powerPerpToMint = ethers.utils.parseUnits('0.5')\n      const powerPerpInEth =  scaledSqueethPrice.mul(powerPerpToMint).mul(normFactor).div(one).div(one)\n      const expectedFee = powerPerpInEth.div(100)\n    \n      const feeRecipientBalanceBefore = await provider.getBalance(feeRecipient.address)\n\n      await controller.connect(random).mintPowerPerpAmount(vaultId, powerPerpToMint, 0)\n\n      const feeRecipientBalanceAfter = await provider.getBalance(feeRecipient.address)\n      const vaultAfter = await controller.vaults(vaultId)\n\n      expect(isSimilar(vaultAfter.collateralAmount.toString(),((vaultBefore.collateralAmount).sub(expectedFee)).toString())).to.be.true\n      expect(isSimilar((feeRecipientBalanceAfter.sub(feeRecipientBalanceBefore)).toString(),(expectedFee.toString()))).to.be.true\n\n    })\n\n    it('should charge fee on mintWPowerPerpAmount from deposit amount', async() => {\n      vaultId = await shortSqueeth.nextId()\n\n      const wSqueethToMint = ethers.utils.parseUnits('0.1')\n      const collateralDeposited = ethers.utils.parseUnits('0.55')\n      \n      const feeRecipientBalanceBefore = await provider.getBalance(feeRecipient.address)\n\n      const powerPerpInEth =  scaledSqueethPrice.mul(wSqueethToMint).div(one)\n      const expectedFee = powerPerpInEth.div(100)\n      const totalEthAttached = expectedFee.add(collateralDeposited)\n\n      const now = await getNow(provider)\n      await provider.send(\"evm_setNextBlockTimestamp\", [now+1]) \n\n      await controller.connect(random).mintWPowerPerpAmount(0, wSqueethToMint, 0, { value: totalEthAttached })\n      \n\n      const feeRecipientBalanceAfter = await provider.getBalance(feeRecipient.address)\n      const vault = await controller.vaults(vaultId)\n\n      expect(isSimilar(vault.collateralAmount.toString(),collateralDeposited.toString())).to.be.true\n      expect(isSimilar((feeRecipientBalanceAfter.sub(feeRecipientBalanceBefore)).toString(),(expectedFee.toString()))).to.be.true\n\n    })\n\n    it('should charge fee on mintWPowerPerpAmount from vault collateral', async() => {\n\n      const vaultBefore = await controller.vaults(vaultId)\n      const wSqueethToMint = ethers.utils.parseUnits('0.1')\n    \n      const feeRecipientBalanceBefore = await provider.getBalance(feeRecipient.address)\n\n      await controller.connect(random).mintWPowerPerpAmount(vaultId, wSqueethToMint, 0)\n      \n      const powerPerpInEth =  scaledSqueethPrice.mul(wSqueethToMint).div(one)\n      const expectedFee = powerPerpInEth.div(100)\n\n      const feeRecipientBalanceAfter = await provider.getBalance(feeRecipient.address)\n      const vaultAfter = await controller.vaults(vaultId)\n\n      expect(isSimilar(vaultAfter.collateralAmount.toString(),((vaultBefore.collateralAmount).sub(expectedFee)).toString())).to.be.true\n      expect(isSimilar((feeRecipientBalanceAfter.sub(feeRecipientBalanceBefore)).toString(),(expectedFee.toString()))).to.be.true\n\n    })\n    after('set the fee back to 0', async() => {\n      await controller.connect(owner).setFeeRate(0)\n    })\n  })\n\n  describe(\"Settlement operations should be banned\", async () => {\n    it(\"Should revert when calling redeemLong\", async () => {\n      await expect(\n        controller.connect(seller1).redeemLong(0)\n      ).to.be.revertedWith(\"C3\");\n    });\n    it(\"Should revert when calling redeemShort\", async () => {\n      await expect(\n        controller.connect(seller1).redeemShort(1)\n      ).to.be.revertedWith(\"C3\");\n    });\n    it(\"Should revert when calling donate\", async () => {\n      await expect(\n        controller.connect(random).donate({value: 1})\n      ).to.be.revertedWith(\"C3\");\n    });\n  });\n  \n  describe(\"Emergency Shutdown and pausing\", function () {\n    const settlementPrice = BigNumber.from('10500').mul(one);\n    const scaledSettlementPrice = settlementPrice.div(oracleScaleFactor)\n    let seller2VaultId: BigNumber;\n    let seller3VaultId: BigNumber;\n\n    // seller 5 is the seller with nft as collateral\n    let seller5VaultId: BigNumber\n    const seller5NFTId = 1\n    \n    let seller3TotalSqueeth: BigNumber\n\n    let initialTick: string\n\n    const ethLiquidityAmount = ethers.utils.parseUnits('30')\n    const squeethLiquidityAmount = ethers.utils.parseUnits('100')\n    \n    let normalizationFactor: BigNumber\n    let wethIsToken0: boolean  \n    const collateralAmount = ethers.utils.parseEther('50')\n    \n\n    // seller 6 is the seller with nft with all squeeth\n    let seller6VaultId: BigNumber\n    const seller6NFTId = 2\n    const s6MintAmount = ethers.utils.parseUnits('0.0001')\n    const seller6Collateral = ethers.utils.parseEther('0.5')\n    \n    // seller 7 is the seller with no short\n    let seller7VaultId: BigNumber\n    const vault7Collateral = ethers.utils.parseEther('0.5')\n\n    // seller8 fail to settle short vault with nft in it, but able to reduceDebt\n    let seller8VaultId: BigNumber\n    const seller8NFTId = 3\n    \n\n    before('set LP token properties', async() => {\n      wethIsToken0 = parseInt(weth.address, 16) < parseInt(squeeth.address, 16)\n      const token0 = wethIsToken0 ? weth.address : squeeth.address\n      const token1 = wethIsToken0 ? squeeth.address : weth.address\n      const { sqrtPrice: sqrtX96Price, tick } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice, wethIsToken0)\n      initialTick = tick\n      await oracle.setAverageTick(squeethEthPool.address, tick)\n\n      \n      // infinite price range\n      const nftTickUpper = 887220\n      const nftTickLower = -887220\n      const liquidity = await vaultLib.getLiquidity(\n        sqrtX96Price,\n        nftTickLower,\n        nftTickUpper,\n        wethIsToken0 ? ethLiquidityAmount : squeethLiquidityAmount,\n        wethIsToken0 ? squeethLiquidityAmount: ethLiquidityAmount,\n      )\n      \n      await squeethEthPool.setSlot0Data(sqrtX96Price, initialTick)\n      await uniPositionManager.setMockedProperties(token0, token1, nftTickLower, nftTickUpper, liquidity)\n\n      // set amount getting out from position manager\n      const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, seller5NFTId, initialTick, wethIsToken0)\n      const token0ToSet = wethIsToken0 ? ethAmount : wPowerPerpAmount\n      const token1ToSet = wethIsToken0 ? wPowerPerpAmount : ethAmount\n      await uniPositionManager.setAmount0Amount1ToDecrease(token0ToSet, token1ToSet)\n\n      // minting 2x the amount of eth and squeeth as we have 2 nfts to test\n      await squeeth.mint(uniPositionManager.address, wPowerPerpAmount.mul(2));\n      await weth.deposit({value: ethAmount.mul(2)});\n      await weth.transfer(uniPositionManager.address, ethAmount.mul(2));\n\n      \n\n\n\n    })\n    \n    before('Prepare a new vault for this test set', async() => {\n      // prepare a vault that's gonna go underwater\n      seller2VaultId = await shortSqueeth.nextId()\n      const mintAmount = ethers.utils.parseUnits('100')\n      await controller.connect(seller2).mintPowerPerpAmount(0, mintAmount, 0, { value: collateralAmount })\n\n      // prepare a vault that's not gonna go insolvent\n      seller3VaultId = await shortSqueeth.nextId()\n      const s3MintAmount = ethers.utils.parseUnits('4')\n      await controller.connect(seller3).mintPowerPerpAmount(0, s3MintAmount, 0, { value: collateralAmount })\n      seller3TotalSqueeth = await squeeth.balanceOf(seller3.address)\n\n      // mint a lot of squeeth from seller1 that system can't payout to.\n      const collateral = ethers.utils.parseUnits('450')\n      await controller.connect(seller1).mintPowerPerpAmount(0, ethers.utils.parseUnits('1000'), 0, {value: collateral})\n\n      seller5VaultId = await shortSqueeth.nextId()\n      const s5MintAmount = ethers.utils.parseUnits('1')\n      // mint fake nft for seller5\n      await uniPositionManager.mint(seller5.address, seller5NFTId)\n      await uniPositionManager.connect(seller5).approve(controller.address, seller5NFTId)\n      await controller.connect(seller5).mintPowerPerpAmount(0, s5MintAmount, seller5NFTId, { value: collateralAmount })   \n\n      // prepare a vault with nft for seller 6\n      seller6VaultId = await shortSqueeth.nextId()\n\n      await uniPositionManager.mint(seller6.address, seller6NFTId)\n      await uniPositionManager.connect(seller6).approve(controller.address, seller6NFTId)\n      await controller.connect(seller6).mintWPowerPerpAmount(0, s6MintAmount, seller6NFTId, { value: seller6Collateral })      \n\n      // prepare a vault with no short for seller 7\n      seller7VaultId = await shortSqueeth.nextId()\n      await controller.connect(seller7).mintPowerPerpAmount(0, 0, 0, { value: vault7Collateral })      \n\n      // prepare an insolvent vault with nft (seller8)\n      seller8VaultId = await shortSqueeth.nextId()\n      const s8MintAmount = ethers.utils.parseUnits('133')\n      await uniPositionManager.mint(seller8.address, seller8NFTId)\n      await uniPositionManager.connect(seller8).approve(controller.address, seller8NFTId)\n      await controller.connect(seller8).mintPowerPerpAmount(0, s8MintAmount, seller8NFTId, { value: 0 })   \n      \n\n      normalizationFactor = await controller.normalizationFactor()\n    })\n\n    describe(\"Pause the system\", async () => {\n      let pausesLeft = 4;\n      it(\"Should revert when called by non-owner\", async () => {\n        await expect(\n          controller.connect(random).pause()\n        ).to.be.revertedWith(\"Ownable: caller is not the owner\");\n      });\n      it(\"Should revert when calling unpause before system is paused\", async () => {\n        await expect(\n          controller.connect(random).unPauseAnyone()\n        ).to.be.revertedWith(\"C1\");\n        await expect(\n          controller.connect(owner).unPauseOwner()\n        ).to.be.revertedWith(\"C1\");\n      });\n      it(\"Should allow owner to pause the system\", async () => {\n        await controller.connect(owner).pause()\n        pausesLeft-=1;\n        expect(await controller.isSystemPaused()).to.be.true;\n        expect((await controller.pausesLeft()).eq(pausesLeft)).to.be.true \n      })\n        // how to ensure that all variables are updated ie lastPauseTime, need block.timestamp here\n      it(\"Should revert when a random person tries to unpause immediately afterwards\", async () => {\n        await expect(\n          controller.connect(random).unPauseAnyone()\n        ).to.be.revertedWith(\"C18\");\n      });\n      it(\"Should allow the owner to un-pause\", async () => {\n        await controller.connect(owner).unPauseOwner()\n        expect(await controller.isSystemPaused()).to.be.false \n        expect((await controller.pausesLeft()).eq(pausesLeft)).to.be.true \n\n      });\n      it(\"Should allow the owner to re-pause\", async () => {\n        await controller.connect(owner).pause()\n        pausesLeft-=1;\n        expect(await controller.isSystemPaused()).to.be.true \n        expect((await controller.pausesLeft()).eq(pausesLeft)).to.be.true \n\n      });\n      it(\"Should allow the anyone to unpause after sufficient time has passed\", async () => {\n        await provider.send(\"evm_increaseTime\", [86400])\n        await provider.send(\"evm_mine\", [])\n        await controller.connect(random).unPauseAnyone()\n        expect(await controller.isSystemPaused()).to.be.false \n      });\n      it(\"Should allow the owner to re-pause\", async () => {\n        await controller.connect(owner).pause()\n        pausesLeft-=1;\n        expect(await controller.isSystemPaused()).to.be.true \n        expect((await controller.pausesLeft()).eq(pausesLeft)).to.be.true \n      });\n      it(\"Should revert when calling mintPowerPerpAmount\", async () => {\n        await expect(\n          controller.connect(seller1).mintPowerPerpAmount(0, 0, 0)\n        ).to.be.revertedWith(\"C0\");\n      });\n      it(\"Should revert when calling mintWPowerPerpAmount\", async () => {\n        await expect(\n          controller.connect(seller1).mintWPowerPerpAmount(0, 0, 0)\n        ).to.be.revertedWith(\"C0\");\n      });\n      it(\"Should revert when calling deposit\", async () => {\n        await expect(\n          controller.connect(seller1).deposit(1, { value: 1})\n        ).to.be.revertedWith(\"C0\");\n      });\n      it(\"Should revert when calling depositUniPositionToken\", async () => {\n        await expect(\n          controller.connect(seller1).depositUniPositionToken(1, 1,)\n        ).to.be.revertedWith(\"C0\");\n      });\n      it(\"Should revert when calling burnWPowerPerpAmount\", async () => {\n        await expect(\n          controller.connect(seller1).burnWPowerPerpAmount(1, 1, 1)\n        ).to.be.revertedWith(\"C0\");\n      });\n      it(\"Should revert when calling burnPowerPerpAmount\", async () => {\n        await expect(\n          controller.connect(seller1).burnPowerPerpAmount(1, 1, 1)\n        ).to.be.revertedWith(\"C0\");\n      });\n      it(\"Should revert when calling withdraw\", async () => {\n        await expect(\n          controller.connect(seller1).withdraw(1, 1)\n        ).to.be.revertedWith(\"C0\");\n      });\n      it(\"Should revert when calling withdrawUniPositionToken\", async () => {\n        await expect(\n          controller.connect(seller1).withdrawUniPositionToken(1)\n        ).to.be.revertedWith(\"C0\");\n      });\n      it(\"Should revert when calling reduceDebt\", async () => {\n        await expect(\n          controller.connect(seller1).reduceDebt(1)\n        ).to.be.revertedWith(\"C0\");\n      });\n      it(\"Should revert when calling applyFunding\", async () => {\n        await expect(\n          controller.connect(seller1).applyFunding()\n        ).to.be.revertedWith(\"C0\");\n      });\n      it(\"Should revert when calling liquidate\", async () => {\n        await expect(\n          controller.connect(seller1).liquidate(0, 0)\n        ).to.be.revertedWith(\"C0\");\n      });\n      it(\"Should revert when calling reduceDebt\", async () => {\n        await expect(\n          controller.connect(seller1).reduceDebt(0)\n        ).to.be.revertedWith(\"C0\");\n      });\n      \n      \n      it(\"Should allow the owner to un-pause\", async () => {\n        await controller.connect(owner).unPauseOwner()\n        expect(await controller.isSystemPaused()).to.be.false \n      });\n\n      it(\"Should revert when a random address tries to reduce debt on a NFT containing vault and the system isnt shut down\", async () => {\n        await expect(\n          controller.connect(random).reduceDebtShutdown(seller8NFTId)\n        ).to.be.revertedWith(\"C3\");\n      });\n      \n      it(\"Should allow the owner to re-pause\", async () => {\n        await controller.connect(owner).pause()\n        pausesLeft-=1;\n        expect(await controller.isSystemPaused()).to.be.true \n        expect((await controller.pausesLeft()).eq(pausesLeft)).to.be.true \n      });\n\n      it(\"Should revert if shutdown is called by non-owner\", async () => {\n        await expect(\n          controller.connect(random).shutDown()\n        ).to.be.revertedWith(\"Ownable: caller is not the owner\");\n      });\n\n      it(\"Should allow the owner to un-pause\", async () => {\n        await controller.connect(owner).unPauseOwner()\n        expect(await controller.isSystemPaused()).to.be.false \n      });\n\n      it(\"Should revert when a owner tries to pause the system after it has been paused 4 times before\", async () => {\n        await expect(\n          controller.connect(owner).pause()\n        ).to.be.revertedWith(\"C16\");\n      });\n    });\n    describe(\"Shut down the system using shutdown when it is unpaused\", async () => {\n      it(\"Should revert when called by non-owner\", async () => {\n        await expect(\n          controller.connect(random).shutDown()\n        ).to.be.revertedWith(\"Ownable: caller is not the owner\");\n      });\n      it(\"Should shutdown the system at a price that it will go insolvent\", async () => {\n        const ethPrice = settlementPrice\n\n        const { tick, sqrtPrice: newSqrtPrice } = getSqrtPriceAndTickBySqueethPrice(scaledSettlementPrice, wethIsToken0)\n        // update prices in pool and oracle.\n        const newTick = tick\n\n        const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, seller8NFTId, newTick, wethIsToken0)\n        const token0ToSet = wethIsToken0 ? ethAmount : wPowerPerpAmount\n        const token1ToSet = wethIsToken0 ? wPowerPerpAmount : ethAmount\n        await uniPositionManager.setAmount0Amount1ToDecrease(token0ToSet, token1ToSet)\n\n        await oracle.connect(random).setPrice(ethUSDPool.address , ethPrice) // eth per 1 squeeth\n\n        await squeethEthPool.setSlot0Data(newSqrtPrice, newTick)\n        await oracle.setPrice(squeethEthPool.address, scaledSettlementPrice)\n        await oracle.setAverageTick(squeethEthPool.address, newTick)\n        await oracle.setPrice(ethUSDPool.address, settlementPrice)\n\n        await controller.connect(owner).shutDown()\n        const snapshot = await controller.indexForSettlement();\n        expect(snapshot.toString()).to.be.eq(ethPrice.div(oracleScaleFactor))\n        expect(await controller.isShutDown()).to.be.true;\n        expect(await controller.isSystemPaused()).to.be.true;\n      });\n      it(\"Should revert when calling shutdown after system is shutdown\", async () => {\n        await expect(\n          controller.connect(owner).shutDown()\n        ).to.be.revertedWith(\"C2\");\n      });\n      it(\"Should revert when calling pause after system is shutdown\", async () => {\n        await expect(\n          controller.connect(owner).pause()\n        ).to.be.revertedWith(\"C2\");\n      });\n      it(\"Should revert when calling unPause after system is shutdown\", async () => {\n        await expect(\n          controller.connect(random).unPauseAnyone()\n        ).to.be.revertedWith(\"C2\");\n        await expect(\n          controller.connect(owner).unPauseOwner()\n        ).to.be.revertedWith(\"C2\");\n      });\n    });\n    describe(\"Settlement: redeemLong\", async () => {\n      it(\"should go insolvent while trying to redeem fair value for seller1 (big holder)\", async () => {\n        const seller1Amount = await squeeth.balanceOf(seller1.address)\n        await expect(\n          controller.connect(seller1).redeemLong(seller1Amount)\n        ).to.be.revertedWith(\"Address: insufficient balance\");\n      });\n      it(\"should accept donation from random address\", async() => {\n        const settleAmount = await squeeth.totalSupply()\n        const expectedPayout = settleAmount.mul(normalizationFactor).mul(settlementPrice).div(one).div(one)\n        const controllerEthBalance = await provider.getBalance(controller.address)\n        const donorBalance = await provider.getBalance(random.address)\n        const ethNeeded = expectedPayout.sub(controllerEthBalance) \n        const donateAmount = donorBalance.gt(ethNeeded) ?  ethNeeded : donorBalance \n        await controller.connect(random).donate({value: donateAmount})\n      })\n      it(\"should be able to redeem long value for seller2\", async () => {\n        const controllerEthBefore = await provider.getBalance(controller.address)\n        const sellerEthBefore = await provider.getBalance(seller2.address)\n        const redeemAmount = await squeeth.balanceOf(seller2.address)\n        await controller.connect(seller2).redeemLong(redeemAmount)\n        \n        // this test works because ES doesn't apply funding, so normalizationFactor won't change after shutdown\n        const expectedPayout = redeemAmount.mul(normalizationFactor).mul(settlementPrice).div(one).div(one).div(oracleScaleFactor)\n        const sellerEthAfter = await provider.getBalance(seller2.address)\n        const controllerEthAfter = await provider.getBalance(controller.address)\n        const squeethBalanceAfter = await squeeth.balanceOf(seller2.address)\n        expect(squeethBalanceAfter.isZero()).to.be.true\n        expect(controllerEthBefore.sub(controllerEthAfter).eq(expectedPayout)).to.be.true\n        // expect(sellerEthAfter.sub(sellerEthBefore).eq(expectedPayout)).to.be.true\n      });\n      it(\"should be able to redeem long value for seller3\", async () => {\n        const controllerEthBefore = await provider.getBalance(controller.address)\n        const sellerEthBefore = await provider.getBalance(seller3.address)\n        const redeemAmount = await squeeth.balanceOf(seller3.address)\n        await controller.connect(seller3).redeemLong(redeemAmount)\n        \n        // this test works because ES doesn't apply funding, so normalizationFactor won't change after shutdown\n        const expectedPayout = redeemAmount.mul(normalizationFactor).mul(settlementPrice).div(one).div(one).div(oracleScaleFactor)\n        const sellerEthAfter = await provider.getBalance(seller3.address)\n        const controllerEthAfter = await provider.getBalance(controller.address)\n        const squeethBalanceAfter = await squeeth.balanceOf(seller3.address)\n        expect(squeethBalanceAfter.isZero()).to.be.true\n        expect(controllerEthBefore.sub(controllerEthAfter).eq(expectedPayout)).to.be.true\n        // expect(sellerEthAfter.sub(sellerEthBefore).eq(expectedPayout)).to.be.true\n      });\n    })\n    describe('Settlement: redeemShort', async() => {\n      // stimulated LP deposits\n      let currentTick: string\n\n      before('set oracle prices', async() => {\n        wethIsToken0 = parseInt(weth.address, 16) < parseInt(squeeth.address, 16)\n        const { sqrtPrice: sqrtX96Price, tick } = getSqrtPriceAndTickBySqueethPrice(scaledSettlementPrice, wethIsToken0)\n        currentTick = tick\n        \n        await oracle.setAverageTick(squeethEthPool.address, currentTick)\n        await oracle.connect(random).setPrice(squeethEthPool.address, scaledSqueethPrice)\n\n        await oracle.connect(random).setPrice(ethUSDPool.address, scaledSettlementPrice)\n    \n        await squeethEthPool.setSlot0Data(sqrtX96Price, currentTick)\n\n        // set amount getting out from position manager\n        const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, seller5NFTId, currentTick, wethIsToken0)\n        const token0ToSet = wethIsToken0 ? ethAmount : wPowerPerpAmount\n        const token1ToSet = wethIsToken0 ? wPowerPerpAmount : ethAmount\n        await uniPositionManager.setAmount0Amount1ToDecrease(token0ToSet, token1ToSet)\n\n        // minting 2x the amount of eth and squeeth as we have 2 nfts to test\n        await squeeth.mint(uniPositionManager.address, wPowerPerpAmount.mul(5));\n        await weth.deposit({value: ethAmount.mul(5)});\n        await weth.transfer(uniPositionManager.address, ethAmount.mul(5));\n\n      })\n\n      it('should revert when a underwater vault (seller2) is trying to redeem', async() => {\n        await expect(\n          controller.connect(seller2).redeemShort(seller2VaultId)\n        ).to.be.revertedWith('SafeMath: subtraction overflow')\n      })\n\n      it('should revert when a underwater vault with nft (seller8) is trying to redeem', async() => {\n        await expect(\n          controller.connect(seller8).redeemShort(seller8VaultId)\n        ).to.be.revertedWith('SafeMath: subtraction overflow')\n      })\n\n\n      it(\"should allow anyone to reduceDebt in the insolvent vault\", async () => {\n        const vaultBefore = await controller.vaults(seller8VaultId)\n        const sellerEthBefore = await provider.getBalance(seller6.address)\n        const controllerEthBefore = await provider.getBalance(controller.address)\n        const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, seller8NFTId, currentTick, wethIsToken0)\n\n        await controller.connect(random).reduceDebtShutdown(seller8VaultId)\n        const vaultAfter = await controller.vaults(seller8VaultId)\n        const sellerEthAfter = await provider.getBalance(seller6.address)\n\n        const controllerEthAfter = await provider.getBalance(controller.address)\n        expect(vaultAfter.collateralAmount.sub(ethAmount).eq(vaultBefore.collateralAmount)).to.be.true\n        expect(vaultBefore.shortAmount.sub(wPowerPerpAmount).eq(vaultAfter.shortAmount)).to.be.true\n        expect(controllerEthAfter.sub(ethAmount).eq(controllerEthBefore)).to.be.true\n        expect(sellerEthBefore.eq(sellerEthAfter)).to.be.true\n      });\n\n      it('should still revert when a underwater vault with nft (seller8) is trying to redeem', async() => {\n        await expect(\n          controller.connect(seller8).redeemShort(seller8VaultId)\n        ).to.be.revertedWith('SafeMath: subtraction overflow')\n      })\n\n      it('should revert when a random user is trying to redeem', async() => {\n        await expect(\n          controller.connect(random).redeemShort(seller3VaultId)\n        ).to.be.revertedWith('C20')\n      })\n\n      it(\"should redeem fair value for normal vault (seller 3)\", async () => {\n        const vaultBefore = await controller.vaults(seller3VaultId)\n        const sellerEthBefore = await provider.getBalance(seller3.address)\n        const controllerEthBefore = await provider.getBalance(controller.address)\n\n        await controller.connect(seller3).redeemShort(seller3VaultId)\n        const vaultAfter = await controller.vaults(seller3VaultId)\n        \n        const squeethDebt = seller3TotalSqueeth.mul(normalizationFactor).mul(settlementPrice).div(one).div(one).div(oracleScaleFactor)\n        const shortPayout = vaultBefore.collateralAmount.sub(squeethDebt)\n        const sellerEthAfter = await provider.getBalance(seller3.address)\n        const controllerEthAfter = await provider.getBalance(controller.address)\n        expect(controllerEthBefore.sub(controllerEthAfter).eq(shortPayout)).to.be.true\n        // expect(sellerEthAfter.sub(sellerEthBefore).eq(shortPayout)).to.be.true\n        expect(isEmptyVault(vaultAfter)).to.be.true;\n      });\n\n      it(\"should redeem fair value for short side with uni v3 nft (seller 5)\", async () => {\n        const { ethAmount: nftEthAmount, wPowerPerpAmount: nftWSqueethAmount } = await vaultLib.getUniPositionBalances(uniPositionManager.address, seller5NFTId, currentTick, wethIsToken0)\n        const token0ToSet = wethIsToken0 ? nftEthAmount : nftWSqueethAmount\n        const token1ToSet = wethIsToken0 ? nftWSqueethAmount : nftEthAmount\n        await uniPositionManager.setAmount0Amount1ToDecrease(token0ToSet, token1ToSet)\n\n        const vaultBefore = await controller.vaults(seller5VaultId)\n        const sellerEthBefore = await provider.getBalance(seller5.address)\n        const squeethBalanceBefore = await squeeth.balanceOf(seller5.address)\n\n        await controller.connect(seller5).redeemShort(seller5VaultId)\n        const vaultAfter = await controller.vaults(seller5VaultId)\n        \n        const amountToReduceDebtBy = (vaultBefore.shortAmount < nftWSqueethAmount) ? vaultBefore.shortAmount : nftWSqueethAmount \n        const squeethDebt = vaultBefore.shortAmount.sub(amountToReduceDebtBy).mul(normalizationFactor).mul(settlementPrice).div(oracleScaleFactor).div(one).div(one)\n        const shortPayout = vaultBefore.collateralAmount.add(nftEthAmount).sub(squeethDebt)\n        const sellerEthAfter = await provider.getBalance(seller5.address)\n        \n        const squeethBalanceAfter = await squeeth.balanceOf(seller5.address)\n        \n        expect(squeethBalanceAfter.sub(squeethBalanceBefore).eq(nftWSqueethAmount.sub(amountToReduceDebtBy))).to.be.true\n        // expect(sellerEthAfter.sub(sellerEthBefore).eq(shortPayout)).to.be.true\n        expect(isEmptyVault(vaultAfter)).to.be.true;\n      });\n\n      it('set seller6 LP token properties', async() => {\n        // amount of wsqueeth worth is now 3x of amount needed\n        const lpWSqueethAmount = s6MintAmount.mul(3)\n        const lpWethAmount = BigNumber.from(0)\n        const token0ToSet = wethIsToken0 ? lpWethAmount : lpWSqueethAmount\n        const token1ToSet = wethIsToken0 ? lpWSqueethAmount : lpWethAmount\n        await uniPositionManager.setAmount0Amount1ToDecrease(token0ToSet, token1ToSet)\n\n        await squeeth.mint(uniPositionManager.address, lpWSqueethAmount);\n      })\n\n      it(\"should redeem fair value for seller 6 with one-sided nft\", async () => {\n        // nft has 3x wsqueeth minted\n        // redeemShort should remove the whole debt in vault\n        // and send the amount left (2/3) back to seller6 in wsqueeth\n        const vaultBefore = await controller.vaults(seller6VaultId)\n        const sellerEthBefore = await provider.getBalance(seller6.address)\n        const sellerWsqueethBefore = await squeeth.balanceOf(seller6.address)\n\n        await controller.connect(seller6).redeemShort(seller6VaultId)\n        const vaultAfter = await controller.vaults(seller6VaultId)\n        \n        const sellerEthAfter = await provider.getBalance(seller6.address)\n        const sellerWsqueethAfter = await squeeth.balanceOf(seller6.address)\n\n        // expect(sellerEthAfter.sub(sellerEthBefore).eq(vaultBefore.collateralAmount)).to.be.true\n        // get the remaining 2/3 (2x the initial minted amount) in wsqueeth\n        expect(sellerWsqueethAfter.sub(sellerWsqueethBefore).eq(s6MintAmount.mul(2))).to.be.true\n        expect(isEmptyVault(vaultAfter)).to.be.true;\n      });\n\n      it(\"should redeem fair value for short vault with no debt (seller7)\", async () => {\n        const sellerEthBefore = await provider.getBalance(seller7.address)\n\n        await controller.connect(seller7).redeemShort(seller7VaultId)\n        const vaultAfter = await controller.vaults(seller7VaultId)\n        \n        const sellerEthAfter = await provider.getBalance(seller7.address)\n\n        // expect(sellerEthAfter.sub(sellerEthBefore).eq(vault7Collateral)).to.be.true\n        expect(isEmptyVault(vaultAfter)).to.be.true;\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/hardhat/test/unit-tests/liquidation.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { BigNumber, providers } from \"ethers\";\nimport { Controller, MockWPowerPerp, MockShortPowerPerp, MockOracle, MockUniswapV3Pool, MockErc20, MockUniPositionManager, LiquidationHelper, ABDKMath64x64 } from \"../../typechain\";\nimport { isSimilar, one, oracleScaleFactor } from '../utils'\n\nconst squeethETHPrice = ethers.utils.parseUnits('3030').mul(one).div(oracleScaleFactor)\nconst ethUSDPrice = ethers.utils.parseUnits('3000')\n\n\n\ndescribe(\"Controller: liquidation unit test\", function () {\n  let squeeth: MockWPowerPerp;\n  let shortSqueeth: MockShortPowerPerp;\n  let controller: Controller;\n  let squeethEthPool: MockUniswapV3Pool;\n  let uniPositionManager: MockUniPositionManager\n  let ethUSDPool: MockUniswapV3Pool;\n  let oracle: MockOracle;\n  let weth: MockErc20;\n  let usdc: MockErc20;\n  let liquidationHelper: LiquidationHelper\n\n  let provider: providers.JsonRpcProvider;\n  let seller1: SignerWithAddress\n  let liquidator: SignerWithAddress\n  let random: SignerWithAddress\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_seller1, _liquidator, _random] = accounts;\n    seller1 = _seller1\n    liquidator = _liquidator\n    random = _random\n    provider = ethers.provider\n  })\n\n  this.beforeAll(\"Setup environment\", async () => {\n    const MockSQUContract = await ethers.getContractFactory(\"MockWPowerPerp\");\n    squeeth = (await MockSQUContract.deploy()) as MockWPowerPerp;\n\n    const NFTContract = await ethers.getContractFactory(\"MockShortPowerPerp\");\n    shortSqueeth = (await NFTContract.deploy()) as MockShortPowerPerp;\n\n    const OracleContract = await ethers.getContractFactory(\"MockOracle\");\n    oracle = (await OracleContract.deploy()) as MockOracle;\n\n    const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n    weth = (await MockErc20Contract.deploy(\"WETH\", \"WETH\", 18)) as MockErc20;\n    usdc = (await MockErc20Contract.deploy(\"USDC\", \"USDC\", 6)) as MockErc20;\n\n    const MockUniswapV3PoolContract = await ethers.getContractFactory(\"MockUniswapV3Pool\");\n    squeethEthPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n    ethUSDPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n\n    const MockPositionManager = await ethers.getContractFactory(\"MockUniPositionManager\");\n    uniPositionManager = (await MockPositionManager.deploy()) as MockUniPositionManager;\n\n    await squeethEthPool.setPoolTokens(weth.address, squeeth.address);\n    await ethUSDPool.setPoolTokens(weth.address, usdc.address);\n\n    await oracle.connect(random).setPrice(squeethEthPool.address , squeethETHPrice) // eth per 1 squeeth\n    await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPrice)  // usdc per 1 eth\n  });\n\n  describe(\"Deployment\", async () => {\n    it(\"Deployment\", async function () {\n      const ABDK = await ethers.getContractFactory(\"ABDKMath64x64\")\n      const ABDKLibrary = (await ABDK.deploy()) as ABDKMath64x64;\n    \n      const TickMathExternal = await ethers.getContractFactory(\"TickMathExternal\")\n      const TickMathLibrary = (await TickMathExternal.deploy());\n    \n      const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n      const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n  \n      const ControllerContract = await ethers.getContractFactory(\"Controller\", {libraries: {ABDKMath64x64: ABDKLibrary.address, TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n      controller = (await ControllerContract.deploy(oracle.address, shortSqueeth.address, squeeth.address, weth.address, usdc.address, ethUSDPool.address, squeethEthPool.address, uniPositionManager.address, 3000)) as Controller;\n      const squeethAddr = await controller.wPowerPerp();\n      const nftAddr = await controller.shortPowerPerp();\n      expect(squeethAddr).to.be.eq(\n        squeeth.address,\n        \"squeeth address mismatch\"\n      );\n      expect(nftAddr).to.be.eq(shortSqueeth.address, \"nft address mismatch\");\n    });\n    after('deploy liquidation helper', async() => {\n      const TickMathExternal = await ethers.getContractFactory(\"TickMathExternal\")\n      const TickMathLibrary = (await TickMathExternal.deploy());\n    \n      const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n      const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n      const LiqHelperFactory = await ethers.getContractFactory(\"LiquidationHelper\", {libraries: {TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n      liquidationHelper = await LiqHelperFactory.deploy(\n          controller.address,\n          oracle.address,\n          squeeth.address,\n          weth.address,\n          usdc.address,\n          ethUSDPool.address,\n          squeethEthPool.address,\n          uniPositionManager.address\n        ) as LiquidationHelper;  \n    })\n  });\n\n  describe(\"Liquidation\", async () => {\n    let vault1Id: BigNumber;\n\n    // small vault that will become a dust vault after liquidation\n    let vault2Id: BigNumber\n\n    // the new eth price that put vault underwater\n    let newEthUsdPrice: BigNumber\n    // the new squeeth price that determines the liquidator bounty\n    let newSqueethEthPrice: BigNumber\n\n    before(\"open vault 1\", async () => {\n      vault1Id = await shortSqueeth.nextId()\n\n      const depositAmount = ethers.utils.parseUnits('45')\n      const mintAmount = ethers.utils.parseUnits('100')\n        \n      const vaultBefore = await controller.vaults(vault1Id)\n      const squeethBalanceBefore = await squeeth.balanceOf(seller1.address)\n      \n      await controller.connect(seller1).mintPowerPerpAmount(0, mintAmount, 0, {value: depositAmount})\n\n      const squeethBalanceAfter = await squeeth.balanceOf(seller1.address)\n      const vaultAfter = await controller.vaults(vault1Id)\n      const normFactor = await controller.normalizationFactor()\n\n      expect(vaultBefore.shortAmount.add(mintAmount.mul(one).div(normFactor)).eq(vaultAfter.shortAmount)).to.be.true\n      expect(squeethBalanceBefore.add(mintAmount.mul(one).div(normFactor)).eq(squeethBalanceAfter)).to.be.true\n    });\n\n    before(\"open vault 2\", async () => {\n      vault2Id = await shortSqueeth.nextId()\n\n      const depositAmount = ethers.utils.parseUnits('0.9')\n      const mintAmount = ethers.utils.parseUnits('2')\n        \n      const vaultBefore = await controller.vaults(vault2Id)\n      const squeethBalanceBefore = await squeeth.balanceOf(seller1.address)\n      \n      await controller.connect(seller1).mintPowerPerpAmount(0, mintAmount, 0, {value: depositAmount})\n\n      const squeethBalanceAfter = await squeeth.balanceOf(seller1.address)\n      const vaultAfter = await controller.vaults(vault2Id)\n      const normFactor = await controller.normalizationFactor()\n      expect(await controller.isVaultSafe(vault2Id)).to.be.true\n      expect(vaultBefore.shortAmount.add(mintAmount.mul(one).div(normFactor)).eq(vaultAfter.shortAmount)).to.be.true\n      expect(squeethBalanceBefore.add(mintAmount.mul(one).div(normFactor)).eq(squeethBalanceAfter)).to.be.true\n\n      // give all wsqueeth to liquidator\n      await squeeth.connect(seller1).transfer(liquidator.address, squeethBalanceAfter)\n    });\n\n    it(\"Should revert liquidating a a vault with id 0\", async () => {\n      const result = await liquidationHelper.checkLiquidation(0);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      expect(isUnsafe).to.be.false\n      expect(isLiquidatableAfterReducingDebt).to.be.false\n      expect(maxWPowerPerpAmount.eq(BigNumber.from(0))).to.be.true\n      expect(collateralToReceive.eq(BigNumber.from(0))).to.be.true\n\n      await expect(controller.connect(liquidator).liquidate(0, 1)).to.be.revertedWith(\n        'C12'\n      )\n    })\n\n    it(\"Should revert liquidating a a vault with id greater than max vaults\", async () => {\n      const vaultId = await shortSqueeth.nextId()\n      const result = await liquidationHelper.checkLiquidation(vaultId);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      expect(isUnsafe).to.be.false\n      expect(isLiquidatableAfterReducingDebt).to.be.false\n      expect(maxWPowerPerpAmount.eq(BigNumber.from(0))).to.be.true\n      expect(collateralToReceive.eq(BigNumber.from(0))).to.be.true\n\n      await expect(controller.connect(liquidator).liquidate(vaultId, 1)).to.be.revertedWith(\n        'C12'\n      )\n    })\n\n    it(\"Should revert liquidating a safe vault\", async () => {\n      const vaultBefore = await controller.vaults(vault1Id)\n\n      // liquidator mint wSqueeth\n      await squeeth.connect(liquidator).mint(liquidator.address, vaultBefore.shortAmount)\n\n      const result = await liquidationHelper.checkLiquidation(vault1Id);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      expect(isUnsafe).to.be.false\n      expect(isLiquidatableAfterReducingDebt).to.be.false\n      expect(maxWPowerPerpAmount.eq(BigNumber.from(0))).to.be.true\n      expect(collateralToReceive.eq(BigNumber.from(0))).to.be.true\n\n      await expect(controller.connect(liquidator).liquidate(vault1Id, vaultBefore.shortAmount)).to.be.revertedWith(\n        'C12'\n      )\n    })\n\n    it('set eth price to make the vault underwater', async() => {\n      newEthUsdPrice = BigNumber.from(4000).mul(one)\n      newSqueethEthPrice = BigNumber.from(4040).mul(one).div(oracleScaleFactor)\n      await oracle.connect(random).setPrice(ethUSDPool.address, newEthUsdPrice)\n      await oracle.connect(random).setPrice(squeethEthPool.address, newSqueethEthPrice)\n\n    })\n    it(\"should revert if the vault become a dust vault after liquidation\", async () => {\n      const vaultBefore = await controller.vaults(vault2Id)\n      const debtToRepay = vaultBefore.shortAmount.sub(1) // not burning all the the short\n\n      const debtShouldRepay = vaultBefore.shortAmount\n      let collateralToSell : BigNumber = newSqueethEthPrice.mul(debtShouldRepay).div(one)\n      collateralToSell = collateralToSell.add(collateralToSell.div(10))\n\n      const result = await liquidationHelper.checkLiquidation(vault2Id);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.true\n      expect(maxWPowerPerpAmount.eq(debtShouldRepay)).to.be.true\n      expect(isSimilar(collateralToReceive.toString(), collateralToSell.toString())).to.be.true\n\n      await expect(controller.connect(liquidator).liquidate(vault2Id, debtToRepay)).to.be.revertedWith('C22');\n    })\n    it(\"should allow liquidating a whole vault if only liquidating half of it is gonna make it a dust vault\", async () => {\n      const vaultBefore = await controller.vaults(vault2Id)\n      const debtToRepay = vaultBefore.shortAmount\n            \n      let collateralToSell : BigNumber = newSqueethEthPrice.mul(debtToRepay).div(one)\n      collateralToSell = collateralToSell.add(collateralToSell.div(10))\n\n      const result = await liquidationHelper.checkLiquidation(vault2Id);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.true\n      expect(maxWPowerPerpAmount.eq(vaultBefore.shortAmount)).to.be.true\n      expect(isSimilar(collateralToReceive.toString(), collateralToSell.toString())).to.be.true\n\n      await controller.connect(liquidator).liquidate(vault2Id, debtToRepay)\n\n      const vaultAfter = await controller.vaults(vault2Id)\n      expect(vaultAfter.shortAmount.isZero()).to.be.true\n\n    })\n\n    it(\"Liquidate unsafe vault (vault 1)\", async () => {\n      const vaultBefore = await controller.vaults(vault1Id)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n      const squeethLiquidatorBalanceBefore = await squeeth.balanceOf(liquidator.address)\n\n      const isVaultSafeBefore = await controller.isVaultSafe(vault1Id)\n      expect(isVaultSafeBefore).to.be.false\n\n      const debtToRepay = vaultBefore.shortAmount.div(2)\n\n      const result = await liquidationHelper.checkLiquidation(vault1Id);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      // specifying a higher maxDebtToRepay number, which won't be used\n      const maxDebtToRepay = debtToRepay.add(10)\n      const tx = await controller.connect(liquidator).liquidate(vault1Id, maxDebtToRepay);\n      const receipt = await tx.wait();\n      \n      let collateralToSell : BigNumber = newSqueethEthPrice.mul(debtToRepay).div(one)\n      collateralToSell = collateralToSell.add(collateralToSell.div(10))\n\n      const vaultAfter = await controller.vaults(vault1Id)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const liquidateEventCollateralToSell : BigNumber = (receipt.events?.find(event => event.event === 'Liquidate'))?.args?.collateralPaid;\n      const squeethLiquidatorBalanceAfter = await squeeth.balanceOf(liquidator.address)\n\n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.true\n      expect(maxWPowerPerpAmount.eq(debtToRepay)).to.be.true\n      expect(isSimilar(collateralToReceive.toString(), collateralToSell.toString())).to.be.true\n\n      expect(isSimilar(liquidatorBalanceAfter.sub(liquidatorBalanceBefore).toString(), collateralToSell.toString())).to.be.true\n      expect(liquidateEventCollateralToSell.eq(collateralToSell)).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(debtToRepay)).to.be.true\n      expect(vaultBefore.collateralAmount.sub(vaultAfter.collateralAmount).eq(collateralToSell)).to.be.true\n      expect(squeethLiquidatorBalanceBefore.sub(squeethLiquidatorBalanceAfter).eq(debtToRepay)).to.be.true\n    })\n  })\n\n  describe(\"Liquidation: un-profitable scenario\", async () => {\n    let vaultId: BigNumber;\n    const newSqueethETHPrice = ethers.utils.parseUnits('9090').mul(one).div(oracleScaleFactor)\n    const newEthUSDPrice = ethers.utils.parseUnits('9000')\n    \n    before(\"open vault\", async () => {\n      const oldEthPrice = BigNumber.from('3000').mul(one)\n      await oracle.connect(random).setPrice(ethUSDPool.address, oldEthPrice)\n      vaultId = await shortSqueeth.nextId()\n      const depositAmount = ethers.utils.parseUnits('45')\n      const mintAmount = ethers.utils.parseUnits('100')\n      await controller.connect(seller1).mintPowerPerpAmount(0, mintAmount, 0, {value: depositAmount})\n    });\n    \n    before(\"set price to a number where vault will become insolvent\", async () => {\n      // change oracle price to make vault liquidatable\n      await oracle.connect(random).setPrice(ethUSDPool.address, newEthUSDPrice)\n      await oracle.connect(random).setPrice(squeethEthPool.address, newSqueethETHPrice)\n      \n    })\n\n    it(\"should revert if the vault is paying out all collateral, but there are still debt\", async () => {\n      const vault = await controller.vaults(vaultId)\n      // liquidator specify amount that would take all collateral, but not clearing all the debt\n      const debtToRepay = vault.shortAmount.sub(1)\n\n      let collateralToSell : BigNumber = newSqueethETHPrice.mul(debtToRepay).div(one)\n      collateralToSell = collateralToSell.add(collateralToSell.div(10))\n\n      const result = await liquidationHelper.checkLiquidation(vaultId);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      expect(collateralToSell.gt(vault.collateralAmount)).to.be.true\n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.true\n      expect(maxWPowerPerpAmount.eq(vault.shortAmount)).to.be.true\n      expect(isSimilar(collateralToReceive.toString(), vault.collateralAmount.toString())).to.be.true\n\n      await expect(controller.connect(liquidator).liquidate(vaultId, debtToRepay)).to.be.revertedWith('C21');\n    })\n\n    it(\"can fully liquidate a underwater vault, even it's not profitable\", async () => {\n      const vaultBefore = await controller.vaults(vaultId)\n      const liquidatorBalanceBefore = await provider.getBalance(liquidator.address)\n      const squeethLiquidatorBalanceBefore = await squeeth.balanceOf(liquidator.address)\n\n      const result = await liquidationHelper.checkLiquidation(vaultId);\n      const [isUnsafe, isLiquidatableAfterReducingDebt, maxWPowerPerpAmount, collateralToReceive] = result;\n\n      // fully liquidate a vault\n      const debtToRepay = vaultBefore.shortAmount\n      const tx = await controller.connect(liquidator).liquidate(vaultId, debtToRepay);\n      const receipt = await tx.wait();\n      \n      let collateralToSell : BigNumber = newSqueethETHPrice.mul(debtToRepay).div(one)\n      collateralToSell = collateralToSell.add(collateralToSell.div(10))\n\n      // paying this amount will reduce total eth \n      expect(collateralToSell.gt(vaultBefore.collateralAmount)).to.be.true\n\n      expect(collateralToSell.gt(vaultBefore.collateralAmount)).to.be.true\n      expect(isUnsafe).to.be.true\n      expect(isLiquidatableAfterReducingDebt).to.be.true\n      expect(maxWPowerPerpAmount.eq(vaultBefore.shortAmount)).to.be.true\n      expect(isSimilar(collateralToReceive.toString(), vaultBefore.collateralAmount.toString())).to.be.true\n\n      const vaultAfter = await controller.vaults(vaultId)\n      const liquidatorBalanceAfter = await provider.getBalance(liquidator.address)\n      const actualAmountPaidForLiquidator : BigNumber = (receipt.events?.find(event => event.event === 'Liquidate'))?.args?.collateralPaid;\n      const squeethLiquidatorBalanceAfter = await squeeth.balanceOf(liquidator.address)\n\n      expect(vaultAfter.collateralAmount.isZero()).to.be.true\n      expect(isSimilar(liquidatorBalanceAfter.sub(liquidatorBalanceBefore).toString(), actualAmountPaidForLiquidator.toString())).to.be.true\n      expect(vaultBefore.shortAmount.sub(vaultAfter.shortAmount).eq(debtToRepay)).to.be.true\n      expect(vaultBefore.collateralAmount.eq(actualAmountPaidForLiquidator)).to.be.true\n      expect(squeethLiquidatorBalanceBefore.sub(squeethLiquidatorBalanceAfter).eq(debtToRepay)).to.be.true\n    })\n  })\n});"
  },
  {
    "path": "packages/hardhat/test/unit-tests/oracle-token-decimals.ts",
    "content": "import { ethers, getNamedAccounts, deployments } from \"hardhat\"\nimport { expect } from \"chai\";\nimport BigNumber, { BigNumber as BigNumberJs } from \"bignumber.js\";\nimport {\n  abi as SWAP_ROUTER_ABI,\n  bytecode as SWAP_ROUTER_BYTECODE,\n} from '@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json'\nimport {\n  abi as POSITION_MANAGER_ABI,\n  bytecode as POSITION_MANAGER_BYTECODE,\n} from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'\nimport {\n  abi as FACTORY_ABI,\n  bytecode as FACTORY_BYTECODE,\n} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json'\nimport { Contract } from \"ethers\";\nimport { convertToken0PriceToSqrtX96Price } from '../calculator'\nimport { isSimilar } from '../utils'\nimport { Oracle, MockErc20 } from \"../../typechain\";\n\ndescribe(\"Oracle\", function () {\n  const ethRawPrice = 2000; // target eth price in USD\n  const ethRawPrice1e18 = (ethRawPrice * 1e18).toString()\n  const provider = ethers.provider;\n  \n  let weth: MockErc20\n  let usdc: MockErc20 // USD token with 6 decimals\n  let randomUSD: MockErc20 // rUSD token with 20 decimals\n\n  let oracle: Oracle;\n  let positionManager: Contract\n  let uniswapFactory: Contract\n\n  let wethUSDPool1: Contract\n  let wethUSDPool2: Contract\n  let deployer: string\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const { deployer: _deployer } = await getNamedAccounts();\n    deployer = _deployer\n\n    const { deploy } = deployments;\n  \n    await deploy(\"UniswapV3Factory\", {\n      from: deployer,\n      contract: {\n        abi: FACTORY_ABI,\n        bytecode: FACTORY_BYTECODE\n      }\n    });\n    uniswapFactory = await ethers.getContract(\"UniswapV3Factory\", deployer);\n    \n  \n    const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n    usdc = (await MockErc20Contract.deploy(\"USDC\", \"USDC\", 6)) as MockErc20;\n    weth = (await MockErc20Contract.deploy(\"WETH\", \"WETH\", 18)) as MockErc20;\n    randomUSD = (await MockErc20Contract.deploy(\"rUSD\", \"rUSD\", 20)) as MockErc20;\n\n    await deploy(\"SwapRouter\", {\n      from: deployer,\n      contract: {\n        abi: SWAP_ROUTER_ABI,\n        bytecode: SWAP_ROUTER_BYTECODE\n      },\n      args: [uniswapFactory.address, weth.address]\n    });\n  \n    // tokenDescriptor is only used to query tokenURI() on NFT. Don't need that in our deployment\n    const tokenDescriptorAddress = ethers.constants.AddressZero\n    await deploy(\"NonfungibleTokenPositionManager\", {\n      from: deployer,\n      contract: {\n        abi: POSITION_MANAGER_ABI,\n        bytecode: POSITION_MANAGER_BYTECODE,\n      },\n      args: [uniswapFactory.address, weth.address, tokenDescriptorAddress]\n    });\n    positionManager = await ethers.getContract(\"NonfungibleTokenPositionManager\", deployer);\n\n    \n    // deploy oracle\n    oracle = (await (await ethers.getContractFactory(\"Oracle\")).deploy()) as Oracle;\n  })\n\n  \n\n  describe(\"ETH/USD pool\", async () => {\n\n    before('setup weth/usdc pool', async() => {\n      const isUSDToken0 = parseInt(usdc.address, 16) < parseInt(weth.address, 16)\n  \n      const weiPriceInUSDCWei = new BigNumber(ethRawPrice).div(new BigNumber(10).pow(18 - 6))\n\n      const sqrtX96Price = isUSDToken0 \n        ? convertToken0PriceToSqrtX96Price((new BigNumber(1).div(weiPriceInUSDCWei)).toString()).toFixed(0)\n        : convertToken0PriceToSqrtX96Price(weiPriceInUSDCWei.toString()).toFixed(0)\n\n      const token0 = isUSDToken0 ? usdc.address : weth.address\n      const token1 = isUSDToken0 ? weth.address : usdc.address\n  \n      await positionManager.createAndInitializePoolIfNecessary(\n        token0,\n        token1,\n        3000, // fee = 0.3%\n        sqrtX96Price\n      )\n  \n  \n      // set pool\n      const wethPool1 = await uniswapFactory.getPool(token0, token1, 3000)\n      wethUSDPool1 = await ethers.getContractAt(\"IUniswapV3Pool\", wethPool1);\n\n    })\n\n    before('increase storage slot', async() => {\n      // increase storage slot to 16\n      await wethUSDPool1.increaseObservationCardinalityNext(16)\n      await provider.send(\"evm_increaseTime\", [30])\n      await provider.send(\"evm_mine\", [])\n    })\n\n    it(\"should return initial price with period = 1\", async () => {\n      const price = new BigNumberJs((await oracle.getTwap(wethUSDPool1.address, weth.address, usdc.address, 1, true)).toString())\n      expect(isSimilar(price.toString(), ethRawPrice1e18)).to.be.true;\n    })\n\n    it(\"should return correct price with safe twap\", async () => {\n      const price = new BigNumberJs((await oracle.getTwap(wethUSDPool1.address, weth.address, usdc.address, 86400, true)).toString())\n      expect(isSimilar(price.toString(), ethRawPrice1e18)).to.be.true;\n    })\n  })\n\n  describe(\"ETH/rUSD pool\", async () => {\n\n    before('setup weth/rUsdc pool', async() => {\n      const isUSDToken0 = parseInt(randomUSD.address, 16) < parseInt(weth.address, 16)\n  \n      const weiPriceInRUSDCWei = new BigNumber(ethRawPrice).times(new BigNumber(10).pow(20 - 18))\n\n      const sqrtX96Price = isUSDToken0 \n        ? convertToken0PriceToSqrtX96Price((new BigNumber(1).div(weiPriceInRUSDCWei)).toString()).toFixed(0)\n        : convertToken0PriceToSqrtX96Price(weiPriceInRUSDCWei.toString()).toFixed(0)\n\n      const token0 = isUSDToken0 ? randomUSD.address : weth.address\n      const token1 = isUSDToken0 ? weth.address : randomUSD.address\n  \n      await positionManager.createAndInitializePoolIfNecessary(\n        token0,\n        token1,\n        3000, // fee = 0.3%\n        sqrtX96Price\n      )\n  \n      // set pool\n      const wethPool1 = await uniswapFactory.getPool(token0, token1, 3000)\n      wethUSDPool2 = await ethers.getContractAt(\"IUniswapV3Pool\", wethPool1);\n\n    })\n\n    before('increase storage slot', async() => {\n      // increase storage slot to 16\n      await wethUSDPool2.increaseObservationCardinalityNext(16)\n      await provider.send(\"evm_increaseTime\", [30])\n      await provider.send(\"evm_mine\", [])\n    })\n\n    it(\"should return initial price with period = 1\", async () => {\n      const price = new BigNumberJs((await oracle.getTwap(wethUSDPool2.address, weth.address, randomUSD.address, 1, false)).toString())\n      expect(isSimilar(price.toString(), ethRawPrice1e18)).to.be.true;\n    })\n\n    it(\"should return correct price with safe twap\", async () => {\n      const price = new BigNumberJs((await oracle.getTwap(wethUSDPool2.address, weth.address, randomUSD.address, 86400, true)).toString())\n      expect(isSimilar(price.toString(), ethRawPrice1e18)).to.be.true;\n    })\n  })\n\n})\n"
  },
  {
    "path": "packages/hardhat/test/unit-tests/oracle.ts",
    "content": "import { ethers, getNamedAccounts, deployments } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { constants, Contract } from \"ethers\";\nimport { BigNumber as BigNumberJs } from \"bignumber.js\";\nimport {\n  abi as SWAP_ROUTER_ABI,\n  bytecode as SWAP_ROUTER_BYTECODE,\n} from '@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json'\nimport {\n  abi as POSITION_MANAGER_ABI,\n  bytecode as POSITION_MANAGER_BYTECODE,\n} from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'\nimport {\n  abi as FACTORY_ABI,\n  bytecode as FACTORY_BYTECODE,\n} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json'\nimport { convertToken0PriceToSqrtX96Price, tickToPrice1e18 } from '../calculator'\nimport { getNow, isSimilar } from '../utils'\nimport { Oracle, MockWPowerPerp, OracleTester, WETH9, ISwapRouter, IUniswapV3Pool } from \"../../typechain\";\n\ndescribe(\"Oracle\", function () {\n  const squeethPriceInETH = 2000; // can sell 1 squeeth for 2000 eth\n  let initPriceTick: number\n  let isWethToken0: boolean\n\n  const squeethPriceInETH1e18 = (squeethPriceInETH * 1e18).toString()\n  const provider = ethers.provider;\n  \n  let squeeth: MockWPowerPerp;\n  let oracle: Oracle;\n  let positionManager: Contract\n  let oracleTester: OracleTester\n  let squeethPool: IUniswapV3Pool\n  let deployer: string\n  let swapRouter: ISwapRouter\n  // store list of timestamp that's the pool is touched. [0] = init time, [1] = first interaction ...\n  const interactionTimestamps: number[] = []\n\n  let weth: WETH9\n\n  this.beforeAll(\"Deploy uniswap protocol & setup uniswap pool\", async() => {\n    const { deployer: _deployer } = await getNamedAccounts();\n    deployer = _deployer\n\n    const { deploy } = deployments;\n  \n    await deploy(\"UniswapV3Factory\", {\n      from: deployer,\n      contract: {\n        abi: FACTORY_ABI,\n        bytecode: FACTORY_BYTECODE\n      }\n    });\n    const uniswapFactory = await ethers.getContract(\"UniswapV3Factory\", deployer);\n    \n    await deploy(\"WETH9\", { from: deployer });\n    weth = await ethers.getContract(\"WETH9\", deployer) as WETH9;\n  \n    const tx = await deploy(\"SwapRouter\", {\n      from: deployer,\n      contract: {\n        abi: SWAP_ROUTER_ABI,\n        bytecode: SWAP_ROUTER_BYTECODE\n      },\n      args: [uniswapFactory.address, weth.address]\n    });\n\n    swapRouter = await ethers.getContractAt('ISwapRouter', tx.address)\n  \n    // tokenDescriptor is only used to query tokenURI() on NFT. Don't need that in our deployment\n    const tokenDescriptorAddress = ethers.constants.AddressZero\n    await deploy(\"NonfungibleTokenPositionManager\", {\n      from: deployer,\n      contract: {\n        abi: POSITION_MANAGER_ABI,\n        bytecode: POSITION_MANAGER_BYTECODE,\n      },\n      args: [uniswapFactory.address, weth.address, tokenDescriptorAddress]\n    });\n    positionManager = await ethers.getContract(\"NonfungibleTokenPositionManager\", deployer);\n\n    // Create ETH/SQUEETH Pool with positionManager\n    squeeth = (await (await ethers.getContractFactory(\"MockWPowerPerp\")).deploy()) as MockWPowerPerp;\n    isWethToken0 = parseInt(weth.address, 16) < parseInt(squeeth.address, 16)\n    \n\n    const sqrtX96Price = isWethToken0 \n      ? convertToken0PriceToSqrtX96Price((new BigNumberJs(1).div(squeethPriceInETH)).toString()).toFixed(0)\n      : convertToken0PriceToSqrtX96Price(squeethPriceInETH.toString()).toFixed(0)\n     \n\n    const token0 = isWethToken0 ? weth.address : squeeth.address\n    const token1 = isWethToken0 ? squeeth.address : weth.address\n\n    // https://docs.uniswap.org/protocol/reference/periphery/base/PoolInitializer\n    const res = await positionManager.createAndInitializePoolIfNecessary(\n      token0,\n      token1,\n      3000, // fee = 0.3%\n      sqrtX96Price\n    )\n\n\n    // keep track of init block timestamp\n    const initBlockNumber = res.blockNumber\n    const block = await provider.getBlock(initBlockNumber)\n    // add init timestamp to array\n    interactionTimestamps.push(block.timestamp)\n\n    // set pool\n    const squeethPoolAddr = await uniswapFactory.getPool(token0, token1, 3000)\n    squeethPool = await ethers.getContractAt(\"IUniswapV3Pool\", squeethPoolAddr);\n    initPriceTick = (await squeethPool.slot0()).tick\n    const cardinality = (await squeethPool.slot0()).observationCardinality\n\n    // the cardinality will be started with 1\n    expect(cardinality).to.be.eq(1)\n\n    // deploy oracle\n    oracle = (await (await ethers.getContractFactory(\"Oracle\")).deploy()) as Oracle;\n\n    await deploy(\"OracleTester\", { args: [oracle.address], from: deployer })\n    oracleTester = (await (await ethers.getContractFactory(\"OracleTester\")).deploy(oracle.address)) as OracleTester;\n  })\n\n  describe(\"Fetch price right after initialization\", async () => {\n    it(\"should return initial price with period = 1\", async () => {\n      const price = new BigNumberJs((await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, 1, false)).toString())\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n    it('should be able to get TWAP since init time', async() => {\n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSince(interactionTimestamps[0], squeethPool.address, squeeth.address, weth.address))\n        .toString())\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n    it('should be able to get TWAP since init time after time goes by', async() => {\n      await provider.send(\"evm_increaseTime\", [50]) // go 50 seconds minutes\n      await provider.send(\"evm_mine\", [])\n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSince(interactionTimestamps[0], squeethPool.address, squeeth.address, weth.address))\n        .toString())\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n    it(\"should revert if trying to request twap since a time before initialization\", async () => {\n      await expect(\n        oracleTester.testGetTwapSince(interactionTimestamps[0] - 1, squeethPool.address, squeeth.address, weth.address)\n      ).to.be.revertedWith(\"OLD\");\n    })\n\n    it(\"should NOT revert if trying to request twap since a time before initialization, with #getTwapSafe\", async () => {\n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSafeSince(interactionTimestamps[0] - 1, squeethPool.address, squeeth.address, weth.address)\n      ).toString());\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n    it('should return max period', async() => {\n      const period = await oracle.getMaxPeriod(squeethPool.address)\n      const now = await getNow(provider)\n      expect(interactionTimestamps[0] + period === now).to.be.true\n    })\n  })\n  \n  describe(\"Fetch price after touching the pool\", async () => {\n    before('add liquidity to the pool', async() => {\n      const squeethAmount = 1\n      const wethAmount = squeethPriceInETH * squeethAmount\n\n      const liquiditySqueethAmount = ethers.utils.parseEther(squeethAmount.toString())\n      const liquidityWethAmount = ethers.utils.parseEther(wethAmount.toString())\n\n      await squeeth.mint(deployer, liquiditySqueethAmount)\n      await weth.deposit({value: liquidityWethAmount})\n\n      await weth.approve(positionManager.address, ethers.constants.MaxUint256)\n      await squeeth.approve(positionManager.address, ethers.constants.MaxUint256)\n      \n      const token0 = isWethToken0 ? weth.address : squeeth.address\n      const token1 = isWethToken0 ? squeeth.address : weth.address\n\n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? liquidityWethAmount : liquiditySqueethAmount,\n        amount1Desired: isWethToken0 ? liquiditySqueethAmount : liquidityWethAmount,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: deployer,// address\n        deadline: await getNow(provider) + 86400\n      }\n      const res = await positionManager.mint(mintParam)\n      const addLiquidityBlock = res.blockNumber\n      const block = await provider.getBlock(addLiquidityBlock)\n      interactionTimestamps.push(block.timestamp)\n\n      \n    })\n    it('should revert if requesting TWAP from init timestamp', async() => {\n      await expect(\n        oracleTester.testGetTwapSince(interactionTimestamps[0], squeethPool.address, squeeth.address, weth.address)\n      ).to.be.revertedWith(\"OLD\");\n    })\n    // todo: Fix this!\n    // it will be good if the test fail in the future, which means that we solve this potential bug.\n    it(\"should be fix in the future: if first observation is updated in the same block, the max duration will be 0 causing the library to revert.\", async () => {\n      await expect(\n        oracleTester.testGetTwapSafeSince(interactionTimestamps[0], squeethPool.address, squeeth.address, weth.address)\n      ).to.be.revertedWith(\"BP\"); // revert by OracleLibrary.\n    })\n    it(\"should NOT revert if requesting TWAP from init timestamp, with #getTwapSafe\", async () => {\n      // fix view function stimulation on hardhat that the blocktime will be same as latest block\n      // causing max period to request = 0;\n      await provider.send(\"evm_mine\", [])\n      \n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSafeSince(interactionTimestamps[0], squeethPool.address, squeeth.address, weth.address)\n      ).toString());\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n    it(\"should NOT revert if requesting time weighted tick from init timestamp, with #getWeightedTickSafe\", async () => {\n      const tick = await oracleTester.testGetWeightedTickSafe(interactionTimestamps[0], squeethPool.address, )\n      expect(initPriceTick === tick).to.be.true\n    })\n    it('should be able to get TWAP since last touch', async() => {\n      await provider.send(\"evm_increaseTime\", [50]) // go 50 seconds minutes\n      await provider.send(\"evm_mine\", [])\n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSince(interactionTimestamps[1], squeethPool.address, squeeth.address, weth.address))\n        .toString())\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n    it(\"should revert if trying to request twap since a time before last touch\", async () => {\n      await expect(\n        oracleTester.testGetTwapSince(interactionTimestamps[1] - 1, squeethPool.address, squeeth.address, weth.address)\n      ).to.be.revertedWith(\"OLD\");\n    })\n    it(\"should NOT revert if trying to request twap since a time before last touch, with #getTwapSafe\", async () => {\n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSafeSince(interactionTimestamps[1] - 1, squeethPool.address, squeeth.address, weth.address)\n      ).toString());\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n    it(\"should NOT revert if trying to request average tick since a time before last touch, with #testGetWeightedTickSafe\", async () => {\n      const tick = await oracleTester.testGetWeightedTickSafe(interactionTimestamps[1] - 1, squeethPool.address)\n      expect(initPriceTick === tick).to.be.true;\n    })\n    it('should return max period as timestamp[1] til now', async() => {\n      const period = await oracle.getMaxPeriod(squeethPool.address)\n      const now = await getNow(provider)\n      expect(interactionTimestamps[1] + period === now).to.be.true\n    })\n  })\n  \n  describe(\"Fetch price after adding storage slot\", async () => {\n    before('increase storage slot', async() => {\n      // increase storage slot to 16\n      await squeethPool.increaseObservationCardinalityNext(16)\n      await provider.send(\"evm_mine\", [])\n    })\n    before('add liquidity to the pool', async() => {\n      const squeethAmount = 1\n      const wethAmount = squeethPriceInETH * squeethAmount\n      const liquiditySqueethAmount = ethers.utils.parseEther(squeethAmount.toString())\n      const liquidityWethAmount = ethers.utils.parseEther(wethAmount.toString())\n      await squeeth.mint(deployer, liquiditySqueethAmount)\n      await weth.deposit({value: liquidityWethAmount})\n\n      const token0 = isWethToken0 ? weth.address : squeeth.address\n      const token1 = isWethToken0 ? squeeth.address : weth.address\n\n      const mintParam = {\n        token0,\n        token1,\n        fee: 3000,\n        tickLower: -887220,// int24 min tick used when selecting full range\n        tickUpper: 887220,// int24 max tick used when selecting full range\n        amount0Desired: isWethToken0 ? liquidityWethAmount : liquiditySqueethAmount,\n        amount1Desired: isWethToken0 ? liquiditySqueethAmount : liquidityWethAmount,\n        amount0Min: 0,\n        amount1Min: 0,\n        recipient: deployer,// address\n        deadline: await getNow(provider) + 86400\n      }\n      const res = await positionManager.mint(mintParam)\n      const initBlockNumber = res.blockNumber\n      const block = await provider.getBlock(initBlockNumber)\n      \n      // interactionTimestamps[2] = second touch timestamp\n      interactionTimestamps.push(block.timestamp)\n      await provider.send(\"evm_mine\", [])\n    })\n    before('increase timestamp', async () => {\n      await provider.send(\"evm_increaseTime\", [50]) // go 50 seconds minutes\n      await provider.send(\"evm_mine\", [])\n    })\n    it('should revert if requesting TWAP from init timestamp', async() => {\n      await expect(\n        oracleTester.testGetTwapSince(interactionTimestamps[0], squeethPool.address, squeeth.address, weth.address)\n      ).to.be.revertedWith(\"OLD\");\n    })\n    it(\"should NOT revert if requesting TWAP from init timestamp, with #getTwapSafe\", async () => {\n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSafeSince(interactionTimestamps[0], squeethPool.address, squeeth.address, weth.address)\n      ).toString());\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n    it(\"should NOT revert if requesting time weighted tick from init timestamp, with #getWeightedTickSafe\", async () => {\n      const tick = await oracleTester.testGetWeightedTickSafe(interactionTimestamps[0], squeethPool.address, )\n      expect(initPriceTick === tick).to.be.true\n    })\n    it('should be able to get TWAP since first touch', async() => {\n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSince(interactionTimestamps[1], squeethPool.address, squeeth.address, weth.address))\n        .toString())\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n    it(\"should revert if trying to request twap since a time before first touch\", async () => {\n      await expect(\n        oracleTester.testGetTwapSince(interactionTimestamps[1] - 1, squeethPool.address, squeeth.address, weth.address)\n      ).to.be.revertedWith(\"OLD\");\n    })\n    it(\"should NOT revert if trying to request twap since a time before first touch, with #getTwapSafe\", async () => {\n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSafeSince(interactionTimestamps[1] - 1, squeethPool.address, squeeth.address, weth.address)\n      ).toString());\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n    it(\"should NOT revert if requesting time weighted tick since a time before first touch, with #getWeightedTickSafe\", async () => {\n      const tick = await oracleTester.testGetWeightedTickSafe(interactionTimestamps[1] - 1, squeethPool.address, )\n      expect(initPriceTick === tick).to.be.true\n    })\n    it('should be able to get TWAP since second touch', async() => {\n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSince(interactionTimestamps[2], squeethPool.address, squeeth.address, weth.address))\n        .toString())\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n    it(\"should be able to get time weighted tick from second touch, with #getWeightedTickSafe\", async () => {\n      const tick = await oracleTester.testGetWeightedTickSafe(interactionTimestamps[2], squeethPool.address, )\n      expect(tick === initPriceTick).to.be.true\n    })\n    it('should be able to get TWAP since time between first touch and second touch with #getTwapSafe', async() => {\n      const period = Math.floor((interactionTimestamps[2] + interactionTimestamps[1]) / 2)\n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSafeSince(period, squeethPool.address, squeeth.address, weth.address))\n        .toString())\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n\n    it('should be able to get a historical TWAP from now until first interaction and it should match a normal twap', async() => {\n      const price = new BigNumberJs((\n        await oracleTester.testGetHistoricalTwapToNow(interactionTimestamps[1], squeethPool.address, squeeth.address, weth.address))\n        .toString())\n      const priceTwap = new BigNumberJs((\n        await oracleTester.testGetTwapSince(interactionTimestamps[1], squeethPool.address, squeeth.address, weth.address))\n        .toString())\n  \n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n      expect(price.eq(priceTwap)).to.be.true\n    })\n\n    it('should be able to get a historical TWAP from second interaction to first interaction', async() => {\n      const price = new BigNumberJs((\n        await oracleTester.testGetHistoricalTwap(interactionTimestamps[1], interactionTimestamps[2], squeethPool.address, squeeth.address, weth.address))\n        .toString())\n  \n      expect(isSimilar(price.toString(), squeethPriceInETH1e18, 3)).to.be.true;\n    })\n\n    it('should be able to get TWAP since second touch with #getTwapSafe', async() => {\n      const price = new BigNumberJs((\n        await oracleTester.testGetTwapSafeSince(interactionTimestamps[2], squeethPool.address, squeeth.address, weth.address))\n        .toString())\n      expect(isSimilar(price.toString(), squeethPriceInETH1e18)).to.be.true;\n    })\n  })\n  \n  // make sure the TWAP is calculated correctly\n  describe(\"oracle tick is time weighted\", async () => {\n    \n    let startTimestamp: number\n    const period = 60\n    let oldTick: number\n    let newTick: number\n    before('increase storage slot', async() => {\n      await squeethPool.increaseObservationCardinalityNext(16)\n    })\n    before('setup time', async() => {\n      const { tick } = await squeethPool.slot0()\n      oldTick = tick\n      startTimestamp = await getNow(provider)\n      \n    })\n    before('increase price by buying from the pool', async () => {\n      const poolWethBalance = await weth.balanceOf(squeethPool.address)\n      const buyAmount = poolWethBalance.div(10)\n      await weth.deposit({value: buyAmount})\n      await weth.approve(swapRouter.address, constants.MaxUint256)\n      const params = {\n        tokenIn: weth.address,\n        tokenOut: squeeth.address,\n        fee: 3000,\n        recipient: deployer,\n        deadline: await getNow(provider) + 100000, // uint256\n        amountIn: buyAmount,\n        amountOutMinimum: 0,\n        sqrtPriceLimitX96: 0,\n      }\n\n      await provider.send(\"evm_setNextBlockTimestamp\", [startTimestamp + period]) \n      await swapRouter.exactInputSingle(params)\n\n      const { tick } = await squeethPool.slot0()\n      newTick = tick\n    })\n\n    it('tick should return the average when each price has same weight ', async() => {\n      await provider.send(\"evm_setNextBlockTimestamp\", [startTimestamp + period*2]) \n      await provider.send(\"evm_mine\", [])\n      // price:            | old tick | new tick |\n      // time period: start|  period  |  period  | now \n      const timeWeightedTick = await oracle.getTimeWeightedAverageTickSafe(squeethPool.address, period*2)\n      expect(isSimilar(timeWeightedTick.toString(), ((newTick + oldTick) / 2).toString())).to.be.true\n\n      // check price returned by oracle match the tick\n      const twap = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, period*2, false)\n      const twapSafe = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, period*2, true)\n\n      const tickToUse = isWethToken0 ? -timeWeightedTick : timeWeightedTick\n      const expectedTwap = tickToPrice1e18(tickToUse)\n      \n      expect(isSimilar(twap.toString(), expectedTwap)).to.be.true\n      expect(twap.eq(twapSafe)).to.be.true\n    })\n\n    it('tick should return the weighed average when price does not have same weight', async() => {\n      await provider.send(\"evm_setNextBlockTimestamp\", [startTimestamp + period*3]) \n      await provider.send(\"evm_mine\", [])\n      // price:            | old tick | new tick           |\n      // time period: start| period   | 2 * period         | now \n      const timeWeightedTick = await oracle.getTimeWeightedAverageTickSafe(squeethPool.address, period*3)\n      expect(isSimilar(timeWeightedTick.toString(), ((newTick*2 + oldTick) / 3).toString())).to.be.true\n\n      // check price returned by oracle match the tick\n      const twap = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, period*3, false)\n      const twapSafe = await oracle.getTwap(squeethPool.address, squeeth.address, weth.address, period*3, true)\n      const tickToUse = isWethToken0 ? -timeWeightedTick : timeWeightedTick\n      const expectedTwap = tickToPrice1e18(tickToUse)\n\n      expect(isSimilar(twap.toString(), expectedTwap.toString())).to.be.true\n      expect(twap.eq(twapSafe)).to.be.true\n    })\n    \n  })\n})"
  },
  {
    "path": "packages/hardhat/test/unit-tests/short-power-perp.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { constants } from \"ethers\";\nimport { ShortPowerPerp, ControllerAccessTester} from \"../../typechain\";\n\ndescribe(\"ShortPowerPerp\", function () {\n  let shortSqueeth: ShortPowerPerp;\n  let random: SignerWithAddress\n  let controller: ControllerAccessTester\n  let address1: SignerWithAddress\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_address1, _random] = accounts;\n    address1 = _address1\n    random = _random\n  });\n\n  describe(\"Deployment\", async () => {\n    it(\"Deployment\", async function () {\n      const ShortPowerPerpContract = await ethers.getContractFactory(\"ShortPowerPerp\");\n      shortSqueeth = (await ShortPowerPerpContract.deploy('Short Squeeth', 'sSQU')) as ShortPowerPerp;\n      const ControllerContract = await ethers.getContractFactory(\"ControllerAccessTester\");\n      controller = (await ControllerContract.deploy(shortSqueeth.address)) as ControllerAccessTester;\n    });\n  });\n\n  describe(\"Initialization\", async () => {\n    it(\"should revert when calling init with invalid address as controller\", async () => {\n      await expect(shortSqueeth.init(constants.AddressZero)).to.be.revertedWith('Invalid controller address')\n    })\n    it(\"should revert when calling init from a random address\", async() => {\n      await expect(shortSqueeth.connect(random).init(controller.address)).to.be.revertedWith(\"Invalid caller of init\")\n    })\n    it(\"Should be able to init contract when called by the deployer\", async () => {\n      await shortSqueeth.connect(address1).init(controller.address);\n      const controllerAddress = await shortSqueeth.controller();\n      expect(controllerAddress).to.be.eq(controller.address,\"Controller address mismatch\");\n    })\n    it(\"should revert when trying to init again\", async () => {\n      await expect(shortSqueeth.connect(address1).init(controller.address)).to.be.revertedWith(\"Initializable: contract is already initialized\")\n    })\n  });\n\n  describe(\"Access control\", async () => {\n    it(\"Should revert if mint called by an address other than controller \", async () => {\n        await expect(shortSqueeth.connect(random).mintNFT(address1.address)).to.be.revertedWith(\"Not controller\")\n    });\n    it('Should mint nft with expected id if mint is called by controller', async() => {\n      const expectedId = await shortSqueeth.nextId()\n      await controller.connect(address1).mintTest(random.address)\n      expect(await shortSqueeth.ownerOf(expectedId) === random.address).to.be.true\n    })\n  });\n\n});\n"
  },
  {
    "path": "packages/hardhat/test/unit-tests/squeeth.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { constants } from \"ethers\";\nimport { WPowerPerp } from \"../../typechain\";\n\ndescribe(\"WPowerPerp\", function () {\n  let wsqueeth: WPowerPerp;\n  let address1: SignerWithAddress\n  let controller: SignerWithAddress\n  let random: SignerWithAddress\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_address1, _controller, _random] = accounts;\n    address1 = _address1\n    controller = _controller\n    random = _random\n  });\n  \n  describe(\"Deploymenl\", async() => {\n    it(\"Deployment\", async function () {\n      const WPowerPerpContract = await ethers.getContractFactory(\"WPowerPerp\");\n      wsqueeth = (await WPowerPerpContract.deploy('Wrapped Squeeth', 'WSQU')) as WPowerPerp;\n    });\n  })\n\n  describe(\"Initialization\", async () => {\n    it(\"should revert when calling init with invalid address as controller\", async () => {\n      await expect(wsqueeth.init(constants.AddressZero)).to.be.revertedWith('Invalid controller address')\n    })\n    it(\"should revert when calling init from a random address\", async () => {\n      await expect(wsqueeth.connect(random).init(controller.address)).to.be.revertedWith('Invalid caller of init')\n    })\n    it(\"should init with controller address when called by the deployer\", async () => {\n      await wsqueeth.connect(address1).init(controller.address)\n      expect(await wsqueeth.controller()).to.be.eq(controller.address)\n    })\n    it('should revert when trying to init again', async() => {\n      await expect(wsqueeth.init(controller.address)).to.be.revertedWith('Initializable: contract is already initialized')\n    })\n    it(\"should have decimals 18\", async () => {\n      expect(await wsqueeth.decimals()).to.be.eq(18)\n    })\n  })\n  describe(\"Minting and burning\", async () => {\n    it(\"should mint with controller\", async () => {\n    const mintAmount = 10\n      await wsqueeth.connect(controller).mint(random.address, mintAmount)\n      expect((await wsqueeth.balanceOf(random.address)).eq(mintAmount)).to.be.true\n    })\n    it(\"should revert when minted from non-controller\", async () => {\n      const mintAmount = 10\n      await expect(wsqueeth.connect(random).mint(random.address, mintAmount)).to.be.revertedWith('Not controller');\n    })\n    it(\"should revert when burned from non-controller\", async () => {\n        const burnAmount = 10\n        await expect(wsqueeth.connect(random).burn(random.address, burnAmount)).to.be.revertedWith('Not controller');\n    })\n      \n    it(\"should burn from controler\", async () => {\n      const burnAmount = 10\n      await wsqueeth.connect(controller).burn(random.address, burnAmount);\n      expect((await wsqueeth.balanceOf(random.address)).eq(0)).to.be.true\n    })\n  }) \n})\n"
  },
  {
    "path": "packages/hardhat/test/unit-tests/strategy/crab-migration.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { BigNumber, providers } from \"ethers\";\nimport { MockCrab, CrabMigration, MockErc20, WETH9, MockEulerDToken, MockEuler} from \"../../../typechain\";\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\ndescribe(\"Crab Migration\", function () {\n \n    let crabStrategyV1: MockCrab;\n    let crabStrategyV2: MockCrab;\n    let crabMigration: CrabMigration;\n\n    let weth: MockErc20;\n    let usdc: MockErc20;\n    let dToken: MockEulerDToken;\n    let dTokenUsdc: MockEulerDToken;\n    let euler: MockEuler;\n\n    let provider: providers.JsonRpcProvider;\n    let owner: SignerWithAddress;\n    let random: SignerWithAddress;\n    let d1: SignerWithAddress;\n    let d2: SignerWithAddress;\n\n    const deposit1Amount = ethers.utils.parseEther(\"10.0\");\n    const deposit2Amount = ethers.utils.parseEther(\"90.0\");\n    const collateral = deposit1Amount.add(deposit2Amount);\n\n    this.beforeAll(\"Prepare accounts\", async () => {\n        const accounts = await ethers.getSigners();\n        const [_owner, _d1, _random, _d2] = accounts;\n        d1 = _d1\n        d2 = _d2\n        random = _random\n        owner = _owner\n        provider = ethers.provider\n    })\n\n    this.beforeAll(\"Setup mock contracts\", async () => { \n        const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n        weth = (await MockErc20Contract.deploy(\"WETH\", \"WETH\", 18)) as MockErc20;\n\n        const MockNonWethErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n        usdc = (await MockNonWethErc20Contract.deploy(\"USDC\", \"USDC\", 18)) as MockErc20;\n\n        const MockEulerDTokenContract = await ethers.getContractFactory(\"MockEulerDToken\");\n        dToken = (await MockEulerDTokenContract.deploy(weth.address)) as MockEulerDToken;\n\n        const MockIncorrectEulerDTokenContract = await ethers.getContractFactory(\"MockEulerDToken\");\n        dTokenUsdc = (await MockIncorrectEulerDTokenContract.deploy(usdc.address)) as MockEulerDToken;\n\n        const MockEulerContract = await ethers.getContractFactory(\"MockEuler\");\n        euler = (await MockEulerContract.deploy()) as MockEuler;\n\n        await weth.mint(dToken.address, collateral);\n    })\n    \n    this.beforeAll(\"Setup Mock Crabs\", async () => {\n        const CrabContract = await ethers.getContractFactory(\"MockCrab\");\n        crabStrategyV1 = (await CrabContract.deploy(\"CrabV1\", \"CrabV1\", 18)) as MockCrab;\n        crabStrategyV2 = (await CrabContract.deploy(\"CrabV2\", \"CrabV2\", 18)) as MockCrab;\n\n        await crabStrategyV1.mint(d1.address, deposit1Amount);\n        await crabStrategyV1.mint(d2.address, deposit2Amount);\n\n        await crabStrategyV1.setVaultDetails(1, collateral, collateral.div(2));\n    })\n\n    describe(\"Deployment tests\", async() => { \n\n        it(\"should revert if deploying to a dToken that is not weth\", async () => { \n            const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n            await expect(MigrationContract.connect(owner).deploy(crabStrategyV1.address, weth.address, euler.address, dTokenUsdc.address, euler.address)).to.be.revertedWith(\"dToken underlying asset should be weth\");\n            })\n\n        it(\"should deploy if correct dToken is specified\", async () => { \n            const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n            crabMigration = (await MigrationContract.connect(owner).deploy(crabStrategyV1.address, weth.address, euler.address, dToken.address, euler.address)) as CrabMigration;\n            })\n    })\n  \n\n    describe(\"Test Migration\", async() => { \n\n        it(\"Should revert if address of euler deposit token is 0\", async function () {\n            const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n            await expect(MigrationContract.connect(owner).deploy(\n                crabStrategyV1.address, weth.address, euler.address, ethers.constants.AddressZero, euler.address)).to.be.revertedWith(\"invalid _dToken address\");\n        });\n\n        it(\"Should revert if address of euler deployment on mainnet is 0\", async function () {\n            const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n            await expect(MigrationContract.connect(owner).deploy(\n                crabStrategyV1.address, weth.address, euler.address, dToken.address, ethers.constants.AddressZero)).to.be.revertedWith(\"invalid _eulerMainnet address\");\n        });\n\n        it(\"Should revert if address of euler exec contract is 0\", async function () {\n            const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n            await expect(MigrationContract.connect(owner).deploy(\n                crabStrategyV1.address, weth.address, ethers.constants.AddressZero, dToken.address, euler.address)).to.be.revertedWith(\"invalid _eulerExec address\");\n        });\n\n        it(\"Should revert if address of crab v1 is 0\", async function () {\n            const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n            await expect(MigrationContract.connect(owner).deploy(\n                ethers.constants.AddressZero, weth.address, euler.address, dToken.address, euler.address)).to.be.revertedWith(\"invalid _crabv1 address\");\n        });\n\n        it(\"Should revert if address of weth is 0\", async function () {\n            const MigrationContract = await ethers.getContractFactory(\"CrabMigration\");\n            await expect(MigrationContract.connect(owner).deploy(\n                crabStrategyV1.address, ethers.constants.AddressZero, euler.address, dToken.address, euler.address)).to.be.revertedWith(\"invalid _weth address\");\n        });\n\n        it(\"should not allow 0 to be set as crab address\", async () => {\n            await expect(crabMigration.connect(owner).setCrabV2(ethers.constants.AddressZero)).to.be.revertedWith(\"M7\");\n        })\n\n        it(\"should set crabV2 with proper address\", async () => {\n            await crabMigration.connect(owner).setCrabV2(crabStrategyV2.address)\n            expect(await crabMigration.crabV2()).to.be.equal(crabStrategyV2.address)\n        })\n\n\n        it(\"d1 deposits crabV1 shares\", async () => { \n            const crabV1BalanceBefore = await crabStrategyV1.balanceOf(crabMigration.address); \n\n            await crabStrategyV1.connect(d1).approve(crabMigration.address, deposit1Amount);\n            await crabMigration.connect(d1).depositV1Shares(deposit1Amount.div(2));\n\n            const crabV1BalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n            const d1SharesDeposited  = await crabMigration.sharesDeposited(d1.address);\n\n            expect(crabV1BalanceBefore).to.be.equal('0');\n            expect(crabV1BalanceAfter).to.be.equal(deposit1Amount.div(2));\n            expect(d1SharesDeposited).to.be.equal(deposit1Amount.div(2));\n        })\n\n        it(\"d1 deposits more crabV1 shares\", async () => { \n            const crabV1BalanceBefore = await crabStrategyV1.balanceOf(crabMigration.address); \n\n            await crabStrategyV1.connect(d1).approve(crabMigration.address, deposit1Amount);\n            await crabMigration.connect(d1).depositV1Shares(deposit1Amount.div(2));\n\n            const crabV1BalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n            const d1SharesDeposited  = await crabMigration.sharesDeposited(d1.address);\n\n            expect(crabV1BalanceBefore).to.be.equal(deposit1Amount.div(2));\n            expect(crabV1BalanceAfter).to.be.equal(deposit1Amount);\n            expect(d1SharesDeposited).to.be.equal(deposit1Amount);\n        })\n\n        it(\"d2 deposits crabV1 shares\", async () => { \n            const crabV1BalanceBefore = await crabStrategyV1.balanceOf(crabMigration.address); \n\n            await crabStrategyV1.connect(d2).approve(crabMigration.address, deposit2Amount);\n            await crabMigration.connect(d2).depositV1Shares(deposit2Amount);\n\n            const crabV1BalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n            const d2SharesDeposited  = await crabMigration.sharesDeposited(d2.address);\n\n            expect(crabV1BalanceAfter.sub(crabV1BalanceBefore)).to.be.equal(deposit2Amount);\n            expect(d2SharesDeposited).to.be.equal(deposit2Amount);\n        })\n\n        it(\"d2 withdraws more shares than they have deposited crabV1 shares\", async () => { \n            await expect(crabMigration.connect(d2).withdrawV1Shares(deposit2Amount.mul(2))).to.be.revertedWith(\"ds-math-sub-underflow\");\n        })\n\n        it(\"d2 withdraws 50% of crabV1 shares\", async () => { \n            const crabV1BalanceBefore = await crabStrategyV1.balanceOf(crabMigration.address); \n\n            await crabMigration.connect(d2).withdrawV1Shares(deposit2Amount.div(2));\n\n            const crabV1BalanceAfter = await crabStrategyV1.balanceOf(crabMigration.address);\n            const d2SharesDeposited  = await crabMigration.sharesDeposited(d2.address);\n\n            expect(crabV1BalanceBefore.sub(crabV1BalanceAfter)).to.be.equal(deposit2Amount.div(2));\n            expect(d2SharesDeposited).to.be.equal(deposit2Amount.sub(deposit2Amount.div(2)));\n        })\n\n\n        it(\"should not be able to claim until strategy has been migrated\", async () => { \n            await expect(crabMigration.connect(d1).claimV2Shares()).to.be.revertedWith(\"M2\");\n        })\n\n        it(\"random should not be able to call onDeferredLiquidity()\", async () => { \n            const data = \"0x0000000000000000000000000000000000000000\"\n            await expect((crabMigration.connect(random).onDeferredLiquidityCheck(data))).to.be.revertedWith(\"M3\");\n        })\n\n        it(\"random should not be able to migrate shares\", async () => { \n            await expect(crabMigration.connect(random).batchMigrate(1)).to.be.revertedWith(\"Ownable: caller is not the owner\");\n        })\n\n        it(\"batchMigrate\", async () => { \n            await crabMigration.connect(owner).batchMigrate(1);\n        })\n    })\n\n\n})"
  },
  {
    "path": "packages/hardhat/test/unit-tests/strategy/crab-strategy-v2.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { BigNumber, providers } from \"ethers\";\nimport { MockController, WETH9, MockShortPowerPerp, MockUniswapV3Pool, MockOracle, MockWPowerPerp, CrabStrategyV2, MockErc20, MockTimelock } from \"../../../typechain\";\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\ndescribe(\"Crab Strategy V2\", function () {\n  const hedgeTimeTolerance = 86400  // 24h\n  const hedgePriceTolerance = ethers.utils.parseUnits('0.15')\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let random: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress;\n  let crabMigration: SignerWithAddress;\n\n  let squeeth: MockWPowerPerp;\n  let weth: WETH9;\n  let wSqueethEthPool: MockUniswapV3Pool;\n  let ethUSDPool: MockUniswapV3Pool;\n  let shortSqueeth: MockShortPowerPerp;\n  let controller: MockController;\n  let oracle: MockOracle;\n  let crabStrategy: CrabStrategyV2;\n  let usdc: MockErc20;\n  let timelock: MockTimelock;\n\n  this.beforeAll(\"Prepare accounts\", async () => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _random, _depositor2, _crabMigration] = accounts;\n    depositor = _depositor\n    depositor2 = _depositor2\n    random = _random\n    owner = _owner\n    crabMigration = _crabMigration\n    provider = ethers.provider\n  })\n\n  this.beforeAll(\"Setup environment\", async () => {\n    const WETH9Contract = await ethers.getContractFactory(\"WETH9\");\n    weth = (await WETH9Contract.deploy()) as WETH9;\n\n    const MockSQUContract = await ethers.getContractFactory(\"MockWPowerPerp\");\n    squeeth = (await MockSQUContract.deploy()) as MockWPowerPerp;\n\n    const MockUniswapV3PoolContract = await ethers.getContractFactory(\"MockUniswapV3Pool\");\n    wSqueethEthPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n    ethUSDPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n\n    const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n    usdc = (await MockErc20Contract.deploy(\"USDC\", \"USDC\", 6)) as MockErc20;\n\n    const MockOracle = await ethers.getContractFactory(\"MockOracle\");\n    oracle = (await MockOracle.deploy()) as MockOracle;\n\n    const NFTContract = await ethers.getContractFactory(\"MockShortPowerPerp\");\n    shortSqueeth = (await NFTContract.deploy()) as MockShortPowerPerp;\n\n    const ControllerContract = await ethers.getContractFactory(\"MockController\");\n    controller = (await ControllerContract.deploy()) as MockController;\n\n    const TimelockContract = await ethers.getContractFactory(\"MockTimelock\");\n    timelock = (await TimelockContract.deploy(owner.address, 3 * 24 * 60 * 60)) as MockTimelock;\n\n\n    await controller.connect(owner).init(shortSqueeth.address, squeeth.address, ethUSDPool.address, usdc.address);\n  })\n\n  describe(\"Deployment\", async () => {\n\n    it(\"Should revert if weth is address 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address,\n        ethers.constants.AddressZero,\n        random.address,\n        wSqueethEthPool.address,\n        timelock.address,\n        crabMigration.address,\n        hedgeTimeTolerance,\n        hedgePriceTolerance)).to.be.revertedWith(\"invalid weth address\");\n    });\n\n    it(\"Should revert if controller is address 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n      await expect(CrabStrategyContract.deploy(\n        ethers.constants.AddressZero,\n        oracle.address,\n        weth.address,\n        random.address,\n        wSqueethEthPool.address,\n        timelock.address,\n        crabMigration.address,\n        hedgeTimeTolerance,\n        hedgePriceTolerance)).to.be.revertedWith(\"invalid controller address\");\n    });\n\n    it(\"Should revert if oracle is address 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        ethers.constants.AddressZero,\n        weth.address,\n        random.address,\n        wSqueethEthPool.address,\n        timelock.address,\n        crabMigration.address,\n        hedgeTimeTolerance,\n        hedgePriceTolerance)).to.be.revertedWith(\"C3\");\n    });\n\n    it(\"Should revert if uniswap factory is address 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address,\n        weth.address,\n        ethers.constants.AddressZero,\n        wSqueethEthPool.address,\n        timelock.address,\n        crabMigration.address,\n        hedgeTimeTolerance,\n        hedgePriceTolerance)).to.be.revertedWith(\"invalid factory address\");\n    });\n\n    it(\"Should revert if wSqueethEth pool is address 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address,\n        weth.address,\n        random.address,\n        ethers.constants.AddressZero,\n        timelock.address,\n        crabMigration.address,\n        hedgeTimeTolerance,\n        hedgePriceTolerance)).to.be.revertedWith(\"C5\");\n    });\n\n    it(\"Should revert if hedge time tolerrance is 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address,\n        weth.address,\n        random.address,\n        wSqueethEthPool.address,\n        timelock.address,\n        crabMigration.address,\n        0,\n        hedgePriceTolerance)).to.be.revertedWith(\"C7\");\n    });\n\n    it(\"Should revert if hedge price tolerance is 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address,\n        weth.address,\n        random.address,\n        wSqueethEthPool.address,\n        timelock.address,\n        crabMigration.address,\n        hedgeTimeTolerance,\n        0)).to.be.revertedWith(\"C8\");\n    });\n\n    it(\"Should revert if hedge price tolerance is > 1e18\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address,\n        weth.address,\n        random.address,\n        wSqueethEthPool.address,\n        timelock.address,\n        crabMigration.address,\n        hedgeTimeTolerance,\n        one.add(1))).to.be.revertedWith(\"C8\");\n    });\n\n    it(\"Should revert if timelock address is 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address,\n        weth.address,\n        random.address,\n        wSqueethEthPool.address,\n        ethers.constants.AddressZero,\n        crabMigration.address,\n        hedgeTimeTolerance,\n        hedgePriceTolerance)).to.be.revertedWith(\"C4\");\n    });\n\n    it(\"Should revert if crab migration address is 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address,\n        weth.address,\n        random.address,\n        wSqueethEthPool.address,\n        timelock.address,\n        ethers.constants.AddressZero,\n        hedgeTimeTolerance,\n        hedgePriceTolerance)).to.be.revertedWith(\"C6\");\n    });\n\n    it(\"Deployment\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategyV2\");\n      crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, random.address, wSqueethEthPool.address, timelock.address, crabMigration.address, hedgeTimeTolerance, hedgePriceTolerance)) as CrabStrategyV2;\n    });\n  });\n\n  describe(\"Crab strategy vault\", async () => {\n    it(\"Check crab details\", async () => {\n      const name = await crabStrategy.name()\n      const symbol = await crabStrategy.symbol()\n\n      expect(name).to.be.eq(\"Crab Strategy v2\")\n      expect(symbol).to.be.eq(\"Crabv2\")\n    })\n    it(\"Check crab strategy opened vault\", async () => {\n      const openedVaultId = await crabStrategy.getStrategyVaultId()\n\n      expect(openedVaultId).to.be.eq(BigNumber.from(1))\n    });\n  });\n\n  describe(\"receive checks\", async () => {\n    it('should revert when sending eth to crab strategy contract from an EOA', async () => {\n      await expect(random.sendTransaction({ to: crabStrategy.address, value: 1 })).to.be.revertedWith('C9')\n    })\n  });\n\n  describe(\"Check pre initialization strategy cap reverts\", async () => {\n    const strategyCap = ethers.utils.parseUnits(\"100\")\n    const wSqueethEthPrice = BigNumber.from('3030').mul(one).div(oracleScaleFactor)\n    const ethUSDPrice = BigNumber.from('3000').mul(one)\n\n    before(async () => {\n      await oracle.connect(owner).setPrice(wSqueethEthPool.address, wSqueethEthPrice)\n      await oracle.connect(random).setPrice(ethUSDPool.address, ethUSDPrice)  // usdc per 1 eth\n    })\n\n    it('should revert non owner tries to set the strategy cap', async () => {\n      await expect(crabStrategy.connect(random).setStrategyCap(strategyCap)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n    it('should revert if owner tries to increase the strategy cap before the contract is initialized', async () => {\n      await expect(crabStrategy.connect(owner).setStrategyCap(strategyCap)).to.be.revertedWith(\"C2\")\n    })\n  });\n\n  describe(\"set other params\", async () => {\n\n    const newHedgeTimeTolerance = 172800  // 48h\n    const newHedgePriceTolerance = ethers.utils.parseUnits('0.1')\n    const newAuctionTime = 1200\n    const newMinAuctionSlippage = ethers.utils.parseUnits('0.9')\n    const revertMinAuctionSlippage = ethers.utils.parseUnits('1')\n    const newMaxAuctionSlippage = ethers.utils.parseUnits('1.1')\n    const revertMaxAuctionSlippage = ethers.utils.parseUnits('1')\n    const newTwapPeriod = 300 // 5 minutes\n    const newDeltaHedgeThreshold = ethers.utils.parseUnits('0.01')\n    const revertDeltaHedgeThreshold = ethers.utils.parseUnits('0.3')\n\n\n    it('should revert if non owner tries to change the hedge time threshold', async () => {\n      await expect(crabStrategy.connect(random).setHedgeTimeThreshold(newHedgeTimeTolerance)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n    it('should revert if owner tries to change the hedge time threshold to 0', async () => {\n      await expect(crabStrategy.connect(owner).setHedgeTimeThreshold(0)).to.be.revertedWith(\"C7\")\n    })\n\n    it('should allow owner to change the hedge time threshold', async () => {\n      await crabStrategy.connect(owner).setHedgeTimeThreshold(newHedgeTimeTolerance)\n      const hedgeTimeThresholdInContract = await crabStrategy.hedgeTimeThreshold()\n      expect(hedgeTimeThresholdInContract.eq(newHedgeTimeTolerance)).to.be.true\n    })\n\n    it('should allow owner to change the hedge time threshold back', async () => {\n      await crabStrategy.connect(owner).setHedgeTimeThreshold(hedgeTimeTolerance)\n      const hedgeTimeThresholdInContract = await crabStrategy.hedgeTimeThreshold()\n      expect(hedgeTimeThresholdInContract.eq(hedgeTimeTolerance)).to.be.true\n    })\n\n    it('should revert if non owner tries to change the hedge price threshold', async () => {\n      await expect(crabStrategy.connect(random).setHedgePriceThreshold(newHedgePriceTolerance)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n    it('should revert if owner tries to change the hedge price threshold to 0', async () => {\n      await expect(crabStrategy.connect(owner).setHedgePriceThreshold(0)).to.be.revertedWith(\"C8\")\n    })\n\n    it('should revert if owner tries to change the hedge price threshold to 1e18+1', async () => {\n      await expect(crabStrategy.connect(owner).setHedgePriceThreshold(one.add(1))).to.be.revertedWith(\"C8\")\n    })\n\n    it('should allow owner to change the hedge price threshold', async () => {\n      await crabStrategy.connect(owner).setHedgePriceThreshold(newHedgePriceTolerance)\n      const hedgePriceThresholdInContract = await crabStrategy.hedgePriceThreshold()\n      expect(hedgePriceThresholdInContract.eq(newHedgePriceTolerance)).to.be.true\n    })\n\n    it('should allow owner to change the hedge price threshold back', async () => {\n      await crabStrategy.connect(owner).setHedgePriceThreshold(hedgePriceTolerance)\n      const hedgePriceThresholdInContract = await crabStrategy.hedgePriceThreshold()\n      expect(hedgePriceThresholdInContract.eq(hedgePriceTolerance)).to.be.true\n    })\n\n    it('should revert if non owner tries to change the delta hedge threshold', async () => {\n      await expect(crabStrategy.connect(random).setHedgingTwapPeriod(newTwapPeriod)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n\n    it('should revert if owner tries to change the twap period to too short of a value', async () => {\n      await expect(crabStrategy.connect(owner).setHedgingTwapPeriod(179)).to.be.revertedWith(\"C14\")\n    })\n\n    it('should allow owner to change the twap period and then change it back', async () => {\n\n      const twapPeriodBefore = await crabStrategy.hedgingTwapPeriod()\n      await crabStrategy.connect(owner).setHedgingTwapPeriod(newTwapPeriod)\n      const newTwapPeriodInContract = await crabStrategy.hedgingTwapPeriod()\n      expect(newTwapPeriodInContract === newTwapPeriod).to.be.true\n      await crabStrategy.connect(owner).setHedgingTwapPeriod(twapPeriodBefore)\n      const newTwapPeriodInContractRevert = await crabStrategy.hedgingTwapPeriod()\n      expect(newTwapPeriodInContractRevert === twapPeriodBefore).to.be.true\n    })\n  });\n\n  describe(\"Deposit into strategy\", async () => {\n    const strategyCap = ethers.utils.parseUnits(\"100\")\n    const wSqueethEthPrice = BigNumber.from('3030').mul(one).div(oracleScaleFactor)\n    const ethUSDPrice = BigNumber.from('3000').mul(one)\n\n    before(async () => {\n      await oracle.connect(owner).setPrice(wSqueethEthPool.address, wSqueethEthPrice)\n      await oracle.connect(random).setPrice(ethUSDPool.address, ethUSDPrice)  // usdc per 1 eth\n    })\n\n    it('should revert deposits if crab not yet initialized as the cap will be 0', async () => {\n      await expect(crabStrategy.connect(depositor2).deposit({ value: 1 })).to.be.revertedWith(\"C16\");\n    })\n\n    it(\"Should initialize strategy\", async () => {\n      const normFactor = BigNumber.from(1)\n      const ethToDeposit = BigNumber.from(60).mul(one)\n      const squeethDelta = wSqueethEthPrice.mul(2);\n  \n      const feeAdj = 0;\n      const debtToMint = ethToDeposit.mul(one).div(squeethDelta.add(feeAdj));\n      const expectedMintedWsqueeth = debtToMint.mul(normFactor)\n\n      await crabStrategy.connect(crabMigration).initialize( expectedMintedWsqueeth, ethToDeposit, 0, 0, strategyCap, { value: ethToDeposit });\n\n      const totalSupply = (await crabStrategy.totalSupply())\n      const migrationCrabV2Balance = (await crabStrategy.balanceOf(crabMigration.address))\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const debtAmount = strategyVault.shortAmount\n      const migrationSqueethBalance = await squeeth.balanceOf(crabMigration.address);\n      const strategyContractSqueeth = await squeeth.balanceOf(crabStrategy.address)\n\n      expect(totalSupply.eq(ethToDeposit)).to.be.true\n      expect(migrationCrabV2Balance.eq(ethToDeposit)).to.be.true\n      expect(isSimilar(debtAmount.toString(), debtToMint.toString(), 10)).to.be.true\n      expect(isSimilar(migrationSqueethBalance.toString(), expectedMintedWsqueeth.toString(), 10)).to.be.true\n      expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n\n      // Send the crab shares and squeeth to the depositor\n      await crabStrategy.connect(crabMigration).transfer(depositor.address, migrationCrabV2Balance);\n      await squeeth.connect(crabMigration).transfer(depositor.address, migrationSqueethBalance);\n    })\n\n    it('should revert non owner tries to set the strategy cap', async () => {\n      await expect(crabStrategy.connect(random).setStrategyCap(strategyCap)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n    it('should allow owner to increase the strategy cap', async () => {\n      await crabStrategy.connect(owner).setStrategyCap(strategyCap.mul(2))\n      const strategyCapInContract = await crabStrategy.strategyCap()\n      expect(strategyCapInContract.eq(strategyCap.mul(2))).to.be.true\n    })\n\n    it('should allow owner to reduce the strategy cap', async () => {\n      await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n      const strategyCapInContract = await crabStrategy.strategyCap()\n      expect(strategyCapInContract.eq(strategyCap)).to.be.true\n    })\n    it(\"Should not allow reinitialization of Crab v2\", async () => { \n      await expect(crabStrategy.connect(crabMigration).initialize(0, 0, 0, 0, 0, {value: 0})).to.be.revertedWith(\"C11\")\n    })\n\n\n    it(\"Should deposit and mint correct LP when initial debt != 0 and return the correct amount of wSqueeth debt per crab strategy token\", async () => {\n      const normFactor = BigNumber.from(1)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtBefore = strategyVault.shortAmount\n      const strategyCollateralBefore = strategyVault.collateralAmount\n      const totalCrabBefore = await crabStrategy.totalSupply()\n\n      const ethToDeposit = BigNumber.from(20).mul(one)\n      const depositorShare = wdiv(ethToDeposit, (strategyCollateralBefore.add(ethToDeposit)))\n      const expectedDepositorCrab = wdiv(wmul(totalCrabBefore, depositorShare), (one.sub(depositorShare)))\n      //   const squeethDelta = wSqueethEthPrice.mul(2);\n\n      // const feeAdj = ethUSDPrice.mul(100).div(10000)\n      const feeAdj = 0\n      const debtToMint = ethToDeposit.mul(strategyDebtBefore).div(strategyCollateralBefore.add(strategyDebtBefore.mul(feeAdj).div(one)));\n      const expectedMintedWsqueeth = debtToMint.mul(normFactor)\n\n      await crabStrategy.connect(depositor2).deposit({ value: ethToDeposit });\n\n      const totalCrabAfter = (await crabStrategy.totalSupply())\n      const depositorCrab = (await crabStrategy.balanceOf(depositor2.address))\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const debtAmount = strategyVaultAfter.shortAmount\n      const depositorSqueethBalance = await squeeth.balanceOf(depositor2.address)\n      const strategyContractSqueeth = await squeeth.balanceOf(crabStrategy.address)\n      const depositorWSqueethDebt = await crabStrategy.getWsqueethFromCrabAmount(depositorCrab)\n\n      expect(totalCrabAfter.eq(totalCrabBefore.add(expectedDepositorCrab))).to.be.true\n      expect(depositorCrab.eq(expectedDepositorCrab)).to.be.true\n      expect(isSimilar(strategyDebtBefore.add(debtToMint).toString(), debtAmount.toString(), 10)).to.be.true\n      expect(isSimilar(depositorSqueethBalance.toString(), expectedMintedWsqueeth.toString(), 10)).to.be.true\n      expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n      expect(depositorWSqueethDebt.eq(depositorSqueethBalance))\n    })\n    it('should revert if cap is hit', async () => {\n      const strategyCap = await crabStrategy.strategyCap()\n      const result = await crabStrategy.getVaultDetails()\n      const ethToDeposit = strategyCap.sub(result[2]).add(1)\n\n      await expect(crabStrategy.connect(depositor2).deposit({ value: ethToDeposit })).to.be.revertedWith(\"C16\");\n    })\n  })\n\n  describe(\"Withdraw from strategy\", async () => {\n    it(\"should revert withdrawing from a random account\", async () => {\n      const depositorSqueethBalanceBefore = await squeeth.balanceOf(depositor.address)\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor.address))\n      const wSqueethAmount = depositorSqueethBalanceBefore\n\n      await squeeth.connect(random).approve(crabStrategy.address, depositorCrabBefore)\n\n      await expect(\n        crabStrategy.connect(random).withdraw(depositorCrabBefore)\n      ).to.be.revertedWith(\"ERC20: transfer amount exceeds balance\");\n    })\n\n    it(\"should withdraw 0 correctly\", async () => {\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtBefore = strategyVault.shortAmount\n      const strategyCollateralBefore = strategyVault.collateralAmount\n      const totalCrabBefore = await crabStrategy.totalSupply()\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor.address))\n      const depositorSqueethBalanceBefore = await squeeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const expectedCrabPercentage = wdiv(depositorCrabBefore, totalCrabBefore)\n      const expectedEthToWithdraw = wmul(strategyCollateralBefore, expectedCrabPercentage)\n\n      await squeeth.connect(depositor).approve(crabStrategy.address, 0)\n      await crabStrategy.connect(depositor).withdraw(0);\n\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAfter = strategyVaultAfter.shortAmount\n      const totalCrabAfter = await crabStrategy.totalSupply()\n      const depositorCrabAfter = (await crabStrategy.balanceOf(depositor.address))\n      const depositorSqueethBalanceAfter = await squeeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(depositorSqueethBalanceAfter.eq(depositorSqueethBalanceBefore)).to.be.true\n      expect(depositorCrabAfter.eq(depositorCrabBefore)).to.be.true\n      expect(totalCrabAfter.eq(totalCrabBefore)).to.be.true\n      expect(strategyCollateralAfter.eq(strategyCollateralBefore)).to.be.true\n      expect(strategyDebtAfter.eq(strategyDebtBefore)).to.be.true\n      expect(isSimilar(depositorEthBalanceAfter.toString(), depositorEthBalanceBefore.toString())).to.be.true\n    })\n\n    it(\"should withdraw correct amount\", async () => {\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtBefore = strategyVault.shortAmount\n      const strategyCollateralBefore = strategyVault.collateralAmount\n      const totalCrabBefore = await crabStrategy.totalSupply()\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor.address))\n      const depositorSqueethBalanceBefore = await squeeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const expectedCrabPercentage = wdiv(depositorCrabBefore, totalCrabBefore)\n      const expectedEthToWithdraw = wmul(strategyCollateralBefore, expectedCrabPercentage)\n\n      await squeeth.connect(depositor).approve(crabStrategy.address, depositorSqueethBalanceBefore)\n      await crabStrategy.connect(depositor).withdraw(depositorCrabBefore);\n\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAfter = strategyVaultAfter.shortAmount\n      const totalCrabAfter = await crabStrategy.totalSupply()\n      const depositorCrabAfter = (await crabStrategy.balanceOf(depositor.address))\n      const depositorSqueethBalanceAfter = await squeeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(depositorSqueethBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(depositorSqueethBalanceBefore.gt(BigNumber.from(0))).to.be.true\n      expect(depositorCrabAfter.eq(BigNumber.from(0))).to.be.true\n      expect(totalCrabAfter.eq(totalCrabBefore.sub(depositorCrabBefore))).to.be.true\n      expect(strategyCollateralAfter.eq(strategyCollateralBefore.sub(expectedEthToWithdraw))).to.be.true\n      expect(strategyDebtAfter.eq(strategyDebtBefore.sub(depositorSqueethBalanceBefore))).to.be.true\n      expect(isSimilar(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).toString(), expectedEthToWithdraw.toString())).to.be.true\n    })\n  })\n\n  describe(\"Migrate vault to new strategy\", async () => {\n    const strategyCap = ethers.utils.parseUnits(\"100\")\n    const ethToDeposit = BigNumber.from(60).mul(one)\n\n    it(\"Should revert if non owner tries to migrate\", async () => {\n      await expect(crabStrategy.connect(random).transferVault(depositor.address)).to.be.revertedWith(\"C1\")\n    })\n\n    it(\"Should revert if owner tries to migrate directly\", async () => {\n      await expect(crabStrategy.connect(owner).transferVault(depositor.address)).to.be.revertedWith(\"C1\")\n    })\n\n    it(\"Should migrate and disable deposit/withdraw if transfer is called by timelock\", async () => {\n      await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n      await crabStrategy.connect(depositor).deposit({ value: ethToDeposit })\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor.address))\n      const depositorSqueethBalanceBefore = await squeeth.balanceOf(depositor.address)\n\n      // Transfer here\n      await timelock.connect(owner).executeVaultTransfer(crabStrategy.address, random.address)\n      const nftBalAfter = await shortSqueeth.balanceOf(crabStrategy.address)\n      const nftBalForRandom = await shortSqueeth.balanceOf(random.address)\n\n      const newCap = await crabStrategy.strategyCap()\n      expect(nftBalAfter.eq(0)).to.be.true\n      expect(nftBalForRandom.eq(1)).to.be.true\n      expect(newCap.eq(0)).to.be.true\n\n      // Try to withdraw\n      await squeeth.connect(depositor).approve(crabStrategy.address, depositorSqueethBalanceBefore)\n      await expect(crabStrategy.connect(depositor).withdraw(depositorCrabBefore)).to.be.revertedWith('C3')\n\n      // Try to deposit\n      await expect(crabStrategy.connect(depositor).deposit({ value: ethToDeposit })).to.be.revertedWith('C16')\n    })\n  })\n})\n"
  },
  {
    "path": "packages/hardhat/test/unit-tests/strategy/crab-strategy.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { BigNumber, providers } from \"ethers\";\nimport { MockController, WETH9, MockShortPowerPerp, MockUniswapV3Pool, MockOracle, MockWPowerPerp, CrabStrategy, MockErc20 } from \"../../../typechain\";\nimport { isSimilar, wmul, wdiv, one, oracleScaleFactor } from \"../../utils\"\n\ndescribe(\"Crab Strategy\", function () {\n  const hedgeTimeTolerance = 86400  // 24h\n  const hedgePriceTolerance = ethers.utils.parseUnits('0.15')\n  const auctionTime = 3600\n  const minAuctionSlippage = ethers.utils.parseUnits('0.95')\n  const maxAuctionSlippage = ethers.utils.parseUnits('1.05')\n\n  let provider: providers.JsonRpcProvider;\n  let owner: SignerWithAddress;\n  let random: SignerWithAddress;\n  let depositor: SignerWithAddress;\n  let depositor2: SignerWithAddress;\n\n  let squeeth: MockWPowerPerp;\n  let weth: WETH9;\n  let wSqueethEthPool: MockUniswapV3Pool;\n  let ethUSDPool: MockUniswapV3Pool;\n  let shortSqueeth: MockShortPowerPerp;\n  let controller: MockController;\n  let oracle: MockOracle;\n  let crabStrategy: CrabStrategy;\n  let usdc: MockErc20;\n\n  this.beforeAll(\"Prepare accounts\", async() => {\n    const accounts = await ethers.getSigners();\n    const [_owner, _depositor, _random, _depositor2] = accounts;\n    depositor = _depositor\n    depositor2 = _depositor2\n    random = _random\n    owner = _owner\n    provider = ethers.provider\n  })\n\n  this.beforeAll(\"Setup environment\", async () => {\n    const WETH9Contract = await ethers.getContractFactory(\"WETH9\");\n    weth = (await WETH9Contract.deploy()) as WETH9;\n\n    const MockSQUContract = await ethers.getContractFactory(\"MockWPowerPerp\");\n    squeeth = (await MockSQUContract.deploy()) as MockWPowerPerp;\n\n    const MockUniswapV3PoolContract = await ethers.getContractFactory(\"MockUniswapV3Pool\");\n    wSqueethEthPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n    ethUSDPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n\n    const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n    usdc = (await MockErc20Contract.deploy(\"USDC\", \"USDC\", 6)) as MockErc20;\n\n    const MockOracle = await ethers.getContractFactory(\"MockOracle\");\n    oracle = (await MockOracle.deploy()) as MockOracle;\n\n    const NFTContract = await ethers.getContractFactory(\"MockShortPowerPerp\");\n    shortSqueeth = (await NFTContract.deploy()) as MockShortPowerPerp;\n\n    const ControllerContract = await ethers.getContractFactory(\"MockController\");\n    controller = (await ControllerContract.deploy()) as MockController;\n\n    await controller.connect(owner).init(shortSqueeth.address, squeeth.address, ethUSDPool.address, usdc.address);\n  })\n\n  describe(\"Deployment\", async () => {\n\n    it(\"Should revert if weth is address 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address, \n        oracle.address, \n        ethers.constants.AddressZero, \n        random.address, \n        wSqueethEthPool.address, \n        hedgeTimeTolerance, \n        hedgePriceTolerance, \n        auctionTime, \n        minAuctionSlippage, \n        maxAuctionSlippage)).to.be.revertedWith(\"invalid weth address\");\n    });\n\n    it(\"Should revert if controller is address 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      await expect(CrabStrategyContract.deploy(\n        ethers.constants.AddressZero, \n        oracle.address, \n        weth.address, \n        random.address, \n        wSqueethEthPool.address, \n        hedgeTimeTolerance, \n        hedgePriceTolerance, \n        auctionTime, \n        minAuctionSlippage, \n        maxAuctionSlippage)).to.be.revertedWith(\"invalid controller address\");\n    });\n\n    it(\"Should revert if oracle is address 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address, \n        ethers.constants.AddressZero, \n        weth.address, \n        random.address, \n        wSqueethEthPool.address,\n        hedgeTimeTolerance, \n        hedgePriceTolerance, \n        auctionTime, \n        minAuctionSlippage, \n        maxAuctionSlippage)).to.be.revertedWith(\"invalid oracle address\");\n    });\n\n    it(\"Should revert if uniswap factory is address 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address, \n        oracle.address, \n        weth.address, \n        ethers.constants.AddressZero, \n        wSqueethEthPool.address, \n        hedgeTimeTolerance, \n        hedgePriceTolerance, \n        auctionTime, minAuctionSlippage, \n        maxAuctionSlippage)).to.be.revertedWith(\"invalid factory address\");\n    });\n\n    it(\"Should revert if wSqueethEth pool is address 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address, \n        weth.address, \n        random.address, \n        ethers.constants.AddressZero, \n        hedgeTimeTolerance, \n        hedgePriceTolerance, \n        auctionTime, \n        minAuctionSlippage, \n        maxAuctionSlippage)).to.be.revertedWith(\"invalid ETH:WSqueeth address\");\n    });\n\n    it(\"Should revert if hedge time tolerrance is 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address, \n        weth.address, \n        random.address, \n        wSqueethEthPool.address, \n        0, \n        hedgePriceTolerance, \n        auctionTime, \n        minAuctionSlippage, \n        maxAuctionSlippage)).to.be.revertedWith(\"invalid hedge time threshold\");\n    });\n\n    it(\"Should revert if hedge price tolerance is 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address, \n        weth.address, \n        random.address, \n        wSqueethEthPool.address, \n        hedgeTimeTolerance, \n        0, \n        auctionTime, \n        minAuctionSlippage, \n        maxAuctionSlippage)).to.be.revertedWith(\"invalid hedge price threshold\");\n    });\n\n    it(\"Should revert if invalid auction time is 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address, \n        weth.address, \n        random.address, \n        wSqueethEthPool.address, \n        hedgeTimeTolerance, \n        hedgePriceTolerance, \n        0, \n        minAuctionSlippage, \n        maxAuctionSlippage)).to.be.revertedWith(\"invalid auction time\");\n    });\n    \n    it(\"Should revert if min auction slippage > 1e18 \", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address, \n        weth.address, \n        random.address, \n        wSqueethEthPool.address, \n        hedgeTimeTolerance, \n        hedgePriceTolerance, \n        auctionTime, \n        ethers.utils.parseUnits('1.01'), \n        maxAuctionSlippage)).to.be.revertedWith(\"min price multiplier too high\");\n    });\n    \n    it(\"Should revert if min price multiplier is 0\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address, \n        weth.address, \n        random.address, \n        wSqueethEthPool.address, \n        hedgeTimeTolerance, \n        hedgePriceTolerance, \n        auctionTime, \n        0, \n        maxAuctionSlippage)).to.be.revertedWith(\"invalid min price multiplier\");\n    });\n    \n    it(\"Should revert if max price multplier < 1e18\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      await expect(CrabStrategyContract.deploy(\n        controller.address,\n        oracle.address, \n        weth.address, \n        random.address, \n        wSqueethEthPool.address, \n        hedgeTimeTolerance, \n        hedgePriceTolerance, \n        auctionTime, \n        minAuctionSlippage, \n        ethers.utils.parseUnits('0.99'))).to.be.revertedWith(\"max price multiplier too low\");\n    });\n    \n    \n    it(\"Deployment\", async function () {\n      const CrabStrategyContract = await ethers.getContractFactory(\"CrabStrategy\");\n      crabStrategy = (await CrabStrategyContract.deploy(controller.address, oracle.address, weth.address, random.address, wSqueethEthPool.address, hedgeTimeTolerance, hedgePriceTolerance, auctionTime, minAuctionSlippage, maxAuctionSlippage)) as CrabStrategy;\n    });\n  });\n\n  describe(\"Crab strategy vault\", async () => {\n    it(\"Check crab details\",  async () => {\n      const name = await crabStrategy.name()\n      const symbol = await crabStrategy.symbol()\n\n      expect(name).to.be.eq(\"Crab Strategy\")\n      expect(symbol).to.be.eq(\"Crab\")\n    })\n    it(\"Check crab strategy opened vault\", async () => {\n      const openedVaultId = await crabStrategy.getStrategyVaultId()\n\n      expect(openedVaultId).to.be.eq(BigNumber.from(1))\n    });\n  });\n\n  describe(\"receive checks\", async () => {\n    it('should revert when sending eth to crab strategy contract from an EOA', async() => {\n      await expect(random.sendTransaction({to: crabStrategy.address, value:1})).to.be.revertedWith('Cannot receive eth')\n    })\n  });\n\n  describe(\"set strategy cap\", async () => {\n    const strategyCap = ethers.utils.parseUnits(\"100\")\n    const wSqueethEthPrice = BigNumber.from('3030').mul(one).div(oracleScaleFactor)\n    const ethUSDPrice = BigNumber.from('3000').mul(one)\n\n    before(async () => {\n      await oracle.connect(owner).setPrice(wSqueethEthPool.address, wSqueethEthPrice)\n      await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPrice)  // usdc per 1 eth\n    })\n\n    it('should revert non owner tries to set the strategy cap', async() => {\n      await expect(crabStrategy.connect(random).setStrategyCap(strategyCap)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n    it('should revert if no cap is set (initially 0 cap)', async() => {\n      const strategyCap = await crabStrategy.strategyCap()\n      const ethToDeposit = 1\n      expect(strategyCap.eq(0)).to.be.true\n\n      await expect(crabStrategy.connect(depositor2).deposit({value: 1})).to.be.revertedWith(\"Deposit exceeds strategy cap\");\n    })\n\n    it('should allow owner to increase the strategy cap', async() => {\n      await crabStrategy.connect(owner).setStrategyCap(strategyCap.mul(2))\n      const strategyCapInContract = await crabStrategy.strategyCap()\n      expect(strategyCapInContract.eq(strategyCap.mul(2))).to.be.true\n    })\n\n    it('should allow owner to reduce the strategy cap', async() => {\n      await crabStrategy.connect(owner).setStrategyCap(strategyCap)\n      const strategyCapInContract = await crabStrategy.strategyCap()\n      expect(strategyCapInContract.eq(strategyCap)).to.be.true\n    })\n  });\n\n  describe(\"set other params\", async () => {\n\n    const newHedgeTimeTolerance = 172800  // 48h\n    const newHedgePriceTolerance = ethers.utils.parseUnits('0.1')\n    const newAuctionTime = 1200\n    const newMinAuctionSlippage = ethers.utils.parseUnits('0.9')\n    const revertMinAuctionSlippage = ethers.utils.parseUnits('1')\n    const newMaxAuctionSlippage = ethers.utils.parseUnits('1.1')\n    const revertMaxAuctionSlippage = ethers.utils.parseUnits('1')\n    const newTwapPeriod = 300 // 5 minutes\n    const newDeltaHedgeThreshold = ethers.utils.parseUnits('0.01')\n    const revertDeltaHedgeThreshold = ethers.utils.parseUnits('0.3')\n\n\n    it('should revert if non owner tries to change the hedge time threshold', async() => {\n      await expect(crabStrategy.connect(random).setHedgeTimeThreshold(newHedgeTimeTolerance)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n    it('should revert if owner tries to change the hedge time threshold to 0', async() => {\n      await expect(crabStrategy.connect(owner).setHedgeTimeThreshold(0)).to.be.revertedWith(\"invalid hedge time threshold\")\n    })\n\n    it('should allow owner to change the hedge time threshold', async() => {\n      await crabStrategy.connect(owner).setHedgeTimeThreshold(newHedgeTimeTolerance)\n      const hedgeTimeThresholdInContract = await crabStrategy.hedgeTimeThreshold()\n      expect(hedgeTimeThresholdInContract.eq(newHedgeTimeTolerance)).to.be.true\n    })\n\n    it('should allow owner to change the hedge time threshold back', async() => {\n      await crabStrategy.connect(owner).setHedgeTimeThreshold(hedgeTimeTolerance)\n      const hedgeTimeThresholdInContract = await crabStrategy.hedgeTimeThreshold()\n      expect(hedgeTimeThresholdInContract.eq(hedgeTimeTolerance)).to.be.true\n    })\n\n    it('should revert if non owner tries to change the hedge price threshold', async() => {\n      await expect(crabStrategy.connect(random).setHedgePriceThreshold(newHedgePriceTolerance)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n    it('should revert if owner tries to change the hedge price threshold to 0', async() => {\n      await expect(crabStrategy.connect(owner).setHedgePriceThreshold(0)).to.be.revertedWith(\"invalid hedge price threshold\")\n    })\n\n    it('should allow owner to change the hedge price threshold', async() => {\n      await crabStrategy.connect(owner).setHedgePriceThreshold(newHedgePriceTolerance)\n      const hedgePriceThresholdInContract = await crabStrategy.hedgePriceThreshold()\n      expect(hedgePriceThresholdInContract.eq(newHedgePriceTolerance)).to.be.true\n    })\n\n    it('should allow owner to change the hedge price threshold back', async() => {\n      await crabStrategy.connect(owner).setHedgePriceThreshold(hedgePriceTolerance)\n      const hedgePriceThresholdInContract = await crabStrategy.hedgePriceThreshold()\n      expect(hedgePriceThresholdInContract.eq(hedgePriceTolerance)).to.be.true\n    })\n\n    it('should revert if non owner tries to change the auction time', async() => {\n      await expect(crabStrategy.connect(random).setAuctionTime(newAuctionTime)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n    it('should revert if owner tries to change the auction time to 0', async() => {\n      await expect(crabStrategy.connect(owner).setAuctionTime(0)).to.be.revertedWith(\"invalid auction time\")\n    })\n\n    it('should allow owner to change the auction time', async() => {\n      await crabStrategy.connect(owner).setAuctionTime(newAuctionTime)\n      const auctionTimeInContract = await crabStrategy.auctionTime()\n      expect(auctionTimeInContract.eq(newAuctionTime)).to.be.true\n    })\n\n    it('should allow owner to change the auction time back', async() => {\n      await crabStrategy.connect(owner).setAuctionTime(auctionTime)\n      const auctionTimeInContract = await crabStrategy.auctionTime()\n      expect(auctionTimeInContract.eq(auctionTime)).to.be.true\n    })\n\n    it('should revert if non owner tries to change the min price multiplier', async() => {\n      await expect(crabStrategy.connect(random).setMinPriceMultiplier(newMinAuctionSlippage)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n    it('should revert if owner tries to change the min price multiplier to too high of a value', async() => {\n      await expect(crabStrategy.connect(owner).setMinPriceMultiplier(revertMinAuctionSlippage)).to.be.revertedWith(\"min price multiplier too high\")\n    })\n\n    it('should allow owner to change the min price multiplier', async() => {\n      await crabStrategy.connect(owner).setMinPriceMultiplier(newMinAuctionSlippage)\n      const newMinAuctionSlippageInContract = await crabStrategy.minPriceMultiplier()\n      expect(newMinAuctionSlippageInContract.eq(newMinAuctionSlippage)).to.be.true\n    })\n\n    it('should allow owner to change the min price multiplier back', async() => {\n      await crabStrategy.connect(owner).setMinPriceMultiplier(minAuctionSlippage)\n      const newMinAuctionSlippageInContract = await crabStrategy.minPriceMultiplier()\n      expect(newMinAuctionSlippageInContract.eq(minAuctionSlippage)).to.be.true\n    })\n\n    it('should revert if non owner tries to change the max price multiplier', async() => {\n      await expect(crabStrategy.connect(random).setMaxPriceMultiplier(newMaxAuctionSlippage)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n    \n    it('should revert if owner tries to change the max price multiplier to too low of a value', async() => {\n      await expect(crabStrategy.connect(owner).setMaxPriceMultiplier(revertMaxAuctionSlippage)).to.be.revertedWith(\"max price multiplier too low\")\n    })\n\n    it('should allow owner to change the max price multiplier', async() => {\n      await crabStrategy.connect(owner).setMaxPriceMultiplier(newMaxAuctionSlippage)\n      const newMaxAuctionSlippageInContract = await crabStrategy.maxPriceMultiplier()\n      expect(newMaxAuctionSlippageInContract.eq(newMaxAuctionSlippage)).to.be.true\n    })\n\n    it('should allow owner to change the max price multiplier back', async() => {\n      await crabStrategy.connect(owner).setMaxPriceMultiplier(maxAuctionSlippage)\n      const newMaxAuctionSlippageInContract = await crabStrategy.maxPriceMultiplier()\n      expect(newMaxAuctionSlippageInContract.eq(maxAuctionSlippage)).to.be.true\n    })\n\n    it('should revert if non owner tries to change the delta hedge threshold', async() => {\n      await expect(crabStrategy.connect(random).setDeltaHedgeThreshold(newDeltaHedgeThreshold)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n    it('should allow owner to change the delta hedge threshold and then change it back', async() => {\n      const deltaHedgeThresholdBefore = await crabStrategy.deltaHedgeThreshold()\n      await crabStrategy.connect(owner).setDeltaHedgeThreshold(newDeltaHedgeThreshold)\n      const newDeltaHedgeThresholdInContract = await crabStrategy.deltaHedgeThreshold()\n      expect(newDeltaHedgeThresholdInContract.eq(newDeltaHedgeThreshold)).to.be.true\n      await crabStrategy.connect(owner).setDeltaHedgeThreshold(deltaHedgeThresholdBefore)\n      const newDeltaHedgeThresholdInContractRevert = await crabStrategy.deltaHedgeThreshold()\n      expect(newDeltaHedgeThresholdInContractRevert.eq(deltaHedgeThresholdBefore)).to.be.true\n    })\n\n    it('should revert if non owner tries to change the delta hedge threshold', async() => {\n      await expect(crabStrategy.connect(random).setHedgingTwapPeriod(newTwapPeriod)).to.be.revertedWith(\"Ownable: caller is not the owner\")\n    })\n\n\n    it('should revert if owner tries to change the twap period to too short of a value', async() => {\n      await expect(crabStrategy.connect(owner).setHedgingTwapPeriod(179)).to.be.revertedWith(\"twap period is too short\")\n    })\n\n    it('should allow owner to change the twap period and then change it back', async() => {\n      \n      const twapPeriodBefore = await crabStrategy.hedgingTwapPeriod()\n      await crabStrategy.connect(owner).setHedgingTwapPeriod(newTwapPeriod)\n      const newTwapPeriodInContract = await crabStrategy.hedgingTwapPeriod()\n      expect(newTwapPeriodInContract===newTwapPeriod).to.be.true\n      await crabStrategy.connect(owner).setHedgingTwapPeriod(twapPeriodBefore)\n      const newTwapPeriodInContractRevert = await crabStrategy.hedgingTwapPeriod()\n      expect(newTwapPeriodInContractRevert===twapPeriodBefore).to.be.true\n    })\n  });\n\n  describe(\"Deposit into strategy\", async () => {\n    const wSqueethEthPrice = BigNumber.from('3030').mul(one).div(oracleScaleFactor)\n    const ethUSDPrice = BigNumber.from('3000').mul(one)\n    \n    before(async () => {\n      await oracle.connect(owner).setPrice(wSqueethEthPool.address, wSqueethEthPrice)\n      await oracle.connect(random).setPrice(ethUSDPool.address , ethUSDPrice)  // usdc per 1 eth\n    })\n\n    it(\"Should deposit and mint correct LP when initial debt = 0\", async () => {\n      const normFactor = BigNumber.from(1)\n      const ethToDeposit = BigNumber.from(60).mul(one)\n      const squeethDelta = wSqueethEthPrice.mul(2);\n      // const feeAdj = ethUSDPrice.mul(100).div(10000)\n      const feeAdj = 0\n      const debtToMint = ethToDeposit.mul(one).div(squeethDelta.add(feeAdj));\n      const expectedMintedWsqueeth = debtToMint.mul(normFactor)\n\n      await crabStrategy.connect(depositor).deposit({value: ethToDeposit});\n\n      const totalSupply = (await crabStrategy.totalSupply())\n      const depositorCrab = (await crabStrategy.balanceOf(depositor.address))\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const debtAmount = strategyVault.shortAmount\n      const depositorSqueethBalance = await squeeth.balanceOf(depositor.address)\n      const strategyContractSqueeth = await squeeth.balanceOf(crabStrategy.address)\n\n      expect(totalSupply.eq(ethToDeposit)).to.be.true\n      expect(depositorCrab.eq(ethToDeposit)).to.be.true\n      expect(isSimilar(debtAmount.toString(), debtToMint.toString(), 10)).to.be.true\n      expect(isSimilar(depositorSqueethBalance.toString(), expectedMintedWsqueeth.toString(), 10)).to.be.true\n      expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n    })\n\n    it(\"Should deposit and mint correct LP when initial debt != 0 and return the correct amount of wSqueeth debt per crab strategy token\", async () => {\n      const normFactor = BigNumber.from(1)\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtBefore = strategyVault.shortAmount\n      const strategyCollateralBefore = strategyVault.collateralAmount\n      const totalCrabBefore = await crabStrategy.totalSupply()\n\n      const ethToDeposit = BigNumber.from(20).mul(one)\n      const depositorShare = wdiv(ethToDeposit, (strategyCollateralBefore.add(ethToDeposit)))\n      const expectedDepositorCrab = wdiv(wmul(totalCrabBefore, depositorShare), (one.sub(depositorShare)))\n    //   const squeethDelta = wSqueethEthPrice.mul(2);\n\n      // const feeAdj = ethUSDPrice.mul(100).div(10000)\n      const feeAdj = 0\n      const debtToMint = ethToDeposit.mul(strategyDebtBefore).div(strategyCollateralBefore.add(strategyDebtBefore.mul(feeAdj).div(one)));\n      const expectedMintedWsqueeth = debtToMint.mul(normFactor)\n\n      await crabStrategy.connect(depositor2).deposit({value: ethToDeposit});\n\n      const totalCrabAfter = (await crabStrategy.totalSupply())\n      const depositorCrab = (await crabStrategy.balanceOf(depositor2.address))\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const debtAmount = strategyVaultAfter.shortAmount\n      const depositorSqueethBalance = await squeeth.balanceOf(depositor2.address)\n      const strategyContractSqueeth = await squeeth.balanceOf(crabStrategy.address)\n      const depositorWSqueethDebt = await crabStrategy.getWsqueethFromCrabAmount(depositorCrab)\n\n      expect(totalCrabAfter.eq(totalCrabBefore.add(expectedDepositorCrab))).to.be.true\n      expect(depositorCrab.eq(expectedDepositorCrab)).to.be.true\n      expect(isSimilar(strategyDebtBefore.add(debtToMint).toString(), debtAmount.toString(), 10)).to.be.true\n      expect(isSimilar(depositorSqueethBalance.toString(), expectedMintedWsqueeth.toString(), 10)).to.be.true\n      expect(strategyContractSqueeth.eq(BigNumber.from(0))).to.be.true\n      expect(depositorWSqueethDebt.eq(depositorSqueethBalance))    \n    })\n    it('should revert if cap is hit', async() => {\n      const strategyCap = await crabStrategy.strategyCap()\n      const result = await crabStrategy.getVaultDetails()\n      const ethToDeposit = strategyCap.sub(result[2]).add(1)\n\n      await expect(crabStrategy.connect(depositor2).deposit({value: ethToDeposit})).to.be.revertedWith(\"Deposit exceeds strategy cap\");\n    })\n  })\n\n  describe(\"Withdraw from strategy\", async () => {\n    it(\"should revert withdrawing from a random account\", async () => {\n      const depositorSqueethBalanceBefore = await squeeth.balanceOf(depositor.address)\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor.address))\n      const wSqueethAmount = depositorSqueethBalanceBefore\n\n      await squeeth.connect(random).approve(crabStrategy.address, depositorCrabBefore)\n\n      await expect(\n        crabStrategy.connect(random).withdraw(depositorCrabBefore)\n      ).to.be.revertedWith(\"ERC20: transfer amount exceeds balance\");\n    })\n\n    it(\"should withdraw 0 correctly\", async () => {\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtBefore = strategyVault.shortAmount\n      const strategyCollateralBefore = strategyVault.collateralAmount\n      const totalCrabBefore = await crabStrategy.totalSupply()\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor.address))\n      const depositorSqueethBalanceBefore = await squeeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const expectedCrabPercentage = wdiv(depositorCrabBefore, totalCrabBefore)\n      const expectedEthToWithdraw = wmul(strategyCollateralBefore, expectedCrabPercentage)\n\n      await squeeth.connect(depositor).approve(crabStrategy.address, 0)\n      await crabStrategy.connect(depositor).withdraw(0);  \n\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAfter = strategyVaultAfter.shortAmount\n      const totalCrabAfter = await crabStrategy.totalSupply()\n      const depositorCrabAfter = (await crabStrategy.balanceOf(depositor.address))\n      const depositorSqueethBalanceAfter = await squeeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(depositorSqueethBalanceAfter.eq(depositorSqueethBalanceBefore)).to.be.true\n      expect(depositorCrabAfter.eq(depositorCrabBefore)).to.be.true\n      expect(totalCrabAfter.eq(totalCrabBefore)).to.be.true\n      expect(strategyCollateralAfter.eq(strategyCollateralBefore)).to.be.true\n      expect(strategyDebtAfter.eq(strategyDebtBefore)).to.be.true\n      expect(isSimilar(depositorEthBalanceAfter.toString(),depositorEthBalanceBefore.toString())).to.be.true\n    })\n\n    it(\"should withdraw correct amount\", async () => {\n      const strategyVault = await controller.vaults(await crabStrategy.vaultId());\n      const strategyDebtBefore = strategyVault.shortAmount\n      const strategyCollateralBefore = strategyVault.collateralAmount\n      const totalCrabBefore = await crabStrategy.totalSupply()\n      const depositorCrabBefore = (await crabStrategy.balanceOf(depositor.address))\n      const depositorSqueethBalanceBefore = await squeeth.balanceOf(depositor.address)\n      const depositorEthBalanceBefore = await provider.getBalance(depositor.address)\n\n      const expectedCrabPercentage = wdiv(depositorCrabBefore, totalCrabBefore)\n      const expectedEthToWithdraw = wmul(strategyCollateralBefore, expectedCrabPercentage)\n\n      await squeeth.connect(depositor).approve(crabStrategy.address, depositorSqueethBalanceBefore)\n      await crabStrategy.connect(depositor).withdraw(depositorCrabBefore);  \n\n      const strategyVaultAfter = await controller.vaults(await crabStrategy.vaultId());\n      const strategyCollateralAfter = strategyVaultAfter.collateralAmount\n      const strategyDebtAfter = strategyVaultAfter.shortAmount\n      const totalCrabAfter = await crabStrategy.totalSupply()\n      const depositorCrabAfter = (await crabStrategy.balanceOf(depositor.address))\n      const depositorSqueethBalanceAfter = await squeeth.balanceOf(depositor.address)\n      const depositorEthBalanceAfter = await provider.getBalance(depositor.address)\n\n      expect(depositorSqueethBalanceAfter.eq(BigNumber.from(0))).to.be.true\n      expect(depositorSqueethBalanceBefore.gt(BigNumber.from(0))).to.be.true\n      expect(depositorCrabAfter.eq(BigNumber.from(0))).to.be.true\n      expect(totalCrabAfter.eq(totalCrabBefore.sub(depositorCrabBefore))).to.be.true\n      expect(strategyCollateralAfter.eq(strategyCollateralBefore.sub(expectedEthToWithdraw))).to.be.true\n      expect(strategyDebtAfter.eq(strategyDebtBefore.sub(depositorSqueethBalanceBefore))).to.be.true\n      expect(isSimilar(depositorEthBalanceAfter.sub(depositorEthBalanceBefore).toString(), expectedEthToWithdraw.toString())).to.be.true\n    })\n  })  \n})\n"
  },
  {
    "path": "packages/hardhat/test/unit-tests/strategy/timelock.ts",
    "content": "import { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\nimport { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { BigNumber, providers } from \"ethers\";\nimport { MockTimelock, Timelock } from \"../../../typechain\";\n\ndescribe(\"Timelock\", async function () {\n  let owner: SignerWithAddress;\n  let nonAdmin: SignerWithAddress;\n  let newAdmin: SignerWithAddress;\n  let provider: providers.JsonRpcProvider;\n  let timelock: MockTimelock\n  let signature = 'setDelay(uint256)';\n  const abi = new ethers.utils.AbiCoder();\n\n  const threeDays = 259200\n  const newDelay = threeDays + 600\n  let data = abi.encode(['uint256'], [newDelay]);\n\n  this.beforeAll(\"Prepare accounts\", async () => {\n    const accounts = await ethers.getSigners();\n    [owner, nonAdmin, newAdmin] = accounts;\n    provider = ethers.provider\n  })\n\n  this.beforeEach(\"Setup environment\", async () => {\n    const timelockContract = await ethers.getContractFactory(\"MockTimelock\")\n    timelock = (await timelockContract.deploy(owner.address, threeDays)) as MockTimelock\n  })\n\n  describe(\"Deployment\", async () => {\n    it(\"Should revert if delay is less than minimum delay\", async () => {\n      const timelockContract = await ethers.getContractFactory(\"MockTimelock\")\n      await expect(timelockContract.deploy(owner.address, 24 * 60 * 60)).to.be.revertedWith(\"Timelock::constructor: Delay must exceed minimum delay.\")\n    })\n\n    it(\"Should revert if delay is greater maximum delay\", async () => {\n      const timelockContract = await ethers.getContractFactory(\"MockTimelock\")\n      await expect(timelockContract.deploy(owner.address, 31 * 24 * 60 * 60)).to.be.revertedWith(\"Timelock::setDelay: Delay must not exceed maximum delay.\")\n    })\n\n    it(\"Should deploy with correct params\", async () => {\n      const timelockContract = await ethers.getContractFactory(\"MockTimelock\")\n      timelock = (await timelockContract.deploy(owner.address, threeDays)) as MockTimelock\n      const admin = await timelock.admin()\n      const delay = await timelock.delay()\n\n      expect(admin).to.be.equal(owner.address)\n      expect(delay.eq(threeDays)).to.be.true\n    })\n  })\n\n  describe(\"setDelay\", async () => {\n    it(\"Should revert if not called by timelock\", async () => {\n      await expect(timelock.setDelay(newDelay)).to.be.revertedWith(\"Timelock::setDelay: Call must come from Timelock.\")\n    })\n  })\n\n  describe(\"setPendingAdmin\", async () => {\n    it(\"Should revert if not called by timelock\", async () => {\n      await expect(timelock.setPendingAdmin(newAdmin.address)).to.be.revertedWith(\"Timelock::setPendingAdmin: Call must come from Timelock.\")\n    })\n  })\n\n  describe(\"acceptAdmin\", async () => {\n    afterEach(async () => {\n      await timelock.mockSetAdmin(owner.address)\n    })\n\n    it(\"Should revert if not called by pending admin\", async () => {\n      await timelock.mockSetPendingAdmin(newAdmin.address)\n      await expect(timelock.connect(owner).acceptAdmin()).to.be.revertedWith(\"Timelock::acceptAdmin: Call must come from pendingAdmin.\")\n    })\n\n    it(\"Should be accepted if called by pending admin\", async () => {\n      await timelock.mockSetPendingAdmin(newAdmin.address)\n      await timelock.connect(newAdmin).acceptAdmin()\n      const admin = await timelock.admin()\n      expect(admin).to.be.equal(newAdmin.address)\n    })\n  })\n\n  describe(\"queueTransaction\", () => {\n    it(\"Should revert if sender is not admin\", async () => {\n      await expect(timelock.connect(nonAdmin).queueTransaction(timelock.address, 0, signature, data, newDelay)).to.be.revertedWith('Timelock::queueTransaction: Call must come from admin.')\n    })\n\n    it(\"Should revert if eta is smaller than the delay\", async () => {\n      await expect(timelock.connect(owner).queueTransaction(timelock.address, 0, signature, data, newDelay)).to.be.revertedWith('Timelock::queueTransaction: Estimated execution block must satisfy delay.')\n    })\n\n    it(\"Should queue properly\", async () => {\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      const eta = currentBlock.timestamp + newDelay\n      const txHash = ethers.utils.keccak256(abi.encode(['address', 'uint256', 'string', 'bytes', 'uint256'],\n        [timelock.address, '0', signature, data, eta.toString()]))\n\n      expect(await timelock.queuedTransactions(txHash)).to.be.false\n\n      await expect(timelock.connect(owner).queueTransaction(timelock.address, 0, signature, data, eta)).to.emit(timelock, \"QueueTransaction\")\n\n      expect(await timelock.queuedTransactions(txHash)).to.be.true\n    })\n  })\n\n  describe(\"cancelTransaction\", () => {\n    let txHash = ''\n    let eta = 0\n\n    beforeEach(async () => {\n      const currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      eta = currentBlock.timestamp + newDelay\n      txHash = ethers.utils.keccak256(abi.encode(['address', 'uint256', 'string', 'bytes', 'uint256'],\n        [timelock.address, '0', signature, data, eta.toString()]))\n      await timelock.connect(owner).queueTransaction(timelock.address, 0, signature, data, eta)\n    });\n\n    it('Should revert if sender is not admin', async () => {\n      await expect(timelock.connect(nonAdmin).cancelTransaction(timelock.address, 0, signature, data, eta)).to.be.revertedWith('Timelock::cancelTransaction: Call must come from admin.')\n    });\n\n    it('Should mark the tx as canceled if called by admin', async () => {\n      expect(await timelock.queuedTransactions(txHash)).to.be.true\n\n      await expect(timelock.connect(owner).cancelTransaction(timelock.address, 0, signature, data, eta)).to.emit(timelock, \"CancelTransaction\")\n\n      expect(await timelock.queuedTransactions(txHash)).to.be.false\n    });\n  })\n\n  describe(\"executeTransaction (setDelay)\", () => {\n    let txHash = ''\n    let eta = 0\n    let currentBlockNumber = 0\n    let currentBlockTimestamp = 0\n\n    beforeEach(async () => {\n      currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      eta = currentBlock.timestamp + threeDays + 1\n      currentBlockTimestamp = currentBlock.timestamp\n      txHash = ethers.utils.keccak256(abi.encode(['address', 'uint256', 'string', 'bytes', 'uint256'],\n        [timelock.address, '0', signature, data, eta.toString()]))\n      await timelock.connect(owner).queueTransaction(timelock.address, 0, signature, data, eta)\n    });\n\n    it('Should revert if sender is not admin', async () => {\n      await expect(timelock.connect(nonAdmin).executeTransaction(timelock.address, 0, signature, data, eta)).to.be.revertedWith('Timelock::executeTransaction: Call must come from admin.')\n    });\n\n    it('Should revert if tx is not queued', async () => {\n      await expect(timelock.connect(owner).executeTransaction(timelock.address, 0, signature, data, eta + 1)).to.be.revertedWith(\"Timelock::executeTransaction: Transaction hasn't been queued.\")\n    });\n\n    it('Should revert if called before timelock', async () => {\n      await expect(timelock.connect(owner).executeTransaction(timelock.address, 0, signature, data, eta)).to.be.revertedWith(\"Timelock::executeTransaction: Transaction hasn't surpassed time lock.\")\n    });\n\n    it('Should revert if the execution is reverted', async () => {\n      const wrongData = abi.encode(['uint256'], [1]);\n      txHash = ethers.utils.keccak256(abi.encode(['address', 'uint256', 'string', 'bytes', 'uint256'],\n        [timelock.address, '0', signature, wrongData, eta + 500]))\n\n      await timelock.connect(owner).queueTransaction(timelock.address, 0, signature, wrongData, eta + 500)\n\n      await provider.send(\"evm_setNextBlockTimestamp\", [eta + 700])\n\n      await expect(timelock.connect(owner).executeTransaction(timelock.address, 0, signature, wrongData, eta + 500)).to.be.revertedWith(\"Timelock::executeTransaction: Transaction execution reverted.\")\n    });\n\n    it('Should execute the tx if called after eta', async () => {\n      await provider.send(\"evm_setNextBlockTimestamp\", [currentBlockTimestamp + threeDays + 2])\n      expect((await timelock.delay()).eq(threeDays)).to.be.true\n      expect(await timelock.queuedTransactions(txHash)).to.be.true\n\n      await expect(timelock.connect(owner).executeTransaction(timelock.address, 0, signature, data, eta)).to.emit(timelock, \"ExecuteTransaction\")\n\n      expect((await timelock.delay()).eq(newDelay)).to.be.true\n      expect(await timelock.queuedTransactions(txHash)).to.be.false\n\n    });\n  })\n\n  describe(\"executeTransaction (setPendingAdmin)\", () => {\n    let txHash = ''\n    let eta = 0\n    let currentBlockNumber = 0\n    let currentBlockTimestamp = 0\n\n    beforeEach(async () => {\n      currentBlockNumber = await provider.getBlockNumber()\n      const currentBlock = await provider.getBlock(currentBlockNumber)\n      eta = currentBlock.timestamp + threeDays + 1\n      currentBlockTimestamp = currentBlock.timestamp\n\n      signature = 'setPendingAdmin(address)';\n      data = abi.encode(['address'], [newAdmin.address]);\n\n      txHash = ethers.utils.keccak256(abi.encode(['address', 'uint256', 'string', 'bytes', 'uint256'],\n        [timelock.address, '0', signature, data, eta.toString()]))\n      await timelock.connect(owner).queueTransaction(timelock.address, 0, signature, data, eta)\n    });\n\n    it('Should revert if sender is not admin', async () => {\n      await expect(timelock.connect(nonAdmin).executeTransaction(timelock.address, 0, signature, data, eta)).to.be.revertedWith('Timelock::executeTransaction: Call must come from admin.')\n    });\n\n    it('Should revert if tx is not queued', async () => {\n      await expect(timelock.connect(owner).executeTransaction(timelock.address, 0, signature, data, eta + 1)).to.be.revertedWith(\"Timelock::executeTransaction: Transaction hasn't been queued.\")\n    });\n\n    it('Should revert if called before timelock', async () => {\n      await expect(timelock.connect(owner).executeTransaction(timelock.address, 0, signature, data, eta)).to.be.revertedWith(\"Timelock::executeTransaction: Transaction hasn't surpassed time lock.\")\n    });\n\n    it('Should execute the tx if called after eta', async () => {\n      await provider.send(\"evm_setNextBlockTimestamp\", [currentBlockTimestamp + threeDays + 2])\n      expect(await timelock.queuedTransactions(txHash)).to.be.true\n      expect((await timelock.pendingAdmin())).to.be.equal(ethers.constants.AddressZero)\n\n      await expect(timelock.connect(owner).executeTransaction(timelock.address, 0, signature, data, eta)).to.emit(timelock, \"NewPendingAdmin\")\n\n      expect(await timelock.queuedTransactions(txHash)).to.be.false\n      expect((await timelock.pendingAdmin())).to.be.equal(newAdmin.address)\n    });\n  })\n})"
  },
  {
    "path": "packages/hardhat/test/unit-tests/vault-lib.ts",
    "content": "import { ethers } from \"hardhat\"\nimport { expect } from \"chai\";\nimport { parseEther } from \"ethers/lib/utils\";\nimport { BigNumber } from \"ethers\";\nimport { MockWPowerPerp, MockUniswapV3Pool, MockErc20, MockUniPositionManager, VaultLibTester } from \"../../typechain\";\nimport { getSqrtPriceAndTickBySqueethPrice, getYAmountAboveRange, getXAmountBelowRange } from \"../calculator\";\nimport { isSimilar, one, oracleScaleFactor } from \"../utils\";\n\n\ndescribe(\"VaultLib\", function () {\n  let squeeth: MockWPowerPerp;\n  let vaultLib: VaultLibTester\n  let squeethEthPool: MockUniswapV3Pool;\n  let uniPositionManager: MockUniPositionManager\n  let weth: MockErc20;\n  let wethIsToken0: boolean\n\n  this.beforeAll(\"Setup environment\", async () => {\n    const MockSQUContract = await ethers.getContractFactory(\"MockWPowerPerp\");\n    squeeth = (await MockSQUContract.deploy()) as MockWPowerPerp;\n\n    const MockErc20Contract = await ethers.getContractFactory(\"MockErc20\");\n    weth = (await MockErc20Contract.deploy(\"WETH\", \"WETH\", 18)) as MockErc20;\n\n    const MockUniswapV3PoolContract = await ethers.getContractFactory(\"MockUniswapV3Pool\");\n    squeethEthPool = (await MockUniswapV3PoolContract.deploy()) as MockUniswapV3Pool;\n\n    const MockPositionManager = await ethers.getContractFactory(\"MockUniPositionManager\");\n    uniPositionManager = (await MockPositionManager.deploy()) as MockUniPositionManager;\n\n    // set token0 and token1 for squeeth/eth pool\n    wethIsToken0 = parseInt(weth.address, 16) < parseInt(squeeth.address, 16)\n    if (wethIsToken0) {\n      await squeethEthPool.setPoolTokens(weth.address, squeeth.address);\n    } else {\n      await squeethEthPool.setPoolTokens(squeeth.address, weth.address);\n    }\n  });\n\n  this.beforeAll(\"Deploy VaultLibTester\", async () => {\n\n    const SqrtPriceExternal = await ethers.getContractFactory(\"SqrtPriceMathPartial\")\n    const SqrtPriceExternalLibrary = (await SqrtPriceExternal.deploy());\n\n    const TickMathExternal = await ethers.getContractFactory(\"TickMathExternal\")\n    const TickMathLibrary = (await TickMathExternal.deploy());\n\n    const VaultTester = await ethers.getContractFactory(\"VaultLibTester\", {libraries: {TickMathExternal: TickMathLibrary.address, SqrtPriceMathPartial: SqrtPriceExternalLibrary.address}});\n    vaultLib = (await VaultTester.deploy()) as VaultLibTester;\n  })\n\n  describe(\"#getUniPositionBalances tests\", function () {\n    let token0: string\n    let token1: string\n\n    describe('case: infinite range, price is always within range', async() => {\n      const nftTokenId = 1\n      const ethPrice = BigNumber.from('3000').mul(one)\n      const scaledSqueethEthPrice = ethPrice.div(oracleScaleFactor)\n      let currentSqrtX96Price: string\n      let currentTick: string\n      const wsqueethLiquidityAmount = parseEther('10')\n      const ethLiquidityAmount = parseEther('3')\n\n      before('calculate shared variables', async( )=> {\n        token0 = wethIsToken0 ? weth.address : squeeth.address\n        token1 = wethIsToken0 ? squeeth.address : weth.address\n      })\n\n      before('calculate prices', async() => {\n        const { sqrtPrice, tick } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethEthPrice, wethIsToken0)\n        currentSqrtX96Price = sqrtPrice\n        currentTick = tick\n      })\n\n      before('set lp token properties, assuming entered when price is 3000', async () => {\n        // infinite nft ticks\n        const nftTickUpper = 887220\n        const nftTickLower = -887220\n\n        const liquidity = await vaultLib.getLiquidity(\n          currentSqrtX96Price,\n          nftTickLower,\n          nftTickUpper,\n          wethIsToken0 ? ethLiquidityAmount : wsqueethLiquidityAmount,\n          wethIsToken0 ? wsqueethLiquidityAmount: ethLiquidityAmount,\n        )\n        await uniPositionManager.setMockedProperties(token0, token1, nftTickLower, nftTickUpper, liquidity)\n      })\n\n      before('set initial price', async() => {\n        await squeethEthPool.setSlot0Data(currentSqrtX96Price, currentTick)\n      })\n\n      it('should get the squeeth / eth amount similar to our deposit amount', async() => {        \n        const result = await vaultLib.getUniPositionBalances(uniPositionManager.address, nftTokenId, currentTick, wethIsToken0)\n        // about 0.001 squeeth\n        expect(isSimilar(result.wPowerPerpAmount.toString(), wsqueethLiquidityAmount.toString())).to.be.true\n        // about 3 eth\n        expect(isSimilar(result.ethAmount.toString(), ethLiquidityAmount.toString())).to.be.true\n      })\n\n      it('should get the correct squeeth / eth amount after price changes', async() => {\n        const newPrice = BigNumber.from('5000')\n        const newScaledSqueethPrice = newPrice.mul(one).div(oracleScaleFactor)\n        const { sqrtPrice, tick: newTick } = getSqrtPriceAndTickBySqueethPrice(newScaledSqueethPrice, wethIsToken0)\n        await squeethEthPool.setSlot0Data(sqrtPrice, newTick)\n        \n        const { ethAmount, wPowerPerpAmount } = await vaultLib.getUniPositionBalances(\n          uniPositionManager.address, \n          nftTokenId, \n          newTick,\n          wethIsToken0\n        )\n        // x * y = k\n        expect(isSimilar(ethAmount.mul(wPowerPerpAmount).toString(), ethLiquidityAmount.mul(wsqueethLiquidityAmount).toString())).to.be.true\n        // eth / squeeth is similar to new price\n        expect(isSimilar(ethAmount.mul(oracleScaleFactor).toString(), newPrice.mul(wPowerPerpAmount).toString(), 3)).to.be.true\n      })\n    })\n    \n    describe('case: LP only in a certain range', async() => {\n      const nftTokenId = 1\n      const initSqueethPrice = BigNumber.from('3000').mul(one).div(oracleScaleFactor)\n      let initSqrtX96Price: string\n      let initTick: string\n\n      let wsqueethLiquidityAmount: BigNumber\n      const ethLiquidityAmount = parseEther('30')\n\n      let liquidity: BigNumber\n\n      before('calculate shared variables', async( )=> {\n        token0 = wethIsToken0 ? weth.address : squeeth.address\n        token1 = wethIsToken0 ? squeeth.address : weth.address\n      })\n\n      before('set price parameters', async() => {\n        const { sqrtPrice, tick } = getSqrtPriceAndTickBySqueethPrice(initSqueethPrice, wethIsToken0)\n        initSqrtX96Price = sqrtPrice\n        initTick = tick\n      })\n\n      before('set LP token properties, assuming with enter with init price.', async() => {\n        const { sqrtPrice: sqrtPriceInit } = getSqrtPriceAndTickBySqueethPrice(initSqueethPrice, wethIsToken0)\n\n        const scaledSqueethPrice4500 = BigNumber.from('4500').mul(one).div(oracleScaleFactor)\n        const scaledSqueethPrice2000 = BigNumber.from('2000').mul(one).div(oracleScaleFactor)\n\n        const { sqrtPrice: sqrtPrice4500, tick: tick4000 } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice4500, wethIsToken0)\n        const { sqrtPrice: sqrtPrice2000, tick: tick2000 } = getSqrtPriceAndTickBySqueethPrice(scaledSqueethPrice2000, wethIsToken0)\n\n        // get approximate liquidity value, with 30 eth deposit\n        liquidity = wethIsToken0\n          ? await vaultLib.getLiquidityForAmount0(sqrtPriceInit, sqrtPrice2000, ethLiquidityAmount.toString())\n          : await vaultLib.getLiquidityForAmount1(sqrtPriceInit, sqrtPrice2000, ethLiquidityAmount.toString())\n\n        const tickUpper = wethIsToken0 ? tick2000 : tick4000;\n        const tickLower = wethIsToken0 ? tick4000 : tick2000;\n\n        const result = await vaultLib.getAmountsForLiquidity(sqrtPriceInit, sqrtPrice2000, sqrtPrice4500, liquidity)\n\n        // set reasonable squeeth liquidity amount\n        wsqueethLiquidityAmount = wethIsToken0 \n          ? result.amount1\n          : result.amount0\n\n        // set property: liquidity and ticks\n        await uniPositionManager.setMockedProperties(token0, token1, tickLower, tickUpper, liquidity)\n      })\n\n      describe('case: price remains the same, we\\'re in the range', async() => {\n        before('set initial price', async() => {\n          await squeethEthPool.setSlot0Data(initSqrtX96Price, initTick)\n        })\n        it('should return approximate amount', async() => {\n          const result = await vaultLib.getUniPositionBalances(\n            uniPositionManager.address, \n            nftTokenId, \n            initTick,\n            wethIsToken0\n          )\n          // about 0.01 squeeth\n          expect(isSimilar(result.wPowerPerpAmount.toString(), wsqueethLiquidityAmount.toString(), 3)).to.be.true\n          // about 30 eth\n          expect(isSimilar(result.ethAmount.toString(), ethLiquidityAmount.toString(), 3)).to.be.true\n        })\n      })\n\n      describe('case: current price is 5000, above the LP range', async() => {\n        const highPrice = BigNumber.from('5000').mul(one)\n        let newTick: string;\n        before('set price', async() => {\n          const { sqrtPrice, tick } = getSqrtPriceAndTickBySqueethPrice(highPrice, wethIsToken0)\n          newTick = tick\n          await squeethEthPool.setSlot0Data(sqrtPrice, tick)\n        })\n        it('should return expected amount of squeeth and eth', async() => {\n          const result = await vaultLib.getUniPositionBalances(\n            uniPositionManager.address, \n            nftTokenId, \n            newTick,\n            wethIsToken0\n          )\n          expect(result.wPowerPerpAmount.isZero()).to.be.true\n\n          const upperBound = 4500 / oracleScaleFactor.toNumber()\n          const lowerBound = 2000 / oracleScaleFactor.toNumber()\n\n          const expectedEthAmount = wethIsToken0\n            ? getXAmountBelowRange((1/upperBound), (1/lowerBound), liquidity.toString())\n            : getYAmountAboveRange(lowerBound, upperBound, liquidity.toString())                \n          \n          expect(isSimilar(result.ethAmount.toString(), expectedEthAmount.toString())).to.be.true\n        })\n      })\n\n      describe('case: current price 1900, below the LP range', async() => {\n        const lowPrice = BigNumber.from('1900').mul(one).div(oracleScaleFactor)\n        let newTick: string;\n        before('set price', async() => {\n          const { sqrtPrice, tick } = getSqrtPriceAndTickBySqueethPrice(lowPrice, wethIsToken0)\n          newTick = tick;\n          await squeethEthPool.setSlot0Data(sqrtPrice, tick)\n        })\n        it('should return expected amount of squeeth and eth', async() => {\n          const result = await vaultLib.getUniPositionBalances(\n            uniPositionManager.address, \n            nftTokenId,\n            newTick,\n            wethIsToken0\n          )\n          expect(result.ethAmount.isZero()).to.be.true\n\n          const upperBound = 4500 / oracleScaleFactor.toNumber()\n          const lowerBound = 2000 / oracleScaleFactor.toNumber()\n\n          const expectedSqueethAmount = wethIsToken0\n            ? getYAmountAboveRange((1/upperBound), (1/lowerBound), liquidity.toString())\n            : getXAmountBelowRange(lowerBound, upperBound, liquidity.toString())\n        \n          expect(isSimilar(result.wPowerPerpAmount.toString(), expectedSqueethAmount.toString())).to.be.true             \n\n        })\n      })\n\n      describe('case: current price 2200, within LP range', async() => {\n        const newPrice = BigNumber.from('2200').mul(one).div(oracleScaleFactor)\n        let newTick: string\n        before('set price', async() => {\n          const { sqrtPrice, tick } = getSqrtPriceAndTickBySqueethPrice(newPrice, wethIsToken0)\n          newTick = tick;\n          await squeethEthPool.setSlot0Data(sqrtPrice, tick)\n          \n        })\n        it('should return expected amount of squeeth and eth', async() => {\n          const result = await vaultLib.getUniPositionBalances(\n            uniPositionManager.address, \n            nftTokenId, \n            newTick,\n            wethIsToken0\n          )\n\n          const upperBound = 4500 / oracleScaleFactor.toNumber()\n          const currentPrice = 2200 / oracleScaleFactor.toNumber()\n          const lowerBound = 2000 / oracleScaleFactor.toNumber()\n          \n          const expectedEthAmount = wethIsToken0\n            ? getXAmountBelowRange((1/currentPrice), (1/lowerBound), liquidity.toString())\n            : getYAmountAboveRange(lowerBound, currentPrice, liquidity.toString())    \n          \n          expect(isSimilar(result.ethAmount.toString(), expectedEthAmount.toString(), 3)).to.be.true\n          \n          \n\n          const expectedSqueethAmount = wethIsToken0\n            ? getYAmountAboveRange((1/upperBound), (1/currentPrice), liquidity.toString())\n            : getXAmountBelowRange(currentPrice, upperBound, liquidity.toString())\n\n          expect(isSimilar(result.wPowerPerpAmount.toString(), expectedSqueethAmount.toString())).to.be.true\n        })\n      })\n    })\n  });\n});\n"
  },
  {
    "path": "packages/hardhat/test/utils.ts",
    "content": "import { BigNumber, ContractTransaction } from \"ethers\";\nimport { BigNumber as BigNumberJs } from \"bignumber.js\";\nimport { ethers } from \"hardhat\";\nimport { SignerWithAddress } from \"@nomiclabs/hardhat-ethers/dist/src/signer-with-address\";\n\nexport const one = BigNumber.from(10).pow(18);\nexport const oracleScaleFactor = BigNumber.from(10).pow(4);\n\ntype Vault = [BigNumber, BigNumber, BigNumber] & {\n    NftCollateralId: BigNumber;\n    collateralAmount: BigNumber;\n    shortAmount: BigNumber;\n};\n\nexport const isEmptyVault = (vault: Vault): boolean => {\n    return vault.collateralAmount.isZero() && vault.shortAmount.isZero();\n};\n\nexport const isSimilar = (number1: string, number2: string, precision: number = 4) => {\n    const error = 1 / 10 ** precision;\n    if (number2 === number1) return true;\n    return new BigNumberJs(number1).div(new BigNumberJs(number2)).minus(1).abs().lt(error);\n};\n\nexport const getNow = async (provider: any) => {\n    const blockNumBefore = await provider.getBlockNumber();\n    const blockBefore = await provider.getBlock(blockNumBefore);\n    return blockBefore.timestamp;\n};\n\nexport const UNDERFLOW_ERROR =\n    \"reverted with panic code 0x11 (Arithmetic operation underflowed or overflowed outside of an unchecked block)\";\n\nexport const wmul = (x: BigNumber, y: BigNumber): BigNumber => {\n    const z = x.mul(y).add(one.div(2)).div(one);\n    return z;\n};\n\nexport const wdiv = (x: BigNumber, y: BigNumber): BigNumber => {\n    const z = x.mul(one).add(y.div(2)).div(y);\n    return z;\n};\n\nexport const signTypedData = async (signer: SignerWithAddress, domainData: any, type: any, data: any) => {\n    const signature2 = await signer._signTypedData(domainData, type, data);\n    const { r: r1, s: s1, v: v1 } = ethers.utils.splitSignature(signature2);\n    return {\n        ...data,\n        r: r1,\n        s: s1,\n        v: String(v1),\n    };\n};\n\nexport const getGasPaid = async (tx: ContractTransaction) => {\n    const receipt = await tx.wait();\n    return receipt.gasUsed.mul(receipt.effectiveGasPrice)\n}\n"
  },
  {
    "path": "packages/hardhat/test/vault-utils.ts",
    "content": "import {BigNumber} from 'ethers'\n\ntype Vault = [string, number, BigNumber, BigNumber] & {\n  operator: string\n  NftCollateralId: number;\n  collateralAmount: BigNumber;\n  shortAmount: BigNumber;\n  \n}\n\nexport const isEmptyVault = (vault: Vault): boolean => {\n  return vault.collateralAmount.isZero() && vault.shortAmount.isZero()\n}\n\nexport const UNDERFLOW_ERROR = \"reverted with panic code 0x11 (Arithmetic operation underflowed or overflowed outside of an unchecked block)\""
  },
  {
    "path": "packages/hardhat/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"target\": \"es2018\",\n        \"module\": \"commonjs\",\n        \"strict\": true,\n        \"esModuleInterop\": true,\n        \"outDir\": \"dist\",\n        \"resolveJsonModule\": true\n    },\n    \"include\": [\"./scripts\", \"./test\", \"./tasks\", \"./deploy\"],\n    \"files\": [\"./hardhat.config.ts\"]\n}\n"
  },
  {
    "path": "packages/services/graph-node/Dockerfile",
    "content": "# Full build with debuginfo for graph-node\n#\n# The expectation if that the docker build uses the parent directory as PWD\n# by running something like the following\n#   docker build --target STAGE -f docker/Dockerfile .\n\nFROM rust:latest as graph-node-build\n\nARG COMMIT_SHA=unknown\nARG REPO_NAME=unknown\nARG BRANCH_NAME=unknown\nARG TAG_NAME=unknown\n\nADD . /graph-node\n\nRUN cd /graph-node \\\n && RUSTFLAGS=\"-g\" cargo install --locked --path node \\\n && cargo clean \\\n && objcopy --only-keep-debug /usr/local/cargo/bin/graph-node /usr/local/cargo/bin/graph-node.debug \\\n && strip -g /usr/local/cargo/bin/graph-node \\\n && cd /usr/local/cargo/bin \\\n && objcopy --add-gnu-debuglink=graph-node.debug graph-node \\\n && echo \"REPO_NAME='$REPO_NAME'\" > /etc/image-info \\\n && echo \"TAG_NAME='$TAG_NAME'\" >> /etc/image-info \\\n && echo \"BRANCH_NAME='$BRANCH_NAME'\" >> /etc/image-info \\\n && echo \"COMMIT_SHA='$COMMIT_SHA'\" >> /etc/image-info \\\n && echo \"CARGO_VERSION='$(cargo --version)'\" >> /etc/image-info \\\n && echo \"RUST_VERSION='$(rustc --version)'\" >> /etc/image-info\n\n# The graph-node runtime image with only the executable\nFROM debian:buster-slim as graph-node\nENV RUST_LOG \"\"\nENV GRAPH_LOG \"\"\nENV EARLY_LOG_CHUNK_SIZE \"\"\nENV ETHEREUM_RPC_PARALLEL_REQUESTS \"\"\nENV ETHEREUM_BLOCK_CHUNK_SIZE \"\"\n\nENV postgres_host \"\"\nENV postgres_user \"\"\nENV postgres_pass \"\"\nENV postgres_db \"\"\n# The full URL to the IPFS node\nENV ipfs \"\"\n# The etherum network(s) to connect to. Set this to a space-separated\n# list of the networks where each entry has the form NAME:URL\nENV ethereum \"\"\n# The role the node should have, one of index-node, query-node, or\n# combined-node\nENV node_role \"combined-node\"\n# The name of this node\nENV node_id \"default\"\n\n# HTTP port\nEXPOSE 8000\n# WebSocket port\nEXPOSE 8001\n# JSON-RPC port\nEXPOSE 8020\n\nRUN apt-get update \\\n && apt-get install -y libpq-dev ca-certificates netcat\n\nADD docker/wait_for docker/start /usr/local/bin/\nCOPY --from=graph-node-build /usr/local/cargo/bin/graph-node /usr/local/bin\nCOPY --from=graph-node-build /etc/image-info /etc/image-info\nCOPY docker/Dockerfile /Dockerfile\nCMD start\n\n# Debug image to access core dumps\nFROM graph-node-build as graph-node-debug\nRUN apt-get update \\\n && apt-get install -y curl gdb postgresql-client\n\nCOPY docker/Dockerfile /Dockerfile\nCOPY docker/bin/* /usr/local/bin/\n"
  },
  {
    "path": "packages/services/graph-node/README.md",
    "content": "# Graph Node Docker Image\n\nPreconfigured Docker image for running a Graph Node.\n\n## Usage\n\n```sh\ndocker run -it \\\n  -e postgres_host=<HOST>[:<PORT>] \\\n  -e postgres_user=<USER> \\\n  -e postgres_pass=<PASSWORD> \\\n  -e postgres_db=<DBNAME> \\\n  -e ipfs=<HOST>:<PORT> \\\n  -e ethereum=<NETWORK_NAME>:<ETHEREUM_RPC_URL> \\\n  graphprotocol/graph-node:latest\n```\n\n### Example usage\n\n```sh\ndocker run -it \\\n  -e postgres_host=host.docker.internal:5432\n  -e postgres_user=graph-node \\\n  -e postgres_pass=oh-hello \\\n  -e postgres_db=graph-node \\\n  -e ipfs=host.docker.internal:5001 \\\n  -e ethereum=mainnet:http://localhost:8545/ \\\n  graphprotocol/graph-node:latest\n```\n\n## Docker Compose\n\nThe Docker Compose setup requires an Ethereum network name and node\nto connect to. By default, it will use `mainnet:http://host.docker.internal:8545`\nin order to connect to an Ethereum node running on your host machine.\nYou can replace this with anything else in `docker-compose.yaml`.\n\n> **Note for Linux users:** On Linux, `host.docker.internal` is not\n> currently supported. Instead, you will have to replace it with the\n> IP address of your Docker host (from the perspective of the Graph\n> Node container).\n> To do this, run:\n>\n> ```\n> CONTAINER_ID=$(docker container ls | grep graph-node | cut -d' ' -f1)\n> docker exec $CONTAINER_ID /bin/bash -c 'ip route | awk \\'/^default via /{print $3}\\''\n> ```\n>\n> This will print the host's IP address. Then, put it into `docker-compose.yml`:\n>\n> ```\n> sed -i -e 's/host.docker.internal/<IP ADDRESS>/g' docker-compose.yml\n> ```\n\nAfter you have set up an Ethereum node—e.g. Ganache or Parity—simply\nclone this repository and run\n\n```sh\ndocker-compose up\n```\n\nThis will start IPFS, Postgres and Graph Node in Docker and create persistent\ndata directories for IPFS and Postgres in `./data/ipfs` and `./data/postgres`. You\ncan access these via:\n\n- Graph Node:\n  - GraphiQL: `http://localhost:8000/`\n  - HTTP: `http://localhost:8000/subgraphs/name/<subgraph-name>`\n  - WebSockets: `ws://localhost:8001/subgraphs/name/<subgraph-name>`\n  - Admin: `http://localhost:8020/`\n- IPFS:\n  - `127.0.0.1:5001` or `/ip4/127.0.0.1/tcp/5001`\n- Postgres:\n  - `postgresql://graph-node:let-me-in@localhost:5432/graph-node`\n\nOnce this is up and running, you can use\n[`graph-cli`](https://github.com/graphprotocol/graph-cli) to create and\ndeploy your subgraph to the running Graph Node.\n"
  },
  {
    "path": "packages/services/graph-node/bin/create",
    "content": "#! /bin/bash\n\nif [ $# != 1 ]; then\n    echo \"usage: create <name>\"\n    exit 1\nfi\n\napi=\"http://index-node.default/\"\n\ndata=$(printf '{\"jsonrpc\": \"2.0\", \"method\": \"subgraph_create\", \"params\": {\"name\":\"%s\"}, \"id\":\"1\"}' \"$1\")\ncurl -s -H \"content-type: application/json\" --data \"$data\" \"$api\"\n"
  },
  {
    "path": "packages/services/graph-node/bin/debug",
    "content": "#! /bin/bash\n\nif [ -f \"$1\" ]\nthen\n    exec rust-gdb -c \"$1\" /usr/local/cargo/bin/graph-node\nelse\n    echo \"usage: debug <core-file>\"\n    exit 1\nfi\n"
  },
  {
    "path": "packages/services/graph-node/bin/deploy",
    "content": "#! /bin/bash\n\nif [ $# != 3 ]; then\n    echo \"usage: deploy <name> <ipfs_hash> <node>\"\n    exit 1\nfi\n\napi=\"http://index-node.default/\"\n\necho \"Deploying $1 (deployment $2)\"\ndata=$(printf '{\"jsonrpc\": \"2.0\", \"method\": \"subgraph_deploy\", \"params\": {\"name\":\"%s\", \"ipfs_hash\":\"%s\", \"node_id\":\"%s\"}, \"id\":\"1\"}' \"$1\" \"$2\" \"$3\")\ncurl -s -H \"content-type: application/json\" --data \"$data\" \"$api\"\n"
  },
  {
    "path": "packages/services/graph-node/bin/reassign",
    "content": "#! /bin/bash\n\nif [ $# -lt 3 ]; then\n    echo \"usage: reassign <name> <ipfs_hash> <node>\"\n    exit 1\nfi\n\napi=\"http://index-node.default/\"\n\necho Assigning to \"$3\"\ndata=$(printf '{\"jsonrpc\": \"2.0\", \"method\": \"subgraph_reassign\", \"params\": {\"name\":\"%s\", \"ipfs_hash\":\"%s\", \"node_id\":\"%s\"}, \"id\":\"1\"}' \"$1\" \"$2\" \"$3\")\ncurl -s -H \"content-type: application/json\" --data \"$data\" \"$api\"\n"
  },
  {
    "path": "packages/services/graph-node/bin/remove",
    "content": "#! /bin/bash\n\nif [ $# != 1 ]; then\n    echo \"usage: create <name>\"\n    exit 1\nfi\n\napi=\"http://index-node.default/\"\n\ndata=$(printf '{\"jsonrpc\": \"2.0\", \"method\": \"subgraph_remove\", \"params\": {\"name\":\"%s\"}, \"id\":\"1\"}' \"$1\")\ncurl -s -H \"content-type: application/json\" --data \"$data\" \"$api\"\n"
  },
  {
    "path": "packages/services/graph-node/build.sh",
    "content": "#! /bin/bash\n\n# This file is only here to ease testing/development. Official images are\n# built using the 'cloudbuild.yaml' file\n\ntype -p podman > /dev/null && docker=podman || docker=docker\n\ncd $(dirname $0)/..\n\nif [ -d .git ]\nthen\n    COMMIT_SHA=$(git rev-parse HEAD)\n    TAG_NAME=$(git tag --points-at HEAD)\n    REPO_NAME=\"Checkout of $(git remote get-url origin) at $(git describe --dirty)\"\n    BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)\nfi\nfor stage in graph-node-build graph-node graph-node-debug\ndo\n    $docker build --target $stage \\\n            --build-arg \"COMMIT_SHA=$COMMIT_SHA\" \\\n            --build-arg \"REPO_NAME=$REPO_NAME\" \\\n            --build-arg \"BRANCH_NAME=$BRANCH_NAME\" \\\n            --build-arg \"TAG_NAME=$TAG_NAME\" \\\n            -t $stage \\\n            -f docker/Dockerfile .\ndone\n"
  },
  {
    "path": "packages/services/graph-node/cloudbuild.yaml",
    "content": "options:\n  machineType: \"N1_HIGHCPU_32\"\ntimeout: 1800s\nsteps:\n- name: 'gcr.io/cloud-builders/docker'\n  args: ['build', '--target', 'graph-node-build',\n         '--build-arg', 'COMMIT_SHA=$COMMIT_SHA',\n         '--build-arg', 'REPO_NAME=$REPO_NAME',\n         '--build-arg', 'BRANCH_NAME=$BRANCH_NAME',\n         '--build-arg', 'TAG_NAME=$TAG_NAME',\n         '-t', 'gcr.io/$PROJECT_ID/graph-node-build:$SHORT_SHA',\n         '-f', 'docker/Dockerfile', '.']\n- name: 'gcr.io/cloud-builders/docker'\n  args: ['build', '--target', 'graph-node',\n         '--build-arg', 'COMMIT_SHA=$COMMIT_SHA',\n         '--build-arg', 'REPO_NAME=$REPO_NAME',\n         '--build-arg', 'BRANCH_NAME=$BRANCH_NAME',\n         '--build-arg', 'TAG_NAME=$TAG_NAME',\n         '-t', 'gcr.io/$PROJECT_ID/graph-node:$SHORT_SHA',\n         '-f', 'docker/Dockerfile', '.']\n- name: 'gcr.io/cloud-builders/docker'\n  args: ['build', '--target', 'graph-node-debug',\n         '--build-arg', 'COMMIT_SHA=$COMMIT_SHA',\n         '--build-arg', 'REPO_NAME=$REPO_NAME',\n         '--build-arg', 'BRANCH_NAME=$BRANCH_NAME',\n         '--build-arg', 'TAG_NAME=$TAG_NAME',\n         '-t', 'gcr.io/$PROJECT_ID/graph-node-debug:$SHORT_SHA',\n         '-f', 'docker/Dockerfile', '.']\n- name: 'gcr.io/cloud-builders/docker'\n  args: ['tag',\n         'gcr.io/$PROJECT_ID/graph-node:$SHORT_SHA',\n         'lutter/graph-node:$SHORT_SHA']\n- name: 'gcr.io/cloud-builders/docker'\n  entrypoint: 'bash'\n  args: ['docker/tag.sh']\n  secretEnv: ['PASSWORD']\n  env:\n    - 'SHORT_SHA=$SHORT_SHA'\n    - 'TAG_NAME=$TAG_NAME'\n    - 'PROJECT_ID=$PROJECT_ID'\n    - 'DOCKER_HUB_USER=$_DOCKER_HUB_USER'\n    - 'BRANCH_NAME=$BRANCH_NAME'\nimages:\n  - 'gcr.io/$PROJECT_ID/graph-node-build:$SHORT_SHA'\n  - 'gcr.io/$PROJECT_ID/graph-node:$SHORT_SHA'\n  - 'gcr.io/$PROJECT_ID/graph-node-debug:$SHORT_SHA'\nsubstitutions:\n  # The owner of the access token whose encrypted value is in PASSWORD\n  _DOCKER_HUB_USER: \"lutter\"\nsecrets:\n - kmsKeyName: projects/the-graph-staging/locations/global/keyRings/docker/cryptoKeys/docker-hub-push\n   secretEnv:\n     PASSWORD: 'CiQAdfFldbmUiHgGP1lPq6bAOfd+VQ/dFwyohB1IQwiwQg03ZE8STQDvWKpv6eJHVUN1YoFC5FcooJrH+Stvx9oMD7jBjgxEH5ngIiAysWP3E4Pgxt/73xnaanbM1EQ94eVFKCiY0GaEKFNu0BJx22vCYmU4'\n"
  },
  {
    "path": "packages/services/graph-node/docker-compose.yml",
    "content": "version: \"3\"\nservices:\n  graph-node:\n    image: graphprotocol/graph-node:latest\n    ports:\n      - \"8000:8000\"\n      - \"8001:8001\"\n      - \"8020:8020\"\n      - \"8030:8030\"\n      - \"8040:8040\"\n    depends_on:\n      - ipfs\n      - postgres\n    environment:\n      postgres_host: postgres\n      postgres_user: graph-node\n      postgres_pass: let-me-in\n      postgres_db: graph-node\n      ipfs: \"ipfs:5001\"\n      ethereum: \"${ETHEREUM_URL}\"\n      GRAPH_LOG: info\n  ipfs:\n    image: ipfs/go-ipfs:v0.4.23\n    ports:\n      - \"5001:5001\"\n    volumes:\n      - ./data/ipfs:/data/ipfs\n  postgres:\n    image: postgres\n    ports:\n      - \"5432:5432\"\n    command:\n      [\n        \"postgres\",\n        \"-cshared_preload_libraries=pg_stat_statements\"\n      ]\n    environment:\n      POSTGRES_USER: graph-node\n      POSTGRES_PASSWORD: let-me-in\n      POSTGRES_DB: graph-node\n    volumes:\n      - ./data/postgres:/var/lib/postgresql/data\n"
  },
  {
    "path": "packages/services/graph-node/hooks/post_checkout",
    "content": "#!/bin/bash\n\nset -e\nset -x\n\necho \"Setting SOURCE_BRANCH to ${SOURCE_BRANCH}\"\n\nsed -i \"s@^ENV SOURCE_BRANCH \\\"master\\\"@ENV SOURCE_BRANCH \\\"${SOURCE_BRANCH}\\\"@g\" Dockerfile\n"
  },
  {
    "path": "packages/services/graph-node/setup.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nif ! which docker 2>&1 > /dev/null; then\n    echo \"Please install 'docker' first\"\n    exit 1\nfi\n\nif ! which docker-compose 2>&1 > /dev/null; then\n    echo \"Please install 'docker-compose' first\"\n    exit 1\nfi\n\nif ! which jq 2>&1 > /dev/null; then\n    echo \"Please install 'jq' first\"\n    exit 1\nfi\n\n# Create the graph-node container\ndocker-compose up --no-start graph-node\n\n# Start graph-node so we can inspect it\ndocker-compose start graph-node\n\n# Identify the container ID\nCONTAINER_ID=$(docker container ls | grep graph-node | cut -d' ' -f1)\n\n# Inspect the container to identify the host IP address\nHOST_IP=$(docker inspect \"$CONTAINER_ID\" | jq -r .[0].NetworkSettings.Networks[].Gateway)\n\necho \"Host IP: $HOST_IP\"\n\n# Inject the host IP into docker-compose.yml\nsed -i -e \"s/host.docker.internal/$HOST_IP/g\" docker-compose.yml\n\nfunction stop_graph_node {\n    # Ensure graph-node is stopped\n    docker-compose stop graph-node\n}\n\ntrap stop_graph_node EXIT\n"
  },
  {
    "path": "packages/services/graph-node/start",
    "content": "#!/bin/bash\n\nsave_coredumps() {\n    graph_dir=/var/lib/graph\n    datestamp=$(date +\"%Y-%m-%dT%H:%M:%S\")\n    ls /core.* >& /dev/null && have_cores=yes || have_cores=no\n    if [ -d \"$graph_dir\" -a \"$have_cores\" = yes ]\n    then\n        core_dir=$graph_dir/cores\n        mkdir -p $core_dir\n        exec >> \"$core_dir\"/messages 2>&1\n        echo \"${HOSTNAME##*-} Saving core dump on ${HOSTNAME} at ${datestamp}\"\n\n        dst=\"$core_dir/$datestamp-${HOSTNAME}\"\n        mkdir \"$dst\"\n        cp /usr/local/bin/graph-node \"$dst\"\n        cp /proc/loadavg \"$dst\"\n        [ -f /Dockerfile ] && cp /Dockerfile \"$dst\"\n        tar czf \"$dst/etc.tgz\" /etc/\n        dmesg -e > \"$dst/dmesg\"\n        # Capture environment variables, but filter out passwords\n        env | sort | sed -r -e 's/^(postgres_pass|ELASTICSEARCH_PASSWORD)=.*$/\\1=REDACTED/' > \"$dst/env\"\n\n        for f in /core.*\n        do\n            echo \"${HOSTNAME##*-} Found core dump $f\"\n            mv \"$f\" \"$dst\"\n        done\n        echo \"${HOSTNAME##*-} Saving done\"\n    fi\n}\n\nwait_for_ipfs() {\n    # Take the IPFS URL in $1 apart and extract host and port. If no explicit\n    # host is given, use 443 for https, and 80 otherwise\n    if [[ \"$1\" =~ ^((https?)://)?([^:/]+)(:([0-9]+))? ]]\n    then\n        proto=${BASH_REMATCH[2]:-http}\n        host=${BASH_REMATCH[3]}\n        port=${BASH_REMATCH[5]}\n        if [ -z \"$port\" ]\n        then\n            [ \"$proto\" = \"https\" ] && port=443 || port=80\n        fi\n        wait_for \"$host:$port\" -t 120\n    else\n        echo \"invalid IPFS URL: $1\"\n        exit 1\n    fi\n}\n\nstart_query_node() {\n    export DISABLE_BLOCK_INGESTOR=true\n    graph-node \\\n        --postgres-url \"$postgres_url\" \\\n        --ethereum-rpc $ethereum \\\n        --ipfs \"$ipfs\"\n}\n\nstart_index_node() {\n    # Only the index node with the name set in BLOCK_INGESTOR should ingest\n    # blocks\n    if [[ ${node_id} != \"${BLOCK_INGESTOR}\" ]]; then\n        export DISABLE_BLOCK_INGESTOR=true\n    fi\n\n    graph-node \\\n\t    --node-id \"${node_id//-/_}\" \\\n\t    --postgres-url \"$postgres_url\" \\\n\t    --ethereum-rpc $ethereum \\\n\t    --ipfs \"$ipfs\"\n}\n\nstart_combined_node() {\n    graph-node \\\n        --postgres-url \"$postgres_url\" \\\n        --ethereum-rpc $ethereum \\\n        --ipfs \"$ipfs\"\n}\n\npostgres_url=\"postgresql://$postgres_user:$postgres_pass@$postgres_host/$postgres_db\"\n\nwait_for_ipfs \"$ipfs\"\nwait_for \"$postgres_host:5432\" -t 120\nsleep 5\n\ntrap save_coredumps EXIT\n\nexport PGAPPNAME=\"${node_id-$HOSTNAME}\"\n\ncase \"${node_role-combined-node}\" in\n    query-node)\n        start_query_node\n        ;;\n    index-node)\n        start_index_node\n        ;;\n    combined-node)\n        start_combined_node\n        ;;\n    *)\n        echo \"Unknown mode for start-node: $1\"\n        echo \"usage: start (combined-node|query-node|index-node)\"\n        exit 1\nesac\n"
  },
  {
    "path": "packages/services/graph-node/tag.sh",
    "content": "#! /bin/bash\n\n# This script is used by cloud build to push Docker images into Docker hub\n\ntag_and_push() {\n    tag=$1\n    docker tag gcr.io/$PROJECT_ID/graph-node:$SHORT_SHA \\\n           graphprotocol/graph-node:$tag\n    docker push graphprotocol/graph-node:$tag\n\n    docker tag gcr.io/$PROJECT_ID/graph-node-debug:$SHORT_SHA \\\n           graphprotocol/graph-node-debug:$tag\n    docker push graphprotocol/graph-node-debug:$tag\n}\n\necho \"Logging into Docker Hub\"\necho $PASSWORD | docker login --username=\"$DOCKER_HUB_USER\" --password-stdin\n\nset -ex\n\ntag_and_push \"$SHORT_SHA\"\n\n# Builds on the master branch become the 'latest'\n[ \"$BRANCH_NAME\" = master ] && tag_and_push latest\n# Builds of tags set the tag in Docker Hub, too\n[ -n \"$TAG_NAME\" ] && tag_and_push \"$TAG_NAME\"\n\nexit 0\n"
  },
  {
    "path": "packages/services/graph-node/wait_for",
    "content": "#!/bin/sh\n\n# POSIX compatible clone of wait-for-it.sh\n# This copy is from https://github.com/eficode/wait-for/commits/master\n# at commit 8d9b4446\n\nTIMEOUT=15\nQUIET=0\n\nechoerr() {\n  if [ \"$QUIET\" -ne 1 ]; then printf \"%s\\n\" \"$*\" 1>&2; fi\n}\n\nusage() {\n  exitcode=\"$1\"\n  cat << USAGE >&2\nUsage:\n  $cmdname host:port [-t timeout] [-- command args]\n  -q | --quiet                        Do not output any status messages\n  -t TIMEOUT | --timeout=timeout      Timeout in seconds, zero for no timeout\n  -- COMMAND ARGS                     Execute command with args after the test finishes\nUSAGE\n  exit \"$exitcode\"\n}\n\nwait_for() {\n  for i in `seq $TIMEOUT` ; do\n    nc -z \"$HOST\" \"$PORT\" > /dev/null 2>&1\n\n    result=$?\n    if [ $result -eq 0 ] ; then\n      if [ $# -gt 0 ] ; then\n        exec \"$@\"\n      fi\n      exit 0\n    fi\n    sleep 1\n  done\n  echo \"Operation timed out\" >&2\n  exit 1\n}\n\nwhile [ $# -gt 0 ]\ndo\n  case \"$1\" in\n    *:* )\n    HOST=$(printf \"%s\\n\" \"$1\"| cut -d : -f 1)\n    PORT=$(printf \"%s\\n\" \"$1\"| cut -d : -f 2)\n    shift 1\n    ;;\n    -q | --quiet)\n    QUIET=1\n    shift 1\n    ;;\n    -t)\n    TIMEOUT=\"$2\"\n    if [ \"$TIMEOUT\" = \"\" ]; then break; fi\n    shift 2\n    ;;\n    --timeout=*)\n    TIMEOUT=\"${1#*=}\"\n    shift 1\n    ;;\n    --)\n    shift\n    break\n    ;;\n    --help)\n    usage 0\n    ;;\n    *)\n    echoerr \"Unknown argument: $1\"\n    usage 1\n    ;;\n  esac\ndone\n\nif [ \"$HOST\" = \"\" -o \"$PORT\" = \"\" ]; then\n  echoerr \"Error: you need to provide a host and port to test.\"\n  usage 2\nfi\n\nwait_for \"$@\"\n"
  },
  {
    "path": "packages/services/package.json",
    "content": "{\n  \"name\": \"@squeeth/services\",\n  \"version\": \"1.0.0\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"submodule-init\": \"git submodule init && git submodule update --remote\",\n    \"arbitrum-init\": \"cd arbitrum && git submodule init && git submodule update && yarn install\",\n    \"arbitrum-build-l1\": \"cd arbitrum && yarn docker:build:geth\",\n    \"arbitrum-run-l1\": \"cd arbitrum && yarn docker:geth\",\n    \"arbitrum-init-l2\": \"cd arbitrum && yarn demo:initialize\",\n    \"arbitrum-run-l2\": \"cd arbitrum && yarn demo:deploy\",\n    \"run-optimism\": \"cd optimism/ops && make up\",\n    \"stop-optimism\": \"cd optimism/ops && make down\",\n    \"run-graph-node\": \"cd graph-node && docker-compose up\",\n    \"remove-graph-node\": \"cd graph-node && docker-compose down\",\n    \"clean-graph-node\": \"rm -rf graph-node/data/\"\n  },\n  \"resolutions\": {\n    \"assemblyscript\": \"git+https://github.com/AssemblyScript/assemblyscript.git#v0.6\"\n  }\n}\n"
  },
  {
    "path": "packages/subgraph/.gitignore",
    "content": "node_modules\nbuild\ngenerated/**\n\n# auto-generated\nsubgraph.yaml"
  },
  {
    "path": "packages/subgraph/README.md",
    "content": "# SQUEETH-MONOREPO SUBGRAPH\n\n## HOW TO DEPLOY SUBGRAPH TO THE HOSTED SERVICE\n\nMake sure to create a subgraph project and have an access token. If you want to update a currentl deploy subgraph, make sure also to have the access token for the existent project.\n\nTo store the access token in your computer, run `graph auth --product hosted-service <ACCESS_TOKEN>`\n\n- To copy the config and ABIs from `hardhat` package, run `node scripts/publish.js` under hadhat folder of our repo. This will copy all your ABIs and create config files under the subgraph folder\n- Make sure to manually copy ABIs from `bull-vault` package, add addresses and starting block in `config` folder for the related network json file\n- Prepare the subgraph for a particular environment using `yarn prepare:ropsten` or `yarn prepare:mainnet`\n- Generate types using `yarn codegen`\n- Write compiled subgraph to /build, using `yarn build`\n- Deploy subgraph based on environment using `yarn deploy:ropsten —deploy-key *******` or `yarn deploy —deploy-key *******`\n\n## HOW TO INDEX NEW CONTRACT IN SUBGRAPH\n\n- Manually copy contract ABI into `abis` folder\n- Add data source in `subgraph.template.yaml`\n- Create entities in `schema.graphql`\n- Add handles in `src/` folder\n- Run `yarn prepare:mainnet` or equivalent depend on the network\n- Run `yarn codegen`\n- Run `yarn build`\n- Run `yarn deploy:...` similar to the one above depend on network"
  },
  {
    "path": "packages/subgraph/config/goerli-config.json",
    "content": "{\n  \"network\": \"goerli\",\n  \"ABDKMath64x64\": \"0x4CA8F19f951052162Bda12D1db72dEDa489dBD83\",\n  \"ABDKMath64x64-start-block\": 8007857,\n  \"Controller\": \"0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508\",\n  \"Controller-start-block\": 8008092,\n  \"ControllerHelper\": \"0xef0F6F951F0e62774597eB29b86065498bB7aC32\",\n  \"ControllerHelper-start-block\": 8042203,\n  \"ControllerHelperUtil\": \"0x85F983af83101600672180Dfc1d840827c4759B5\",\n  \"ControllerHelperUtil-start-block\": 8042201,\n  \"CrabMigration\": \"0x5632367328327189A4858ac413A6424fe12F6C8f\",\n  \"CrabMigration-start-block\": 7477293,\n  \"CrabStrategyDeployment\": \"0x9a23a941F5e70F6960a0E39B8a3964ef83DCbe91\",\n  \"CrabStrategyDeployment-start-block\": 8008121,\n  \"CrabStrategyV2\": \"0x3fF39f6BF8156bdA997D93E3EFF6904c2bc4481f\",\n  \"CrabStrategyV2-start-block\": 8014067,\n  \"Oracle\": \"0xf7F94b4607Bcd1235212803bE8fD1B54D1D01b77\",\n  \"Oracle-start-block\": 8008055,\n  \"ShortHelper\": \"0xE3606363ABE8fdE4A7f1A2058361976A4590e1e9\",\n  \"ShortHelper-start-block\": 8008115,\n  \"ShortPowerPerp\": \"0xe85595e810B77cf606D0aFd7eB575BB025323beE\",\n  \"ShortPowerPerp-start-block\": 8008056,\n  \"SqrtPriceMathPartial\": \"0xa932Db3b9f630436aeb5a9AF8687E521dc943569\",\n  \"SqrtPriceMathPartial-start-block\": 8007860,\n  \"TickMathExternal\": \"0x569292d3d8B44F02B11ef048A3Dd361e57880E8C\",\n  \"TickMathExternal-start-block\": 8007859,\n  \"Timelock\": \"0x95A9A4A6c9F8Ca5e92a498682a91aa7821C3c0b6\",\n  \"Timelock-start-block\": 7477295,\n  \"WPowerPerp\": \"0x9421c968D28DD789363FbD8c9aA5cF2090F0a656\",\n  \"WPowerPerp-start-block\": 8008057,\n  \"Quoter\": \"0x759442726c06F7938cd2cB63aC9Ae373Dc1dEcf6\",\n  \"Quoter-start-block\": 8007331,\n  \"CrabHelper\": \"0xFB02DBd2f3803d660413335789291186A0390E35\",\n  \"CrabHelper-start-block\": 8014068,\n  \"MockErc20\": \"0x306bf03b689f7d7e5e9D3aAC87a068F16AFF9482\",\n  \"MockErc20-start-block\": 8006325,\n  \"NonfungiblePositionManager\": \"0x24a66308bab3BEbC2821480adA395BF1C4ff8Bf2\",\n  \"NonfungiblePositionManager-start-block\": 8007329,\n  \"SwapRouter\": \"0x833A158dA5ceBc44901211427E9Df936023EC0d3\",\n  \"SwapRouter-start-block\": 8007328,\n  \"UniswapV3Factory\": \"0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa\",\n  \"UniswapV3Factory-start-block\": 8007327,\n  \"OpynWETH9\": \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\",\n  \"OpynWETH9-start-block\": 8006276,\n  \"CrabNetting\": \"0xe78bf6383bf78376ca0062a7984cfdcab39b9bf0\",\n  \"CrabNetting-start-block\": 7953032,\n  \"ZenAuction\": \"0xE5E4302933aef104Bb93181Ae9E8A664E42c8d9C\",\n  \"ZenAuction-start-block\": 8145337,\n  \"ZenBullStrategy\": \"0x2a5AD7582a9e42944Ee32671436593D16999c70a\",\n  \"ZenBullStrategy-start-block\": 8145337,\n  \"ZenEmergencyShutdown\": \"0x14386333EFa3354c1cF39A38a9c9E372A4bC8c36\",\n  \"ZenEmergencyShutdown-start-block\": 8145337,\n  \"FlashZen\": \"0x3876aF971560FD4c4ba3FB18632AcC0570B745b1\",\n  \"FlashZen-start-block\": 8145337\n}"
  },
  {
    "path": "packages/subgraph/config/localhost-config.json",
    "content": "{\n  \"network\": \"localhost\",\n  \"Controller\": \"0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1\",\n  \"Controller-start-block\": 17,\n  \"MockErc20\": \"0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512\",\n  \"MockErc20-start-block\": 2,\n  \"NonfungiblePositionManager\": \"0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9\",\n  \"NonfungiblePositionManager-start-block\": 5,\n  \"Oracle\": \"0x0165878A594ca255338adfa4d48449f69242Eb8F\",\n  \"Oracle-start-block\": 7,\n  \"Quoter\": \"0x5FC8d32690cc91D4c39d9d3abcBD16989F875707\",\n  \"Quoter-start-block\": 6,\n  \"ShortHelper\": \"0x3Aa5ebB10DC797CAC828524e59A333d0A371443c\",\n  \"ShortHelper-start-block\": 20,\n  \"SwapRouter\": \"0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9\",\n  \"SwapRouter-start-block\": 4,\n  \"UniswapV3Factory\": \"0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0\",\n  \"UniswapV3Factory-start-block\": 3,\n  \"VaultNFTManager\": \"0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6\",\n  \"VaultNFTManager-start-block\": 9,\n  \"WETH9\": \"0x5FbDB2315678afecb367f032d93F642f64180aa3\",\n  \"WETH9-start-block\": 1,\n  \"WSqueeth\": \"0x8A791620dd6260079BF849Dc5567aDC3F2FdC318\",\n  \"WSqueeth-start-block\": 10,\n  \"ABDKMath64x64\": \"0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82\",\n  \"ABDKMath64x64-start-block\": 14,\n  \"ControllerHelperUtil\": \"0x59b670e9fA9D0A427751Af201D676719a970857b\",\n  \"ControllerHelperUtil-start-block\": 22,\n  \"CrabStrategyDeployment\": \"0xc6e7DF5E7b4f2A278906862b61205850344D4e7d\",\n  \"CrabStrategyDeployment-start-block\": 21,\n  \"ShortPowerPerp\": \"0xa513E6E4b8f2a923D98304ec87F64353C4D5C853\",\n  \"ShortPowerPerp-start-block\": 8,\n  \"SqrtPriceMathPartial\": \"0x0B306BF915C4d645ff596e518fAf3F9669b97016\",\n  \"SqrtPriceMathPartial-start-block\": 16,\n  \"TickMathExternal\": \"0x9A676e781A523b5d0C0e43731313A708CB607508\",\n  \"TickMathExternal-start-block\": 15,\n  \"WPowerPerp\": \"0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6\",\n  \"WPowerPerp-start-block\": 9\n}"
  },
  {
    "path": "packages/subgraph/config/mainnet-config.json",
    "content": "{\n  \"network\": \"mainnet\",\n  \"ABDKMath64x64\": \"0x21A8D15322C257Abd2b22a56eDde758398be0F32\",\n  \"ABDKMath64x64-start-block\": 13982526,\n  \"Controller\": \"0x64187ae08781B09368e6253F9E94951243A493D5\",\n  \"Controller-start-block\": 13982541,\n  \"Oracle\": \"0x65D66c76447ccB45dAf1e8044e918fA786A483A1\",\n  \"Oracle-start-block\": 13982498,\n  \"Quoter\": \"0xC8d3a4e6BB4952E3658CCA5081c358e6935Efa43\",\n  \"Quoter-start-block\": 13977429,\n  \"ShortHelper\": \"0x3b4095D5ff0e629972CAAa50bd3004B09a1632C5\",\n  \"ShortHelper-start-block\": 13982573,\n  \"ShortPowerPerp\": \"0xa653e22A963ff0026292Cc8B67941c0ba7863a38\",\n  \"ShortPowerPerp-start-block\": 13982499,\n  \"WPowerPerp\": \"0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B\",\n  \"WPowerPerp-start-block\": 13982500,\n  \"SqrtPriceMathPartial\": \"0xb9127F2e97F6816DCd7b85d8617B7AcFe5E15419\",\n  \"SqrtPriceMathPartial-start-block\": 14922911,\n  \"TickMathExternal\": \"0x8f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D\",\n  \"TickMathExternal-start-block\": 14922910,\n  \"CrabStrategyDeployment\": \"0xf205ad80bb86ac92247638914265887a8baa437d\",\n  \"CrabStrategyDeployment-start-block\": 11808056,\n  \"ControllerHelper\": \"0xfa86d43b41Fa7a759c606130cc81970A955ff816\",\n  \"ControllerHelper-start-block\": 14925294,\n  \"ControllerHelperUtil\": \"0xB53c2eE92A24B08521912e1687Bc8142a7E6a9EE\",\n  \"ControllerHelperUtil-start-block\": 14922913,\n  \"CrabMigration\": \"0xa1CAB67a4383312718a5799Eaa127906e9d4B19E\",\n  \"CrabMigration-start-block\": 15134561,\n  \"Timelock\": \"0x67c083aE303741372F0f321Bf9cAD567CFEFE2DC\",\n  \"Timelock-start-block\": 15134581,\n  \"CrabStrategyV2\": \"0x3B960E47784150F5a63777201ee2B15253D713e8\",\n  \"CrabStrategyV2-start-block\": 15134614,\n  \"CrabHelper\": \"0x2F55e27E669F070dEf7B5771dB72f6B31A6d4df8\",\n  \"CrabHelper-start-block\": 15765940,\n  \"CrabNetting\": \"0x6E536adDB53d1b47d357cdca83BCF460194A395F\",\n  \"CrabNetting-start-block\": 16185539,\n  \"ZenAuction\": \"0x6cd0890054d308264cD68B0b6ba38A36860593ec\",\n  \"ZenAuction-start-block\": 16199889,\n  \"ZenBullStrategy\": \"0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507\",\n  \"ZenBullStrategy-start-block\": 16199889,\n  \"ZenEmergencyShutdown\": \"0x67eF7C98f17ba050056369C9C4E2b9475AE7705E\",\n  \"ZenEmergencyShutdown-start-block\": 16199889,\n  \"FlashZen\": \"0x11A56a3A7A6Eb768A9125798B1eABE9EBD9EcE02\",\n  \"FlashZen-start-block\": 16199889\n}"
  },
  {
    "path": "packages/subgraph/config/rinkebyArbitrum-config.json",
    "content": "{\n  \"network\": \"rinkebyArbitrum\",\n  \"Controller\": \"0x6FBbc7eBd7E421839915e8e4fAcC9947dC32F4dE\",\n  \"Controller-start-block\": 5750462,\n  \"MockErc20\": \"0xc4D15025D49a88D70B023870d810f4cAa5c18a63\",\n  \"MockErc20-start-block\": 5750357,\n  \"Oracle\": \"0xe790Afe86c0bdc4Dd7C6CBb7dB087552Ec85F6fB\",\n  \"Oracle-start-block\": 5750458,\n  \"Quoter\": \"0x8f92cfB1BF6eD1ce79F2E8Eb0DC96e0F3b61276D\",\n  \"Quoter-start-block\": 3910585,\n  \"ShortHelper\": \"0x5A30a1E3873A2B5Fc9DB9b2b52491C4b6086FAe0\",\n  \"ShortHelper-start-block\": 5750498,\n  \"VaultNFTManager\": \"0x40FA4273a739667D7dBf1C46755C27338eAa0728\",\n  \"VaultNFTManager-start-block\": 5750466,\n  \"WSqueeth\": \"0xEC0db8766bc003C14861af996e411beA6Bf800aB\",\n  \"WSqueeth-start-block\": 5750472\n}"
  },
  {
    "path": "packages/subgraph/config/ropsten-config.json",
    "content": "{\n  \"network\": \"ropsten\",\n  \"ABDKMath64x64\": \"0xc3eEC23787Ea5F9310332B7970C3570B6dc933a4\",\n  \"ABDKMath64x64-start-block\": 11808044,\n  \"Controller\": \"0x59F0c781a6eC387F09C40FAA22b7477a2950d209\",\n  \"Controller-start-block\": 11808049,\n  \"MockErc20\": \"0xEeAa5cE3b4f9B38b0518aA15b7e0834DDEE67bDa\",\n  \"MockErc20-start-block\": 11257245,\n  \"NonfungiblePositionManager\": \"0x8c7C1F786dA4DEe7d4bB49697A9B0C0c8Fb328e0\",\n  \"NonfungiblePositionManager-start-block\": 11342319,\n  \"Oracle\": \"0xBD9F4bE886653177D22fA9c79FD0DFc41407fC89\",\n  \"Oracle-start-block\": 11808026,\n  \"Quoter\": \"0x267aEB76BEb6DC7Ab0D88FeEaC8A948e237e2d69\",\n  \"Quoter-start-block\": 11342322,\n  \"ShortHelper\": \"0x8903918DFE74476E90B63061E5b9c3E63b65d3F4\",\n  \"ShortHelper-start-block\": 11808055,\n  \"ShortPowerPerp\": \"0x49721ED2d693F3653BC1216b8E330fA53CFC80eD\",\n  \"ShortPowerPerp-start-block\": 11808027,\n  \"SwapRouter\": \"0x528a19A3e88861E7298C86fE5490B8Ec007a4204\",\n  \"SwapRouter-start-block\": 11342318,\n  \"UniswapV3Factory\": \"0xa9C2f675FF8290494675dF5CFc2733319EaeeFDc\",\n  \"UniswapV3Factory-start-block\": 11342317,\n  \"WPowerPerp\": \"0xa4222f78d23593e82Aa74742d25D06720DCa4ab7\",\n  \"WPowerPerp-start-block\": 11808030,\n  \"CrabStrategyDeployment\": \"0x0637A9184cf4DD294F8AfA3963DeAC2Dfadfb00F\",\n  \"CrabStrategyDeployment-start-block\": 11841072,\n  \"SqrtPriceMathPartial\": \"0x565483126A5fC6004455F4e11014C442A61D740c\",\n  \"SqrtPriceMathPartial-start-block\": 12325018,\n  \"TickMathExternal\": \"0x0772382Dd7D99adb5218d31fAdfE1c68c8477335\",\n  \"TickMathExternal-start-block\": 12325016,\n  \"ControllerHelper\": \"0x7e9C5490e91F93529c6480B46a59D738F6bcEa43\",\n  \"ControllerHelper-start-block\": 12347841,\n  \"ControllerHelperUtil\": \"0x7a29594866CF3383555b8e051C80142e86d1058C\",\n  \"ControllerHelperUtil-start-block\": 12344832,\n  \"CrabMigration\": \"0xD0fb9d47B5F65d76C6bDf1b9E43a4A2345080B2f\",\n  \"CrabMigration-start-block\": 12581444,\n  \"Timelock\": \"0xF15964458bcA1941dE53fBc004BA7842f4783EC6\",\n  \"Timelock-start-block\": 12482222,\n  \"CrabStrategyV2\": \"0xdD1e9c25115e0d6e531d9F9E6ab7dbbEd15158Ce\",\n  \"CrabStrategyV2-start-block\": 12581446\n}"
  },
  {
    "path": "packages/subgraph/package.json",
    "content": "{\n  \"name\": \"@squeeth/subgraph\",\n  \"version\": \"0.1.0\",\n  \"license\": \"UNLICENSED\",\n  \"scripts\": {\n    \"codegen\": \"graph codegen\",\n    \"build\": \"graph build\",\n    \"deploy\": \"yarn prepare:mainnet && graph deploy --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ opynfinance/squeeth\",\n    \"create-local\": \"graph create --node http://localhost:8020/ opynfinance/squeeth\",\n    \"remove-local\": \"graph remove --node http://localhost:8020/ opynfinance/squeeth\",\n    \"deploy-local\": \"graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 opynfinance/squeeth\",\n    \"prepare:ropsten\": \"mustache config/ropsten-config.json subgraph.template.yaml > subgraph.yaml\",\n    \"deploy:ropsten\": \"yarn prepare:ropsten && graph deploy --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ opynfinance/squeeth-ropsten\",\n    \"prepare:mainnet\": \"mustache config/mainnet-config.json subgraph.template.yaml > subgraph.yaml\",\n    \"prepare:goerli\": \"mustache config/goerli-config.json subgraph.template.yaml > subgraph.yaml\",\n    \"deploy:goerli\": \"graph deploy --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ haythem96/squeeth-temp-subgraph\"\n  },\n  \"dependencies\": {\n    \"@graphprotocol/graph-cli\": \"0.45.2\",\n    \"@graphprotocol/graph-ts\": \"0.27.0\"\n  },\n  \"devDependencies\": {\n    \"mustache\": \"^4.2.0\"\n  }\n}"
  },
  {
    "path": "packages/subgraph/schema.graphql",
    "content": "type Vault @entity {\n  id: ID!\n  shortAmount: BigInt!\n  collateralAmount: BigInt!\n  NftCollateralId: BigInt\n  operator: Bytes\n  owner: Account!\n}\n\ntype Account @entity {\n  id: ID!\n  vaults: [Vault!]! @derivedFrom(field: \"owner\")\n  vaultCount: BigInt!\n}\n\ntype Liquidation @entity {\n  id: ID!\n  vaultId: BigInt!\n  debtAmount: BigInt!\n  collateralPaid: BigInt!\n  liquidator: Bytes!\n  timestamp: BigInt!\n}\n\ntype NormalizationFactorUpdate @entity {\n  id: ID!\n  oldNormFactor: BigInt!\n  newNormFactor: BigInt!\n  lastModificationTimestamp: BigInt!\n  timestamp: BigInt!\n}\n\ntype HourStatSnapshot @entity {\n  id: ID!\n  timestamp: BigInt!\n  totalCollateralAmount: BigInt!\n}\n\ntype DayStatSnapshot @entity {\n  id: ID!\n  timestamp: BigInt!\n  totalCollateralAmount: BigInt!\n}\n\nenum Action {\n  WITHDRAW_COLLAT\n  DEPOSIT_COLLAT\n  OPEN_SHORT\n  CLOSE_SHORT\n  MINT\n  BURN\n  LIQUIDATE\n}\n\ntype VaultHistory @entity {\n  id: ID!\n  from: Bytes!\n  sender: Bytes!\n  txid: String!\n  timestamp: BigInt!\n  totalEthCollateralAmount: BigInt!\n  oSqthAmount: BigInt!\n  ethCollateralAmount: BigInt!\n  action: Action!\n  vaultId: BigInt!\n}\n\ntype CrabStrategyTx @entity {\n  id: ID!\n  type: String!\n  lpAmount: BigInt\n  ethAmount: BigInt!\n  wSqueethAmount: BigInt\n  owner: Bytes\n  isSellingSqueeth: Boolean\n  timestamp: BigInt!\n  auctionPrice: BigInt\n  wSqueethHedgeTargetAmount: BigInt\n  ethHedgeTargetAmount: BigInt\n  hedgerPrice: BigInt\n}\n\ntype CrabAuction @entity {\n  id: ID!\n  isSellingSqueeth: Boolean!\n  squeethAmount: BigInt!\n  ethAmount: BigInt!\n  isHedgingOnUniswap: Boolean!\n  owner: Bytes!\n  timestamp: BigInt!\n}\n\ntype CrabHedgeTimeThreshold @entity {\n  id: ID!\n  threshold: BigInt!\n  timestamp: BigInt!\n}\n\ntype TimeLockTx @entity {\n  id: ID!\n  target: Bytes!\n  value: BigInt!\n  signature: String!\n  data: Bytes\n  eta: BigInt!\n  queued: Boolean\n  timestamp: BigInt!\n}\n\ntype ExecuteTimeLockTx @entity {\n  id: ID!\n  timelocktx: TimeLockTx!\n  timestamp: BigInt!\n}\n\ntype HedgeOTC @entity {\n  id: ID!\n  bidID: BigInt!\n  quantity: BigInt!\n  isBuying: Boolean!\n  clearingPrice: BigInt!\n  timestamp: BigInt!\n}\n\ntype HedgeOTCSingle @entity {\n  id: ID!\n  trader: Bytes!\n  bidID: BigInt!\n  quantity: BigInt!\n  price: BigInt!\n  isBuying: Boolean!\n  clearingPrice: BigInt!\n  hedgeOTC: HedgeOTC!\n  timestamp: BigInt!\n}\n\ntype SetStrategyCap @entity {\n  id: ID!\n  cap: BigInt!\n  timestamp: BigInt!\n}\n\ntype SetHedgingTwapPeriod @entity {\n  id: ID!\n  hedging: BigInt!\n  timestamp: BigInt!\n}\n\ntype SetHedgePriceThreshold @entity {\n  id: ID!\n  threshold: BigInt!\n  timestamp: BigInt!\n}\n\ntype SetOTCPriceTolerance @entity {\n  id: ID!\n  tolerance: BigInt!\n  timestamp: BigInt!\n}\n\ntype VaultTransferred @entity {\n  id: ID!\n  vaultID: BigInt!\n  strategy: Bytes!\n  timestamp: BigInt!\n}\n\ntype CrabUserTx @entity {\n  id: ID!\n  owner: Bytes!\n  user: Bytes!\n  lpAmount: BigInt\n  ethAmount: BigInt!\n  wSqueethAmount: BigInt\n  type: String!\n  timestamp: BigInt!\n  erc20Token: String\n  erc20Amount: BigInt\n  excessEth: BigInt\n  transaction: String!\n}\n\ntype Strategy @entity {\n  id: ID!\n  totalSupply: BigInt!\n  vaultId: BigInt!\n  lastHedgeTimestamp: BigInt!\n  lastHedgeTx: String!\n}\n\ntype BullUserTx @entity {\n  id: ID!\n  owner: Bytes!\n  user: Bytes!\n  ethAmount: BigInt!\n  bullAmount: BigInt!\n  crabAmount: BigInt\n  wSqueethAmount: BigInt!\n  wethLentAmount: BigInt!\n  usdcBorrowedAmount: BigInt!\n  type: String!\n  timestamp: BigInt!\n  erc20Token: String\n  erc20Amount: BigInt\n  excessEth: BigInt\n}\n\ntype SetAddress @entity {\n  id: ID!\n  oldAddress: Bytes!\n  newAddress: Bytes!\n  timestamp: BigInt!\n}\n\ntype SetUpperLower @entity {\n  id: ID!\n  oldLower: BigInt!\n  oldUpper: BigInt!\n  newLower: BigInt!\n  newUpper: BigInt!\n}\n\ntype SetParams @entity {\n  id: ID!\n  oldValue: BigInt!\n  newValue: BigInt!\n}\n\ntype LeverageRebalance @entity {\n  id: ID!\n  isSellingUsdc: Boolean\n  usdcAmount: BigInt!\n  wethLimitAmount: BigInt!\n  timestamp: BigInt!\n}\n\ntype FullRebalance @entity {\n  id: ID!\n  crabAmount: BigInt\n  clearingPrice: BigInt\n  wPowerPerpAmount: BigInt\n  wethTargetInEuler: BigInt\n  isDepositingInCrab: Boolean\n  timestamp: BigInt!\n}"
  },
  {
    "path": "packages/subgraph/src/bullStrategy.ts",
    "content": "import {\n    Withdraw,\n    Deposit,\n    SetCap,\n    RedeemCrabAndWithdrawEth,\n    SetShutdownContract,\n    ShutdownRepayAndWithdraw,\n    Farm,\n    DepositEthIntoCrab,\n    WithdrawShutdown,\n    AuctionRepayAndWithdrawFromLeverage,\n    SetAuction,\n    Transfer\n} from \"../generated/ZenBullStrategy/ZenBullStrategy\"\nimport {\n    SetCrUpperAndLower,\n    SetDeltaUpperAndLower,\n    LeverageRebalance,\n    FullRebalance,\n    SetFullRebalanceClearingPriceTolerance,\n    SetRebalanceWethLimitPriceTolerance,\n    SetAuctionManager\n} from \"../generated/ZenAuction/ZenAuction\"\nimport {\n    FlashWithdraw,\n    FlashDeposit,\n} from \"../generated/FlashZen/FlashZen\"\nimport {\n    SetAddress as SetAddressSchema,\n    SetUpperLower as SetUpperLowerSchema,\n    LeverageRebalance as LeverageRebalanceSchema,\n    SetStrategyCap as SetStrategyCapSchema,\n    SetParams as SetParamsSchema,\n    BullUserTx as BullUserTxSchema,\n    BullUserTx,\n    Strategy,\n    FullRebalance as FullRebalanceSchema\n} from \"../generated/schema\"\nimport * as WETH9 from \"../generated/Weth/Weth\"\nimport { Address, BigInt, ByteArray, Bytes, ethereum, log } from \"@graphprotocol/graph-ts\"\nimport { loadOrCreateStrategy } from \"./util\"\nimport { AUCTION_BULL, FLASH_BULL_ADDR, WETH } from \"./constants\"\n\nexport function loadOrCreateTx(id: string): BullUserTxSchema {\n  let userTx = BullUserTx.load(id)\n  if (userTx) return userTx\n\n  userTx = new BullUserTx(id)\n  userTx.owner = Bytes.empty()\n  userTx.user = Bytes.empty()\n  userTx.ethAmount = BigInt.zero()\n  userTx.type = \"TRANSFER\"\n  userTx.timestamp = BigInt.zero()\n  userTx.bullAmount = BigInt.zero()\n  userTx.wSqueethAmount = BigInt.zero()\n  userTx.wethLentAmount = BigInt.zero()\n  userTx.usdcBorrowedAmount = BigInt.zero()\n\n  return userTx\n}\n\nexport function handleWithdraw(event: Withdraw): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.wSqueethAmount = event.params.wPowerPerpToRedeem\n  userTx.bullAmount = event.params.bullAmount\n  userTx.ethAmount = event.params.wethToWithdraw\n  userTx.crabAmount = event.params.crabToRedeem\n  userTx.user = event.params.to\n  userTx.wethLentAmount = event.params.wethToWithdraw\n  userTx.usdcBorrowedAmount = event.params.usdcToRepay\n  userTx.owner = event.transaction.from\n  userTx.type = 'WITHDRAW'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleSetCap(event: SetCap): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.ethAmount = event.params.newCap\n  userTx.type = 'SET_CAP'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleDeposit(event: Deposit): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.ethAmount = event.transaction.value\n  userTx.crabAmount = event.params.crabAmount\n  userTx.user = event.params.from\n  userTx.wethLentAmount = event.params.wethLent\n  userTx.usdcBorrowedAmount = event.params.usdcBorrowed\n  userTx.owner = event.transaction.from\n  userTx.type = 'DEPOSIT'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleSetStrategyCap(event: SetCap): void {\n  const cap = new SetStrategyCapSchema(event.transaction.hash.toHex());\n  cap.cap = event.params.newCap;\n  cap.timestamp = event.block.timestamp;\n  cap.save();\n}\n\nexport function handleSetAuction(event: SetAuction): void {\n  const shutdownContract = new SetAddressSchema(event.transaction.hash.toHex());\n  shutdownContract.oldAddress = event.params.oldAuction;\n  shutdownContract.newAddress = event.params.newAuction;\n  shutdownContract.timestamp = event.block.timestamp;\n  shutdownContract.save();\n}\n\nexport function handleRedeemCrabAndWithdrawEth(event: RedeemCrabAndWithdrawEth): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.ethAmount = event.params.wethBalanceReturned\n  userTx.wSqueethAmount = event.params.wPowerPerpRedeemed\n  userTx.crabAmount = event.params.crabToRedeem\n  userTx.user = event.transaction.from\n  userTx.owner = event.transaction.from\n  userTx.type = 'REDEEM_CRAB_AND_WITHDRAW_ETH'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleSetShutdownContract(event: SetShutdownContract): void {\n  const shutdownContract = new SetAddressSchema(event.transaction.hash.toHex());\n  shutdownContract.oldAddress = event.params.oldShutdownContract;\n  shutdownContract.newAddress = event.params.newShutdownContract;\n  shutdownContract.timestamp = event.block.timestamp;\n  shutdownContract.save();\n}\n\nexport function handleShutdownRepayAndWithdraw(event: ShutdownRepayAndWithdraw): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.ethAmount = event.transaction.value\n  userTx.crabAmount = event.params.crabToRedeem\n  userTx.user = event.transaction.from\n  userTx.bullAmount = event.params.shareToUnwind\n  userTx.owner = event.transaction.from\n  userTx.type = 'SHUTDOWN_REPAY_AND_WITHDRAW'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleFarm(event: Farm): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.erc20Token = event.params.asset.toHex()\n  userTx.user = event.params.receiver\n  userTx.owner = event.transaction.from\n}\n\nexport function handleDepositEthIntoCrab(event: DepositEthIntoCrab): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.ethAmount = event.params.ethToDeposit\n  userTx.user = event.transaction.from\n  userTx.owner = event.transaction.from\n  userTx.type = 'DEPOSIT_ETH_INTO_CRAB'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleWithdrawShutdown(event: WithdrawShutdown): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.ethAmount = event.params.ethToReceive\n  userTx.user = event.params.withdrawer\n  userTx.bullAmount = event.params.bullAmount\n  userTx.owner = event.transaction.from\n  userTx.type = 'WITHDRAW_SHUTDOWN'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleAuctionRepayAndWithdrawFromLeverage(event: AuctionRepayAndWithdrawFromLeverage): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.ethAmount = event.params.wethToWithdraw\n  userTx.usdcBorrowedAmount = event.params.usdcToRepay\n  userTx.user = event.transaction.from\n  userTx.owner = event.transaction.from\n  userTx.type = 'AUCTION_REPAY_AND_WITHDRAW_FROM_LEVERAGE'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n\n}\n\nexport function handleSetCrUpperAndLower(event: SetCrUpperAndLower): void {\n  const params = new SetUpperLowerSchema(event.transaction.hash.toHex());\n  params.oldLower = event.params.oldCrLower\n  params.oldUpper = event.params.oldCrUpper\n  params.newLower = event.params.newCrLower\n  params.newUpper = event.params.newCrUpper\n  params.save()\n}\n\nexport function handleSetDeltaUpperAndLower(event: SetDeltaUpperAndLower): void {\n  const params = new SetUpperLowerSchema(event.transaction.hash.toHex());\n  params.oldLower = event.params.oldDeltaLower\n  params.oldUpper = event.params.oldDeltaUpper\n  params.newLower = event.params.newDeltaLower\n  params.newUpper = event.params.newDeltaUpper\n  params.save()\n}\n\nexport function handleLeverageRebalance(event: LeverageRebalance): void { \n  const rebalance = new LeverageRebalanceSchema(event.transaction.hash.toHex());\n  rebalance.isSellingUsdc = event.params.isSellingUsdc\n  rebalance.usdcAmount = event.params.usdcAmount\n  rebalance.wethLimitAmount = event.params.wethLimitAmount\n  rebalance.timestamp = event.block.timestamp\n  rebalance.save()\n\n  const strategy = loadOrCreateStrategy(AUCTION_BULL.toHex())\n  strategy.lastHedgeTimestamp = event.block.timestamp\n  strategy.lastHedgeTx = event.transaction.hash.toHex()\n  strategy.save()\n}\n\nexport function handleSetFullRebalanceClearingPriceTolerance(event: SetFullRebalanceClearingPriceTolerance): void {\n  const params = new SetParamsSchema(event.transaction.hash.toHex());\n  params.oldValue = event.params.oldPriceTolerance\n  params.newValue = event.params.newPriceTolerance\n  params.save()\n}\n\nexport function handleSetRebalanceWethLimitPriceTolerance(event: SetRebalanceWethLimitPriceTolerance): void {\n  const params = new SetParamsSchema(event.transaction.hash.toHex());\n  params.oldValue = event.params.oldWethLimitPriceTolerance\n  params.newValue = event.params.newWethLimitPriceTolerance\n  params.save()\n}\n\nexport function handleSetAuctionManager(event: SetAuctionManager): void {\n  const shutdownContract = new SetAddressSchema(event.transaction.hash.toHex());\n  shutdownContract.oldAddress = event.params.oldAuctionManager;\n  shutdownContract.newAddress = event.params.newAuctionManager;\n  shutdownContract.timestamp = event.block.timestamp;\n  shutdownContract.save();\n}\n\nexport function handleFullRebalance(event: FullRebalance): void { \n  const rebalance = new FullRebalanceSchema(event.transaction.hash.toHex());\n  rebalance.crabAmount = event.params.crabAmount\n  rebalance.clearingPrice = event.params.clearingPrice\n  rebalance.wPowerPerpAmount = event.params.wPowerPerpAmount\n  rebalance.wethTargetInEuler = event.params.wethTargetInEuler\n  rebalance.isDepositingInCrab = event.params.isDepositingInCrab\n  rebalance.timestamp = event.block.timestamp\n  rebalance.save()\n\n  const strategy = loadOrCreateStrategy(AUCTION_BULL.toHex())\n  strategy.lastHedgeTimestamp = event.block.timestamp\n  strategy.lastHedgeTx = event.transaction.hash.toHex()\n  strategy.save()\n}\n\nexport function handleFlashDeposit(event: FlashDeposit): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.ethAmount = findFlashBullEthDeposited(event)\n  userTx.crabAmount = event.params.crabAmount\n  userTx.user = event.transaction.from\n  userTx.wethLentAmount = event.params.wethToLend\n  userTx.usdcBorrowedAmount = event.params.usdcToBorrow\n  userTx.owner = event.transaction.from\n  userTx.type = 'FLASH_DEPOSIT'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleFlashWithdraw(event: FlashWithdraw): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.bullAmount = event.params.bullAmount\n  userTx.ethAmount = event.params.ethReturned\n  userTx.user = event.transaction.from\n  userTx.owner = event.transaction.from\n  userTx.type = 'FLASH_WITHDRAW'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleTransfer(event: Transfer): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.bullAmount = event.params.value\n  userTx.save()\n}\n\nfunction findFlashBullEthDeposited(event: FlashDeposit): BigInt {\n  let returnedAmount = event.params.ethDeposited\n  if (!event.receipt) return returnedAmount\n\n  const allEvents = (event.receipt as ethereum.TransactionReceipt).logs as Array<ethereum.Log>\n  if (!allEvents) return returnedAmount\n\n  for (let i = 0; i < allEvents.length; i++) {\n    const e = allEvents[i]\n    if (!e) continue\n\n    if (e.topics[0].toHexString().toLowerCase() == '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'.toLowerCase() && WETH.equals(e.address)) { // Transfer event (should add)\n      const dec = ethereum.decode('(uint256)', Bytes.fromHexString(e.data.toHexString()))\n      const dec2 = ethereum.decode('(address)', Bytes.fromHexString(e.topics[2].toHexString()))\n      if (dec2) {\n        const decodedTopics = dec2.toTuple()\n        if (dec && FLASH_BULL_ADDR.equals(decodedTopics[0].toAddress())) { // If the event is a transfer to the flash bull\n          const decoded = dec.toTuple()\n          returnedAmount = returnedAmount.plus(decoded[0].toBigInt())\n        }\n      }\n    } else if (e.topics[0].toHexString() == '0x3ca13b7aab12bad7472691fe558faa6b25e99099824a0070a88bd5aa84be610f') { // Deposit colat (should subtract)\n      const dec = ethereum.decode('(address,uint256,uint256)', Bytes.fromHexString(e.data.toHexString()))\n      if (dec) {\n        const decoded = dec.toTuple()\n        returnedAmount = returnedAmount.minus(decoded[2].toBigInt())\n      }\n    } else if (e.topics[0].toHexString() == '0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c') { // Wrap deposit event (should subtract)\n      const dec = ethereum.decode('(uint256)', Bytes.fromHexString(e.data.toHexString()))\n      if (dec) {\n        const decoded = dec.toTuple()\n        returnedAmount = returnedAmount.minus(decoded[0].toBigInt())\n      }\n    }\n  }\n\n  return event.params.ethDeposited.minus(returnedAmount)\n}\n"
  },
  {
    "path": "packages/subgraph/src/constants.ts",
    "content": "import { Address, BigInt, dataSource } from \"@graphprotocol/graph-ts\";\nimport { getShortHelperAddr, getCrabV2Addr, getCrabMigrationAddr, getCrabV1Addr, getBullAddr, getFlashBullAddr, getAuctionBullAddr, getWethAddr } from \"./util\";\n\nexport const BIGINT_ONE = BigInt.fromI32(1);\nexport const BIGINT_ZERO = BigInt.fromI32(0);\nexport const EMPTY_ADDR = Address.empty();\n// mainnet\nexport const MAINNET_SHORT_HELPER_ADDR = Address.fromString(\n  \"0x3b4095D5ff0e629972CAAa50bd3004B09a1632C5\"\n);\nexport const MAINNET_CRAB_V2_ADDR = Address.fromString(\n  \"0x3B960E47784150F5a63777201ee2B15253D713e8\"\n);\nexport const MAINNET_CRAB_MIGRATION_ADDR = Address.fromString(\n  \"0xD0fb9d47B5F65d76C6bDf1b9E43a4A2345080B2f\"\n);\nexport const MAINNET_CRAB_V1_ADDR = Address.fromString(\n  \"0xf205ad80bb86ac92247638914265887a8baa437d\"\n);\nexport const MAINNET_FLASH_BULL_ADDR = Address.fromString(\n  \"0x11A56a3A7A6Eb768A9125798B1eABE9EBD9EcE02\"\n);\nexport const MAINNET_BULL_STRATEGY_ADDR = Address.fromString(\n  \"0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507\"\n);\nexport const MAINNET_AUCTION_BULL_ADDR = Address.fromString(\n  \"0x6cd0890054d308264cD68B0b6ba38A36860593ec\"\n);\n\nexport const MAINNET_WETH_ADDR = Address.fromString(\n  \"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\"\n);\n// ropsten\nexport const ROPSTEN_SHORT_HELPER_ADDR = Address.fromString(\n  \"0x8903918DFE74476E90B63061E5b9c3E63b65d3F4\"\n);\nexport const ROPSTEN_CRAB_V2_ADDR = Address.fromString(\n  \"0xdD1e9c25115e0d6e531d9F9E6ab7dbbEd15158Ce\"\n);\nexport const ROPSTEN_CRAB_MIGRATION_ADDR = Address.fromString(\n  \"0xD0fb9d47B5F65d76C6bDf1b9E43a4A2345080B2f\"\n);\nexport const ROPSTEN_CRAB_V1_ADDR = Address.fromString(\n  \"0xbffBD99cFD9d77c49595dFe8eB531715906ca4Cf\"\n);\n// localhost?\nexport const LOCALHOST_SHORT_HELPER_ADDR = Address.fromString(\n  \"0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE\"\n);\n// rinekby arbitrum\nexport const RA_SHORT_HELPER_ADDR = Address.fromString(\n  \"0x5A30a1E3873A2B5Fc9DB9b2b52491C4b6086FAe0\"\n);\n// goerli\nexport const GOERLI_SHORT_HELPER_ADDR = Address.fromString(\n  \"0xD837848Ca57AdBb4361911C1aD8397FA21e35672\"\n);\nexport const GOERLI_CRAB_V2_ADDR = Address.fromString(\n  \"0x4Eb533506f996dea20f3d582C2ff36BA527ba35D\"\n);\nexport const GOERLI_CRAB_MIGRATION_ADDR = Address.fromString(\n  \"0x5632367328327189A4858ac413A6424fe12F6C8f\"\n);\nexport const GOERLI_CRAB_V1_ADDR = Address.fromString(\n  \"0x5632367328327189A4858ac413A6424fe12F6C8f\"\n);\nexport const GOERLI_BULL_STRATEGY_ADDR = Address.fromString(\n  \"0x2a5AD7582a9e42944Ee32671436593D16999c70a\"\n);\nexport const GOERLI_AUCTION_BULL_ADDR = Address.fromString(\n  \"0xE5E4302933aef104Bb93181Ae9E8A664E42c8d9C\"\n);\nexport const GOERLI_FLASH_BULL_ADDR = Address.fromString(\n  \"0x3876aF971560FD4c4ba3FB18632AcC0570B745b1\"\n);\n\nexport const GOERLI_WETH_ADDR = Address.fromString(\n  \"0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103\"\n);\n\nexport const SHORT_HELPER_ADDR = getShortHelperAddr(dataSource.network());\nexport const CRAB_V2_ADDR = getCrabV2Addr(dataSource.network());\nexport const CRAB_MIGRATION_ADDR = getCrabMigrationAddr(dataSource.network());\nexport const CRAB_V1_ADDR = getCrabV1Addr(dataSource.network());\nexport const FLASH_BULL_ADDR = getFlashBullAddr(dataSource.network());\nexport const BULL_ADDR = getBullAddr(dataSource.network());\nexport const AUCTION_BULL = getAuctionBullAddr(dataSource.network());\nexport const WETH = getWethAddr(dataSource.network());\n"
  },
  {
    "path": "packages/subgraph/src/controller.ts",
    "content": "import {\n  Address,\n  BigInt,\n  Bytes,\n  log,\n  dataSource,\n} from \"@graphprotocol/graph-ts\";\nimport {\n  Controller,\n  BurnShort,\n  DepositCollateral,\n  DepositUniPositionToken,\n  FeeRateUpdated,\n  FeeRecipientUpdated,\n  Liquidate,\n  MintShort,\n  NormalizationFactorUpdated,\n  OpenVault,\n  OwnershipTransferred,\n  Paused,\n  RedeemLong,\n  RedeemShort,\n  ReduceDebt,\n  Shutdown,\n  UnPaused,\n  UpdateOperator,\n  WithdrawCollateral,\n  WithdrawUniPositionToken,\n} from \"../generated/Controller/Controller\";\nimport {\n  Vault,\n  Liquidation,\n  NormalizationFactorUpdate,\n  HourStatSnapshot,\n  DayStatSnapshot,\n  VaultHistory,\n  BullUserTx,\n} from \"../generated/schema\";\nimport { loadOrCreateAccount } from \"./util\";\n\nimport {\n  BIGINT_ONE,\n  BIGINT_ZERO,\n  SHORT_HELPER_ADDR,\n  EMPTY_ADDR,\n} from \"./constants\";\n\nimport * as bull from './bullStrategy'\n\n// Note: If a handler doesn't require existing field values, it is faster\n// _not_ to load the entity from the store. Instead, create it fresh with\n// `new Entity(...)`, set the fields that should be updated and save the\n// entity back to the store. Fields that were not set or unset remain\n// unchanged, allowing for partial updates to be applied.\n\n// It is also possible to access smart contracts from mappings. For\n// example, the contract that has emitted the event can be connected to\n// with:\n//\n// let contract = Contract.bind(event.address)\n//\n// The following functions can then be called on this contract to access\n// state variables and other data:\n//\n// - contract.FUNDING_PERIOD(...)\n// - contract.TWAP_PERIOD(...)\n// - contract.burnPowerPerpAmount(...)\n// - contract.ethQuoteCurrencyPool(...)\n// - contract.feeRate(...)\n// - contract.feeRecipient(...)\n// - contract.getDenormalizedMark(...)\n// - contract.getDenormalizedMarkForFunding(...)\n// - contract.getExpectedNormalizationFactor(...)\n// - contract.getIndex(...)\n// - contract.getUnscaledIndex(...)\n// - contract.indexForSettlement(...)\n// - contract.isShutDown(...)\n// - contract.isSystemPaused(...)\n// - contract.isVaultSafe(...)\n// - contract.lastFundingUpdateTimestamp(...)\n// - contract.lastPauseTime(...)\n// - contract.liquidate(...)\n// - contract.normalizationFactor(...)\n// - contract.onERC721Received(...)\n// - contract.oracle(...)\n// - contract.owner(...)\n// - contract.pausesLeft(...)\n// - contract.quoteCurrency(...)\n// - contract.shortPowerPerp(...)\n// - contract.vaults(...)\n// - contract.wPowerPerp(...)\n// - contract.wPowerPerpPool(...)\n// - contract.weth(...)\n\nexport function handleBurnShort(event: BurnShort): void {\n  const vault = Vault.load(event.params.vaultId.toString());\n  if (!vault) return;\n\n  vault.shortAmount = vault.shortAmount.minus(event.params.amount);\n  vault.save();\n\n  let timestamp = event.block.timestamp;\n  let transactionHash = event.transaction.hash.toHex();\n\n  //check if users manually burn or using shorthelper to close position\n  let actionType: string;\n  if (event.params.sender == SHORT_HELPER_ADDR) {\n    actionType = \"CLOSE_SHORT\";\n  } else {\n    actionType = \"BURN\";\n  }\n  //update vault history\n  const vaultTransaction = getTransactionDetail(\n    event.transaction.from,\n    event.params.sender,\n    event.params.vaultId,\n    event.params.amount,\n    vault,\n    timestamp,\n    actionType,\n    transactionHash,\n    BIGINT_ZERO\n  );\n  vaultTransaction.save();\n\n  \n}\n\nexport function handleDepositCollateral(event: DepositCollateral): void {\n  const vault = Vault.load(event.params.vaultId.toString());\n  if (!vault) return;\n\n  vault.collateralAmount = vault.collateralAmount.plus(event.params.amount);\n  vault.save();\n\n  let timestamp = event.block.timestamp;\n  let transactionHash = event.transaction.hash.toHex();\n\n  //update vault history\n  const vaultTransaction = getTransactionDetail(\n    event.transaction.from,\n    event.params.sender,\n    event.params.vaultId,\n    event.params.amount,\n    vault,\n    timestamp,\n    \"DEPOSIT_COLLAT\",\n    transactionHash,\n    BIGINT_ZERO\n  );\n  vaultTransaction.save();\n\n  // update TVL stats\n  const hourStatSnapshot = getHourStatSnapshot(timestamp);\n  hourStatSnapshot.totalCollateralAmount =\n    hourStatSnapshot.totalCollateralAmount.plus(event.params.amount);\n  hourStatSnapshot.save();\n\n  const dayStatSnapshot = getDayStatSnapshot(timestamp);\n  dayStatSnapshot.totalCollateralAmount =\n    dayStatSnapshot.totalCollateralAmount.plus(event.params.amount);\n  dayStatSnapshot.save();\n}\n\nexport function handleDepositUniPositionToken(\n  event: DepositUniPositionToken\n): void {\n  const vault = Vault.load(event.params.vaultId.toString());\n  if (!vault) return;\n\n  vault.NftCollateralId = event.params.tokenId;\n  vault.save();\n}\n\nexport function handleFeeRateUpdated(event: FeeRateUpdated): void {}\n\nexport function handleFeeRecipientUpdated(event: FeeRecipientUpdated): void {}\n\nexport function handleLiquidate(event: Liquidate): void {\n  const vault = Vault.load(event.params.vaultId.toString());\n  if (!vault) return;\n\n  vault.shortAmount = vault.shortAmount.minus(event.params.debtAmount);\n  vault.collateralAmount = vault.collateralAmount.minus(\n    event.params.collateralPaid\n  );\n  vault.save();\n\n  let timestamp = event.block.timestamp;\n  let transactionHash = event.transaction.hash.toHex();\n  //update vault history\n  const vaultTransaction = getTransactionDetail(\n    event.transaction.from,\n    EMPTY_ADDR,\n    event.params.vaultId,\n    event.params.collateralPaid,\n    vault,\n    timestamp,\n    \"LIQUIDATE\",\n    transactionHash,\n    event.params.debtAmount\n  );\n  vaultTransaction.save();\n\n  // update TVL stats\n  const hourStatSnapshot = getHourStatSnapshot(timestamp);\n  hourStatSnapshot.totalCollateralAmount =\n    hourStatSnapshot.totalCollateralAmount.minus(event.params.collateralPaid);\n  hourStatSnapshot.save();\n\n  const dayStatSnapshot = getDayStatSnapshot(timestamp);\n  dayStatSnapshot.totalCollateralAmount =\n    dayStatSnapshot.totalCollateralAmount.minus(event.params.collateralPaid);\n  dayStatSnapshot.save();\n\n  const liquidation = new Liquidation(\n    `${event.transaction.hash.toHex()}-${event.logIndex.toString()}`\n  );\n  liquidation.debtAmount = event.params.debtAmount;\n  liquidation.collateralPaid = event.params.collateralPaid;\n  liquidation.vaultId = event.params.vaultId;\n  liquidation.liquidator = event.params.liquidator;\n  liquidation.timestamp = event.block.timestamp;\n  liquidation.save();\n}\n\nexport function handleMintShort(event: MintShort): void {\n  const vault = Vault.load(event.params.vaultId.toString());\n  if (!vault) return;\n\n  vault.shortAmount = vault.shortAmount.plus(event.params.amount);\n  vault.save();\n\n  let timestamp = event.block.timestamp;\n  let transactionHash = event.transaction.hash.toHex();\n  //check if users manually mint or using shorthelper to close position\n  //if directly sent to short helper address, then it's open short in 1 step, if directly sen t to controller address, then it's mint\n  let actionType: string;\n  if (event.params.sender == SHORT_HELPER_ADDR) {\n    actionType = \"OPEN_SHORT\";\n  } else {\n    actionType = \"MINT\";\n  }\n\n  //update vault history\n  const vaultTransaction = getTransactionDetail(\n    event.transaction.from,\n    event.params.sender,\n    event.params.vaultId,\n    event.params.amount,\n    vault,\n    timestamp,\n    actionType,\n    transactionHash,\n    BIGINT_ZERO\n  );\n  vaultTransaction.save();\n}\n\nexport function handleNormalizationFactorUpdated(\n  event: NormalizationFactorUpdated\n): void {\n  const nfUpdate = new NormalizationFactorUpdate(\n    `${event.transaction.hash.toHex()}-${event.logIndex.toString()}`\n  );\n  nfUpdate.newNormFactor = event.params.newNormFactor;\n  nfUpdate.oldNormFactor = event.params.oldNormFactor;\n  nfUpdate.timestamp = event.params.timestamp;\n  nfUpdate.lastModificationTimestamp = event.params.lastModificationTimestamp;\n  nfUpdate.save();\n}\n\nexport function handleOpenVault(event: OpenVault): void {\n  const account = loadOrCreateAccount(event.transaction.from.toHex());\n  account.vaultCount = account.vaultCount.plus(BIGINT_ONE);\n  account.save();\n\n  const vault = new Vault(event.params.vaultId.toString());\n  vault.owner = event.transaction.from.toHex();\n  vault.collateralAmount = BIGINT_ZERO;\n  vault.shortAmount = BIGINT_ZERO;\n  vault.save();\n}\n\nexport function handleOwnershipTransferred(event: OwnershipTransferred): void {}\n\nexport function handlePaused(event: Paused): void {}\n\nexport function handleRedeemLong(event: RedeemLong): void {}\n\nexport function handleRedeemShort(event: RedeemShort): void {}\n\nexport function handleReduceDebt(event: ReduceDebt): void {}\n\nexport function handleShutdown(event: Shutdown): void {}\n\nexport function handleUnPaused(event: UnPaused): void {}\n\nexport function handleUpdateOperator(event: UpdateOperator): void {\n  const vault = Vault.load(event.params.vaultId.toString());\n  if (!vault) return;\n\n  vault.operator = event.params.operator;\n  vault.save();\n}\n\nexport function handleWithdrawCollateral(event: WithdrawCollateral): void {\n  const vault = Vault.load(event.params.vaultId.toString());\n  if (!vault) return;\n\n  vault.collateralAmount = vault.collateralAmount.minus(event.params.amount);\n  vault.save();\n\n  let timestamp = event.block.timestamp;\n  let transactionHash = event.transaction.hash.toHex();\n\n  //update vault history\n  const vaultTransaction = getTransactionDetail(\n    event.transaction.from,\n    event.params.sender,\n    event.params.vaultId,\n    event.params.amount,\n    vault,\n    timestamp,\n    \"WITHDRAW_COLLAT\",\n    transactionHash,\n    BIGINT_ZERO\n  );\n  vaultTransaction.save();\n\n  // update TVL stats\n  const hourStatSnapshot = getHourStatSnapshot(timestamp);\n  hourStatSnapshot.totalCollateralAmount =\n    hourStatSnapshot.totalCollateralAmount.minus(event.params.amount);\n  hourStatSnapshot.save();\n\n  const dayStatSnapshot = getDayStatSnapshot(timestamp);\n  dayStatSnapshot.totalCollateralAmount =\n    dayStatSnapshot.totalCollateralAmount.minus(event.params.amount);\n  dayStatSnapshot.save();\n}\n\nexport function handleWithdrawUniPositionToken(\n  event: WithdrawUniPositionToken\n): void {\n  const vault = Vault.load(event.params.vaultId.toString());\n  if (!vault) return;\n\n  vault.NftCollateralId = BIGINT_ZERO;\n  vault.save();\n}\n\nfunction getHourStatSnapshot(timestamp: BigInt): HourStatSnapshot {\n  let hourIndex = timestamp.toI32() / 3600; // get unique hour within unix history\n  let hourStartUnix = hourIndex * 3600; // want the rounded effect\n  let hourStartUnixBigInt = BigInt.fromI32(hourStartUnix);\n\n  let hourStatSnapshot = HourStatSnapshot.load(\"last\");\n\n  if (hourStatSnapshot === null) {\n    hourStatSnapshot = new HourStatSnapshot(\"last\");\n    hourStatSnapshot.totalCollateralAmount = BIGINT_ZERO;\n    hourStatSnapshot.timestamp = hourStartUnixBigInt;\n  }\n\n  if (\n    hourStatSnapshot !== null &&\n    hourStatSnapshot.timestamp.notEqual(hourStartUnixBigInt)\n  ) {\n    let totalCollateral = hourStatSnapshot.totalCollateralAmount;\n    hourStatSnapshot.id = hourStatSnapshot.timestamp.toString();\n    hourStatSnapshot.save();\n\n    hourStatSnapshot = new HourStatSnapshot(\"last\");\n    hourStatSnapshot.totalCollateralAmount = totalCollateral;\n    hourStatSnapshot.timestamp = hourStartUnixBigInt;\n  }\n\n  return hourStatSnapshot as HourStatSnapshot;\n}\n\nfunction getDayStatSnapshot(timestamp: BigInt): DayStatSnapshot {\n  let dayID = timestamp.toI32() / 86400;\n  let dayStartUnix = dayID * 86400;\n  let dayStartUnixBigInt = BigInt.fromI32(dayStartUnix);\n\n  let dayStatSnapshot = DayStatSnapshot.load(\"last\");\n\n  if (dayStatSnapshot === null) {\n    dayStatSnapshot = new DayStatSnapshot(\"last\");\n    dayStatSnapshot.totalCollateralAmount = BIGINT_ZERO;\n    dayStatSnapshot.timestamp = dayStartUnixBigInt;\n  }\n\n  if (\n    dayStatSnapshot !== null &&\n    dayStatSnapshot.timestamp.notEqual(dayStartUnixBigInt)\n  ) {\n    let totalCollateral = dayStatSnapshot.totalCollateralAmount;\n    dayStatSnapshot.id = dayStatSnapshot.timestamp.toString();\n    dayStatSnapshot.save();\n\n    dayStatSnapshot = new DayStatSnapshot(\"last\");\n    dayStatSnapshot.totalCollateralAmount = totalCollateral;\n    dayStatSnapshot.timestamp = dayStartUnixBigInt;\n  }\n\n  return dayStatSnapshot as DayStatSnapshot;\n}\n\nfunction getTransactionDetail(\n  from: Bytes,\n  sender: Bytes,\n  vaultId: BigInt,\n  amount: BigInt,\n  vault: Vault,\n  timestamp: BigInt,\n  action: string,\n  transactionHash: string,\n  debtAmount: BigInt\n): VaultHistory {\n  const vaultHistory = new VaultHistory(transactionHash + \"-\" + action);\n  vaultHistory.totalEthCollateralAmount = vault.collateralAmount;\n  vaultHistory.action = action;\n  vaultHistory.vaultId = vaultId;\n  vaultHistory.txid = transactionHash;\n  vaultHistory.timestamp = timestamp;\n  vaultHistory.from = from;\n  vaultHistory.sender = sender;\n  vaultHistory.ethCollateralAmount = BigInt.zero()\n  vaultHistory.oSqthAmount = BigInt.zero();\n\n  if (action == \"DEPOSIT_COLLAT\" || action == \"WITHDRAW_COLLAT\") {\n    vaultHistory.ethCollateralAmount = amount;\n  } else if (action == \"LIQUIDATE\") {\n    vaultHistory.ethCollateralAmount = amount;\n    vaultHistory.oSqthAmount = debtAmount;\n  } else {\n    vaultHistory.oSqthAmount = amount;\n  }\n\n  return vaultHistory as VaultHistory;\n}\n"
  },
  {
    "path": "packages/subgraph/src/crabV2.ts",
    "content": "import {\n  SetHedgePriceThreshold,\n  SetHedgeTimeThreshold,\n  HedgeOTC,\n  HedgeOTCSingle,\n  SetStrategyCap,\n  SetHedgingTwapPeriod,\n  SetOTCPriceTolerance,\n  VaultTransferred,\n  Deposit,\n  Withdraw,\n  WithdrawShutdown,\n  FlashDeposit,\n  FlashWithdraw,\n  FlashDepositCallback,\n  FlashWithdrawCallback,\n  Transfer,\n  CrabStrategyV2\n} from \"../generated/CrabStrategyV2/CrabStrategyV2\"\nimport { BigInt, Bytes, ethereum, json, log } from \"@graphprotocol/graph-ts\"\n\nimport { QueueTransaction } from \"../generated/Timelock/Timelock\";\nimport { FlashDepositERC20, FlashWithdrawERC20 } from \"../generated/CrabHelper/CrabHelper\";\n\nimport {\n  CrabHedgeTimeThreshold,\n  ExecuteTimeLockTx,\n  HedgeOTC as HedgeOTCSchema,\n  HedgeOTCSingle as HedgeOTCSingleSchema,\n  SetHedgingTwapPeriod as SetHedgingTwapPeriodSchema,\n  SetStrategyCap as SetStrategyCapSchema,\n  SetHedgePriceThreshold as SetHedgePriceThresholdSchema,\n  TimeLockTx,\n  SetOTCPriceTolerance as SetOTCPriceToleranceSchema,\n  VaultTransferred as VaultTransferredSchema,\n  CrabUserTx as CrabUserTxSchema,\n  CrabUserTx,\n  Strategy,\n  Vault,\n} from \"../generated/schema\"\nimport { ClaimV2Shares, DepositV1Shares } from \"../generated/CrabMigration/CrabMigration\";\nimport { CRAB_MIGRATION_ADDR, CRAB_V1_ADDR, CRAB_V2_ADDR, FLASH_BULL_ADDR, BULL_ADDR } from \"./constants\";\nimport { CrabNetting, CrabWithdrawn, USDCDeposited } from \"../generated/CrabNetting/CrabNetting\";\nimport { loadOrCreateStrategy } from \"./util\";\n\nfunction loadOrCreateTx(id: string): CrabUserTxSchema {\n  let userTx = CrabUserTx.load(id)\n  if (userTx) return userTx\n\n  userTx = new CrabUserTx(id)\n  userTx.owner = Bytes.empty()\n  userTx.user = Bytes.empty()\n  userTx.ethAmount = BigInt.zero()\n  userTx.type = \"TRANSFER\"\n  userTx.timestamp = BigInt.zero()\n  userTx.transaction = id\n\n  return userTx\n}\n\nexport function handleDeposit(event: Deposit): void {\n  if (event.params.depositor.equals(FLASH_BULL_ADDR) || event.params.depositor.equals(BULL_ADDR)) return\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.wSqueethAmount = event.params.wSqueethAmount\n  userTx.lpAmount = event.params.lpAmount\n  userTx.ethAmount = event.transaction.value\n  userTx.user = event.params.depositor\n  userTx.owner = event.transaction.from\n  userTx.type = 'DEPOSIT'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleWithdraw(event: Withdraw): void {\n  if (event.params.withdrawer.equals(FLASH_BULL_ADDR) || event.params.withdrawer.equals(BULL_ADDR)) return\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.wSqueethAmount = event.params.wSqueethAmount\n  userTx.lpAmount = event.params.crabAmount\n  userTx.ethAmount = event.params.ethWithdrawn\n  userTx.user = event.params.withdrawer\n  userTx.owner = event.transaction.from\n  userTx.type = 'WITHDRAW'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleWithdrawShutdown(event: WithdrawShutdown): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.lpAmount = event.params.crabAmount\n  userTx.ethAmount = event.params.ethWithdrawn\n  userTx.user = event.params.withdrawer\n  userTx.owner = event.transaction.from\n  userTx.type = 'WITHDRAW_SHUTDOWN'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleFlashDeposit(event: FlashDeposit): void {\n  if (event.params.depositor.equals(FLASH_BULL_ADDR) || event.params.depositor.equals(BULL_ADDR)) return\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.wSqueethAmount = event.params.tradedAmountOut\n  if (event.transaction.value.isZero()) {\n    const constructedInput = '0x' + event.transaction.input.toHex().substring(10)\n    let dec = ethereum.decode('(uint256,uint256,uint256,uint24,uint24,address)', Bytes.fromHexString(constructedInput))\n    if (dec) {\n      const decoded = dec.toTuple()\n      log.info('USDC input {}', [constructedInput])\n      log.info('USDC input {} {}', [decoded[0].toBigInt().toString(), decoded[2].toBigInt().toString()])\n      userTx.ethAmount = (userTx.ethAmount !== null ? userTx.ethAmount : BigInt.fromString('0')).plus(decoded[2].toBigInt())\n    }\n  } else {\n    userTx.ethAmount = (userTx.ethAmount !== null ? userTx.ethAmount : BigInt.fromString('0')).plus(event.transaction.value)\n  }\n  userTx.user = event.params.depositor\n  userTx.owner = event.transaction.from\n  userTx.type = 'FLASH_DEPOSIT'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleFlashWithdraw(event: FlashWithdraw): void {\n  if (event.params.withdrawer.equals(FLASH_BULL_ADDR) || event.params.withdrawer.equals(BULL_ADDR)) return\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.wSqueethAmount = event.params.wSqueethAmount\n  userTx.lpAmount = event.params.crabAmount\n  userTx.user = event.params.withdrawer\n  if (userTx.user.equals(CRAB_MIGRATION_ADDR)) {\n    userTx.user = event.transaction.from\n  }\n  userTx.owner = event.transaction.from\n  userTx.type = 'FLASH_WITHDRAW'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n}\n\nexport function handleFlashDepositCallback(event: FlashDepositCallback): void {\n  if (event.params.depositor.equals(FLASH_BULL_ADDR) || event.params.depositor.equals(BULL_ADDR)) return\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.ethAmount = ((userTx.ethAmount !== null ? userTx.ethAmount : BigInt.fromString('0')) as BigInt).minus(event.params.excess)\n  userTx.type = 'FLASH_DEPOSIT_CALLBACK'\n  userTx.save()\n}\n\nexport function handleFlashDepositERC20(event: FlashDepositERC20): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.erc20Amount = event.params.depositedAmount\n  userTx.erc20Token = event.params.depositedERC20.toHex()\n  userTx.excessEth = event.params.returnedEth\n  userTx.save()\n}\n\nexport function handleFlashWithdrawERC20(event: FlashWithdrawERC20): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.erc20Amount = event.params.withdrawnAmount\n  userTx.erc20Token = event.params.withdrawnERC20.toHex()\n  userTx.save()\n}\n\nexport function handleNettingDeposit(event: USDCDeposited): void {\n  const userTx = loadOrCreateTx(`${event.transaction.hash.toHex()}-${event.logIndex.toString()}`)\n  const contract = CrabNetting.bind(event.address)\n\n  userTx.erc20Amount = event.params.usdcAmount\n  userTx.lpAmount = event.params.crabAmount\n  userTx.user= event.params.depositor\n  userTx.owner = event.params.depositor\n  userTx.erc20Token = contract.usdc().toHex()\n  userTx.type = 'OTC_DEPOSIT'\n  userTx.timestamp = event.block.timestamp\n  userTx.transaction = event.transaction.hash.toHex()\n\n  userTx.save()\n}\n\nexport function handleNettingWithdraw(event: CrabWithdrawn): void {\n  const userTx = loadOrCreateTx(`${event.transaction.hash.toHex()}-${event.logIndex.toString()}`)\n  const contract = CrabNetting.bind(event.address)\n\n  userTx.erc20Amount = event.params.usdcAmount\n  userTx.lpAmount = event.params.crabAmount\n  userTx.user= event.params.withdrawer\n  userTx.owner = event.params.withdrawer\n  userTx.erc20Token = contract.usdc().toHex()\n  userTx.type = 'OTC_WITHDRAW'\n  userTx.timestamp = event.block.timestamp\n  userTx.transaction = event.transaction.hash.toHex()\n\n  userTx.save()\n}\n\nexport function handleFlashWithdrawCallback(event: FlashWithdrawCallback): void {\n  if (event.params.withdrawer.equals(FLASH_BULL_ADDR) || event.params.withdrawer.equals(BULL_ADDR)) return\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  userTx.ethAmount = event.params.excess\n  userTx.type = 'FLASH_WITHDRAW_CALLBACK'\n  userTx.save()\n}\n\nexport function handleTransfer(event: Transfer): void {\n  const strategy = loadOrCreateStrategy(CRAB_V2_ADDR.toHex())\n\n  let contract = CrabStrategyV2.bind(event.address)\n  const vaultId = contract.vaultId()\n  strategy.vaultId = vaultId\n\n  // Minting token\n  if (event.params.from.toHex().toLowerCase() == '0x0000000000000000000000000000000000000000') {\n    const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n    userTx.lpAmount = event.params.value\n    userTx.save()\n\n    strategy.totalSupply = (strategy.totalSupply || BigInt.zero()).plus(event.params.value)\n    strategy.save()\n  }\n  // Burning token\n  if (event.params.to.toHex().toLowerCase() == '0x0000000000000000000000000000000000000000') {\n    strategy.totalSupply = strategy.totalSupply.minus(event.params.value)\n    strategy.save()\n  }\n}\n\nexport function handleDepositV1Shares(event: DepositV1Shares): void {\n  const userTx = loadOrCreateTx(event.transaction.hash.toHex())\n  const strategy = loadOrCreateStrategy(CRAB_V1_ADDR.toHex())\n  const vault = Vault.load(strategy.vaultId.toString());\n  if (!vault) return\n\n  userTx.lpAmount = event.params.crabV1Amount\n  userTx.ethAmount = event.params.crabV1Amount.times(vault.collateralAmount).div(strategy.totalSupply)\n  userTx.user = event.params.user\n  userTx.owner = event.transaction.from\n  userTx.type = 'DEPOSIT_V1'\n  userTx.timestamp = event.block.timestamp\n  userTx.save()\n\n}\n\nexport function handleSetHedgeTimeThreshold(event: SetHedgeTimeThreshold): void {\n  const timeThreshold = new CrabHedgeTimeThreshold(event.transaction.hash.toHex())\n  timeThreshold.threshold = event.params.newHedgeTimeThreshold;\n  timeThreshold.timestamp = event.block.timestamp;\n  timeThreshold.save()\n}\n\nexport function handleQueueTransaction(event: QueueTransaction): void {\n  const tx = new TimeLockTx(event.params.txHash.toHex());\n  tx.target = event.params.target;\n  tx.value = event.params.value;\n  tx.signature = event.params.signature;\n  tx.data = event.params.data;\n  tx.eta = event.params.eta\n  tx.queued = true;\n  tx.timestamp = event.block.timestamp;\n  tx.save()\n}\n\nexport function handleExecuteTransaction(event: QueueTransaction): void {\n  const execTimeLockTx = new ExecuteTimeLockTx(event.params.txHash.toHex());\n  execTimeLockTx.timestamp = event.block.timestamp;\n  const id = event.params.txHash.toHex();\n  const tx = TimeLockTx.load(id);\n  if (tx) {\n    tx.queued = false\n    tx.save();\n    execTimeLockTx.timelocktx = tx.id;\n  }\n  execTimeLockTx.save();\n}\n\nexport function handleHedgeOTC(event: HedgeOTC): void {\n  const hedge = new HedgeOTCSchema(event.transaction.hash.toHex());\n  hedge.bidID = event.params.bidId;\n  hedge.clearingPrice = event.params.clearingPrice;\n  hedge.quantity = event.params.quantity;\n  hedge.isBuying = event.params.isBuying;\n  hedge.timestamp = event.block.timestamp;\n  hedge.save();\n\n  const strategy = loadOrCreateStrategy(CRAB_V2_ADDR.toHex())\n  strategy.lastHedgeTimestamp = event.block.timestamp\n  strategy.lastHedgeTx = event.transaction.hash.toHex()\n  strategy.save()\n}\n\nexport function handleHedgeOTCSingle(event: HedgeOTCSingle): void {\n  const hedge = new HedgeOTCSingleSchema(event.transaction.hash.toHex() + event.logIndex.toHexString());\n  hedge.hedgeOTC = event.transaction.hash.toHex();\n  hedge.trader = event.params.trader;\n  hedge.bidID = event.params.bidId;\n  hedge.clearingPrice = event.params.clearingPrice;\n  hedge.quantity = event.params.quantity;\n  hedge.price = event.params.price;\n  hedge.isBuying = event.params.isBuying;\n  hedge.timestamp = event.block.timestamp;\n  hedge.save();\n}\n\nexport function handleSetStrategyCap(event: SetStrategyCap): void {\n  const cap = new SetStrategyCapSchema(event.transaction.hash.toHex());\n  cap.cap = event.params.newCapAmount;\n  cap.timestamp = event.block.timestamp;\n  cap.save();\n}\n\nexport function handleSetHedgingTwapPeriod(event: SetHedgingTwapPeriod): void {\n  const twap = new SetHedgingTwapPeriodSchema(event.transaction.hash.toHex());\n  twap.hedging = event.params.newHedgingTwapPeriod;\n  twap.timestamp = event.block.timestamp;\n  twap.save();\n}\n\nexport function handleSetHedgePriceThreshold(event: SetHedgePriceThreshold): void {\n  const price = new SetHedgePriceThresholdSchema(event.transaction.hash.toHex());\n  price.threshold = event.params.newHedgePriceThreshold;\n  price.timestamp = event.block.timestamp;\n  price.save();\n}\n\nexport function handleSetOTCPriceTolerance(event: SetOTCPriceTolerance): void {\n  const tolerance = new SetOTCPriceToleranceSchema(event.transaction.hash.toHex());\n  tolerance.tolerance = event.params.otcPriceTolerance;\n  tolerance.timestamp = event.block.timestamp;\n  tolerance.save();\n}\n\nexport function handleVaultTransferred(event: VaultTransferred): void {\n  const transfer = new VaultTransferredSchema(event.transaction.hash.toHex());\n  transfer.strategy = event.params.newStrategy;\n  transfer.vaultID = event.params.vaultId;\n  transfer.save();\n}"
  },
  {
    "path": "packages/subgraph/src/crabstrategy.ts",
    "content": "import { Address, BigInt, log } from \"@graphprotocol/graph-ts\"\nimport {\n  CrabStrategy,\n  Deposit,\n  Withdraw,\n  FlashDeposit,\n  FlashWithdraw,\n  Transfer,\n  HedgeOnUniswap,\n  Hedge,\n  FlashDepositCallback,\n  FlashWithdrawCallback,\n  ExecuteSellAuction,\n  ExecuteBuyAuction\n} from \"../generated/CrabStrategy/CrabStrategy\"\nimport { CrabStrategyV2 } from \"../generated/CrabStrategyV2/CrabStrategyV2\"\nimport { CrabAuction, CrabStrategyTx, Strategy } from \"../generated/schema\"\nimport { CRAB_V1_ADDR } from \"./constants\"\nimport { loadOrCreateStrategy } from \"./util\"\n\nfunction loadOrCreateTx(id: string): CrabStrategyTx {\n  let strategy = CrabStrategyTx.load(id)\n  if (strategy) return strategy\n\n  strategy = new CrabStrategyTx(id)\n  strategy.type = \"Transfer\"\n  strategy.lpAmount = BigInt.zero()\n  strategy.ethAmount = BigInt.zero()\n  strategy.timestamp = BigInt.zero()\n  return strategy\n}\n\nexport function handleDeposit(event: Deposit): void {\n  const strategyTx = loadOrCreateTx(event.transaction.hash.toHex())\n  strategyTx.wSqueethAmount = event.params.wSqueethAmount\n  strategyTx.lpAmount = event.params.lpAmount\n  strategyTx.ethAmount = event.transaction.value\n  strategyTx.owner = event.transaction.from\n  strategyTx.timestamp = event.block.timestamp\n  strategyTx.type = 'DEPOSIT'\n  strategyTx.save()\n}\n\nexport function handleWithdraw(event: Withdraw): void {\n  const strategyTx = loadOrCreateTx(event.transaction.hash.toHex())\n  strategyTx.wSqueethAmount = event.params.wSqueethAmount\n  strategyTx.lpAmount = event.params.crabAmount\n  strategyTx.ethAmount = event.params.ethWithdrawn\n  strategyTx.owner = event.transaction.from\n  strategyTx.timestamp = event.block.timestamp\n  strategyTx.type = 'WITHDRAW'\n  strategyTx.save()\n}\n\nexport function handleFlashDeposit(event: FlashDeposit): void {\n  const strategyTx = loadOrCreateTx(event.transaction.hash.toHex())\n  strategyTx.wSqueethAmount = event.params.tradedAmountOut\n  strategyTx.ethAmount = (strategyTx.ethAmount !== null ? strategyTx.ethAmount : BigInt.fromString('0')).plus(event.transaction.value)\n  strategyTx.owner = event.transaction.from\n  strategyTx.timestamp = event.block.timestamp\n  strategyTx.type = 'FLASH_DEPOSIT'\n  strategyTx.save()\n}\n\nexport function handleFlashWithdraw(event: FlashWithdraw): void {\n  const strategyTx = loadOrCreateTx(event.transaction.hash.toHex())\n  strategyTx.wSqueethAmount = event.params.wSqueethAmount\n  strategyTx.lpAmount = event.params.crabAmount\n  strategyTx.owner = event.transaction.from\n  strategyTx.timestamp = event.block.timestamp\n  strategyTx.type = 'FLASH_WITHDRAW'\n  strategyTx.save()\n}\n\nexport function handleHedgeOnUniswap(event: HedgeOnUniswap): void {\n  const strategyTx = loadOrCreateTx(event.transaction.hash.toHex())\n  strategyTx.type = 'HEDGE_ON_UNISWAP'\n  strategyTx.wSqueethHedgeTargetAmount = event.params.wSqueethHedgeTargetAmount\n  strategyTx.ethHedgeTargetAmount = event.params.ethHedgetargetAmount\n  strategyTx.auctionPrice = event.params.auctionPrice\n  strategyTx.isSellingSqueeth = event.params.auctionType\n  strategyTx.owner = event.params.hedger\n  strategyTx.timestamp = event.block.timestamp\n  strategyTx.save()\n}\n\nexport function handleHedge(event: Hedge): void {\n  const strategyTx = loadOrCreateTx(event.transaction.hash.toHex())\n  strategyTx.type = 'HEDGE'\n  strategyTx.wSqueethHedgeTargetAmount = event.params.wSqueethHedgeTargetAmount\n  strategyTx.ethHedgeTargetAmount = event.params.ethHedgetargetAmount\n  strategyTx.auctionPrice = event.params.auctionPrice\n  strategyTx.isSellingSqueeth = event.params.auctionType\n  strategyTx.hedgerPrice = event.params.hedgerPrice\n  strategyTx.owner = event.params.hedger\n  strategyTx.timestamp = event.block.timestamp\n  strategyTx.save()\n}\n\nexport function handleFlashDepositCallback(event: FlashDepositCallback): void {\n  const strategyTx = loadOrCreateTx(event.transaction.hash.toHex())\n  strategyTx.ethAmount = ((strategyTx.ethAmount !== null ? strategyTx.ethAmount : BigInt.fromString('0')) as BigInt).minus(event.params.excess)\n  strategyTx.save()\n}\n\nexport function handleFlashWithdrawCallback(event: FlashWithdrawCallback): void {\n  const strategyTx = loadOrCreateTx(event.transaction.hash.toHex())\n  strategyTx.ethAmount = event.params.excess\n  strategyTx.save()\n}\n\nexport function handleTransfer(event: Transfer): void {\n  const strategyTx = loadOrCreateTx(event.transaction.hash.toHex())\n  const strategy = loadOrCreateStrategy(CRAB_V1_ADDR.toHex())\n\n  let contract = CrabStrategy.bind(event.address)\n  const vaultId = contract.vaultId()\n  strategy.vaultId = vaultId\n\n\n  // Minting token\n  if (event.params.from.toHex().toLowerCase() == '0x0000000000000000000000000000000000000000') {\n    strategyTx.lpAmount = event.params.value\n    strategyTx.save()\n    strategy.totalSupply = strategy.totalSupply.plus(event.params.value)\n    strategy.save()\n  }\n  // Burning token\n  if (event.params.to.toHex().toLowerCase() == '0x0000000000000000000000000000000000000000') {\n    strategy.totalSupply = strategy.totalSupply.minus(event.params.value)\n    strategy.save()\n  }\n}\n\nexport function handleExecuteSellAuction(event: ExecuteSellAuction): void {\n  const auction = new CrabAuction(event.transaction.hash.toHex())\n  auction.ethAmount = event.params.ethBought\n  auction.squeethAmount = event.params.wSqueethSold\n  auction.isSellingSqueeth = true\n  auction.isHedgingOnUniswap = event.params.isHedgingOnUniswap\n  auction.timestamp = event.block.timestamp\n  auction.owner = event.transaction.from\n  auction.save()\n}\n\nexport function handleExecuteBuyAuction(event: ExecuteBuyAuction): void {\n  const auction = new CrabAuction(event.transaction.hash.toHex())\n  auction.ethAmount = event.params.ethSold\n  auction.squeethAmount = event.params.wSqueethBought\n  auction.isSellingSqueeth = false\n  auction.isHedgingOnUniswap = event.params.isHedgingOnUniswap\n  auction.timestamp = event.block.timestamp\n  auction.owner = event.transaction.from\n  auction.save()\n}"
  },
  {
    "path": "packages/subgraph/src/util.ts",
    "content": "import { Address, BigInt } from \"@graphprotocol/graph-ts\";\nimport { Account, Strategy } from \"../generated/schema\";\nimport {\n  MAINNET_SHORT_HELPER_ADDR,\n  ROPSTEN_SHORT_HELPER_ADDR,\n  LOCALHOST_SHORT_HELPER_ADDR,\n  RA_SHORT_HELPER_ADDR,\n  GOERLI_SHORT_HELPER_ADDR,\n  BIGINT_ZERO,\n  MAINNET_CRAB_V2_ADDR,\n  ROPSTEN_CRAB_V2_ADDR,\n  MAINNET_CRAB_MIGRATION_ADDR,\n  ROPSTEN_CRAB_MIGRATION_ADDR,\n  MAINNET_CRAB_V1_ADDR,\n  ROPSTEN_CRAB_V1_ADDR,\n  GOERLI_CRAB_V2_ADDR,\n  GOERLI_CRAB_MIGRATION_ADDR,\n  GOERLI_CRAB_V1_ADDR,\n  MAINNET_FLASH_BULL_ADDR,\n  GOERLI_FLASH_BULL_ADDR,\n  MAINNET_BULL_STRATEGY_ADDR,\n  GOERLI_BULL_STRATEGY_ADDR,\n  GOERLI_AUCTION_BULL_ADDR,\n  MAINNET_AUCTION_BULL_ADDR,\n  MAINNET_WETH_ADDR,\n  GOERLI_WETH_ADDR\n} from \"./constants\";\n\nexport function getShortHelperAddr(networkName: string): Address {\n  let addr = MAINNET_SHORT_HELPER_ADDR;\n  if (networkName == \"ropsten\") {\n    addr = ROPSTEN_SHORT_HELPER_ADDR;\n  } else if (networkName == \"localhost\") {\n    addr = LOCALHOST_SHORT_HELPER_ADDR;\n  } else if (networkName == \"rinkebyArbitrum\") {\n    addr = RA_SHORT_HELPER_ADDR;\n  } else if (networkName == \"goerli\") {\n    addr = GOERLI_SHORT_HELPER_ADDR;\n  } \n  return addr;\n}\n\nexport function getCrabV2Addr(networkName: string): Address {\n  let addr = MAINNET_CRAB_V2_ADDR;\n  if (networkName == \"ropsten\") {\n    addr = ROPSTEN_CRAB_V2_ADDR;\n  } else if (networkName == \"goerli\") {\n    addr = GOERLI_CRAB_V2_ADDR\n  }\n\n  return addr;\n}\n\nexport function getCrabMigrationAddr(networkName: string): Address {\n  let addr = MAINNET_CRAB_MIGRATION_ADDR;\n  if (networkName == \"ropsten\") {\n    addr = ROPSTEN_CRAB_MIGRATION_ADDR;\n  } else if (networkName == \"goerli\") {\n    addr = GOERLI_CRAB_MIGRATION_ADDR;\n  }\n\n  return addr;\n}\n\nexport function getCrabV1Addr(networkName: string): Address {\n  let addr = MAINNET_CRAB_V1_ADDR;\n  if (networkName == \"ropsten\") {\n    addr = ROPSTEN_CRAB_V1_ADDR\n  } else if (networkName == \"goerli\") {\n    addr = GOERLI_CRAB_V1_ADDR\n  }\n\n  return addr;\n}\n\nexport function getFlashBullAddr(networkName: string): Address {\n  let addr = MAINNET_FLASH_BULL_ADDR;\n  if (networkName == \"ropsten\") {\n    addr = GOERLI_FLASH_BULL_ADDR\n  } else if (networkName == \"goerli\") {\n    addr = GOERLI_FLASH_BULL_ADDR\n  }\n\n  return addr;\n}\n\nexport function getBullAddr(networkName: string): Address {\n  let addr = MAINNET_BULL_STRATEGY_ADDR;\n  if (networkName == \"ropsten\") {\n    addr = GOERLI_BULL_STRATEGY_ADDR\n  } else if (networkName == \"goerli\") {\n    addr = GOERLI_BULL_STRATEGY_ADDR\n  }\n\n  return addr;\n}\n\nexport function getAuctionBullAddr(networkName: string): Address {\n  let addr = MAINNET_AUCTION_BULL_ADDR;\n  if (networkName == \"ropsten\") {\n    addr = GOERLI_AUCTION_BULL_ADDR\n  } else if (networkName == \"goerli\") {\n    addr = GOERLI_AUCTION_BULL_ADDR\n  }\n\n  return addr;\n}\n\nexport function getWethAddr(networkName: string): Address {\n  let addr = MAINNET_WETH_ADDR;\n  if (networkName == \"goerli\") {\n    addr = GOERLI_WETH_ADDR;\n  }\n\n  return addr;\n}\n\nexport function loadOrCreateAccount(accountId: string): Account {\n  let account = Account.load(accountId);\n  // if no account, create new entity\n  if (account == null) {\n    account = new Account(accountId);\n    account.vaultCount = BIGINT_ZERO;\n  }\n  return account as Account;\n}\n\nexport function loadOrCreateStrategy(id: string): Strategy {\n  let strategy = Strategy.load(id)\n  if (strategy) return strategy\n\n  strategy =  new Strategy(id)\n  strategy.totalSupply = BigInt.zero()\n  strategy.vaultId = BigInt.zero()\n  strategy.lastHedgeTimestamp = BigInt.zero()\n  strategy.lastHedgeTx = ''\n  return strategy\n}"
  },
  {
    "path": "packages/subgraph/subgraph.template.yaml",
    "content": "specVersion: 0.0.6\nschema:\n  file: ./schema.graphql\ndataSources:\n  - kind: ethereum/contract\n    name: Controller\n    network: {{network}}\n    source:\n      address: \"{{Controller}}\"\n      abi: Controller\n      startBlock: {{Controller-start-block}}\n    mapping:\n      kind: ethereum/events\n      apiVersion: 0.0.7\n      language: wasm/assemblyscript\n      entities:\n        - BurnShort\n        - DepositCollateral\n        - DepositUniPositionToken\n        - FeeRateUpdated\n        - FeeRecipientUpdated\n        - Liquidate\n        - MintShort\n        - NormalizationFactorUpdated\n        - OpenVault\n        - OwnershipTransferred\n        - Paused\n        - RedeemLong\n        - RedeemShort\n        - ReduceDebt\n        - Shutdown\n        - UnPaused\n        - UpdateOperator\n        - WithdrawCollateral\n        - WithdrawUniPositionToken\n      abis:\n        - name: Controller\n          file: ./abis/Controller.json\n      eventHandlers:\n        - event: BurnShort(address,uint256,uint256)\n          handler: handleBurnShort\n        - event: DepositCollateral(address,uint256,uint256)\n          handler: handleDepositCollateral\n        - event: DepositUniPositionToken(address,uint256,uint256)\n          handler: handleDepositUniPositionToken\n        - event: FeeRateUpdated(uint256,uint256)\n          handler: handleFeeRateUpdated\n        - event: FeeRecipientUpdated(address,address)\n          handler: handleFeeRecipientUpdated\n        - event: Liquidate(address,uint256,uint256,uint256)\n          handler: handleLiquidate\n        - event: MintShort(address,uint256,uint256)\n          handler: handleMintShort\n        - event: NormalizationFactorUpdated(uint256,uint256,uint256,uint256)\n          handler: handleNormalizationFactorUpdated\n        - event: OpenVault(address,uint256)\n          handler: handleOpenVault\n        - event: OwnershipTransferred(indexed address,indexed address)\n          handler: handleOwnershipTransferred\n        - event: Paused(uint256)\n          handler: handlePaused\n        - event: RedeemLong(address,uint256,uint256)\n          handler: handleRedeemLong\n        - event: RedeemShort(address,uint256,uint256)\n          handler: handleRedeemShort\n        - event: ReduceDebt(address,uint256,uint256,uint256,uint256,uint256,uint256)\n          handler: handleReduceDebt\n        - event: Shutdown(uint256)\n          handler: handleShutdown\n        - event: UnPaused(address)\n          handler: handleUnPaused\n        - event: UpdateOperator(address,uint256,address)\n          handler: handleUpdateOperator\n        - event: WithdrawCollateral(address,uint256,uint256)\n          handler: handleWithdrawCollateral\n        - event: WithdrawUniPositionToken(address,uint256,uint256)\n          handler: handleWithdrawUniPositionToken\n      file: ./src/controller.ts\n  - kind: ethereum/contract\n    name: CrabStrategy\n    network: {{network}}\n    source:\n      address: \"{{CrabStrategyDeployment}}\"\n      abi: CrabStrategy\n      startBlock: {{CrabStrategyDeployment-start-block}}\n    mapping:\n      kind: ethereum/events\n      apiVersion: 0.0.7\n      language: wasm/assemblyscript\n      entities:\n        - Deposit\n        - Withdraw\n        - WithdrawShutdown\n        - FlashDeposit\n        - FlashWithdraw\n        - Transfer\n        - HedgeOnUniswap\n        - Hedge\n        - FlashDepositCallback\n        - FlashWithdrawCallback\n        - ExecuteSellAuction\n        - ExecuteBuyAuction\n        - Strategy\n      abis:\n        - name: CrabStrategy\n          file: ./abis/CrabStrategyDeployment.json\n      eventHandlers:\n        - event: Deposit(indexed address,uint256,uint256)\n          handler: handleDeposit\n        - event: Withdraw(indexed address,uint256,uint256,uint256)\n          handler: handleWithdraw\n        - event: FlashDeposit(indexed address,uint256,uint256)\n          handler: handleFlashDeposit\n        - event: FlashWithdraw(indexed address,uint256,uint256)\n          handler: handleFlashWithdraw\n        - event: Transfer(indexed address,indexed address,uint256)\n          handler: handleTransfer\n        - event: HedgeOnUniswap(indexed address,bool,uint256,uint256,uint256)\n          handler: handleHedgeOnUniswap\n        - event: Hedge(indexed address,bool,uint256,uint256,uint256,uint256)\n          handler: handleHedge\n        - event: FlashDepositCallback(indexed address,uint256,uint256)\n          handler: handleFlashDepositCallback\n        - event: FlashWithdrawCallback(indexed address,uint256,uint256)\n          handler: handleFlashWithdrawCallback \n        - event: ExecuteSellAuction(indexed address,uint256,uint256,bool)\n          handler: handleExecuteSellAuction\n        - event: ExecuteBuyAuction(indexed address,uint256,uint256,bool)\n          handler: handleExecuteBuyAuction \n      file: ./src/crabstrategy.ts\n  - kind: ethereum/contract\n    name: CrabStrategyV2\n    network: {{network}}\n    source:\n      address: \"{{CrabStrategyV2}}\"\n      abi: CrabStrategyV2\n      startBlock: {{CrabStrategyV2-start-block}}\n    mapping:\n      kind: ethereum/events\n      apiVersion: 0.0.7\n      language: wasm/assemblyscript\n      entities:\n        - SetHedgeTimeThreshold\n      abis:\n        - name: CrabStrategyV2\n          file: ./abis/CrabStrategyV2.json\n      eventHandlers:\n        - event: SetHedgeTimeThreshold(uint256)\n          handler: handleSetHedgeTimeThreshold\n        - event: HedgeOTC(uint256,uint256,bool,uint256)\n          handler: handleHedgeOTC\n        - event: HedgeOTCSingle(address,uint256,uint256,uint256,bool,uint256)\n          handler: handleHedgeOTCSingle\n        - event: SetStrategyCap(uint256)\n          handler: handleSetStrategyCap\n        - event: SetHedgingTwapPeriod(uint32)\n          handler: handleSetHedgingTwapPeriod\n        - event: SetHedgePriceThreshold(uint256)\n          handler: handleSetHedgePriceThreshold\n        - event: SetOTCPriceTolerance(uint256)\n          handler: handleSetOTCPriceTolerance\n        - event: VaultTransferred(indexed address,uint256)\n          handler: handleVaultTransferred\n        - event: Deposit(indexed address,uint256,uint256)\n          handler: handleDeposit\n        - event: Withdraw(indexed address,uint256,uint256,uint256)\n          handler: handleWithdraw\n        - event: WithdrawShutdown(indexed address,uint256,uint256)\n          handler: handleWithdrawShutdown\n        - event: FlashDeposit(indexed address,uint256,uint256)\n          handler: handleFlashDeposit\n        - event: FlashWithdraw(indexed address,uint256,uint256)\n          handler: handleFlashWithdraw\n        - event: FlashDepositCallback(indexed address,uint256,uint256)\n          handler: handleFlashDepositCallback\n        - event: FlashWithdrawCallback(indexed address,uint256,uint256)\n          handler: handleFlashWithdrawCallback \n        - event: Transfer(indexed address,indexed address,uint256)\n          handler: handleTransfer\n      file: ./src/crabV2.ts\n  - kind: ethereum/contract\n    name: Timelock\n    network: {{network}}\n    source:\n      address: \"{{Timelock}}\"\n      abi: Timelock\n      startBlock: {{Timelock-start-block}}\n    mapping:\n      kind: ethereum/events\n      apiVersion: 0.0.7\n      language: wasm/assemblyscript\n      entities:\n        - TimeLockTx\n      abis:\n        - name: Timelock\n          file: ./abis/Timelock.json\n      eventHandlers:\n        - event: QueueTransaction(indexed bytes32,indexed address,uint256,string,bytes,uint256)\n          handler: handleQueueTransaction\n        - event: ExecuteTransaction(indexed bytes32,indexed address,uint256,string,bytes,uint256)\n          handler: handleExecuteTransaction\n      file: ./src/crabV2.ts\n  - kind: ethereum/contract\n    name: CrabMigration\n    network: {{network}}\n    source:\n      address: \"{{CrabMigration}}\"\n      abi: CrabMigration\n      startBlock: {{CrabMigration-start-block}}\n    mapping:\n      kind: ethereum/events\n      apiVersion: 0.0.7\n      language: wasm/assemblyscript\n      entities:\n        - Strategy\n      abis:\n        - name: CrabMigration\n          file: ./abis/CrabMigration.json\n      eventHandlers:\n        - event: DepositV1Shares(indexed address,uint256)\n          handler: handleDepositV1Shares\n      file: ./src/crabV2.ts\n  - kind: ethereum/contract\n    name: CrabHelper\n    network: {{network}}\n    source:\n      address: \"{{CrabHelper}}\"\n      abi: CrabHelper\n      startBlock: {{CrabHelper-start-block}}\n    mapping:\n      kind: ethereum/events\n      apiVersion: 0.0.7\n      language: wasm/assemblyscript\n      entities:\n        - Strategy\n      abis:\n        - name: CrabHelper\n          file: ./abis/CrabHelper.json\n      eventHandlers:\n        - event: FlashDepositERC20(indexed address,address,uint256,uint256,uint256,uint256)\n          handler: handleFlashDepositERC20\n        - event: FlashWithdrawERC20(indexed address,address,uint256,uint256,uint256)\n          handler: handleFlashWithdrawERC20\n      file: ./src/crabV2.ts\n  - kind: ethereum/contract\n    name: CrabNetting\n    network: {{network}}\n    source:\n      address: \"{{CrabNetting}}\"\n      abi: CrabNetting\n      startBlock: {{CrabNetting-start-block}}\n    mapping:\n      kind: ethereum/events\n      apiVersion: 0.0.7\n      language: wasm/assemblyscript\n      entities:\n        - Strategy\n      abis:\n        - name: CrabNetting\n          file: ./abis/CrabNetting.json\n      eventHandlers:\n        - event: USDCDeposited(indexed address,uint256,uint256,indexed uint256,uint256)\n          handler: handleNettingDeposit\n        - event: CrabWithdrawn(indexed address,uint256,uint256,indexed uint256)\n          handler: handleNettingWithdraw\n      file: ./src/crabV2.ts\n  - kind: ethereum/contract\n    name: ZenBullStrategy\n    network: {{network}}\n    source:\n      address: \"{{ZenBullStrategy}}\"\n      abi: ZenBullStrategy\n      startBlock: {{ZenBullStrategy-start-block}}\n    mapping:\n      kind: ethereum/events\n      apiVersion: 0.0.7\n      language: wasm/assemblyscript\n      entities:\n        - Deposit\n        - Withdraw\n        - WithdrawShutdown\n        - Strategy\n      abis:\n        - name: ZenBullStrategy\n          file: ./abis/ZenBullStrategy.json\n      eventHandlers:\n        - event: Withdraw(indexed address,uint256,uint256,uint256,uint256,uint256)\n          handler: handleWithdraw\n        - event: Deposit(indexed address,uint256,uint256,uint256)\n          handler: handleDeposit\n        - event: SetCap(uint256,uint256)\n          handler: handleSetCap\n        - event: RedeemCrabAndWithdrawEth(indexed uint256,uint256,uint256)\n          handler: handleRedeemCrabAndWithdrawEth\n        - event: SetShutdownContract(address,address)\n          handler: handleSetShutdownContract\n        - event: ShutdownRepayAndWithdraw(uint256,uint256,uint256)\n          handler: handleShutdownRepayAndWithdraw\n        - event: Farm(indexed address,indexed address)\n          handler: handleFarm\n        - event: DepositEthIntoCrab(uint256)\n          handler: handleDepositEthIntoCrab\n        - event: WithdrawShutdown(indexed address,uint256,uint256)\n          handler: handleWithdrawShutdown\n        - event: AuctionRepayAndWithdrawFromLeverage(indexed address,uint256,uint256)\n          handler: handleAuctionRepayAndWithdrawFromLeverage\n        - event: SetAuction(address,address)\n          handler: handleSetAuction\n        - event: Transfer(indexed address,indexed address,uint256)\n          handler: handleTransfer\n      file: ./src/bullStrategy.ts\n  - kind: ethereum/contract\n    name: ZenAuction\n    network: {{network}}\n    source:\n      address: \"{{ZenAuction}}\"\n      abi: ZenAuction\n      startBlock: {{ZenAuction-start-block}}\n    mapping:\n      kind: ethereum/events\n      apiVersion: 0.0.7\n      language: wasm/assemblyscript\n      entities:\n        - Strategy\n      abis:\n        - name: ZenAuction\n          file: ./abis/ZenAuction.json\n      eventHandlers:\n        - event: SetCrUpperAndLower(uint256,uint256,uint256,uint256)\n          handler: handleSetCrUpperAndLower\n        - event: SetDeltaUpperAndLower(uint256,uint256,uint256,uint256)\n          handler: handleSetDeltaUpperAndLower\n        - event: LeverageRebalance(bool,uint256,uint256)\n          handler: handleLeverageRebalance\n        - event: FullRebalance(uint256,uint256,bool,uint256,uint256)\n          handler: handleFullRebalance\n        - event: SetFullRebalanceClearingPriceTolerance(uint256,uint256)\n          handler: handleSetFullRebalanceClearingPriceTolerance\n        - event: SetRebalanceWethLimitPriceTolerance(uint256,uint256)\n          handler: handleSetRebalanceWethLimitPriceTolerance\n        - event: SetAuctionManager(address,address)\n          handler: handleSetAuctionManager\n      file: ./src/bullStrategy.ts\n  - kind: ethereum/contract\n    name: FlashZen\n    network: {{network}}\n    source:\n      address: \"{{FlashZen}}\"\n      abi: FlashZen\n      startBlock: {{FlashZen-start-block}}\n    mapping:\n      kind: ethereum/events\n      apiVersion: 0.0.7\n      language: wasm/assemblyscript\n      entities:\n        - Strategy\n      abis:\n        - name: FlashZen\n          file: ./abis/FlashZen.json\n      eventHandlers:\n        - event: FlashWithdraw(indexed address,uint256,uint256)\n          handler: handleFlashWithdraw\n        - event: FlashDeposit(indexed address,uint256,uint256,uint256,uint256,uint256)\n          handler: handleFlashDeposit\n          receipt: true\n      file: ./src/bullStrategy.ts"
  },
  {
    "path": "packages/zen-bull-netting/.gitignore",
    "content": "/report\n/broadcast\n/out\n/cache\n.env"
  },
  {
    "path": "packages/zen-bull-netting/README.md",
    "content": "# ZenBull Netting Contract\n\n## Table of Contents\n\n- [ZenBull Netting](#zenbull-netting)\n  - [Table of Contents](#table-of-contents)\n  - [Local Development](#local-development)\n  - [How To Deploy](#how-to-deploy)\n  - [Audits](#audits)\n  - [License](#license)\n\n## Local Development\n\nTo install dependencies and compile contracts:\n\n```bash\ngit clone https://github.com/opynfinance/squeeth-monorepo && cd packages/zen-bull-netting\n```\n\nTo install Foundry (assuming a Linux or macOS system):\n\n```bash\ncurl -L https://foundry.paradigm.xyz | bash\n```\n\nThis will download foundryup. To start Foundry, run:\n\n```bash\nfoundryup\n```\n\nTo install dependencies:\n\n```\nforge install\n```\n\n<!-- There are three Foundry profiles for running the test suites, which bypass the IR pipeline to speed up compilation. To run tests, run any of the following: -->\n\n```bash\nFOUNDRY_PROFILE=test forge test # run only test functions\nFOUNDRY_PROFILE=fuzz forge test # run only fuz testing (function with name that include \"Fuzzing\")\nFOUNDRY_PROFILE=coverage forge coverage # coverage report\n```\n\nTo run tests, you need to create `.env` file with the variables included in `.env.example`.\n\nYou may wish to include a `.env` file that `export`s a specific profile when developing locally.\n\nThe following modifiers are also available:\n\n- Level 2 (-vv): Logs emitted during tests are also displayed.\n- Level 3 (-vvv): Stack traces for failing tests are also displayed.\n- Level 4 (-vvvv): Stack traces for all tests are displayed, and setup traces for failing tests are displayed.\n- Level 5 (-vvvvv): Stack traces and setup traces are always displayed.\n\n```bash\nFOUNDRY_PROFILE=test forge test forge test  -vvvv\n```\n\nFor more information on foundry testing and use, see [Foundry Book installation instructions](https://book.getfoundry.sh/getting-started/installation.html).\n\n## How To Deploy\n\nBefore running the deployment script, make sure to copy `.env.example` in a `.env` file and set the environment variables.\n\nThe deployment script for [Mainnet](/packages/zen-bull-netting/script/MainnetDeployScript.s.sol) and [Goerli](/packages/zen-bull-netting/script/GoerliDeployScript.s.sol) can be executed using the below command:\n```shell\n$ source .env\n$ forge script script/MainnetDeployScript.s.sol:MainnetDeployScript --rpc-url $MAINNET_RPC_URL --broadcast --verify -vvvv\n```\n\n## Audits\n\n## License\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/.gitignore",
    "content": "book/"
  },
  {
    "path": "packages/zen-bull-netting/docs/book.css",
    "content": "table {\n    margin: 0 auto;\n    border-collapse: collapse;\n    width: 100%;\n}\n\ntable td:first-child {\n    width: 15%;\n}\n  \ntable td:nth-child(2) {\n    width: 25%;\n}"
  },
  {
    "path": "packages/zen-bull-netting/docs/book.toml",
    "content": "[book]\nsrc = 'src'\ntitle = ''\n[output.html]\nno-section-label = true\nadditional-js = ['solidity.min.js']\nadditional-css = ['book.css']\ngit-repository-url = 'https://github.com/opynfinance/squeeth-monorepo'\n\n[output.html.fold]\nenable = true\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/README.md",
    "content": "# ZenBull Netting Contract\n\n## Table of Contents\n\n- [ZenBull Netting](#zenbull-netting)\n  - [Table of Contents](#table-of-contents)\n  - [Local Development](#local-development)\n  - [How To Deploy](#how-to-deploy)\n  - [Audits](#audits)\n  - [License](#license)\n\n## Local Development\n\nTo install dependencies and compile contracts:\n\n```bash\ngit clone https://github.com/opynfinance/squeeth-monorepo && cd packages/zen-bull-netting\n```\n\nTo install Foundry (assuming a Linux or macOS system):\n\n```bash\ncurl -L https://foundry.paradigm.xyz | bash\n```\n\nThis will download foundryup. To start Foundry, run:\n\n```bash\nfoundryup\n```\n\nTo install dependencies:\n\n```\nforge install\n```\n\n<!-- There are three Foundry profiles for running the test suites, which bypass the IR pipeline to speed up compilation. To run tests, run any of the following: -->\n\n```bash\nFOUNDRY_PROFILE=test forge test # run only test functions\nFOUNDRY_PROFILE=fuzz forge test # run only fuz testing (function with name that include \"Fuzzing\")\nFOUNDRY_PROFILE=coverage forge coverage # coverage report\n```\n\nTo run tests, you need to create `.env` file with the variables included in `.env.example`.\n\nYou may wish to include a `.env` file that `export`s a specific profile when developing locally.\n\nThe following modifiers are also available:\n\n- Level 2 (-vv): Logs emitted during tests are also displayed.\n- Level 3 (-vvv): Stack traces for failing tests are also displayed.\n- Level 4 (-vvvv): Stack traces for all tests are displayed, and setup traces for failing tests are displayed.\n- Level 5 (-vvvvv): Stack traces and setup traces are always displayed.\n\n```bash\nFOUNDRY_PROFILE=test forge test forge test  -vvvv\n```\n\nFor more information on foundry testing and use, see [Foundry Book installation instructions](https://book.getfoundry.sh/getting-started/installation.html).\n\n## How To Deploy\n\nBefore running the deployment script, make sure to copy `.env.example` in a `.env` file and set the environment variables.\n\nThe deployment script for [Mainnet](/packages/zen-bull-netting/script/MainnetDeployScript.s.sol) and [Goerli](/packages/zen-bull-netting/script/GoerliDeployScript.s.sol) can be executed using the below command:\n```shell\n$ source .env\n$ forge script script/MainnetDeployScript.s.sol:MainnetDeployScript --rpc-url $MAINNET_RPC_URL --broadcast --verify -vvvv\n```\n\n## Audits\n\n## License\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/SUMMARY.md",
    "content": "# Summary\n- [Home](README.md)\n# src\n  - [❱ interface](src/interface/README.md)\n    - [IController](src/interface/IController.sol/contract.IController.md)\n    - [ICrabStrategyV2](src/interface/ICrabStrategyV2.sol/contract.ICrabStrategyV2.md)\n    - [IEulerSimpleLens](src/interface/IEulerSimpleLens.sol/contract.IEulerSimpleLens.md)\n    - [IFlashZen](src/interface/IFlashZen.sol/contract.IFlashZen.md)\n    - [IOracle](src/interface/IOracle.sol/contract.IOracle.md)\n    - [IWETH](src/interface/IWETH.sol/contract.IWETH.md)\n    - [IZenBullStrategy](src/interface/IZenBullStrategy.sol/contract.IZenBullStrategy.md)\n  - [PoolAddress](src/FlashSwap.sol/contract.PoolAddress.md)\n  - [CallbackValidation](src/FlashSwap.sol/contract.CallbackValidation.md)\n  - [FlashSwap](src/FlashSwap.sol/contract.FlashSwap.md)\n  - [NettingLib](src/NettingLib.sol/contract.NettingLib.md)\n  - [ZenBullNetting](src/ZenBullNetting.sol/contract.ZenBullNetting.md)\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/FlashSwap.sol/contract.CallbackValidation.md",
    "content": "# CallbackValidation\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/FlashSwap.sol)\n\nProvides validation for callbacks from Uniswap V3 Pools\n\n\n## Functions\n### verifyCallback\n\nReturns the address of a valid Uniswap V3 Pool\n\n\n```solidity\nfunction verifyCallback(address factory, address tokenA, address tokenB, uint24 fee)\n    internal\n    view\n    returns (IUniswapV3Pool pool);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`factory`|`address`|The contract address of the Uniswap V3 factory|\n|`tokenA`|`address`|The contract address of either token0 or token1|\n|`tokenB`|`address`|The contract address of the other token|\n|`fee`|`uint24`|The fee collected upon every swap in the pool, denominated in hundredths of a bip|\n\n**Returns**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`pool`|`IUniswapV3Pool`|The V3 pool contract address|\n\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/FlashSwap.sol/contract.FlashSwap.md",
    "content": "# FlashSwap\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/FlashSwap.sol)\n\n**Inherits:**\nIUniswapV3SwapCallback\n\n**Author:**\nopyn team\n\nFlashSwap contract\n\n*contract that interacts with Uniswap pool*\n\n\n## State Variables\n### factory\n*Uniswap factory address*\n\n\n```solidity\naddress internal immutable factory;\n```\n\n\n## Functions\n### constructor\n\n*constructor*\n\n\n```solidity\nconstructor(address _factory);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_factory`|`address`|uniswap factory address|\n\n\n### uniswapV3SwapCallback\n\nuniswap swap callback function for flashes\n\n\n```solidity\nfunction uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) external override;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`amount0Delta`|`int256`|amount of token0|\n|`amount1Delta`|`int256`|amount of token1|\n|`_data`|`bytes`|callback data encoded as SwapCallbackData struct|\n\n\n### _uniFlashSwap\n\n\n```solidity\nfunction _uniFlashSwap(address pool, uint256 amountToPay, bytes memory callData, uint8 callSource) internal virtual;\n```\n\n### _exactInFlashSwap\n\nexecute an exact-in flash swap (specify an exact amount to pay)\n\n\n```solidity\nfunction _exactInFlashSwap(\n    address _tokenIn,\n    address _tokenOut,\n    uint24 _fee,\n    uint256 _amountIn,\n    uint256 _amountOutMinimum,\n    uint8 _callSource,\n    bytes memory _data\n) internal returns (uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_tokenIn`|`address`|token address to sell|\n|`_tokenOut`|`address`|token address to receive|\n|`_fee`|`uint24`|pool fee|\n|`_amountIn`|`uint256`|amount to sell|\n|`_amountOutMinimum`|`uint256`|minimum amount to receive|\n|`_callSource`|`uint8`|function call source|\n|`_data`|`bytes`|arbitrary data assigned with the call|\n\n\n### _exactOutFlashSwap\n\nexecute an exact-out flash swap (specify an exact amount to receive)\n\n\n```solidity\nfunction _exactOutFlashSwap(\n    address _tokenIn,\n    address _tokenOut,\n    uint24 _fee,\n    uint256 _amountOut,\n    uint256 _amountInMaximum,\n    uint8 _callSource,\n    bytes memory _data\n) internal;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_tokenIn`|`address`|token address to sell|\n|`_tokenOut`|`address`|token address to receive|\n|`_fee`|`uint24`|pool fee|\n|`_amountOut`|`uint256`|exact amount to receive|\n|`_amountInMaximum`|`uint256`|maximum amount to sell|\n|`_callSource`|`uint8`|function call source|\n|`_data`|`bytes`|arbitrary data assigned with the call|\n\n\n### _exactInputInternal\n\ninternal function for exact-in swap on uniswap (specify exact amount to pay)\n\n\n```solidity\nfunction _exactInputInternal(\n    uint256 _amountIn,\n    address _recipient,\n    uint160 _sqrtPriceLimitX96,\n    SwapCallbackData memory data\n) private returns (uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_amountIn`|`uint256`|amount of token to pay|\n|`_recipient`|`address`|recipient for receive|\n|`_sqrtPriceLimitX96`|`uint160`|sqrt price limit|\n|`data`|`SwapCallbackData`||\n\n**Returns**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`<none>`|`uint256`|amount of token bought (amountOut)|\n\n\n### _exactOutputInternal\n\ninternal function for exact-out swap on uniswap (specify exact amount to receive)\n\n\n```solidity\nfunction _exactOutputInternal(\n    uint256 _amountOut,\n    address _recipient,\n    uint160 _sqrtPriceLimitX96,\n    SwapCallbackData memory data\n) private returns (uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_amountOut`|`uint256`|amount of token to receive|\n|`_recipient`|`address`|recipient for receive|\n|`_sqrtPriceLimitX96`|`uint160`|price limit|\n|`data`|`SwapCallbackData`||\n\n**Returns**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`<none>`|`uint256`|amount of token sold (amountIn)|\n\n\n### _getPool\n\nreturns the uniswap pool for the given token pair and fee\n\n*the pool contract may or may not exist*\n\n\n```solidity\nfunction _getPool(address tokenA, address tokenB, uint24 fee) internal view returns (IUniswapV3Pool);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`tokenA`|`address`|address of first token|\n|`tokenB`|`address`|address of second token|\n|`fee`|`uint24`|fee tier for pool|\n\n\n## Structs\n### SwapCallbackData\n\n```solidity\nstruct SwapCallbackData {\n    bytes path;\n    address caller;\n    uint8 callSource;\n    bytes callData;\n}\n```\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/FlashSwap.sol/contract.PoolAddress.md",
    "content": "# PoolAddress\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/FlashSwap.sol)\n\n\n## State Variables\n### POOL_INIT_CODE_HASH\n\n```solidity\nbytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\n```\n\n\n## Functions\n### getPoolKey\n\nReturns PoolKey: the ordered tokens with the matched fee levels\n\n\n```solidity\nfunction getPoolKey(address tokenA, address tokenB, uint24 fee) internal pure returns (PoolKey memory);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`tokenA`|`address`|The first token of a pool, unsorted|\n|`tokenB`|`address`|The second token of a pool, unsorted|\n|`fee`|`uint24`|The fee level of the pool|\n\n**Returns**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`<none>`|`PoolKey`|Poolkey The pool details with ordered token0 and token1 assignments|\n\n\n### computeAddress\n\nDeterministically computes the pool address given the factory and PoolKey\n\n\n```solidity\nfunction computeAddress(address factory, PoolKey memory key) internal pure returns (address pool);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`factory`|`address`|The Uniswap V3 factory contract address|\n|`key`|`PoolKey`|The PoolKey|\n\n**Returns**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`pool`|`address`|The contract address of the V3 pool|\n\n\n## Structs\n### PoolKey\nThe identifying key of the pool\n\n\n```solidity\nstruct PoolKey {\n    address token0;\n    address token1;\n    uint24 fee;\n}\n```\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/NettingLib.sol/contract.NettingLib.md",
    "content": "# NettingLib\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/NettingLib.sol)\n\n\n## Functions\n### transferWethFromMarketMakers\n\ntransfer WETH from market maker to netting contract\n\n*this is executed during the deposit auction, MM buying OSQTH for WETH*\n\n\n```solidity\nfunction transferWethFromMarketMakers(\n    address _weth,\n    address _trader,\n    uint256 _quantity,\n    uint256 _oSqthToMint,\n    uint256 _clearingPrice\n) external returns (bool, uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_weth`|`address`|WETH address|\n|`_trader`|`address`|market maker address|\n|`_quantity`|`uint256`|oSQTH quantity|\n|`_oSqthToMint`|`uint256`|remaining amount of the total oSqthToMint|\n|`_clearingPrice`|`uint256`|auction clearing price|\n\n\n### transferOsqthToMarketMakers\n\ntransfer oSQTH to market maker\n\n*this is executed during the deposit auction, MM buying OSQTH for WETH*\n\n\n```solidity\nfunction transferOsqthToMarketMakers(\n    address _oSqth,\n    address _trader,\n    uint256 _bidId,\n    uint256 _oSqthBalance,\n    uint256 _quantity\n) external returns (bool, uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_oSqth`|`address`|oSQTH address|\n|`_trader`|`address`|market maker address|\n|`_bidId`|`uint256`|MM's bid ID|\n|`_oSqthBalance`|`uint256`|remaining netting contracts's oSQTH balance|\n|`_quantity`|`uint256`|oSQTH quantity in market maker order|\n\n\n### transferOsqthFromMarketMakers\n\ntransfer oSQTH from market maker\n\n*this is executed during the withdraw auction, MM selling OSQTH for WETH*\n\n\n```solidity\nfunction transferOsqthFromMarketMakers(\n    address _oSqth,\n    address _trader,\n    uint256 _remainingOsqthToPull,\n    uint256 _quantity\n) internal returns (uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_oSqth`|`address`|oSQTH address|\n|`_trader`|`address`|market maker address|\n|`_remainingOsqthToPull`|`uint256`|remaining amount of oSQTH from the total oSQTH amount to transfer from order array|\n|`_quantity`|`uint256`|oSQTH quantity in market maker order|\n\n\n### transferWethToMarketMaker\n\ntransfer WETH to market maker\n\n*this is executed during the withdraw auction, MM selling OSQTH for WETH*\n\n\n```solidity\nfunction transferWethToMarketMaker(\n    address _weth,\n    address _trader,\n    uint256 _bidId,\n    uint256 _remainingOsqthToPull,\n    uint256 _quantity,\n    uint256 _clearingPrice\n) external returns (uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_weth`|`address`|WETH address|\n|`_trader`|`address`|market maker address|\n|`_bidId`|`uint256`|market maker bid ID|\n|`_remainingOsqthToPull`|`uint256`|total oSQTH to get from orders array|\n|`_quantity`|`uint256`|market maker's oSQTH order quantity|\n|`_clearingPrice`|`uint256`|auction clearing price|\n\n\n### getCrabPrice\n\nget _crab token price\n\n\n```solidity\nfunction getCrabPrice(\n    address _oracle,\n    address _crab,\n    address _ethUsdcPool,\n    address _ethSqueethPool,\n    address _oSqth,\n    address _usdc,\n    address _weth,\n    address _zenBull,\n    uint32 _auctionTwapPeriod\n) external view returns (uint256, uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_oracle`|`address`|oracle address|\n|`_crab`|`address`|crab token address|\n|`_ethUsdcPool`|`address`|ETH/USDC Uni v3 pool address|\n|`_ethSqueethPool`|`address`|ETH/oSQTH Uni v3 pool address|\n|`_oSqth`|`address`|oSQTH address|\n|`_usdc`|`address`|USDC address|\n|`_weth`|`address`|WETH address|\n|`_zenBull`|`address`|ZenBull strategy address|\n|`_auctionTwapPeriod`|`uint32`|auction TWAP|\n\n\n### getZenBullPrice\n\nget ZenBull token price\n\n\n```solidity\nfunction getZenBullPrice(\n    address _zenBull,\n    address _eulerLens,\n    address _usdc,\n    address _weth,\n    uint256 _crabFairPriceInEth,\n    uint256 _ethUsdcPrice\n) external view returns (uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_zenBull`|`address`|ZenBull token address|\n|`_eulerLens`|`address`|EulerSimpleLens contract address|\n|`_usdc`|`address`|USDC address|\n|`_weth`|`address`|WETH address|\n|`_crabFairPriceInEth`|`uint256`|Crab token price|\n|`_ethUsdcPrice`|`uint256`|ETH/USDC price|\n\n\n### calcOsqthToMintAndEthIntoCrab\n\ncalculate oSQTH to mint and amount of eth to deposit into Crab v2 based on amount of crab token\n\n\n```solidity\nfunction calcOsqthToMintAndEthIntoCrab(address _crab, address _zenBull, uint256 _crabAmount)\n    external\n    view\n    returns (uint256, uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_crab`|`address`|crab strategy address|\n|`_zenBull`|`address`|ZenBull strategy address|\n|`_crabAmount`|`uint256`|amount of crab token|\n\n\n### calcWethToLendAndUsdcToBorrow\n\ncalculate amount of WETH to lend in and USDC to borrow from Euler\n\n\n```solidity\nfunction calcWethToLendAndUsdcToBorrow(\n    address _eulerLens,\n    address _zenBull,\n    address _weth,\n    address _usdc,\n    uint256 _crabAmount\n) external view returns (uint256, uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_eulerLens`|`address`|EulerSimpleLens contract address|\n|`_zenBull`|`address`|ZenBull strategy address|\n|`_weth`|`address`|WETH address|\n|`_usdc`|`address`|USDC address|\n|`_crabAmount`|`uint256`|amount of crab token|\n\n\n### calcOsqthAmount\n\ncalculate amount of oSQTH to get based on amount of ZenBull to Withdraw\n\n\n```solidity\nfunction calcOsqthAmount(address _zenBull, address _crab, uint256 _withdrawsToProcess)\n    external\n    view\n    returns (uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_zenBull`|`address`|ZenBull strategy address|\n|`_crab`|`address`|crab strategy address|\n|`_withdrawsToProcess`|`uint256`|amount of ZenBull token to withdraw|\n\n\n### mul\n\n\n```solidity\nfunction mul(uint256 _x, uint256 _y) internal pure returns (uint256);\n```\n\n### div\n\n\n```solidity\nfunction div(uint256 _x, uint256 _y) internal pure returns (uint256);\n```\n\n## Events\n### TransferWethFromMarketMakers\n\n```solidity\nevent TransferWethFromMarketMakers(\n    address indexed trader, uint256 quantity, uint256 wethAmount, uint256 remainingOsqthBalance, uint256 clearingPrice\n);\n```\n\n### TransferOsqthToMarketMakers\n\n```solidity\nevent TransferOsqthToMarketMakers(\n    address indexed trader, uint256 bidId, uint256 quantity, uint256 remainingOsqthBalance\n);\n```\n\n### TransferOsqthFromMarketMakers\n\n```solidity\nevent TransferOsqthFromMarketMakers(address indexed trader, uint256 quantity, uint256 oSqthRemaining);\n```\n\n### TransferWethToMarketMaker\n\n```solidity\nevent TransferWethToMarketMaker(\n    address indexed trader,\n    uint256 bidId,\n    uint256 quantity,\n    uint256 wethAmount,\n    uint256 oSqthRemaining,\n    uint256 clearingPrice\n);\n```\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/README.md",
    "content": "\n\n# Contents\n- [interface](/src/interface)\n- [PoolAddress](FlashSwap.sol/contract.PoolAddress.md)\n- [CallbackValidation](FlashSwap.sol/contract.CallbackValidation.md)\n- [FlashSwap](FlashSwap.sol/contract.FlashSwap.md)\n- [NettingLib](NettingLib.sol/contract.NettingLib.md)\n- [ZenBullNetting](ZenBullNetting.sol/contract.ZenBullNetting.md)\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/ZenBullNetting.sol/contract.ZenBullNetting.md",
    "content": "# ZenBullNetting\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/ZenBullNetting.sol)\n\n**Inherits:**\nOwnable, EIP712, [FlashSwap](/src/FlashSwap.sol/contract.FlashSwap.md)\n\n**Author:**\nOpyn team\n\nError codes\nZBN01: Auction TWAP is less than min value\nZBN02: OTC price tolerance is greater than max OTC tolerance price\nZBN03: Amount to queue for deposit is less than min amount\nZBN04: Can not dequeue deposited amount because auction is already live and force dequeued not activated\nZBN05: Amount of ETH to deposit left in the queue is less than min amount\nZBN06: Queued deposit is not longer than 1 week to force dequeue\nZBN07: Amount of ZenBull to queue for withdraw is less than min amount\nZBN08: Amount of ZenBull to withdraw left in the queue is less than min amount\nZBN09: Queued withdraw is not longer than 1 week to force dequeue\nZBN10: ETH quantity to net is less than queued for deposits\nZBN11: ZenBull quantity to net is less than queued for withdraws\nZBN12: ZenBull Price too high\nZBN13: ZenBull Price too low\nZBN14: Clearing price too high relative to Uniswap twap\nZBN15: Clearing price too low relative to Uniswap twap\nZBN16: Invalid order signer\nZBN17: Order already expired\nZBN18: Nonce already used\nZBN19: auction order is not selling\nZBN20: sell order price greater than clearing\nZBN21: auction order is not buying\nZBN22: buy order price greater than clearing\nZBN23: not enough buy orders for sqth\nZBN24: not authorized to perform netting at price\n\nContract for Netting Deposits and Withdrawals in ZenBull\n\n*ZenBullNetting contract*\n\n\n## State Variables\n### _ZENBULL_NETTING_TYPEHASH\n*typehash for signed orders*\n\n\n```solidity\nbytes32 private constant _ZENBULL_NETTING_TYPEHASH = keccak256(\n    \"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\"\n);\n```\n\n\n### MAX_OTC_PRICE_TOLERANCE\n*OTC price tolerance cannot exceed 20%*\n\n\n```solidity\nuint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17;\n```\n\n\n### MIN_AUCTION_TWAP\n*min auction TWAP*\n\n\n```solidity\nuint32 public constant MIN_AUCTION_TWAP = 180 seconds;\n```\n\n\n### isAuctionLive\n*owner sets to true when starting auction*\n\n\n```solidity\nbool public isAuctionLive;\n```\n\n\n### minEthAmount\n*min ETH amounts to withdraw or deposit via netting*\n\n\n```solidity\nuint256 public minEthAmount;\n```\n\n\n### minZenBullAmount\n*min ZenBull amounts to withdraw or deposit via netting*\n\n\n```solidity\nuint256 public minZenBullAmount;\n```\n\n\n### depositsIndex\n*array index of last processed deposits*\n\n\n```solidity\nuint256 public depositsIndex;\n```\n\n\n### withdrawsIndex\n*array index of last processed withdraws*\n\n\n```solidity\nuint256 public withdrawsIndex;\n```\n\n\n### otcPriceTolerance\n\n```solidity\nuint256 public otcPriceTolerance;\n```\n\n\n### auctionTwapPeriod\n*twap period to use for auction calculations*\n\n\n```solidity\nuint32 public auctionTwapPeriod;\n```\n\n\n### weth\n*WETH token address*\n\n\n```solidity\naddress private immutable weth;\n```\n\n\n### oSqth\n*oSQTH token address*\n\n\n```solidity\naddress private immutable oSqth;\n```\n\n\n### usdc\n*USDC token address*\n\n\n```solidity\naddress private immutable usdc;\n```\n\n\n### zenBull\n*ZenBull token address*\n\n\n```solidity\naddress private immutable zenBull;\n```\n\n\n### oracle\n*WPowerPerp Oracle address*\n\n\n```solidity\naddress private immutable oracle;\n```\n\n\n### ethSqueethPool\n*ETH/oSQTH uniswap v3 pool address*\n\n\n```solidity\naddress private immutable ethSqueethPool;\n```\n\n\n### ethUsdcPool\n*ETH/USDC uniswap v3 pool address*\n\n\n```solidity\naddress private immutable ethUsdcPool;\n```\n\n\n### eulerLens\n*Euler Simple Lens contract address*\n\n\n```solidity\naddress private immutable eulerLens;\n```\n\n\n### crab\n*crab strategy contract address*\n\n\n```solidity\naddress private immutable crab;\n```\n\n\n### flashZenBull\n*FlashZen contract address*\n\n\n```solidity\naddress private immutable flashZenBull;\n```\n\n\n### bot\n*bot address to automate netAtPrice() calls*\n\n\n```solidity\naddress public bot;\n```\n\n\n### deposits\n*array of ETH deposit receipts*\n\n\n```solidity\nReceipt[] public deposits;\n```\n\n\n### withdraws\n*array of ZenBull withdrawal receipts*\n\n\n```solidity\nReceipt[] public withdraws;\n```\n\n\n### ethBalance\n*ETH amount to deposit for an address*\n\n\n```solidity\nmapping(address => uint256) public ethBalance;\n```\n\n\n### zenBullBalance\n*ZenBull amount to withdraw for an address*\n\n\n```solidity\nmapping(address => uint256) public zenBullBalance;\n```\n\n\n### userDepositsIndex\n*indexes of deposit receipts of an address*\n\n\n```solidity\nmapping(address => uint256[]) public userDepositsIndex;\n```\n\n\n### userWithdrawsIndex\n*indexes of withdraw receipts of an address*\n\n\n```solidity\nmapping(address => uint256[]) public userWithdrawsIndex;\n```\n\n\n### nonces\n*store the used flag for a nonce for each address*\n\n\n```solidity\nmapping(address => mapping(uint256 => bool)) public nonces;\n```\n\n\n## Functions\n### constructor\n\n\n```solidity\nconstructor(address _zenBull, address _eulerSimpleLens, address _flashZenBull, address _uniFactory)\n    EIP712(\"ZenBullNetting\", \"1\")\n    FlashSwap(_uniFactory);\n```\n\n### receive\n\nreceive function to allow ETH transfer to this contract\n\n\n```solidity\nreceive() external payable;\n```\n\n### DOMAIN_SEPARATOR\n\n*view function to get the domain seperator used in signing*\n\n\n```solidity\nfunction DOMAIN_SEPARATOR() external view returns (bytes32);\n```\n\n### toggleAuctionLive\n\n*toggles the value of isAuctionLive*\n\n\n```solidity\nfunction toggleAuctionLive() external onlyOwner;\n```\n\n### setMinEthAmount\n\nset min ETH amount\n\n\n```solidity\nfunction setMinEthAmount(uint256 _amount) external onlyOwner;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_amount`|`uint256`|the amount to be set as minEthAmount|\n\n\n### setMinZenBullAmount\n\nset minZenBullAmount\n\n\n```solidity\nfunction setMinZenBullAmount(uint256 _amount) external onlyOwner;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_amount`|`uint256`|the number to be set as minZenBullAmount|\n\n\n### setDepositsIndex\n\nset the depositIndex so that we want to skip processing some deposits\n\n\n```solidity\nfunction setDepositsIndex(uint256 _newDepositsIndex) external onlyOwner;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_newDepositsIndex`|`uint256`|the new deposits index|\n\n\n### setWithdrawsIndex\n\nset the withdraw index so that we want to skip processing some withdraws\n\n\n```solidity\nfunction setWithdrawsIndex(uint256 _newWithdrawsIndex) external onlyOwner;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_newWithdrawsIndex`|`uint256`|the new withdraw index|\n\n\n### setAuctionTwapPeriod\n\nowner can set the twap period in seconds that is used for obtaining TWAP prices\n\n\n```solidity\nfunction setAuctionTwapPeriod(uint32 _auctionTwapPeriod) external onlyOwner;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_auctionTwapPeriod`|`uint32`|the twap period, in seconds|\n\n\n### setOTCPriceTolerance\n\nowner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\n\n\n```solidity\nfunction setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_otcPriceTolerance`|`uint256`|the OTC price tolerance, in percent, scaled by 1e18|\n\n\n### setBot\n\nset bot address\n\n\n```solidity\nfunction setBot(address _bot) external onlyOwner;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_bot`|`address`|bot address|\n\n\n### cancelNonce\n\n*cancel nonce by marking it as used*\n\n\n```solidity\nfunction cancelNonce(uint256 _nonce) external;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_nonce`|`uint256`|nonce to cancel|\n\n\n### queueEth\n\nqueue ETH for deposit into ZenBull\n\n*payable function*\n\n\n```solidity\nfunction queueEth() external payable;\n```\n\n### dequeueEth\n\nwithdraw ETH from queue\n\n\n```solidity\nfunction dequeueEth(uint256 _amount, bool _force) external;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_amount`|`uint256`|ETH amount to dequeue|\n|`_force`|`bool`|forceWithdraw if deposited more than a week ago|\n\n\n### queueZenBull\n\nqueue ZenBull token for withdraw from strategy\n\n\n```solidity\nfunction queueZenBull(uint256 _amount) external;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_amount`|`uint256`|ZenBull amount to withdraw|\n\n\n### dequeueZenBull\n\nwithdraw ZenBull from queue\n\n\n```solidity\nfunction dequeueZenBull(uint256 _amount, bool _force) external;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_amount`|`uint256`|ZenBull amount to dequeue|\n|`_force`|`bool`|forceWithdraw if queued more than a week ago|\n\n\n### netAtPrice\n\nswaps quantity amount of ETH for ZenBull token at ZenBull/ETH price\n\n\n```solidity\nfunction netAtPrice(uint256 _price, uint256 _quantity) external;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_price`|`uint256`|price of ZenBull in ETH|\n|`_quantity`|`uint256`|amount of ETH to net|\n\n\n### depositAuction\n\nauction for queued deposits\n\n*takes in orders from MM's to buy oSQTH*\n\n\n```solidity\nfunction depositAuction(DepositAuctionParams calldata _params) external onlyOwner;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_params`|`DepositAuctionParams`|deposit Params|\n\n\n### withdrawAuction\n\nauction for queued withdraws\n\n*takes in orders from MM's to sell oSQTH*\n\n\n```solidity\nfunction withdrawAuction(WithdrawAuctionParams calldata _params) external onlyOwner;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_params`|`WithdrawAuctionParams`|withdraw Params|\n\n\n### _uniFlashSwap\n\n*to handle uniswap flashswap callback*\n\n\n```solidity\nfunction _uniFlashSwap(address pool, uint256 amountToPay, bytes memory callData, uint8 callSource) internal override;\n```\n\n### _queueEth\n\n*queue ETH for deposit into ZenBull*\n\n\n```solidity\nfunction _queueEth() internal;\n```\n\n### depositsQueued\n\nget the sum of queued ETH\n\n\n```solidity\nfunction depositsQueued() external view returns (uint256);\n```\n**Returns**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`<none>`|`uint256`|sum ETH amount in queue|\n\n\n### getDepositReceipt\n\nget a deposit receipt by index\n\n\n```solidity\nfunction getDepositReceipt(uint256 _index) external view returns (address, uint256, uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_index`|`uint256`|deposit index in deposits array|\n\n**Returns**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`<none>`|`address`|receipt sender, amount and timestamp|\n|`<none>`|`uint256`||\n|`<none>`|`uint256`||\n\n\n### withdrawsQueued\n\nget the sum of queued ZenBull\n\n\n```solidity\nfunction withdrawsQueued() external view returns (uint256);\n```\n**Returns**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`<none>`|`uint256`|sum ZenBull amount in queue|\n\n\n### getWithdrawReceipt\n\nget a withdraw receipt by index\n\n\n```solidity\nfunction getWithdrawReceipt(uint256 _index) external view returns (address, uint256, uint256);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_index`|`uint256`|withdraw index in withdraws array|\n\n**Returns**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`<none>`|`address`|receipt sender, amount and timestamp|\n|`<none>`|`uint256`||\n|`<none>`|`uint256`||\n\n\n### checkOrder\n\nchecks the expiry nonce and signer of an order\n\n\n```solidity\nfunction checkOrder(Order memory _order) external view returns (bool);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_order`|`Order`|Order struct|\n\n\n### _useNonce\n\n*set nonce flag of the trader to true*\n\n\n```solidity\nfunction _useNonce(address _trader, uint256 _nonce) internal;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_trader`|`address`|address of the signer|\n|`_nonce`|`uint256`|number that is to be traded only once|\n\n\n### _getZenBullPrice\n\n*get ZenBull token price using uniswap TWAP*\n\n\n```solidity\nfunction _getZenBullPrice() internal view returns (uint256);\n```\n**Returns**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`<none>`|`uint256`|ZenBull price|\n\n\n### _checkOTCPrice\n\ncheck that the proposed sale price is within a tolerance of the current Uniswap twap\n\n\n```solidity\nfunction _checkOTCPrice(uint256 _price, bool _isAuctionBuying) internal view;\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_price`|`uint256`|clearing price provided by manager|\n|`_isAuctionBuying`|`bool`|is auction buying or selling oSQTH|\n\n\n### _checkOrder\n\n*checks the expiry nonce and signer of an order*\n\n\n```solidity\nfunction _checkOrder(Order memory _order) internal view returns (bool);\n```\n**Parameters**\n\n|Name|Type|Description|\n|----|----|-----------|\n|`_order`|`Order`|Order struct|\n\n\n## Events\n### SetMinZenBullAmount\n\n```solidity\nevent SetMinZenBullAmount(uint256 oldAmount, uint256 newAmount);\n```\n\n### SetMinEthAmount\n\n```solidity\nevent SetMinEthAmount(uint256 oldAmount, uint256 newAmount);\n```\n\n### SetDepositsIndex\n\n```solidity\nevent SetDepositsIndex(uint256 oldDepositsIndex, uint256 newDepositsIndex);\n```\n\n### SetWithdrawsIndex\n\n```solidity\nevent SetWithdrawsIndex(uint256 oldWithdrawsIndex, uint256 newWithdrawsIndex);\n```\n\n### SetAuctionTwapPeriod\n\n```solidity\nevent SetAuctionTwapPeriod(uint32 previousTwap, uint32 newTwap);\n```\n\n### SetOTCPriceTolerance\n\n```solidity\nevent SetOTCPriceTolerance(uint256 previousTolerance, uint256 newOtcPriceTolerance);\n```\n\n### ToggledAuctionLive\n\n```solidity\nevent ToggledAuctionLive(bool isAuctionLive);\n```\n\n### QueueEth\n\n```solidity\nevent QueueEth(address indexed depositor, uint256 amount, uint256 depositorsBalance, uint256 indexed receiptIndex);\n```\n\n### DequeueEth\n\n```solidity\nevent DequeueEth(address indexed depositor, uint256 amount, uint256 depositorsBalance);\n```\n\n### QueueZenBull\n\n```solidity\nevent QueueZenBull(\n    address indexed withdrawer, uint256 amount, uint256 withdrawersBalance, uint256 indexed receiptIndex\n);\n```\n\n### DequeueZenBull\n\n```solidity\nevent DequeueZenBull(address indexed withdrawer, uint256 amount, uint256 withdrawersBalance);\n```\n\n### NetAtPrice\n\n```solidity\nevent NetAtPrice(\n    bool indexed isDeposit,\n    address indexed receiver,\n    uint256 amountQueuedProcessed,\n    uint256 amountReceived,\n    uint256 indexed index\n);\n```\n\n### EthDeposited\n\n```solidity\nevent EthDeposited(\n    address indexed depositor,\n    uint256 ethAmount,\n    uint256 zenBullAmount,\n    uint256 indexed receiptIndex,\n    uint256 refundedETH\n);\n```\n\n### ZenBullWithdrawn\n\n```solidity\nevent ZenBullWithdrawn(\n    address indexed withdrawer, uint256 zenBullAmount, uint256 ethAmount, uint256 indexed receiptIndex\n);\n```\n\n### SetBot\n\n```solidity\nevent SetBot(address bot);\n```\n\n### DepositAuction\n\n```solidity\nevent DepositAuction(\n    uint256 wethDeposited, uint256 crabAmount, uint256 clearingPrice, uint256 oSqthAmount, uint256 depositsIndex\n);\n```\n\n### WithdrawAuction\n\n```solidity\nevent WithdrawAuction(uint256 zenBullWithdrawn, uint256 clearingPrice, uint256 oSqthAmount, uint256 withdrawsIndex);\n```\n\n### CancelNonce\n\n```solidity\nevent CancelNonce(address trader, uint256 nonce);\n```\n\n### TransferWethFromMarketMakers\n*shared events with the NettingLib for client side to detect them*\n\n\n```solidity\nevent TransferWethFromMarketMakers(address indexed trader, uint256 quantity, uint256 wethAmount, uint256 clearingPrice);\n```\n\n### TransferOsqthToMarketMakers\n\n```solidity\nevent TransferOsqthToMarketMakers(\n    address indexed trader, uint256 bidId, uint256 quantity, uint256 remainingOsqthBalance\n);\n```\n\n### TransferOsqthFromMarketMakers\n\n```solidity\nevent TransferOsqthFromMarketMakers(address indexed trader, uint256 quantity, uint256 oSqthRemaining);\n```\n\n### TransferWethToMarketMaker\n\n```solidity\nevent TransferWethToMarketMaker(\n    address indexed trader,\n    uint256 bidId,\n    uint256 quantity,\n    uint256 wethAmount,\n    uint256 oSqthRemaining,\n    uint256 clearingPrice\n);\n```\n\n## Structs\n### Order\n*order struct for a signed order from market maker*\n\n\n```solidity\nstruct Order {\n    uint256 bidId;\n    address trader;\n    uint256 quantity;\n    uint256 price;\n    bool isBuying;\n    uint256 expiry;\n    uint256 nonce;\n    uint8 v;\n    bytes32 r;\n    bytes32 s;\n}\n```\n\n### Receipt\n*receipt used to store deposits and withdraws*\n\n\n```solidity\nstruct Receipt {\n    address sender;\n    uint256 amount;\n    uint256 timestamp;\n}\n```\n\n### DepositAuctionParams\n\n```solidity\nstruct DepositAuctionParams {\n    uint256 depositsToProcess;\n    uint256 crabAmount;\n    Order[] orders;\n    uint256 clearingPrice;\n    uint256 flashDepositEthToCrab;\n    uint256 flashDepositMinEthFromSqth;\n    uint256 flashDepositMinEthFromUsdc;\n    uint24 flashDepositWPowerPerpPoolFee;\n    uint24 wethUsdcPoolFee;\n}\n```\n\n### WithdrawAuctionParams\n*params for withdraw auction*\n\n\n```solidity\nstruct WithdrawAuctionParams {\n    uint256 withdrawsToProcess;\n    Order[] orders;\n    uint256 clearingPrice;\n    uint256 maxWethForUsdc;\n    uint24 wethUsdcPoolFee;\n}\n```\n\n### MemoryVar\n*struct to store proportional amounts of erc20s (received or to send)*\n\n\n```solidity\nstruct MemoryVar {\n    uint256 currentZenBullBalance;\n    uint256 remainingEth;\n    uint256 remainingDeposits;\n    uint256 oSqthBalance;\n}\n```\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/interface/IController.sol/contract.IController.md",
    "content": "# IController\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/interface/IController.sol)\n\n\n## Functions\n### weth\n\n\n```solidity\nfunction weth() external view returns (address);\n```\n\n### quoteCurrency\n\n\n```solidity\nfunction quoteCurrency() external view returns (address);\n```\n\n### ethQuoteCurrencyPool\n\n\n```solidity\nfunction ethQuoteCurrencyPool() external view returns (address);\n```\n\n### wPowerPerp\n\n\n```solidity\nfunction wPowerPerp() external view returns (address);\n```\n\n### wPowerPerpPool\n\n\n```solidity\nfunction wPowerPerpPool() external view returns (address);\n```\n\n### oracle\n\n\n```solidity\nfunction oracle() external view returns (address);\n```\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/interface/ICrabStrategyV2.sol/contract.ICrabStrategyV2.md",
    "content": "# ICrabStrategyV2\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/interface/ICrabStrategyV2.sol)\n\n**Inherits:**\nIERC20\n\n\n## Functions\n### getVaultDetails\n\n\n```solidity\nfunction getVaultDetails() external view returns (address, uint256, uint256, uint256);\n```\n\n### deposit\n\n\n```solidity\nfunction deposit() external payable;\n```\n\n### withdraw\n\n\n```solidity\nfunction withdraw(uint256 _crabAmount) external;\n```\n\n### flashDeposit\n\n\n```solidity\nfunction flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\n```\n\n### getWsqueethFromCrabAmount\n\n\n```solidity\nfunction getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256);\n```\n\n### powerTokenController\n\n\n```solidity\nfunction powerTokenController() external view returns (address);\n```\n\n### weth\n\n\n```solidity\nfunction weth() external view returns (address);\n```\n\n### wPowerPerp\n\n\n```solidity\nfunction wPowerPerp() external view returns (address);\n```\n\n### oracle\n\n\n```solidity\nfunction oracle() external view returns (address);\n```\n\n### ethWSqueethPool\n\n\n```solidity\nfunction ethWSqueethPool() external view returns (address);\n```\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/interface/IEulerSimpleLens.sol/contract.IEulerSimpleLens.md",
    "content": "# IEulerSimpleLens\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/interface/IEulerSimpleLens.sol)\n\n\n## Functions\n### getDTokenBalance\n\n\n```solidity\nfunction getDTokenBalance(address underlying, address account) external view returns (uint256);\n```\n\n### getETokenBalance\n\n\n```solidity\nfunction getETokenBalance(address underlying, address account) external view returns (uint256);\n```\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/interface/IFlashZen.sol/contract.IFlashZen.md",
    "content": "# IFlashZen\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/interface/IFlashZen.sol)\n\n\n## Functions\n### flashDeposit\n\n\n```solidity\nfunction flashDeposit(FlashDepositParams calldata _params) external payable;\n```\n\n## Structs\n### FlashDepositParams\n\n```solidity\nstruct FlashDepositParams {\n    uint256 ethToCrab;\n    uint256 minEthFromSqth;\n    uint256 minEthFromUsdc;\n    uint24 wPowerPerpPoolFee;\n    uint24 usdcPoolFee;\n}\n```\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/interface/IOracle.sol/contract.IOracle.md",
    "content": "# IOracle\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/interface/IOracle.sol)\n\n\n## Functions\n### getTwap\n\n\n```solidity\nfunction getTwap(address _pool, address _base, address _quote, uint32 _period, bool _checkPeriod)\n    external\n    view\n    returns (uint256);\n```\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/interface/IWETH.sol/contract.IWETH.md",
    "content": "# IWETH\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/interface/IWETH.sol)\n\n**Inherits:**\nIERC20\n\n\n## Functions\n### deposit\n\n\n```solidity\nfunction deposit() external payable;\n```\n\n### withdraw\n\n\n```solidity\nfunction withdraw(uint256 wad) external;\n```\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/interface/IZenBullStrategy.sol/contract.IZenBullStrategy.md",
    "content": "# IZenBullStrategy\n[Git Source](https://github.com/opynfinance/squeeth-monorepo/blob/334783aa87db73939fb00d5b133216b0033dfece/src/interface/IZenBullStrategy.sol)\n\n**Inherits:**\nIERC20\n\n\n## Functions\n### powerTokenController\n\n\n```solidity\nfunction powerTokenController() external view returns (address);\n```\n\n### getCrabBalance\n\n\n```solidity\nfunction getCrabBalance() external view returns (uint256);\n```\n\n### getCrabVaultDetails\n\n\n```solidity\nfunction getCrabVaultDetails() external view returns (uint256, uint256);\n```\n\n### crab\n\n\n```solidity\nfunction crab() external view returns (address);\n```\n\n### withdraw\n\n\n```solidity\nfunction withdraw(uint256 _bullAmount) external;\n```\n\n### deposit\n\n\n```solidity\nfunction deposit(uint256 _crabAmount) external payable;\n```\n\n"
  },
  {
    "path": "packages/zen-bull-netting/docs/src/src/interface/README.md",
    "content": "\n\n# Contents\n- [IController](IController.sol/contract.IController.md)\n- [ICrabStrategyV2](ICrabStrategyV2.sol/contract.ICrabStrategyV2.md)\n- [IEulerSimpleLens](IEulerSimpleLens.sol/contract.IEulerSimpleLens.md)\n- [IFlashZen](IFlashZen.sol/contract.IFlashZen.md)\n- [IOracle](IOracle.sol/contract.IOracle.md)\n- [IWETH](IWETH.sol/contract.IWETH.md)\n- [IZenBullStrategy](IZenBullStrategy.sol/contract.IZenBullStrategy.md)\n"
  },
  {
    "path": "packages/zen-bull-netting/foundry.toml",
    "content": "[profile.default]\nsrc = 'src'\nout = 'out'\nlibs = ['lib']\ntest = 'test'\nauto_detect_solc = true\noptimizer = true\noptimizer_runs = 10\n\n[profile.test]\nno_match_test = \"Fuzzing\"\nno_match_contract = \"Fuzzing\"\ngas_reports = [\"ZenBullNetting\"]\n\n[profile.fuzz]\nruns = 2500\nmax_local_rejects = 1024\nmax_global_rejects = 65536\nseed = '0x3e8'\ndictionary_weight = 40\ninclude_storage = true\ninclude_push_bytes = true\nmatch_test = \"Fuzzing\"\nmatch_contract = \"Fuzzing\"\n\n[profile.invariant]\nruns = 256\ndepth = 15\nfail_on_revert = false\ncall_override = false\ndictionary_weight = 80\ninclude_storage = true\ninclude_push_bytes = true\n\n[profile.fmt]\nline_length = 100\ntab_width = 4\nbracket_spacing = true\n\n[profile.coverage]\nvia_ir = true\nno_match_test = \"Fuzzing\"\nno_match_contract = \"Script\"\n\n[profile.coverage.optimizer_details]\nconstantOptimizer = true\nyul = true\n\n[profile.coverage.optimizer_details.yulDetails]\nstackAllocation = true\noptimizerSteps = ''\n\n[rpc_endpoints]\nmainnet = \"${MAINNET_RPC_URL}\"\ngoerli = \"${GOERLI_RPC_URL}\"\n\n[etherscan]\ngoerli = { key = \"${ETHERSCAN_API_KEY}\" }\n\n# See more config options https://github.com/foundry-rs/foundry/tree/master/config"
  },
  {
    "path": "packages/zen-bull-netting/remappings.txt",
    "content": "ds-test/=lib/forge-std/lib/ds-test/src/\nforge-std/=lib/forge-std/src/\nv3-core/=lib/v3-core/contracts/\nv3-periphery/=lib/v3-periphery/contracts/\nopenzeppelin/=lib/openzeppelin-contracts/contracts\n@uniswap/v3-core=lib/v3-core/"
  },
  {
    "path": "packages/zen-bull-netting/script/DeployScript.s.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport \"forge-std/Script.sol\";\nimport { ZenBullNetting } from \"../src/ZenBullNetting.sol\";\n\ncontract DeployScript is Script {\n    /// @dev owner address for BullStrategy, EmergencyShutdown and AuctionBull\n    address private ownerAddress;\n    address private zenBullAddress;\n    address private eulerSimpleLensAddress;\n    address private flashZenAddress;\n    address private uniFactoryAddress;\n\n    uint256 private initialMinEthAmount;\n    uint256 private initialMinZenBullAmount;\n\n    // Deploy contracts\n    ZenBullNetting zenBullNetting;\n\n    constructor(\n        address _ownerAddress,\n        address _zenBullAddress,\n        address _eulerSimpleLensAddress,\n        address _flashZenAddress,\n        address _uniFactoryAddress,\n        uint256 _initialMinEthAmount,\n        uint256 _initialMinZenBullAmount\n    ) {\n        require(_ownerAddress != address(0), \"Invalid owner address\");\n        require(_zenBullAddress != address(0), \"Invalid ZenBull address\");\n        require(_eulerSimpleLensAddress != address(0), \"Invalid EulerSimpleLens address\");\n        require(_flashZenAddress != address(0), \"Invalid FlashZen address\");\n        require(_uniFactoryAddress != address(0), \"Invalid Uni V3 Factory address\");\n        require(_initialMinEthAmount > 0, \"Invalid min ETH amount\");\n        require(_initialMinZenBullAmount > 0, \"Invalid min ZenBull amount\");\n\n        ownerAddress = _ownerAddress;\n        zenBullAddress = _zenBullAddress;\n        eulerSimpleLensAddress = _eulerSimpleLensAddress;\n        flashZenAddress = _flashZenAddress;\n        uniFactoryAddress = _uniFactoryAddress;\n        initialMinEthAmount = _initialMinEthAmount;\n        initialMinZenBullAmount = _initialMinZenBullAmount;\n    }\n\n    function run() public {\n        uint256 deployerKey = vm.envUint(\"DEPLOYER_PK\");\n\n        address deployerAddress = vm.rememberKey(deployerKey);\n\n        vm.startBroadcast(deployerAddress);\n\n        // deploy contracts\n        zenBullNetting =\n        new ZenBullNetting(zenBullAddress, eulerSimpleLensAddress, flashZenAddress, uniFactoryAddress);\n\n        // set initial params\n        zenBullNetting.setMinEthAmount(initialMinEthAmount);\n        zenBullNetting.setMinZenBullAmount(initialMinZenBullAmount);\n\n        // transfer ownership\n        zenBullNetting.transferOwnership(ownerAddress);\n\n        vm.stopBroadcast();\n\n        require(zenBullNetting.owner() == ownerAddress);\n        require(zenBullNetting.MAX_OTC_PRICE_TOLERANCE() == 2e17);\n        require(zenBullNetting.MIN_AUCTION_TWAP() == 180);\n        require(zenBullNetting.otcPriceTolerance() == 5e16);\n        require(zenBullNetting.auctionTwapPeriod() == 420);\n        require(\n            zenBullNetting.DOMAIN_SEPARATOR()\n                == keccak256(\n                    abi.encode(\n                        keccak256(\n                            \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n                        ),\n                        keccak256(bytes(\"ZenBullNetting\")),\n                        keccak256(bytes(\"1\")),\n                        block.chainid,\n                        address(zenBullNetting)\n                    )\n                )\n        );\n    }\n\n    function testAvoidCoverage() public pure {\n        return;\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/script/GoerliDeployScript.s.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport { DeployScript } from \"./DeployScript.s.sol\";\n\ncontract GoerliDeployScript is DeployScript {\n    address public constant ownerAddress = 0xE3Dc747E5A8D8B664Dd701EE6A72AE63e740Ebc6;\n    address public constant zenBullAddress = 0x2a5AD7582a9e42944Ee32671436593D16999c70a;\n    address public constant eulerSimpleLensAddress = 0x62626a0f051B547b3182e55D1Eba667138790D8D;\n    address public constant flashZenAddress = 0x3876aF971560FD4c4ba3FB18632AcC0570B745b1;\n    address public constant uniFactoryAddress = 0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa;\n\n    uint256 public constant initialMinEthAmount = 1e18;\n    uint256 public constant initialMinZenBullAmount = 1;\n\n    constructor()\n        DeployScript(\n            ownerAddress,\n            zenBullAddress,\n            eulerSimpleLensAddress,\n            flashZenAddress,\n            uniFactoryAddress,\n            initialMinEthAmount,\n            initialMinZenBullAmount\n        )\n    { }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/script/MainnetDeployScript.s.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport { DeployScript } from \"./DeployScript.s.sol\";\n\ncontract MainnetDeployScript is DeployScript {\n    address public constant ownerAddress = 0xAfE66363c27EedB597a140c28B70b32F113fd5a8;\n    address public constant zenBullAddress = 0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507;\n    address public constant eulerSimpleLensAddress = 0xAF68CFba29D0e15490236A5631cA9497e035CD39;\n    address public constant flashZenAddress = 0x11A56a3A7A6Eb768A9125798B1eABE9EBD9EcE02;\n    address public constant uniFactoryAddress = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\n\n    uint256 public constant initialMinEthAmount = 1e18;\n    uint256 public constant initialMinZenBullAmount = 1;\n\n    constructor()\n        DeployScript(\n            ownerAddress,\n            zenBullAddress,\n            eulerSimpleLensAddress,\n            flashZenAddress,\n            uniFactoryAddress,\n            initialMinEthAmount,\n            initialMinZenBullAmount\n        )\n    { }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/src/FlashSwap.sol",
    "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n// pragma abicoder v2;\n\n// interface\nimport \"v3-core/interfaces/callback/IUniswapV3SwapCallback.sol\";\nimport \"v3-core/interfaces/IUniswapV3Pool.sol\";\n// lib\nimport \"v3-periphery/libraries/Path.sol\";\nimport \"v3-core/libraries/TickMath.sol\";\nimport \"v3-core/libraries/SafeCast.sol\";\n\nlibrary PoolAddress {\n    bytes32 internal constant POOL_INIT_CODE_HASH =\n        0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\n\n    /// @notice The identifying key of the pool\n    struct PoolKey {\n        address token0;\n        address token1;\n        uint24 fee;\n    }\n\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\n    /// @param tokenA The first token of a pool, unsorted\n    /// @param tokenB The second token of a pool, unsorted\n    /// @param fee The fee level of the pool\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\n    function getPoolKey(address tokenA, address tokenB, uint24 fee)\n        internal\n        pure\n        returns (PoolKey memory)\n    {\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\n        return PoolKey({ token0: tokenA, token1: tokenB, fee: fee });\n    }\n\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\n    /// @param factory The Uniswap V3 factory contract address\n    /// @param key The PoolKey\n    /// @return pool The contract address of the V3 pool\n    function computeAddress(address factory, PoolKey memory key)\n        internal\n        pure\n        returns (address pool)\n    {\n        require(key.token0 < key.token1);\n        pool = address(\n            uint160(\n                uint256(\n                    keccak256(\n                        abi.encodePacked(\n                            hex\"ff\",\n                            factory,\n                            keccak256(abi.encode(key.token0, key.token1, key.fee)),\n                            POOL_INIT_CODE_HASH\n                        )\n                    )\n                )\n            )\n        );\n    }\n}\n\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\nlibrary CallbackValidation {\n    /// @notice Returns the address of a valid Uniswap V3 Pool\n    /// @param factory The contract address of the Uniswap V3 factory\n    /// @param tokenA The contract address of either token0 or token1\n    /// @param tokenB The contract address of the other token\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n    /// @return pool The V3 pool contract address\n    function verifyCallback(address factory, address tokenA, address tokenB, uint24 fee)\n        internal\n        view\n        returns (IUniswapV3Pool pool)\n    {\n        pool = IUniswapV3Pool(\n            PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee))\n        );\n        require(msg.sender == address(pool));\n    }\n}\n\n/**\n * @notice FlashSwap contract\n * @dev contract that interacts with Uniswap pool\n * @author opyn team\n */\nabstract contract FlashSwap is IUniswapV3SwapCallback {\n    using Path for bytes;\n    using SafeCast for uint256;\n\n    /// @dev Uniswap factory address\n    address internal immutable factory;\n\n    struct SwapCallbackData {\n        bytes path;\n        address caller;\n        uint8 callSource;\n        bytes callData;\n    }\n\n    /**\n     * @dev constructor\n     * @param _factory uniswap factory address\n     */\n    constructor(address _factory) {\n        require(_factory != address(0), \"Invalid factory address\");\n\n        factory = _factory;\n    }\n\n    /**\n     * @notice uniswap swap callback function for flashes\n     * @param amount0Delta amount of token0\n     * @param amount1Delta amount of token1\n     * @param _data callback data encoded as SwapCallbackData struct\n     */\n    function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data)\n        external\n        override\n    {\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\n\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\n\n        //ensure that callback comes from uniswap pool\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\n\n        //determine the amount that needs to be repaid as part of the flashswap\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\n\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\n        _uniFlashSwap(pool, amountToPay, data.callData, data.callSource);\n    }\n\n    // /**\n    //  * @notice function to be called by uniswap callback.\n    //  * @dev this function should be overridden by the child contract\n    //  * @param _uniFlashSwapData UniFlashswapCallbackData struct\n    //  */\n    function _uniFlashSwap(\n        address pool,\n        uint256 amountToPay,\n        bytes memory callData,\n        uint8 callSource\n    ) internal virtual { }\n\n    /**\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\n     * @param _tokenIn token address to sell\n     * @param _tokenOut token address to receive\n     * @param _fee pool fee\n     * @param _amountIn amount to sell\n     * @param _amountOutMinimum minimum amount to receive\n     * @param _callSource function call source\n     * @param _data arbitrary data assigned with the call\n     */\n    function _exactInFlashSwap(\n        address _tokenIn,\n        address _tokenOut,\n        uint24 _fee,\n        uint256 _amountIn,\n        uint256 _amountOutMinimum,\n        uint8 _callSource,\n        bytes memory _data\n    ) internal returns (uint256) {\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\n        uint256 amountOut = _exactInputInternal(\n            _amountIn,\n            address(this),\n            uint160(0),\n            SwapCallbackData({\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\n                caller: msg.sender,\n                callSource: _callSource,\n                callData: _data\n            })\n        );\n\n        //slippage limit check\n        require(amountOut >= _amountOutMinimum, \"amount out less than min\");\n\n        return amountOut;\n    }\n\n    /**\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\n     * @param _tokenIn token address to sell\n     * @param _tokenOut token address to receive\n     * @param _fee pool fee\n     * @param _amountOut exact amount to receive\n     * @param _amountInMaximum maximum amount to sell\n     * @param _callSource function call source\n     * @param _data arbitrary data assigned with the call\n     */\n    function _exactOutFlashSwap(\n        address _tokenIn,\n        address _tokenOut,\n        uint24 _fee,\n        uint256 _amountOut,\n        uint256 _amountInMaximum,\n        uint8 _callSource,\n        bytes memory _data\n    ) internal {\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\n        uint256 amountIn = _exactOutputInternal(\n            _amountOut,\n            address(this),\n            uint160(0),\n            SwapCallbackData({\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\n                caller: msg.sender,\n                callSource: _callSource,\n                callData: _data\n            })\n        );\n\n        //slippage limit check\n        require(amountIn <= _amountInMaximum, \"amount in greater than max\");\n    }\n\n    /**\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\n     * @param _amountIn amount of token to pay\n     * @param _recipient recipient for receive\n     * @param _sqrtPriceLimitX96 sqrt price limit\n     * @return amount of token bought (amountOut)\n     */\n    function _exactInputInternal(\n        uint256 _amountIn,\n        address _recipient,\n        uint160 _sqrtPriceLimitX96,\n        SwapCallbackData memory data\n    ) private returns (uint256) {\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\n\n        //uniswap token0 has a lower address than token1\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\n        //zeroForOne determines which token is being sold and which is being bought\n        bool zeroForOne = tokenIn < tokenOut;\n\n        //swap on uniswap, including data to trigger call back for flashswap\n        (int256 amount0, int256 amount1) = _getPool(tokenIn, tokenOut, fee).swap(\n            _recipient,\n            zeroForOne,\n            _amountIn.toInt256(),\n            _sqrtPriceLimitX96 == 0\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\n                : _sqrtPriceLimitX96,\n            abi.encode(data)\n        );\n\n        //determine the amountOut based on which token has a lower address\n        return uint256(-(zeroForOne ? amount1 : amount0));\n    }\n\n    /**\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\n     * @param _amountOut amount of token to receive\n     * @param _recipient recipient for receive\n     * @param _sqrtPriceLimitX96 price limit\n     * @return amount of token sold (amountIn)\n     */\n    function _exactOutputInternal(\n        uint256 _amountOut,\n        address _recipient,\n        uint160 _sqrtPriceLimitX96,\n        SwapCallbackData memory data\n    ) private returns (uint256) {\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\n\n        //uniswap token0 has a lower address than token1\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\n        //zeroForOne determines which token is being sold and which is being bought\n        bool zeroForOne = tokenIn < tokenOut;\n\n        //swap on uniswap, including data to trigger call back for flashswap\n        (int256 amount0Delta, int256 amount1Delta) = _getPool(tokenIn, tokenOut, fee).swap(\n            _recipient,\n            zeroForOne,\n            -_amountOut.toInt256(),\n            _sqrtPriceLimitX96 == 0\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\n                : _sqrtPriceLimitX96,\n            abi.encode(data)\n        );\n\n        //determine the amountIn and amountOut based on which token has a lower address\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\n            : (uint256(amount1Delta), uint256(-amount0Delta));\n        // it's technically possible to not receive the full output amount,\n        // so if no price limit has been specified, require this possibility away\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\n\n        return amountIn;\n    }\n\n    /**\n     * @notice returns the uniswap pool for the given token pair and fee\n     * @dev the pool contract may or may not exist\n     * @param tokenA address of first token\n     * @param tokenB address of second token\n     * @param fee fee tier for pool\n     */\n    function _getPool(address tokenA, address tokenB, uint24 fee)\n        internal\n        view\n        returns (IUniswapV3Pool)\n    {\n        return IUniswapV3Pool(\n            PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee))\n        );\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/src/NettingLib.sol",
    "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n// interface\nimport { IERC20 } from \"openzeppelin/interfaces/IERC20.sol\";\nimport { IZenBullStrategy } from \"./interface/IZenBullStrategy.sol\";\nimport { IOracle } from \"./interface/IOracle.sol\";\nimport { IEulerSimpleLens } from \"./interface/IEulerSimpleLens.sol\";\n\nlibrary NettingLib {\n    event TransferWethFromMarketMakers(\n        address indexed trader,\n        uint256 quantity,\n        uint256 wethAmount,\n        uint256 remainingOsqthBalance,\n        uint256 clearingPrice\n    );\n    event TransferOsqthToMarketMakers(\n        address indexed trader, uint256 bidId, uint256 quantity, uint256 remainingOsqthBalance\n    );\n    event TransferOsqthFromMarketMakers(\n        address indexed trader, uint256 quantity, uint256 oSqthRemaining\n    );\n    event TransferWethToMarketMaker(\n        address indexed trader,\n        uint256 bidId,\n        uint256 quantity,\n        uint256 wethAmount,\n        uint256 oSqthRemaining,\n        uint256 clearingPrice\n    );\n\n    /**\n     * @notice transfer WETH from market maker to netting contract\n     * @dev this is executed during the deposit auction, MM buying OSQTH for WETH\n     * @param _weth WETH address\n     * @param _trader market maker address\n     * @param _quantity oSQTH quantity\n     * @param _oSqthToMint remaining amount of the total oSqthToMint\n     * @param _clearingPrice auction clearing price\n     */\n    function transferWethFromMarketMakers(\n        address _weth,\n        address _trader,\n        uint256 _quantity,\n        uint256 _oSqthToMint,\n        uint256 _clearingPrice\n    ) external returns (bool, uint256) {\n        uint256 wethAmount;\n        uint256 remainingOsqthToMint;\n        if (_quantity >= _oSqthToMint) {\n            wethAmount = (_oSqthToMint * _clearingPrice) / 1e18;\n            IERC20(_weth).transferFrom(_trader, address(this), wethAmount);\n\n            emit TransferWethFromMarketMakers(\n                _trader, _oSqthToMint, wethAmount, remainingOsqthToMint, _clearingPrice\n            );\n            return (true, remainingOsqthToMint);\n        } else {\n            wethAmount = (_quantity * _clearingPrice) / 1e18;\n            remainingOsqthToMint = _oSqthToMint - _quantity;\n            IERC20(_weth).transferFrom(_trader, address(this), wethAmount);\n\n            emit TransferWethFromMarketMakers(\n                _trader, _quantity, wethAmount, remainingOsqthToMint, _clearingPrice\n            );\n            return (false, remainingOsqthToMint);\n        }\n    }\n\n    /**\n     * @notice transfer oSQTH to market maker\n     * @dev this is executed during the deposit auction, MM buying OSQTH for WETH\n     * @param _oSqth oSQTH address\n     * @param _trader market maker address\n     * @param _bidId MM's bid ID\n     * @param _oSqthBalance remaining netting contracts's oSQTH balance\n     * @param _quantity oSQTH quantity in market maker order\n     */\n    function transferOsqthToMarketMakers(\n        address _oSqth,\n        address _trader,\n        uint256 _bidId,\n        uint256 _oSqthBalance,\n        uint256 _quantity\n    ) external returns (bool, uint256) {\n        uint256 remainingOsqthBalance;\n        if (_quantity < _oSqthBalance) {\n            IERC20(_oSqth).transfer(_trader, _quantity);\n\n            remainingOsqthBalance = _oSqthBalance - _quantity;\n\n            emit TransferOsqthToMarketMakers(_trader, _bidId, _quantity, remainingOsqthBalance);\n\n            return (false, remainingOsqthBalance);\n        } else {\n            IERC20(_oSqth).transfer(_trader, _oSqthBalance);\n\n            emit TransferOsqthToMarketMakers(_trader, _bidId, _oSqthBalance, remainingOsqthBalance);\n\n            return (true, remainingOsqthBalance);\n        }\n    }\n\n    /**\n     * @notice transfer oSQTH from market maker\n     * @dev this is executed during the withdraw auction, MM selling OSQTH for WETH\n     * @param _oSqth oSQTH address\n     * @param _trader market maker address\n     * @param _remainingOsqthToPull remaining amount of oSQTH from the total oSQTH amount to transfer from order array\n     * @param _quantity oSQTH quantity in market maker order\n     */\n    function transferOsqthFromMarketMakers(\n        address _oSqth,\n        address _trader,\n        uint256 _remainingOsqthToPull,\n        uint256 _quantity\n    ) internal returns (uint256) {\n        uint256 oSqthRemaining;\n        if (_quantity < _remainingOsqthToPull) {\n            IERC20(_oSqth).transferFrom(_trader, address(this), _quantity);\n\n            oSqthRemaining = _remainingOsqthToPull - _quantity;\n\n            emit TransferOsqthFromMarketMakers(_trader, _quantity, oSqthRemaining);\n        } else {\n            IERC20(_oSqth).transferFrom(_trader, address(this), _remainingOsqthToPull);\n\n            emit TransferOsqthFromMarketMakers(_trader, _remainingOsqthToPull, oSqthRemaining);\n        }\n\n        return oSqthRemaining;\n    }\n\n    /**\n     * @notice transfer WETH to market maker\n     * @dev this is executed during the withdraw auction, MM selling OSQTH for WETH\n     * @param _weth WETH address\n     * @param _trader market maker address\n     * @param _bidId market maker bid ID\n     * @param _remainingOsqthToPull total oSQTH to get from orders array\n     * @param _quantity market maker's oSQTH order quantity\n     * @param _clearingPrice auction clearing price\n     */\n    function transferWethToMarketMaker(\n        address _weth,\n        address _trader,\n        uint256 _bidId,\n        uint256 _remainingOsqthToPull,\n        uint256 _quantity,\n        uint256 _clearingPrice\n    ) external returns (uint256) {\n        uint256 oSqthQuantity;\n\n        if (_quantity < _remainingOsqthToPull) {\n            oSqthQuantity = _quantity;\n        } else {\n            oSqthQuantity = _remainingOsqthToPull;\n        }\n\n        uint256 wethAmount = (oSqthQuantity * _clearingPrice) / 1e18;\n        _remainingOsqthToPull -= oSqthQuantity;\n        IERC20(_weth).transfer(_trader, wethAmount);\n\n        emit TransferWethToMarketMaker(\n            _trader, _bidId, _quantity, wethAmount, _remainingOsqthToPull, _clearingPrice\n        );\n\n        return _remainingOsqthToPull;\n    }\n\n    /**\n     * @notice get _crab token price\n     * @param _oracle oracle address\n     * @param _crab crab token address\n     * @param _ethUsdcPool ETH/USDC Uni v3 pool address\n     * @param _ethSqueethPool ETH/oSQTH Uni v3 pool address\n     * @param _oSqth oSQTH address\n     * @param _usdc USDC address\n     * @param _weth WETH address\n     * @param _zenBull ZenBull strategy address\n     * @param _auctionTwapPeriod auction TWAP\n     */\n    function getCrabPrice(\n        address _oracle,\n        address _crab,\n        address _ethUsdcPool,\n        address _ethSqueethPool,\n        address _oSqth,\n        address _usdc,\n        address _weth,\n        address _zenBull,\n        uint32 _auctionTwapPeriod\n    ) external view returns (uint256, uint256) {\n        uint256 squeethEthPrice =\n            IOracle(_oracle).getTwap(_ethSqueethPool, _oSqth, _weth, _auctionTwapPeriod, false);\n        uint256 _ethUsdcPrice =\n            IOracle(_oracle).getTwap(_ethUsdcPool, _weth, _usdc, _auctionTwapPeriod, false);\n        (uint256 crabCollateral, uint256 crabDebt) =\n            IZenBullStrategy(_zenBull).getCrabVaultDetails();\n        uint256 _crabFairPriceInEth = (crabCollateral - (crabDebt * squeethEthPrice / 1e18)) * 1e18\n            / IERC20(_crab).totalSupply();\n\n        return (_crabFairPriceInEth, _ethUsdcPrice);\n    }\n\n    /**\n     * @notice get ZenBull token price\n     * @param _zenBull ZenBull token address\n     * @param _eulerLens EulerSimpleLens contract address\n     * @param _usdc USDC address\n     * @param _weth WETH address\n     * @param _crabFairPriceInEth Crab token price\n     * @param _ethUsdcPrice ETH/USDC price\n     */\n    function getZenBullPrice(\n        address _zenBull,\n        address _eulerLens,\n        address _usdc,\n        address _weth,\n        uint256 _crabFairPriceInEth,\n        uint256 _ethUsdcPrice\n    ) external view returns (uint256) {\n        uint256 zenBullCrabBalance = IZenBullStrategy(_zenBull).getCrabBalance();\n        return (\n            IEulerSimpleLens(_eulerLens).getETokenBalance(_weth, _zenBull)\n                + (zenBullCrabBalance * _crabFairPriceInEth / 1e18)\n                - (\n                    (IEulerSimpleLens(_eulerLens).getDTokenBalance(_usdc, _zenBull) * 1e12 * 1e18)\n                        / _ethUsdcPrice\n                )\n        ) * 1e18 / IERC20(_zenBull).totalSupply();\n    }\n\n    /**\n     * @notice calculate oSQTH to mint and amount of eth to deposit into Crab v2 based on amount of crab token\n     * @param _crab crab strategy address\n     * @param _zenBull ZenBull strategy address\n     * @param _crabAmount amount of crab token\n     */\n    function calcOsqthToMintAndEthIntoCrab(address _crab, address _zenBull, uint256 _crabAmount)\n        external\n        view\n        returns (uint256, uint256)\n    {\n        uint256 crabTotalSupply = IERC20(_crab).totalSupply();\n        (uint256 crabEth, uint256 crabDebt) = IZenBullStrategy(_zenBull).getCrabVaultDetails();\n        uint256 _oSqthToMint = _crabAmount * crabDebt / crabTotalSupply;\n        uint256 ethIntoCrab = _crabAmount * crabEth / crabTotalSupply;\n\n        return (_oSqthToMint, ethIntoCrab);\n    }\n\n    /**\n     * @notice calculate amount of WETH to lend in and USDC to borrow from Euler\n     * @param _eulerLens EulerSimpleLens contract address\n     * @param _zenBull ZenBull strategy address\n     * @param _weth WETH address\n     * @param _usdc USDC address\n     * @param _crabAmount amount of crab token\n     */\n    function calcWethToLendAndUsdcToBorrow(\n        address _eulerLens,\n        address _zenBull,\n        address _weth,\n        address _usdc,\n        uint256 _crabAmount\n    ) external view returns (uint256, uint256) {\n        uint256 share =\n            div(_crabAmount, (IZenBullStrategy(_zenBull).getCrabBalance() + _crabAmount));\n        uint256 wethToLend = div(\n            mul(IEulerSimpleLens(_eulerLens).getETokenBalance(_weth, _zenBull), share), 1e18 - share\n        );\n        uint256 usdcToBorrow = div(\n            mul(IEulerSimpleLens(_eulerLens).getDTokenBalance(_usdc, _zenBull), share), 1e18 - share\n        );\n\n        return (wethToLend, usdcToBorrow);\n    }\n\n    /**\n     * @notice calculate amount of oSQTH to get based on amount of ZenBull to Withdraw\n     * @param _zenBull ZenBull strategy address\n     * @param _crab crab strategy address\n     * @param _withdrawsToProcess amount of ZenBull token to withdraw\n     */\n    function calcOsqthAmount(address _zenBull, address _crab, uint256 _withdrawsToProcess)\n        external\n        view\n        returns (uint256)\n    {\n        uint256 bullTotalSupply = IERC20(_zenBull).totalSupply();\n        (, uint256 crabDebt) = IZenBullStrategy(_zenBull).getCrabVaultDetails();\n        uint256 share = div(_withdrawsToProcess, bullTotalSupply);\n        uint256 _crabAmount = mul(share, IZenBullStrategy(_zenBull).getCrabBalance());\n\n        return div(mul(_crabAmount, crabDebt), IERC20(_crab).totalSupply());\n    }\n\n    function mul(uint256 _x, uint256 _y) internal pure returns (uint256) {\n        // add(mul(_x, _y), WAD / 2) / WAD;\n        return ((_x * _y) + (1e18 / 2)) / 1e18;\n    }\n\n    function div(uint256 _x, uint256 _y) internal pure returns (uint256) {\n        // add(mul(_x, WAD), _y / 2) / _y;\n        return ((_x * 1e18) + (_y / 2)) / _y;\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/src/ZenBullNetting.sol",
    "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.13;\npragma abicoder v2;\n\n// interface\nimport { IERC20 } from \"openzeppelin/interfaces/IERC20.sol\";\nimport { IZenBullStrategy } from \"./interface/IZenBullStrategy.sol\";\nimport { IController } from \"./interface/IController.sol\";\nimport { IOracle } from \"./interface/IOracle.sol\";\nimport { IEulerSimpleLens } from \"./interface/IEulerSimpleLens.sol\";\nimport { IWETH } from \"./interface/IWETH.sol\";\nimport { ICrabStrategyV2 } from \"./interface/ICrabStrategyV2.sol\";\nimport { IFlashZen } from \"./interface/IFlashZen.sol\";\n// contract\nimport { Ownable } from \"openzeppelin/access/Ownable.sol\";\nimport { EIP712 } from \"openzeppelin/utils/cryptography/draft-EIP712.sol\";\nimport { ECDSA } from \"openzeppelin/utils/cryptography/ECDSA.sol\";\nimport { FlashSwap } from \"./FlashSwap.sol\";\n// lib\nimport { Address } from \"openzeppelin/utils/Address.sol\";\nimport { NettingLib } from \"./NettingLib.sol\";\n\n/**\n * Error codes\n * ZBN01: Auction TWAP is less than min value\n * ZBN02: OTC price tolerance is greater than max OTC tolerance price\n * ZBN03: Amount to queue for deposit is less than min amount\n * ZBN04: Can not dequeue deposited amount because auction is already live and force dequeued not activated\n * ZBN05: Amount of ETH to deposit left in the queue is less than min amount\n * ZBN06: Queued deposit is not longer than 1 week to force dequeue\n * ZBN07: Amount of ZenBull to queue for withdraw is less than min amount\n * ZBN08: Amount of ZenBull to withdraw left in the queue is less than min amount\n * ZBN09: Queued withdraw is not longer than 1 week to force dequeue\n * ZBN10: ETH quantity to net is less than queued for deposits\n * ZBN11: ZenBull quantity to net is less than queued for withdraws\n * ZBN12: ZenBull Price too high\n * ZBN13: ZenBull Price too low\n * ZBN14: Clearing price too high relative to Uniswap twap\n * ZBN15: Clearing price too low relative to Uniswap twap\n * ZBN16: Invalid order signer\n * ZBN17: Order already expired\n * ZBN18: Nonce already used\n * ZBN19: auction order is not selling\n * ZBN20: sell order price greater than clearing\n * ZBN21: auction order is not buying\n * ZBN22: buy order price greater than clearing\n * ZBN23: not enough buy orders for sqth\n * ZBN24: not authorized to perform netting at price\n */\n\n/**\n * @dev ZenBullNetting contract\n * @notice Contract for Netting Deposits and Withdrawals in ZenBull\n * @author Opyn team\n */\ncontract ZenBullNetting is Ownable, EIP712, FlashSwap {\n    using Address for address payable;\n\n    /// @dev typehash for signed orders\n    bytes32 private constant _ZENBULL_NETTING_TYPEHASH = keccak256(\n        \"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\"\n    );\n    /// @dev OTC price tolerance cannot exceed 20%\n    uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20%\n    /// @dev min auction TWAP\n    uint32 public constant MIN_AUCTION_TWAP = 180 seconds;\n\n    /// @dev owner sets to true when starting auction\n    bool public isAuctionLive;\n\n    /// @dev min ETH amounts to withdraw or deposit via netting\n    uint256 public minEthAmount;\n    /// @dev min ZenBull amounts to withdraw or deposit via netting\n    uint256 public minZenBullAmount;\n    /// @dev array index of last processed deposits\n    uint256 public depositsIndex;\n    /// @dev array index of last processed withdraws\n    uint256 public withdrawsIndex;\n    // @dev OTC price must be within this distance of the uniswap twap price\n    uint256 public otcPriceTolerance;\n    /// @dev twap period to use for auction calculations\n    uint32 public auctionTwapPeriod;\n\n    /// @dev WETH token address\n    address private immutable weth;\n    /// @dev oSQTH token address\n    address private immutable oSqth;\n    /// @dev USDC token address\n    address private immutable usdc;\n    /// @dev ZenBull token address\n    address private immutable zenBull;\n    /// @dev WPowerPerp Oracle address\n    address private immutable oracle;\n    /// @dev ETH/oSQTH uniswap v3 pool address\n    address private immutable ethSqueethPool;\n    /// @dev ETH/USDC uniswap v3 pool address\n    address private immutable ethUsdcPool;\n    /// @dev Euler Simple Lens contract address\n    address private immutable eulerLens;\n    /// @dev crab strategy contract address\n    address private immutable crab;\n    /// @dev FlashZen contract address\n    address private immutable flashZenBull;\n\n    /// @dev bot address to automate netAtPrice() calls\n    address public bot;\n\n    /// @dev array of ETH deposit receipts\n    Receipt[] public deposits;\n    /// @dev array of ZenBull withdrawal receipts\n    Receipt[] public withdraws;\n\n    /// @dev ETH amount to deposit for an address\n    mapping(address => uint256) public ethBalance;\n    /// @dev ZenBull amount to withdraw for an address\n    mapping(address => uint256) public zenBullBalance;\n    /// @dev indexes of deposit receipts of an address\n    mapping(address => uint256[]) public userDepositsIndex;\n    /// @dev indexes of withdraw receipts of an address\n    mapping(address => uint256[]) public userWithdrawsIndex;\n    /// @dev store the used flag for a nonce for each address\n    mapping(address => mapping(uint256 => bool)) public nonces;\n\n    /// @dev order struct for a signed order from market maker\n    struct Order {\n        uint256 bidId;\n        address trader;\n        uint256 quantity;\n        uint256 price;\n        bool isBuying;\n        uint256 expiry;\n        uint256 nonce;\n        uint8 v;\n        bytes32 r;\n        bytes32 s;\n    }\n\n    /// @dev receipt used to store deposits and withdraws\n    struct Receipt {\n        /// @dev address of the depositor or withdrawer\n        address sender;\n        /// @dev ETH amount to queue for deposit or ZenBull amount to queue for withdrawal\n        uint256 amount;\n        /// @dev time of deposit\n        uint256 timestamp;\n    }\n\n    struct DepositAuctionParams {\n        /// @dev WETH to deposit\n        uint256 depositsToProcess;\n        /// @dev Crab amount to deposit into ZenBull\n        uint256 crabAmount;\n        /// @dev orders to buy sqth\n        Order[] orders;\n        /// @dev price from the auction to sell sqth\n        uint256 clearingPrice;\n        /// @dev amount to deposit into crab in ZenBull flash deposit\n        uint256 flashDepositEthToCrab;\n        /// @dev min ETH to get from oSQTH in ZenBull flash deposit\n        uint256 flashDepositMinEthFromSqth;\n        /// @dev min ETH to get from USDC in ZenBull flash deposit\n        uint256 flashDepositMinEthFromUsdc;\n        /// @dev uniswap weth/wPowerPerp pool fee ZenBull flash deposit\n        uint24 flashDepositWPowerPerpPoolFee;\n        /// @dev uniswap fee for swapping eth to USD, and pool fee to use for ZenBull flash deposit\n        uint24 wethUsdcPoolFee;\n    }\n\n    /// @dev params for withdraw auction\n    struct WithdrawAuctionParams {\n        /// @dev amont of bull to queue for withdrawal\n        uint256 withdrawsToProcess;\n        /// @dev orders that sell oSqth to the auction\n        Order[] orders;\n        /// @dev price that the auction pays for the purchased oSqth\n        uint256 clearingPrice;\n        /// @dev max WETH to pay for flashswapped USDC\n        uint256 maxWethForUsdc;\n        /// @dev uniswap fee for swapping eth to USD;\n        uint24 wethUsdcPoolFee;\n    }\n\n    /// @dev struct to store proportional amounts of erc20s (received or to send)\n    struct MemoryVar {\n        uint256 currentZenBullBalance;\n        uint256 remainingEth;\n        uint256 remainingDeposits;\n        uint256 oSqthBalance;\n    }\n\n    event SetMinZenBullAmount(uint256 oldAmount, uint256 newAmount);\n    event SetMinEthAmount(uint256 oldAmount, uint256 newAmount);\n    event SetDepositsIndex(uint256 oldDepositsIndex, uint256 newDepositsIndex);\n    event SetWithdrawsIndex(uint256 oldWithdrawsIndex, uint256 newWithdrawsIndex);\n    event SetAuctionTwapPeriod(uint32 previousTwap, uint32 newTwap);\n    event SetOTCPriceTolerance(uint256 previousTolerance, uint256 newOtcPriceTolerance);\n    event ToggledAuctionLive(bool isAuctionLive);\n    event QueueEth(\n        address indexed depositor,\n        uint256 amount,\n        uint256 depositorsBalance,\n        uint256 indexed receiptIndex\n    );\n    event DequeueEth(address indexed depositor, uint256 amount, uint256 depositorsBalance);\n    event QueueZenBull(\n        address indexed withdrawer,\n        uint256 amount,\n        uint256 withdrawersBalance,\n        uint256 indexed receiptIndex\n    );\n    event DequeueZenBull(address indexed withdrawer, uint256 amount, uint256 withdrawersBalance);\n    event NetAtPrice(\n        bool indexed isDeposit,\n        address indexed receiver,\n        uint256 amountQueuedProcessed,\n        uint256 amountReceived,\n        uint256 indexed index\n    );\n    event EthDeposited(\n        address indexed depositor,\n        uint256 ethAmount,\n        uint256 zenBullAmount,\n        uint256 indexed receiptIndex,\n        uint256 refundedETH\n    );\n    event ZenBullWithdrawn(\n        address indexed withdrawer,\n        uint256 zenBullAmount,\n        uint256 ethAmount,\n        uint256 indexed receiptIndex\n    );\n    event SetBot(address bot);\n    event DepositAuction(\n        uint256 wethDeposited,\n        uint256 crabAmount,\n        uint256 clearingPrice,\n        uint256 oSqthAmount,\n        uint256 depositsIndex\n    );\n    event WithdrawAuction(\n        uint256 zenBullWithdrawn, uint256 clearingPrice, uint256 oSqthAmount, uint256 withdrawsIndex\n    );\n    event CancelNonce(address trader, uint256 nonce);\n    /// @dev shared events with the NettingLib for client side to detect them\n    event TransferWethFromMarketMakers(\n        address indexed trader, uint256 quantity, uint256 wethAmount, uint256 clearingPrice\n    );\n    event TransferOsqthToMarketMakers(\n        address indexed trader, uint256 bidId, uint256 quantity, uint256 remainingOsqthBalance\n    );\n    event TransferOsqthFromMarketMakers(\n        address indexed trader, uint256 quantity, uint256 oSqthRemaining\n    );\n    event TransferWethToMarketMaker(\n        address indexed trader,\n        uint256 bidId,\n        uint256 quantity,\n        uint256 wethAmount,\n        uint256 oSqthRemaining,\n        uint256 clearingPrice\n    );\n\n    constructor(\n        address _zenBull,\n        address _eulerSimpleLens,\n        address _flashZenBull,\n        address _uniFactory\n    ) EIP712(\"ZenBullNetting\", \"1\") FlashSwap(_uniFactory) {\n        otcPriceTolerance = 5e16; // 5%\n        auctionTwapPeriod = 420 seconds;\n\n        zenBull = _zenBull;\n        eulerLens = _eulerSimpleLens;\n        weth = IController(IZenBullStrategy(_zenBull).powerTokenController()).weth();\n        oracle = IController(IZenBullStrategy(_zenBull).powerTokenController()).oracle();\n        ethSqueethPool =\n            IController(IZenBullStrategy(_zenBull).powerTokenController()).wPowerPerpPool();\n        ethUsdcPool =\n            IController(IZenBullStrategy(_zenBull).powerTokenController()).ethQuoteCurrencyPool();\n        usdc = IController(IZenBullStrategy(_zenBull).powerTokenController()).quoteCurrency();\n        oSqth = IController(IZenBullStrategy(_zenBull).powerTokenController()).wPowerPerp();\n        crab = IZenBullStrategy(zenBull).crab();\n        flashZenBull = _flashZenBull;\n\n        IERC20(usdc).approve(_zenBull, type(uint256).max);\n        IERC20(oSqth).approve(_zenBull, type(uint256).max);\n        IERC20(crab).approve(_zenBull, type(uint256).max);\n    }\n\n    /**\n     * @notice receive function to allow ETH transfer to this contract\n     */\n    receive() external payable {\n        if ((msg.sender != weth) && (msg.sender != zenBull) && (msg.sender != flashZenBull)) {\n            _queueEth();\n        }\n    }\n\n    /**\n     * @dev view function to get the domain seperator used in signing\n     */\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\n        return _domainSeparatorV4();\n    }\n\n    /**\n     * @dev toggles the value of isAuctionLive\n     */\n    function toggleAuctionLive() external onlyOwner {\n        isAuctionLive = !isAuctionLive;\n        emit ToggledAuctionLive(isAuctionLive);\n    }\n\n    /**\n     * @notice set min ETH amount\n     * @param _amount the amount to be set as minEthAmount\n     */\n    function setMinEthAmount(uint256 _amount) external onlyOwner {\n        emit SetMinEthAmount(minEthAmount, _amount);\n        minEthAmount = _amount;\n    }\n\n    /**\n     * @notice set minZenBullAmount\n     * @param _amount the number to be set as minZenBullAmount\n     */\n    function setMinZenBullAmount(uint256 _amount) external onlyOwner {\n        emit SetMinZenBullAmount(minZenBullAmount, _amount);\n\n        minZenBullAmount = _amount;\n    }\n\n    /**\n     * @notice set the depositIndex so that we want to skip processing some deposits\n     * @param _newDepositsIndex the new deposits index\n     */\n    function setDepositsIndex(uint256 _newDepositsIndex) external onlyOwner {\n        emit SetDepositsIndex(depositsIndex, _newDepositsIndex);\n\n        depositsIndex = _newDepositsIndex;\n    }\n\n    /**\n     * @notice set the withdraw index so that we want to skip processing some withdraws\n     * @param _newWithdrawsIndex the new withdraw index\n     */\n    function setWithdrawsIndex(uint256 _newWithdrawsIndex) external onlyOwner {\n        emit SetWithdrawsIndex(withdrawsIndex, _newWithdrawsIndex);\n\n        withdrawsIndex = _newWithdrawsIndex;\n    }\n\n    /**\n     * @notice owner can set the twap period in seconds that is used for obtaining TWAP prices\n     * @param _auctionTwapPeriod the twap period, in seconds\n     */\n    function setAuctionTwapPeriod(uint32 _auctionTwapPeriod) external onlyOwner {\n        require(_auctionTwapPeriod >= MIN_AUCTION_TWAP, \"ZBN01\");\n\n        emit SetAuctionTwapPeriod(auctionTwapPeriod, _auctionTwapPeriod);\n\n        auctionTwapPeriod = _auctionTwapPeriod;\n    }\n\n    /**\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price\n     * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18\n     */\n    function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner {\n        // Tolerance cannot be more than 20%\n        require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, \"ZBN02\");\n\n        emit SetOTCPriceTolerance(otcPriceTolerance, _otcPriceTolerance);\n\n        otcPriceTolerance = _otcPriceTolerance;\n    }\n\n    /**\n     * @notice set bot address\n     * @param _bot bot address\n     */\n    function setBot(address _bot) external onlyOwner {\n        bot = _bot;\n\n        emit SetBot(_bot);\n    }\n\n    /**\n     * @dev cancel nonce by marking it as used\n     * @param _nonce nonce to cancel\n     */\n    function cancelNonce(uint256 _nonce) external {\n        nonces[msg.sender][_nonce] = true;\n\n        emit CancelNonce(msg.sender, _nonce);\n    }\n\n    /**\n     * @notice queue ETH for deposit into ZenBull\n     * @dev payable function\n     */\n    function queueEth() external payable {\n        _queueEth();\n    }\n\n    /**\n     * @notice withdraw ETH from queue\n     * @param _amount ETH amount to dequeue\n     * @param _force forceWithdraw if deposited more than a week ago\n     */\n    function dequeueEth(uint256 _amount, bool _force) external {\n        require(!isAuctionLive || _force, \"ZBN04\");\n\n        ethBalance[msg.sender] = ethBalance[msg.sender] - _amount;\n\n        require(ethBalance[msg.sender] >= minEthAmount || ethBalance[msg.sender] == 0, \"ZBN05\");\n\n        // start withdrawing from the users last deposit\n        uint256 toWithdraw = _amount;\n        uint256 lastDepositIndex = userDepositsIndex[msg.sender].length;\n        for (uint256 i = lastDepositIndex; i > 0; i--) {\n            Receipt storage receipt = deposits[userDepositsIndex[msg.sender][i - 1]];\n\n            if (_force) {\n                require(block.timestamp > receipt.timestamp + 1 weeks, \"ZBN06\");\n            }\n            if (receipt.amount > toWithdraw) {\n                receipt.amount -= toWithdraw;\n                break;\n            } else {\n                toWithdraw -= receipt.amount;\n                delete deposits[userDepositsIndex[msg.sender][i - 1]];\n                userDepositsIndex[msg.sender].pop();\n            }\n        }\n\n        payable(msg.sender).sendValue(_amount);\n\n        emit DequeueEth(msg.sender, _amount, ethBalance[msg.sender]);\n    }\n\n    /**\n     * @notice queue ZenBull token for withdraw from strategy\n     * @param _amount ZenBull amount to withdraw\n     */\n    function queueZenBull(uint256 _amount) external {\n        require(_amount >= minZenBullAmount, \"ZBN07\");\n\n        zenBullBalance[msg.sender] = zenBullBalance[msg.sender] + _amount;\n        withdraws.push(Receipt(msg.sender, _amount, block.timestamp));\n        userWithdrawsIndex[msg.sender].push(withdraws.length - 1);\n\n        IERC20(zenBull).transferFrom(msg.sender, address(this), _amount);\n\n        emit QueueZenBull(msg.sender, _amount, zenBullBalance[msg.sender], withdraws.length - 1);\n    }\n\n    /**\n     * @notice withdraw ZenBull from queue\n     * @param _amount ZenBull amount to dequeue\n     * @param _force forceWithdraw if queued more than a week ago\n     */\n    function dequeueZenBull(uint256 _amount, bool _force) external {\n        require(!isAuctionLive || _force, \"ZBN04\");\n\n        zenBullBalance[msg.sender] = zenBullBalance[msg.sender] - _amount;\n\n        require(\n            zenBullBalance[msg.sender] >= minZenBullAmount || zenBullBalance[msg.sender] == 0,\n            \"ZBN08\"\n        );\n\n        // deQueue ZenBull from the last, last in first out\n        uint256 toRemove = _amount;\n        uint256 lastWithdrawIndex = userWithdrawsIndex[msg.sender].length;\n        for (uint256 i = lastWithdrawIndex; i > 0; i--) {\n            Receipt storage receipt = withdraws[userWithdrawsIndex[msg.sender][i - 1]];\n            if (_force) {\n                require(block.timestamp > receipt.timestamp + 1 weeks, \"ZBN09\");\n            }\n            if (receipt.amount > toRemove) {\n                receipt.amount -= toRemove;\n                break;\n            } else {\n                toRemove -= receipt.amount;\n                delete withdraws[userWithdrawsIndex[msg.sender][i - 1]];\n                userWithdrawsIndex[msg.sender].pop();\n            }\n        }\n\n        IERC20(zenBull).transfer(msg.sender, _amount);\n\n        emit DequeueZenBull(msg.sender, _amount, zenBullBalance[msg.sender]);\n    }\n\n    /**\n     * @notice swaps quantity amount of ETH for ZenBull token at ZenBull/ETH price\n     * @param _price price of ZenBull in ETH\n     * @param _quantity amount of ETH to net\n     */\n    function netAtPrice(uint256 _price, uint256 _quantity) external {\n        require((msg.sender == owner()) || (msg.sender == bot), \"ZBN24\");\n\n        uint256 zenBullFairPrice = _getZenBullPrice();\n\n        require(_price <= (zenBullFairPrice * (1e18 + otcPriceTolerance)) / 1e18, \"ZBN12\");\n        require(_price >= (zenBullFairPrice * (1e18 - otcPriceTolerance)) / 1e18, \"ZBN13\");\n\n        uint256 zenBullQuantity = (_quantity * 1e18) / _price;\n\n        require(_quantity <= address(this).balance, \"ZBN10\");\n        require(zenBullQuantity <= IERC20(zenBull).balanceOf(address(this)), \"ZBN11\");\n\n        // process deposits and send ZenBull\n        uint256 i = depositsIndex;\n        uint256 amountToSend;\n        while (_quantity > 0) {\n            Receipt memory deposit = deposits[i];\n            if (deposit.amount == 0) {\n                i++;\n                continue;\n            }\n            if (deposit.amount <= _quantity) {\n                // deposit amount is lesser than quantity use it fully\n                _quantity = _quantity - deposit.amount;\n                ethBalance[deposit.sender] -= deposit.amount;\n                amountToSend = (deposit.amount * 1e18) / _price;\n                IERC20(zenBull).transfer(deposit.sender, amountToSend);\n\n                emit NetAtPrice(true, deposit.sender, deposit.amount, amountToSend, i);\n                delete deposits[i];\n                i++;\n            } else {\n                // deposit amount is greater than quantity; use it partially\n                deposits[i].amount = deposit.amount - _quantity;\n                ethBalance[deposit.sender] -= _quantity;\n                amountToSend = (_quantity * 1e18) / _price;\n\n                IERC20(zenBull).transfer(deposit.sender, amountToSend);\n\n                emit NetAtPrice(true, deposit.sender, _quantity, amountToSend, i);\n                break;\n            }\n        }\n        depositsIndex = i;\n\n        // process withdraws and send usdc\n        i = withdrawsIndex;\n        while (zenBullQuantity > 0) {\n            Receipt memory withdraw = withdraws[i];\n            if (withdraw.amount == 0) {\n                i++;\n                continue;\n            }\n            if (withdraw.amount <= zenBullQuantity) {\n                zenBullQuantity = zenBullQuantity - withdraw.amount;\n                zenBullBalance[withdraw.sender] -= withdraw.amount;\n                amountToSend = (withdraw.amount * _price) / 1e18;\n\n                payable(withdraw.sender).sendValue(amountToSend);\n\n                emit NetAtPrice(false, withdraw.sender, withdraw.amount, amountToSend, i);\n\n                delete withdraws[i];\n                i++;\n            } else {\n                withdraws[i].amount = withdraw.amount - zenBullQuantity;\n                zenBullBalance[withdraw.sender] -= zenBullQuantity;\n                amountToSend = (zenBullQuantity * _price) / 1e18;\n\n                payable(withdraw.sender).sendValue(amountToSend);\n\n                emit NetAtPrice(false, withdraw.sender, zenBullQuantity, amountToSend, i);\n\n                break;\n            }\n        }\n        withdrawsIndex = i;\n    }\n\n    /**\n     * @notice auction for queued deposits\n     * @dev takes in orders from MM's to buy oSQTH\n     * @param _params deposit Params\n     */\n    function depositAuction(DepositAuctionParams calldata _params) external onlyOwner {\n        _checkOTCPrice(_params.clearingPrice, false);\n\n        uint256 initialZenBullBalance = IERC20(zenBull).balanceOf(address(this));\n        uint256 initialEthBalance = address(this).balance;\n        (uint256 oSqthToMint, uint256 ethIntoCrab) =\n            NettingLib.calcOsqthToMintAndEthIntoCrab(crab, zenBull, _params.crabAmount);\n\n        // get WETH from MM\n        for (uint256 i = 0; i < _params.orders.length; i++) {\n            require(_params.orders[i].isBuying, \"ZBN21\");\n            require(_params.orders[i].price >= _params.clearingPrice, \"ZBN22\");\n\n            _checkOrder(_params.orders[i]);\n            _useNonce(_params.orders[i].trader, _params.orders[i].nonce);\n\n            bool shouldBreak;\n            (shouldBreak, oSqthToMint) = NettingLib.transferWethFromMarketMakers(\n                weth,\n                _params.orders[i].trader,\n                _params.orders[i].quantity,\n                oSqthToMint,\n                _params.clearingPrice\n            );\n            if (shouldBreak) break;\n        }\n        require(oSqthToMint == 0, \"ZBN23\");\n\n        {\n            // deposit into crab\n            uint256 wethFromAuction = IWETH(weth).balanceOf(address(this));\n            IWETH(weth).withdraw(wethFromAuction);\n\n            ICrabStrategyV2(crab).deposit{ value: ethIntoCrab }();\n\n            (uint256 wethToLend, uint256 usdcToBorrow) = NettingLib.calcWethToLendAndUsdcToBorrow(\n                eulerLens, zenBull, weth, usdc, IERC20(crab).balanceOf(address(this))\n            );\n\n            // flashswap WETH for USDC debt, and deposit crab + wethToLend into ZenBull\n            uint256 minWethForUsdcDebt =\n                wethToLend - (_params.depositsToProcess + wethFromAuction - ethIntoCrab);\n            _exactInFlashSwap(\n                usdc,\n                weth,\n                _params.wethUsdcPoolFee,\n                usdcToBorrow,\n                minWethForUsdcDebt,\n                1,\n                abi.encodePacked(wethToLend)\n            );\n        }\n\n        MemoryVar memory memVar;\n        memVar.remainingEth =\n            address(this).balance - (initialEthBalance - _params.depositsToProcess);\n\n        {\n            if (memVar.remainingEth > 0 && _params.flashDepositEthToCrab > 0) {\n                IFlashZen.FlashDepositParams memory params = IFlashZen.FlashDepositParams({\n                    ethToCrab: _params.flashDepositEthToCrab,\n                    minEthFromSqth: _params.flashDepositMinEthFromSqth,\n                    minEthFromUsdc: _params.flashDepositMinEthFromUsdc,\n                    wPowerPerpPoolFee: _params.flashDepositWPowerPerpPoolFee,\n                    usdcPoolFee: _params.wethUsdcPoolFee\n                });\n\n                IFlashZen(flashZenBull).flashDeposit{ value: memVar.remainingEth }(params);\n            }\n        }\n\n        // send oSqth to market makers\n        memVar.oSqthBalance = IERC20(oSqth).balanceOf(address(this));\n        for (uint256 i = 0; i < _params.orders.length; i++) {\n            bool shouldBreak;\n            (shouldBreak, memVar.oSqthBalance) = NettingLib.transferOsqthToMarketMakers(\n                oSqth,\n                _params.orders[i].trader,\n                _params.orders[i].bidId,\n                memVar.oSqthBalance,\n                _params.orders[i].quantity\n            );\n            if (shouldBreak) break;\n        }\n\n        // send ZenBull to depositor\n        memVar.remainingDeposits = _params.depositsToProcess;\n        uint256 k = depositsIndex;\n        memVar.currentZenBullBalance =\n            IERC20(zenBull).balanceOf(address(this)) - initialZenBullBalance;\n        memVar.remainingEth =\n            address(this).balance - (initialEthBalance - _params.depositsToProcess);\n\n        while (memVar.remainingDeposits > 0) {\n            Receipt memory depositReceipt = deposits[k];\n            if (depositReceipt.amount == 0) {\n                k++;\n                continue;\n            } else {\n                uint256 zenBullAmountToSend;\n                uint256 ethAmountToSend;\n                if (depositReceipt.amount <= memVar.remainingDeposits) {\n                    memVar.remainingDeposits = memVar.remainingDeposits - depositReceipt.amount;\n                    ethBalance[depositReceipt.sender] -= depositReceipt.amount;\n\n                    zenBullAmountToSend = depositReceipt.amount * memVar.currentZenBullBalance\n                        / _params.depositsToProcess;\n\n                    IERC20(zenBull).transfer(deposits[k].sender, zenBullAmountToSend);\n\n                    delete deposits[k];\n                    k++;\n\n                    ethAmountToSend =\n                        depositReceipt.amount * memVar.remainingEth / _params.depositsToProcess;\n                    if (ethAmountToSend > 1e12) {\n                        payable(depositReceipt.sender).sendValue(ethAmountToSend);\n                    }\n\n                    emit EthDeposited(\n                        depositReceipt.sender,\n                        depositReceipt.amount,\n                        zenBullAmountToSend,\n                        k,\n                        ethAmountToSend\n                    );\n                } else {\n                    ethBalance[depositReceipt.sender] -= memVar.remainingDeposits;\n\n                    zenBullAmountToSend = memVar.remainingDeposits * memVar.currentZenBullBalance\n                        / _params.depositsToProcess;\n                    IERC20(zenBull).transfer(depositReceipt.sender, zenBullAmountToSend);\n\n                    deposits[k].amount -= memVar.remainingDeposits;\n\n                    ethAmountToSend =\n                        memVar.remainingDeposits * memVar.remainingEth / _params.depositsToProcess;\n\n                    if (ethAmountToSend > 1e12) {\n                        payable(depositReceipt.sender).sendValue(ethAmountToSend);\n                    }\n\n                    emit EthDeposited(\n                        depositReceipt.sender,\n                        memVar.remainingDeposits,\n                        zenBullAmountToSend,\n                        k,\n                        ethAmountToSend\n                    );\n                    break;\n                }\n            }\n        }\n        depositsIndex = k;\n        isAuctionLive = false;\n\n        emit DepositAuction(\n            _params.depositsToProcess,\n            _params.crabAmount,\n            _params.clearingPrice,\n            memVar.oSqthBalance,\n            k\n        );\n    }\n\n    /**\n     * @notice auction for queued withdraws\n     * @dev takes in orders from MM's to sell oSQTH\n     * @param _params withdraw Params\n     */\n    function withdrawAuction(WithdrawAuctionParams calldata _params) external onlyOwner {\n        _checkOTCPrice(_params.clearingPrice, true);\n\n        uint256 initialEthBalance = address(this).balance;\n        uint256 oSqthAmount = NettingLib.calcOsqthAmount(zenBull, crab, _params.withdrawsToProcess);\n\n        // get oSQTH from market makers orders\n        uint256 toExchange = oSqthAmount;\n        for (uint256 i = 0; i < _params.orders.length && toExchange > 0; i++) {\n            _checkOrder(_params.orders[i]);\n            _useNonce(_params.orders[i].trader, _params.orders[i].nonce);\n\n            require(!_params.orders[i].isBuying, \"ZBN19\");\n            require(_params.orders[i].price <= _params.clearingPrice, \"ZBN20\");\n\n            toExchange = NettingLib.transferOsqthFromMarketMakers(\n                oSqth, _params.orders[i].trader, toExchange, _params.orders[i].quantity\n            );\n        }\n\n        uint256 usdcToRepay = NettingLib.mul(\n            NettingLib.div(_params.withdrawsToProcess, IERC20(zenBull).totalSupply()),\n            IEulerSimpleLens(eulerLens).getDTokenBalance(usdc, zenBull)\n        );\n\n        // WETH-USDC swap\n        _exactOutFlashSwap(\n            weth,\n            usdc,\n            _params.wethUsdcPoolFee,\n            usdcToRepay,\n            _params.maxWethForUsdc,\n            0,\n            abi.encodePacked(_params.withdrawsToProcess)\n        );\n\n        // send WETH to market makers\n        IWETH(weth).deposit{ value: address(this).balance - initialEthBalance }();\n        toExchange = oSqthAmount;\n        for (uint256 i = 0; i < _params.orders.length && toExchange > 0; i++) {\n            toExchange = NettingLib.transferWethToMarketMaker(\n                weth,\n                _params.orders[i].trader,\n                _params.orders[i].bidId,\n                toExchange,\n                _params.orders[i].quantity,\n                _params.clearingPrice\n            );\n        }\n\n        // send ETH to withdrawers\n        uint256 ethToWithdrawers = IWETH(weth).balanceOf(address(this));\n        IWETH(weth).withdraw(ethToWithdrawers);\n\n        uint256 remainingWithdraws = _params.withdrawsToProcess;\n        uint256 j = withdrawsIndex;\n        uint256 ethAmount;\n\n        while (remainingWithdraws > 0) {\n            Receipt memory withdraw = withdraws[j];\n            if (withdraw.amount == 0) {\n                j++;\n                continue;\n            }\n            if (withdraw.amount <= remainingWithdraws) {\n                // full usage\n                remainingWithdraws -= withdraw.amount;\n                zenBullBalance[withdraw.sender] -= withdraw.amount;\n\n                // send proportional usdc\n                ethAmount = withdraw.amount * ethToWithdrawers / _params.withdrawsToProcess;\n\n                delete withdraws[j];\n                j++;\n\n                payable(withdraw.sender).sendValue(ethAmount);\n\n                emit ZenBullWithdrawn(withdraw.sender, withdraw.amount, ethAmount, j);\n            } else {\n                withdraws[j].amount -= remainingWithdraws;\n                zenBullBalance[withdraw.sender] -= remainingWithdraws;\n\n                // send proportional usdc\n                ethAmount = remainingWithdraws * ethToWithdrawers / _params.withdrawsToProcess;\n\n                payable(withdraw.sender).sendValue(ethAmount);\n\n                emit ZenBullWithdrawn(withdraw.sender, remainingWithdraws, ethAmount, j);\n\n                break;\n            }\n        }\n\n        withdrawsIndex = j;\n        isAuctionLive = false;\n\n        emit WithdrawAuction(_params.withdrawsToProcess, _params.clearingPrice, oSqthAmount, j);\n    }\n\n    /**\n     * @dev to handle uniswap flashswap callback\n     */\n    function _uniFlashSwap(\n        address pool,\n        uint256 amountToPay,\n        bytes memory callData,\n        uint8 callSource\n    ) internal override {\n        if (callSource == 0) {\n            uint256 zenBullAmountToBurn = abi.decode(callData, (uint256));\n\n            IZenBullStrategy(zenBull).withdraw(zenBullAmountToBurn);\n            IWETH(weth).deposit{ value: amountToPay }();\n            IWETH(weth).transfer(pool, amountToPay);\n        } else if (callSource == 1) {\n            uint256 wethToLend = abi.decode(callData, (uint256));\n\n            IWETH(weth).withdraw(IWETH(weth).balanceOf(address(this)));\n            IZenBullStrategy(zenBull).deposit{ value: wethToLend }(\n                IERC20(crab).balanceOf(address(this))\n            );\n            IERC20(usdc).transfer(pool, amountToPay);\n        }\n    }\n\n    /**\n     * @dev queue ETH for deposit into ZenBull\n     */\n    function _queueEth() internal {\n        require(msg.value >= minEthAmount, \"ZBN03\");\n\n        // update eth balance of user, add their receipt, and receipt index to user deposits index\n        ethBalance[msg.sender] = ethBalance[msg.sender] + msg.value;\n        deposits.push(Receipt(msg.sender, msg.value, block.timestamp));\n        userDepositsIndex[msg.sender].push(deposits.length - 1);\n\n        emit QueueEth(msg.sender, msg.value, ethBalance[msg.sender], deposits.length - 1);\n    }\n\n    /**\n     * @notice get the sum of queued ETH\n     * @return sum ETH amount in queue\n     */\n    function depositsQueued() external view returns (uint256) {\n        uint256 j = depositsIndex;\n        uint256 sum;\n        while (j < deposits.length) {\n            sum = sum + deposits[j].amount;\n            j++;\n        }\n        return sum;\n    }\n\n    /**\n     * @notice get a deposit receipt by index\n     * @param _index deposit index in deposits array\n     * @return receipt sender, amount and timestamp\n     */\n    function getDepositReceipt(uint256 _index) external view returns (address, uint256, uint256) {\n        Receipt memory receipt = deposits[_index];\n\n        return (receipt.sender, receipt.amount, receipt.timestamp);\n    }\n\n    /**\n     * @notice get the sum of queued ZenBull\n     * @return sum ZenBull amount in queue\n     */\n    function withdrawsQueued() external view returns (uint256) {\n        uint256 j = withdrawsIndex;\n        uint256 sum;\n        while (j < withdraws.length) {\n            sum = sum + withdraws[j].amount;\n            j++;\n        }\n        return sum;\n    }\n\n    /**\n     * @notice get a withdraw receipt by index\n     * @param _index withdraw index in withdraws array\n     * @return receipt sender, amount and timestamp\n     */\n    function getWithdrawReceipt(uint256 _index) external view returns (address, uint256, uint256) {\n        Receipt memory receipt = withdraws[_index];\n\n        return (receipt.sender, receipt.amount, receipt.timestamp);\n    }\n\n    /**\n     * @notice checks the expiry nonce and signer of an order\n     * @param _order Order struct\n     */\n    function checkOrder(Order memory _order) external view returns (bool) {\n        return _checkOrder(_order);\n    }\n\n    /**\n     * @dev set nonce flag of the trader to true\n     * @param _trader address of the signer\n     * @param _nonce number that is to be traded only once\n     */\n    function _useNonce(address _trader, uint256 _nonce) internal {\n        require(!nonces[_trader][_nonce], \"ZBN18\");\n\n        nonces[_trader][_nonce] = true;\n    }\n\n    /**\n     * @dev get ZenBull token price using uniswap TWAP\n     * @return ZenBull price\n     */\n    function _getZenBullPrice() internal view returns (uint256) {\n        (uint256 crabFairPriceInEth, uint256 ethUsdcPrice) = NettingLib.getCrabPrice(\n            oracle, crab, ethUsdcPool, ethSqueethPool, oSqth, usdc, weth, zenBull, auctionTwapPeriod\n        );\n\n        return NettingLib.getZenBullPrice(\n            zenBull, eulerLens, usdc, weth, crabFairPriceInEth, ethUsdcPrice\n        );\n    }\n\n    /**\n     * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap\n     * @param _price clearing price provided by manager\n     * @param _isAuctionBuying is auction buying or selling oSQTH\n     */\n    function _checkOTCPrice(uint256 _price, bool _isAuctionBuying) internal view {\n        // Get twap\n        uint256 squeethEthPrice =\n            IOracle(oracle).getTwap(ethSqueethPool, oSqth, weth, auctionTwapPeriod, false);\n\n        if (_isAuctionBuying) {\n            require(_price <= (squeethEthPrice * (1e18 + otcPriceTolerance)) / 1e18, \"ZBN14\");\n        } else {\n            require(_price >= (squeethEthPrice * (1e18 - otcPriceTolerance)) / 1e18, \"ZBN15\");\n        }\n    }\n\n    /**\n     * @dev checks the expiry nonce and signer of an order\n     * @param _order Order struct\n     */\n    function _checkOrder(Order memory _order) internal view returns (bool) {\n        bytes32 structHash = keccak256(\n            abi.encode(\n                _ZENBULL_NETTING_TYPEHASH,\n                _order.bidId,\n                _order.trader,\n                _order.quantity,\n                _order.price,\n                _order.isBuying,\n                _order.expiry,\n                _order.nonce\n            )\n        );\n\n        bytes32 hash = _hashTypedDataV4(structHash);\n        address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\n        require(offerSigner == _order.trader, \"ZBN16\");\n        require(_order.expiry >= block.timestamp, \"ZBN17\");\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/src/interface/IController.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\n\ninterface IController {\n    function weth() external view returns (address);\n    function quoteCurrency() external view returns (address);\n    function ethQuoteCurrencyPool() external view returns (address);\n    function wPowerPerp() external view returns (address);\n    function wPowerPerpPool() external view returns (address);\n    function oracle() external view returns (address);\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/src/interface/ICrabStrategyV2.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport { IERC20 } from \"openzeppelin/interfaces/IERC20.sol\";\n\ninterface ICrabStrategyV2 is IERC20 {\n    function getVaultDetails() external view returns (address, uint256, uint256, uint256);\n\n    function deposit() external payable;\n\n    function withdraw(uint256 _crabAmount) external;\n\n    function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable;\n\n    function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256);\n\n    function powerTokenController() external view returns (address);\n\n    function weth() external view returns (address);\n\n    function wPowerPerp() external view returns (address);\n\n    function oracle() external view returns (address);\n\n    function ethWSqueethPool() external view returns (address);\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/src/interface/IEulerSimpleLens.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\ninterface IEulerSimpleLens {\n    function getDTokenBalance(address underlying, address account)\n        external\n        view\n        returns (uint256);\n    function getETokenBalance(address underlying, address account)\n        external\n        view\n        returns (uint256);\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/src/interface/IFlashZen.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\ninterface IFlashZen {\n    struct FlashDepositParams {\n        uint256 ethToCrab;\n        uint256 minEthFromSqth;\n        uint256 minEthFromUsdc;\n        uint24 wPowerPerpPoolFee;\n        uint24 usdcPoolFee;\n    }\n\n    function flashDeposit(FlashDepositParams calldata _params) external payable;\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/src/interface/IOracle.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\ninterface IOracle {\n    function getTwap(\n        address _pool,\n        address _base,\n        address _quote,\n        uint32 _period,\n        bool _checkPeriod\n    ) external view returns (uint256);\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/src/interface/IWETH.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\ninterface IWETH is IERC20 {\n    function deposit() external payable;\n\n    function withdraw(uint256 wad) external;\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/src/interface/IZenBullStrategy.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\ninterface IZenBullStrategy is IERC20 {\n    function powerTokenController() external view returns (address);\n    function getCrabBalance() external view returns (uint256);\n    function getCrabVaultDetails() external view returns (uint256, uint256);\n    function crab() external view returns (address);\n    function withdraw(uint256 _bullAmount) external;\n    function deposit(uint256 _crabAmount) external payable;\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/ZenBullNettingBaseSetup.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n// contracts\nimport { SigUtil } from \"./util/SigUtil.sol\";\nimport { ZenBullNetting } from \"../src/ZenBullNetting.sol\";\n//lib\nimport { NettingLib } from \"../src/NettingLib.sol\";\n\n/**\n * ZenBull Netting Setup\n */\ncontract ZenBullNettingBaseSetup is Test {\n    SigUtil internal sigUtil;\n    ZenBullNetting internal zenBullNetting;\n\n    address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n    address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n    address public constant ZEN_BULL = 0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507;\n    address public constant EULER_SIMPLE_LENS = 0x5077B7642abF198b4a5b7C4BdCE4f03016C7089C;\n    address public constant UNI_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\n    address public constant WPOWERPERP = 0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B;\n    address public constant ORACLE = 0x65D66c76447ccB45dAf1e8044e918fA786A483A1;\n    address public constant CRAB = 0x3B960E47784150F5a63777201ee2B15253D713e8;\n    address public constant FLASH_ZEN = 0x11A56a3A7A6Eb768A9125798B1eABE9EBD9EcE02;\n\n    address public ethSqueethPool = 0x82c427AdFDf2d245Ec51D8046b41c4ee87F0d29C;\n    address public ethUsdcPool = 0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8;\n\n    uint256 public deployerPk;\n    uint256 public ownerPk;\n    address public deployer;\n    address public owner;\n\n    function setUp() public virtual {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 16419302);\n\n        deployerPk = 0xA11CD;\n        deployer = vm.addr(deployerPk);\n        ownerPk = 0xB11CD;\n        owner = vm.addr(ownerPk);\n\n        vm.startPrank(deployer);\n        zenBullNetting = new ZenBullNetting(ZEN_BULL, EULER_SIMPLE_LENS, FLASH_ZEN, UNI_FACTORY);\n        zenBullNetting.transferOwnership(owner);\n        sigUtil = new SigUtil(zenBullNetting.DOMAIN_SEPARATOR());\n        vm.stopPrank();\n\n        vm.label(deployer, \"Deployer\");\n        vm.label(owner, \"Owner\");\n        vm.label(address(zenBullNetting), \"ZenBullNetting\");\n    }\n\n    function testDeployment() public {\n        assertEq(zenBullNetting.owner(), owner);\n        assertEq(zenBullNetting.MAX_OTC_PRICE_TOLERANCE(), 2e17);\n        assertEq(zenBullNetting.MIN_AUCTION_TWAP(), 180);\n        assertEq(zenBullNetting.otcPriceTolerance(), 5e16);\n        assertEq(zenBullNetting.auctionTwapPeriod(), 420);\n        assertEq(\n            zenBullNetting.DOMAIN_SEPARATOR(),\n            keccak256(\n                abi.encode(\n                    keccak256(\n                        \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n                    ),\n                    keccak256(bytes(\"ZenBullNetting\")),\n                    keccak256(bytes(\"1\")),\n                    block.chainid,\n                    address(zenBullNetting)\n                )\n            )\n        );\n    }\n\n    function _queueEth(address _user, uint256 _amount) internal {\n        vm.startPrank(_user);\n        zenBullNetting.queueEth{ value: _amount }();\n        vm.stopPrank();\n    }\n\n    function _queueZenBull(address _user, uint256 _amount) internal {\n        vm.startPrank(_user);\n        IERC20(ZEN_BULL).approve(address(zenBullNetting), _amount);\n        zenBullNetting.queueZenBull(_amount);\n        vm.stopPrank();\n    }\n\n    /**\n     * @dev get ZenBull token price using uniswap TWAP\n     * @return ZenBull price\n     */\n    function getZenBullPrice() internal view returns (uint256) {\n        (uint256 crabFairPriceInEth, uint256 ethUsdcPrice) = NettingLib.getCrabPrice(\n            ORACLE,\n            CRAB,\n            ethUsdcPool,\n            ethSqueethPool,\n            WPOWERPERP,\n            USDC,\n            WETH,\n            ZEN_BULL,\n            zenBullNetting.auctionTwapPeriod()\n        );\n\n        return NettingLib.getZenBullPrice(\n            ZEN_BULL, EULER_SIMPLE_LENS, USDC, WETH, crabFairPriceInEth, ethUsdcPrice\n        );\n    }\n\n    function mul(uint256 x, uint256 y) internal pure returns (uint256) {\n        // add(mul(x, y), WAD / 2) / WAD;\n        return ((x * y) + (1e18 / 2)) / 1e18;\n    }\n\n    function div(uint256 x, uint256 y) internal pure returns (uint256) {\n        // add(mul(x, WAD), y / 2) / y;\n        return ((x * 1e18) + (y / 2)) / y;\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/fuzzing/ZenBullNetting/DepositAuctionFuzzing.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../../ZenBullNettingBaseSetup.t.sol\";\n// interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IZenBullStrategy } from \"../../../src/interface/IZenBullStrategy.sol\";\nimport { IOracle } from \"../../../src/interface/IOracle.sol\";\nimport { IEulerSimpleLens } from \"../../../src/interface/IEulerSimpleLens.sol\";\nimport { IWETH } from \"../../../src/interface/IWETH.sol\";\n// contract\nimport { SigUtil } from \"../../util/SigUtil.sol\";\nimport { ZenBullNetting } from \"../../../src/ZenBullNetting.sol\";\n\ncontract DepositAuctionFuzzing is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n    uint256 public user2Pk;\n    address public user2;\n    uint256 public mm1Pk;\n    address public mm1;\n    uint256 public mm2Pk;\n    address public mm2;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 1e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        vm.startPrank(owner);\n        zenBullNetting.setMinEthAmount(minWeth);\n        zenBullNetting.setMinZenBullAmount(minZenBull);\n        vm.stopPrank();\n\n        (user1, user1Pk) = makeAddrAndKey(\"User1\");\n        (user2, user2Pk) = makeAddrAndKey(\"User2\");\n        (mm1, mm1Pk) = makeAddrAndKey(\"MM1\");\n        (mm2, mm2Pk) = makeAddrAndKey(\"MM2\");\n\n        vm.deal(user1, 5000e18);\n        vm.deal(user2, 5000e18);\n        vm.deal(mm1, 5000e18);\n        vm.deal(mm2, 5000e18);\n\n        vm.prank(mm1);\n        IWETH(WETH).deposit{ value: 5000e18 }();\n        vm.prank(mm2);\n        IWETH(WETH).deposit{ value: 5000e18 }();\n\n        // update ZenBull cap to 100000 ETH\n        vm.store(ZEN_BULL, bytes32(uint256(9)), bytes32(uint256(100000e18)));\n    }\n\n    function _calAuctionCrabAmount(uint256 _depositToProcess) internal view returns (uint256) {\n        uint256 ethUsdPrice = IOracle(ORACLE).getTwap(ethUsdcPool, WETH, USDC, 420, false);\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        (uint256 crabCollateral, uint256 crabDebt) =\n            IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 crabUsdPrice = (\n            crabCollateral * ethUsdPrice / 1e18 - (crabDebt * squeethEthPrice * ethUsdPrice / 1e36)\n        ) * 1e18 / IERC20(CRAB).totalSupply();\n        uint256 bullEquityValue = (\n            IZenBullStrategy(ZEN_BULL).getCrabBalance() * crabUsdPrice / 1e18\n        )\n            + (\n                IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL) * ethUsdPrice\n                    / 1e18\n            ) - (IEulerSimpleLens(EULER_SIMPLE_LENS).getDTokenBalance(USDC, ZEN_BULL) * 1e12);\n        uint256 expectBullAmount = _depositToProcess * ethUsdPrice * 99e16 / 1e18 / bullEquityValue\n            * IZenBullStrategy(ZEN_BULL).totalSupply() / 1e18;\n\n        return expectBullAmount * 1e18 / IZenBullStrategy(ZEN_BULL).totalSupply()\n            * IZenBullStrategy(ZEN_BULL).getCrabBalance() / 1e18;\n    }\n\n    function testFuzzingDepositAuction(uint256 _amount) public {\n        _amount = bound(_amount, zenBullNetting.minEthAmount(), uint256(1000e18));\n        _queueEth(user1, _amount);\n\n        uint256 crabAmount = _calAuctionCrabAmount(_amount);\n        uint256 crabTotalSupply = IERC20(CRAB).totalSupply();\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount = crabAmount * crabDebt / crabTotalSupply;\n\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.DepositAuctionParams memory params = ZenBullNetting.DepositAuctionParams({\n            depositsToProcess: _amount,\n            crabAmount: crabAmount,\n            orders: orders,\n            clearingPrice: squeethEthPrice * 99e16 / 1e18,\n            flashDepositEthToCrab: 0,\n            flashDepositMinEthFromSqth: 0,\n            flashDepositMinEthFromUsdc: 0,\n            flashDepositWPowerPerpPoolFee: 3000,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WETH).approve(address(zenBullNetting), oSqthAmount * params.clearingPrice / 1e18);\n\n        vm.startPrank(owner);\n        zenBullNetting.depositAuction(params);\n        vm.stopPrank();\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/integration-test/ZenBullNetting/DepositAuction.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../../ZenBullNettingBaseSetup.t.sol\";\n// interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IZenBullStrategy } from \"../../../src/interface/IZenBullStrategy.sol\";\nimport { IOracle } from \"../../../src/interface/IOracle.sol\";\nimport { IEulerSimpleLens } from \"../../../src/interface/IEulerSimpleLens.sol\";\nimport { IWETH } from \"../../../src/interface/IWETH.sol\";\n// contract\nimport { SigUtil } from \"../../util/SigUtil.sol\";\nimport { ZenBullNetting } from \"../../../src/ZenBullNetting.sol\";\n\ncontract DepositAuction is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n    uint256 public user2Pk;\n    address public user2;\n    uint256 public mm1Pk;\n    address public mm1;\n    uint256 public mm2Pk;\n    address public mm2;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 1e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        vm.startPrank(owner);\n        zenBullNetting.setMinEthAmount(minWeth);\n        zenBullNetting.setMinZenBullAmount(minZenBull);\n        vm.stopPrank();\n\n        (user1, user1Pk) = makeAddrAndKey(\"User1\");\n        (user2, user2Pk) = makeAddrAndKey(\"User2\");\n        (mm1, mm1Pk) = makeAddrAndKey(\"MM1\");\n        (mm2, mm2Pk) = makeAddrAndKey(\"MM2\");\n\n        vm.deal(user1, 5000e18);\n        vm.deal(user2, 5000e18);\n        vm.deal(mm1, 5000e18);\n        vm.deal(mm2, 5000e18);\n\n        vm.prank(mm1);\n        IWETH(WETH).deposit{ value: 1000e18 }();\n        vm.prank(mm2);\n        IWETH(WETH).deposit{ value: 1000e18 }();\n    }\n\n    function _calAuctionCrabAmount(uint256 _depositToProcess) internal view returns (uint256) {\n        uint256 ethUsdPrice = IOracle(ORACLE).getTwap(ethUsdcPool, WETH, USDC, 420, false);\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        (uint256 crabCollateral, uint256 crabDebt) =\n            IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 crabUsdPrice = (\n            crabCollateral * ethUsdPrice / 1e18 - (crabDebt * squeethEthPrice * ethUsdPrice / 1e36)\n        ) * 1e18 / IERC20(CRAB).totalSupply();\n        uint256 bullEquityValue = (\n            IZenBullStrategy(ZEN_BULL).getCrabBalance() * crabUsdPrice / 1e18\n        )\n            + (\n                IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL) * ethUsdPrice\n                    / 1e18\n            ) - (IEulerSimpleLens(EULER_SIMPLE_LENS).getDTokenBalance(USDC, ZEN_BULL) * 1e12);\n        uint256 expectBullAmount = _depositToProcess * ethUsdPrice * 99e16 / 1e18 / bullEquityValue\n            * IZenBullStrategy(ZEN_BULL).totalSupply() / 1e18;\n\n        return expectBullAmount * 1e18 / IZenBullStrategy(ZEN_BULL).totalSupply()\n            * IZenBullStrategy(ZEN_BULL).getCrabBalance() / 1e18;\n    }\n\n    function testFullDepositAuction() public {\n        uint256 amount = 10e18;\n        _queueEth(user1, amount);\n\n        uint256 crabAmount = _calAuctionCrabAmount(amount);\n        uint256 crabTotalSupply = IERC20(CRAB).totalSupply();\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount = crabAmount * crabDebt / crabTotalSupply;\n\n        uint256 share =\n            crabAmount * 1e18 / (IZenBullStrategy(ZEN_BULL).getCrabBalance() + crabAmount);\n        uint256 bullTotalSupply = IERC20(ZEN_BULL).totalSupply();\n        uint256 bullToMint = share * bullTotalSupply / (1e18 - share);\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.DepositAuctionParams memory params = ZenBullNetting.DepositAuctionParams({\n            depositsToProcess: amount,\n            crabAmount: crabAmount,\n            orders: orders,\n            clearingPrice: squeethEthPrice * 99e16 / 1e18,\n            // flashDepositEthToCrab: 18e15,\n            flashDepositEthToCrab: 0,\n            flashDepositMinEthFromSqth: 0,\n            flashDepositMinEthFromUsdc: 0,\n            flashDepositWPowerPerpPoolFee: 3000,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WETH).approve(address(zenBullNetting), oSqthAmount * params.clearingPrice / 1e18);\n\n        uint256 mm1WpowerPerpBalanceBefore = IERC20(WPOWERPERP).balanceOf(mm1);\n        uint256 wPowerPerpTotalSupplyBefore = IERC20(WPOWERPERP).totalSupply();\n        uint256 user1EthBalanceBefore = user1.balance;\n        uint256 wethInEulerBefore =\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL);\n        uint256 wethToLend = bullToMint * wethInEulerBefore / bullTotalSupply;\n\n        vm.startPrank(owner);\n        zenBullNetting.depositAuction(params);\n        vm.stopPrank();\n\n        uint256 wPowerPerpTotalSupplyAfter = IERC20(WPOWERPERP).totalSupply();\n\n        assertEq(\n            IERC20(WPOWERPERP).balanceOf(mm1) - mm1WpowerPerpBalanceBefore,\n            wPowerPerpTotalSupplyAfter - wPowerPerpTotalSupplyBefore\n        );\n        assertGt(user1.balance, user1EthBalanceBefore);\n        assertApproxEqAbs(\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL) - wethInEulerBefore,\n            wethToLend,\n            2000\n        );\n    }\n\n    function testPartialDepositAuction() public {\n        uint256 amount = 10e18;\n        _queueEth(user1, amount * 2);\n\n        uint256 crabAmount = _calAuctionCrabAmount(amount);\n        uint256 crabTotalSupply = IERC20(CRAB).totalSupply();\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount = crabAmount * crabDebt / crabTotalSupply;\n\n        uint256 share =\n            crabAmount * 1e18 / (IZenBullStrategy(ZEN_BULL).getCrabBalance() + crabAmount);\n        uint256 bullTotalSupply = IERC20(ZEN_BULL).totalSupply();\n        uint256 bullToMint = share * bullTotalSupply / (1e18 - share);\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.DepositAuctionParams memory params = ZenBullNetting.DepositAuctionParams({\n            depositsToProcess: amount,\n            crabAmount: crabAmount,\n            orders: orders,\n            clearingPrice: squeethEthPrice * 99e16 / 1e18,\n            // flashDepositEthToCrab: 18e15,\n            flashDepositEthToCrab: 0,\n            flashDepositMinEthFromSqth: 0,\n            flashDepositMinEthFromUsdc: 0,\n            flashDepositWPowerPerpPoolFee: 3000,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WETH).approve(address(zenBullNetting), oSqthAmount * params.clearingPrice / 1e18);\n\n        uint256 mm1WpowerPerpBalanceBefore = IERC20(WPOWERPERP).balanceOf(mm1);\n        uint256 wPowerPerpTotalSupplyBefore = IERC20(WPOWERPERP).totalSupply();\n        uint256 user1EthBalanceBefore = user1.balance;\n        uint256 wethInEulerBefore =\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL);\n        uint256 wethToLend = bullToMint * wethInEulerBefore / bullTotalSupply;\n\n        vm.startPrank(owner);\n        zenBullNetting.depositAuction(params);\n        vm.stopPrank();\n\n        uint256 wPowerPerpTotalSupplyAfter = IERC20(WPOWERPERP).totalSupply();\n\n        assertEq(\n            IERC20(WPOWERPERP).balanceOf(mm1) - mm1WpowerPerpBalanceBefore,\n            wPowerPerpTotalSupplyAfter - wPowerPerpTotalSupplyBefore\n        );\n        assertGt(user1.balance, user1EthBalanceBefore);\n        assertApproxEqAbs(\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL) - wethInEulerBefore,\n            wethToLend,\n            2000\n        );\n    }\n\n    function testDepositAuctionWithMultipleOrders() public {\n        uint256 amount = 10e18;\n        _queueEth(user1, amount);\n\n        uint256 crabAmount = _calAuctionCrabAmount(amount);\n        uint256 crabTotalSupply = IERC20(CRAB).totalSupply();\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount = crabAmount * crabDebt / crabTotalSupply;\n        uint256 share =\n            crabAmount * 1e18 / (IZenBullStrategy(ZEN_BULL).getCrabBalance() + crabAmount);\n        uint256 bullTotalSupply = IERC20(ZEN_BULL).totalSupply();\n        uint256 bullToMint = share * bullTotalSupply / (1e18 - share);\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](2);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount / 2,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount / 2,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n\n            // trader signing bid\n            orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm2,\n                quantity: oSqthAmount / 2 + 1,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm2Pk, bidDigest);\n            orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm2,\n                quantity: oSqthAmount / 2 + 1,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[1] = orderData;\n        }\n\n        ZenBullNetting.DepositAuctionParams memory params = ZenBullNetting.DepositAuctionParams({\n            depositsToProcess: amount,\n            crabAmount: crabAmount,\n            orders: orders,\n            clearingPrice: squeethEthPrice * 99e16 / 1e18,\n            flashDepositEthToCrab: 0,\n            flashDepositMinEthFromSqth: 0,\n            flashDepositMinEthFromUsdc: 0,\n            flashDepositWPowerPerpPoolFee: 3000,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WETH).approve(\n            address(zenBullNetting), (oSqthAmount / 2) * params.clearingPrice / 1e18\n        );\n        vm.prank(mm2);\n        IERC20(WETH).approve(\n            address(zenBullNetting), (oSqthAmount / 2) * params.clearingPrice / 1e18\n        );\n\n        uint256 mm1WpowerPerpBalanceBefore = IERC20(WPOWERPERP).balanceOf(mm1);\n        uint256 wPowerPerpTotalSupplyBefore = IERC20(WPOWERPERP).totalSupply();\n        uint256 user1EthBalanceBefore = user1.balance;\n        uint256 wethInEulerBefore =\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL);\n        uint256 wethToLend = bullToMint * wethInEulerBefore / bullTotalSupply;\n\n        vm.startPrank(owner);\n        zenBullNetting.depositAuction(params);\n        vm.stopPrank();\n\n        uint256 wPowerPerpTotalSupplyAfter = IERC20(WPOWERPERP).totalSupply();\n\n        assertEq(IERC20(WPOWERPERP).balanceOf(mm1) - mm1WpowerPerpBalanceBefore, oSqthAmount / 2);\n        assertEq(\n            IERC20(WPOWERPERP).balanceOf(mm2) - mm1WpowerPerpBalanceBefore,\n            wPowerPerpTotalSupplyAfter - wPowerPerpTotalSupplyBefore - oSqthAmount / 2\n        );\n        assertGt(user1.balance, user1EthBalanceBefore);\n        assertApproxEqAbs(\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL) - wethInEulerBefore,\n            wethToLend,\n            2000\n        );\n    }\n\n    function testDepositAuctionWhenOrderIsSelling() public {\n        uint256 amount = 10e18;\n        _queueEth(user1, amount);\n\n        uint256 crabAmount = _calAuctionCrabAmount(amount);\n        uint256 crabTotalSupply = IERC20(CRAB).totalSupply();\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount = crabAmount * crabDebt / crabTotalSupply;\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.DepositAuctionParams memory params = ZenBullNetting.DepositAuctionParams({\n            depositsToProcess: amount,\n            crabAmount: crabAmount,\n            orders: orders,\n            clearingPrice: squeethEthPrice * 99e16 / 1e18,\n            flashDepositEthToCrab: 0,\n            flashDepositMinEthFromSqth: 0,\n            flashDepositMinEthFromUsdc: 0,\n            flashDepositWPowerPerpPoolFee: 3000,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WETH).approve(address(zenBullNetting), oSqthAmount * params.clearingPrice / 1e18);\n\n        vm.startPrank(owner);\n        vm.expectRevert(bytes(\"ZBN21\"));\n        zenBullNetting.depositAuction(params);\n        vm.stopPrank();\n    }\n\n    function testDepositAuctionWhenPricerLessThanClearingPrice() public {\n        uint256 amount = 10e18;\n        _queueEth(user1, amount);\n\n        uint256 crabAmount = _calAuctionCrabAmount(amount);\n        uint256 crabTotalSupply = IERC20(CRAB).totalSupply();\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount = crabAmount * crabDebt / crabTotalSupply;\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n\n        uint256 clearingPrice = squeethEthPrice * 99e16 / 1e18;\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: clearingPrice - 1,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: clearingPrice - 1,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.DepositAuctionParams memory params = ZenBullNetting.DepositAuctionParams({\n            depositsToProcess: amount,\n            crabAmount: crabAmount,\n            orders: orders,\n            clearingPrice: clearingPrice,\n            flashDepositEthToCrab: 0,\n            flashDepositMinEthFromSqth: 0,\n            flashDepositMinEthFromUsdc: 0,\n            flashDepositWPowerPerpPoolFee: 3000,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WETH).approve(address(zenBullNetting), oSqthAmount * params.clearingPrice / 1e18);\n\n        vm.startPrank(owner);\n        vm.expectRevert(bytes(\"ZBN22\"));\n        zenBullNetting.depositAuction(params);\n        vm.stopPrank();\n    }\n\n    function testDepositAuctionWhenOrderOsqthAmountIsNotEnough() public {\n        uint256 amount = 10e18;\n        _queueEth(user1, amount);\n\n        uint256 crabAmount = _calAuctionCrabAmount(amount);\n        uint256 crabTotalSupply = IERC20(CRAB).totalSupply();\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount = crabAmount * crabDebt / crabTotalSupply;\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n\n        uint256 clearingPrice = squeethEthPrice * 99e16 / 1e18;\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount - 100,\n                price: clearingPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount - 100,\n                price: clearingPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.DepositAuctionParams memory params = ZenBullNetting.DepositAuctionParams({\n            depositsToProcess: amount,\n            crabAmount: crabAmount,\n            orders: orders,\n            clearingPrice: clearingPrice,\n            flashDepositEthToCrab: 0,\n            flashDepositMinEthFromSqth: 0,\n            flashDepositMinEthFromUsdc: 0,\n            flashDepositWPowerPerpPoolFee: 3000,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WETH).approve(\n            address(zenBullNetting), (oSqthAmount - 100) * params.clearingPrice / 1e18\n        );\n\n        vm.startPrank(owner);\n        vm.expectRevert(bytes(\"ZBN23\"));\n        zenBullNetting.depositAuction(params);\n        vm.stopPrank();\n    }\n\n    function testDepositAuctionWhenPriceIsLessThanTolerance() public {\n        uint256 amount = 10e18;\n        _queueEth(user1, amount);\n\n        uint256 crabAmount = _calAuctionCrabAmount(amount);\n        uint256 crabTotalSupply = IERC20(CRAB).totalSupply();\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount = crabAmount * crabDebt / crabTotalSupply;\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.DepositAuctionParams memory params = ZenBullNetting.DepositAuctionParams({\n            depositsToProcess: amount,\n            crabAmount: crabAmount,\n            orders: orders,\n            // clearingPrice: squeethEthPrice * 99e16 / 1e18,\n            clearingPrice: ((squeethEthPrice * (1e18 - zenBullNetting.otcPriceTolerance())) / 1e18) - 1,\n            flashDepositEthToCrab: 0,\n            flashDepositMinEthFromSqth: 0,\n            flashDepositMinEthFromUsdc: 0,\n            flashDepositWPowerPerpPoolFee: 3000,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WETH).approve(address(zenBullNetting), oSqthAmount * params.clearingPrice / 1e18);\n\n        vm.startPrank(owner);\n        vm.expectRevert(bytes(\"ZBN15\"));\n        zenBullNetting.depositAuction(params);\n        vm.stopPrank();\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/integration-test/ZenBullNetting/DequeueEth.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\ncontract DequeueEth is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n    uint256 public user2Pk;\n    address public user2;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 1e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        vm.startPrank(owner);\n        zenBullNetting.setMinEthAmount(minWeth);\n        zenBullNetting.setMinZenBullAmount(minZenBull);\n        vm.stopPrank();\n\n        (user1, user1Pk) = makeAddrAndKey(\"User1\");\n        (user2, user2Pk) = makeAddrAndKey(\"User2\");\n\n        vm.deal(user1, 5000e18);\n        vm.deal(user2, 5000e18);\n    }\n\n    function testDequeueEth() public {\n        uint256 amount = 100e18;\n        _queueEth(user1, amount);\n\n        uint256 user1EthBalanceBefore = user1.balance;\n        uint256 zenBullNettingEthBalanceBefore = address(zenBullNetting).balance;\n\n        vm.startPrank(user1);\n        zenBullNetting.dequeueEth(amount, false);\n        vm.stopPrank();\n\n        assertEq(user1EthBalanceBefore + amount, user1.balance);\n        assertEq(zenBullNettingEthBalanceBefore - amount, address(zenBullNetting).balance);\n    }\n\n    function testDequeueEthPartial() public {\n        uint256 amountToQueue = 100e18;\n        _queueEth(user1, amountToQueue);\n\n        uint256 user1EthBalanceBefore = user1.balance;\n        uint256 zenBullNettingEthBalanceBefore = address(zenBullNetting).balance;\n        uint256 amountToDequeue = amountToQueue / 2;\n\n        vm.startPrank(user1);\n        zenBullNetting.dequeueEth(amountToDequeue, false);\n        vm.stopPrank();\n\n        (address sender, uint256 amount,) = zenBullNetting.getDepositReceipt(0);\n\n        assertEq(user1EthBalanceBefore + amountToDequeue, user1.balance);\n        assertEq(zenBullNettingEthBalanceBefore - amountToDequeue, address(zenBullNetting).balance);\n        assertEq(sender, user1);\n        assertEq(amount, amountToQueue - amountToDequeue);\n    }\n\n    function testDequeueEthWhenAuctionIsLive() public {\n        uint256 amount = 100e18;\n        _queueEth(user1, amount);\n\n        vm.prank(owner);\n        zenBullNetting.toggleAuctionLive();\n        assertEq(zenBullNetting.isAuctionLive(), true);\n\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"ZBN04\"));\n        zenBullNetting.dequeueEth(amount, false);\n        vm.stopPrank();\n    }\n\n    function testForceDequeueEthWhenAuctionIsLiveAndTimeLessThanOneWeek() public {\n        uint256 amount = 100e18;\n        _queueEth(user1, amount);\n\n        vm.prank(owner);\n        zenBullNetting.toggleAuctionLive();\n        assertEq(zenBullNetting.isAuctionLive(), true);\n\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"ZBN06\"));\n        zenBullNetting.dequeueEth(amount, true);\n        vm.stopPrank();\n    }\n\n    function testDequeueEthForceWhenAuctionIsLiveAndTimeMoreThanOneWeek() public {\n        uint256 amountToQueue = 100e18;\n        _queueEth(user1, amountToQueue);\n\n        uint256 user1EthBalanceBefore = user1.balance;\n        uint256 zenBullNettingEthBalanceBefore = address(zenBullNetting).balance;\n\n        vm.prank(owner);\n        zenBullNetting.toggleAuctionLive();\n        assertEq(zenBullNetting.isAuctionLive(), true);\n\n        (,, uint256 receiptTimestamp) = zenBullNetting.getDepositReceipt(0);\n\n        vm.warp(receiptTimestamp + 1.1 weeks);\n\n        vm.startPrank(user1);\n        zenBullNetting.dequeueEth(amountToQueue, true);\n        vm.stopPrank();\n\n        assertEq(user1EthBalanceBefore + amountToQueue, user1.balance);\n        assertEq(zenBullNettingEthBalanceBefore - amountToQueue, address(zenBullNetting).balance);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/integration-test/ZenBullNetting/DequeueZenBull.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\ncontract DequeueZenBull is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n    uint256 public user2Pk;\n    address public user2;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 1e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        vm.startPrank(owner);\n        zenBullNetting.setMinEthAmount(minWeth);\n        zenBullNetting.setMinZenBullAmount(minZenBull);\n        vm.stopPrank();\n\n        (user1, user1Pk) = makeAddrAndKey(\"User1\");\n        (user2, user2Pk) = makeAddrAndKey(\"User2\");\n\n        // some ZenBUll rich address\n        vm.startPrank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 15e18);\n        IERC20(ZEN_BULL).transfer(user2, 15e18);\n        vm.stopPrank();\n    }\n\n    function testDequeueZenBull() public {\n        uint256 amount = 10e18;\n        _queueZenBull(user1, amount);\n\n        uint256 user1ZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 zenBullNettingZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(address(zenBullNetting));\n\n        vm.startPrank(user1);\n        zenBullNetting.dequeueZenBull(amount, false);\n        vm.stopPrank();\n\n        assertEq(user1ZenBalanceBefore + amount, IERC20(ZEN_BULL).balanceOf(user1));\n        assertEq(\n            zenBullNettingZenBalanceBefore - amount,\n            IERC20(ZEN_BULL).balanceOf(address(zenBullNetting))\n        );\n    }\n\n    function testDequeueZenBullPartial() public {\n        uint256 amountToQueue = 10e18;\n        _queueZenBull(user1, amountToQueue);\n\n        uint256 user1ZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 zenBullNettingZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(address(zenBullNetting));\n        uint256 amountToDequeue = amountToQueue / 2;\n\n        vm.startPrank(user1);\n        zenBullNetting.dequeueZenBull(amountToDequeue, false);\n        vm.stopPrank();\n\n        (address sender, uint256 amount,) = zenBullNetting.getWithdrawReceipt(0);\n\n        assertEq(user1ZenBalanceBefore + amountToDequeue, IERC20(ZEN_BULL).balanceOf(user1));\n        assertEq(\n            zenBullNettingZenBalanceBefore - amountToDequeue,\n            IERC20(ZEN_BULL).balanceOf(address(zenBullNetting))\n        );\n        assertEq(sender, user1);\n        assertEq(amount, amountToQueue - amountToDequeue);\n    }\n\n    function testDequeueZenBullPartialWhenRemainingLessThanMin() public {\n        uint256 amountToQueue = 10e18;\n        _queueZenBull(user1, amountToQueue);\n\n        uint256 amountToDequeue = amountToQueue - zenBullNetting.minZenBullAmount() + 1;\n\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"ZBN08\"));\n        zenBullNetting.dequeueZenBull(amountToDequeue, false);\n        vm.stopPrank();\n    }\n\n    function testDequeueZenBullWhenAuctionIsLive() public {\n        uint256 amount = 10e18;\n        _queueZenBull(user1, amount);\n\n        vm.prank(owner);\n        zenBullNetting.toggleAuctionLive();\n        assertEq(zenBullNetting.isAuctionLive(), true);\n\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"ZBN04\"));\n        zenBullNetting.dequeueZenBull(amount, false);\n        vm.stopPrank();\n    }\n\n    function testForceDequeueZenBullWhenAuctionIsLiveAndTimeLessThanOneWeek() public {\n        uint256 amount = 10e18;\n        _queueZenBull(user1, amount);\n\n        vm.prank(owner);\n        zenBullNetting.toggleAuctionLive();\n        assertEq(zenBullNetting.isAuctionLive(), true);\n\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"ZBN09\"));\n        zenBullNetting.dequeueZenBull(amount, true);\n        vm.stopPrank();\n    }\n\n    function testForceDequeueZenBullWhenAuctionIsLiveAndTimeMoreThanOneWeek() public {\n        uint256 amountToQueue = 10e18;\n        _queueZenBull(user1, amountToQueue);\n\n        uint256 user1ZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 zenBullNettingZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(address(zenBullNetting));\n\n        vm.prank(owner);\n        zenBullNetting.toggleAuctionLive();\n        assertEq(zenBullNetting.isAuctionLive(), true);\n\n        (,, uint256 receiptTimestamp) = zenBullNetting.getWithdrawReceipt(0);\n\n        vm.warp(receiptTimestamp + 1.1 weeks);\n\n        vm.startPrank(user1);\n        zenBullNetting.dequeueZenBull(amountToQueue, true);\n        vm.stopPrank();\n\n        assertEq(user1ZenBalanceBefore + amountToQueue, IERC20(ZEN_BULL).balanceOf(user1));\n        assertEq(\n            zenBullNettingZenBalanceBefore - amountToQueue,\n            IERC20(ZEN_BULL).balanceOf(address(zenBullNetting))\n        );\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/integration-test/ZenBullNetting/NetAtPrice.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\ncontract NetAtPrice is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n    uint256 public user2Pk;\n    address public user2;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 1e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        vm.startPrank(owner);\n        zenBullNetting.setMinEthAmount(minWeth);\n        zenBullNetting.setMinZenBullAmount(minZenBull);\n        // zenBullNetting.setOTCPriceTolerance(2e16);\n        vm.stopPrank();\n\n        (user1, user1Pk) = makeAddrAndKey(\"User1\");\n        (user2, user2Pk) = makeAddrAndKey(\"User2\");\n\n        vm.deal(user1, 5000e18);\n        vm.deal(user2, 5000e18);\n        // some ZenBUll rich address\n        vm.startPrank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 15e18);\n        IERC20(ZEN_BULL).transfer(user2, 15e18);\n        vm.stopPrank();\n    }\n\n    function testNetAtPrice() public {\n        uint256 ethToQueue = 10e18;\n        uint256 zenBullFairPrice = getZenBullPrice();\n        uint256 zenBullToQueue = ethToQueue * 1e18 / zenBullFairPrice;\n\n        _queueEth(user1, ethToQueue);\n        _queueZenBull(user2, zenBullToQueue);\n\n        (, uint256 depReceiptAmountBefore,) = zenBullNetting.getDepositReceipt(0);\n        (, uint256 withReceiptAmountBefore,) = zenBullNetting.getWithdrawReceipt(0);\n\n        uint256 user1ZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 user2EthBalanceBefore = user2.balance;\n        uint256 zenBullNettingEthBalanceBefore = address(zenBullNetting).balance;\n        uint256 zenBullNettingZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(address(zenBullNetting));\n\n        vm.prank(owner);\n        zenBullNetting.netAtPrice(zenBullFairPrice, ethToQueue);\n\n        (, uint256 depReceiptAmountAfter,) = zenBullNetting.getDepositReceipt(0);\n        (, uint256 withReceiptAmountAfter,) = zenBullNetting.getWithdrawReceipt(0);\n\n        assertEq(\n            IERC20(ZEN_BULL).balanceOf(address(zenBullNetting)) + zenBullToQueue,\n            zenBullNettingZenBalanceBefore\n        );\n        assertApproxEqAbs(\n            address(zenBullNetting).balance + ethToQueue, zenBullNettingEthBalanceBefore, 2\n        );\n        assertEq(IERC20(ZEN_BULL).balanceOf(user1) - user1ZenBalanceBefore, zenBullToQueue);\n        assertApproxEqAbs(user2.balance - ethToQueue, user2EthBalanceBefore, 2);\n        assertEq(withReceiptAmountBefore - zenBullToQueue, withReceiptAmountAfter);\n        assertEq(depReceiptAmountBefore - ethToQueue, depReceiptAmountAfter);\n    }\n\n    function testNetAtPriceWhenCallerIsBot() public {\n        uint256 botPk;\n        address bot;\n        (bot, botPk) = makeAddrAndKey(\"Bot\");\n\n        vm.prank(owner);\n        zenBullNetting.setBot(bot);\n\n        uint256 ethToQueue = 10e18;\n        uint256 zenBullFairPrice = getZenBullPrice();\n        uint256 zenBullToQueue = ethToQueue * 1e18 / zenBullFairPrice;\n\n        _queueEth(user1, ethToQueue);\n        _queueZenBull(user2, zenBullToQueue);\n\n        (, uint256 depReceiptAmountBefore,) = zenBullNetting.getDepositReceipt(0);\n        (, uint256 withReceiptAmountBefore,) = zenBullNetting.getWithdrawReceipt(0);\n\n        uint256 user1ZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 user2EthBalanceBefore = user2.balance;\n        uint256 zenBullNettingEthBalanceBefore = address(zenBullNetting).balance;\n        uint256 zenBullNettingZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(address(zenBullNetting));\n\n        vm.prank(bot);\n        zenBullNetting.netAtPrice(zenBullFairPrice, ethToQueue);\n\n        (, uint256 depReceiptAmountAfter,) = zenBullNetting.getDepositReceipt(0);\n        (, uint256 withReceiptAmountAfter,) = zenBullNetting.getWithdrawReceipt(0);\n\n        assertEq(\n            IERC20(ZEN_BULL).balanceOf(address(zenBullNetting)) + zenBullToQueue,\n            zenBullNettingZenBalanceBefore\n        );\n        assertApproxEqAbs(\n            address(zenBullNetting).balance + ethToQueue, zenBullNettingEthBalanceBefore, 2\n        );\n        assertEq(IERC20(ZEN_BULL).balanceOf(user1) - user1ZenBalanceBefore, zenBullToQueue);\n        assertApproxEqAbs(user2.balance - ethToQueue, user2EthBalanceBefore, 2);\n        assertEq(withReceiptAmountBefore - zenBullToQueue, withReceiptAmountAfter);\n        assertEq(depReceiptAmountBefore - ethToQueue, depReceiptAmountAfter);\n        assertEq(zenBullNetting.bot(), bot);\n    }\n\n    function testNetAtPriceWhenZenAmountGreaterThanQueued() public {\n        uint256 ethToQueue = 10e18;\n        uint256 zenBullFairPrice = getZenBullPrice();\n        uint256 zenBullToQueue = ethToQueue * 1e18 / zenBullFairPrice - 1;\n\n        _queueEth(user1, ethToQueue);\n        _queueZenBull(user2, zenBullToQueue);\n\n        vm.prank(owner);\n        vm.expectRevert(bytes(\"ZBN11\"));\n        zenBullNetting.netAtPrice(zenBullFairPrice, ethToQueue);\n    }\n\n    function testNetAtPriceWhenEthAmountGreaterThanQueued() public {\n        uint256 ethToQueue = 10e18;\n        uint256 zenBullFairPrice = getZenBullPrice();\n        uint256 zenBullToQueue = ethToQueue * 1e18 / zenBullFairPrice;\n\n        _queueEth(user1, ethToQueue - 1);\n        _queueZenBull(user2, zenBullToQueue);\n\n        vm.prank(owner);\n        vm.expectRevert(bytes(\"ZBN10\"));\n        zenBullNetting.netAtPrice(zenBullFairPrice, ethToQueue);\n    }\n\n    function testNetAtPricePartially() public {\n        uint256 ethToQueue = 10e18;\n        uint256 zenBullFairPrice = getZenBullPrice();\n        uint256 zenBullToQueue = ethToQueue * 1e18 / zenBullFairPrice;\n\n        _queueEth(user1, ethToQueue);\n        _queueZenBull(user2, zenBullToQueue);\n\n        (, uint256 depReceiptAmountBefore,) = zenBullNetting.getDepositReceipt(0);\n        (, uint256 withReceiptAmountBefore,) = zenBullNetting.getWithdrawReceipt(0);\n\n        uint256 user1ZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 user2EthBalanceBefore = user2.balance;\n        uint256 zenBullNettingEthBalanceBefore = address(zenBullNetting).balance;\n        uint256 zenBullNettingZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(address(zenBullNetting));\n\n        uint256 ethToNet = ethToQueue / 2;\n        uint256 zenBullToNet = ethToNet * 1e18 / zenBullFairPrice;\n        vm.prank(owner);\n        zenBullNetting.netAtPrice(zenBullFairPrice, ethToNet);\n\n        (, uint256 depReceiptAmountAfter,) = zenBullNetting.getDepositReceipt(0);\n        (, uint256 withReceiptAmountAfter,) = zenBullNetting.getWithdrawReceipt(0);\n\n        assertEq(\n            IERC20(ZEN_BULL).balanceOf(address(zenBullNetting)) + zenBullToNet,\n            zenBullNettingZenBalanceBefore\n        );\n        assertApproxEqAbs(\n            address(zenBullNetting).balance + ethToNet, zenBullNettingEthBalanceBefore, 2\n        );\n        assertEq(IERC20(ZEN_BULL).balanceOf(user1) - user1ZenBalanceBefore, zenBullToNet);\n        assertEq(IERC20(ZEN_BULL).balanceOf(user1) - user1ZenBalanceBefore, zenBullToNet);\n        assertApproxEqAbs(user2.balance - ethToNet, user2EthBalanceBefore, 2);\n        assertEq(withReceiptAmountBefore - zenBullToNet, withReceiptAmountAfter);\n        assertEq(depReceiptAmountBefore - ethToNet, depReceiptAmountAfter);\n    }\n\n    function testNetAtPriceWithEmptyDepositReceipt() public {\n        uint256 ethToQueue = 10e18;\n        uint256 zenBullFairPrice = getZenBullPrice();\n        uint256 zenBullToQueue = ethToQueue * 1e18 / zenBullFairPrice;\n\n        _queueEth(user1, ethToQueue);\n        vm.prank(user1);\n        zenBullNetting.dequeueEth(ethToQueue, false);\n\n        _queueEth(user1, ethToQueue);\n        _queueZenBull(user2, zenBullToQueue);\n\n        (, uint256 depReceiptAmountBefore,) = zenBullNetting.getDepositReceipt(1);\n        (, uint256 withReceiptAmountBefore,) = zenBullNetting.getWithdrawReceipt(0);\n\n        uint256 user1ZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 user2EthBalanceBefore = user2.balance;\n        uint256 zenBullNettingEthBalanceBefore = address(zenBullNetting).balance;\n        uint256 zenBullNettingZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(address(zenBullNetting));\n\n        vm.prank(owner);\n        zenBullNetting.netAtPrice(zenBullFairPrice, ethToQueue);\n\n        (, uint256 depReceiptAmountAfter,) = zenBullNetting.getDepositReceipt(0);\n        (, uint256 withReceiptAmountAfter,) = zenBullNetting.getWithdrawReceipt(0);\n\n        assertEq(\n            IERC20(ZEN_BULL).balanceOf(address(zenBullNetting)) + zenBullToQueue,\n            zenBullNettingZenBalanceBefore\n        );\n        assertApproxEqAbs(\n            address(zenBullNetting).balance + ethToQueue, zenBullNettingEthBalanceBefore, 2\n        );\n        assertEq(IERC20(ZEN_BULL).balanceOf(user1) - user1ZenBalanceBefore, zenBullToQueue);\n        assertApproxEqAbs(user2.balance - ethToQueue, user2EthBalanceBefore, 2);\n        assertEq(withReceiptAmountBefore - zenBullToQueue, withReceiptAmountAfter);\n        assertEq(depReceiptAmountBefore - ethToQueue, depReceiptAmountAfter);\n    }\n\n    function testNetAtPriceWithEmptyWithdrawReceipt() public {\n        uint256 ethToQueue = 10e18;\n        uint256 zenBullFairPrice = getZenBullPrice();\n        uint256 zenBullToQueue = ethToQueue * 1e18 / zenBullFairPrice;\n\n        _queueZenBull(user2, zenBullToQueue);\n        vm.prank(user2);\n        zenBullNetting.dequeueZenBull(zenBullToQueue, false);\n\n        _queueEth(user1, ethToQueue);\n        _queueZenBull(user2, zenBullToQueue);\n\n        (, uint256 depReceiptAmountBefore,) = zenBullNetting.getDepositReceipt(0);\n        (, uint256 withReceiptAmountBefore,) = zenBullNetting.getWithdrawReceipt(1);\n\n        uint256 user1ZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 user2EthBalanceBefore = user2.balance;\n        uint256 zenBullNettingEthBalanceBefore = address(zenBullNetting).balance;\n        uint256 zenBullNettingZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(address(zenBullNetting));\n\n        vm.prank(owner);\n        zenBullNetting.netAtPrice(zenBullFairPrice, ethToQueue);\n\n        (, uint256 depReceiptAmountAfter,) = zenBullNetting.getDepositReceipt(0);\n        (, uint256 withReceiptAmountAfter,) = zenBullNetting.getWithdrawReceipt(0);\n\n        assertEq(\n            IERC20(ZEN_BULL).balanceOf(address(zenBullNetting)) + zenBullToQueue,\n            zenBullNettingZenBalanceBefore\n        );\n        assertApproxEqAbs(\n            address(zenBullNetting).balance + ethToQueue, zenBullNettingEthBalanceBefore, 2\n        );\n        assertEq(IERC20(ZEN_BULL).balanceOf(user1) - user1ZenBalanceBefore, zenBullToQueue);\n        assertApproxEqAbs(user2.balance - ethToQueue, user2EthBalanceBefore, 2);\n        assertEq(withReceiptAmountBefore - zenBullToQueue, withReceiptAmountAfter);\n        assertEq(depReceiptAmountBefore - ethToQueue, depReceiptAmountAfter);\n    }\n\n    function testNetAtPriceWhenPriceIsFarBelowFairPrice() public {\n        uint256 ethToQueue = 10e18;\n        uint256 zenBullFairPrice = getZenBullPrice();\n        zenBullFairPrice =\n            (zenBullFairPrice * (1e18 - zenBullNetting.otcPriceTolerance())) / 1e18 - 1;\n        uint256 zenBullToQueue = ethToQueue * 1e18 / zenBullFairPrice;\n\n        _queueEth(user1, ethToQueue);\n        _queueZenBull(user2, zenBullToQueue);\n\n        vm.prank(owner);\n        vm.expectRevert(bytes(\"ZBN13\"));\n        zenBullNetting.netAtPrice(zenBullFairPrice, ethToQueue);\n    }\n\n    function testNetAtPriceWhenPriceIsFarAboveFairPrice() public {\n        uint256 ethToQueue = 10e18;\n        uint256 zenBullFairPrice = getZenBullPrice();\n        zenBullFairPrice =\n            (zenBullFairPrice * (1e18 + zenBullNetting.otcPriceTolerance())) / 1e18 + 1;\n        uint256 zenBullToQueue = ethToQueue * 1e18 / zenBullFairPrice;\n\n        _queueEth(user1, ethToQueue);\n        _queueZenBull(user2, zenBullToQueue);\n\n        vm.prank(owner);\n        vm.expectRevert(bytes(\"ZBN12\"));\n        zenBullNetting.netAtPrice(zenBullFairPrice, ethToQueue);\n    }\n\n    function testNetAtPriceWhenCallerIsRandom() public {\n        uint256 ethToQueue = 10e18;\n        uint256 zenBullFairPrice = getZenBullPrice();\n        uint256 zenBullToQueue = ethToQueue * 1e18 / zenBullFairPrice;\n\n        _queueEth(user1, ethToQueue);\n        _queueZenBull(user2, zenBullToQueue);\n\n        vm.prank(user2);\n        vm.expectRevert(bytes(\"ZBN24\"));\n        zenBullNetting.netAtPrice(zenBullFairPrice, ethToQueue);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/integration-test/ZenBullNetting/WithdrawAuction.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../../ZenBullNettingBaseSetup.t.sol\";\n// interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IZenBullStrategy } from \"../../../src/interface/IZenBullStrategy.sol\";\nimport { IOracle } from \"../../../src/interface/IOracle.sol\";\nimport { IEulerSimpleLens } from \"../../../src/interface/IEulerSimpleLens.sol\";\n\n// contract\nimport { SigUtil } from \"../../util/SigUtil.sol\";\nimport { ZenBullNetting } from \"../../../src/ZenBullNetting.sol\";\n\ncontract WithdrawAuction is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n    uint256 public user2Pk;\n    address public user2;\n    uint256 public mm1Pk;\n    address public mm1;\n    uint256 public mm2Pk;\n    address public mm2;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 1e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        vm.startPrank(owner);\n        zenBullNetting.setMinEthAmount(minWeth);\n        zenBullNetting.setMinZenBullAmount(minZenBull);\n        vm.stopPrank();\n\n        (user1, user1Pk) = makeAddrAndKey(\"User1\");\n        (user2, user2Pk) = makeAddrAndKey(\"User2\");\n        (mm1, mm1Pk) = makeAddrAndKey(\"MM1\");\n        (mm2, mm2Pk) = makeAddrAndKey(\"MM2\");\n\n        vm.deal(user1, 5000e18);\n        vm.deal(user2, 5000e18);\n        // some ZenBUll rich address\n        vm.startPrank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 15e18);\n        IERC20(ZEN_BULL).transfer(user2, 15e18);\n        vm.stopPrank();\n        // some oSQTH rich person\n        vm.startPrank(0x0154d25120Ed20A516fE43991702e7463c5A6F6e);\n        IERC20(WPOWERPERP).transfer(mm1, 1000e18);\n        IERC20(WPOWERPERP).transfer(mm2, 1000e18);\n        vm.stopPrank();\n    }\n\n    function testFullWithdrawAuction() public {\n        uint256 amount = 10e18;\n        _queueZenBull(user1, amount);\n\n        uint256 oSqthAmount;\n        {\n            uint256 share = div(amount, IZenBullStrategy(ZEN_BULL).totalSupply());\n            uint256 crabAmount = mul(share, IZenBullStrategy(ZEN_BULL).getCrabBalance());\n            (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n            oSqthAmount = div(mul(crabAmount, crabDebt), IERC20(CRAB).totalSupply());\n        }\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.WithdrawAuctionParams memory params = ZenBullNetting.WithdrawAuctionParams({\n            withdrawsToProcess: amount,\n            orders: orders,\n            clearingPrice: squeethEthPrice,\n            maxWethForUsdc: 100000e18,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WPOWERPERP).approve(address(zenBullNetting), oSqthAmount);\n\n        uint256 mm1WethBalanceBefore = IERC20(WETH).balanceOf(mm1);\n        uint256 mm1WpowerPerpBalanceBefore = IERC20(WPOWERPERP).balanceOf(mm1);\n        uint256 debtBalanceBefore =\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getDTokenBalance(USDC, ZEN_BULL);\n        uint256 usdcToRepay = amount * debtBalanceBefore / IERC20(ZEN_BULL).totalSupply();\n        uint256 wethInEulerBefore =\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL);\n        uint256 wethToWithdraw = amount * wethInEulerBefore / IERC20(ZEN_BULL).totalSupply();\n\n        (, uint256 receiptAmountBefore,) = zenBullNetting.getWithdrawReceipt(0);\n        uint256 user1EthBalanceBefore = user1.balance;\n\n        vm.startPrank(owner);\n        zenBullNetting.withdrawAuction(params);\n        vm.stopPrank();\n\n        (, uint256 receiptAmountAfter,) = zenBullNetting.getWithdrawReceipt(0);\n\n        assertEq(receiptAmountBefore - amount, receiptAmountAfter);\n        assertEq(IERC20(WPOWERPERP).balanceOf(mm1) + oSqthAmount, mm1WpowerPerpBalanceBefore);\n        assertEq(\n            IERC20(WETH).balanceOf(mm1) - (oSqthAmount * params.clearingPrice / 1e18),\n            mm1WethBalanceBefore\n        );\n        assertLt(IERC20(WPOWERPERP).balanceOf(mm1), mm1WpowerPerpBalanceBefore);\n        assertEq(\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getDTokenBalance(USDC, ZEN_BULL) + usdcToRepay,\n            debtBalanceBefore\n        );\n        assertApproxEqAbs(\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL) + wethToWithdraw,\n            wethInEulerBefore,\n            200\n        );\n        uint256 user1EthBalanceAfter = user1.balance;\n        assertGt(user1EthBalanceAfter, user1EthBalanceBefore);\n    }\n\n    function testPartialWithdrawAuction() public {\n        uint256 amount = 5e18;\n        _queueZenBull(user1, amount * 2);\n\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount;\n        {\n            uint256 share = div(amount, IZenBullStrategy(ZEN_BULL).totalSupply());\n            uint256 crabAmount = mul(share, IZenBullStrategy(ZEN_BULL).getCrabBalance());\n            oSqthAmount = div(mul(crabAmount, crabDebt), IERC20(CRAB).totalSupply());\n        }\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.WithdrawAuctionParams memory params = ZenBullNetting.WithdrawAuctionParams({\n            withdrawsToProcess: amount,\n            orders: orders,\n            clearingPrice: squeethEthPrice,\n            maxWethForUsdc: 100000e18,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WPOWERPERP).approve(address(zenBullNetting), oSqthAmount);\n\n        uint256 mm1WpowerPerpBalanceBefore = IERC20(WPOWERPERP).balanceOf(mm1);\n        uint256 debtBalanceBefore =\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getDTokenBalance(USDC, ZEN_BULL);\n        uint256 usdcToRepay =\n            (amount * 1e18 / IERC20(ZEN_BULL).totalSupply()) * debtBalanceBefore / 1e18;\n        uint256 wethInEulerBefore =\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL);\n        uint256 wethToWithdraw = amount * wethInEulerBefore / IERC20(ZEN_BULL).totalSupply();\n\n        vm.startPrank(owner);\n        zenBullNetting.withdrawAuction(params);\n        vm.stopPrank();\n\n        assertEq(IERC20(WPOWERPERP).balanceOf(mm1) + oSqthAmount, mm1WpowerPerpBalanceBefore);\n        assertEq(\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getDTokenBalance(USDC, ZEN_BULL) + usdcToRepay,\n            debtBalanceBefore\n        );\n        assertApproxEqAbs(\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL) + wethToWithdraw,\n            wethInEulerBefore,\n            200\n        );\n    }\n\n    function testWithdrawAuctionWithAnEmptyReceipt() public {\n        uint256 amount = 10e18;\n        _queueZenBull(user1, amount);\n\n        vm.prank(user1);\n        zenBullNetting.dequeueZenBull(amount, false);\n\n        _queueZenBull(user1, amount);\n\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount;\n        {\n            uint256 share = div(amount, IZenBullStrategy(ZEN_BULL).totalSupply());\n            uint256 crabAmount = mul(share, IZenBullStrategy(ZEN_BULL).getCrabBalance());\n            oSqthAmount = div(mul(crabAmount, crabDebt), IERC20(CRAB).totalSupply());\n        }\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.WithdrawAuctionParams memory params = ZenBullNetting.WithdrawAuctionParams({\n            withdrawsToProcess: amount,\n            orders: orders,\n            clearingPrice: squeethEthPrice,\n            maxWethForUsdc: 100000e18,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WPOWERPERP).approve(address(zenBullNetting), oSqthAmount);\n\n        uint256 mm1WpowerPerpBalanceBefore = IERC20(WPOWERPERP).balanceOf(mm1);\n        uint256 debtBalanceBefore =\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getDTokenBalance(USDC, ZEN_BULL);\n        uint256 usdcToRepay = amount * debtBalanceBefore / IERC20(ZEN_BULL).totalSupply();\n        uint256 wethInEulerBefore =\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL);\n        uint256 wethToWithdraw = amount * wethInEulerBefore / IERC20(ZEN_BULL).totalSupply();\n\n        vm.startPrank(owner);\n        zenBullNetting.withdrawAuction(params);\n        vm.stopPrank();\n\n        assertEq(IERC20(WPOWERPERP).balanceOf(mm1) + oSqthAmount, mm1WpowerPerpBalanceBefore);\n        assertEq(\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getDTokenBalance(USDC, ZEN_BULL) + usdcToRepay,\n            debtBalanceBefore\n        );\n        assertApproxEqAbs(\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL) + wethToWithdraw,\n            wethInEulerBefore,\n            200\n        );\n    }\n\n    function testWithdrawAuctionWithMultipleOrders() public {\n        uint256 amount = 10e18;\n        _queueZenBull(user1, amount);\n\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount;\n        {\n            uint256 share = div(amount, IZenBullStrategy(ZEN_BULL).totalSupply());\n            uint256 crabAmount = mul(share, IZenBullStrategy(ZEN_BULL).getCrabBalance());\n            oSqthAmount = div(mul(crabAmount, crabDebt), IERC20(CRAB).totalSupply());\n        }\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](2);\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount / 2,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount / 2,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n\n            // trader signing bid\n            orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm2,\n                quantity: oSqthAmount / 2,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm2Pk, bidDigest);\n            orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm2,\n                quantity: oSqthAmount / 2,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[1] = orderData;\n        }\n\n        ZenBullNetting.WithdrawAuctionParams memory params = ZenBullNetting.WithdrawAuctionParams({\n            withdrawsToProcess: amount,\n            orders: orders,\n            clearingPrice: squeethEthPrice,\n            maxWethForUsdc: 100000e18,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WPOWERPERP).approve(address(zenBullNetting), oSqthAmount / 2);\n        vm.prank(mm2);\n        IERC20(WPOWERPERP).approve(address(zenBullNetting), oSqthAmount / 2);\n\n        uint256 mm1WpowerPerpBalanceBefore = IERC20(WPOWERPERP).balanceOf(mm1);\n        uint256 mm2WpowerPerpBalanceBefore = IERC20(WPOWERPERP).balanceOf(mm2);\n        uint256 debtBalanceBefore =\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getDTokenBalance(USDC, ZEN_BULL);\n        uint256 usdcToRepay = amount * debtBalanceBefore / IERC20(ZEN_BULL).totalSupply();\n        uint256 wethInEulerBefore =\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL);\n        uint256 wethToWithdraw = amount * wethInEulerBefore / IERC20(ZEN_BULL).totalSupply();\n\n        vm.startPrank(owner);\n        zenBullNetting.withdrawAuction(params);\n        vm.stopPrank();\n\n        assertEq(IERC20(WPOWERPERP).balanceOf(mm1) + oSqthAmount / 2, mm1WpowerPerpBalanceBefore);\n        assertEq(IERC20(WPOWERPERP).balanceOf(mm2) + oSqthAmount / 2, mm2WpowerPerpBalanceBefore);\n        assertEq(\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getDTokenBalance(USDC, ZEN_BULL) + usdcToRepay,\n            debtBalanceBefore\n        );\n        assertApproxEqAbs(\n            IEulerSimpleLens(EULER_SIMPLE_LENS).getETokenBalance(WETH, ZEN_BULL) + wethToWithdraw,\n            wethInEulerBefore,\n            200\n        );\n    }\n\n    function testWithdrawAuctionWhenPriceGreaterThanClearingPrice() public {\n        uint256 amount = 10e18;\n        _queueZenBull(user1, amount);\n\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount;\n        {\n            uint256 share = div(amount, IZenBullStrategy(ZEN_BULL).totalSupply());\n            uint256 crabAmount = mul(share, IZenBullStrategy(ZEN_BULL).getCrabBalance());\n            oSqthAmount = div(mul(crabAmount, crabDebt), IERC20(CRAB).totalSupply());\n        }\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice + 1,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice + 1,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.WithdrawAuctionParams memory params = ZenBullNetting.WithdrawAuctionParams({\n            withdrawsToProcess: amount,\n            orders: orders,\n            clearingPrice: squeethEthPrice,\n            maxWethForUsdc: 100000e18,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WPOWERPERP).approve(address(zenBullNetting), oSqthAmount);\n\n        vm.startPrank(owner);\n        vm.expectRevert(bytes(\"ZBN20\"));\n        zenBullNetting.withdrawAuction(params);\n        vm.stopPrank();\n    }\n\n    function testWithdrawAuctionWhenClearingPriceIsGreaterThanTolerance() public {\n        uint256 amount = 10e18;\n        _queueZenBull(user1, amount);\n\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount;\n        {\n            uint256 share = div(amount, IZenBullStrategy(ZEN_BULL).totalSupply());\n            uint256 crabAmount = mul(share, IZenBullStrategy(ZEN_BULL).getCrabBalance());\n            oSqthAmount = div(mul(crabAmount, crabDebt), IERC20(CRAB).totalSupply());\n        }\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.WithdrawAuctionParams memory params = ZenBullNetting.WithdrawAuctionParams({\n            withdrawsToProcess: amount,\n            orders: orders,\n            clearingPrice: ((squeethEthPrice * (1e18 + zenBullNetting.otcPriceTolerance())) / 1e18) + 1,\n            maxWethForUsdc: 100000e18,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WPOWERPERP).approve(address(zenBullNetting), oSqthAmount);\n\n        vm.startPrank(owner);\n        vm.expectRevert(bytes(\"ZBN14\"));\n        zenBullNetting.withdrawAuction(params);\n        vm.stopPrank();\n    }\n\n    function testWithdrawAuctionWhenOrderIsBuying() public {\n        uint256 amount = 10e18;\n        _queueZenBull(user1, amount);\n\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount;\n        {\n            uint256 share = div(amount, IZenBullStrategy(ZEN_BULL).totalSupply());\n            uint256 crabAmount = mul(share, IZenBullStrategy(ZEN_BULL).getCrabBalance());\n            oSqthAmount = div(mul(crabAmount, crabDebt), IERC20(CRAB).totalSupply());\n        }\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](1);\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount,\n                price: squeethEthPrice,\n                isBuying: true,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n        }\n\n        ZenBullNetting.WithdrawAuctionParams memory params = ZenBullNetting.WithdrawAuctionParams({\n            withdrawsToProcess: amount,\n            orders: orders,\n            clearingPrice: squeethEthPrice,\n            maxWethForUsdc: 100000e18,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WPOWERPERP).approve(address(zenBullNetting), oSqthAmount);\n\n        vm.startPrank(owner);\n        vm.expectRevert(bytes(\"ZBN19\"));\n        zenBullNetting.withdrawAuction(params);\n        vm.stopPrank();\n    }\n\n    function testWithdrawAuctionWhenNonceIsAlreadyUsed() public {\n        uint256 amount = 10e18;\n        _queueZenBull(user1, amount);\n\n        (, uint256 crabDebt) = IZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n        uint256 oSqthAmount;\n        {\n            uint256 share = div(amount, IZenBullStrategy(ZEN_BULL).totalSupply());\n            uint256 crabAmount = mul(share, IZenBullStrategy(ZEN_BULL).getCrabBalance());\n            oSqthAmount = div(mul(crabAmount, crabDebt), IERC20(CRAB).totalSupply());\n        }\n        uint256 squeethEthPrice =\n            IOracle(ORACLE).getTwap(ethSqueethPool, WPOWERPERP, WETH, 420, false);\n        ZenBullNetting.Order[] memory orders = new ZenBullNetting.Order[](2);\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount / 2,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n                bidId: 1,\n                trader: mm1,\n                quantity: oSqthAmount / 2,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[0] = orderData;\n\n            // trader signing bid\n            orderSig = SigUtil.Order({\n                bidId: 2,\n                trader: mm1,\n                quantity: oSqthAmount / 2,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(mm1Pk, bidDigest);\n            orderData = ZenBullNetting.Order({\n                bidId: 2,\n                trader: mm1,\n                quantity: oSqthAmount / 2,\n                price: squeethEthPrice,\n                isBuying: false,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders[1] = orderData;\n        }\n\n        ZenBullNetting.WithdrawAuctionParams memory params = ZenBullNetting.WithdrawAuctionParams({\n            withdrawsToProcess: amount,\n            orders: orders,\n            clearingPrice: squeethEthPrice,\n            maxWethForUsdc: 100000e18,\n            wethUsdcPoolFee: 3000\n        });\n\n        vm.prank(mm1);\n        IERC20(WPOWERPERP).approve(address(zenBullNetting), oSqthAmount);\n\n        vm.startPrank(owner);\n        vm.expectRevert(bytes(\"ZBN18\"));\n        zenBullNetting.withdrawAuction(params);\n        vm.stopPrank();\n    }\n\n    function testCheckOrder() public {\n        // trader signature vars\n        uint8 v;\n        bytes32 r;\n        bytes32 s;\n        // trader signing bid\n        SigUtil.Order memory orderSig = SigUtil.Order({\n            bidId: 1,\n            trader: mm1,\n            quantity: 0,\n            price: 0,\n            isBuying: false,\n            expiry: block.timestamp + 1000,\n            nonce: 0\n        });\n        bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n        (v, r, s) = vm.sign(mm1Pk, bidDigest);\n        ZenBullNetting.Order memory orderData = ZenBullNetting.Order({\n            bidId: 1,\n            trader: mm1,\n            quantity: 0,\n            price: 0,\n            isBuying: false,\n            expiry: block.timestamp + 1000,\n            nonce: 0,\n            v: v,\n            r: r,\n            s: s\n        });\n\n        assertEq(zenBullNetting.checkOrder(orderData), true);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/unit-test/CancelNonce.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../ZenBullNettingBaseSetup.t.sol\";\n\n/**\n * Unit tests\n */\ncontract CancelNonce is ZenBullNettingBaseSetup {\n    uint256 public traderPk;\n    address public trader1;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        traderPk = 0xA12CD;\n        trader1 = vm.addr(traderPk);\n\n        vm.label(trader1, \"trader1\");\n    }\n\n    function testCancelNonce() public {\n        uint256 nonce = 5;\n\n        vm.prank(trader1);\n        zenBullNetting.cancelNonce(nonce);\n\n        assertEq(zenBullNetting.nonces(trader1, nonce), true);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/unit-test/QueueEth.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\n/**\n * Unit tests\n */\ncontract QueueEth is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 3e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        user1Pk = 0xA12CD;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User1\");\n\n        vm.deal(user1, 5000e18);\n        // some ZenBUll rich address\n        vm.prank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 30e18);\n    }\n\n    function testQueueEth() public {\n        uint256 amount = 100e18;\n        uint256 user1EthBalanceBefore = user1.balance;\n        uint256 zenBullNettingEthBalanceBefore = address(zenBullNetting).balance;\n\n        _queueEth(user1, amount);\n\n        assertEq(zenBullNetting.ethBalance(user1), amount);\n        assertEq(address(zenBullNetting).balance - zenBullNettingEthBalanceBefore, amount);\n        assertEq(user1.balance + amount, user1EthBalanceBefore);\n        assertEq(zenBullNetting.depositsQueued(), amount);\n    }\n\n    function testQueueEthThroughDirectEthSend() public {\n        uint256 amount = 100e18;\n        uint256 user1EthBalanceBefore = user1.balance;\n        uint256 zenBullNettingEthBalanceBefore = address(zenBullNetting).balance;\n\n        // _queueEth(user1, amount);\n        vm.prank(user1);\n        (bool success,) = address(zenBullNetting).call{ value: amount }(\"\");\n\n        assertTrue(success);\n        assertEq(zenBullNetting.ethBalance(user1), amount);\n        assertEq(address(zenBullNetting).balance - zenBullNettingEthBalanceBefore, amount);\n        assertEq(user1.balance + amount, user1EthBalanceBefore);\n        assertEq(zenBullNetting.depositsQueued(), amount);\n    }\n\n    function testQueueEthWhenAmountLessThanMinAmount() public {\n        vm.prank(owner);\n        zenBullNetting.setMinEthAmount(minWeth);\n\n        uint256 amount = zenBullNetting.minEthAmount() - 1;\n\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"ZBN03\"));\n        zenBullNetting.queueEth{ value: amount }();\n        vm.stopPrank();\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/unit-test/QueueZenBull.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\n/**\n * Unit tests\n */\ncontract QueueZenBull is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 3e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        user1Pk = 0xA12CD;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User1\");\n\n        vm.deal(user1, 5000e18);\n        // some ZenBUll rich address\n        vm.prank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 30e18);\n    }\n\n    function testQueueZenBull() public {\n        uint256 amount = 5e18;\n        uint256 user1ZenBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 zenBullNettingZenhBalanceBefore =\n            IERC20(ZEN_BULL).balanceOf(address(zenBullNetting));\n\n        _queueZenBull(user1, amount);\n\n        assertEq(zenBullNetting.zenBullBalance(user1), amount);\n        assertEq(\n            IERC20(ZEN_BULL).balanceOf(address(zenBullNetting)) - zenBullNettingZenhBalanceBefore,\n            amount\n        );\n        assertEq(IERC20(ZEN_BULL).balanceOf(user1) + amount, user1ZenBalanceBefore);\n        assertEq(zenBullNetting.withdrawsQueued(), amount);\n    }\n\n    function testQueueZenBullWhenAmountLessThanMinAmount() public {\n        vm.prank(owner);\n        zenBullNetting.setMinZenBullAmount(minZenBull);\n\n        uint256 amount = zenBullNetting.minZenBullAmount() - 1;\n\n        vm.startPrank(user1);\n        IERC20(ZEN_BULL).approve(address(zenBullNetting), amount);\n        vm.expectRevert(bytes(\"ZBN07\"));\n        zenBullNetting.queueZenBull(amount);\n        vm.stopPrank();\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/unit-test/SetAuctionTwapPeriod.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\n/**\n * Unit tests\n */\ncontract SetAuctionTwapPeriod is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 3e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        user1Pk = 0xA12CD;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User1\");\n\n        vm.deal(user1, 5000e18);\n        // some ZenBUll rich address\n        vm.prank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 30e18);\n    }\n\n    function testSetAuctionTwapPeriod() public {\n        vm.prank(owner);\n        zenBullNetting.setAuctionTwapPeriod(42069);\n\n        assertEq(zenBullNetting.auctionTwapPeriod(), 42069);\n    }\n\n    function testSetAuctionTwapPeriodWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        zenBullNetting.setAuctionTwapPeriod(42069);\n    }\n\n    function testSetAuctionTwapPeriodWhenPeriodLessThanMinimum() public {\n        uint32 minAuctionTwap = zenBullNetting.MIN_AUCTION_TWAP();\n        vm.prank(owner);\n        vm.expectRevert(bytes(\"ZBN01\"));\n        zenBullNetting.setAuctionTwapPeriod(minAuctionTwap - 1);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/unit-test/SetDepositsIndex.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\n/**\n * Unit tests\n */\ncontract SetDepositsIndex is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 3e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        user1Pk = 0xA12CD;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User1\");\n\n        vm.deal(user1, 5000e18);\n        // some ZenBUll rich address\n        vm.prank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 30e18);\n    }\n\n    function testSetDepositsIndex() public {\n        vm.prank(owner);\n        zenBullNetting.setDepositsIndex(2);\n\n        assertEq(zenBullNetting.depositsIndex(), 2);\n    }\n\n    function testSetDepositsIndexWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        zenBullNetting.setDepositsIndex(2);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/unit-test/SetMinEthAmount.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\n/**\n * Unit tests\n */\ncontract SetMinEthAmount is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 3e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        user1Pk = 0xA12CD;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User1\");\n\n        vm.deal(user1, 5000e18);\n        // some ZenBUll rich address\n        vm.prank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 30e18);\n    }\n\n    function testSetMinEthAmount() public {\n        vm.prank(owner);\n        zenBullNetting.setMinEthAmount(minWeth);\n        assertEq(zenBullNetting.minEthAmount(), minWeth);\n    }\n\n    function testSetMinEthAmountWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        zenBullNetting.setMinEthAmount(minWeth);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/unit-test/SetMinZenBullAmount.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\n/**\n * Unit tests\n */\ncontract ZenBullNettingUnit is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 3e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        user1Pk = 0xA12CD;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User1\");\n\n        vm.deal(user1, 5000e18);\n        // some ZenBUll rich address\n        vm.prank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 30e18);\n    }\n\n    function testSetMinBullAmount() public {\n        vm.prank(owner);\n        zenBullNetting.setMinZenBullAmount(3e18);\n\n        assertEq(zenBullNetting.minZenBullAmount(), 3e18);\n    }\n\n    function testSetMinBullAmountWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        zenBullNetting.setMinZenBullAmount(3e18);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/unit-test/SetOTCPriceTolerance.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\n/**\n * Unit tests\n */\ncontract SetOTCPriceTolerance is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 3e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        user1Pk = 0xA12CD;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User1\");\n\n        vm.deal(user1, 5000e18);\n        // some ZenBUll rich address\n        vm.prank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 30e18);\n    }\n\n    function testSetOTCPriceTolerance() public {\n        vm.prank(owner);\n        zenBullNetting.setOTCPriceTolerance(2e16);\n\n        assertEq(zenBullNetting.otcPriceTolerance(), 2e16);\n    }\n\n    function testSetOTCPriceToleranceWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        zenBullNetting.setOTCPriceTolerance(2e16);\n    }\n\n    function testSetOTCPriceToleranceWhenPeriodLessThanMinimum() public {\n        uint256 maxOtcPriceTolerance = zenBullNetting.MAX_OTC_PRICE_TOLERANCE();\n        vm.prank(owner);\n        vm.expectRevert(bytes(\"ZBN02\"));\n        zenBullNetting.setOTCPriceTolerance(maxOtcPriceTolerance + 1);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/unit-test/SetWithdrawsIndex.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\n/**\n * Unit tests\n */\ncontract SetWithdrawsIndex is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 3e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        user1Pk = 0xA12CD;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User1\");\n\n        vm.deal(user1, 5000e18);\n        // some ZenBUll rich address\n        vm.prank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 30e18);\n    }\n\n    function testSetWithdrawsIndex() public {\n        vm.prank(owner);\n        zenBullNetting.setWithdrawsIndex(4);\n\n        assertEq(zenBullNetting.withdrawsIndex(), 4);\n    }\n\n    function testSetWithdrawsIndexWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        zenBullNetting.setWithdrawsIndex(2);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/unit-test/ToggleAuctionLive.t.sol",
    "content": "pragma solidity ^0.8.13;\n\npragma abicoder v2;\n\n// test dependency\nimport { console } from \"forge-std/console.sol\";\nimport { ZenBullNettingBaseSetup } from \"../ZenBullNettingBaseSetup.t.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\n/**\n * Unit tests\n */\ncontract ZenBullNettingUnit is ZenBullNettingBaseSetup {\n    uint256 public user1Pk;\n    address public user1;\n\n    uint256 minWeth = 5e18;\n    uint256 minZenBull = 3e18;\n\n    function setUp() public override {\n        ZenBullNettingBaseSetup.setUp();\n\n        user1Pk = 0xA12CD;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User1\");\n\n        vm.deal(user1, 5000e18);\n        // some ZenBUll rich address\n        vm.prank(0xaae102ca930508e6dA30924Bf0374F0F247729d5);\n        IERC20(ZEN_BULL).transfer(user1, 30e18);\n    }\n\n    function testToggleAuctionLive() public {\n        assertEq(zenBullNetting.isAuctionLive(), false);\n\n        vm.prank(owner);\n        zenBullNetting.toggleAuctionLive();\n\n        assertEq(zenBullNetting.isAuctionLive(), true);\n    }\n\n    function testToggleAuctionLiveWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        zenBullNetting.toggleAuctionLive();\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-netting/test/util/SigUtil.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\npragma abicoder v2;\n\ncontract SigUtil {\n    bytes32 internal DOMAIN_SEPARATOR;\n\n    constructor(bytes32 _DOMAIN_SEPARATOR) {\n        DOMAIN_SEPARATOR = _DOMAIN_SEPARATOR;\n    }\n\n    /// @dev typehash for signed orders\n    bytes32 private constant _ZENBULL_NETTING_TYPEHASH = keccak256(\n        \"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\"\n    );\n\n    struct Order {\n        uint256 bidId;\n        address trader;\n        uint256 quantity;\n        uint256 price;\n        bool isBuying;\n        uint256 expiry;\n        uint256 nonce;\n    }\n\n    // computes the hash of a Order\n    function getStructHash(Order memory _order) internal pure returns (bytes32) {\n        return keccak256(\n            abi.encode(\n                _ZENBULL_NETTING_TYPEHASH,\n                _order.bidId,\n                _order.trader,\n                _order.quantity,\n                _order.price,\n                _order.isBuying,\n                _order.expiry,\n                _order.nonce\n            )\n        );\n    }\n\n    // computes the hash of the fully encoded EIP-712 message for the domain, which can be used to recover the signer\n    function getTypedDataHash(Order memory _order) public view returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR, getStructHash(_order)));\n    }\n\n    function testAvoidCoverage() public pure {\n        return;\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/.gitignore",
    "content": "/report\n/broadcast\n/out\n/cache\n.env"
  },
  {
    "path": "packages/zen-bull-vault/LICENSE_BUSL",
    "content": "Business Source License 1.1\n\nLicense text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.\n\n\n\"Business Source License\" is a trademark of MariaDB Corporation Ab.\n\n-----------------------------------------------------------------------------\n\nParameters\nLicensor:           \t Opyn \nLicensed Work:       \t Opyn Zen Bull v1.0\n                     \t\t The Licensed Work is (c) 2022 Opyn\n\nAdditional Use Grant: Any uses listed and defined at\nhttps://github.com/opynfinance/squeeth-monorepo/packages/hardhat/USE_GRANT\n\nChange Date:          The earlier of 2023-12-16 or a date specified at\nhttps://github.com/opynfinance/squeeth-monorepo/packages/hardhat/CHANGE_DATE\n\nChange License:        GNU General Public License v2.0 or later\n\n-----------------------------------------------------------------------------\n\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provided that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN \"AS IS\" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE.\n\nMariaDB hereby grants you permission to use this License’s text to license\nyour works, and to refer to it using the trademark \"Business Source License\",\nas long as you comply with the Covenants of Licensor below.\n\n-----------------------------------------------------------------------------\n\nCovenants of Licensor\n\nIn consideration of the right to use this License’s text and the \"Business\nSource License\" name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provided by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n  or a license that is compatible with GPL Version 2.0 or a later version,\n  where \"compatible\" means that software provided under the Change License can\n  be included in a program with software provided under GPL Version 2.0 or a\n  later version. Licensor may specify additional Change Licenses without\n  limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n  impose any additional restriction on the right granted in this License, as\n  the Additional Use Grant; or (b) insert the text \"None\".\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\n\n-----------------------------------------------------------------------------\n\nNotice\n\nThe Business Source License (this document, or the \"License\") is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License."
  },
  {
    "path": "packages/zen-bull-vault/README.md",
    "content": "# BULL VAULT\n\n## Table of Contents\n\n- [BULL VAULT](#bull-vault)\n  - [Table of Contents](#table-of-contents)\n  - [Local Development](#local-development)\n  - [How To Deploy](#how-to-deploy)\n  - [Contracts Architecture](#contracts-architecture)\n  - [Audits](#audits)\n  - [License](#license)\n\n## Local Development\n\nTo install dependencies and compile contracts:\n\n```bash\ngit clone https://github.com/opynfinance/squeeth-monorepo && cd packages/bull-vault\n```\n\nTo install Foundry (assuming a Linux or macOS system):\n\n```bash\ncurl -L https://foundry.paradigm.xyz | bash\n```\n\nThis will download foundryup. To start Foundry, run:\n\n```bash\nfoundryup\n```\n\nTo install dependencies:\n\n```\nforge install\n```\n\n<!-- There are three Foundry profiles for running the test suites, which bypass the IR pipeline to speed up compilation. To run tests, run any of the following: -->\n\n```bash\nFOUNDRY_PROFILE=test forge test # run only test functions\nFOUNDRY_PROFILE=fuzz forge test # run only fuz testing (function with name that include \"Fuzzing\")\nFOUNDRY_PROFILE=coverage forge coverage # coverage report\n```\n\nTo run tests, you need to create `.env` file with the variables included in `.env.example`.\n\nYou may wish to include a `.env` file that `export`s a specific profile when developing locally.\n\nThe following modifiers are also available:\n\n- Level 2 (-vv): Logs emitted during tests are also displayed.\n- Level 3 (-vvv): Stack traces for failing tests are also displayed.\n- Level 4 (-vvvv): Stack traces for all tests are displayed, and setup traces for failing tests are displayed.\n- Level 5 (-vvvvv): Stack traces and setup traces are always displayed.\n\n```bash\nFOUNDRY_PROFILE=test forge test forge test  -vvvv\n```\n\nFor more information on foundry testing and use, see [Foundry Book installation instructions](https://book.getfoundry.sh/getting-started/installation.html).\n\n## How To Deploy\n\nBefore running the deployment script, make sure to copy `.env.example` in a `.env` file and set the environment variables.\n\nThe deployment script for [Mainnet](/packages/bull-vault/script/MainnetDeploy.s.sol) and [Goerli](/packages/bull-vault/script/GoerliDeploy.s.sol) can be executed using the below command:\n```shell\n$ source .env\n$ forge script script/MainnetDeploy.s.sol:MainnetDeploy --rpc-url $MAINNET_RPC_URL --broadcast --verify -vvvv\n```\n\n## SCRIPTS\n\n### ADD LIQUIDITY IN EULER MARKET\n\nMake sure to add the env vars `SCRIPT_USER_PK` and `UNDERLYING_AMOUNT` in the `.env` file.\n\nTo add USDC liquidity:\n```shell\n$ source .env\n\n# for USDC \n$ forge script script/GoerliAddUsdcLiquidityEuler.s.sol:GoerliAddUsdcLiquidityEuler --rpc-url $GOERLI_RPC_URL --broadcast --verify -vvvv\n\n# for WETH\n$ forge script script/GoerliAddWethLiquidityEuler.s.sol:GoerliAddWethLiquidityEuler --rpc-url $GOERLI_RPC_URL --broadcast --verify -vvvv\n```\n\nTo add liquidity for asset other than WETH or USDC, create a new script following the `GoerliAddUsdcLiquidityEuler` pattern. \n\n## Audits\n\n## License\n"
  },
  {
    "path": "packages/zen-bull-vault/doc/report/report_auction_bull",
    "content": "## Sūrya's Description Report\n\n### Files Description Table\n\n\n|  File Name  |  SHA-1 Hash  |\n|-------------|--------------|\n| src/AuctionBull.sol | 426515c2e89a605eec88214b0233dc50e9ff4a28 |\n\n\n### Contracts Description Table\n\n\n|  Contract  |         Type        |       Bases      |                  |                 |\n|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:|\n|     └      |  **Function Name**  |  **Visibility**  |  **Mutability**  |  **Modifiers**  |\n||||||\n| **AuctionBull** | Implementation | UniFlash, Ownable, EIP712 |||\n| └ | <Constructor> | Public ❗️ | 🛑  | UniFlash Ownable EIP712 |\n| └ | <Receive Ether> | External ❗️ |  💵 |NO❗️ |\n| └ | setAuctionManager | External ❗️ | 🛑  | onlyOwner |\n| └ | setFullRebalanceClearingPriceTolerance | External ❗️ | 🛑  | onlyOwner |\n| └ | setRebalanceWethLimitPriceTolerance | External ❗️ | 🛑  | onlyOwner |\n| └ | setCrUpperAndLower | External ❗️ | 🛑  | onlyOwner |\n| └ | setDeltaUpperAndLower | External ❗️ | 🛑  | onlyOwner |\n| └ | fullRebalance | External ❗️ | 🛑  |NO❗️ |\n| └ | leverageRebalance | External ❗️ | 🛑  |NO❗️ |\n| └ | useNonce | External ❗️ | 🛑  |NO❗️ |\n| └ | DOMAIN_SEPARATOR | External ❗️ |   |NO❗️ |\n| └ | getCurrentDeltaAndCollatRatio | External ❗️ |   |NO❗️ |\n| └ | _pullFundsFromOrders | Internal 🔒 | 🛑  | |\n| └ | _pushFundsFromOrders | Internal 🔒 | 🛑  | |\n| └ | _executeCrabDeposit | Internal 🔒 | 🛑  | |\n| └ | _uniFlashSwap | Internal 🔒 | 🛑  | |\n| └ | _executeLeverageComponentRebalancing | Internal 🔒 | 🛑  | |\n| └ | _transferToOrder | Internal 🔒 | 🛑  | |\n| └ | _transferFromOrder | Internal 🔒 | 🛑  | |\n| └ | _verifyOrder | Internal 🔒 | 🛑  | |\n| └ | _useNonce | Internal 🔒 | 🛑  | |\n| └ | _isValidRebalance | Internal 🔒 |   | |\n| └ | _calcWPowerPerpAmountFromCrab | Internal 🔒 |   | |\n| └ | _getCurrentDeltaAndCollatRatio | Internal 🔒 |   | |\n| └ | _calcWPowerPerpToMintAndFee | Internal 🔒 |   | |\n| └ | _checkFullRebalanceClearingPrice | Internal 🔒 |   | |\n| └ | _checkRebalanceLimitPrice | Internal 🔒 |   | |\n\n\n### Legend\n\n|  Symbol  |  Meaning  |\n|:--------:|-----------|\n|    🛑    | Function can modify state |\n|    💵    | Function is payable |\n"
  },
  {
    "path": "packages/zen-bull-vault/doc/report/report_auction_bull.md",
    "content": "## Sūrya's Description Report\n\n### Files Description Table\n\n\n|  File Name  |  SHA-1 Hash  |\n|-------------|--------------|\n| src/AuctionBull.sol | 426515c2e89a605eec88214b0233dc50e9ff4a28 |\n\n\n### Contracts Description Table\n\n\n|  Contract  |         Type        |       Bases      |                  |                 |\n|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:|\n|     └      |  **Function Name**  |  **Visibility**  |  **Mutability**  |  **Modifiers**  |\n||||||\n| **AuctionBull** | Implementation | UniFlash, Ownable, EIP712 |||\n| └ | <Constructor> | Public ❗️ | 🛑  | UniFlash Ownable EIP712 |\n| └ | <Receive Ether> | External ❗️ |  💵 |NO❗️ |\n| └ | setAuctionManager | External ❗️ | 🛑  | onlyOwner |\n| └ | setFullRebalanceClearingPriceTolerance | External ❗️ | 🛑  | onlyOwner |\n| └ | setRebalanceWethLimitPriceTolerance | External ❗️ | 🛑  | onlyOwner |\n| └ | setCrUpperAndLower | External ❗️ | 🛑  | onlyOwner |\n| └ | setDeltaUpperAndLower | External ❗️ | 🛑  | onlyOwner |\n| └ | fullRebalance | External ❗️ | 🛑  |NO❗️ |\n| └ | leverageRebalance | External ❗️ | 🛑  |NO❗️ |\n| └ | useNonce | External ❗️ | 🛑  |NO❗️ |\n| └ | DOMAIN_SEPARATOR | External ❗️ |   |NO❗️ |\n| └ | getCurrentDeltaAndCollatRatio | External ❗️ |   |NO❗️ |\n| └ | _pullFundsFromOrders | Internal 🔒 | 🛑  | |\n| └ | _pushFundsFromOrders | Internal 🔒 | 🛑  | |\n| └ | _executeCrabDeposit | Internal 🔒 | 🛑  | |\n| └ | _uniFlashSwap | Internal 🔒 | 🛑  | |\n| └ | _executeLeverageComponentRebalancing | Internal 🔒 | 🛑  | |\n| └ | _transferToOrder | Internal 🔒 | 🛑  | |\n| └ | _transferFromOrder | Internal 🔒 | 🛑  | |\n| └ | _verifyOrder | Internal 🔒 | 🛑  | |\n| └ | _useNonce | Internal 🔒 | 🛑  | |\n| └ | _isValidRebalance | Internal 🔒 |   | |\n| └ | _calcWPowerPerpAmountFromCrab | Internal 🔒 |   | |\n| └ | _getCurrentDeltaAndCollatRatio | Internal 🔒 |   | |\n| └ | _calcWPowerPerpToMintAndFee | Internal 🔒 |   | |\n| └ | _checkFullRebalanceClearingPrice | Internal 🔒 |   | |\n| └ | _checkRebalanceLimitPrice | Internal 🔒 |   | |\n\n\n### Legend\n\n|  Symbol  |  Meaning  |\n|:--------:|-----------|\n|    🛑    | Function can modify state |\n|    💵    | Function is payable |\n"
  },
  {
    "path": "packages/zen-bull-vault/doc/report/report_bull_strategy",
    "content": "## Sūrya's Description Report\n\n### Files Description Table\n\n\n|  File Name  |  SHA-1 Hash  |\n|-------------|--------------|\n| src/BullStrategy.sol | f0170109e72d05c0f967a756bec518db678da6b4 |\n\n\n### Contracts Description Table\n\n\n|  Contract  |         Type        |       Bases      |                  |                 |\n|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:|\n|     └      |  **Function Name**  |  **Visibility**  |  **Mutability**  |  **Modifiers**  |\n||||||\n| **BullStrategy** | Implementation | ERC20, LeverageBull |||\n| └ | <Constructor> | Public ❗️ | 🛑  | ERC20 LeverageBull |\n| └ | <Receive Ether> | External ❗️ |  💵 |NO❗️ |\n| └ | farm | External ❗️ | 🛑  | onlyOwner |\n| └ | setCap | External ❗️ | 🛑  | onlyOwner |\n| └ | setShutdownContract | External ❗️ | 🛑  | onlyOwner |\n| └ | deposit | External ❗️ |  💵 |NO❗️ |\n| └ | withdraw | External ❗️ | 🛑  |NO❗️ |\n| └ | redeemCrabAndWithdrawWEth | External ❗️ | 🛑  |NO❗️ |\n| └ | depositEthIntoCrab | External ❗️ | 🛑  |NO❗️ |\n| └ | shutdownRepayAndWithdraw | External ❗️ | 🛑  |NO❗️ |\n| └ | withdrawShutdown | External ❗️ | 🛑  |NO❗️ |\n| └ | getCrabBalance | External ❗️ |   |NO❗️ |\n| └ | getCrabVaultDetails | External ❗️ |   |NO❗️ |\n| └ | _increaseCrabBalance | Private 🔐 | 🛑  | |\n| └ | _decreaseCrabBalance | Private 🔐 | 🛑  | |\n| └ | _getCrabVaultDetails | Internal 🔒 |   | |\n\n\n### Legend\n\n|  Symbol  |  Meaning  |\n|:--------:|-----------|\n|    🛑    | Function can modify state |\n|    💵    | Function is payable |\n"
  },
  {
    "path": "packages/zen-bull-vault/doc/report/report_bull_strategy.md",
    "content": "## Sūrya's Description Report\n\n### Files Description Table\n\n\n|  File Name  |  SHA-1 Hash  |\n|-------------|--------------|\n| src/BullStrategy.sol | f0170109e72d05c0f967a756bec518db678da6b4 |\n\n\n### Contracts Description Table\n\n\n|  Contract  |         Type        |       Bases      |                  |                 |\n|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:|\n|     └      |  **Function Name**  |  **Visibility**  |  **Mutability**  |  **Modifiers**  |\n||||||\n| **BullStrategy** | Implementation | ERC20, LeverageBull |||\n| └ | <Constructor> | Public ❗️ | 🛑  | ERC20 LeverageBull |\n| └ | <Receive Ether> | External ❗️ |  💵 |NO❗️ |\n| └ | farm | External ❗️ | 🛑  | onlyOwner |\n| └ | setCap | External ❗️ | 🛑  | onlyOwner |\n| └ | setShutdownContract | External ❗️ | 🛑  | onlyOwner |\n| └ | deposit | External ❗️ |  💵 |NO❗️ |\n| └ | withdraw | External ❗️ | 🛑  |NO❗️ |\n| └ | redeemCrabAndWithdrawWEth | External ❗️ | 🛑  |NO❗️ |\n| └ | depositEthIntoCrab | External ❗️ | 🛑  |NO❗️ |\n| └ | shutdownRepayAndWithdraw | External ❗️ | 🛑  |NO❗️ |\n| └ | withdrawShutdown | External ❗️ | 🛑  |NO❗️ |\n| └ | getCrabBalance | External ❗️ |   |NO❗️ |\n| └ | getCrabVaultDetails | External ❗️ |   |NO❗️ |\n| └ | _increaseCrabBalance | Private 🔐 | 🛑  | |\n| └ | _decreaseCrabBalance | Private 🔐 | 🛑  | |\n| └ | _getCrabVaultDetails | Internal 🔒 |   | |\n\n\n### Legend\n\n|  Symbol  |  Meaning  |\n|:--------:|-----------|\n|    🛑    | Function can modify state |\n|    💵    | Function is payable |\n"
  },
  {
    "path": "packages/zen-bull-vault/doc/report/report_emergency_shutdown",
    "content": "## Sūrya's Description Report\n\n### Files Description Table\n\n\n|  File Name  |  SHA-1 Hash  |\n|-------------|--------------|\n| src/EmergencyShutdown.sol | 6eafc9caf92ed9580fc79d4b7ba567e2d662b1c2 |\n\n\n### Contracts Description Table\n\n\n|  Contract  |         Type        |       Bases      |                  |                 |\n|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:|\n|     └      |  **Function Name**  |  **Visibility**  |  **Mutability**  |  **Modifiers**  |\n||||||\n| **EmergencyShutdown** | Implementation | UniFlash, Ownable |||\n| └ | <Constructor> | Public ❗️ | 🛑  | UniFlash |\n| └ | redeemShortShutdown | External ❗️ | 🛑  | onlyOwner |\n| └ | _uniFlashSwap | Internal 🔒 | 🛑  | |\n\n\n### Legend\n\n|  Symbol  |  Meaning  |\n|:--------:|-----------|\n|    🛑    | Function can modify state |\n|    💵    | Function is payable |\n"
  },
  {
    "path": "packages/zen-bull-vault/doc/report/report_emergency_shutdown.md",
    "content": "## Sūrya's Description Report\n\n### Files Description Table\n\n\n|  File Name  |  SHA-1 Hash  |\n|-------------|--------------|\n| src/EmergencyShutdown.sol | 6eafc9caf92ed9580fc79d4b7ba567e2d662b1c2 |\n\n\n### Contracts Description Table\n\n\n|  Contract  |         Type        |       Bases      |                  |                 |\n|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:|\n|     └      |  **Function Name**  |  **Visibility**  |  **Mutability**  |  **Modifiers**  |\n||||||\n| **EmergencyShutdown** | Implementation | UniFlash, Ownable |||\n| └ | <Constructor> | Public ❗️ | 🛑  | UniFlash |\n| └ | redeemShortShutdown | External ❗️ | 🛑  | onlyOwner |\n| └ | _uniFlashSwap | Internal 🔒 | 🛑  | |\n\n\n### Legend\n\n|  Symbol  |  Meaning  |\n|:--------:|-----------|\n|    🛑    | Function can modify state |\n|    💵    | Function is payable |\n"
  },
  {
    "path": "packages/zen-bull-vault/doc/report/report_flash_bull",
    "content": "## Sūrya's Description Report\n\n### Files Description Table\n\n\n|  File Name  |  SHA-1 Hash  |\n|-------------|--------------|\n| src/FlashBull.sol | 8498f69dac8c8ab83647b18f6e77f759bd38178f |\n\n\n### Contracts Description Table\n\n\n|  Contract  |         Type        |       Bases      |                  |                 |\n|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:|\n|     └      |  **Function Name**  |  **Visibility**  |  **Mutability**  |  **Modifiers**  |\n||||||\n| **FlashBull** | Implementation | UniFlash |||\n| └ | <Constructor> | Public ❗️ | 🛑  | UniFlash |\n| └ | <Receive Ether> | External ❗️ |  💵 |NO❗️ |\n| └ | flashDeposit | External ❗️ |  💵 |NO❗️ |\n| └ | flashWithdraw | External ❗️ | 🛑  |NO❗️ |\n| └ | _uniFlashSwap | Internal 🔒 | 🛑  | |\n| └ | _calcwPowerPerpToMintAndFee | Internal 🔒 |   | |\n| └ | _calcSharesToMint | Internal 🔒 |   | |\n| └ | _getCrabVaultDetails | Internal 🔒 |   | |\n\n\n### Legend\n\n|  Symbol  |  Meaning  |\n|:--------:|-----------|\n|    🛑    | Function can modify state |\n|    💵    | Function is payable |\n"
  },
  {
    "path": "packages/zen-bull-vault/doc/report/report_flash_bull.md",
    "content": "## Sūrya's Description Report\n\n### Files Description Table\n\n\n|  File Name  |  SHA-1 Hash  |\n|-------------|--------------|\n| src/FlashBull.sol | 8498f69dac8c8ab83647b18f6e77f759bd38178f |\n\n\n### Contracts Description Table\n\n\n|  Contract  |         Type        |       Bases      |                  |                 |\n|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:|\n|     └      |  **Function Name**  |  **Visibility**  |  **Mutability**  |  **Modifiers**  |\n||||||\n| **FlashBull** | Implementation | UniFlash |||\n| └ | <Constructor> | Public ❗️ | 🛑  | UniFlash |\n| └ | <Receive Ether> | External ❗️ |  💵 |NO❗️ |\n| └ | flashDeposit | External ❗️ |  💵 |NO❗️ |\n| └ | flashWithdraw | External ❗️ | 🛑  |NO❗️ |\n| └ | _uniFlashSwap | Internal 🔒 | 🛑  | |\n| └ | _calcwPowerPerpToMintAndFee | Internal 🔒 |   | |\n| └ | _calcSharesToMint | Internal 🔒 |   | |\n| └ | _getCrabVaultDetails | Internal 🔒 |   | |\n\n\n### Legend\n\n|  Symbol  |  Meaning  |\n|:--------:|-----------|\n|    🛑    | Function can modify state |\n|    💵    | Function is payable |\n"
  },
  {
    "path": "packages/zen-bull-vault/foundry.toml",
    "content": "[profile.default]\nsrc = 'src'\nout = 'out'\nlibs = ['lib']\ntest = 'test'\nauto_detect_solc = true\noptimizer = true\noptimizer_runs = 1500\n\n[profile.test]\nno_match_test = \"Fuzzing\"\nno_match_contract = \"Fuzz\"\ngas_reports = [\"ZenBullStrategy\", \"FlashZen\"]\n\n[profile.fuzz]\nruns = 2000\nmax_local_rejects = 1024\nmax_global_rejects = 65536\nseed = '0x3e8'\ndictionary_weight = 40\ninclude_storage = true\ninclude_push_bytes = true\nmatch_test = \"Fuzzing\"\nmatch_contract = \"Fuzz\"\n\n[profile.invariant]\nruns = 256\ndepth = 15\nfail_on_revert = false\ncall_override = false\ndictionary_weight = 80\ninclude_storage = true\ninclude_push_bytes = true\n\n[profile.fmt]\nline_length = 100\ntab_width = 4\nbracket_spacing = true\n\n[profile.coverage]\nvia_ir = true\nno_match_test = \"Fuzzing\"\n\n[profile.coverage.optimizer_details]\nconstantOptimizer = true\nyul = true\n\n[profile.coverage.optimizer_details.yulDetails]\nstackAllocation = true\noptimizerSteps = ''\n\n[rpc_endpoints]\nmainnet = \"${MAINNET_RPC_URL}\"\ngoerli = \"${GOERLI_RPC_URL}\"\n\n[etherscan]\ngoerli = { key = \"${ETHERSCAN_API_KEY}\" }\n\n# See more config options https://github.com/foundry-rs/foundry/tree/master/config"
  },
  {
    "path": "packages/zen-bull-vault/remappings.txt",
    "content": "ds-test/=lib/forge-std/lib/ds-test/src/\nforge-std/=lib/forge-std/src/\nopenzeppelin/=lib/openzeppelin-contracts/contracts/\nsolenv/=lib/solenv/src/\nsolidity-stringutils/=lib/solenv/lib/solidity-stringutils/src/\nsqueeth-monorepo/=lib/squeeth-monorepo/packages/hardhat/contracts/\nv3-core/=lib/v3-core/contracts/\nv3-periphery/=lib/v3-periphery/contracts/\n@openzeppelin=lib/openzeppelin-contracts/\n@uniswap/v3-core/=lib/v3-core/\n@uniswap/v3-periphery/=lib/v3-periphery/"
  },
  {
    "path": "packages/zen-bull-vault/script/AddLiquidityEuler.s.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\nimport \"forge-std/Script.sol\";\n\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IEulerEToken } from \"../src/interface/IEulerEToken.sol\";\nimport { IEulerMarkets } from \"../src/interface/IEulerMarkets.sol\";\n\ncontract AddLiquidityEuler is Script {\n    address private immutable euler;\n    address private immutable eulerMarkets;\n    address private immutable eToken;\n    address private immutable underlying;\n\n    constructor(address _euler, address _eulerMarkets, address _underlying, address _eToken) {\n        euler = _euler;\n        eulerMarkets = _eulerMarkets;\n        underlying = _underlying;\n        eToken = _eToken;\n    }\n\n    function run() public {\n        uint256 userKey = vm.envUint(\"SCRIPT_USER_PK\");\n        address userAddress = vm.rememberKey(userKey);\n        vm.startBroadcast(userAddress);\n\n        uint256 underlyingAmount = vm.envUint(\"UNDERLYING_AMOUNT\");\n        IERC20(underlying).approve(euler, underlyingAmount);\n\n        IEulerEToken(eToken).deposit(0, underlyingAmount);\n\n        IEulerMarkets markets = IEulerMarkets(eulerMarkets);\n        markets.enterMarket(0, underlying);\n\n        vm.stopBroadcast();\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/script/Deploy.s.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\nimport \"forge-std/Script.sol\";\n\nimport { ZenBullStrategy } from \"../src/ZenBullStrategy.sol\";\nimport { ZenEmergencyShutdown } from \"../src/ZenEmergencyShutdown.sol\";\nimport { ZenAuction } from \"../src/ZenAuction.sol\";\nimport { FlashZen } from \"../src/FlashZen.sol\";\n\ncontract DeployScript is Script {\n    /// @dev owner address for BullStrategy, EmergencyShutdown and AuctionBull\n    address private systemOwnerAddress;\n    address private auctionManagerAddress;\n    address private crabAddress;\n    address private powerTokenControllerAddress;\n    address private eulerAddress;\n    address private eulerMarketsModuleAddress;\n    address private uniFactoryAddress;\n    address private eTokenAddress;\n    address private dTokenAddress;\n\n    uint256 private zenBullStrategyCap;\n    uint256 private fullRebalancePriceTolerance;\n    uint256 private rebalanceWethLimitPriceTolerance;\n    uint256 private crUpper;\n    uint256 private crLower;\n    uint256 private deltaUpper;\n    uint256 private deltaLower;\n\n    // Deploy contracts\n    ZenBullStrategy zenBullStrategy;\n    ZenEmergencyShutdown emergencyShutdown;\n    ZenAuction zenAuction;\n    FlashZen flashZen;\n\n    function run() public {\n        uint256 deployerKey = vm.envUint(\"DEPLOYER_PK\");\n\n        address deployerAddress = vm.rememberKey(deployerKey);\n\n        vm.startBroadcast(deployerAddress);\n\n        // deploy contracts\n        zenBullStrategy =\n        new ZenBullStrategy(crabAddress, powerTokenControllerAddress, eulerAddress, eulerMarketsModuleAddress);\n        emergencyShutdown = new ZenEmergencyShutdown(address(zenBullStrategy), uniFactoryAddress);\n        zenAuction =\n        new ZenAuction(auctionManagerAddress, address(zenBullStrategy), uniFactoryAddress, crabAddress, eTokenAddress, dTokenAddress);\n        flashZen = new FlashZen(address(zenBullStrategy), uniFactoryAddress);\n\n        // set contracts params\n        setBullStrategyParams();\n        setAuctionBullParams();\n\n        // transfer ownership\n        transferOwnershipToSystemOwnerAddress();\n\n        vm.stopBroadcast();\n    }\n\n    function setAddressParamsAtConstructor(\n        address _systemOwnerAddress,\n        address _auctionManagerAddress,\n        address _crabAddress,\n        address _powerTokenControllerAddress,\n        address _eulerAddress,\n        address _eulerMarketsModuleAddress,\n        address _uniFactoryAddress,\n        address _eTokenAddress,\n        address _dTokenAddress\n    ) internal {\n        systemOwnerAddress = _systemOwnerAddress;\n        auctionManagerAddress = _auctionManagerAddress;\n        crabAddress = _crabAddress;\n        powerTokenControllerAddress = _powerTokenControllerAddress;\n        eulerAddress = _eulerAddress;\n        eulerMarketsModuleAddress = _eulerMarketsModuleAddress;\n        uniFactoryAddress = _uniFactoryAddress;\n        eTokenAddress = _eTokenAddress;\n        dTokenAddress = _dTokenAddress;\n    }\n\n    function setUintParamsAtConstructor(\n        uint256 _zenBullStrategyCap,\n        uint256 _fullRebalancePriceTolerance,\n        uint256 _rebalanceWethLimitPriceTolerance,\n        uint256 _crUpper,\n        uint256 _crLower,\n        uint256 _deltaUpper,\n        uint256 _deltaLower\n    ) internal {\n        zenBullStrategyCap = _zenBullStrategyCap;\n        fullRebalancePriceTolerance = _fullRebalancePriceTolerance;\n        rebalanceWethLimitPriceTolerance = _rebalanceWethLimitPriceTolerance;\n        crUpper = _crUpper;\n        crLower = _crLower;\n        deltaLower = _deltaLower;\n        deltaUpper = _deltaUpper;\n    }\n\n    function checkParams() private view {\n        require(systemOwnerAddress != address(0));\n        require(auctionManagerAddress != address(0));\n        require(crabAddress != address(0));\n        require(powerTokenControllerAddress != address(0));\n        require(eulerAddress != address(0));\n        require(eulerMarketsModuleAddress != address(0));\n        require(uniFactoryAddress != address(0));\n        require(eTokenAddress != address(0));\n        require(dTokenAddress != address(0));\n\n        require(zenBullStrategyCap > 0);\n    }\n\n    function setBullStrategyParams() private {\n        zenBullStrategy.setCap(zenBullStrategyCap);\n        zenBullStrategy.setShutdownContract(address(emergencyShutdown));\n        zenBullStrategy.setAuction(address(zenAuction));\n\n        require(zenBullStrategy.strategyCap() == zenBullStrategyCap);\n        require(zenBullStrategy.shutdownContract() == address(emergencyShutdown));\n        require(zenBullStrategy.auction() == address(zenAuction));\n    }\n\n    function setAuctionBullParams() private {\n        zenAuction.setAuctionManager(auctionManagerAddress);\n        zenAuction.setFullRebalanceClearingPriceTolerance(fullRebalancePriceTolerance);\n        zenAuction.setRebalanceWethLimitPriceTolerance(rebalanceWethLimitPriceTolerance);\n        zenAuction.setCrUpperAndLower(crLower, crUpper);\n        zenAuction.setDeltaUpperAndLower(deltaLower, deltaUpper);\n\n        require(zenAuction.auctionManager() == auctionManagerAddress);\n        require(zenAuction.fullRebalanceClearingPriceTolerance() == fullRebalancePriceTolerance);\n        require(zenAuction.rebalanceWethLimitPriceTolerance() == rebalanceWethLimitPriceTolerance);\n        require(zenAuction.crLower() == crLower && zenAuction.crUpper() == crUpper);\n        require(zenAuction.deltaLower() == deltaLower && zenAuction.deltaUpper() == deltaUpper);\n    }\n\n    function transferOwnershipToSystemOwnerAddress() private {\n        zenBullStrategy.transferOwnership(systemOwnerAddress);\n        emergencyShutdown.transferOwnership(systemOwnerAddress);\n        zenAuction.transferOwnership(systemOwnerAddress);\n\n        require(zenBullStrategy.owner() == systemOwnerAddress);\n        require(emergencyShutdown.owner() == systemOwnerAddress);\n        require(zenAuction.owner() == systemOwnerAddress);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/script/GoerliAddUsdcLiquidityEuler.s.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.7.6;\n\nimport { AddLiquidityEuler } from \"./AddLiquidityEuler.s.sol\";\n\ncontract GoerliAddUsdcLiquidityEuler is AddLiquidityEuler {\n    address public constant euler = 0x931172BB95549d0f29e10ae2D079ABA3C63318B3;\n    address public constant eulerMarkets = 0x3EbC39b84B1F856fAFE9803A9e1Eae7Da016Da36;\n    address public constant usdc = 0x306bf03b689f7d7e5e9D3aAC87a068F16AFF9482;\n    address public constant eUsdc = 0x19EB4AC774bB84Fe725cffB9F71D79ab2fB4E12a;\n\n    constructor() AddLiquidityEuler(euler, eulerMarkets, usdc, eUsdc) { }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/script/GoerliAddWethLiquidityEuler.s.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.7.6;\n\nimport { AddLiquidityEuler } from \"./AddLiquidityEuler.s.sol\";\n\ncontract GoerliAddWethLiquidityEuler is AddLiquidityEuler {\n    address public constant euler = 0x931172BB95549d0f29e10ae2D079ABA3C63318B3;\n    address public constant eulerMarkets = 0x3EbC39b84B1F856fAFE9803A9e1Eae7Da016Da36;\n    address public constant weth = 0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103;\n    address public constant eWeth = 0xEf5e087D827194732Bc1843351ccA80982E154eB;\n\n    constructor() AddLiquidityEuler(euler, eulerMarkets, weth, eWeth) { }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/script/GoerliDeploy.s.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.7.6;\n\nimport { DeployScript } from \"./Deploy.s.sol\";\n\ncontract GoerliDeploy is DeployScript {\n    address public constant systemOwnerAddress = 0xE3Dc747E5A8D8B664Dd701EE6A72AE63e740Ebc6;\n    address public constant auctionManagerAddress = 0xE3Dc747E5A8D8B664Dd701EE6A72AE63e740Ebc6;\n    address public constant crabAddress = 0x3fF39f6BF8156bdA997D93E3EFF6904c2bc4481f;\n    address public constant powerTokenControllerAddress = 0x6FC3f76f8a2D256Cc091bD58baB8c2Bc3F51d508;\n    address public constant eulerAddress = 0x931172BB95549d0f29e10ae2D079ABA3C63318B3;\n    address public constant eulerMarketsModuleAddress = 0x3EbC39b84B1F856fAFE9803A9e1Eae7Da016Da36;\n    address public constant uniFactoryAddress = 0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa;\n    address public constant eTokenAddress = 0xEf5e087D827194732Bc1843351ccA80982E154eB;\n    address public constant dTokenAddress = 0x356079240635B276A63065478471d89340443C49;\n    uint256 public constant bullStrategyCap = 500000e18;\n    uint256 public constant fullRebalancePriceTolerance = 0.05e18;\n    uint256 public constant rebalanceWethLimitPriceTolerance = 0.05e18;\n    uint256 public constant crUpper = 2.2e18;\n    uint256 public constant crLower = 1.8e18;\n    uint256 public constant deltaUpper = 1.1e18;\n    uint256 public constant deltaLower = 0.9e18;\n\n    constructor() {\n        setAddressParamsAtConstructor(\n            systemOwnerAddress,\n            auctionManagerAddress,\n            crabAddress,\n            powerTokenControllerAddress,\n            eulerAddress,\n            eulerMarketsModuleAddress,\n            uniFactoryAddress,\n            eTokenAddress,\n            dTokenAddress\n        );\n\n        setUintParamsAtConstructor(\n            bullStrategyCap,\n            fullRebalancePriceTolerance,\n            rebalanceWethLimitPriceTolerance,\n            crUpper,\n            crLower,\n            deltaUpper,\n            deltaLower\n        );\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/script/GoerliDeployEmergencyWithdraw.s.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\nimport \"forge-std/Script.sol\";\n\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { EmergencyWithdraw } from \"../src/EmergencyWithdraw.sol\";\n\ncontract GoerliDeployEmergencyWithdraw is Script {\n    address payable public constant ZEN_BULL = 0x2a5AD7582a9e42944Ee32671436593D16999c70a;\n    address public constant WETH = 0x083fd3D47eC8DC56b572321bc4dA8b26f7E82103;\n    address public constant CRAB = 0x3fF39f6BF8156bdA997D93E3EFF6904c2bc4481f;\n    address public constant UNI_FACTORY = 0x55C0ceF3cc64F511C34b18c720bCf38feC6C6fFa;\n    address public constant WPOWERPERP = 0x9421c968D28DD789363FbD8c9aA5cF2090F0a656;\n    address public constant ETH_USDC_POOL = 0x5d3EfE9157003f05be0d4031F00D43F952d6F6b7;\n    address public constant USDC = 0x306bf03b689f7d7e5e9D3aAC87a068F16AFF9482;\n    address public constant E_TOKEN = 0xEf5e087D827194732Bc1843351ccA80982E154eB;\n    address public constant D_TOKEN = 0x356079240635B276A63065478471d89340443C49;\n\n    // Deploy contracts\n    EmergencyWithdraw emergencyWithdraw;\n\n    function run() public {\n        uint256 deployerKey = vm.envUint(\"DEPLOYER_PK\");\n        address deployerAddress = vm.rememberKey(deployerKey);\n\n        vm.startBroadcast(deployerAddress);\n\n        emergencyWithdraw = new EmergencyWithdraw(\n            CRAB,\n            ZEN_BULL,\n            WETH,\n            USDC,\n            WPOWERPERP,\n            ETH_USDC_POOL,\n            E_TOKEN,\n            D_TOKEN,\n            UNI_FACTORY\n        );\n\n        vm.stopBroadcast();\n\n        require(emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal() == 0);\n        // require(\n        //     emergencyWithdraw.redeemedRecoveryAmountForEulerWithdrawal() ==\n        //         IERC20(ZEN_BULL).totalSupply()\n        // );\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/script/MainnetDeploy.s.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.7.6;\n\nimport { DeployScript } from \"./Deploy.s.sol\";\n\ncontract MainnetDeploy is DeployScript {\n    address public constant systemOwnerAddress = 0xAfE66363c27EedB597a140c28B70b32F113fd5a8;\n    address public constant auctionManagerAddress = 0xAfE66363c27EedB597a140c28B70b32F113fd5a8;\n    address public constant crabAddress = 0x3B960E47784150F5a63777201ee2B15253D713e8;\n    address public constant powerTokenControllerAddress = 0x64187ae08781B09368e6253F9E94951243A493D5;\n    address public constant eulerAddress = 0x27182842E098f60e3D576794A5bFFb0777E025d3;\n    address public constant eulerMarketsModuleAddress = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3;\n    address public constant uniFactoryAddress = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\n    address public constant eTokenAddress = 0x1b808F49ADD4b8C6b5117d9681cF7312Fcf0dC1D;\n    address public constant dTokenAddress = 0x84721A3dB22EB852233AEAE74f9bC8477F8bcc42;\n    uint256 public constant bullStrategyCap = 400e18;\n    uint256 public constant fullRebalancePriceTolerance = 0.05e18;\n    uint256 public constant rebalanceWethLimitPriceTolerance = 0.05e18;\n    uint256 public constant crUpper = 2.2e18;\n    uint256 public constant crLower = 1.8e18;\n    uint256 public constant deltaUpper = 1.1e18;\n    uint256 public constant deltaLower = 0.9e18;\n\n    constructor() {\n        setAddressParamsAtConstructor(\n            systemOwnerAddress,\n            auctionManagerAddress,\n            crabAddress,\n            powerTokenControllerAddress,\n            eulerAddress,\n            eulerMarketsModuleAddress,\n            uniFactoryAddress,\n            eTokenAddress,\n            dTokenAddress\n        );\n\n        setUintParamsAtConstructor(\n            bullStrategyCap,\n            fullRebalancePriceTolerance,\n            rebalanceWethLimitPriceTolerance,\n            crUpper,\n            crLower,\n            deltaUpper,\n            deltaLower\n        );\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/script/MainnetDeployEmergencyWithdraw.s.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\nimport \"forge-std/Script.sol\";\n\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { EmergencyWithdraw } from \"../src/EmergencyWithdraw.sol\";\n\n/**\n * Before running the deployment script, make sure to copy `.env.example` in a `.env` file and set the environment variables. (Mainly the MAINNET_RPC_URL, DEPLOYER_PK and ETHERSCAN_API_KEY vars)\n * This script can be executed using the below command:\n * - source .env\n * - forge script script/MainnetDeployEmergencyWithdraw.s.sol:MainnetDeployEmergencyWithdraw --rpc-url $MAINNET_RPC_URL --broadcast --verify -vvvv\n */\ncontract MainnetDeployEmergencyWithdraw is Script {\n    address payable public constant ZEN_BULL = 0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507;\n    address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n    address public constant CRAB = 0x3B960E47784150F5a63777201ee2B15253D713e8;\n    address public constant UNI_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\n    address public constant WPOWERPERP = 0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B;\n    address public constant ETH_USDC_POOL = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640;\n    address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n    address public constant E_TOKEN = 0x1b808F49ADD4b8C6b5117d9681cF7312Fcf0dC1D;\n    address public constant D_TOKEN = 0x84721A3dB22EB852233AEAE74f9bC8477F8bcc42;\n\n    // Deploy contracts\n    EmergencyWithdraw emergencyWithdraw;\n\n    function run() public {\n        uint256 deployerKey = vm.envUint(\"DEPLOYER_PK\");\n        address deployerAddress = vm.rememberKey(deployerKey);\n\n        vm.startBroadcast(deployerAddress);\n\n        emergencyWithdraw =\n        new EmergencyWithdraw(CRAB, ZEN_BULL, WETH, USDC, WPOWERPERP, ETH_USDC_POOL, E_TOKEN, D_TOKEN, UNI_FACTORY);\n\n        vm.stopBroadcast();\n\n        require(emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal() == 0);\n        require(emergencyWithdraw.redeemedRecoveryAmountForEulerWithdrawal() == 0);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/script/MainnetDeployShutdownEmergencyWithdraw.s.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\nimport \"forge-std/Script.sol\";\n\nimport { ShutdownEmergencyWithdraw } from \"../src/ShutdownEmergencyWithdraw.sol\";\n\n/**\n * Before running the deployment script, make sure to copy `.env.example` in a `.env` file and set the environment variables. (Mainly the MAINNET_RPC_URL, DEPLOYER_PK and ETHERSCAN_API_KEY vars)\n * This script can be executed using the below command:\n * - source .env\n * - forge script script/MainnetDeployShutdownEmergencyWithdraw.s.sol:MainnetDeployShutdownEmergencyWithdraw --rpc-url $MAINNET_RPC_URL --broadcast --verify -vvvv\n */\ncontract MainnetDeployShutdownEmergencyWithdraw is Script {\n    address payable public constant ZEN_BULL = 0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507;\n    address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n    address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n    address payable public constant CRAB = 0x3B960E47784150F5a63777201ee2B15253D713e8;\n    address public constant OSQTH = 0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B;\n    address public constant ETH_USDC_POOL = 0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8;\n    address payable public constant CONTROLLER = 0x64187ae08781B09368e6253F9E94951243A493D5;\n    address public constant ORACLE = 0x65D66c76447ccB45dAf1e8044e918fA786A483A1;\n    address public constant ZEN_BULL_EMERGENCY_WITHDRAW = 0x3DdC956B08c0A6dA2249f8c528fF0594F5AEa381;\n\n    // multisig owner\n    address public constant OWNER = 0xAfE66363c27EedB597a140c28B70b32F113fd5a8;\n\n    // Deploy contracts\n    ShutdownEmergencyWithdraw shutdownEmergencyWithdraw;\n\n    function run() public {\n        uint256 deployerKey = vm.envUint(\"DEPLOYER_PK\");\n        address deployerAddress = vm.rememberKey(deployerKey);\n\n        vm.startBroadcast(deployerAddress);\n\n        shutdownEmergencyWithdraw = new ShutdownEmergencyWithdraw(\n            CRAB,\n            ZEN_BULL,\n            WETH,\n            USDC,\n            OSQTH,\n            ETH_USDC_POOL,\n            ORACLE,\n            ZEN_BULL_EMERGENCY_WITHDRAW,\n            CONTROLLER,\n            OWNER\n        );\n\n        vm.stopBroadcast();\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/EmergencyWithdraw.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IZenBullStrategy } from \"./interface/IZenBullStrategy.sol\";\nimport { IWETH9 } from \"squeeth-monorepo/interfaces/IWETH9.sol\";\nimport { IEulerEToken } from \"./interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"./interface/IEulerDToken.sol\";\n// contract\nimport { ERC20 } from \"openzeppelin/token/ERC20/ERC20.sol\";\nimport { UniFlash } from \"./UniFlash.sol\";\nimport { UniOracle } from \"./UniOracle.sol\";\n// lib\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\nimport { Address } from \"openzeppelin/utils/Address.sol\";\n\ncontract EmergencyWithdraw is ERC20, UniFlash {\n    using StrategyMath for uint256;\n    using Address for address payable;\n\n    uint256 internal constant ONE = 1e18;\n    /// @dev WETH decimals - USDC decimals\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n    uint256 public constant MAX_WETH_PER_DEBT_REPAY = 100 ether;\n    uint256 public constant LIMIT_PRICE_TOLERANCE = 2e15; // 0.2%\n\n    /// @dev crab strategy address\n    address internal immutable crab;\n    /// @dev ZenBull strategy address\n    address internal immutable zenBull;\n    /// @dev WETH address\n    address internal immutable weth;\n    /// @dev USDC address\n    address internal immutable usdc;\n    /// @dev wPowerPerp address\n    address internal immutable wPowerPerp;\n    /// @dev eth/usdc uniswap pool address\n    address internal immutable ethUSDCPool;\n    address internal immutable eToken;\n    address internal immutable dToken;\n\n    /// @dev total amount of redeemed ZenBull through emergencyWithdrawEthFromCrab\n    uint256 public redeemedZenBullAmountForCrabWithdrawal;\n    /// @dev ZenBull total supply amount at the time of this contract deployment, used for Euler withdrawal calc\n    uint256 public redeemedRecoveryAmountForEulerWithdrawal;\n    /// @dev if true, ETH withdrawal is enabled, after 100% of Euler debt and collateral has been removed\n    bool public ethWithdrawalActivated;\n\n    enum FLASH_SOURCE {\n        EMERGENCY_WITHDRAW_ETH_FROM_CRAB,\n        EMERGENCY_REPAY_EULER_DEBT\n    }\n\n    event Withdraw(\n        address indexed recepient,\n        uint256 zenBullAmountRedeemed,\n        uint256 crabAmountRedeemed,\n        uint256 wPowerPerpRedeemed,\n        uint256 ethReceived,\n        uint256 eulerRecoveryTokenAmount\n    );\n    event EmergencyRepayEulerDebt(\n        address indexed sender,\n        uint256 ratio,\n        uint256 usdcToRepay,\n        uint256 wethToWithdraw,\n        uint256 maxEthForUsdc,\n        bool isEthWithdrawalActivated\n    );\n    event WithdrawEth(address indexed recepient, uint256 ethAmount);\n\n    /**\n     * @dev constructor\n     * @param _crab crab address\n     * @param _zenBull ZenBull address\n     * @param _weth WETH address\n     * @param _wPowerPerp WPowerPerp address\n     * @param _factory Uni V3 factory contract\n     */\n    constructor(\n        address _crab,\n        address _zenBull,\n        address _weth,\n        address _usdc,\n        address _wPowerPerp,\n        address _ethUSDCPool,\n        address _eToken,\n        address _dToken,\n        address _factory\n    ) ERC20(\"ZenBullEulerRecovery\", \"ZBER\") UniFlash(_factory) {\n        crab = _crab;\n        zenBull = _zenBull;\n        weth = _weth;\n        usdc = _usdc;\n        wPowerPerp = _wPowerPerp;\n        ethUSDCPool = _ethUSDCPool;\n        eToken = _eToken;\n        dToken = _dToken;\n\n        IERC20(_wPowerPerp).approve(_zenBull, type(uint256).max);\n        IERC20(_usdc).approve(_zenBull, type(uint256).max);\n    }\n\n    /**\n     * @dev receive ETH\n     */\n    receive() external payable {\n        require(msg.sender == weth, \"Can't receive ETH from this sender\");\n    }\n\n    /**\n     * @notice withdraw ETH deposited into crab\n     * @dev this will give the sender ZBEPR token as ownership for the ETH deposited in Euler pool\n     * @param _zenBullAmount ZenBull amount to redeem\n     * @param _maxEthForWPowerPerp max ETH to pay for flashswapped oSQTH amount\n     */\n    function emergencyWithdrawEthFromCrab(uint256 _zenBullAmount, uint256 _maxEthForWPowerPerp)\n        external\n    {\n        IERC20(zenBull).transferFrom(msg.sender, address(this), _zenBullAmount);\n\n        uint256 circulatingTotalSupply =\n            IERC20(zenBull).totalSupply().sub(redeemedZenBullAmountForCrabWithdrawal);\n        uint256 crabToRedeem = _zenBullAmount.wdiv(circulatingTotalSupply).wmul(\n            IZenBullStrategy(zenBull).getCrabBalance()\n        );\n        (, uint256 wPowerPerpInCrab) = IZenBullStrategy(zenBull).getCrabVaultDetails();\n        uint256 wPowerPerpToRedeem =\n            crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(crab).totalSupply());\n\n        _mint(msg.sender, _zenBullAmount);\n\n        redeemedZenBullAmountForCrabWithdrawal =\n            redeemedZenBullAmountForCrabWithdrawal.add(_zenBullAmount);\n\n        _exactOutFlashSwap(\n            weth,\n            wPowerPerp,\n            3000,\n            wPowerPerpToRedeem,\n            _maxEthForWPowerPerp,\n            uint8(FLASH_SOURCE.EMERGENCY_WITHDRAW_ETH_FROM_CRAB),\n            abi.encodePacked(crabToRedeem, wPowerPerpToRedeem)\n        );\n\n        uint256 payout = IERC20(weth).balanceOf(address(this));\n        IWETH9(weth).withdraw(payout);\n        payable(msg.sender).sendValue(payout);\n\n        emit Withdraw(\n            msg.sender, _zenBullAmount, crabToRedeem, wPowerPerpToRedeem, payout, _zenBullAmount\n        );\n    }\n\n    /**\n     * @notice repay a portion of Euler debt and withdraw WETH collateral to this contract based on ZenBullEulerRecovery amount\n     * @dev this will revert of WETH to withdraw from Euler is greater than max, or limit price breach the tolerance %\n     * @dev if all ZenBullEulerRecovery are burnt, the ETH withdrawl will be activated\n     * @param _ratio ratio of WETH to withdraw from total WETH in Euler in 18 decimals (e.g 2e17 => 0.2 => 20%)\n     * @param _limitPriceUsdcPerEth ETH limit price\n     * @param _poolFee ETH/USDC Uni v3 pool fee\n     */\n    function emergencyRepayEulerDebt(uint256 _ratio, uint256 _limitPriceUsdcPerEth, uint24 _poolFee)\n        external\n    {\n        uint256 usdcToRepay = _ratio.wmul(IEulerDToken(dToken).balanceOf(zenBull));\n        uint256 wethToWithdraw = _ratio.wmul(IEulerEToken(eToken).balanceOfUnderlying(zenBull));\n\n        require(\n            wethToWithdraw <= MAX_WETH_PER_DEBT_REPAY,\n            \"WETH to withdraw is greater than max per repay\"\n        );\n\n        uint256 ethUsdcPrice = UniOracle._getTwap(ethUSDCPool, weth, usdc, 420, false);\n\n        require(\n            _limitPriceUsdcPerEth >= ethUsdcPrice.wmul((ONE.sub(LIMIT_PRICE_TOLERANCE))),\n            \"ETH limit price lower than limit price tolerance\"\n        );\n\n        _exactOutFlashSwap(\n            weth,\n            usdc,\n            _poolFee,\n            usdcToRepay,\n            usdcToRepay.mul(WETH_DECIMALS_DIFF).wdiv(_limitPriceUsdcPerEth),\n            uint8(FLASH_SOURCE.EMERGENCY_REPAY_EULER_DEBT),\n            abi.encodePacked(usdcToRepay, wethToWithdraw)\n        );\n\n        IWETH9(weth).withdraw(IERC20(weth).balanceOf(address(this)));\n\n        if (\n            (IEulerEToken(eToken).balanceOfUnderlying(zenBull) == 0)\n                && (IEulerDToken(dToken).balanceOf(zenBull) == 0)\n        ) {\n            ethWithdrawalActivated = true;\n        }\n\n        emit EmergencyRepayEulerDebt(\n            msg.sender,\n            _ratio,\n            usdcToRepay,\n            wethToWithdraw,\n            _limitPriceUsdcPerEth,\n            ethWithdrawalActivated\n        );\n    }\n\n    /**\n     * @notice withdraw ETH from this contract, will revert if ZenBull still have some debt not repaid\n     */\n    function withdrawEth(uint256 _recoveryTokenAmount) external {\n        require(ethWithdrawalActivated, \"ETH withdrawal not activated yet\");\n\n        uint256 payout = _recoveryTokenAmount.wmul(address(this).balance).wdiv(\n            IERC20(zenBull).totalSupply().sub(redeemedRecoveryAmountForEulerWithdrawal)\n        );\n        redeemedRecoveryAmountForEulerWithdrawal =\n            redeemedRecoveryAmountForEulerWithdrawal.add(_recoveryTokenAmount);\n\n        _burn(msg.sender, _recoveryTokenAmount);\n        payable(msg.sender).sendValue(payout);\n\n        emit WithdrawEth(msg.sender, payout);\n    }\n\n    /**\n     * @dev function to handle Uni v3 FlashSwapCallBack\n     * @param _uniFlashSwapData data struct\n     */\n    function _uniFlashSwap(UniFlashswapCallbackData memory _uniFlashSwapData) internal override {\n        if (\n            FLASH_SOURCE(_uniFlashSwapData.callSource)\n                == FLASH_SOURCE.EMERGENCY_WITHDRAW_ETH_FROM_CRAB\n        ) {\n            (uint256 crabToRedeem, uint256 wPowerPerpToRedeem) =\n                abi.decode(_uniFlashSwapData.callData, (uint256, uint256));\n\n            IZenBullStrategy(zenBull).redeemCrabAndWithdrawWEth(crabToRedeem, wPowerPerpToRedeem);\n\n            IERC20(weth).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        } else if (\n            FLASH_SOURCE(_uniFlashSwapData.callSource) == FLASH_SOURCE.EMERGENCY_REPAY_EULER_DEBT\n        ) {\n            (uint256 usdcToRepay, uint256 wethToWithdraw) =\n                abi.decode(_uniFlashSwapData.callData, (uint256, uint256));\n\n            IZenBullStrategy(zenBull).auctionRepayAndWithdrawFromLeverage(\n                usdcToRepay, wethToWithdraw\n            );\n\n            IERC20(weth).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        }\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/FlashZen.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// interface\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IWETH9 } from \"squeeth-monorepo/interfaces/IWETH9.sol\";\nimport { ICrabStrategyV2 } from \"./interface/ICrabStrategyV2.sol\";\nimport { IZenBullStrategy } from \"./interface/IZenBullStrategy.sol\";\n// contract\nimport { UniFlash } from \"./UniFlash.sol\";\n// lib\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\nimport { Address } from \"openzeppelin/utils/Address.sol\";\nimport { UniOracle } from \"./UniOracle.sol\";\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\n\n/**\n * Error code\n * FB0: can only receive eth from weth contract or bull strategy\n */\n\n/**\n * @notice FlashZen contract\n * @dev handle the flashswap interactions\n * @author opyn team\n */\ncontract FlashZen is UniFlash {\n    using StrategyMath for uint256;\n    using Address for address payable;\n\n    /// @dev 1e18\n    uint256 private constant ONE = 1e18;\n    /// @dev TWAP period\n    uint32 private constant TWAP = 420;\n\n    /// @dev enum to differentiate between Uniswap swap callback function source\n    enum FLASH_SOURCE {\n        GENERAL_SWAP,\n        FLASH_DEPOSIT_CRAB,\n        FLASH_DEPOSIT_LENDING_COLLATERAL,\n        FLASH_SWAP_WPOWERPERP,\n        FLASH_WITHDRAW_BULL\n    }\n\n    /// @dev wPowerPerp address\n    address private immutable wPowerPerp;\n    /// @dev weth address\n    address private immutable weth;\n    /// @dev usdc address\n    address private immutable usdc;\n    /// @dev Crab V2 address\n    address private immutable crab;\n    /// @dev ETH:wPowerPerp Uniswap pool\n    address private immutable ethWPowerPerpPool;\n    /// @dev ETH:USDC Uniswap pool\n    address private immutable ethUSDCPool;\n    /// @dev bull stratgey address\n    address public immutable bullStrategy;\n    /// @dev power perp controller address\n    address private immutable powerTokenController;\n\n    /// @dev data structs from Uni v3 callback\n    struct FlashDepositCrabData {\n        uint256 ethToDepositInCrab;\n    }\n\n    /// @dev struct for data encoding\n    struct FlashDepositCollateralData {\n        uint256 crabToDeposit;\n        uint256 wethToLend;\n    }\n\n    /// @dev struct for data encoding\n    struct FlashWithdrawBullData {\n        uint256 bullToRedeem;\n        uint256 usdcToRepay;\n    }\n\n    /// @dev struct for data encoding\n    struct FlashSwapWPowerPerpData {\n        uint256 bullToRedeem;\n        uint256 crabToRedeem;\n        uint256 wPowerPerpToRedeem;\n        uint256 usdcToRepay;\n        uint256 maxEthForUsdc;\n        uint256 usdcPoolFee;\n    }\n\n    /// @dev flashDeposit params structs\n    struct FlashDepositParams {\n        uint256 ethToCrab;\n        uint256 minEthFromSqth;\n        uint256 minEthFromUsdc;\n        uint24 wPowerPerpPoolFee;\n        uint24 usdcPoolFee;\n    }\n\n    /// @dev flashWithdraw params structs\n    struct FlashWithdrawParams {\n        uint256 bullAmount;\n        uint256 maxEthForWPowerPerp;\n        uint256 maxEthForUsdc;\n        uint24 wPowerPerpPoolFee;\n        uint24 usdcPoolFee;\n    }\n\n    event FlashWithdraw(address indexed to, uint256 bullAmount, uint256 ethReturned);\n    event FlashDeposit(\n        address indexed from,\n        uint256 crabAmount,\n        uint256 ethDeposited,\n        uint256 wPowerPerpToMint,\n        uint256 usdcToBorrow,\n        uint256 wethToLend\n    );\n\n    /**\n     * @notice constructor\n     * @param _bull bull address\n     * @param _factory factory address\n     */\n    constructor(address _bull, address _factory) UniFlash(_factory) {\n        bullStrategy = _bull;\n        crab = IZenBullStrategy(_bull).crab();\n        powerTokenController = IZenBullStrategy(_bull).powerTokenController();\n        wPowerPerp = IController(IZenBullStrategy(_bull).powerTokenController()).wPowerPerp();\n        weth = IController(IZenBullStrategy(_bull).powerTokenController()).weth();\n        usdc = IController(IZenBullStrategy(_bull).powerTokenController()).quoteCurrency();\n        ethWPowerPerpPool =\n            IController(IZenBullStrategy(_bull).powerTokenController()).wPowerPerpPool();\n        ethUSDCPool =\n            IController(IZenBullStrategy(_bull).powerTokenController()).ethQuoteCurrencyPool();\n\n        ICrabStrategyV2(IZenBullStrategy(_bull).crab()).approve(_bull, type(uint256).max);\n        IERC20(IController(IZenBullStrategy(_bull).powerTokenController()).wPowerPerp()).approve(\n            _bull, type(uint256).max\n        );\n        IERC20(IController(IZenBullStrategy(_bull).powerTokenController()).quoteCurrency()).approve(\n            _bull, type(uint256).max\n        );\n    }\n\n    /**\n     * @notice receive function to allow ETH transfer to this contract\n     */\n    receive() external payable {\n        require(msg.sender == weth || msg.sender == bullStrategy, \"FB1\");\n    }\n\n    /**\n     * @notice flash deposit into strategy, providing ETH, selling wPowerPerp and USDC, and receiving strategy tokens\n     * @dev this function will execute a flash swap where it receives ETH from selling wPowerPerp and deposits into crab,\n     * @dev and buys ETH for USDC and repays the flashswap by depositing ETH into Euler and borrowing USDC and by minted wPowerPerp from depositing\n     * @param _params FlashDepositParams params\n     */\n    function flashDeposit(FlashDepositParams calldata _params) external payable {\n        uint256 crabAmount;\n        uint256 wPowerPerpToMint;\n        uint256 ethInCrab;\n        uint256 wPowerPerpInCrab;\n        {\n            (ethInCrab, wPowerPerpInCrab) = _getCrabVaultDetails();\n\n            uint256 ethFee;\n            (wPowerPerpToMint, ethFee) =\n                _calcwPowerPerpToMintAndFee(_params.ethToCrab, wPowerPerpInCrab, ethInCrab);\n            crabAmount = _calcSharesToMint(\n                _params.ethToCrab.sub(ethFee), ethInCrab, IERC20(crab).totalSupply()\n            );\n        }\n\n        // oSQTH-ETH swap\n        _exactInFlashSwap(\n            wPowerPerp,\n            weth,\n            _params.wPowerPerpPoolFee,\n            wPowerPerpToMint,\n            _params.minEthFromSqth,\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT_CRAB),\n            abi.encodePacked(_params.ethToCrab)\n        );\n\n        (ethInCrab, wPowerPerpInCrab) = _getCrabVaultDetails();\n        uint256 share;\n        if (IERC20(bullStrategy).totalSupply() == 0) {\n            share = ONE;\n        } else {\n            share = crabAmount.wdiv(IZenBullStrategy(bullStrategy).getCrabBalance().add(crabAmount));\n        }\n        (uint256 wethToLend, uint256 usdcToBorrow) = IZenBullStrategy(bullStrategy)\n            .calcLeverageEthUsdc(\n            crabAmount, share, ethInCrab, wPowerPerpInCrab, IERC20(crab).totalSupply()\n        );\n\n        // ETH-USDC swap\n        _exactInFlashSwap(\n            usdc,\n            weth,\n            _params.usdcPoolFee,\n            usdcToBorrow,\n            _params.minEthFromUsdc,\n            uint8(FLASH_SOURCE.FLASH_DEPOSIT_LENDING_COLLATERAL),\n            abi.encodePacked(crabAmount, wethToLend)\n        );\n\n        // return excess eth to the user that was not needed for slippage\n        if (address(this).balance > 0) {\n            payable(msg.sender).sendValue(address(this).balance);\n        }\n\n        IERC20(bullStrategy).transfer(msg.sender, IERC20(bullStrategy).balanceOf(address(this)));\n\n        emit FlashDeposit(\n            msg.sender, crabAmount, msg.value, wPowerPerpToMint, usdcToBorrow, wethToLend\n        );\n    }\n\n    /**\n     * @notice flash withdraw from strategy, receiving ETH and providing strategy tokens\n     * @dev buys wPowerPerp via flashswap for ETH to withdraw from crab and sells ETH for USDC to repay Euler debt and withdraw Euler collateral\n     * @dev proceeds from crab withdrawal and euler collateral are used to repay the flashswaps\n     * @param _params FlashWithdrawParams struct\n     */\n    function flashWithdraw(FlashWithdrawParams calldata _params) external {\n        IERC20(bullStrategy).transferFrom(msg.sender, address(this), _params.bullAmount);\n\n        uint256 usdcToRepay;\n        uint256 crabToRedeem;\n        uint256 wPowerPerpToRedeem;\n\n        {\n            uint256 bullShare = _params.bullAmount.wdiv(IERC20(bullStrategy).totalSupply());\n            crabToRedeem = bullShare.wmul(IZenBullStrategy(bullStrategy).getCrabBalance());\n            (, uint256 wPowerPerpInCrab) = _getCrabVaultDetails();\n            wPowerPerpToRedeem =\n                crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(crab).totalSupply());\n            usdcToRepay = IZenBullStrategy(bullStrategy).calcUsdcToRepay(bullShare);\n        }\n\n        // oSQTH-ETH swap\n        _exactOutFlashSwap(\n            weth,\n            wPowerPerp,\n            _params.wPowerPerpPoolFee,\n            wPowerPerpToRedeem,\n            _params.maxEthForWPowerPerp,\n            uint8(FLASH_SOURCE.FLASH_SWAP_WPOWERPERP),\n            abi.encodePacked(\n                _params.bullAmount,\n                crabToRedeem,\n                wPowerPerpToRedeem,\n                usdcToRepay,\n                _params.maxEthForUsdc,\n                uint256(_params.usdcPoolFee)\n            )\n        );\n\n        uint256 ethToReturn = address(this).balance;\n        payable(msg.sender).sendValue(ethToReturn);\n\n        emit FlashWithdraw(msg.sender, _params.bullAmount, ethToReturn);\n    }\n\n    /**\n     * @notice uniswap flash swap callback function to handle different types of flashswaps\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\n     * @param _uniFlashSwapData UniFlashswapCallbackData struct\n     */\n    function _uniFlashSwap(UniFlashswapCallbackData memory _uniFlashSwapData) internal override {\n        if (FLASH_SOURCE(_uniFlashSwapData.callSource) == FLASH_SOURCE.FLASH_DEPOSIT_CRAB) {\n            FlashDepositCrabData memory data =\n                abi.decode(_uniFlashSwapData.callData, (FlashDepositCrabData));\n\n            // convert WETH to ETH as Uniswap uses WETH\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\n            ICrabStrategyV2(crab).deposit{ value: data.ethToDepositInCrab }();\n\n            // repay the wPowerPerp flash swap\n            IERC20(wPowerPerp).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        } else if (\n            FLASH_SOURCE(_uniFlashSwapData.callSource)\n                == FLASH_SOURCE.FLASH_DEPOSIT_LENDING_COLLATERAL\n        ) {\n            FlashDepositCollateralData memory data =\n                abi.decode(_uniFlashSwapData.callData, (FlashDepositCollateralData));\n            IWETH9(weth).withdraw(IWETH9(weth).balanceOf(address(this)));\n\n            IZenBullStrategy(bullStrategy).deposit{ value: data.wethToLend }(data.crabToDeposit);\n\n            // repay the dollars flash swap\n            IERC20(usdc).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        } else if (FLASH_SOURCE(_uniFlashSwapData.callSource) == FLASH_SOURCE.FLASH_SWAP_WPOWERPERP)\n        {\n            FlashSwapWPowerPerpData memory data =\n                abi.decode(_uniFlashSwapData.callData, (FlashSwapWPowerPerpData));\n\n            // ETH-USDC swap\n            _exactOutFlashSwap(\n                weth,\n                usdc,\n                uint24(data.usdcPoolFee),\n                data.usdcToRepay,\n                data.maxEthForUsdc,\n                uint8(FLASH_SOURCE.FLASH_WITHDRAW_BULL),\n                abi.encodePacked(data.bullToRedeem, data.usdcToRepay)\n            );\n\n            IWETH9(weth).deposit{ value: _uniFlashSwapData.amountToPay }();\n            IERC20(weth).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        } else if (FLASH_SOURCE(_uniFlashSwapData.callSource) == FLASH_SOURCE.FLASH_WITHDRAW_BULL) {\n            FlashWithdrawBullData memory data =\n                abi.decode(_uniFlashSwapData.callData, (FlashWithdrawBullData));\n\n            IZenBullStrategy(bullStrategy).withdraw(data.bullToRedeem);\n\n            IWETH9(weth).deposit{ value: _uniFlashSwapData.amountToPay }();\n            IERC20(weth).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        }\n    }\n\n    /**\n     * @dev calculate amount of wPowerPerp to mint and fee based on ETH to deposit into crab\n     * @param _depositedEthAmount ETH amount deposited\n     * @param _strategyDebtAmount amount of wPowerPerp debt in vault\n     * @param _strategyCollateralAmount amount of ETH collateral in vault\n     * @return wPowerPerp to mint, mint fee amount\n     */\n    function _calcwPowerPerpToMintAndFee(\n        uint256 _depositedEthAmount,\n        uint256 _strategyDebtAmount,\n        uint256 _strategyCollateralAmount\n    ) internal view returns (uint256, uint256) {\n        uint256 wPowerPerpToMint;\n        uint256 feeRate = IController(powerTokenController).feeRate();\n        if (feeRate != 0) {\n            uint256 wPowerPerpEthPrice =\n                UniOracle._getTwap(ethWPowerPerpPool, wPowerPerp, weth, TWAP, false);\n            uint256 feeAdjustment = wPowerPerpEthPrice.mul(feeRate).div(10000);\n            wPowerPerpToMint = _depositedEthAmount.wmul(_strategyDebtAmount).wdiv(\n                _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\n            );\n            uint256 fee = wPowerPerpToMint.wmul(feeAdjustment);\n            return (wPowerPerpToMint, fee);\n        }\n        wPowerPerpToMint =\n            _depositedEthAmount.wmul(_strategyDebtAmount).wdiv(_strategyCollateralAmount);\n        return (wPowerPerpToMint, 0);\n    }\n\n    /**\n     * @dev calculate amount of strategy token to mint for depositor\n     * @param _amount amount of ETH deposited\n     * @param _strategyCollateralAmount amount of strategy collateral\n     * @param _crabTotalSupply total supply of strategy token\n     * @return amount of strategy token to mint\n     */\n    function _calcSharesToMint(\n        uint256 _amount,\n        uint256 _strategyCollateralAmount,\n        uint256 _crabTotalSupply\n    ) internal pure returns (uint256) {\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\n\n        if (_crabTotalSupply != 0) {\n            return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\n        }\n\n        return _amount;\n    }\n\n    /**\n     * @notice get crab vault debt and collateral details\n     * @return vault eth collateral, vault wPowerPerp debt\n     */\n\n    function _getCrabVaultDetails() internal view returns (uint256, uint256) {\n        VaultLib.Vault memory strategyVault =\n            IController(powerTokenController).vaults(ICrabStrategyV2(crab).vaultId());\n\n        return (strategyVault.collateralAmount, strategyVault.shortAmount);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/LeverageZen.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity =0.7.6;\n\n// interface\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IWETH9 } from \"squeeth-monorepo/interfaces/IWETH9.sol\";\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IEulerMarkets } from \"./interface/IEulerMarkets.sol\";\nimport { IEulerEToken } from \"./interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"./interface/IEulerDToken.sol\";\n// contract\nimport { Ownable } from \"openzeppelin/access/Ownable.sol\";\n// lib\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\nimport { UniOracle } from \"./UniOracle.sol\";\n\n/**\n * Error codes\n * LB0: ETH sent is not at least ETH to deposit in Euler\n * LB1: caller is not auction address\n * LB2: auction can not be set to 0 address\n */\n\n/**\n * @notice LeverageZen contract\n * @dev contract that interacts with leverage component (borrow and collateral on Euler)\n * @author opyn team\n */\ncontract LeverageZen is Ownable {\n    using StrategyMath for uint256;\n\n    /// @dev TWAP period\n    uint32 internal constant TWAP = 420;\n    /// @dev 1e18\n    uint256 internal constant ONE = 1e18;\n    /// @dev WETH decimals - USDC decimals\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n    /// @dev target CR for our ETH collateral\n    uint256 public constant TARGET_CR = 2e18; // 2 collat ratio\n\n    /// @dev ETH:wPowerPerp Uniswap pool\n    address internal immutable ethWPowerPerpPool;\n    /// @dev ETH:USDC Uniswap pool\n    address internal immutable ethUSDCPool;\n    /// @dev wPowerPerp address\n    address internal immutable wPowerPerp;\n    /// @dev USDC address\n    address internal immutable usdc;\n    /// @dev WETH address\n    address internal immutable weth;\n    /// @dev euler markets module\n    address internal immutable eulerMarkets;\n    /// @dev euler eToken that represent the collateral asset (WETH)\n    address internal immutable eToken;\n    /// @dev euler dToken that represent the borrowed asset (USDC)\n    address internal immutable dToken;\n    /// @dev auction contract address\n    address public auction;\n\n    event AuctionRepayAndWithdrawFromLeverage(\n        address indexed from, uint256 usdcToRepay, uint256 wethToWithdraw\n    );\n    event SetAuction(address oldAuction, address newAuction);\n\n    event DepositAndRepayFromLeverage(\n        address indexed from, uint256 wethDeposited, uint256 usdcRepaid\n    );\n\n    /**\n     * @dev constructor\n     * @param _euler euler address\n     * @param _eulerMarkets euler markets module address\n     * @param _powerTokenController wPowerPerp controller address\n     */\n    constructor(address _euler, address _eulerMarkets, address _powerTokenController) Ownable() {\n        eulerMarkets = _eulerMarkets;\n        eToken = IEulerMarkets(_eulerMarkets).underlyingToEToken(\n            IController(_powerTokenController).weth()\n        );\n        dToken = IEulerMarkets(_eulerMarkets).underlyingToDToken(\n            IController(_powerTokenController).quoteCurrency()\n        );\n        weth = IController(_powerTokenController).weth();\n        usdc = IController(_powerTokenController).quoteCurrency();\n        wPowerPerp = IController(_powerTokenController).wPowerPerp();\n        ethWPowerPerpPool = IController(_powerTokenController).wPowerPerpPool();\n        ethUSDCPool = IController(_powerTokenController).ethQuoteCurrencyPool();\n\n        IERC20(IController(_powerTokenController).weth()).approve(_euler, type(uint256).max);\n        IERC20(IController(_powerTokenController).quoteCurrency()).approve(\n            _euler, type(uint256).max\n        );\n\n        IEulerMarkets(_eulerMarkets).enterMarket(0, IController(_powerTokenController).weth());\n    }\n\n    /**\n     * @notice sets the auction implementation contract that is able to call functions to adjust debt and collateral in an auction\n     * @param _auction new auction address\n     */\n    function setAuction(address _auction) external onlyOwner {\n        require(_auction != address(0), \"LB2\");\n\n        emit SetAuction(auction, _auction);\n\n        auction = _auction;\n    }\n\n    /**\n     * @notice called by the auction address to repay USDC debt and withdraw weth from Euler\n     * @param _usdcToRepay amount of USDC to repay\n     * @param _wethToWithdraw amount of WETH to withdraw\n     */\n    function auctionRepayAndWithdrawFromLeverage(uint256 _usdcToRepay, uint256 _wethToWithdraw)\n        external\n    {\n        require(msg.sender == auction, \"LB1\");\n\n        if (_usdcToRepay > 0) {\n            IERC20(usdc).transferFrom(msg.sender, address(this), _usdcToRepay);\n            IEulerDToken(dToken).repay(0, _usdcToRepay);\n        }\n        if (_wethToWithdraw > 0) {\n            IEulerEToken(eToken).withdraw(0, _wethToWithdraw);\n            IERC20(weth).transfer(msg.sender, _wethToWithdraw);\n        }\n\n        emit AuctionRepayAndWithdrawFromLeverage(msg.sender, _usdcToRepay, _wethToWithdraw);\n    }\n\n    /**\n     * @notice called by the auction address to depost WETH in Euler or borrow USDC debt\n     * @param _wethToDeposit amount of WETH to deposit\n     * @param _usdcToBorrow amount of USDC to borrow\n     */\n    function depositAndBorrowFromLeverage(uint256 _wethToDeposit, uint256 _usdcToBorrow) external {\n        require(msg.sender == auction, \"LB1\");\n\n        if (_wethToDeposit > 0) {\n            IERC20(weth).transferFrom(msg.sender, address(this), _wethToDeposit);\n            IEulerEToken(eToken).deposit(0, _wethToDeposit);\n        }\n        if (_usdcToBorrow > 0) {\n            IEulerDToken(dToken).borrow(0, _usdcToBorrow);\n            IERC20(usdc).transfer(msg.sender, _usdcToBorrow);\n        }\n    }\n\n    /**\n     * @notice called by the auction address to deposit more WETH into Euler or repay USDC debt\n     * @param _wethToDeposit WETH amount to deposit\n     * @param _usdcToRepay USDC amount to repay\n     */\n    function auctionDepositAndRepayFromLeverage(uint256 _wethToDeposit, uint256 _usdcToRepay)\n        external\n    {\n        require(msg.sender == auction, \"LB1\");\n\n        if (_wethToDeposit > 0) {\n            IERC20(weth).transferFrom(msg.sender, address(this), _wethToDeposit);\n            IEulerEToken(eToken).deposit(0, _wethToDeposit);\n        }\n        if (_usdcToRepay > 0) {\n            IERC20(usdc).transferFrom(msg.sender, address(this), _usdcToRepay);\n            IEulerDToken(dToken).repay(0, _usdcToRepay);\n        }\n\n        emit DepositAndRepayFromLeverage(msg.sender, _wethToDeposit, _usdcToRepay);\n    }\n\n    /**\n     * @notice calculate target amounts of weth collateral and usdc debt based on crab and bull state\n     * @param _crabAmount amount of crab\n     * @param _bullShare share of bull contract scaled to 1e18\n     * @param _ethInCrab ETH collateral held through crab's vault\n     * @param _wPowerPerpInCrab wPowerPerp debt owed through crab's vault\n     * @param _totalCrabSupply total supply of crab token\n     * @return weth to lend in Euler, usdc to borrow in Euler\n     */\n    function calcLeverageEthUsdc(\n        uint256 _crabAmount,\n        uint256 _bullShare,\n        uint256 _ethInCrab,\n        uint256 _wPowerPerpInCrab,\n        uint256 _totalCrabSupply\n    ) external view returns (uint256, uint256) {\n        return _calcLeverageWethUsdc(\n            _crabAmount, _bullShare, _ethInCrab, _wPowerPerpInCrab, _totalCrabSupply\n        );\n    }\n\n    /**\n     * @notice calculate amount of USDC debt to to repay to Euler based on amount of share of bull token\n     * @param _bullShare bull share amount\n     * @return USDC to repay\n     */\n    function calcUsdcToRepay(uint256 _bullShare) external view returns (uint256) {\n        return _calcUsdcToRepay(_bullShare);\n    }\n\n    /**\n     * @notice calculate amount of ETH collateral to withdraw to Euler based on amount of share of bull token\n     * @param _bullShare bull share amount\n     * @return WETH to withdraw\n     */\n    function calcWethToWithdraw(uint256 _bullShare) external view returns (uint256) {\n        return _calcWethToWithdraw(_bullShare);\n    }\n\n    /**\n     * @notice deposit ETH into leverage component and borrow USDC\n     * @dev this function handles only the leverage component part\n     * @param _crabAmount amount of crab token deposited\n     * @param _bullShare amount of bull share minted\n     * @param _ethInCrab eth in crab strategy\n     * @param _wPowerPerpInCrab wPowerPerp debt of crab strategy\n     * @param _crabTotalSupply total supply of crab tokens\n     * @return ETH deposited as collateral in Euler and borrowed amount of USDC, and total ETH deposited as collateral in Euler\n     */\n    function _leverageDeposit(\n        uint256 _crabAmount,\n        uint256 _bullShare,\n        uint256 _ethInCrab,\n        uint256 _wPowerPerpInCrab,\n        uint256 _crabTotalSupply\n    ) internal returns (uint256, uint256, uint256) {\n        (uint256 wethToLend, uint256 usdcToBorrow) = _calcLeverageWethUsdc(\n            _crabAmount, _bullShare, _ethInCrab, _wPowerPerpInCrab, _crabTotalSupply\n        );\n\n        require(wethToLend <= msg.value, \"LB0\");\n\n        _depositWethInEuler(wethToLend);\n        _borrowUsdcFromEuler(usdcToBorrow);\n\n        return (wethToLend, usdcToBorrow, IEulerEToken(eToken).balanceOfUnderlying(address(this)));\n    }\n\n    /**\n     * @notice deposit weth as collateral in Euler market\n     * @param _ethToDeposit amount of ETH to deposit\n     */\n    function _depositWethInEuler(uint256 _ethToDeposit) internal {\n        IWETH9(weth).deposit{ value: _ethToDeposit }();\n        IEulerEToken(eToken).deposit(0, _ethToDeposit);\n    }\n\n    /**\n     * @notice borrow USDC from Euler against deposited collateral\n     * @param _usdcToBorrow amount of USDC to borrow\n     */\n    function _borrowUsdcFromEuler(uint256 _usdcToBorrow) internal {\n        IEulerDToken(dToken).borrow(0, _usdcToBorrow);\n    }\n\n    /**\n     * @notice repay USDC debt to euler and withdraw collateral based on the bull share amount to burn\n     * @param _bullShare amount of bull share to burn\n     */\n    function _repayAndWithdrawFromLeverage(uint256 _bullShare)\n        internal\n        returns (uint256, uint256)\n    {\n        uint256 usdcToRepay = _calcUsdcToRepay(_bullShare);\n        uint256 wethToWithdraw = _calcWethToWithdraw(_bullShare);\n\n        IERC20(usdc).transferFrom(msg.sender, address(this), usdcToRepay);\n        IEulerDToken(dToken).repay(0, usdcToRepay);\n        IEulerEToken(eToken).withdraw(0, wethToWithdraw);\n\n        IWETH9(weth).withdraw(wethToWithdraw);\n\n        return (usdcToRepay, wethToWithdraw);\n    }\n\n    /**\n     * @notice calculate target amounts of weth collateral and usdc debt based on crab and bull state\n     * @param _crabAmount amount of crab\n     * @param _bullShare share of bull contract scaled to 1e18\n     * @param _ethInCrab ETH collateral held through crab's vault\n     * @param _wPowerPerpInCrab wPowerPerp debt owed through crab's vault\n     * @param _totalCrabSupply total supply of crab token\n     * @return weth to lend in Euler, usdc to borrow in Euler\n     */\n    function _calcLeverageWethUsdc(\n        uint256 _crabAmount,\n        uint256 _bullShare,\n        uint256 _ethInCrab,\n        uint256 _wPowerPerpInCrab,\n        uint256 _totalCrabSupply\n    ) internal view returns (uint256, uint256) {\n        uint256 wethToLend;\n        {\n            if (_bullShare == ONE) {\n                uint256 ethUsdPrice = UniOracle._getTwap(ethUSDCPool, weth, usdc, TWAP, false);\n                uint256 wPowerPerpEthPrice =\n                    UniOracle._getTwap(ethWPowerPerpPool, wPowerPerp, weth, TWAP, false);\n                uint256 crabUsdPrice = (\n                    _ethInCrab.wmul(ethUsdPrice).sub(\n                        _wPowerPerpInCrab.wmul(wPowerPerpEthPrice).wmul(ethUsdPrice)\n                    )\n                ).wdiv(_totalCrabSupply);\n                wethToLend = TARGET_CR.wmul(_crabAmount).wmul(crabUsdPrice).wdiv(ethUsdPrice);\n                uint256 usdcToBorrow =\n                    wethToLend.wmul(ethUsdPrice).wdiv(TARGET_CR).div(WETH_DECIMALS_DIFF);\n                return (wethToLend, usdcToBorrow);\n            }\n        }\n        wethToLend = IEulerEToken(eToken).balanceOfUnderlying(address(this)).wmul(_bullShare).wdiv(\n            ONE.sub(_bullShare)\n        );\n        uint256 usdcToBorrow =\n            IEulerDToken(dToken).balanceOf(address(this)).wmul(_bullShare).wdiv(ONE.sub(_bullShare));\n        return (wethToLend, usdcToBorrow);\n    }\n\n    /**\n     * @notice calculate amount of WETH to withdraw from Euler based on share of bull token\n     * @param _bullShare bull share amount\n     * @return WETH to withdraw\n     */\n    function _calcWethToWithdraw(uint256 _bullShare) internal view returns (uint256) {\n        return _bullShare.wmul(IEulerEToken(eToken).balanceOfUnderlying(address(this)));\n    }\n\n    /**\n     * @notice calculate amount of USDC debt to to repay to Euler based on share of bull token\n     * @param _bullShare bull share amount\n     * @return USDC to repay\n     */\n    function _calcUsdcToRepay(uint256 _bullShare) internal view returns (uint256) {\n        return _bullShare.wmul(IEulerDToken(dToken).balanceOf(address(this)));\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/ShutdownEmergencyWithdraw.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IZenBullStrategy } from \"./interface/IZenBullStrategy.sol\";\nimport { IZenEmergencyWithdraw } from \"./interface/IZenEmergencyWithdraw.sol\";\nimport { IWETH9 } from \"squeeth-monorepo/interfaces/IWETH9.sol\";\nimport { IOracle } from \"squeeth-monorepo/interfaces/IOracle.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\n// contract\nimport { Ownable } from \"openzeppelin/access/Ownable.sol\";\n// lib\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\nimport { Address } from \"openzeppelin/utils/Address.sol\";\n\ncontract ShutdownEmergencyWithdraw is Ownable {\n    using StrategyMath for uint256;\n    using Address for address payable;\n\n    uint256 public constant INDEX_SCALE = 1e4;\n    uint32 public constant TWAP_PERIOD = 420 seconds;\n\n    /// @dev crab strategy address\n    address internal immutable crab;\n    /// @dev ZenBull strategy address\n    address internal immutable zenBull;\n    /// @dev WETH address\n    address internal immutable weth;\n    /// @dev USDC address\n    address internal immutable usdc;\n    /// @dev ETH:USDC pool address\n    address internal immutable ethUsdcPool;\n    /// @dev wPowerPerp address\n    address internal immutable wPowerPerp;\n    /// @dev oracle address\n    address internal immutable oracle;\n    /// @dev ZenBull emergency withdraw address\n    address internal immutable zenBullEmergencyWithdraw;\n    /// @dev controller address\n    address internal immutable controller;\n    /// @dev amount of weth available for redemption\n    uint256 public wethAtRedemption;\n    /// @dev zen bull total supply at redemption\n    uint256 public zenBullTotalSupplyAtRedemption;\n\n    event ShutdownEmergencyWithdraw(\n        address indexed sender,\n        uint256 crabAmountRedeemed,\n        uint256 wPowerPerpRedeemed,\n        uint256 totalPayout,\n        uint256 ethValueInWPowerPerp,\n        uint256 wethAtRedemption\n    );\n\n    event ZenBullRedeemed(address indexed sender, uint256 zenAmountRedeemed, uint256 wethReceived);\n\n    /**\n     * @dev constructor\n     * @param _crab crab address\n     * @param _zenBull ZenBull address\n     * @param _weth WETH address\n     * @param _usdc USDC address\n     * @param _wPowerPerp WPowerPerp address\n     * @param _oracle oracle address\n     * @param _zenBullEmergencyWithdraw ZenBull emergency withdraw address\n     * @param _controller controller address\n     * @param _ethUsdcPool ETH:USDC pool address\n     */\n    constructor(\n        address _crab,\n        address _zenBull,\n        address _weth,\n        address _usdc,\n        address _wPowerPerp,\n        address _ethUsdcPool,\n        address _oracle,\n        address _zenBullEmergencyWithdraw,\n        address _controller,\n        address _owner\n    ) {\n        crab = _crab;\n        zenBull = _zenBull;\n        weth = _weth;\n        usdc = _usdc;\n        wPowerPerp = _wPowerPerp;\n        oracle = _oracle;\n        controller = _controller;\n        zenBullEmergencyWithdraw = _zenBullEmergencyWithdraw;\n        ethUsdcPool = _ethUsdcPool;\n        transferOwnership(_owner);\n        IERC20(_wPowerPerp).approve(_zenBull, type(uint256).max);\n    }\n\n    /**\n     * @dev receive ETH\n     */\n    receive() external payable {\n        require(msg.sender == weth, \"Can't receive ETH from sender\");\n    }\n\n    /**\n    * @notice emergency function to withdraw remaining Crab tokens from ZenBull and unwind positions\n    * @dev only callable by owner. Must be called before users can claim their share via claimZenBullRedemption\n    * @dev zen bull holders will be able to redeem their proportional share of the withdrawn WETH\n    * @dev this function:\n    * 1. calculates how many wPowerPerp tokens are needed to redeem the Crab position\n    * 2. takes wPowerPerp tokens from msg.sender (the person helping unwind)\n    * 3. redeems Crab tokens for WETH\n    * 4. compensates msg.sender with WETH equal to their wPowerPerp value\n    * 5. keeps remaining WETH for ZenBull holders to claim\n    */\n    function shutdownEmergencyWithdraw() external onlyOwner {\n        require(zenBullTotalSupplyAtRedemption == 0, \"ZenBull total supply set\");\n        uint256 crabToRedeem = IZenBullStrategy(zenBull).getCrabBalance();\n        (, uint256 wPowerPerpInCrab) = IZenBullStrategy(zenBull).getCrabVaultDetails();\n\n        uint256 ethIndexPrice =\n            IOracle(oracle).getTwap(ethUsdcPool, weth, usdc, TWAP_PERIOD, true).div(INDEX_SCALE);\n\n        uint256 wPowerPerpToRedeem =\n            crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(crab).totalSupply());\n        uint256 wPowerPerpValueInEth = wPowerPerpToRedeem.wmul(ethIndexPrice).wmul(\n            IController(controller).getExpectedNormalizationFactor()\n        );\n\n        IERC20(wPowerPerp).transferFrom(msg.sender, address(this), wPowerPerpToRedeem);\n\n        uint256 totalPayout =\n            IZenBullStrategy(zenBull).redeemCrabAndWithdrawWEth(crabToRedeem, wPowerPerpToRedeem);\n\n        IERC20(weth).transfer(msg.sender, wPowerPerpValueInEth);\n\n        zenBullTotalSupplyAtRedemption = IERC20(zenBull).totalSupply()\n            - IZenEmergencyWithdraw(zenBullEmergencyWithdraw).redeemedZenBullAmountForCrabWithdrawal();\n\n        wethAtRedemption = IERC20(weth).balanceOf(address(this));\n\n        emit ShutdownEmergencyWithdraw(\n            msg.sender,\n            crabToRedeem,\n            wPowerPerpToRedeem,\n            totalPayout,\n            wPowerPerpValueInEth,\n            wethAtRedemption\n        );\n    }\n\n\n    /**\n    * @notice allows ZenBull token holders to claim their proportional share of WETH after emergency shutdown\n    * @dev after shutdownEmergencyWithdraw has been called, ZenBull holders can redeem their tokens for WETH\n    * @dev the WETH amount received is proportional to their share of remaining circulating ZenBull supply at time of shutdown\n    * @dev wethOwed = (amountToRedeem / zenBullTotalSupplyAtRedemption) * wethAtRedemption\n    * @param _amountToRedeem an amount of ZenBull tokens to redeem for WETH\n    */\n    function claimZenBullRedemption(uint256 _amountToRedeem) external {\n        require(zenBullTotalSupplyAtRedemption != 0, \"Emergency withdraw not called\");\n        IERC20(zenBull).transferFrom(msg.sender, address(this), _amountToRedeem);\n        uint256 wethOwed =\n            _amountToRedeem.wmul(wethAtRedemption).wdiv(zenBullTotalSupplyAtRedemption);\n        IERC20(weth).transfer(msg.sender, wethOwed);\n        emit ZenBullRedeemed(msg.sender, _amountToRedeem, wethOwed);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/UniFlash.sol",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport \"v3-core/interfaces/callback/IUniswapV3SwapCallback.sol\";\nimport \"v3-core/interfaces/IUniswapV3Pool.sol\";\n// lib\nimport \"v3-periphery/libraries/Path.sol\";\nimport \"v3-periphery/libraries/PoolAddress.sol\";\nimport \"v3-periphery/libraries/CallbackValidation.sol\";\nimport \"v3-core/libraries/TickMath.sol\";\nimport \"v3-core/libraries/SafeCast.sol\";\nimport { SafeMath } from \"openzeppelin/math/SafeMath.sol\";\n\n/**\n * @notice UniFlash contract\n * @dev contract that interacts with Uniswap pool\n * @author opyn team\n */\nabstract contract UniFlash is IUniswapV3SwapCallback {\n    using Path for bytes;\n    using SafeCast for uint256;\n    using SafeMath for uint256;\n\n    /// @dev Uniswap factory address\n    address internal immutable factory;\n\n    struct SwapCallbackData {\n        bytes path;\n        address caller;\n        uint8 callSource;\n        bytes callData;\n    }\n\n    struct UniFlashswapCallbackData {\n        address pool;\n        address caller;\n        address tokenIn;\n        address tokenOut;\n        uint24 fee;\n        uint256 amountToPay;\n        bytes callData;\n        uint8 callSource;\n    }\n\n    /**\n     * @dev constructor\n     * @param _factory uniswap factory address\n     */\n    constructor(address _factory) {\n        require(_factory != address(0), \"invalid factory address\");\n        factory = _factory;\n    }\n\n    /**\n     * @notice uniswap swap callback function for flashes\n     * @param amount0Delta amount of token0\n     * @param amount1Delta amount of token1\n     * @param _data callback data encoded as SwapCallbackData struct\n     */\n    function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data)\n        external\n        override\n    {\n        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported\n\n        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\n\n        //ensure that callback comes from uniswap pool\n        address pool = address(CallbackValidation.verifyCallback(factory, tokenIn, tokenOut, fee));\n\n        //determine the amount that needs to be repaid as part of the flashswap\n        uint256 amountToPay = amount0Delta > 0 ? uint256(amount0Delta) : uint256(amount1Delta);\n\n        //calls the strategy function that uses the proceeds from flash swap and executes logic to have an amount of token to repay the flash swap\n        _uniFlashSwap(\n            UniFlashswapCallbackData(\n                pool,\n                data.caller,\n                tokenIn,\n                tokenOut,\n                fee,\n                amountToPay,\n                data.callData,\n                data.callSource\n            )\n        );\n    }\n\n    /**\n     * @notice function to be called by uniswap callback.\n     * @dev this function should be overridden by the child contract\n     * @param _uniFlashSwapData UniFlashswapCallbackData struct\n     */\n    function _uniFlashSwap(UniFlashswapCallbackData memory _uniFlashSwapData) internal virtual { }\n\n    /**\n     * @notice execute an exact-in flash swap (specify an exact amount to pay)\n     * @param _tokenIn token address to sell\n     * @param _tokenOut token address to receive\n     * @param _fee pool fee\n     * @param _amountIn amount to sell\n     * @param _amountOutMinimum minimum amount to receive\n     * @param _callSource function call source\n     * @param _data arbitrary data assigned with the call\n     */\n    function _exactInFlashSwap(\n        address _tokenIn,\n        address _tokenOut,\n        uint24 _fee,\n        uint256 _amountIn,\n        uint256 _amountOutMinimum,\n        uint8 _callSource,\n        bytes memory _data\n    ) internal returns (uint256) {\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\n        uint256 amountOut = _exactInputInternal(\n            _amountIn,\n            address(this),\n            uint160(0),\n            SwapCallbackData({\n                path: abi.encodePacked(_tokenIn, _fee, _tokenOut),\n                caller: msg.sender,\n                callSource: _callSource,\n                callData: _data\n            })\n        );\n\n        //slippage limit check\n        require(amountOut >= _amountOutMinimum, \"amount out less than min\");\n\n        return amountOut;\n    }\n\n    /**\n     * @notice execute an exact-out flash swap (specify an exact amount to receive)\n     * @param _tokenIn token address to sell\n     * @param _tokenOut token address to receive\n     * @param _fee pool fee\n     * @param _amountOut exact amount to receive\n     * @param _amountInMaximum maximum amount to sell\n     * @param _callSource function call source\n     * @param _data arbitrary data assigned with the call\n     */\n    function _exactOutFlashSwap(\n        address _tokenIn,\n        address _tokenOut,\n        uint24 _fee,\n        uint256 _amountOut,\n        uint256 _amountInMaximum,\n        uint8 _callSource,\n        bytes memory _data\n    ) internal {\n        //calls internal uniswap swap function that will trigger a callback for the flash swap\n        uint256 amountIn = _exactOutputInternal(\n            _amountOut,\n            address(this),\n            uint160(0),\n            SwapCallbackData({\n                path: abi.encodePacked(_tokenOut, _fee, _tokenIn),\n                caller: msg.sender,\n                callSource: _callSource,\n                callData: _data\n            })\n        );\n\n        //slippage limit check\n        require(amountIn <= _amountInMaximum, \"amount in greater than max\");\n    }\n\n    /**\n     * @notice internal function for exact-in swap on uniswap (specify exact amount to pay)\n     * @param _amountIn amount of token to pay\n     * @param _recipient recipient for receive\n     * @param _sqrtPriceLimitX96 sqrt price limit\n     * @return amount of token bought (amountOut)\n     */\n    function _exactInputInternal(\n        uint256 _amountIn,\n        address _recipient,\n        uint160 _sqrtPriceLimitX96,\n        SwapCallbackData memory data\n    ) private returns (uint256) {\n        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();\n\n        //uniswap token0 has a lower address than token1\n        //if tokenIn<tokenOut, we are selling an exact amount of token0 in exchange for token1\n        //zeroForOne determines which token is being sold and which is being bought\n        bool zeroForOne = tokenIn < tokenOut;\n\n        //swap on uniswap, including data to trigger call back for flashswap\n        (int256 amount0, int256 amount1) = _getPool(tokenIn, tokenOut, fee).swap(\n            _recipient,\n            zeroForOne,\n            _amountIn.toInt256(),\n            _sqrtPriceLimitX96 == 0\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\n                : _sqrtPriceLimitX96,\n            abi.encode(data)\n        );\n\n        //determine the amountOut based on which token has a lower address\n        return uint256(-(zeroForOne ? amount1 : amount0));\n    }\n\n    /**\n     * @notice internal function for exact-out swap on uniswap (specify exact amount to receive)\n     * @param _amountOut amount of token to receive\n     * @param _recipient recipient for receive\n     * @param _sqrtPriceLimitX96 price limit\n     * @return amount of token sold (amountIn)\n     */\n    function _exactOutputInternal(\n        uint256 _amountOut,\n        address _recipient,\n        uint160 _sqrtPriceLimitX96,\n        SwapCallbackData memory data\n    ) private returns (uint256) {\n        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();\n\n        //uniswap token0 has a lower address than token1\n        //if tokenIn<tokenOut, we are buying an exact amount of token1 in exchange for token0\n        //zeroForOne determines which token is being sold and which is being bought\n        bool zeroForOne = tokenIn < tokenOut;\n\n        //swap on uniswap, including data to trigger call back for flashswap\n        (int256 amount0Delta, int256 amount1Delta) = _getPool(tokenIn, tokenOut, fee).swap(\n            _recipient,\n            zeroForOne,\n            -_amountOut.toInt256(),\n            _sqrtPriceLimitX96 == 0\n                ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)\n                : _sqrtPriceLimitX96,\n            abi.encode(data)\n        );\n\n        //determine the amountIn and amountOut based on which token has a lower address\n        (uint256 amountIn, uint256 amountOutReceived) = zeroForOne\n            ? (uint256(amount0Delta), uint256(-amount1Delta))\n            : (uint256(amount1Delta), uint256(-amount0Delta));\n        // it's technically possible to not receive the full output amount,\n        // so if no price limit has been specified, require this possibility away\n        if (_sqrtPriceLimitX96 == 0) require(amountOutReceived == _amountOut);\n\n        return amountIn;\n    }\n\n    /**\n     * @notice returns the uniswap pool for the given token pair and fee\n     * @dev the pool contract may or may not exist\n     * @param tokenA address of first token\n     * @param tokenB address of second token\n     * @param fee fee tier for pool\n     */\n    function _getPool(address tokenA, address tokenB, uint24 fee)\n        internal\n        view\n        returns (IUniswapV3Pool)\n    {\n        return IUniswapV3Pool(\n            PoolAddress.computeAddress(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee))\n        );\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/UniOracle.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport \"v3-core/interfaces/IUniswapV3Pool.sol\";\nimport { IERC20Detailed } from \"squeeth-monorepo/interfaces/IERC20Detailed.sol\";\n// lib\nimport \"v3-periphery/libraries/Path.sol\";\nimport \"v3-periphery/libraries/PoolAddress.sol\";\nimport \"v3-core/libraries/SafeCast.sol\";\nimport { OracleLibrary } from \"squeeth-monorepo/libs/OracleLibrary.sol\";\nimport { SafeMath } from \"openzeppelin/math/SafeMath.sol\";\n\n/**\n * @notice UniOracle contract\n * @dev contract that interact with Uniswap pool\n * @author opyn team\n */\nlibrary UniOracle {\n    using Path for bytes;\n    using SafeCast for uint256;\n    using SafeMath for uint256;\n\n    /**\n     * @notice get twap converted with base & quote token decimals\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool and !_checkPeriod, this will revert with \"OLD\"\n     * @param _pool uniswap pool address\n     * @param _base base currency. to get eth/usd price, eth is base token\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\n     * @param _period number of seconds in the past to start calculating time-weighted average\n     * @param _checkPeriod if true, checks the maximum period and overrides it if less than period provided\n     * @return price of 1 base currency in quote currency. scaled by 1e18\n     */\n    function _getTwap(\n        address _pool,\n        address _base,\n        address _quote,\n        uint32 _period,\n        bool _checkPeriod\n    ) internal view returns (uint256) {\n        // if the period is already checked, request TWAP directly. Will revert if period is too long.\n        if (!_checkPeriod) return _fetchTwap(_pool, _base, _quote, _period);\n\n        // make sure the requested period < maxPeriod the pool recorded.\n        uint32 maxPeriod = _getMaxPeriod(_pool);\n        uint32 requestPeriod = _period > maxPeriod ? maxPeriod : _period;\n        return _fetchTwap(_pool, _base, _quote, requestPeriod);\n    }\n\n    /**\n     * @notice get twap converted with base & quote token decimals\n     * @dev if period is longer than the current timestamp - first timestamp stored in the pool, this will revert with \"OLD\"\n     * @param _pool uniswap pool address\n     * @param _base base currency. to get eth/usd price, eth is base token\n     * @param _quote quote currency. to get eth/usd price, usd is the quote currency\n     * @param _period number of seconds in the past to start calculating time-weighted average\n     * @return twap price which is scaled\n     */\n    function _fetchTwap(address _pool, address _base, address _quote, uint32 _period)\n        private\n        view\n        returns (uint256)\n    {\n        int24 twapTick = OracleLibrary.consultAtHistoricTime(_pool, _period, 0);\n        uint256 quoteAmountOut =\n            OracleLibrary.getQuoteAtTick(twapTick, uint128(1e18), _base, _quote);\n\n        uint8 baseDecimals = IERC20Detailed(_base).decimals();\n        uint8 quoteDecimals = IERC20Detailed(_quote).decimals();\n        if (baseDecimals == quoteDecimals) return quoteAmountOut;\n\n        // if quote token has less decimals, the returned quoteAmountOut will be lower, need to scale up by decimal difference\n        if (baseDecimals > quoteDecimals) {\n            return quoteAmountOut.mul(10 ** (baseDecimals - quoteDecimals));\n        }\n\n        // if quote token has more decimals, the returned quoteAmountOut will be higher, need to scale down by decimal difference\n        return quoteAmountOut.div(10 ** (quoteDecimals - baseDecimals));\n    }\n\n    /**\n     * @notice get the max period that can be used to request twap\n     * @param _pool uniswap pool address\n     * @return max period can be used to request twap\n     */\n    function _getMaxPeriod(address _pool) private view returns (uint32) {\n        IUniswapV3Pool pool = IUniswapV3Pool(_pool);\n        // observationIndex: the index of the last oracle observation that was written\n        // cardinality: the current maximum number of observations stored in the pool\n        (,, uint16 observationIndex, uint16 cardinality,,,) = pool.slot0();\n\n        // first observation index\n        // it's safe to use % without checking cardinality = 0 because cardinality is always >= 1\n        uint16 oldestObservationIndex = (observationIndex + 1) % cardinality;\n\n        (uint32 oldestObservationTimestamp,,, bool initialized) =\n            pool.observations(oldestObservationIndex);\n\n        if (initialized) return uint32(block.timestamp) - oldestObservationTimestamp;\n\n        // (index + 1) % cardinality is not the oldest index,\n        // probably because cardinality is increased after last observation.\n        // in this case, observation at index 0 should be the oldest.\n        (oldestObservationTimestamp,,,) = pool.observations(0);\n\n        return uint32(block.timestamp) - oldestObservationTimestamp;\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/ZenAuction.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IZenBullStrategy } from \"./interface/IZenBullStrategy.sol\";\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IEulerEToken } from \"./interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"./interface/IEulerDToken.sol\";\n// contract\nimport { Ownable } from \"openzeppelin/access/Ownable.sol\";\nimport { UniFlash } from \"./UniFlash.sol\";\nimport { UniOracle } from \"./UniOracle.sol\";\nimport { EIP712 } from \"openzeppelin/drafts/EIP712.sol\";\n// lib\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\nimport { ECDSA } from \"openzeppelin/cryptography/ECDSA.sol\";\nimport { Address } from \"openzeppelin/utils/Address.sol\";\n\n/**\n * Error code\n * AB0: caller is not auction manager\n * AB1: invalid delta after rebalance\n * AB2: invalid CR after rebalance\n * AB3: invalid CR lower and upper values\n * AB4: invalid delta lower and upper values\n * AB5: invalid clearing price\n * AB6: order is not taking the other side of the trade\n * AB7: current order price smaller than previous order price\n * AB8: current order price greater than previous order price\n * AB9: order price is less than clearing price\n * AB10: order price is greater than clearing price\n * AB11: order signer is different than order trader\n * AB12: order already expired\n * AB13: nonce already used\n * AB14: clearning price tolerance is too high\n * AB15: ETH limit price is out of tolerance range\n * AB16: WETH limit price tolerance is too high\n * AB17: price too low relative to Uniswap twap\n * AB18: price too high relative to Uniswap twap\n * AB19: auction manager can not be 0 address\n * AB20: can only receive eth from bull strategy\n * AB21: invalid receiver address\n */\n\n/**\n * @notice ZenAuction contract\n * @author opyn team\n */\ncontract ZenAuction is UniFlash, Ownable, EIP712 {\n    using StrategyMath for uint256;\n    using Address for address payable;\n\n    /// @dev typehash for signed orders\n    bytes32 private constant _FULL_REBALANCE_TYPEHASH = keccak256(\n        \"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\"\n    );\n\n    /// @dev 1e18\n    uint256 internal constant ONE = 1e18;\n    /// @dev TWAP period\n    uint32 internal constant TWAP = 420;\n    /// @dev WETH decimals - USDC decimals\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n\n    /// @dev full rebalance clearing price tolerance cannot exceed 20%\n    uint256 public constant MAX_FULL_REBALANCE_CLEARING_PRICE_TOLERANCE = 2e17; // 20%\n    /// @dev full rebalance WETH limit price tolerance cannot exceed 20%\n    uint256 public constant MAX_REBALANCE_WETH_LIMIT_PRICE_TOLERANCE = 2e17; // 20%\n\n    /// @dev USDC address\n    address private immutable usdc;\n    /// @dev WETH address\n    address private immutable weth;\n    /// @dev bull strategy address\n    address private immutable bullStrategy;\n    /// @dev wPowerPerp/eth uniswap pool address\n    address private immutable ethWPowerPerpPool;\n    /// @dev eth/usdc uniswap pool address\n    address private immutable ethUSDCPool;\n    /// @dev wPowerPerp address\n    address private immutable wPowerPerp;\n    /// @dev crab strategy address\n    address private immutable crab;\n    /// @dev euler eToken for WETH\n    address private immutable eToken;\n    /// @dev euler dToken for USDC\n    address private immutable dToken;\n\n    /// @dev highest delta the auction manager can rebalance to\n    uint256 public deltaUpper;\n    /// @dev lowest delta the auction manager can rebalance to\n    uint256 public deltaLower;\n    /// @dev highest CR the auction manager can rebalance to\n    uint256 public crUpper;\n    /// @dev lowest CR the auction manager can rebalance to\n    uint256 public crLower;\n    /// @dev full rebalance clearing price must be within this distance of the wPowerPerp:eth uniswap twap price\n    uint256 public fullRebalanceClearingPriceTolerance = 5e16; // 5%\n    /// @dev full rebalance WETH limit price must be within this distance of the eth:usd uniswap twap price\n    uint256 public rebalanceWethLimitPriceTolerance = 5e16; // 5%\n\n    /// @dev auction manager\n    address public auctionManager;\n\n    /// @dev store the used flag for a nonce for each address\n    mapping(address => mapping(uint256 => bool)) public nonces;\n\n    /// @dev enum to differentiate between Uniswap swap callback function source\n    enum FLASH_SOURCE {\n        LEVERAGE_REBALANCE_DECREASE_DEBT,\n        LEVERAGE_REBALANCE_INCREASE_DEBT,\n        FULL_REBALANCE_BORROW_USDC_BUY_WETH,\n        FULL_REBALANCE_REPAY_USDC_WITHDRAW_WETH,\n        FULL_REBALANCE_DEPOSIT_WETH_BORROW_USDC_DEPOSIT_INTO_CRAB,\n        FULL_REBALANCE_WITHDRAW_WETH_BORROW_USDC_DEPOSIT_INTO_CRAB,\n        FULL_REBALANCE_SELL_WETH_REPAY_USDC_DEPOSIT_INTO_CRAB,\n        FULL_REBALANCE_REPAY_USDC_DEPOSIT_WETH\n    }\n    ///@dev fullRebalance order struct\n\n    struct Order {\n        uint256 bidId;\n        address trader;\n        uint256 quantity;\n        uint256 price;\n        bool isBuying;\n        uint256 expiry;\n        uint256 nonce;\n        uint8 v;\n        bytes32 r;\n        bytes32 s;\n    }\n\n    ///@dev _executeCrabDeposit params struct\n\n    ///@dev _executeCrabDeposit params struct\n    struct ExecuteCrabDepositParams {\n        uint256 crabAmount;\n        uint256 wethTargetInEuler;\n        uint256 wethLimitPrice;\n        uint256 ethInCrab;\n        uint256 wethBoughtFromAuction;\n        uint24 ethUsdcPoolFee;\n    }\n\n    ///@dev _executeLeverageComponentRebalancing params struct\n    struct ExecuteLeverageComponentRebalancingParams {\n        uint256 wethTargetInEuler;\n        uint256 wethLimitPrice;\n        uint256 netWethReceived;\n        uint24 ethUsdcPoolFee;\n    }\n\n    event SetCrUpperAndLower(\n        uint256 oldCrLower, uint256 oldCrUpper, uint256 newCrLower, uint256 newCrUpper\n    );\n    event SetDeltaUpperAndLower(\n        uint256 oldDeltaLower, uint256 oldDeltaUpper, uint256 newDeltaLower, uint256 newDeltaUpper\n    );\n    event LeverageRebalance(bool isSellingUsdc, uint256 usdcAmount, uint256 wethLimitAmount);\n\n    event FullRebalance(\n        uint256 crabAmount,\n        uint256 clearingPrice,\n        bool isDepositingInCrab,\n        uint256 wPowerPerpAmount,\n        uint256 wethTargetInEuler\n    );\n\n    event SetFullRebalanceClearingPriceTolerance(\n        uint256 oldPriceTolerance, uint256 newPriceTolerance\n    );\n    event SetRebalanceWethLimitPriceTolerance(\n        uint256 oldWethLimitPriceTolerance, uint256 newWethLimitPriceTolerance\n    );\n    event SetAuctionManager(address oldAuctionManager, address newAuctionManager);\n    event Farm(address indexed asset, address indexed receiver);\n\n    /**\n     * @notice constructor for ZenAuction\n     * @param _auctionManager the address that can run auctions\n     * @param _bull bull strategy address\n     * @param _factory uniswap factory address\n     * @param _crab crab strategy address\n     * @param _eToken euler collateral token address for weth\n     * @param _dToken euler debt token address for usdc\n     */\n    constructor(\n        address _auctionManager,\n        address _bull,\n        address _factory,\n        address _crab,\n        address _eToken,\n        address _dToken\n    ) UniFlash(_factory) Ownable() EIP712(\"AuctionBull\", \"1\") {\n        auctionManager = _auctionManager;\n        bullStrategy = _bull;\n        weth = IController(IZenBullStrategy(_bull).powerTokenController()).weth();\n        usdc = IController(IZenBullStrategy(_bull).powerTokenController()).quoteCurrency();\n        ethWPowerPerpPool =\n            IController(IZenBullStrategy(_bull).powerTokenController()).wPowerPerpPool();\n        ethUSDCPool =\n            IController(IZenBullStrategy(_bull).powerTokenController()).ethQuoteCurrencyPool();\n        wPowerPerp = IController(IZenBullStrategy(_bull).powerTokenController()).wPowerPerp();\n        crab = _crab;\n        eToken = _eToken;\n        dToken = _dToken;\n\n        IERC20(IController(IZenBullStrategy(_bull).powerTokenController()).weth()).approve(\n            _bull, type(uint256).max\n        );\n        IERC20(IController(IZenBullStrategy(_bull).powerTokenController()).quoteCurrency()).approve(\n            _bull, type(uint256).max\n        );\n        IERC20(IController(IZenBullStrategy(_bull).powerTokenController()).wPowerPerp()).approve(\n            _bull, type(uint256).max\n        );\n    }\n\n    /**\n     * @notice receive function to allow ETH transfer to this contract\n     */\n    receive() external payable {\n        require(msg.sender == address(bullStrategy), \"AB20\");\n    }\n\n    /**\n     * @notice sets the auction manager, who has permission to run fullRebalance() and leverageRebalance() functions to rebalance the strategy\n     * @param _auctionManager the new auction manager address\n     */\n    function setAuctionManager(address _auctionManager) external onlyOwner {\n        require(_auctionManager != address(0), \"AB19\");\n\n        emit SetAuctionManager(auctionManager, _auctionManager);\n\n        auctionManager = _auctionManager;\n    }\n\n    /**\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum tolerance between a clearing sale price and the current uniswap twap price\n     * @param _fullRebalancePriceTolerance the OTC price tolerance, in percent, scaled by 1e18\n     */\n    function setFullRebalanceClearingPriceTolerance(uint256 _fullRebalancePriceTolerance)\n        external\n        onlyOwner\n    {\n        // tolerance cannot be more than 20%\n        require(_fullRebalancePriceTolerance <= MAX_FULL_REBALANCE_CLEARING_PRICE_TOLERANCE, \"AB14\");\n\n        emit SetFullRebalanceClearingPriceTolerance(\n            fullRebalanceClearingPriceTolerance, _fullRebalancePriceTolerance\n        );\n\n        fullRebalanceClearingPriceTolerance = _fullRebalancePriceTolerance;\n    }\n\n    /**\n     * @notice owner can set a threshold, scaled by 1e18 that determines the maximum tolerance between a WETH limit price and the current uniswap twap price\n     * @param _rebalanceWethLimitPriceTolerance the WETH limit price tolerance, in percent, scaled by 1e18\n     */\n    function setRebalanceWethLimitPriceTolerance(uint256 _rebalanceWethLimitPriceTolerance)\n        external\n        onlyOwner\n    {\n        // tolerance cannot be more than 20%\n        require(\n            _rebalanceWethLimitPriceTolerance <= MAX_REBALANCE_WETH_LIMIT_PRICE_TOLERANCE, \"AB16\"\n        );\n\n        emit SetRebalanceWethLimitPriceTolerance(\n            rebalanceWethLimitPriceTolerance, _rebalanceWethLimitPriceTolerance\n        );\n\n        rebalanceWethLimitPriceTolerance = _rebalanceWethLimitPriceTolerance;\n    }\n\n    /**\n     * @notice set strategy lower and upper collateral ratio\n     * @dev should only be callable by owner\n     * @param _crLower lower CR scaled by 1e18\n     * @param _crUpper upper CR scaled by 1e18\n     */\n    function setCrUpperAndLower(uint256 _crLower, uint256 _crUpper) external onlyOwner {\n        require(_crUpper > _crLower, \"AB3\");\n\n        emit SetCrUpperAndLower(crLower, crUpper, _crLower, _crUpper);\n\n        crLower = _crLower;\n        crUpper = _crUpper;\n    }\n\n    /**\n     * @notice set strategy lower and upper delta to ETH price\n     * @dev can only be callable by owner\n     * @param _deltaLower lower delta scaled by 1e18\n     * @param _deltaUpper upper delta scaled by 1e18\n     */\n    function setDeltaUpperAndLower(uint256 _deltaLower, uint256 _deltaUpper) external onlyOwner {\n        require(_deltaUpper > _deltaLower, \"AB4\");\n\n        emit SetDeltaUpperAndLower(deltaLower, deltaUpper, _deltaLower, _deltaUpper);\n\n        deltaLower = _deltaLower;\n        deltaUpper = _deltaUpper;\n    }\n\n    /**\n     * @notice withdraw assets transfered directly to this contract\n     * @dev can only be called by owner\n     * @param _asset asset address\n     * @param _receiver receiver address\n     */\n    function farm(address _asset, address _receiver) external onlyOwner {\n        require(_receiver != address(0), \"AB21\");\n\n        if (_asset == address(0)) {\n            payable(_receiver).sendValue(address(this).balance);\n        } else {\n            IERC20(_asset).transfer(_receiver, IERC20(_asset).balanceOf(address(this)));\n        }\n\n        emit Farm(_asset, _receiver);\n    }\n\n    /**\n     * @notice rebalance delta and collateral ratio of strategy using an array of signed orders\n     * @dev can only be called by the auction manager\n     * @param _orders list of orders\n     * @param _crabAmount amount of crab to withdraw or deposit\n     * @param _clearingPrice clearing price in WETH per wPowerPerp, in 1e18 units\n     * @param _wethTargetInEuler target WETH collateral amount in leverage component\n     * @param _wethLimitPrice limit price for WETH/USDC trade\n     * @param _isDepositingInCrab true if the rebalance will deposit into crab, false if withdrawing funds from crab\n     */\n    function fullRebalance(\n        Order[] memory _orders,\n        uint256 _crabAmount,\n        uint256 _clearingPrice,\n        uint256 _wethTargetInEuler,\n        uint256 _wethLimitPrice,\n        uint24 _ethUsdcPoolFee,\n        bool _isDepositingInCrab\n    ) external {\n        require(msg.sender == auctionManager, \"AB0\");\n        require(_clearingPrice > 0, \"AB5\");\n\n        _checkFullRebalanceClearingPrice(_clearingPrice, _isDepositingInCrab);\n        _checkRebalanceLimitPrice(_wethLimitPrice);\n\n        // get current crab vault state\n        (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n            IZenBullStrategy(bullStrategy).getCrabVaultDetails();\n        // total amount of wPowerPerp to trade given crab amount\n        uint256 wPowerPerpAmount = _calcWPowerPerpAmountFromCrab(\n            _isDepositingInCrab, _crabAmount, ethInCrab, wPowerPerpInCrab\n        );\n\n        uint256 pulledFunds =\n            _pullFundsFromOrders(_orders, wPowerPerpAmount, _clearingPrice, _isDepositingInCrab);\n\n        if (_isDepositingInCrab) {\n            /**\n             * if auction is depositing into crab:\n             * - if target WETH to have in Euler is greater than current amount in Euler, borrow USDC to buy more WETH and deposit in Euler\n             * - if target WETH to have in Euler is less than current amount in Euler, remove WETH from Euler\n             * - deposit into crab, pay auction traders wPowerPerp\n             */\n            _executeCrabDeposit(\n                ExecuteCrabDepositParams({\n                    crabAmount: _crabAmount,\n                    wethTargetInEuler: _wethTargetInEuler,\n                    wethLimitPrice: _wethLimitPrice,\n                    ethInCrab: ethInCrab,\n                    wethBoughtFromAuction: pulledFunds,\n                    ethUsdcPoolFee: _ethUsdcPoolFee\n                })\n            );\n\n            _pushFundsFromOrders(_orders, wPowerPerpAmount, _clearingPrice);\n        } else {\n            uint256 wethFromCrab = IZenBullStrategy(bullStrategy).redeemCrabAndWithdrawWEth(\n                _crabAmount, wPowerPerpAmount\n            );\n            uint256 pushedFunds = _pushFundsFromOrders(_orders, wPowerPerpAmount, _clearingPrice);\n\n            // rebalance bull strategy delta\n            _executeLeverageComponentRebalancing(\n                ExecuteLeverageComponentRebalancingParams({\n                    wethTargetInEuler: _wethTargetInEuler,\n                    wethLimitPrice: _wethLimitPrice,\n                    netWethReceived: wethFromCrab.sub(pushedFunds),\n                    ethUsdcPoolFee: _ethUsdcPoolFee\n                })\n            );\n        }\n\n        // check that rebalance does not breach collateral ratio or delta tolerance\n        _isValidRebalance();\n\n        emit FullRebalance(\n            _crabAmount, _clearingPrice, _isDepositingInCrab, wPowerPerpAmount, _wethTargetInEuler\n        );\n    }\n\n    /**\n     * @notice change the strategy eth delta by increasing or decreasing USDC debt\n     * @dev can only be called by auction manager\n     * @param _isSellingUsdc true if strategy is selling USDC\n     * @param _usdcAmount USDC amount to trade\n     * @param _wethLimitPrice WETH/USDC limit price, scaled 1e18 units\n     * @param _poolFee USDC/WETH pool fee\n     */\n    function leverageRebalance(\n        bool _isSellingUsdc,\n        uint256 _usdcAmount,\n        uint256 _wethLimitPrice,\n        uint24 _poolFee\n    ) external {\n        require(msg.sender == auctionManager, \"AB0\");\n\n        _checkRebalanceLimitPrice(_wethLimitPrice);\n\n        if (_isSellingUsdc) {\n            // swap USDC to WETH\n            _exactInFlashSwap(\n                usdc,\n                weth,\n                _poolFee,\n                _usdcAmount,\n                _usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(_wethLimitPrice),\n                uint8(FLASH_SOURCE.LEVERAGE_REBALANCE_INCREASE_DEBT),\n                \"\"\n            );\n        } else {\n            // swap WETH to USDC\n            _exactOutFlashSwap(\n                weth,\n                usdc,\n                _poolFee,\n                _usdcAmount,\n                _usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(_wethLimitPrice),\n                uint8(FLASH_SOURCE.LEVERAGE_REBALANCE_DECREASE_DEBT),\n                abi.encodePacked(_usdcAmount)\n            );\n        }\n\n        _isValidRebalance();\n\n        emit LeverageRebalance(_isSellingUsdc, _usdcAmount, _wethLimitPrice);\n    }\n\n    /**\n     * @notice allows an order to be cancelled by marking its nonce used for a given msg.sender\n     * @param _nonce the nonce to mark as used\n     */\n    function useNonce(uint256 _nonce) external {\n        _useNonce(msg.sender, _nonce);\n    }\n    /**\n     * @notice returns the domain separator\n     * @return the domain separator\n     */\n    // solhint-disable-next-line func-name-mixedcase\n\n    function DOMAIN_SEPARATOR() external view returns (bytes32) {\n        return _domainSeparatorV4();\n    }\n\n    /**\n     * @notice get current bull strategy delta and collateral ratio\n     * @return delta and collateral ratio\n     */\n    function getCurrentDeltaAndCollatRatio() external view returns (uint256, uint256) {\n        return _getCurrentDeltaAndCollatRatio();\n    }\n\n    /**\n     * @notice pulls funds from trader of auction orders (weth or wPowerPerp) depending on the direction of trade\n     * @param _orders list of orders\n     * @param remainingAmount amount of wPowerPerp to trade\n     * @param _clearingPrice clearing price weth/wPowerPerp, in 1e18 units\n     * @param _isDepositingInCrab true if the rebalance will deposit into Crab, false if withdrawing funds from Crab\n     */\n    function _pullFundsFromOrders(\n        Order[] memory _orders,\n        uint256 remainingAmount,\n        uint256 _clearingPrice,\n        bool _isDepositingInCrab\n    ) internal returns (uint256) {\n        // loop through orders, check each order validity\n        // pull funds from orders\n\n        uint256 prevPrice = _orders[0].price;\n        uint256 currentPrice;\n\n        uint256 amountTransfered;\n        uint256 ordersLength = _orders.length;\n        for (uint256 i; i < ordersLength; ++i) {\n            _verifyOrder(_orders[i], _clearingPrice, _isDepositingInCrab);\n\n            currentPrice = _orders[i].price;\n            // check that orders are in order\n            if (_isDepositingInCrab) {\n                require(currentPrice <= prevPrice, \"AB8\");\n            } else {\n                require(currentPrice >= prevPrice, \"AB7\");\n            }\n            prevPrice = currentPrice;\n\n            amountTransfered = amountTransfered.add(\n                _transferFromOrder(_orders[i], remainingAmount, _clearingPrice)\n            );\n\n            if (remainingAmount > _orders[i].quantity) {\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\n            } else {\n                break;\n            }\n        }\n\n        return amountTransfered;\n    }\n\n    /**\n     * @notice pushes funds to trader of auction orders (weth or wPowerPerp) depending on the direction of trade\n     * @param _orders list of orders\n     * @param remainingAmount amount of wPowerPerp to trade\n     * @param _clearingPrice clearing price weth/wPowerPerp, in 1e18 units\n     */\n\n    function _pushFundsFromOrders(\n        Order[] memory _orders,\n        uint256 remainingAmount,\n        uint256 _clearingPrice\n    ) internal returns (uint256) {\n        uint256 pushedFunds;\n        uint256 ordersLength = _orders.length;\n        for (uint256 i; i < ordersLength; ++i) {\n            pushedFunds =\n                pushedFunds.add(_transferToOrder(_orders[i], remainingAmount, _clearingPrice));\n            if (remainingAmount > _orders[i].quantity) {\n                remainingAmount = remainingAmount.sub(_orders[i].quantity);\n            } else {\n                break;\n            }\n        }\n\n        return pushedFunds;\n    }\n\n    /**\n     * @notice execute crab deposit as well as changes to euler collateral and debt as part of a full rebalance\n     * @param _params ExecuteCrabDepositParams struct\n     */\n    function _executeCrabDeposit(ExecuteCrabDepositParams memory _params) internal {\n        // total eth needed for this crab deposit\n        uint256 totalEthNeededForCrab =\n            _params.crabAmount.wdiv(IERC20(crab).totalSupply()).wmul(_params.ethInCrab);\n        // additional eth needed\n        uint256 ethNeededForCrab = totalEthNeededForCrab.sub(_params.wethBoughtFromAuction);\n        // WETH collateral in Euler\n        uint256 wethInCollateral = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        if (_params.wethTargetInEuler > wethInCollateral) {\n            // crab deposit eth + collateral shortfall\n            uint256 wethToGet =\n                _params.wethTargetInEuler.sub(wethInCollateral).add(ethNeededForCrab);\n            // sell USDC to buy WETH\n            _exactOutFlashSwap(\n                usdc,\n                weth,\n                _params.ethUsdcPoolFee,\n                wethToGet,\n                wethToGet.wmul(_params.wethLimitPrice).div(WETH_DECIMALS_DIFF),\n                uint8(FLASH_SOURCE.FULL_REBALANCE_DEPOSIT_WETH_BORROW_USDC_DEPOSIT_INTO_CRAB),\n                abi.encodePacked(\n                    _params.wethTargetInEuler.sub(wethInCollateral), totalEthNeededForCrab\n                )\n            );\n        } else {\n            // WETH to take out of Euler\n            uint256 wethFromEuler = wethInCollateral.sub(_params.wethTargetInEuler);\n\n            if (ethNeededForCrab >= wethFromEuler) {\n                // crab deposit eth - excess collateral\n                uint256 wethToGet = ethNeededForCrab.sub(wethFromEuler);\n                // sell USDC to buy WETH\n                _exactOutFlashSwap(\n                    usdc,\n                    weth,\n                    _params.ethUsdcPoolFee,\n                    wethToGet,\n                    wethToGet.wmul(_params.wethLimitPrice).div(WETH_DECIMALS_DIFF),\n                    uint8(FLASH_SOURCE.FULL_REBALANCE_WITHDRAW_WETH_BORROW_USDC_DEPOSIT_INTO_CRAB),\n                    abi.encodePacked(wethFromEuler, totalEthNeededForCrab)\n                );\n            } else {\n                uint256 wethToSell = wethFromEuler.sub(ethNeededForCrab);\n                // sell WETH for USDC\n                _exactInFlashSwap(\n                    weth,\n                    usdc,\n                    _params.ethUsdcPoolFee,\n                    wethToSell,\n                    wethToSell.wmul(_params.wethLimitPrice).div(WETH_DECIMALS_DIFF),\n                    uint8(FLASH_SOURCE.FULL_REBALANCE_SELL_WETH_REPAY_USDC_DEPOSIT_INTO_CRAB),\n                    abi.encodePacked(wethFromEuler, totalEthNeededForCrab)\n                );\n            }\n        }\n    }\n\n    /**\n     * @notice uniswap flash swap callback function to handle different types of flashswaps\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\n     * @param _uniFlashSwapData UniFlashswapCallbackData struct\n     */\n    function _uniFlashSwap(UniFlashswapCallbackData memory _uniFlashSwapData) internal override {\n        if (\n            FLASH_SOURCE(_uniFlashSwapData.callSource)\n                == FLASH_SOURCE.LEVERAGE_REBALANCE_INCREASE_DEBT\n        ) {\n            IZenBullStrategy(bullStrategy).depositAndBorrowFromLeverage(\n                IERC20(weth).balanceOf(address(this)), _uniFlashSwapData.amountToPay\n            );\n\n            IERC20(usdc).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        } else if (\n            FLASH_SOURCE(_uniFlashSwapData.callSource)\n                == FLASH_SOURCE.LEVERAGE_REBALANCE_DECREASE_DEBT\n        ) {\n            uint256 usdcToRepay = abi.decode(_uniFlashSwapData.callData, (uint256));\n            // Repay some USDC debt\n            IZenBullStrategy(bullStrategy).auctionRepayAndWithdrawFromLeverage(\n                usdcToRepay, _uniFlashSwapData.amountToPay\n            );\n\n            IERC20(weth).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        } else if (\n            FLASH_SOURCE(_uniFlashSwapData.callSource)\n                == FLASH_SOURCE.FULL_REBALANCE_BORROW_USDC_BUY_WETH\n        ) {\n            uint256 wethToDeposit = abi.decode(_uniFlashSwapData.callData, (uint256));\n            IZenBullStrategy(bullStrategy).depositAndBorrowFromLeverage(\n                wethToDeposit, _uniFlashSwapData.amountToPay\n            );\n\n            IERC20(usdc).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        } else if (\n            FLASH_SOURCE(_uniFlashSwapData.callSource)\n                == FLASH_SOURCE.FULL_REBALANCE_REPAY_USDC_DEPOSIT_WETH\n        ) {\n            uint256 wethToDeposit = abi.decode(_uniFlashSwapData.callData, (uint256));\n\n            IZenBullStrategy(bullStrategy).auctionDepositAndRepayFromLeverage(\n                wethToDeposit, IERC20(usdc).balanceOf(address(this))\n            );\n            IERC20(weth).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        } else if (\n            FLASH_SOURCE(_uniFlashSwapData.callSource)\n                == FLASH_SOURCE.FULL_REBALANCE_REPAY_USDC_WITHDRAW_WETH\n        ) {\n            uint256 remainingWeth = abi.decode(_uniFlashSwapData.callData, (uint256));\n\n            IZenBullStrategy(bullStrategy).auctionRepayAndWithdrawFromLeverage(\n                IERC20(usdc).balanceOf(address(this)),\n                _uniFlashSwapData.amountToPay.sub(remainingWeth)\n            );\n\n            // we need to withdraw\n            IERC20(weth).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        } else if (\n            FLASH_SOURCE(_uniFlashSwapData.callSource)\n                == FLASH_SOURCE.FULL_REBALANCE_DEPOSIT_WETH_BORROW_USDC_DEPOSIT_INTO_CRAB\n        ) {\n            (uint256 wethToLeverage, uint256 ethToCrab) =\n                abi.decode(_uniFlashSwapData.callData, (uint256, uint256));\n\n            IZenBullStrategy(bullStrategy).depositAndBorrowFromLeverage(\n                wethToLeverage, _uniFlashSwapData.amountToPay\n            );\n\n            IZenBullStrategy(bullStrategy).depositEthIntoCrab(ethToCrab);\n\n            IERC20(usdc).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        } else if (\n            FLASH_SOURCE(_uniFlashSwapData.callSource)\n                == FLASH_SOURCE.FULL_REBALANCE_WITHDRAW_WETH_BORROW_USDC_DEPOSIT_INTO_CRAB\n        ) {\n            (uint256 wethToWithdraw, uint256 ethToCrab) =\n                abi.decode(_uniFlashSwapData.callData, (uint256, uint256));\n\n            IZenBullStrategy(bullStrategy).auctionRepayAndWithdrawFromLeverage(0, wethToWithdraw);\n\n            IZenBullStrategy(bullStrategy).depositAndBorrowFromLeverage(\n                0, _uniFlashSwapData.amountToPay\n            );\n\n            IZenBullStrategy(bullStrategy).depositEthIntoCrab(ethToCrab);\n\n            IERC20(usdc).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        } else if (\n            FLASH_SOURCE(_uniFlashSwapData.callSource)\n                == FLASH_SOURCE.FULL_REBALANCE_SELL_WETH_REPAY_USDC_DEPOSIT_INTO_CRAB\n        ) {\n            (uint256 wethToWithdraw, uint256 ethToCrab) =\n                abi.decode(_uniFlashSwapData.callData, (uint256, uint256));\n\n            IZenBullStrategy(bullStrategy).auctionRepayAndWithdrawFromLeverage(\n                IERC20(usdc).balanceOf(address(this)), wethToWithdraw\n            );\n\n            IZenBullStrategy(bullStrategy).depositEthIntoCrab(ethToCrab);\n\n            IERC20(weth).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        }\n    }\n\n    /**\n     * @notice rebalance bull strategy delta by borrowing or repaying USDC and changing eth collateral as part of a full rebalance when withdrawing from crab\n     * @param _params ExecuteLeverageComponentRebalancingParams struct\n     */\n    function _executeLeverageComponentRebalancing(\n        ExecuteLeverageComponentRebalancingParams memory _params\n    ) internal {\n        uint256 wethInCollateral = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        if (_params.wethTargetInEuler > _params.netWethReceived.add(wethInCollateral)) {\n            // have less ETH than we need in Euler, we have to buy and deposit it\n            // borrow more USDC to buy WETH\n            uint256 wethToBuy =\n                _params.wethTargetInEuler.sub(_params.netWethReceived.add(wethInCollateral));\n            _exactOutFlashSwap(\n                usdc,\n                weth,\n                _params.ethUsdcPoolFee,\n                wethToBuy,\n                wethToBuy.wmul(_params.wethLimitPrice).div(WETH_DECIMALS_DIFF),\n                uint8(FLASH_SOURCE.FULL_REBALANCE_BORROW_USDC_BUY_WETH),\n                abi.encodePacked(wethToBuy.add(_params.netWethReceived))\n            );\n        } else {\n            // have more ETH than we need in either Euler or from withdrawing from crab\n            //we need to sell ETH and either deposit or withdraw from euler\n            uint256 wethToSell =\n                _params.netWethReceived.add(wethInCollateral).sub(_params.wethTargetInEuler);\n            // wethToSell + wEthTargetInEuler = _params.netWethReceived+wethInCollateral\n\n            // repay USDC debt from WETH\n            if (_params.wethTargetInEuler < wethInCollateral) {\n                // if we need to withdraw from in euler, do that\n                _exactInFlashSwap(\n                    weth,\n                    usdc,\n                    _params.ethUsdcPoolFee,\n                    wethToSell,\n                    wethToSell.wmul(_params.wethLimitPrice).div(WETH_DECIMALS_DIFF),\n                    uint8(FLASH_SOURCE.FULL_REBALANCE_REPAY_USDC_WITHDRAW_WETH),\n                    abi.encodePacked(_params.netWethReceived)\n                );\n            } else {\n                // if we need to deposit to euler do that\n                _exactInFlashSwap(\n                    weth,\n                    usdc,\n                    _params.ethUsdcPoolFee,\n                    wethToSell,\n                    wethToSell.wmul(_params.wethLimitPrice).div(WETH_DECIMALS_DIFF),\n                    uint8(FLASH_SOURCE.FULL_REBALANCE_REPAY_USDC_DEPOSIT_WETH),\n                    abi.encodePacked(_params.wethTargetInEuler.sub(wethInCollateral))\n                );\n            }\n        }\n    }\n\n    /**\n     * @notice transfer payment to auction participant from contract\n     * @param _order Order struct\n     * @param _remainingAmount remaining amount to be transfered\n     * @param _clearingPrice clearing price in WETH/wPowerPerp determined at auction\n     */\n    function _transferToOrder(Order memory _order, uint256 _remainingAmount, uint256 _clearingPrice)\n        internal\n        returns (uint256)\n    {\n        // adjust quantity for partial fills\n        if (_remainingAmount < _order.quantity) {\n            _order.quantity = _remainingAmount;\n        }\n        if (_order.isBuying) {\n            // trader sent WETH and receives wPowerPerp\n            IERC20(wPowerPerp).transfer(_order.trader, _order.quantity);\n\n            return _order.quantity;\n        } else {\n            // trader sent wPowerPerp and receives WETH\n            // WETH clearing price for the order\n            uint256 wethAmount = _order.quantity.wmul(_clearingPrice);\n            IERC20(weth).transfer(_order.trader, wethAmount);\n\n            return wethAmount;\n        }\n    }\n\n    /**\n     * @notice transfer payment from auction participant to contract\n     * @param _order Order struct\n     * @param _remainingAmount remaining amount to be transfered\n     * @param _clearingPrice clearing price in WETH/wPowerPerp determined at auction\n     */\n    function _transferFromOrder(\n        Order memory _order,\n        uint256 _remainingAmount,\n        uint256 _clearingPrice\n    ) internal returns (uint256) {\n        // adjust quantity for partial fills\n        if (_remainingAmount < _order.quantity) {\n            _order.quantity = _remainingAmount;\n        }\n\n        if (_order.isBuying) {\n            // trader sends WETH and receives wPowerPerp\n            // WETH clearing price for the order\n            uint256 wethAmount = _order.quantity.wmul(_clearingPrice);\n            IERC20(weth).transferFrom(_order.trader, address(this), wethAmount);\n\n            return wethAmount;\n        } else {\n            // trader send wPowerPerp and receives WETH\n            IERC20(wPowerPerp).transferFrom(_order.trader, address(this), _order.quantity);\n\n            return _order.quantity;\n        }\n    }\n\n    /**\n     * @notice verify that an auction order is valid\n     * @param _order Order struct\n     * @param _clearingPrice clearing price in WETH/wPowerPerp\n     * @param _isDepositingInCrab true if rebalance is depositing into crab\n     */\n    function _verifyOrder(Order memory _order, uint256 _clearingPrice, bool _isDepositingInCrab)\n        internal\n    {\n        // check that order trade against hedge direction\n        require(_order.isBuying == _isDepositingInCrab, \"AB6\");\n        // check that order beats clearing price\n        if (_order.isBuying) {\n            require(_clearingPrice <= _order.price, \"AB9\");\n        } else {\n            require(_clearingPrice >= _order.price, \"AB10\");\n        }\n\n        _useNonce(_order.trader, _order.nonce);\n        bytes32 structHash = keccak256(\n            abi.encode(\n                _FULL_REBALANCE_TYPEHASH,\n                _order.bidId,\n                _order.trader,\n                _order.quantity,\n                _order.price,\n                _order.isBuying,\n                _order.expiry,\n                _order.nonce\n            )\n        );\n\n        bytes32 hash = _hashTypedDataV4(structHash);\n        address orderSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s);\n        require(orderSigner == _order.trader, \"AB11\");\n        require(_order.expiry >= block.timestamp, \"AB12\");\n    }\n\n    /**\n     * @dev set nonce flag of the trader to true\n     * @param _trader address of the signer\n     * @param _nonce number that is to be traded only once\n     */\n    function _useNonce(address _trader, uint256 _nonce) internal {\n        require(!nonces[_trader][_nonce], \"AB13\");\n        nonces[_trader][_nonce] = true;\n    }\n\n    /**\n     * @notice check if strategy delta and collateral is within tolerance\n     */\n    function _isValidRebalance() internal view {\n        (uint256 delta, uint256 cr) = _getCurrentDeltaAndCollatRatio();\n\n        require(delta <= deltaUpper && delta >= deltaLower, \"AB1\");\n        require(cr <= crUpper && cr >= crLower, \"AB2\");\n    }\n\n    /**\n     * @dev calculate amount of wPowerPerp associated with a crab deposit or withdrawal\n     * @param _isDepositingInCrab true if depositing into crab\n     * @param _crabAmount amount of crab to deposit/withdraw\n     * @param _ethInCrab amount of eth collateral owned by crab strategy\n     * @param _wPowerPerpInCrab amount of wPowerPerp debt owed by crab strategy\n     * @return wPowerPerpAmount\n     */\n    function _calcWPowerPerpAmountFromCrab(\n        bool _isDepositingInCrab,\n        uint256 _crabAmount,\n        uint256 _ethInCrab,\n        uint256 _wPowerPerpInCrab\n    ) internal view returns (uint256) {\n        uint256 wPowerPerpAmount;\n        if (_isDepositingInCrab) {\n            uint256 ethToDepositInCrab =\n                _crabAmount.wdiv(IERC20(crab).totalSupply()).wmul(_ethInCrab);\n            (wPowerPerpAmount,) =\n                _calcWPowerPerpToMintAndFee(ethToDepositInCrab, _wPowerPerpInCrab, _ethInCrab);\n        } else {\n            wPowerPerpAmount = _crabAmount.wmul(_wPowerPerpInCrab).wdiv(IERC20(crab).totalSupply());\n        }\n\n        return wPowerPerpAmount;\n    }\n\n    /**\n     * @notice get current bull strategy delta and collateral ratio\n     * @return delta and collateral ratio\n     */\n    function _getCurrentDeltaAndCollatRatio() internal view returns (uint256, uint256) {\n        (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n            IZenBullStrategy(bullStrategy).getCrabVaultDetails();\n        uint256 ethUsdPrice = UniOracle._getTwap(ethUSDCPool, weth, usdc, TWAP, false);\n        uint256 wPowerPerpEthPrice =\n            UniOracle._getTwap(ethWPowerPerpPool, wPowerPerp, weth, TWAP, false);\n        uint256 crabUsdPrice = (\n            ethInCrab.wmul(ethUsdPrice).sub(\n                wPowerPerpInCrab.wmul(wPowerPerpEthPrice).wmul(ethUsdPrice)\n            )\n        ).wdiv(IERC20(crab).totalSupply());\n\n        uint256 usdcDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        uint256 wethInCollateral = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        uint256 delta = (wethInCollateral.wmul(ethUsdPrice)).wdiv(\n            (IZenBullStrategy(bullStrategy).getCrabBalance().wmul(crabUsdPrice)).add(\n                wethInCollateral.wmul(ethUsdPrice)\n            ).sub(usdcDebt.mul(WETH_DECIMALS_DIFF))\n        );\n\n        uint256 cr = wethInCollateral.wmul(ethUsdPrice).wdiv(usdcDebt.mul(WETH_DECIMALS_DIFF));\n\n        return (delta, cr);\n    }\n\n    /**\n     * @dev calculate amount of wPowerPerp to mint and fee based on ETH to deposit into crab\n     * @param _depositedEthAmount amount of ETH deposited\n     * @param _strategyDebtAmount amount of wPowerperp debt in strategy vault before deposit\n     * @param _strategyCollateralAmount amount of ETH collatal in strategy vault before deposit\n     * @return amount of wPowerPerp to mint and fee\n     */\n    function _calcWPowerPerpToMintAndFee(\n        uint256 _depositedEthAmount,\n        uint256 _strategyDebtAmount,\n        uint256 _strategyCollateralAmount\n    ) internal view returns (uint256, uint256) {\n        uint256 wPowerPerpEthPrice =\n            UniOracle._getTwap(ethWPowerPerpPool, wPowerPerp, weth, TWAP, false);\n        uint256 feeRate =\n            IController(IZenBullStrategy(bullStrategy).powerTokenController()).feeRate();\n        uint256 feeAdjustment = wPowerPerpEthPrice.mul(feeRate).div(10000);\n        uint256 wPowerPerpToMint = _depositedEthAmount.wmul(_strategyDebtAmount).wdiv(\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\n        );\n        uint256 fee = wPowerPerpToMint.wmul(feeAdjustment);\n\n        return (wPowerPerpToMint, fee);\n    }\n\n    /**\n     * @notice check that the proposed auction price is within a tolerance of the current Uniswap twap\n     * @param _price clearing price provided by manager\n     * @param _isDepositingInCrab is bull depositing in Crab\n     */\n    function _checkFullRebalanceClearingPrice(uint256 _price, bool _isDepositingInCrab)\n        internal\n        view\n    {\n        // Get twap\n        uint256 wPowerPerpEthPrice =\n            UniOracle._getTwap(ethWPowerPerpPool, wPowerPerp, weth, TWAP, false);\n\n        if (_isDepositingInCrab) {\n            require(\n                _price >= wPowerPerpEthPrice.wmul((ONE.sub(fullRebalanceClearingPriceTolerance))),\n                \"AB17\"\n            );\n        } else {\n            require(\n                _price <= wPowerPerpEthPrice.wmul((ONE.add(fullRebalanceClearingPriceTolerance))),\n                \"AB18\"\n            );\n        }\n    }\n\n    /**\n     * @notice check that the proposed auction price is within a tolerance of the current Uniswap twap\n     * @param _wethLimitPrice WETH limit price provided by manager\n     */\n    function _checkRebalanceLimitPrice(uint256 _wethLimitPrice) internal view {\n        // get twaps to check price within tolerance\n        uint256 ethUsdPrice = UniOracle._getTwap(ethUSDCPool, weth, usdc, TWAP, false);\n\n        require(\n            (_wethLimitPrice >= ethUsdPrice.wmul((ONE.sub(rebalanceWethLimitPriceTolerance))))\n                && (_wethLimitPrice <= ethUsdPrice.wmul((ONE.add(rebalanceWethLimitPriceTolerance)))),\n            \"AB15\"\n        );\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/ZenBullStrategy.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { ICrabStrategyV2 } from \"./interface/ICrabStrategyV2.sol\";\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IWETH9 } from \"squeeth-monorepo/interfaces/IWETH9.sol\";\n// contract\nimport { ERC20 } from \"openzeppelin/token/ERC20/ERC20.sol\";\nimport { LeverageZen } from \"./LeverageZen.sol\";\n// lib\nimport { Address } from \"openzeppelin/utils/Address.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\n\n/**\n * Error codes\n * BS1: Can't receive ETH from this sender\n * BS2: Strategy cap reached max\n * BS3: RedeemShortShutdown must be called first\n * BS4: Emergency shutdown contract needs to initiate the shutdownRepayAndWithdraw call\n * BS5: Can't farm token\n * BS6: Invalid shutdownContract address set\n * BS7: wPowerPerp contract has been shutdown\n * BS8: Caller is not auction address\n * BS9: deposited amount less than minimum\n * BS10: Remaining amount of bull token should be more than minimum or zero\n * BS11: Invalid receiver address\n * BS12: Strategy is shutdown\n */\n\n/**\n * @notice ZenBullStrategy contract\n * @author opyn team\n */\ncontract ZenBullStrategy is ERC20, LeverageZen {\n    using StrategyMath for uint256;\n    using Address for address payable;\n\n    /// @dev amount of crab token owned by bull strategy\n    uint256 private _crabBalance;\n    /// @dev crab contract address\n    address public immutable crab;\n    /// @dev powerToken controller\n    address public immutable powerTokenController;\n    /// @dev public emergency shutdown contract\n    address public shutdownContract;\n    /// @dev the cap in ETH for the strategy, above which deposits will be rejected\n    uint256 public strategyCap;\n    /// @dev set to true when redeemShortShutdown has been called\n    bool public hasRedeemedInShutdown;\n\n    event Withdraw(\n        address indexed to,\n        uint256 bullAmount,\n        uint256 crabToRedeem,\n        uint256 wPowerPerpToRedeem,\n        uint256 usdcToRepay,\n        uint256 wethToWithdraw\n    );\n    event Deposit(address indexed from, uint256 crabAmount, uint256 wethLent, uint256 usdcBorrowed);\n    event SetCap(uint256 oldCap, uint256 newCap);\n    event RedeemCrabAndWithdrawEth(\n        uint256 indexed crabToRedeem, uint256 wPowerPerpRedeemed, uint256 wethBalanceReturned\n    );\n    event SetShutdownContract(address oldShutdownContract, address newShutdownContract);\n    event ShutdownRepayAndWithdraw(\n        uint256 wethToUniswap, uint256 shareToUnwind, uint256 crabToRedeem\n    );\n    event Farm(address indexed asset, address indexed receiver);\n    event DepositEthIntoCrab(uint256 ethToDeposit);\n    event WithdrawShutdown(address indexed withdrawer, uint256 bullAmount, uint256 ethToReceive);\n\n    /**\n     * @notice constructor for BullStrategy\n     * @param _crab crab address\n     * @param _powerTokenController wPowerPerp Controller address\n     * @param _euler euler address\n     * @param _eulerMarketsModule euler markets module address\n     */\n\n    constructor(\n        address _crab,\n        address _powerTokenController,\n        address _euler,\n        address _eulerMarketsModule\n    )\n        ERC20(\"Zen Bull Strategy\", \"ZenBull\")\n        LeverageZen(_euler, _eulerMarketsModule, _powerTokenController)\n    {\n        crab = _crab;\n        powerTokenController = _powerTokenController;\n        IERC20(IController(_powerTokenController).wPowerPerp()).approve(_crab, type(uint256).max);\n    }\n\n    /**\n     * @notice receive function to allow ETH transfer to this contract\n     */\n    receive() external payable {\n        require(msg.sender == weth || msg.sender == address(crab), \"BS1\");\n    }\n\n    /**\n     * @notice withdraw assets transfered directly to this contract\n     * @dev can only be called by owner\n     * @param _asset asset address\n     * @param _receiver receiver address\n     */\n    function farm(address _asset, address _receiver) external onlyOwner {\n        require(!IController(powerTokenController).isShutDown(), \"BS7\");\n        require(!hasRedeemedInShutdown, \"BS12\");\n        require((_asset != crab) && (_asset != eToken) && (_asset != dToken), \"BS5\");\n        require(_receiver != address(0), \"BS11\");\n\n        if (_asset == address(0)) {\n            payable(_receiver).sendValue(address(this).balance);\n        } else {\n            IERC20(_asset).transfer(_receiver, IERC20(_asset).balanceOf(address(this)));\n        }\n\n        emit Farm(_asset, _receiver);\n    }\n\n    /**\n     * @notice set strategy cap which is checked on deposits and compared against the collateral in Euler\n     * @param _cap strategy cap\n     */\n    function setCap(uint256 _cap) external onlyOwner {\n        emit SetCap(strategyCap, _cap);\n\n        strategyCap = _cap;\n    }\n\n    /**\n     * @notice set shutdown contract that can be used to unwind the strategy if WPowerPerp controller contract is shut down\n     * @param _shutdownContract shutdown contract address\n     */\n    function setShutdownContract(address _shutdownContract) external onlyOwner {\n        require(_shutdownContract != address(0), \"BS6\");\n\n        emit SetShutdownContract(shutdownContract, _shutdownContract);\n\n        shutdownContract = _shutdownContract;\n    }\n\n    /**\n     * @notice deposit to crab: deposits crab and ETH, receives USDC, wPowerPerp and Bull token\n     * @param _crabAmount amount of crab token to deposit\n     */\n    function deposit(uint256 _crabAmount) external payable {\n        require(!IController(powerTokenController).isShutDown(), \"BS7\");\n\n        IERC20(crab).transferFrom(msg.sender, address(this), _crabAmount);\n        uint256 crabBalance = _increaseCrabBalance(_crabAmount);\n\n        uint256 share = ONE;\n\n        if (totalSupply() == 0) {\n            _mint(msg.sender, _crabAmount);\n        } else {\n            share = _crabAmount.wdiv(crabBalance);\n            uint256 bullToMint = share.wmul(totalSupply()).wdiv(ONE.sub(share));\n            _mint(msg.sender, bullToMint);\n        }\n\n        require(totalSupply() > 1e14, \"BS9\");\n\n        (uint256 ethInCrab, uint256 wPowerPerpInCrab) = _getCrabVaultDetails();\n        // deposit eth into leverage component and borrow USDC\n        (uint256 wethLent, uint256 usdcBorrowed, uint256 _totalWethInEuler) = _leverageDeposit(\n            _crabAmount, share, ethInCrab, wPowerPerpInCrab, IERC20(crab).totalSupply()\n        );\n\n        require(_totalWethInEuler <= strategyCap, \"BS2\");\n\n        // transfer borrowed USDC to depositor\n        IERC20(usdc).transfer(msg.sender, usdcBorrowed);\n\n        // refund unused ETH\n        payable(msg.sender).sendValue(address(this).balance);\n\n        emit Deposit(msg.sender, _crabAmount, wethLent, usdcBorrowed);\n    }\n\n    /**\n     * @notice withdraw from crab: repay wPowerPerp, USDC and Bull token and receive ETH\n     * @param _bullAmount amount of Bull token to redeem\n     */\n    function withdraw(uint256 _bullAmount) external {\n        uint256 share = _bullAmount.wdiv(totalSupply());\n        uint256 crabToRedeem = share.wmul(_crabBalance);\n        uint256 crabTotalSupply = IERC20(crab).totalSupply();\n        (, uint256 wPowerPerpInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpToRedeem = crabToRedeem.wmul(wPowerPerpInCrab).wdiv(crabTotalSupply);\n\n        IERC20(wPowerPerp).transferFrom(msg.sender, address(this), wPowerPerpToRedeem);\n\n        _burn(msg.sender, _bullAmount);\n\n        require(totalSupply() == 0 || totalSupply() > 1e14, \"BS10\");\n\n        _decreaseCrabBalance(crabToRedeem);\n        ICrabStrategyV2(crab).withdraw(crabToRedeem);\n\n        (uint256 usdcToRepay,) = _repayAndWithdrawFromLeverage(share);\n\n        emit Withdraw(\n            msg.sender,\n            _bullAmount,\n            crabToRedeem,\n            wPowerPerpToRedeem,\n            usdcToRepay,\n            address(this).balance\n        );\n\n        payable(msg.sender).sendValue(address(this).balance);\n    }\n\n    /**\n     * @notice auction contract redeems some crab to withdraw eth\n     * @param _crabToRedeem amount of crab token redeemed by auction\n     * @param _wPowerPerpToRedeem amount of wPowerPerp sent back for crab redeem\n     */\n    function redeemCrabAndWithdrawWEth(uint256 _crabToRedeem, uint256 _wPowerPerpToRedeem)\n        external\n        returns (uint256)\n    {\n        require(msg.sender == auction, \"BS8\");\n\n        IERC20(wPowerPerp).transferFrom(msg.sender, address(this), _wPowerPerpToRedeem);\n\n        uint256 crabBalancebefore = IERC20(crab).balanceOf(address(this));\n\n        ICrabStrategyV2(crab).withdraw(_crabToRedeem);\n\n        _decreaseCrabBalance(crabBalancebefore.sub(IERC20(crab).balanceOf(address(this))));\n\n        uint256 wethBalanceToReturn = address(this).balance;\n        IWETH9(weth).deposit{ value: wethBalanceToReturn }();\n        IWETH9(weth).transfer(msg.sender, wethBalanceToReturn);\n\n        emit RedeemCrabAndWithdrawEth(_crabToRedeem, _wPowerPerpToRedeem, wethBalanceToReturn);\n\n        return wethBalanceToReturn;\n    }\n\n    /**\n     * @notice auction contract deposits into crab and receives some wPowerPerp\n     * @param _ethToDeposit amount of eth to deposit\n     */\n    function depositEthIntoCrab(uint256 _ethToDeposit) external {\n        require(msg.sender == auction, \"BS8\");\n\n        IWETH9(weth).transferFrom(msg.sender, address(this), _ethToDeposit);\n        IWETH9(weth).withdraw(_ethToDeposit);\n\n        uint256 crabBalancebefore = IERC20(crab).balanceOf(address(this));\n\n        ICrabStrategyV2(crab).deposit{ value: _ethToDeposit }();\n\n        _increaseCrabBalance(IERC20(crab).balanceOf(address(this)).sub(crabBalancebefore));\n\n        IERC20(wPowerPerp).transfer(msg.sender, IERC20(wPowerPerp).balanceOf(address(this)));\n\n        emit DepositEthIntoCrab(_ethToDeposit);\n    }\n\n    /**\n     * @notice close out Euler leverage position if contracts have been shut down\n     * @param wethToUniswap weth to repay to uniswap via auction contract\n     * @param shareToUnwind share of crab to redeem scaled by 1e18\n     */\n    function shutdownRepayAndWithdraw(uint256 wethToUniswap, uint256 shareToUnwind) external {\n        require(msg.sender == shutdownContract, \"BS4\");\n        if (shareToUnwind == ONE) {\n            hasRedeemedInShutdown = true;\n        }\n\n        uint256 crabToRedeem = shareToUnwind.wmul(ICrabStrategyV2(crab).balanceOf(address(this)));\n        _decreaseCrabBalance(crabToRedeem);\n        ICrabStrategyV2(crab).withdrawShutdown(crabToRedeem);\n\n        _repayAndWithdrawFromLeverage(shareToUnwind);\n        IWETH9(weth).deposit{ value: wethToUniswap }();\n        IWETH9(weth).transfer(shutdownContract, wethToUniswap);\n\n        emit ShutdownRepayAndWithdraw(wethToUniswap, shareToUnwind, crabToRedeem);\n    }\n\n    /**\n     * @notice allows a user to withdraw their share of ETH if WPowerPerp controller contracts have been shut down\n     * @dev redeemShortShutdown must have been called first\n     * @param _bullAmount bull amount to withdraw\n     */\n    function withdrawShutdown(uint256 _bullAmount) external {\n        require(hasRedeemedInShutdown, \"BS3\");\n\n        uint256 share = _bullAmount.wdiv(totalSupply());\n        uint256 ethToReceive = share.wmul(address(this).balance);\n\n        _burn(msg.sender, _bullAmount);\n\n        payable(msg.sender).sendValue(ethToReceive);\n\n        emit WithdrawShutdown(msg.sender, _bullAmount, ethToReceive);\n    }\n\n    /**\n     * @notice return the internal accounting of the bull strategy's crab balance\n     * @return crab token amount hold by the bull strategy\n     */\n    function getCrabBalance() external view returns (uint256) {\n        return _crabBalance;\n    }\n\n    /**\n     * @notice get crab vault debt and collateral details\n     * @return vault eth collateral, vault wPowerPerp debt\n     */\n    function getCrabVaultDetails() external view returns (uint256, uint256) {\n        return _getCrabVaultDetails();\n    }\n\n    /**\n     * @notice increase internal accounting of bull stragtegy's crab balance\n     * @param _crabAmount crab amount\n     */\n    function _increaseCrabBalance(uint256 _crabAmount) private returns (uint256) {\n        _crabBalance = _crabBalance.add(_crabAmount);\n        return _crabBalance;\n    }\n\n    /**\n     * @notice decrease internal accounting of bull strategy's crab balance\n     * @param _crabAmount crab amount\n     */\n    function _decreaseCrabBalance(uint256 _crabAmount) private returns (uint256) {\n        _crabBalance = _crabBalance.sub(_crabAmount);\n        return _crabBalance;\n    }\n\n    /**\n     * @notice get crab vault debt and collateral details\n     * @return vault eth collateral, vault wPowerPerp debt\n     */\n    function _getCrabVaultDetails() internal view returns (uint256, uint256) {\n        VaultLib.Vault memory strategyVault =\n            IController(powerTokenController).vaults(ICrabStrategyV2(crab).vaultId());\n\n        return (strategyVault.collateralAmount, strategyVault.shortAmount);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/ZenEmergencyShutdown.sol",
    "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity =0.7.6;\npragma abicoder v2;\n\n// interface\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IWETH9 } from \"squeeth-monorepo/interfaces/IWETH9.sol\";\nimport { IZenBullStrategy } from \"./interface/IZenBullStrategy.sol\";\n// contract\nimport { UniFlash } from \"./UniFlash.sol\";\nimport { Ownable } from \"openzeppelin/access/Ownable.sol\";\n//lib\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\n\n/**\n * Error codes\n * ES1: Strategy has already been fully unwound with redeemShortShutdown()\n */\n\n/**\n * @notice ZenEmergencyShutdown contract\n * @dev handle the emergency shutdown of the Bull strategy if the wPowerPerp and Crab contracts are shut down\n * @author opyn team\n */\ncontract ZenEmergencyShutdown is UniFlash, Ownable {\n    using StrategyMath for uint256;\n\n    /// @dev 1e18\n    uint256 private constant ONE = 1e18;\n    /// @dev difference in decimals between WETH and USDC\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n    /// @dev enum to differentiate between Uniswap swap callback function source\n\n    /// @dev enum to differentiate between Uniswap swap callback function source\n    enum FLASH_SOURCE { SHUTDOWN }\n\n    /// @dev redeemShortShutdown params structs\n    struct ShutdownParams {\n        uint256 shareToUnwind;\n        uint256 ethLimitPrice;\n        uint24 ethPoolFee;\n    }\n\n    /// @dev weth address\n    address private immutable weth;\n    /// @dev usdc address\n    address private immutable usdc;\n    /// @dev bull stratgey address\n    address public immutable bullStrategy;\n\n    /**\n     * @notice constructor\n     * @param _bull bull strategy address\n     * @param _factory uniswap v3 factory\n     */\n    constructor(address _bull, address _factory) UniFlash(_factory) {\n        bullStrategy = _bull;\n        weth = IController(IZenBullStrategy(_bull).powerTokenController()).weth();\n        usdc = IController(IZenBullStrategy(_bull).powerTokenController()).quoteCurrency();\n    }\n\n    /**\n     * @notice redeem the Crab shares owned by Bull if WPowerPerp controller contract is shutdown and collapse leverage trade to hold ETH only\n     * @param _params Shutdown params struct\n     */\n\n    function redeemShortShutdown(ShutdownParams calldata _params) external onlyOwner {\n        require(!IZenBullStrategy(bullStrategy).hasRedeemedInShutdown(), \"ES1\");\n\n        uint256 usdcToRepay = IZenBullStrategy(bullStrategy).calcUsdcToRepay(_params.shareToUnwind);\n        _exactOutFlashSwap(\n            weth,\n            usdc,\n            _params.ethPoolFee,\n            usdcToRepay,\n            usdcToRepay.mul(WETH_DECIMALS_DIFF).wdiv(_params.ethLimitPrice),\n            uint8(FLASH_SOURCE.SHUTDOWN),\n            abi.encodePacked(usdcToRepay, _params.shareToUnwind)\n        );\n    }\n\n    /**\n     * @notice uniswap flash swap callback function to handle different types of flashswaps\n     * @dev this function will be called by flashswap callback function uniswapV3SwapCallback()\n     * @param _uniFlashSwapData UniFlashswapCallbackData struct\n     */\n    function _uniFlashSwap(UniFlashswapCallbackData memory _uniFlashSwapData) internal override {\n        if (FLASH_SOURCE(_uniFlashSwapData.callSource) == FLASH_SOURCE.SHUTDOWN) {\n            (uint256 usdcToRepay, uint256 shareToUnwind) =\n                abi.decode(_uniFlashSwapData.callData, (uint256, uint256));\n\n            IERC20(usdc).approve(bullStrategy, usdcToRepay);\n            IZenBullStrategy(bullStrategy).shutdownRepayAndWithdraw(\n                _uniFlashSwapData.amountToPay, shareToUnwind\n            );\n\n            // repay the weth flash swap\n            IWETH9(weth).transfer(_uniFlashSwapData.pool, _uniFlashSwapData.amountToPay);\n        }\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/interface/ICrabStrategyV2.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\n\ninterface ICrabStrategyV2 is IERC20 {\n    function deposit() external payable;\n    function weth() external view returns (address);\n    function wPowerPerp() external view returns (address);\n    function vaultId() external view returns (uint256);\n    function withdraw(uint256 _crabAmount) external;\n    function withdrawShutdown(uint256 _crabAmount) external;\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/interface/IEulerDToken.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\ninterface IEulerDToken {\n    function balanceOf(address account) external view returns (uint256);\n    function borrow(uint256 subAccountId, uint256 amount) external;\n    function repay(uint256 subAccountId, uint256 amount) external;\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/interface/IEulerEToken.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\ninterface IEulerEToken {\n    function balanceOf(address account) external view returns (uint256);\n    function balanceOfUnderlying(address account) external view returns (uint256);\n    function deposit(uint256 subAccountId, uint256 amount) external;\n    function withdraw(uint256 subAccountId, uint256 amount) external;\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/interface/IEulerMarkets.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\ninterface IEulerMarkets {\n    function underlyingToEToken(address underlying) external view returns (address);\n    function underlyingToDToken(address underlying) external view returns (address);\n    function enterMarket(uint256 subAccountId, address newMarket) external;\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/interface/ILeverageZen.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\ninterface ILeverageZen {\n    function calcLeverageEthUsdc(\n        uint256 _crabAmount,\n        uint256 _bullShare,\n        uint256 _ethInCrab,\n        uint256 _squeethInCrab,\n        uint256 _totalCrabSupply\n    ) external view returns (uint256, uint256);\n\n    function calcUsdcToRepay(uint256 _bullShare) external view returns (uint256);\n\n    function calcWethToWithdraw(uint256 _bullShare) external view returns (uint256);\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/interface/IZenBullStrategy.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\ninterface IZenBullStrategy {\n    function deposit(uint256 _crabAmount) external payable;\n    function withdraw(uint256 _bullAmount) external;\n    function crab() external view returns (address);\n    function powerTokenController() external view returns (address);\n    function getCrabVaultDetails() external view returns (uint256, uint256);\n    function calcLeverageEthUsdc(\n        uint256 _crabAmount,\n        uint256 _bullShare,\n        uint256 _ethInCrab,\n        uint256 _squeethInCrab,\n        uint256 _crabTotalSupply\n    ) external view returns (uint256, uint256);\n    function calcUsdcToRepay(uint256 _bullShare) external view returns (uint256);\n    function getCrabBalance() external view returns (uint256);\n    function auctionRepayAndWithdrawFromLeverage(uint256 _usdcToRepay, uint256 _wethToWithdraw)\n        external;\n    function auctionDepositAndRepayFromLeverage(uint256 _wethToDeposit, uint256 _usdcToRepay)\n        external;\n    function shutdownRepayAndWithdraw(uint256 wethToUniswap, uint256 shareToUnwind) external;\n    function hasRedeemedInShutdown() external view returns (bool);\n    function depositAndBorrowFromLeverage(uint256 _wethToDeposit, uint256 _usdcToBorrow) external;\n    function TARGET_CR() external view returns (uint256);\n    function depositEthIntoCrab(uint256 _ethToDeposit) external;\n    function redeemCrabAndWithdrawWEth(uint256 _crabToRedeem, uint256 _wPowerPerpToRedeem)\n        external\n        returns (uint256);\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/src/interface/IZenEmergencyWithdraw.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\ninterface IZenEmergencyWithdraw {\n    function redeemedZenBullAmountForCrabWithdrawal() external returns (uint256);\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/e2e/EmergencyWithdrawScenarios.t.sol",
    "content": "pragma solidity =0.7.6;\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IEulerDToken } from \"../../src/interface/IEulerDToken.sol\";\nimport { Quoter } from \"v3-periphery/lens/Quoter.sol\";\nimport { EmergencyWithdraw } from \"../../src/EmergencyWithdraw.sol\";\nimport { ZenBullStrategy } from \"../../src/ZenBullStrategy.sol\";\nimport { TestUtil } from \"../util/TestUtil.t.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\n\ncontract EmergencyWithdrawScenarios is Test {\n    using StrategyMath for uint256;\n\n    address payable public constant ZEN_BULL = 0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507;\n    address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n    address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n    address payable public constant CONTROLLER = 0x64187ae08781B09368e6253F9E94951243A493D5;\n    address payable public constant CRAB = 0x3B960E47784150F5a63777201ee2B15253D713e8;\n    address public constant UNI_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\n    address public constant WPOWERPERP = 0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B;\n    address public constant ETH_SQUEETH_POOL = 0x82c427AdFDf2d245Ec51D8046b41c4ee87F0d29C;\n    address public constant QUOTER = 0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6;\n    address public constant ZEN_BULL_OWNER = 0xAfE66363c27EedB597a140c28B70b32F113fd5a8;\n    address public constant E_TOKEN = 0x1b808F49ADD4b8C6b5117d9681cF7312Fcf0dC1D;\n    address public constant D_TOKEN = 0x84721A3dB22EB852233AEAE74f9bC8477F8bcc42;\n    address public constant ETH_USDC_POOL = 0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8;\n\n    uint256 deployerPk;\n    uint256 user1Pk;\n    uint256 user2Pk;\n    uint256 user3Pk;\n    address deployer;\n    address user1;\n    address user2;\n    address user3;\n\n    TestUtil internal testUtil;\n    EmergencyWithdraw internal emergencyWithdraw;\n\n    function setUp() public virtual {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 16839439);\n\n        deployerPk = 0xA11CD;\n        deployer = vm.addr(deployerPk);\n        user1Pk = 0xB21CD;\n        user1 = vm.addr(user1Pk);\n        user2Pk = 0xB22CD;\n        user2 = vm.addr(user2Pk);\n        user3Pk = 0xB12CD;\n        user3 = vm.addr(user3Pk);\n\n        vm.label(deployer, \"Deployer\");\n        vm.label(user1, \"user1\");\n        vm.label(user2, \"user2\");\n        vm.label(user3, \"user3\");\n\n        _deployAndConfigure();\n    }\n\n    function testDepositWhenEulerIsNotWorking() public {\n        uint256 crabToDeposit = 10e18;\n\n        vm.startPrank(user1);\n        IERC20(CRAB).approve(ZEN_BULL, crabToDeposit);\n        vm.expectRevert(bytes(\"REVERT\"));\n        ZenBullStrategy(ZEN_BULL).deposit{ value: 100e18 }(crabToDeposit);\n        vm.stopPrank();\n    }\n\n    function testEmergencyWithdrawEthFromCrabWhenEulerIsNotWorking() public {\n        uint256 bullToRedeem = IERC20(ZEN_BULL).balanceOf(user1);\n        (uint256 wPowerPerpToRedeem,) = _calcWPowerPerpAndCrabNeededForWithdraw(bullToRedeem);\n        // transfer some oSQTH from some squeether\n        vm.prank(0x493dd8a5654549726ABA0a4D8882DA5Cd43EaF25);\n        IERC20(WPOWERPERP).transfer(user1, 1000e18);\n\n        vm.startPrank(user1);\n        IERC20(USDC).approve(ZEN_BULL, 10000e6);\n        IERC20(WPOWERPERP).approve(ZEN_BULL, wPowerPerpToRedeem);\n        vm.expectRevert(bytes(\"REVERT\"));\n        ZenBullStrategy(ZEN_BULL).withdraw(bullToRedeem);\n        vm.stopPrank();\n    }\n\n    // function testEmergencyWithdrawEthFromCrabWhenEulerWorksAndAfterEmergencyWithdraw() public {\n    //     // block number before euler rekt\n    //     vm.rollFork(16817896);\n    //     _deployAndConfigure();\n\n    //     uint256 normalWithdrawPayoutBeforeEmergencyWithdraws;\n    //     {\n    //         // normal withdraw from user2\n    //         uint256 bullAmountToWithdraw = IERC20(ZEN_BULL).balanceOf(user2);\n    //         (uint256 wPowerPerpToRedeem, uint256 crabToRedeem) =\n    //             _calcWPowerPerpAndCrabNeededForWithdraw(bullAmountToWithdraw);\n    //         uint256 usdcToRepay = _calcUsdcNeededForWithdraw(bullAmountToWithdraw);\n    //         uint256 wethToWithdrawFromEuler = testUtil.calcWethToWithdraw(bullAmountToWithdraw);\n    //         (uint256 ethInCrab,) = ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n    //         uint256 ethToWithdrawFromCrab =\n    //             crabToRedeem.wdiv(IERC20(CRAB).totalSupply()).wmul(ethInCrab);\n    //         // transfer some oSQTH from some squeether\n    //         vm.prank(0x56178a0d5F301bAf6CF3e1Cd53d9863437345Bf9);\n    //         IERC20(WPOWERPERP).transfer(user2, wPowerPerpToRedeem);\n\n    //         vm.prank(0x0A59649758aa4d66E25f08Dd01271e891fe52199);\n    //         IERC20(USDC).transfer(user2, usdcToRepay);\n\n    //         uint256 user2EthBalanceBefore = address(user2).balance;\n\n    //         vm.startPrank(user2);\n    //         IERC20(USDC).approve(ZEN_BULL, usdcToRepay);\n    //         IERC20(WPOWERPERP).approve(ZEN_BULL, wPowerPerpToRedeem);\n    //         ZenBullStrategy(ZEN_BULL).withdraw(bullAmountToWithdraw);\n    //         vm.stopPrank();\n\n    //         uint256 user2EthBalanceAfter = address(user2).balance;\n    //         normalWithdrawPayoutBeforeEmergencyWithdraws =\n    //             user2EthBalanceAfter.sub(user2EthBalanceBefore);\n    //     }\n\n    //     // roll again before euler rekt\n    //     vm.rollFork(16817896);\n    //     _deployAndConfigure();\n\n    //     // withdraw through emergency contract\n    //     {\n    //         uint256 emergencyRedeemedBull =\n    //             emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n    //         uint256 user1BullBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n\n    //         uint256 maxWethForOsqth;\n    //         {\n    //             uint256 bullShare = user1BullBalanceBefore.wdiv(\n    //                 IERC20(ZEN_BULL).totalSupply().sub(emergencyRedeemedBull)\n    //             );\n    //             uint256 crabToRedeem = bullShare.wmul(ZenBullStrategy(ZEN_BULL).getCrabBalance());\n    //             (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n    //                 ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n    //             uint256 wPowerPerpToRedeem =\n    //                 crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(CRAB).totalSupply());\n\n    //             maxWethForOsqth = Quoter(QUOTER).quoteExactOutputSingle(\n    //                 WETH, WPOWERPERP, 3000, wPowerPerpToRedeem, 0\n    //             );\n    //         }\n\n    //         vm.startPrank(user1);\n    //         IERC20(ZEN_BULL).approve(address(emergencyWithdraw), type(uint256).max);\n    //         emergencyWithdraw.emergencyWithdrawEthFromCrab(user1BullBalanceBefore, maxWethForOsqth);\n    //         vm.stopPrank();\n\n    //         // user3 emergency withdraw\n    //         emergencyRedeemedBull = emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n    //         uint256 user3BullBalanceBefore = IERC20(ZEN_BULL).balanceOf(user3);\n\n    //         {\n    //             uint256 bullShare = user3BullBalanceBefore.wdiv(\n    //                 IERC20(ZEN_BULL).totalSupply().sub(emergencyRedeemedBull)\n    //             );\n    //             uint256 crabToRedeem = bullShare.wmul(ZenBullStrategy(ZEN_BULL).getCrabBalance());\n    //             (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n    //                 ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n    //             uint256 wPowerPerpToRedeem =\n    //                 crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(CRAB).totalSupply());\n\n    //             maxWethForOsqth = Quoter(QUOTER).quoteExactOutputSingle(\n    //                 WETH, WPOWERPERP, 3000, wPowerPerpToRedeem, 0\n    //             );\n    //         }\n\n    //         vm.startPrank(user3);\n    //         IERC20(ZEN_BULL).approve(address(emergencyWithdraw), type(uint256).max);\n    //         emergencyWithdraw.emergencyWithdrawEthFromCrab(user3BullBalanceBefore, maxWethForOsqth);\n    //         vm.stopPrank();\n    //     }\n\n    //     uint256 normalWithdrawPayoutAfterEmergencyWithdraws;\n    //     {\n    //         // normal withdraw from user2\n    //         uint256 bullAmountToWithdraw = IERC20(ZEN_BULL).balanceOf(user2);\n    //         (uint256 wPowerPerpToRedeem, uint256 crabToRedeem) =\n    //             _calcWPowerPerpAndCrabNeededForWithdraw(bullAmountToWithdraw);\n    //         uint256 usdcToRepay = _calcUsdcNeededForWithdraw(bullAmountToWithdraw);\n    //         uint256 wethToWithdrawFromEuler = testUtil.calcWethToWithdraw(bullAmountToWithdraw);\n    //         (uint256 ethInCrab,) = ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n    //         uint256 ethToWithdrawFromCrab =\n    //             crabToRedeem.wdiv(IERC20(CRAB).totalSupply()).wmul(ethInCrab);\n    //         // transfer some oSQTH from some squeether\n    //         vm.prank(0x56178a0d5F301bAf6CF3e1Cd53d9863437345Bf9);\n    //         IERC20(WPOWERPERP).transfer(user2, wPowerPerpToRedeem);\n\n    //         vm.prank(0x0A59649758aa4d66E25f08Dd01271e891fe52199);\n    //         IERC20(USDC).transfer(user2, usdcToRepay);\n\n    //         uint256 user2EthBalanceBefore = address(user2).balance;\n\n    //         vm.startPrank(user2);\n    //         IERC20(USDC).approve(ZEN_BULL, usdcToRepay);\n    //         IERC20(WPOWERPERP).approve(ZEN_BULL, wPowerPerpToRedeem);\n    //         ZenBullStrategy(ZEN_BULL).withdraw(bullAmountToWithdraw);\n    //         vm.stopPrank();\n\n    //         uint256 user2EthBalanceAfter = address(user2).balance;\n    //         normalWithdrawPayoutAfterEmergencyWithdraws =\n    //             user2EthBalanceAfter.sub(user2EthBalanceBefore);\n    //     }\n\n    //     assertLt(\n    //         normalWithdrawPayoutAfterEmergencyWithdraws,\n    //         normalWithdrawPayoutBeforeEmergencyWithdraws\n    //     );\n    // }\n\n    function testScenarioEmergencyWithdrawAfterNormalWithdraw() public {\n        // block number before euler rekt\n        vm.rollFork(16817896);\n        _deployAndConfigure();\n\n        // user1 withdraw through emergency contract\n        {\n            uint256 emergencyRedeemedBull =\n                emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n            uint256 user1BullBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n\n            uint256 maxWethForOsqth;\n            {\n                uint256 bullShare = user1BullBalanceBefore.wdiv(\n                    IERC20(ZEN_BULL).totalSupply().sub(emergencyRedeemedBull)\n                );\n                uint256 crabToRedeem = bullShare.wmul(ZenBullStrategy(ZEN_BULL).getCrabBalance());\n                (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n                    ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n                uint256 wPowerPerpToRedeem =\n                    crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(CRAB).totalSupply());\n\n                maxWethForOsqth = Quoter(QUOTER).quoteExactOutputSingle(\n                    WETH, WPOWERPERP, 3000, wPowerPerpToRedeem, 0\n                );\n            }\n\n            vm.startPrank(user1);\n            IERC20(ZEN_BULL).approve(address(emergencyWithdraw), type(uint256).max);\n            emergencyWithdraw.emergencyWithdrawEthFromCrab(user1BullBalanceBefore, maxWethForOsqth);\n            vm.stopPrank();\n        }\n\n        uint256 normalWithdrawPayoutBeforeEmergencyWithdraws;\n        {\n            // normal withdraw from user2\n            uint256 bullAmountToWithdraw = IERC20(ZEN_BULL).balanceOf(user2);\n            (uint256 wPowerPerpToRedeem, uint256 crabToRedeem) =\n                _calcWPowerPerpAndCrabNeededForWithdraw(bullAmountToWithdraw);\n            uint256 usdcToRepay = _calcUsdcNeededForWithdraw(bullAmountToWithdraw);\n            uint256 wethToWithdrawFromEuler = testUtil.calcWethToWithdraw(bullAmountToWithdraw);\n            (uint256 ethInCrab,) = ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n            uint256 ethToWithdrawFromCrab =\n                crabToRedeem.wdiv(IERC20(CRAB).totalSupply()).wmul(ethInCrab);\n            // transfer some oSQTH from some squeether\n            vm.prank(0x56178a0d5F301bAf6CF3e1Cd53d9863437345Bf9);\n            IERC20(WPOWERPERP).transfer(user2, wPowerPerpToRedeem);\n\n            vm.prank(0x0A59649758aa4d66E25f08Dd01271e891fe52199);\n            IERC20(USDC).transfer(user2, usdcToRepay);\n\n            uint256 user2EthBalanceBefore = address(user2).balance;\n\n            vm.startPrank(user2);\n            IERC20(USDC).approve(ZEN_BULL, usdcToRepay);\n            IERC20(WPOWERPERP).approve(ZEN_BULL, wPowerPerpToRedeem);\n            ZenBullStrategy(ZEN_BULL).withdraw(bullAmountToWithdraw);\n            vm.stopPrank();\n\n            uint256 user2EthBalanceAfter = address(user2).balance;\n            normalWithdrawPayoutBeforeEmergencyWithdraws =\n                user2EthBalanceAfter.sub(user2EthBalanceBefore);\n        }\n    }\n\n    function _deployAndConfigure() internal {\n        vm.startPrank(deployer);\n        emergencyWithdraw =\n        new EmergencyWithdraw(CRAB, ZEN_BULL, WETH, USDC, WPOWERPERP, ETH_USDC_POOL, E_TOKEN, D_TOKEN, UNI_FACTORY);\n        testUtil = new TestUtil(ZEN_BULL, CONTROLLER, E_TOKEN, D_TOKEN, CRAB);\n        vm.stopPrank();\n\n        vm.label(address(emergencyWithdraw), \"EmergencyWithdraw\");\n\n        // prank ZenBull owner to point to a new auction contract address\n        vm.prank(0xAfE66363c27EedB597a140c28B70b32F113fd5a8);\n        ZenBullStrategy(ZEN_BULL).setAuction(address(emergencyWithdraw));\n\n        // bull whale\n        vm.startPrank(0xB845d3C82853b362ADF47A045c087d52384a7776);\n        IERC20(ZEN_BULL).transfer(\n            user1, IERC20(ZEN_BULL).balanceOf(0xB845d3C82853b362ADF47A045c087d52384a7776) / 2\n        );\n        IERC20(ZEN_BULL).transfer(\n            user2, IERC20(ZEN_BULL).balanceOf(0xB845d3C82853b362ADF47A045c087d52384a7776) / 2\n        );\n        vm.stopPrank();\n        vm.startPrank(0xc00d8dAC46b1F8bcEae2477591822B4E5B0a7C6b);\n        IERC20(ZEN_BULL).transfer(\n            user3, IERC20(ZEN_BULL).balanceOf(0xc00d8dAC46b1F8bcEae2477591822B4E5B0a7C6b)\n        );\n        vm.stopPrank();\n        // crab whale\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(CRAB).transfer(user1, 70e18);\n        vm.deal(user1, 100e18);\n    }\n\n    function _emergencyWithdrawEthFromCrab(address _user, uint256 _zenBullAmount) internal {\n        uint256 emergencyRedeemedBull = emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n        uint256 maxWethForOsqth;\n        uint256 ethToWithdrawFromCrab;\n        {\n            uint256 bullShare =\n                _zenBullAmount.wdiv(IERC20(ZEN_BULL).totalSupply().sub(emergencyRedeemedBull));\n            uint256 crabToRedeem = bullShare.wmul(ZenBullStrategy(ZEN_BULL).getCrabBalance());\n            (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n                ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n            uint256 wPowerPerpToRedeem =\n                crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(CRAB).totalSupply());\n\n            maxWethForOsqth =\n                Quoter(QUOTER).quoteExactOutputSingle(WETH, WPOWERPERP, 3000, wPowerPerpToRedeem, 0);\n            ethToWithdrawFromCrab = crabToRedeem.wdiv(IERC20(CRAB).totalSupply()).wmul(ethInCrab);\n        }\n\n        vm.startPrank(_user);\n        IERC20(ZEN_BULL).approve(address(emergencyWithdraw), type(uint256).max);\n        emergencyWithdraw.emergencyWithdrawEthFromCrab(_zenBullAmount, maxWethForOsqth);\n        vm.stopPrank();\n    }\n\n    function _calcWPowerPerpAndCrabNeededForWithdraw(uint256 _bullAmount)\n        internal\n        view\n        returns (uint256, uint256)\n    {\n        uint256 share = _bullAmount.wdiv(ZenBullStrategy(ZEN_BULL).totalSupply());\n        uint256 crabToRedeem = share.wmul(ZenBullStrategy(ZEN_BULL).getCrabBalance());\n        uint256 crabTotalSupply = IERC20(CRAB).totalSupply();\n        (, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        return (crabToRedeem.wmul(squeethInCrab).wdiv(crabTotalSupply), crabToRedeem);\n    }\n\n    function _calcUsdcNeededForWithdraw(uint256 _bullAmount) internal view returns (uint256) {\n        uint256 share = _bullAmount.wdiv(ZenBullStrategy(ZEN_BULL).totalSupply());\n        return share.wmul(IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL));\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/e2e/ShutdownEmergencyWithdrawTest.t.sol",
    "content": "pragma solidity =0.7.6;\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IOracle } from \"squeeth-monorepo/interfaces/IOracle.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { ShutdownEmergencyWithdraw } from \"../../src/ShutdownEmergencyWithdraw.sol\";\nimport { ZenBullStrategy } from \"../../src/ZenBullStrategy.sol\";\nimport { IZenEmergencyWithdraw } from \"../../src/interface/IZenEmergencyWithdraw.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\n\ncontract ShutdownEmergencyWithdrawTest is Test {\n    using StrategyMath for uint256;\n\n    address payable public constant ZEN_BULL = 0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507;\n    address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n    address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n    address payable public constant CRAB = 0x3B960E47784150F5a63777201ee2B15253D713e8;\n    address public constant OSQTH = 0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B;\n    address public constant ETH_USDC_POOL = 0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8;\n    address payable public constant CONTROLLER = 0x64187ae08781B09368e6253F9E94951243A493D5;\n    address public constant ORACLE = 0x65D66c76447ccB45dAf1e8044e918fA786A483A1;\n    address public constant ZEN_BULL_EMERGENCY_WITHDRAW = 0x3DdC956B08c0A6dA2249f8c528fF0594F5AEa381;\n\n    // multisig owner\n    address public constant OWNER = 0xAfE66363c27EedB597a140c28B70b32F113fd5a8;\n\n    uint256 public constant INDEX_SCALE = 1e4;\n    uint32 public constant TWAP_PERIOD = 420 seconds;\n\n    uint256 deployerPk;\n    uint256 user3Pk;\n    address deployer;\n    address user1;\n    address user2;\n    address user3;\n\n    ShutdownEmergencyWithdraw internal shutdownEmergencyWithdraw;\n\n    function setUp() public virtual {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 21095588);\n\n        deployerPk = 0xA11CD;\n        deployer = vm.addr(deployerPk);\n        user1 = 0x73738c989398EBAfdAfD097836Fd910BAc14CCDC;\n        user2 = 0x1ba20876565280C8274eEd551B575936097e414F;\n        user3Pk = 0xB12CD;\n        user3 = vm.addr(user3Pk);\n\n        vm.label(deployer, \"Deployer\");\n        vm.label(user1, \"User1\");\n        vm.label(user2, \"User2\");\n        _deployAndConfigure();\n    }\n\n    function testShutdownEmergencyWithdrawNotOwner() public {\n        vm.startPrank(user1);\n        vm.expectRevert(\"Ownable: caller is not the owner\");\n        shutdownEmergencyWithdraw.shutdownEmergencyWithdraw();\n        vm.stopPrank();\n    }\n\n    function testShutdownEmergencyWithdrawFromDeployerNotOwner() public {\n        vm.startPrank(deployer);\n        vm.expectRevert(\"Ownable: caller is not the owner\");\n        shutdownEmergencyWithdraw.shutdownEmergencyWithdraw();\n        vm.stopPrank();\n    }\n\n    function testShutdownEmergencyWithdraw() public {\n        // get initial crab balance in zen bull strategy\n        uint256 initialZenBullCrabBalance = ZenBullStrategy(ZEN_BULL).getCrabBalance();\n\n        (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n            ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n\n        uint256 ethShare = initialZenBullCrabBalance.wdiv(IERC20(CRAB).totalSupply());\n        uint256 wethToReceive = ethInCrab.wmul(ethShare);\n\n        uint256 ethIndexPrice =\n            IOracle(ORACLE).getTwap(ETH_USDC_POOL, WETH, USDC, TWAP_PERIOD, true).div(INDEX_SCALE);\n\n        uint256 wPowerPerpToProvide =\n            initialZenBullCrabBalance.wmul(wPowerPerpInCrab).wdiv(IERC20(CRAB).totalSupply());\n        uint256 wethToCaller = wPowerPerpToProvide.wmul(ethIndexPrice).wmul(\n            IController(CONTROLLER).getExpectedNormalizationFactor()\n        );\n\n        // use deal() to get some oSQTH for testing\n        deal(address(OSQTH), address(OWNER), wPowerPerpToProvide);\n\n        // get initial balances\n        uint256 initialOwnerWethBalance = IERC20(WETH).balanceOf(OWNER);\n        uint256 initialOwnerWPowerPerpBalance = IERC20(OSQTH).balanceOf(OWNER);\n\n        // execute emergency withdrawal\n        vm.startPrank(OWNER);\n        IERC20(OSQTH).approve(address(shutdownEmergencyWithdraw), wPowerPerpToProvide);\n        shutdownEmergencyWithdraw.shutdownEmergencyWithdraw();\n        vm.stopPrank();\n\n        // verify the results\n        uint256 finalOwnerWethBalance = IERC20(WETH).balanceOf(OWNER);\n        uint256 finalZenBullCrabBalance = ZenBullStrategy(ZEN_BULL).getCrabBalance();\n        uint256 finalZenBullCrabBalanceFromCrab = IERC20(CRAB).balanceOf(address(ZEN_BULL));\n        uint256 finalOwnerWPowerPerpBalance = IERC20(OSQTH).balanceOf(OWNER);\n\n        // check that ETH was received by deployer\n        assertEq(\n            finalOwnerWethBalance,\n            initialOwnerWethBalance + wethToCaller,\n            \"Owner should have received correct WETH\"\n        );\n\n        // check that contract has correct eth balance\n        assertEq(\n            IERC20(WETH).balanceOf(address(shutdownEmergencyWithdraw)),\n            wethToReceive - wethToCaller,\n            \"ShutdownEmergencyWithdraw should have correct WETH balance\"\n        );\n        assertApproxEqRel(\n            IERC20(WETH).balanceOf(address(shutdownEmergencyWithdraw)),\n            wethToCaller,\n            7e16,\n            \"The value of WETH should be close to 50% / 50%, within 7%\"\n        );\n        // check that Crab balance was reduced and wpowerperp was provided correctly\n        assertEq(finalZenBullCrabBalance, 0, \"All Crab should have been redeemed\");\n        assertEq(finalZenBullCrabBalanceFromCrab, 0, \"All Crab should have been redeemed\");\n        assertEq(\n            finalOwnerWPowerPerpBalance,\n            initialOwnerWPowerPerpBalance - wPowerPerpToProvide,\n            \"Owner should have provided correct WPowerPerp\"\n        );\n    }\n\n    function testClaimZenBullRedemption() public {\n        // get initial crab balance in zen bull strategy\n        uint256 initialZenBullCrabBalance = ZenBullStrategy(ZEN_BULL).getCrabBalance();\n\n        (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n            ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n\n        uint256 share = initialZenBullCrabBalance.wdiv(IERC20(CRAB).totalSupply());\n        uint256 wethToReceive = ethInCrab.wmul(share);\n\n        uint256 wPowerPerpToProvide =\n            initialZenBullCrabBalance.wmul(wPowerPerpInCrab).wdiv(IERC20(CRAB).totalSupply());\n\n        // use deal() to get some oSQTH for testing\n        deal(address(OSQTH), address(OWNER), wPowerPerpToProvide);\n\n        // execute emergency withdrawal\n        vm.startPrank(OWNER);\n        IERC20(OSQTH).approve(address(shutdownEmergencyWithdraw), wPowerPerpToProvide);\n        shutdownEmergencyWithdraw.shutdownEmergencyWithdraw();\n        vm.stopPrank();\n\n        // get initial balances before claiming\n        uint256 initialOwnerWethBalance = IERC20(WETH).balanceOf(OWNER);\n        uint256 initialUser1WethBalance = IERC20(WETH).balanceOf(user1);\n        uint256 initialUser1ZenBullBalance = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 initialUser2WethBalance = IERC20(WETH).balanceOf(user2);\n        uint256 initialUser2ZenBullBalance = IERC20(ZEN_BULL).balanceOf(user2);\n\n        assertGt(initialUser1ZenBullBalance, 0, \"User1 should have some ZenBull\");\n        assertGt(initialUser2ZenBullBalance, 0, \"User2 should have some ZenBull\");\n\n        uint256 remainingZenBullTotalSupply = IERC20(ZEN_BULL).totalSupply()\n            - IZenEmergencyWithdraw(ZEN_BULL_EMERGENCY_WITHDRAW).redeemedZenBullAmountForCrabWithdrawal(\n            );\n        uint256 user1WethToReceive = initialUser1ZenBullBalance.wmul(\n            IERC20(WETH).balanceOf(address(shutdownEmergencyWithdraw))\n        ).wdiv(remainingZenBullTotalSupply);\n        uint256 user2WethToReceive = initialUser2ZenBullBalance.wmul(\n            IERC20(WETH).balanceOf(address(shutdownEmergencyWithdraw))\n        ).wdiv(remainingZenBullTotalSupply);\n\n        uint256 user1WethExpectedCheck;\n\n        {\n        uint256 totalSupplyCheck = 205.071599790461620024e18-190.713979953694709911e18;\n        uint256 initialUser1ZenBullBalanceCheck = 6.868492039476635186e18;\n\n        user1WethExpectedCheck = initialUser1ZenBullBalanceCheck.wmul(IERC20(WETH).balanceOf(address(shutdownEmergencyWithdraw))).wdiv(totalSupplyCheck);\n        }\n        \n        vm.startPrank(user1);\n        IERC20(ZEN_BULL).approve(address(shutdownEmergencyWithdraw), initialUser1ZenBullBalance);\n        shutdownEmergencyWithdraw.claimZenBullRedemption(initialUser1ZenBullBalance);\n        vm.stopPrank();\n\n        uint256 finalUser1WethBalance = IERC20(WETH).balanceOf(user1);\n        uint256 finalUser1ZenBullBalance = IERC20(ZEN_BULL).balanceOf(user1);\n\n        vm.startPrank(user2);\n        IERC20(ZEN_BULL).approve(address(shutdownEmergencyWithdraw), initialUser2ZenBullBalance);\n        shutdownEmergencyWithdraw.claimZenBullRedemption(initialUser2ZenBullBalance);\n        vm.stopPrank();\n\n        vm.startPrank(user3);\n        IERC20(ZEN_BULL).approve(address(shutdownEmergencyWithdraw), 1e18);\n        vm.expectRevert(\"ERC20: transfer amount exceeds balance\");\n        shutdownEmergencyWithdraw.claimZenBullRedemption(1e18);\n        vm.stopPrank();\n\n        uint256 finalUser2WethBalance = IERC20(WETH).balanceOf(user2);\n        uint256 finalUser2ZenBullBalance = IERC20(ZEN_BULL).balanceOf(user2);\n        uint256 finalOwnerWethBalance = IERC20(WETH).balanceOf(OWNER);\n\n        //user 1\n        assertEq(finalUser1ZenBullBalance, 0, \"User1 should have no ZenBull left\");\n        assertEq(\n            finalUser1WethBalance,\n            initialUser1WethBalance + user1WethToReceive,\n            \"User1 should have received correct WETH\"\n        );\n        assertEq(\n            finalUser1WethBalance,\n            initialUser1WethBalance + user1WethExpectedCheck,\n            \"User1 should have received correct WETH check\"\n        );\n        //user 2\n        assertEq(finalUser2ZenBullBalance, 0, \"User2 should have no ZenBull left\");\n        assertEq(\n            finalUser2WethBalance,\n            initialUser2WethBalance + user2WethToReceive,\n            \"User2 should have received correct WETH\"\n        );\n        //owner\n        assertEq(\n            finalOwnerWethBalance,\n            initialOwnerWethBalance,\n            \"Owner should have not received any WETH\"\n        );\n    }\n\n    function _deployAndConfigure() internal {\n        vm.startPrank(deployer);\n        shutdownEmergencyWithdraw = new ShutdownEmergencyWithdraw(\n            CRAB,\n            ZEN_BULL,\n            WETH,\n            USDC,\n            OSQTH,\n            ETH_USDC_POOL,\n            ORACLE,\n            ZEN_BULL_EMERGENCY_WITHDRAW,\n            CONTROLLER,\n            OWNER\n        );\n        vm.stopPrank();\n\n        // prank ZenBull owner to point to a new auction contract address\n        vm.prank(OWNER);\n        ZenBullStrategy(ZEN_BULL).setAuction(address(shutdownEmergencyWithdraw));\n\n        assertEq(\n            shutdownEmergencyWithdraw.owner(),\n            OWNER,\n            \"ShutdownEmergencyWithdraw should have the correct owner\"\n        );\n\n        vm.label(address(shutdownEmergencyWithdraw), \"ShutdownWithdraw\");\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/fuzz-test/FlashZenFuzzTest.t.sol",
    "content": "pragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IEulerMarkets } from \"../../src/interface/IEulerMarkets.sol\";\nimport { IEulerEToken } from \"../../src/interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"../../src/interface/IEulerDToken.sol\";\n// contract\nimport { TestUtil } from \"../util/TestUtil.t.sol\";\nimport { ZenBullStrategy } from \"../../src/ZenBullStrategy.sol\";\nimport { CrabStrategyV2 } from \"squeeth-monorepo/strategy/CrabStrategyV2.sol\";\nimport { Controller } from \"squeeth-monorepo/core/Controller.sol\";\nimport { FlashZen } from \"../../src/FlashZen.sol\";\n// lib\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\nimport { UniOracle } from \"../../src/UniOracle.sol\";\n\n/**\n * @notice fuzz testing\n */\ncontract FlashZenFuzzTest is Test {\n    using StrategyMath for uint256;\n\n    uint32 internal constant TWAP = 420;\n    uint128 internal constant ONE = 1e18;\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n\n    TestUtil internal testUtil;\n    FlashZen internal flashBull;\n    ZenBullStrategy internal bullStrategy;\n    CrabStrategyV2 internal crabV2;\n    Controller internal controller;\n\n    address internal weth;\n    address internal usdc;\n    address internal euler;\n    address internal eulerMarketsModule;\n    address internal eToken;\n    address internal dToken;\n    address internal wPowerPerp;\n    address internal ethWSqueethPool;\n    address internal ethUsdcPool;\n\n    uint256 internal user1Pk;\n    uint256 internal deployerPk;\n    address internal user1;\n    address internal deployer;\n\n    uint256 internal cap;\n\n    // var to avoid stack too deep in test functions\n    uint256 userEthBalanceBeforeTx;\n    uint256 bullToMint;\n\n    function setUp() public {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 15781550);\n\n        deployerPk = 0xAB11CE;\n        deployer = vm.addr(deployerPk);\n\n        vm.startPrank(deployer);\n        euler = 0x27182842E098f60e3D576794A5bFFb0777E025d3;\n        eulerMarketsModule = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3;\n        controller = Controller(0x64187ae08781B09368e6253F9E94951243A493D5);\n        crabV2 = CrabStrategyV2(0x3B960E47784150F5a63777201ee2B15253D713e8);\n        bullStrategy = new ZenBullStrategy(\n            address(crabV2),\n            address(controller),\n            euler,\n            eulerMarketsModule\n        );\n        bullStrategy.transferOwnership(deployer);\n        flashBull = new FlashZen(\n            address(bullStrategy),\n            0x1F98431c8aD98523631AE4a59f267346ea31F984\n        );\n        usdc = controller.quoteCurrency();\n        weth = controller.weth();\n        eToken = IEulerMarkets(eulerMarketsModule).underlyingToEToken(weth);\n        dToken = IEulerMarkets(eulerMarketsModule).underlyingToDToken(usdc);\n        wPowerPerp = controller.wPowerPerp();\n        ethWSqueethPool = IController(bullStrategy.powerTokenController()).wPowerPerpPool();\n        ethUsdcPool = IController(bullStrategy.powerTokenController()).ethQuoteCurrencyPool();\n        testUtil = new TestUtil(\n            address(bullStrategy),\n            address(controller),\n            eToken,\n            dToken,\n            address(crabV2)\n        );\n\n        cap = 100000e18;\n        bullStrategy.setCap(cap);\n\n        vm.stopPrank();\n        user1Pk = 0xA11CE;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User 1\");\n        vm.label(address(bullStrategy), \"BullStrategy\");\n        vm.label(address(flashBull), \"FlashBull\");\n        vm.label(euler, \"Euler\");\n        vm.label(eulerMarketsModule, \"EulerMarkets\");\n        vm.label(usdc, \"USDC\");\n        vm.label(weth, \"WETH\");\n\n        vm.deal(user1, 100000000e18);\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 100e18);\n        // some WETH and USDC rich address\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(weth).transfer(user1, 10100e18);\n    }\n\n    function testFuzzingFlashDeposit(uint256 _ethToCrab) public {\n        _ethToCrab = bound(_ethToCrab, 1e16, 600e18);\n        (uint256 ethInCrab, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n\n        (uint256 wSqueethToMint, uint256 fee) =\n            _calcWsqueethToMintAndFee(_ethToCrab, squeethInCrab, ethInCrab);\n        uint256 crabToBeMinted =\n            _calcSharesToMint(_ethToCrab.sub(fee), ethInCrab, IERC20(crabV2).totalSupply());\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        {\n            ethInCrab += _ethToCrab;\n            squeethInCrab += wSqueethToMint;\n        }\n\n        (uint256 wethToLend, uint256 usdcToBorrow) = bullStrategy.calcLeverageEthUsdc(\n            crabToBeMinted, 1e18, ethInCrab, squeethInCrab, crabV2.totalSupply().add(crabToBeMinted)\n        );\n\n        uint256 minEthFromSqueeth;\n        uint256 minEthFromUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            minEthFromSqueeth = wSqueethToMint.wmul(squeethEthPrice.wmul(95e16));\n            minEthFromUsdc = usdcToBorrow.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(101e16));\n        }\n        bullToMint = testUtil.calcBullToMint(crabToBeMinted);\n\n        vm.startPrank(user1);\n        flashBull.flashDeposit{\n            value: calcTotalEthToBull(wethToLend, _ethToCrab, usdcToBorrow, wSqueethToMint)\n        }(\n            FlashZen.FlashDepositParams({\n                ethToCrab: _ethToCrab,\n                minEthFromSqth: minEthFromSqueeth,\n                minEthFromUsdc: minEthFromUsdc,\n                wPowerPerpPoolFee: uint24(3000),\n                usdcPoolFee: uint24(3000)\n            })\n        );\n        vm.stopPrank();\n\n        assertEq(\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)),\n            usdcToBorrow,\n            \"Bull USDC debt amount mismatch\"\n        );\n        assertApproxEqAbs(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), wethToLend, 5\n        );\n        assertEq(\n            bullStrategy.getCrabBalance().sub(crabToBeMinted),\n            bullCrabBalanceBefore,\n            \"Bull crab balance mismatch\"\n        );\n        assertEq(bullToMint, bullStrategy.balanceOf(user1), \"User1 bull balance mismatch\");\n    }\n\n    function testFuzzingFlashWithdraw(uint256 _crabAmount) public {\n        _crabAmount = bound(\n            _crabAmount, 1e18, IERC20(crabV2).balanceOf(0x06CECFbac34101aE41C88EbC2450f8602b3d164b)\n        );\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, _crabAmount);\n        vm.startPrank(user1);\n        _deposit(_crabAmount);\n        vm.stopPrank();\n\n        uint256 bullToRedeem = bullStrategy.balanceOf(user1);\n        (uint256 crabToRedeem, uint256 wPowerPerpToRedeem,, uint256 usdcToRepay) =\n            calcAssetsNeededForFlashWithdraw(bullToRedeem);\n        uint256 maxEthForWPowerPerp;\n        uint256 maxEthForUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n\n            maxEthForWPowerPerp = wPowerPerpToRedeem.wmul(squeethEthPrice.wmul(105e16));\n            maxEthForUsdc =\n                usdcToRepay.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(uint256(1e18).sub(5e15)));\n        }\n\n        FlashZen.FlashWithdrawParams memory params = FlashZen.FlashWithdrawParams({\n            bullAmount: bullStrategy.balanceOf(user1),\n            maxEthForWPowerPerp: maxEthForWPowerPerp,\n            maxEthForUsdc: maxEthForUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        uint256 wethToWithdraw = testUtil.calcWethToWithdraw(bullToRedeem);\n        uint256 userBullBalanceBefore = bullStrategy.balanceOf(user1);\n        uint256 ethInLendingBefore = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        uint256 usdcBorrowedBefore = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        uint256 crabBalanceBefore = crabV2.balanceOf(address(bullStrategy));\n\n        vm.startPrank(user1);\n        bullStrategy.approve(address(flashBull), params.bullAmount);\n        flashBull.flashWithdraw(params);\n        vm.stopPrank();\n\n        assertEq(\n            usdcBorrowedBefore.sub(usdcToRepay),\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)),\n            \"Bull USDC debt amount mismatch\"\n        );\n        assertEq(\n            ethInLendingBefore.sub(wethToWithdraw),\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)),\n            \"Bull ETH in leverage amount mismatch\"\n        );\n        assertEq(\n            userBullBalanceBefore.sub(bullToRedeem),\n            bullStrategy.balanceOf(user1),\n            \"User1 bull balance mismatch\"\n        );\n        assertEq(\n            crabBalanceBefore.sub(crabToRedeem),\n            crabV2.balanceOf(address(bullStrategy)),\n            \"Bull crab balance mismatch\"\n        );\n        // ignoring the assert below because I couldn't find a exact way to calc ethToWithdrawFromBull as I'm setting maxToPay higher than the actual slippage, need to read events\n        // assertTrue((user1.balance).sub(userEthBalanceBeforeTx).sub(ethToWithdrawFromBull) <= 1e18);\n    }\n\n    /**\n     *\n     * /************************************************************* Helper functions! ************************************************************\n     */\n    function squeethPrice() internal view returns (uint256) {\n        return UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n    }\n\n    function ethPrice() internal view returns (uint256) {\n        return UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n    }\n\n    function calcTotalEthToBull(\n        uint256 wethToLend,\n        uint256 ethToCrab,\n        uint256 usdcToBorrow,\n        uint256 wSqueethToMint\n    ) internal view returns (uint256) {\n        uint256 totalEthToBull = wethToLend.add(ethToCrab).sub(usdcToBorrow.wdiv(ethPrice())).sub(\n            wSqueethToMint.wmul(squeethPrice())\n        ).add(1e16);\n        return totalEthToBull;\n    }\n\n    function _calcWsqueethToMintAndFee(\n        uint256 _depositedAmount,\n        uint256 _strategyDebtAmount,\n        uint256 _strategyCollateralAmount\n    ) internal view returns (uint256, uint256) {\n        uint256 wSqueethToMint;\n        uint256 wSqueethEthPrice =\n            UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n        uint256 feeRate = IController(bullStrategy.powerTokenController()).feeRate();\n        uint256 feeAdjustment = wSqueethEthPrice.mul(feeRate).div(10000);\n\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\n        );\n\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\n\n        return (wSqueethToMint, fee);\n    }\n\n    /**\n     * @dev calculate amount of strategy token to mint for depositor\n     * @param _amount amount of ETH deposited\n     * @param _strategyCollateralAmount amount of strategy collateral\n     * @param _crabTotalSupply total supply of strategy token\n     * @return amount of strategy token to mint\n     */\n    function _calcSharesToMint(\n        uint256 _amount,\n        uint256 _strategyCollateralAmount,\n        uint256 _crabTotalSupply\n    ) internal pure returns (uint256) {\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\n\n        if (_crabTotalSupply != 0) {\n            return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\n        }\n\n        return _amount;\n    }\n\n    function _deposit(uint256 _crabToDeposit) internal returns (uint256, uint256) {\n        (uint256 wethToLend, uint256 usdcToBorrow) =\n            testUtil.calcCollateralAndBorrowAmount(_crabToDeposit);\n\n        IERC20(crabV2).approve(address(bullStrategy), _crabToDeposit);\n        bullStrategy.deposit{ value: wethToLend }(_crabToDeposit);\n\n        return (wethToLend, usdcToBorrow);\n    }\n\n    function calcAssetsNeededForFlashWithdraw(uint256 _bullAmount)\n        internal\n        view\n        returns (uint256, uint256, uint256, uint256)\n    {\n        uint256 bullShare = _bullAmount.wdiv(bullStrategy.totalSupply());\n        uint256 crabToRedeem = bullShare.wmul(crabV2.balanceOf(address(bullStrategy)));\n        (uint256 ethInCrab, uint256 squeethInCrab) = bullStrategy.getCrabVaultDetails();\n        uint256 crabTotalSupply = crabV2.totalSupply();\n        uint256 wPowerPerpToRedeem = crabToRedeem.wmul(squeethInCrab).wdiv(crabTotalSupply);\n        uint256 ethToWithdraw = crabToRedeem.wmul(ethInCrab).wdiv(crabTotalSupply);\n        uint256 usdcToRepay = bullStrategy.calcUsdcToRepay(bullShare);\n\n        return (crabToRedeem, wPowerPerpToRedeem, ethToWithdraw, usdcToRepay);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/fuzz-test/LeverageZenFuzzTest.t.sol",
    "content": "pragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IWETH9 } from \"squeeth-monorepo/interfaces/IWETH9.sol\";\nimport { IEulerMarkets } from \"../../src/interface/IEulerMarkets.sol\";\nimport { IEulerEToken } from \"../../src/interface/IEulerEToken.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IEulerDToken } from \"../../src/interface/IEulerDToken.sol\";\n// contract\nimport { LeverageZen } from \"../../src/LeverageZen.sol\";\nimport { Controller } from \"squeeth-monorepo/core/Controller.sol\";\n// lib\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\nimport { UniOracle } from \"../../src/UniOracle.sol\";\n\n/**\n * @notice fuzz testing\n */\ncontract LeverageZenFuzzTest is Test {\n    using StrategyMath for uint256;\n\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n    uint32 internal constant TWAP = 420;\n    uint256 public constant TARGET_CR = 2e18; // 200% collat ratio\n\n    Controller internal controller;\n    LeverageZen internal leverageBull;\n\n    uint256 internal leverageOwnerPk;\n    uint256 internal deployerPk;\n    uint256 internal auctionPk;\n\n    address internal leverageOwner;\n    address internal deployer;\n    address internal auction;\n\n    address internal weth;\n    address internal usdc;\n    address internal euler;\n    address internal eulerMarketsModule;\n    address internal eToken;\n    address internal ethUsdcPool;\n    address internal dToken;\n\n    function setUp() public {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 15781550);\n\n        deployerPk = 0xA11CD;\n        deployer = vm.addr(deployerPk);\n        leverageOwnerPk = 0xB11CD;\n        leverageOwner = vm.addr(leverageOwnerPk);\n        auctionPk = 0xA11CE;\n        auction = vm.addr(auctionPk);\n\n        vm.startPrank(deployer);\n        euler = 0x27182842E098f60e3D576794A5bFFb0777E025d3;\n        eulerMarketsModule = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3;\n        controller = Controller(0x64187ae08781B09368e6253F9E94951243A493D5);\n        leverageBull = new LeverageZen(euler, eulerMarketsModule, address(controller));\n        leverageBull.transferOwnership(leverageOwner);\n        usdc = controller.quoteCurrency();\n        weth = controller.weth();\n        eToken = IEulerMarkets(eulerMarketsModule).underlyingToEToken(weth);\n        dToken = IEulerMarkets(eulerMarketsModule).underlyingToDToken(usdc);\n        ethUsdcPool = controller.ethQuoteCurrencyPool();\n        vm.stopPrank();\n\n        vm.prank(leverageOwner);\n        leverageBull.setAuction(auction);\n\n        vm.label(auction, \"Auction\");\n        vm.label(address(leverageBull), \"LeverageBull\");\n        vm.label(euler, \"Euler\");\n        vm.label(eulerMarketsModule, \"EulerMarkets\");\n        vm.label(usdc, \"USDC\");\n        vm.label(weth, \"WETH\");\n    }\n\n    function testFuzzingDepositAndWithdrawFullBalanceOfUnderlying(uint256 _wethToDeposit) public {\n        _wethToDeposit = bound(_wethToDeposit, 1e18, 100000000e18);\n\n        vm.deal(auction, _wethToDeposit);\n\n        vm.startPrank(auction);\n        // deposit first WETH in euler\n        IWETH9(weth).deposit{ value: _wethToDeposit }();\n        IWETH9(weth).approve(address(leverageBull), _wethToDeposit);\n        leverageBull.depositAndBorrowFromLeverage(_wethToDeposit, 0);\n        vm.stopPrank();\n\n        vm.prank(address(leverageBull));\n        IEulerMarkets(eulerMarketsModule).enterMarket(0, weth);\n\n        uint256 balanceOfUnderlying =\n            IEulerEToken(eToken).balanceOfUnderlying(address(leverageBull));\n        uint256 wethBalanceBefore = IERC20(weth).balanceOf(auction);\n\n        // balanceOfUnderlying is rounded down after deposit, 2wei delta sometimes\n        assertApproxEqAbs(balanceOfUnderlying, _wethToDeposit, 2);\n\n        vm.prank(auction);\n        leverageBull.auctionRepayAndWithdrawFromLeverage(0, balanceOfUnderlying);\n\n        uint256 wethBalanceAfter = IERC20(weth).balanceOf(auction);\n        uint256 eTokenBalanceAfter = IERC20(eToken).balanceOf(address(leverageBull));\n\n        assertEq(eTokenBalanceAfter, 0);\n        assertEq(wethBalanceAfter.sub(wethBalanceBefore), balanceOfUnderlying);\n    }\n\n    function testFuzzingDepositAndWithdrawPartialBalanceOfUnderlying(\n        uint256 _wethToDeposit,\n        uint256 _percentage\n    ) public {\n        _wethToDeposit = bound(_wethToDeposit, 1e18, 100000000e18);\n        _percentage = bound(_percentage, 0, 100);\n\n        vm.deal(auction, _wethToDeposit);\n\n        vm.startPrank(auction);\n        // deposit first WETH in euler\n        IWETH9(weth).deposit{ value: _wethToDeposit }();\n        IWETH9(weth).approve(address(leverageBull), _wethToDeposit);\n        leverageBull.depositAndBorrowFromLeverage(_wethToDeposit, 0);\n        vm.stopPrank();\n\n        vm.prank(address(leverageBull));\n        IEulerMarkets(eulerMarketsModule).enterMarket(0, weth);\n\n        uint256 balanceOfUnderlying =\n            IEulerEToken(eToken).balanceOfUnderlying(address(leverageBull));\n        uint256 wethBalanceBefore = IERC20(weth).balanceOf(auction);\n        uint256 balanceOfUnderlyingToWithdraw = balanceOfUnderlying.mul(_percentage).div(100);\n\n        // balanceOfUnderlying is rounded down after deposit, 2wei delta sometimes\n        assertApproxEqAbs(balanceOfUnderlying, _wethToDeposit, 2);\n\n        vm.prank(auction);\n        leverageBull.auctionRepayAndWithdrawFromLeverage(0, balanceOfUnderlyingToWithdraw);\n\n        uint256 wethBalanceAfter = IERC20(weth).balanceOf(auction);\n\n        assertEq(wethBalanceAfter.sub(wethBalanceBefore), balanceOfUnderlyingToWithdraw);\n    }\n\n    function testFuzzingBorrowAndRepayFullBalanceOf(uint256 _wethToDeposit) public {\n        _wethToDeposit = bound(_wethToDeposit, 1e18, 100000000e18);\n\n        vm.deal(auction, _wethToDeposit);\n\n        vm.startPrank(auction);\n        // deposit first WETH in euler\n        IWETH9(weth).deposit{ value: _wethToDeposit }();\n        IWETH9(weth).approve(address(leverageBull), _wethToDeposit);\n        leverageBull.depositAndBorrowFromLeverage(_wethToDeposit, 0);\n        vm.stopPrank();\n\n        vm.prank(address(leverageBull));\n        IEulerMarkets(eulerMarketsModule).enterMarket(0, weth);\n\n        uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n        uint256 usdcToBorrow =\n            _wethToDeposit.wmul(ethUsdPrice).wdiv(TARGET_CR).div(WETH_DECIMALS_DIFF);\n        uint256 eulerUsdcBalance = IERC20(usdc).balanceOf(euler);\n\n        if (usdcToBorrow > eulerUsdcBalance) usdcToBorrow = eulerUsdcBalance;\n\n        uint256 usdcBalanceBefore = IERC20(usdc).balanceOf(auction);\n\n        vm.startPrank(auction);\n        leverageBull.depositAndBorrowFromLeverage(0, usdcToBorrow);\n        vm.stopPrank();\n\n        uint256 usdcBalanceAfter = IERC20(usdc).balanceOf(auction);\n\n        assertEq(usdcBalanceAfter.sub(usdcBalanceBefore), usdcToBorrow);\n\n        vm.startPrank(auction);\n        uint256 usdcToRepay = IEulerDToken(dToken).balanceOf(address(leverageBull));\n        IERC20(usdc).approve(address(leverageBull), usdcToRepay);\n        leverageBull.auctionRepayAndWithdrawFromLeverage(usdcToRepay, 0);\n\n        assertEq(IEulerDToken(dToken).balanceOf(auction), 0);\n        assertEq(usdcBalanceAfter.sub(usdcToRepay), 0);\n    }\n\n    function testFuzzingBorrowAndRepayPartialBalanceOf(uint256 _wethToDeposit, uint256 _percentage)\n        public\n    {\n        _wethToDeposit = bound(_wethToDeposit, 1e18, 100000000e18);\n        _percentage = bound(_percentage, 0, 100);\n\n        vm.deal(auction, _wethToDeposit);\n\n        vm.startPrank(auction);\n        // deposit first WETH in euler\n        IWETH9(weth).deposit{ value: _wethToDeposit }();\n        IWETH9(weth).approve(address(leverageBull), _wethToDeposit);\n        leverageBull.depositAndBorrowFromLeverage(_wethToDeposit, 0);\n        vm.stopPrank();\n\n        vm.prank(address(leverageBull));\n        IEulerMarkets(eulerMarketsModule).enterMarket(0, weth);\n\n        uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n        uint256 usdcToBorrow =\n            _wethToDeposit.wmul(ethUsdPrice).wdiv(TARGET_CR).div(WETH_DECIMALS_DIFF);\n        uint256 eulerUsdcBalance = IERC20(usdc).balanceOf(euler);\n\n        if (usdcToBorrow > eulerUsdcBalance) usdcToBorrow = eulerUsdcBalance;\n\n        uint256 usdcBalanceBefore = IERC20(usdc).balanceOf(auction);\n\n        vm.startPrank(auction);\n        leverageBull.depositAndBorrowFromLeverage(0, usdcToBorrow);\n        vm.stopPrank();\n\n        uint256 usdcBalanceAfter = IERC20(usdc).balanceOf(auction);\n\n        assertEq(usdcBalanceAfter.sub(usdcBalanceBefore), usdcToBorrow);\n\n        vm.startPrank(auction);\n        uint256 debtAmount = IEulerDToken(dToken).balanceOf(address(leverageBull));\n        uint256 usdcToRepay = debtAmount.mul(_percentage).div(100);\n        IERC20(usdc).approve(address(leverageBull), usdcToRepay);\n        leverageBull.auctionRepayAndWithdrawFromLeverage(usdcToRepay, 0);\n\n        assertEq(debtAmount.sub(usdcToRepay), IEulerDToken(dToken).balanceOf(address(leverageBull)));\n        assertEq(usdcBalanceAfter.sub(IERC20(usdc).balanceOf(auction)), usdcToRepay);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/fuzz-test/ZenAuctionFuzzTest.t.sol",
    "content": "pragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IWETH9 } from \"squeeth-monorepo/interfaces/IWETH9.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IEulerMarkets } from \"../../src/interface/IEulerMarkets.sol\";\nimport { IEulerEToken } from \"../../src/interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"../../src/interface/IEulerDToken.sol\";\nimport { ISwapRouter } from \"v3-periphery/interfaces/ISwapRouter.sol\";\n// contract\nimport { TestUtil } from \"../util/TestUtil.t.sol\";\nimport { SwapRouter } from \"v3-periphery/SwapRouter.sol\";\nimport { Quoter } from \"v3-periphery/lens/Quoter.sol\";\nimport { ZenBullStrategy } from \"../../src/ZenBullStrategy.sol\";\nimport { CrabStrategyV2 } from \"squeeth-monorepo/strategy/CrabStrategyV2.sol\";\nimport { Controller } from \"squeeth-monorepo/core/Controller.sol\";\nimport { ZenAuction } from \"../../src/ZenAuction.sol\";\nimport { FlashZen } from \"../../src/FlashZen.sol\";\nimport { SigUtil } from \"../util/SigUtil.sol\";\n// lib\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\nimport { UniOracle } from \"../../src/UniOracle.sol\";\n\n/**\n * @notice fuzz testing\n */\ncontract ZenAuctionFuzzTest is Test {\n    using StrategyMath for uint256;\n\n    uint32 internal constant TWAP = 420;\n    uint128 internal constant ONE = 1e18;\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n\n    ZenBullStrategy internal bullStrategy;\n    FlashZen internal flashBull;\n    ZenAuction internal auctionBull;\n    CrabStrategyV2 internal crabV2;\n    Controller internal controller;\n    SwapRouter internal swapRouter;\n    TestUtil internal testUtil;\n    Quoter internal quoter;\n    SigUtil internal sigUtil;\n\n    uint256 internal user1Pk;\n    uint256 internal user2Pk;\n    uint256 internal ownerPk;\n    uint256 internal deployerPk;\n    uint256 internal auctionManagerPk;\n\n    address internal user1;\n    address internal user2;\n    address internal owner;\n    address internal deployer;\n    address internal auctionManager;\n\n    address internal weth;\n    address internal usdc;\n    address internal euler;\n    address internal factory;\n    address internal ethWSqueethPool;\n    address internal ethUsdcPool;\n    address internal eulerMarketsModule;\n    address internal eToken;\n    address internal dToken;\n    address internal wPowerPerp;\n\n    uint256 internal cap;\n\n    /// @dev to avoid stack too deep\n    uint256 currentWethInLeverage;\n    uint256 currentDebt;\n    uint256 targetWethInLeverage;\n    uint256 targetDebt;\n    uint256 userWethBalanceBeforeAuction;\n    uint256 userWPowerPerpBalanceBeforeAuction;\n    uint256 user2WethBalanceBeforeAuction;\n    uint256 user2WPowerPerpBalanceBeforeAuction;\n    ZenAuction.Order[] orders;\n\n    function setUp() public {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 15939557);\n        // vm.createSelectFork(FORK_URL, 15781550);\n\n        ownerPk = 0xA1CCE;\n        owner = vm.addr(ownerPk);\n        auctionManagerPk = 0xA1DCE;\n        auctionManager = vm.addr(auctionManagerPk);\n        deployerPk = 0xA11CE;\n        deployer = vm.addr(deployerPk);\n        user1Pk = 0xA11DE;\n        user1 = vm.addr(user1Pk);\n        user2Pk = 0xC11CE;\n        user2 = vm.addr(user2Pk);\n\n        vm.startPrank(deployer);\n        quoter = Quoter(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);\n        swapRouter = SwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);\n        factory = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\n        euler = 0x27182842E098f60e3D576794A5bFFb0777E025d3;\n        eulerMarketsModule = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3;\n        controller = Controller(0x64187ae08781B09368e6253F9E94951243A493D5);\n        crabV2 = CrabStrategyV2(0x3B960E47784150F5a63777201ee2B15253D713e8);\n        bullStrategy = new ZenBullStrategy(\n            address(crabV2),\n            address(controller),\n            euler,\n            eulerMarketsModule\n        );\n        bullStrategy.transferOwnership(owner);\n        flashBull = new FlashZen(address(bullStrategy), factory);\n        usdc = controller.quoteCurrency();\n        weth = controller.weth();\n        eToken = IEulerMarkets(eulerMarketsModule).underlyingToEToken(weth);\n        dToken = IEulerMarkets(eulerMarketsModule).underlyingToDToken(usdc);\n        wPowerPerp = controller.wPowerPerp();\n        ethWSqueethPool = controller.wPowerPerpPool();\n        ethUsdcPool = controller.ethQuoteCurrencyPool();\n        auctionBull = new ZenAuction(\n            auctionManager,\n            address(bullStrategy),\n            factory,\n            address(crabV2),\n            eToken,\n            dToken\n        );\n        auctionBull.transferOwnership(owner);\n        testUtil = new TestUtil(\n            address(bullStrategy),\n            address(controller),\n            eToken,\n            dToken,\n            address(crabV2)\n        );\n        sigUtil = new SigUtil(auctionBull.DOMAIN_SEPARATOR());\n        vm.stopPrank();\n\n        cap = 100000e18;\n        vm.startPrank(owner);\n        bullStrategy.setCap(cap);\n        bullStrategy.setAuction(address(auctionBull));\n        auctionBull.setCrUpperAndLower(1.8e18, 2.2e18);\n        auctionBull.setDeltaUpperAndLower(0.9e18, 1.1e18);\n        auctionBull.setFullRebalanceClearingPriceTolerance(2e17);\n        auctionBull.setRebalanceWethLimitPriceTolerance(2e17);\n        vm.stopPrank();\n\n        vm.label(user1, \"User 1\");\n        vm.label(user2, \"User 2\");\n        vm.label(address(bullStrategy), \"BullStrategy\");\n        vm.label(euler, \"Euler\");\n        vm.label(eulerMarketsModule, \"EulerMarkets\");\n        vm.label(usdc, \"USDC\");\n        vm.label(weth, \"WETH\");\n        vm.label(wPowerPerp, \"oSQTH\");\n        vm.label(address(crabV2), \"crabV2\");\n        vm.label(address(swapRouter), \"SwapRouter\");\n        vm.label(address(sigUtil), \"SigUtils\");\n\n        vm.deal(user1, 10000000e18);\n        vm.deal(user2, 10000000e18);\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 50e18);\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user2, 50e18);\n        // some WETH and USDC rich address\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(weth).transfer(user1, 5000e18);\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(weth).transfer(user2, 5000e18);\n        vm.prank(0x40ec5B33f54e0E8A33A975908C5BA1c14e5BbbDf);\n        IERC20(usdc).transfer(user1, 250000000e6);\n        vm.prank(0x40ec5B33f54e0E8A33A975908C5BA1c14e5BbbDf);\n        IERC20(usdc).transfer(user2, 250000000e6);\n        //vm.stopPrank();\n        // osQTH whale\n        vm.prank(0x35AeD16f957b39342744B8366A8c13172507D7b8);\n        IERC20(wPowerPerp).transfer(user1, 500e18);\n        vm.prank(0x35AeD16f957b39342744B8366A8c13172507D7b8);\n        IERC20(wPowerPerp).transfer(user2, 500e18);\n        // mint more oSQTH\n        vm.prank(user1);\n        controller.mintWPowerPerpAmount{ value: 100000e18 }(0, 10000e18, 0);\n        vm.prank(user2);\n        controller.mintWPowerPerpAmount{ value: 100000e18 }(0, 10000e18, 0);\n\n        _initateDepositInBull();\n    }\n\n    function testFuzzingFullRebalance(\n        uint256 sellUsdcBuyWethAmount,\n        uint256 sellWethBuyUsdcAmount,\n        uint256 sellWethBuyWPowerPerpAmount,\n        uint256 sellWPowerPerpAmountBuyWethAmount\n    ) public {\n        sellUsdcBuyWethAmount = bound(sellUsdcBuyWethAmount, 1, 5000000e6);\n        sellWethBuyUsdcAmount = bound(sellWethBuyUsdcAmount, 1, 200e18);\n        sellWethBuyWPowerPerpAmount = bound(sellWethBuyWPowerPerpAmount, 1, 200e18);\n        sellWPowerPerpAmountBuyWethAmount = bound(sellWPowerPerpAmountBuyWethAmount, 1, 200e18);\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        {\n            // All possible price moves\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), type(uint256).max);\n            IERC20(weth).approve(address(swapRouter), type(uint256).max);\n            IERC20(wPowerPerp).approve(address(swapRouter), type(uint256).max);\n            IWETH9(weth).deposit{ value: sellWethBuyWPowerPerpAmount }();\n            IWETH9(weth).deposit{ value: sellWethBuyUsdcAmount }();\n            IERC20(wPowerPerp).approve(address(auctionBull), type(uint256).max);\n\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellUsdcBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: usdc,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyUsdcAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyWPowerPerpAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: wPowerPerp,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWPowerPerpAmountBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.mul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            (targetDebt < currentDebt) ? ethUsdPrice.wmul(8e17) : ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertApproxEqRel(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)),\n            targetWethInLeverage,\n            1e16\n        );\n        if (isDepositingInCrab) {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.add(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.add(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n            assertEq(squeethInCrab.add(wPowerPerpAmountToTrade), squeethInCrabAfter);\n        } else {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.sub(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.add(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.sub(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n        }\n    }\n\n    // Helper functions\n    function _getCrabVaultDetails() internal view returns (uint256, uint256) {\n        VaultLib.Vault memory strategyVault =\n            IController(address(controller)).vaults(crabV2.vaultId());\n\n        return (strategyVault.collateralAmount, strategyVault.shortAmount);\n    }\n\n    function calcTotalEthToBull(\n        uint256 wethToLend,\n        uint256 ethToCrab,\n        uint256 usdcToBorrow,\n        uint256 wSqueethToMint\n    ) internal view returns (uint256) {\n        uint256 totalEthToBull = wethToLend.add(ethToCrab).sub(usdcToBorrow.wdiv(ethPrice())).sub(\n            wSqueethToMint.wmul(squeethPrice())\n        ).add(1e16);\n        return totalEthToBull;\n    }\n\n    /**\n     * @dev calculate amount of strategy token to mint for depositor\n     * @param _amount amount of ETH deposited\n     * @param _strategyCollateralAmount amount of strategy collateral\n     * @param _crabTotalSupply total supply of strategy token\n     * @return amount of strategy token to mint\n     */\n    function _calcSharesToMint(\n        uint256 _amount,\n        uint256 _strategyCollateralAmount,\n        uint256 _crabTotalSupply\n    ) internal pure returns (uint256) {\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\n\n        if (_crabTotalSupply != 0) {\n            return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\n        }\n\n        return _amount;\n    }\n\n    function _calcWsqueethToMintAndFee(\n        uint256 _depositedAmount,\n        uint256 _strategyDebtAmount,\n        uint256 _strategyCollateralAmount\n    ) internal view returns (uint256, uint256) {\n        uint256 wSqueethToMint;\n        uint256 wSqueethEthPrice = squeethPrice();\n        uint256 feeRate = IController(bullStrategy.powerTokenController()).feeRate();\n        uint256 feeAdjustment = wSqueethEthPrice.mul(feeRate).div(10000);\n\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\n        );\n\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\n\n        return (wSqueethToMint, fee);\n    }\n\n    function squeethPrice() internal view returns (uint256) {\n        return UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n    }\n\n    function ethPrice() internal view returns (uint256) {\n        return UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n    }\n\n    function _initateDepositInBull() internal {\n        // Put some money in bull to start with\n        uint256 ethToCrab = 5e18;\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        (uint256 wSqueethToMint, uint256 fee) =\n            _calcWsqueethToMintAndFee(ethToCrab, squeethInCrab, ethInCrab);\n        uint256 crabToBeMinted =\n            _calcSharesToMint(ethToCrab.sub(fee), ethInCrab, IERC20(crabV2).totalSupply());\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        uint256 bullShare = 1e18;\n        (uint256 wethToLend, uint256 usdcToBorrow) = bullStrategy.calcLeverageEthUsdc(\n            crabToBeMinted, bullShare, ethInCrab, squeethInCrab, crabV2.totalSupply()\n        );\n\n        uint256 totalEthToBull =\n            calcTotalEthToBull(wethToLend, ethToCrab, usdcToBorrow, wSqueethToMint);\n\n        FlashZen.FlashDepositParams memory params = FlashZen.FlashDepositParams({\n            ethToCrab: ethToCrab,\n            minEthFromSqth: 0,\n            minEthFromUsdc: 0,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(user1);\n        flashBull.flashDeposit{ value: totalEthToBull }(params);\n        vm.stopPrank();\n\n        assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n        assertApproxEqAbs(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), wethToLend, 1\n        );\n        assertEq(bullStrategy.getCrabBalance().sub(crabToBeMinted), bullCrabBalanceBefore);\n    }\n\n    function _calcTargetCollateralAndDebtInLeverage() internal view returns (uint256, uint256) {\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            1,\n            false\n        );\n\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 crabUsdPrice = (\n            ethInCrab.wmul(ethUsdPrice).sub(squeethInCrab.wmul(squeethEthPrice).wmul(ethUsdPrice))\n        ).wdiv(crabV2.totalSupply());\n        uint256 equityValue = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)).wmul(\n            ethUsdPrice\n        ).add(IERC20(crabV2).balanceOf(address(bullStrategy)).wmul(crabUsdPrice)).sub(\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)).mul(1e12)\n        );\n        uint256 targetCollateral = equityValue.wdiv(ethUsdPrice);\n        uint256 _targetDebt =\n            targetCollateral.wmul(ethUsdPrice).wdiv(bullStrategy.TARGET_CR()).div(1e12);\n        return (targetCollateral, _targetDebt);\n    }\n\n    function _calcCrabAmountToTrade(\n        uint256 _currentWethInLeverage,\n        uint256 _currentDebt,\n        uint256 _targetWeth,\n        uint256 _targetDebt,\n        uint256 _ethUsdPrice\n    ) internal view returns (uint256, bool) {\n        (uint256 wethDeltaInDollar, bool isWethDeltaInDollarPositive) = (\n            _targetWeth > _currentWethInLeverage\n        )\n            ? (_targetWeth.sub(_currentWethInLeverage).wmul(_ethUsdPrice), false)\n            : (_currentWethInLeverage.sub(_targetWeth).wmul(_ethUsdPrice), true);\n        (uint256 debtDeltaInDollar, bool isDebtDeltaInDollarPositive) = (_targetDebt > _currentDebt)\n            ? (_targetDebt.sub(_currentDebt), false)\n            : (_currentDebt.sub(_targetDebt), true);\n        wethDeltaInDollar = wethDeltaInDollar.div(1e12);\n        bool isDepositingInCrab;\n        uint256 dollarToExchangeWithCrab;\n\n        if (isDebtDeltaInDollarPositive) {\n            if (isWethDeltaInDollarPositive) {\n                (dollarToExchangeWithCrab, isDepositingInCrab) = (\n                    debtDeltaInDollar > wethDeltaInDollar\n                )\n                    ? (debtDeltaInDollar.sub(wethDeltaInDollar), false)\n                    : (wethDeltaInDollar.sub(debtDeltaInDollar), true);\n            } else {\n                (dollarToExchangeWithCrab, isDepositingInCrab) =\n                    (debtDeltaInDollar.add(wethDeltaInDollar), false);\n            }\n        } else {\n            if (!isWethDeltaInDollarPositive) {\n                (dollarToExchangeWithCrab, isDepositingInCrab) = (\n                    debtDeltaInDollar > wethDeltaInDollar\n                )\n                    ? (debtDeltaInDollar.sub(wethDeltaInDollar), true)\n                    : (wethDeltaInDollar.sub(debtDeltaInDollar), false);\n            } else {\n                (dollarToExchangeWithCrab, isDepositingInCrab) =\n                    (debtDeltaInDollar.add(wethDeltaInDollar), true);\n            }\n        }\n        uint256 crabAmount = dollarToExchangeWithCrab.mul(1e12).wdiv(testUtil.getCrabPrice());\n\n        return (crabAmount, isDepositingInCrab);\n    }\n\n    function _calcWPowerPerpAmountFromCrab(\n        bool _isDepositingInCrab,\n        uint256 _crabAmount,\n        uint256 _ethInCrab,\n        uint256 _squeethInCrab\n    ) internal view returns (uint256) {\n        uint256 wPowerPerpAmount;\n        if (_isDepositingInCrab) {\n            uint256 ethToDepositInCrab =\n                _crabAmount.wdiv(IERC20(crabV2).totalSupply()).wmul(_ethInCrab);\n            (wPowerPerpAmount,) =\n                _calcWsqueethToMintAndFee(ethToDepositInCrab, _squeethInCrab, _ethInCrab);\n        } else {\n            wPowerPerpAmount = _crabAmount.wmul(_squeethInCrab).wdiv(IERC20(crabV2).totalSupply());\n        }\n\n        return wPowerPerpAmount;\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/fuzz-test/ZenBullStrategyFuzzTest.t.sol",
    "content": "pragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IEulerMarkets } from \"../../src/interface/IEulerMarkets.sol\";\nimport { IEulerEToken } from \"../../src/interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"../../src/interface/IEulerDToken.sol\";\n// contract\nimport { TestUtil } from \"../util/TestUtil.t.sol\";\nimport { ZenBullStrategy } from \"../../src/ZenBullStrategy.sol\";\nimport { CrabStrategyV2 } from \"squeeth-monorepo/strategy/CrabStrategyV2.sol\";\nimport { Controller } from \"squeeth-monorepo/core/Controller.sol\";\n// lib\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\nimport { UniOracle } from \"../../src/UniOracle.sol\";\n\n/**\n * @notice fuzz testing\n */\ncontract ZenBullStrategyFuzzTest is Test {\n    using StrategyMath for uint256;\n\n    TestUtil internal testUtil;\n    ZenBullStrategy internal bullStrategy;\n    CrabStrategyV2 internal crabV2;\n    Controller internal controller;\n\n    uint256 internal bullOwnerPk;\n    uint256 internal deployerPk;\n    uint256 internal user1Pk;\n    uint256 internal ownerPk;\n    address internal user1;\n    address internal owner;\n    address internal weth;\n    address internal usdc;\n    address internal euler;\n    address internal eulerMarketsModule;\n    address internal eToken;\n    address internal dToken;\n    address internal wPowerPerp;\n    address internal deployer;\n    address internal bullOwner;\n\n    uint256 internal cap;\n\n    function setUp() public {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 15781550);\n\n        deployerPk = 0xA11CD;\n        deployer = vm.addr(deployerPk);\n        bullOwnerPk = 0xB11CD;\n        bullOwner = vm.addr(bullOwnerPk);\n\n        vm.startPrank(deployer);\n        euler = 0x27182842E098f60e3D576794A5bFFb0777E025d3;\n        eulerMarketsModule = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3;\n        controller = Controller(0x64187ae08781B09368e6253F9E94951243A493D5);\n        crabV2 = CrabStrategyV2(0x3B960E47784150F5a63777201ee2B15253D713e8);\n        bullStrategy =\n            new ZenBullStrategy(address(crabV2), address(controller), euler, eulerMarketsModule);\n        bullStrategy.transferOwnership(bullOwner);\n        usdc = controller.quoteCurrency();\n        weth = controller.weth();\n        eToken = IEulerMarkets(eulerMarketsModule).underlyingToEToken(weth);\n        dToken = IEulerMarkets(eulerMarketsModule).underlyingToDToken(usdc);\n        wPowerPerp = controller.wPowerPerp();\n        testUtil =\n        new TestUtil(address(bullStrategy), address (controller), eToken, dToken, address(crabV2));\n        vm.stopPrank();\n\n        cap = 100000e18;\n        vm.prank(bullOwner);\n        bullStrategy.setCap(cap);\n\n        user1Pk = 0xA11CE;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User 1\");\n        vm.label(address(bullStrategy), \"BullStrategy\");\n        vm.label(euler, \"Euler\");\n        vm.label(eulerMarketsModule, \"EulerMarkets\");\n        vm.label(usdc, \"USDC\");\n        vm.label(weth, \"WETH\");\n        vm.label(wPowerPerp, \"oSQTH\");\n        vm.label(address(crabV2), \"crabV2\");\n\n        vm.deal(user1, 100000000e18);\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 100e18);\n        // some WETH and USDC rich address\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(weth).transfer(user1, 10000e18);\n    }\n\n    function testFuzzingDeposit(uint256 _crabAmount) public {\n        _crabAmount = bound(_crabAmount, 1.1e14, IERC20(crabV2).balanceOf(user1));\n\n        uint256 bullToMint = testUtil.calcBullToMint(_crabAmount);\n        (uint256 wethToLend, uint256 usdcToBorrow) =\n            testUtil.calcCollateralAndBorrowAmount(_crabAmount);\n        uint256 userBullBalanceBefore = bullStrategy.balanceOf(user1);\n        uint256 ethInLendingBefore = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        uint256 usdcBorrowedBefore = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        uint256 userUsdcBalanceBefore = IERC20(usdc).balanceOf(user1);\n\n        vm.startPrank(user1);\n        IERC20(crabV2).approve(address(bullStrategy), _crabAmount);\n        bullStrategy.deposit{ value: wethToLend }(_crabAmount);\n        vm.stopPrank();\n\n        assertEq(bullStrategy.balanceOf(user1).sub(userBullBalanceBefore), bullToMint);\n        assertTrue(\n            wethToLend.sub(\n                IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)).sub(\n                    ethInLendingBefore\n                )\n            ) <= 2\n        );\n        assertEq(\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcBorrowedBefore),\n            usdcToBorrow\n        );\n        assertEq(IERC20(usdc).balanceOf(user1).sub(userUsdcBalanceBefore), usdcToBorrow);\n        assertTrue(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy))\n                <= bullStrategy.strategyCap()\n        );\n    }\n\n    function testFuzzingWithdraw(uint256 _crabAmount) public {\n        // use bound() instead of vm.assume for better performance in fuzzing\n        _crabAmount = bound(_crabAmount, 1.1e14, IERC20(crabV2).balanceOf(user1));\n\n        uint256 bullToMint = testUtil.calcBullToMint(_crabAmount);\n        (uint256 wethToLend,) = testUtil.calcCollateralAndBorrowAmount(_crabAmount);\n        vm.startPrank(user1);\n        IERC20(crabV2).approve(address(bullStrategy), _crabAmount);\n        bullStrategy.deposit{ value: wethToLend }(_crabAmount);\n        vm.stopPrank();\n\n        (uint256 wPowerPerpToRedeem, uint256 crabToRedeem) =\n            _calcWPowerPerpAndCrabNeededForWithdraw(bullToMint);\n        uint256 usdcToRepay = _calcUsdcNeededForWithdraw(bullToMint);\n        uint256 wethToWithdraw = testUtil.calcWethToWithdraw(bullToMint);\n        // transfer some oSQTH from some squeether\n        vm.prank(0x56178a0d5F301bAf6CF3e1Cd53d9863437345Bf9);\n        IERC20(wPowerPerp).transfer(user1, wPowerPerpToRedeem);\n\n        uint256 userBullBalanceBefore = bullStrategy.balanceOf(user1);\n        uint256 ethInLendingBefore = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        uint256 usdcBorrowedBefore = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        uint256 userUsdcBalanceBefore = IERC20(usdc).balanceOf(user1);\n        uint256 userWPowerPerpBalanceBefore = IERC20(wPowerPerp).balanceOf(user1);\n        uint256 crabBalanceBefore = crabV2.balanceOf(address(bullStrategy));\n\n        vm.startPrank(user1);\n        IERC20(usdc).approve(address(bullStrategy), usdcToRepay);\n        IERC20(wPowerPerp).approve(address(bullStrategy), wPowerPerpToRedeem);\n        bullStrategy.withdraw(bullToMint);\n        vm.stopPrank();\n\n        assertEq(\n            usdcBorrowedBefore.sub(usdcToRepay),\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)),\n            \"Bull USDC debt amount mismatch\"\n        );\n        assertEq(\n            ethInLendingBefore.sub(wethToWithdraw),\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)),\n            \"Bull ETH in leverage amount mismatch\"\n        );\n        assertEq(\n            userUsdcBalanceBefore.sub(usdcToRepay),\n            IERC20(usdc).balanceOf(user1),\n            \"User1 USDC balance mismatch\"\n        );\n        assertEq(\n            userBullBalanceBefore.sub(bullToMint),\n            bullStrategy.balanceOf(user1),\n            \"User1 bull balance mismatch\"\n        );\n        assertEq(\n            userWPowerPerpBalanceBefore.sub(wPowerPerpToRedeem),\n            IERC20(wPowerPerp).balanceOf(user1),\n            \"User1 oSQTH balance mismatch\"\n        );\n        assertEq(\n            crabBalanceBefore.sub(crabToRedeem),\n            crabV2.balanceOf(address(bullStrategy)),\n            \"Bull ccrab balance mismatch\"\n        );\n    }\n\n    /**\n     *\n     * /************************************************************* Helper functions for testing! ********************************************************\n     */\n    function _calcWPowerPerpAndCrabNeededForWithdraw(uint256 _bullAmount)\n        internal\n        view\n        returns (uint256, uint256)\n    {\n        uint256 share = _bullAmount.wdiv(bullStrategy.totalSupply());\n        uint256 crabToRedeem = share.wmul(bullStrategy.getCrabBalance());\n        uint256 crabTotalSupply = IERC20(crabV2).totalSupply();\n        (, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        return (crabToRedeem.wmul(squeethInCrab).wdiv(crabTotalSupply), crabToRedeem);\n    }\n\n    function _calcUsdcNeededForWithdraw(uint256 _bullAmount) internal view returns (uint256) {\n        uint256 share = _bullAmount.wdiv(bullStrategy.totalSupply());\n        return share.wmul(IEulerDToken(dToken).balanceOf(address(bullStrategy)));\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/integration-test/EmergencyWithdraw/EmergencyRepayEulerDebtTest.t.sol",
    "content": "pragma solidity =0.7.6;\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IEulerEToken } from \"../../../src/interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"../../../src/interface/IEulerDToken.sol\";\nimport { Quoter } from \"v3-periphery/lens/Quoter.sol\";\nimport { EmergencyWithdraw } from \"../../../src/EmergencyWithdraw.sol\";\nimport { ZenBullStrategy } from \"../../../src/ZenBullStrategy.sol\";\nimport { UniOracle } from \"../../../src/UniOracle.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\n\ncontract EmergencyRepayEulerDebtTest is Test {\n    using StrategyMath for uint256;\n\n    uint256 internal constant ONE = 1e18;\n\n    address payable public constant ZEN_BULL = 0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507;\n    address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n    address public constant CRAB = 0x3B960E47784150F5a63777201ee2B15253D713e8;\n    address public constant UNI_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\n    address public constant WPOWERPERP = 0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B;\n    address public constant QUOTER = 0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6;\n    address public constant ETH_USDC_POOL = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640;\n    address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n    address public constant E_TOKEN = 0x1b808F49ADD4b8C6b5117d9681cF7312Fcf0dC1D;\n    address public constant D_TOKEN = 0x84721A3dB22EB852233AEAE74f9bC8477F8bcc42;\n\n    uint256 deployerPk;\n    uint256 user1Pk;\n    uint256 user2Pk;\n    address deployer;\n    address user1;\n    address user2;\n\n    EmergencyWithdraw internal emergencyWithdraw;\n\n    function setUp() public virtual {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 16816896);\n\n        deployerPk = 0xA11CD;\n        deployer = vm.addr(deployerPk);\n        user1Pk = 0xB21CD;\n        user1 = vm.addr(user1Pk);\n        user2Pk = 0xB22CD;\n        user2 = vm.addr(user2Pk);\n\n        vm.startPrank(deployer);\n        emergencyWithdraw =\n        new EmergencyWithdraw(CRAB, ZEN_BULL, WETH, USDC, WPOWERPERP, ETH_USDC_POOL, E_TOKEN, D_TOKEN, UNI_FACTORY);\n        vm.stopPrank();\n\n        // prank ZenBull owner to point to a new auction contract address\n        vm.prank(0xAfE66363c27EedB597a140c28B70b32F113fd5a8);\n        ZenBullStrategy(ZEN_BULL).setAuction(address(emergencyWithdraw));\n\n        // bull whale gives some to user1\n        vm.startPrank(0xB845d3C82853b362ADF47A045c087d52384a7776);\n        IERC20(ZEN_BULL).transfer(\n            user1, IERC20(ZEN_BULL).balanceOf(0xB845d3C82853b362ADF47A045c087d52384a7776) / 2\n        );\n        vm.stopPrank();\n\n        vm.label(deployer, \"Deployer\");\n        vm.label(user1, \"user1\");\n        vm.label(address(emergencyWithdraw), \"EmergencyWithdraw\");\n    }\n\n    function testEmergencyRepayEulerDebt() public {\n        uint256 ethLimitPrice =\n            UniOracle._getTwap(ETH_USDC_POOL, WETH, USDC, 420, false).wmul((ONE.sub(2e15)));\n        uint256 emergencyContractEthBalanceBefore = address(emergencyWithdraw).balance;\n        uint256 zenBullDebtBefore = IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL);\n        uint256 zenBullCollateralBefore = IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL);\n        uint256 ratio = 2e17;\n        uint256 wethToWithdraw = ratio.wmul(IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL));\n        uint256 usdcToRepay = ratio.wmul(IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL));\n        uint256 ethToRepayForFlashswap =\n            Quoter(QUOTER).quoteExactOutputSingle(WETH, USDC, 500, usdcToRepay, 0);\n\n        vm.startPrank(user1);\n        emergencyWithdraw.emergencyRepayEulerDebt(ratio, ethLimitPrice, 500);\n        vm.stopPrank();\n\n        uint256 emergencyContractEthBalanceAfter = address(emergencyWithdraw).balance;\n        uint256 zenBullDebtAfter = IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL);\n        uint256 zenBullCollateralAfter = IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL);\n\n        assertEq(zenBullDebtBefore.sub(usdcToRepay), zenBullDebtAfter);\n        assertApproxEqRel(zenBullCollateralBefore.sub(wethToWithdraw), zenBullCollateralAfter, 1);\n        assertEq(\n            emergencyContractEthBalanceBefore.add(wethToWithdraw.sub(ethToRepayForFlashswap)),\n            emergencyContractEthBalanceAfter\n        );\n    }\n\n    function testMultipleEmergencyRepayEulerDebt() public {\n        uint256 totalEthInContract;\n\n        uint256 ratio = 1e17;\n        while (IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL) > 0) {\n            if (ratio > 1e18) ratio = 1e18;\n\n            uint256 ethLimitPrice =\n                UniOracle._getTwap(ETH_USDC_POOL, WETH, USDC, 420, false).wmul((ONE.sub(2e15)));\n            uint256 emergencyContractEthBalanceBefore = address(emergencyWithdraw).balance;\n            uint256 zenBullDebtBefore = IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL);\n            uint256 zenBullCollateralBefore = IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL);\n            uint256 wethToWithdraw = ratio.wmul(IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL));\n            if (wethToWithdraw > emergencyWithdraw.MAX_WETH_PER_DEBT_REPAY()) {\n                ratio = ratio / 2;\n                wethToWithdraw = ratio.wmul(IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL));\n            }\n            uint256 usdcToRepay = ratio.wmul(IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL));\n            // console.log(\"usdcToRepay\", usdcToRepay);\n            uint256 ethToRepayForFlashswap =\n                Quoter(QUOTER).quoteExactOutputSingle(WETH, USDC, 500, usdcToRepay, 0);\n            totalEthInContract = totalEthInContract.add(wethToWithdraw.sub(ethToRepayForFlashswap));\n\n            vm.startPrank(user1);\n            emergencyWithdraw.emergencyRepayEulerDebt(ratio, ethLimitPrice, 500);\n            vm.stopPrank();\n\n            uint256 emergencyContractEthBalanceAfter = address(emergencyWithdraw).balance;\n            uint256 zenBullDebtAfter = IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL);\n            uint256 zenBullCollateralAfter = IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL);\n\n            assertEq(zenBullDebtBefore.sub(usdcToRepay), zenBullDebtAfter);\n            assertApproxEqRel(\n                zenBullCollateralBefore.sub(wethToWithdraw), zenBullCollateralAfter, 1000000000\n            );\n            assertEq(\n                emergencyContractEthBalanceBefore.add(wethToWithdraw.sub(ethToRepayForFlashswap)),\n                emergencyContractEthBalanceAfter\n            );\n\n            ratio = ratio.mul(2);\n            skip(420);\n        }\n\n        assertEq(IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL), 0);\n        assertEq(IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL), 0);\n        assertEq(address(emergencyWithdraw).balance, totalEthInContract);\n    }\n\n    function testEmergencyRepayEulerDebtWhenAmountInGreaterThanMax() public {\n        uint256 ethLimitPrice =\n            UniOracle._getTwap(ETH_USDC_POOL, WETH, USDC, 420, false).wmul((ONE.add(1e16)));\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"amount in greater than max\"));\n        emergencyWithdraw.emergencyRepayEulerDebt(2e17, ethLimitPrice, 500);\n        vm.stopPrank();\n    }\n\n    function testEmergencyRepayEulerDebtWhenWethToWithdrawGreaterThanMax() public {\n        uint256 ethLimitPrice =\n            (Quoter(QUOTER).quoteExactOutputSingle(USDC, WETH, 500, 1e18, 0)).wmul((ONE.add(1e16)));\n\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"WETH to withdraw is greater than max per repay\"));\n        emergencyWithdraw.emergencyRepayEulerDebt(1e18, ethLimitPrice, 500);\n        vm.stopPrank();\n    }\n\n    function testMultipleEmergencyRepayEulerDebtAndWithdraw() public {\n        // User 1 redeems some crab from emergencyWithdrawEthFromCrab\n        uint256 redeemedZenBullAmountForCrabWithdrawalBefore =\n            emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n        uint256 user1BullBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 user1EthBalanceBefore = address(user1).balance;\n        uint256 user1RecoveryTokenBalanceBefore = IERC20(emergencyWithdraw).balanceOf(user1);\n\n        uint256 maxWethForOsqth;\n        uint256 ethToWithdrawFromCrab;\n        {\n            uint256 bullShare = user1BullBalanceBefore.wdiv(\n                IERC20(ZEN_BULL).totalSupply().sub(redeemedZenBullAmountForCrabWithdrawalBefore)\n            );\n            uint256 crabToRedeem = bullShare.wmul(ZenBullStrategy(ZEN_BULL).getCrabBalance());\n            (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n                ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n            uint256 wPowerPerpToRedeem =\n                crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(CRAB).totalSupply());\n\n            maxWethForOsqth =\n                Quoter(QUOTER).quoteExactOutputSingle(WETH, WPOWERPERP, 3000, wPowerPerpToRedeem, 0);\n            ethToWithdrawFromCrab = crabToRedeem.wdiv(IERC20(CRAB).totalSupply()).wmul(ethInCrab);\n        }\n\n        vm.startPrank(user1);\n        IERC20(ZEN_BULL).approve(address(emergencyWithdraw), type(uint256).max);\n        emergencyWithdraw.emergencyWithdrawEthFromCrab(user1BullBalanceBefore, maxWethForOsqth);\n        vm.stopPrank();\n\n        uint256 redeemedZenBullAmountForCrabWithdrawalAfter =\n            emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n        uint256 user1BullBalanceAfter = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 user1EthBalanceAfter = address(user1).balance;\n        uint256 user1RecoveryTokenBalanceAfter = IERC20(emergencyWithdraw).balanceOf(user1);\n\n        uint256 totalEthInContract;\n        uint256 ratio = 1e17;\n        // Reduce Bull's Euler balances to zero by paying down debt with emergencyRepayEulerDebt\n        while (IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL) > 0) {\n            if (ratio > 1e18) ratio = 1e18;\n\n            uint256 ethLimitPrice =\n                UniOracle._getTwap(ETH_USDC_POOL, WETH, USDC, 420, false).wmul((ONE.sub(2e15)));\n            uint256 emergencyContractEthBalanceBefore = address(emergencyWithdraw).balance;\n            uint256 zenBullDebtBefore = IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL);\n            uint256 zenBullCollateralBefore = IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL);\n            uint256 wethToWithdraw = ratio.wmul(IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL));\n            if (wethToWithdraw > emergencyWithdraw.MAX_WETH_PER_DEBT_REPAY()) {\n                ratio = ratio / 2;\n                wethToWithdraw = ratio.wmul(IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL));\n            }\n            uint256 usdcToRepay = ratio.wmul(IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL));\n            uint256 ethToRepayForFlashswap =\n                Quoter(QUOTER).quoteExactOutputSingle(WETH, USDC, 500, usdcToRepay, 0);\n            totalEthInContract = totalEthInContract.add(wethToWithdraw.sub(ethToRepayForFlashswap));\n\n            vm.startPrank(user1);\n            emergencyWithdraw.emergencyRepayEulerDebt(ratio, ethLimitPrice, 500);\n            vm.stopPrank();\n\n            uint256 emergencyContractEthBalanceAfter = address(emergencyWithdraw).balance;\n            uint256 zenBullDebtAfter = IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL);\n            uint256 zenBullCollateralAfter = IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL);\n\n            assertEq(zenBullDebtBefore.sub(usdcToRepay), zenBullDebtAfter);\n            assertApproxEqRel(\n                zenBullCollateralBefore.sub(wethToWithdraw), zenBullCollateralAfter, 1000000000\n            );\n            assertEq(\n                emergencyContractEthBalanceBefore.add(wethToWithdraw.sub(ethToRepayForFlashswap)),\n                emergencyContractEthBalanceAfter\n            );\n\n            ratio = ratio.mul(2);\n            skip(420);\n        }\n\n        assertEq(IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL), 0);\n        assertEq(IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL), 0);\n        assertEq(address(emergencyWithdraw).balance, totalEthInContract);\n\n        // User 1 withdraws ETH now that all Euler balances are zero\n        uint256 zenBullTotalSupplyForEulerWithdrawalBefore =\n            emergencyWithdraw.redeemedRecoveryAmountForEulerWithdrawal();\n        uint256 user1RecoveryTokenBalanceBefore_ = emergencyWithdraw.balanceOf(user1);\n        uint256 emergencyWithdrawEthBalanceBefore = address(emergencyWithdraw).balance;\n        vm.startPrank(user1);\n        uint256 user1BalanceBefore = address(user1).balance;\n        emergencyWithdraw.withdrawEth(emergencyWithdraw.balanceOf(user1));\n        uint256 user1BalanceAfter = address(user1).balance;\n        vm.stopPrank();\n        assertEq(\n            user1BalanceAfter.sub(user1BalanceBefore),\n            user1RecoveryTokenBalanceBefore_.wmul(emergencyWithdrawEthBalanceBefore).wdiv(\n                IERC20(ZEN_BULL).totalSupply().sub(zenBullTotalSupplyForEulerWithdrawalBefore)\n            )\n        );\n        assertEq(emergencyWithdraw.balanceOf(user1), 0);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/integration-test/EmergencyWithdraw/EmergencyWithdrawEthFromCrabTest.t.sol",
    "content": "pragma solidity =0.7.6;\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { Quoter } from \"v3-periphery/lens/Quoter.sol\";\nimport { EmergencyWithdraw } from \"../../../src/EmergencyWithdraw.sol\";\nimport { ZenBullStrategy } from \"../../../src/ZenBullStrategy.sol\";\nimport { UniOracle } from \"../../../src/UniOracle.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\n\ncontract EmergencyWithdrawEthFromCrabTest is Test {\n    using StrategyMath for uint256;\n\n    address payable public constant ZEN_BULL = 0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507;\n    address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n    address public constant CRAB = 0x3B960E47784150F5a63777201ee2B15253D713e8;\n    address public constant UNI_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\n    address public constant WPOWERPERP = 0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B;\n    address public constant QUOTER = 0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6;\n    address public constant ETH_USDC_POOL = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640;\n    address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n    address public constant E_TOKEN = 0x1b808F49ADD4b8C6b5117d9681cF7312Fcf0dC1D;\n    address public constant D_TOKEN = 0x84721A3dB22EB852233AEAE74f9bC8477F8bcc42;\n\n    uint256 deployerPk;\n    uint256 user1Pk;\n    uint256 user2Pk;\n    address deployer;\n    address user1;\n    address user2;\n\n    EmergencyWithdraw internal emergencyWithdraw;\n\n    function setUp() public virtual {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 16838439);\n\n        deployerPk = 0xA11CD;\n        deployer = vm.addr(deployerPk);\n        user1Pk = 0xB21CD;\n        user1 = vm.addr(user1Pk);\n        user2Pk = 0xB22CD;\n        user2 = vm.addr(user2Pk);\n\n        vm.startPrank(deployer);\n        emergencyWithdraw =\n        new EmergencyWithdraw(CRAB, ZEN_BULL, WETH, USDC, WPOWERPERP, ETH_USDC_POOL, E_TOKEN, D_TOKEN, UNI_FACTORY);\n        vm.stopPrank();\n\n        // prank ZenBull owner to point to a new auction contract address\n        vm.prank(0xAfE66363c27EedB597a140c28B70b32F113fd5a8);\n        ZenBullStrategy(ZEN_BULL).setAuction(address(emergencyWithdraw));\n\n        vm.label(deployer, \"Deployer\");\n        vm.label(user1, \"user1\");\n        vm.label(address(emergencyWithdraw), \"EmergencyWithdraw\");\n\n        // bull whale\n        vm.startPrank(0xB845d3C82853b362ADF47A045c087d52384a7776);\n        IERC20(ZEN_BULL).transfer(\n            user1, IERC20(ZEN_BULL).balanceOf(0xB845d3C82853b362ADF47A045c087d52384a7776) / 2\n        );\n        IERC20(ZEN_BULL).transfer(\n            user2, IERC20(ZEN_BULL).balanceOf(0xB845d3C82853b362ADF47A045c087d52384a7776) / 2\n        );\n        vm.stopPrank();\n    }\n\n    function testSetup() public {\n        assertEq(emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal(), 0);\n    }\n\n    function testEmergencyWithdrawEthFromCrab() public {\n        uint256 emergencyRedeemedBull = emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n        uint256 user1BullBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 user1EthBalanceBefore = address(user1).balance;\n        uint256 user1RecoveryTokenBalanceBefore = IERC20(emergencyWithdraw).balanceOf(user1);\n\n        uint256 maxWethForOsqth;\n        uint256 ethToWithdrawFromCrab;\n        {\n            uint256 bullShare = user1BullBalanceBefore.wdiv(\n                IERC20(ZEN_BULL).totalSupply().sub(emergencyRedeemedBull)\n            );\n            uint256 crabToRedeem = bullShare.wmul(ZenBullStrategy(ZEN_BULL).getCrabBalance());\n            (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n                ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n            uint256 wPowerPerpToRedeem =\n                crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(CRAB).totalSupply());\n\n            maxWethForOsqth =\n                Quoter(QUOTER).quoteExactOutputSingle(WETH, WPOWERPERP, 3000, wPowerPerpToRedeem, 0);\n            ethToWithdrawFromCrab = crabToRedeem.wdiv(IERC20(CRAB).totalSupply()).wmul(ethInCrab);\n        }\n\n        vm.startPrank(user1);\n        IERC20(ZEN_BULL).approve(address(emergencyWithdraw), type(uint256).max);\n        emergencyWithdraw.emergencyWithdrawEthFromCrab(user1BullBalanceBefore, maxWethForOsqth);\n        vm.stopPrank();\n\n        uint256 bullSupplyAfter = emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n        uint256 user1BullBalanceAfter = IERC20(ZEN_BULL).balanceOf(user1);\n        uint256 user1EthBalanceAfter = address(user1).balance;\n        uint256 user1RecoveryTokenBalanceAfter = IERC20(emergencyWithdraw).balanceOf(user1);\n\n        assertEq(bullSupplyAfter, emergencyRedeemedBull.add(user1BullBalanceBefore));\n        assertEq(user1BullBalanceAfter, 0);\n        assertEq(\n            user1RecoveryTokenBalanceAfter - user1RecoveryTokenBalanceBefore, user1BullBalanceBefore\n        );\n        assertEq(\n            ethToWithdrawFromCrab.sub(maxWethForOsqth),\n            user1EthBalanceAfter.sub(user1EthBalanceBefore)\n        );\n    }\n\n    function testMultipleEmergencyWithdrawEthFromCrab() public {\n        {\n            uint256 emergencyRedeemedBull =\n                emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n            uint256 user1BullBalanceBefore = IERC20(ZEN_BULL).balanceOf(user1);\n            uint256 user1EthBalanceBefore = address(user1).balance;\n            uint256 user1RecoveryTokenBalanceBefore = IERC20(emergencyWithdraw).balanceOf(user1);\n\n            uint256 maxWethForOsqth;\n            uint256 ethToWithdrawFromCrab;\n            {\n                uint256 bullShare = user1BullBalanceBefore.wdiv(\n                    IERC20(ZEN_BULL).totalSupply().sub(emergencyRedeemedBull)\n                );\n                uint256 crabToRedeem = bullShare.wmul(ZenBullStrategy(ZEN_BULL).getCrabBalance());\n                (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n                    ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n                uint256 wPowerPerpToRedeem =\n                    crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(CRAB).totalSupply());\n\n                maxWethForOsqth = Quoter(QUOTER).quoteExactOutputSingle(\n                    WETH, WPOWERPERP, 3000, wPowerPerpToRedeem, 0\n                );\n                ethToWithdrawFromCrab =\n                    crabToRedeem.wdiv(IERC20(CRAB).totalSupply()).wmul(ethInCrab);\n            }\n\n            vm.startPrank(user1);\n            IERC20(ZEN_BULL).approve(address(emergencyWithdraw), type(uint256).max);\n            emergencyWithdraw.emergencyWithdrawEthFromCrab(user1BullBalanceBefore, maxWethForOsqth);\n            vm.stopPrank();\n\n            uint256 bullSupplyAfter = emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n            uint256 user1BullBalanceAfter = IERC20(ZEN_BULL).balanceOf(user1);\n            uint256 user1EthBalanceAfter = address(user1).balance;\n            uint256 user1RecoveryTokenBalanceAfter = IERC20(emergencyWithdraw).balanceOf(user1);\n\n            assertEq(bullSupplyAfter, emergencyRedeemedBull.add(user1BullBalanceBefore));\n            assertEq(user1BullBalanceAfter, 0);\n            assertEq(\n                user1RecoveryTokenBalanceAfter - user1RecoveryTokenBalanceBefore,\n                user1BullBalanceBefore\n            );\n            assertEq(\n                ethToWithdrawFromCrab.sub(maxWethForOsqth),\n                user1EthBalanceAfter.sub(user1EthBalanceBefore)\n            );\n        }\n\n        uint256 emergencyRedeemedBull = emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n        uint256 user2BullBalanceBefore = IERC20(ZEN_BULL).balanceOf(user2);\n        uint256 user2EthBalanceBefore = address(user2).balance;\n        uint256 user2RecoveryTokenBalanceBefore = IERC20(emergencyWithdraw).balanceOf(user2);\n\n        uint256 maxWethForOsqth;\n        uint256 ethToWithdrawFromCrab;\n        {\n            uint256 bullShare = user2BullBalanceBefore.wdiv(\n                IERC20(ZEN_BULL).totalSupply().sub(emergencyRedeemedBull)\n            );\n            uint256 crabToRedeem = bullShare.wmul(ZenBullStrategy(ZEN_BULL).getCrabBalance());\n            (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n                ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n            uint256 wPowerPerpToRedeem =\n                crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(CRAB).totalSupply());\n\n            maxWethForOsqth =\n                Quoter(QUOTER).quoteExactOutputSingle(WETH, WPOWERPERP, 3000, wPowerPerpToRedeem, 0);\n            ethToWithdrawFromCrab = crabToRedeem.wdiv(IERC20(CRAB).totalSupply()).wmul(ethInCrab);\n        }\n\n        vm.startPrank(user2);\n        IERC20(ZEN_BULL).approve(address(emergencyWithdraw), type(uint256).max);\n        emergencyWithdraw.emergencyWithdrawEthFromCrab(user2BullBalanceBefore, maxWethForOsqth);\n        vm.stopPrank();\n\n        uint256 bullSupplyAfter = emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n        uint256 user2BullBalanceAfter = IERC20(ZEN_BULL).balanceOf(user2);\n        uint256 user2EthBalanceAfter = address(user2).balance;\n        uint256 user2RecoveryTokenBalanceAfter = IERC20(emergencyWithdraw).balanceOf(user2);\n\n        assertEq(bullSupplyAfter, emergencyRedeemedBull.add(user2BullBalanceBefore));\n        assertEq(user2BullBalanceAfter, 0);\n        assertEq(\n            user2RecoveryTokenBalanceAfter - user2RecoveryTokenBalanceBefore, user2BullBalanceBefore\n        );\n        assertEq(\n            ethToWithdrawFromCrab.sub(maxWethForOsqth),\n            user2EthBalanceAfter.sub(user2EthBalanceBefore)\n        );\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/integration-test/EmergencyWithdraw/WithdrawEthTest.t.sol",
    "content": "pragma solidity =0.7.6;\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IEulerEToken } from \"../../../src/interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"../../../src/interface/IEulerDToken.sol\";\nimport { Quoter } from \"v3-periphery/lens/Quoter.sol\";\nimport { EmergencyWithdraw } from \"../../../src/EmergencyWithdraw.sol\";\nimport { ZenBullStrategy } from \"../../../src/ZenBullStrategy.sol\";\nimport { UniOracle } from \"../../../src/UniOracle.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\";\n\ncontract WithdrawEthTest is Test {\n    using StrategyMath for uint256;\n\n    uint256 internal constant ONE = 1e18;\n\n    address payable public constant ZEN_BULL = 0xb46Fb07b0c80DBC3F97cae3BFe168AcaD46dF507;\n    address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n    address public constant CRAB = 0x3B960E47784150F5a63777201ee2B15253D713e8;\n    address public constant UNI_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\n    address public constant WPOWERPERP = 0xf1B99e3E573A1a9C5E6B2Ce818b617F0E664E86B;\n    address public constant QUOTER = 0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6;\n    address public constant ETH_USDC_POOL = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640;\n    address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n    address public constant E_TOKEN = 0x1b808F49ADD4b8C6b5117d9681cF7312Fcf0dC1D;\n    address public constant D_TOKEN = 0x84721A3dB22EB852233AEAE74f9bC8477F8bcc42;\n\n    uint256 deployerPk;\n    uint256 user1Pk;\n    uint256 user2Pk;\n    address deployer;\n    address user1;\n    address user2;\n\n    EmergencyWithdraw internal emergencyWithdraw;\n\n    function setUp() public virtual {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 16816896);\n\n        deployerPk = 0xA11CD;\n        deployer = vm.addr(deployerPk);\n        user1Pk = 0xB21CD;\n        user1 = vm.addr(user1Pk);\n        user2Pk = 0xB22CD;\n        user2 = vm.addr(user2Pk);\n\n        vm.startPrank(deployer);\n        emergencyWithdraw =\n        new EmergencyWithdraw(CRAB, ZEN_BULL, WETH, USDC, WPOWERPERP, ETH_USDC_POOL, E_TOKEN, D_TOKEN, UNI_FACTORY);\n        vm.stopPrank();\n\n        // prank ZenBull owner to point to a new auction contract address\n        vm.prank(0xAfE66363c27EedB597a140c28B70b32F113fd5a8);\n        ZenBullStrategy(ZEN_BULL).setAuction(address(emergencyWithdraw));\n\n        vm.label(deployer, \"Deployer\");\n        vm.label(user1, \"user1\");\n        vm.label(address(emergencyWithdraw), \"EmergencyWithdraw\");\n\n        // bull whale\n        vm.startPrank(0xB845d3C82853b362ADF47A045c087d52384a7776);\n        IERC20(ZEN_BULL).transfer(\n            user1, IERC20(ZEN_BULL).balanceOf(0xB845d3C82853b362ADF47A045c087d52384a7776) / 2\n        );\n        IERC20(ZEN_BULL).transfer(\n            user2, IERC20(ZEN_BULL).balanceOf(0xB845d3C82853b362ADF47A045c087d52384a7776) / 2\n        );\n        vm.stopPrank();\n    }\n\n    function testWithdrawEthWhenNotActivated() public {\n        _emergencyWithdrawEthFromCrab(user1, IERC20(ZEN_BULL).balanceOf(user1));\n\n        uint256 recoveryTokenAmount = emergencyWithdraw.balanceOf(user1);\n\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"ETH withdrawal not activated yet\"));\n        emergencyWithdraw.withdrawEth(recoveryTokenAmount);\n        vm.stopPrank();\n    }\n\n    function testWithdrawEthWhenActivated() public {\n        {\n            uint256 ratio = 1e17;\n            while (IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL) > 0) {\n                if (ratio > 1e18) ratio = 1e18;\n\n                uint256 ethLimitPrice =\n                    UniOracle._getTwap(ETH_USDC_POOL, WETH, USDC, 420, false).wmul((ONE.sub(2e15)));\n                uint256 wethToWithdraw =\n                    ratio.wmul(IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL));\n                if (wethToWithdraw > emergencyWithdraw.MAX_WETH_PER_DEBT_REPAY()) {\n                    ratio = ratio / 2;\n                    wethToWithdraw = ratio.wmul(IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL));\n                }\n                uint256 usdcToRepay = ratio.wmul(IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL));\n                uint256 ethToRepayForFlashswap =\n                    Quoter(QUOTER).quoteExactOutputSingle(WETH, USDC, 500, usdcToRepay, 0);\n\n                vm.startPrank(user1);\n                emergencyWithdraw.emergencyRepayEulerDebt(ratio, ethLimitPrice, 500);\n                vm.stopPrank();\n\n                ratio = ratio.mul(2);\n                skip(420);\n            }\n\n            assertEq(IEulerDToken(D_TOKEN).balanceOf(ZEN_BULL), 0);\n            assertEq(IEulerEToken(E_TOKEN).balanceOfUnderlying(ZEN_BULL), 0);\n            assertEq(emergencyWithdraw.ethWithdrawalActivated(), true);\n            assertEq(emergencyWithdraw.ethWithdrawalActivated(), true);\n        }\n\n        _emergencyWithdrawEthFromCrab(user1, IERC20(ZEN_BULL).balanceOf(user1));\n        uint256 recoveryTokenAmount = emergencyWithdraw.balanceOf(user1);\n        uint256 totalRedeemedRecoveryTokenBefore =\n            emergencyWithdraw.redeemedRecoveryAmountForEulerWithdrawal();\n        uint256 payout = recoveryTokenAmount.wmul(address(emergencyWithdraw).balance).wdiv(\n            IERC20(ZEN_BULL).totalSupply().sub(totalRedeemedRecoveryTokenBefore)\n        );\n        uint256 user1EthBalanceBefore = address(user1).balance;\n        uint256 contractEthBalanceBefore = address(emergencyWithdraw).balance;\n\n        vm.startPrank(user1);\n        emergencyWithdraw.withdrawEth(recoveryTokenAmount);\n        vm.stopPrank();\n\n        assertEq(emergencyWithdraw.balanceOf(user1), 0);\n        assertEq(user1EthBalanceBefore.add(payout), address(user1).balance);\n        assertEq(contractEthBalanceBefore.sub(payout), address(emergencyWithdraw).balance);\n        assertEq(emergencyWithdraw.balanceOf(user1), 0);\n        assertEq(\n            emergencyWithdraw.redeemedRecoveryAmountForEulerWithdrawal(),\n            totalRedeemedRecoveryTokenBefore.add(recoveryTokenAmount)\n        );\n    }\n\n    function _emergencyWithdrawEthFromCrab(address _user, uint256 _zenBullAmount) internal {\n        uint256 emergencyRedeemedBull = emergencyWithdraw.redeemedZenBullAmountForCrabWithdrawal();\n        uint256 maxWethForOsqth;\n        uint256 ethToWithdrawFromCrab;\n        {\n            uint256 bullShare =\n                _zenBullAmount.wdiv(IERC20(ZEN_BULL).totalSupply().sub(emergencyRedeemedBull));\n            uint256 crabToRedeem = bullShare.wmul(ZenBullStrategy(ZEN_BULL).getCrabBalance());\n            (uint256 ethInCrab, uint256 wPowerPerpInCrab) =\n                ZenBullStrategy(ZEN_BULL).getCrabVaultDetails();\n            uint256 wPowerPerpToRedeem =\n                crabToRedeem.wmul(wPowerPerpInCrab).wdiv(IERC20(CRAB).totalSupply());\n\n            maxWethForOsqth =\n                Quoter(QUOTER).quoteExactOutputSingle(WETH, WPOWERPERP, 3000, wPowerPerpToRedeem, 0);\n            ethToWithdrawFromCrab = crabToRedeem.wdiv(IERC20(CRAB).totalSupply()).wmul(ethInCrab);\n        }\n\n        vm.startPrank(_user);\n        IERC20(ZEN_BULL).approve(address(emergencyWithdraw), type(uint256).max);\n        emergencyWithdraw.emergencyWithdrawEthFromCrab(_zenBullAmount, maxWethForOsqth);\n        vm.stopPrank();\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/integration-test/FlashZenTestFork.t.sol",
    "content": "pragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IEulerMarkets } from \"../../src/interface/IEulerMarkets.sol\";\nimport { IEulerEToken } from \"../../src/interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"../../src/interface/IEulerDToken.sol\";\n// contract\nimport { SwapRouter } from \"v3-periphery/SwapRouter.sol\";\nimport { Quoter } from \"v3-periphery/lens/Quoter.sol\";\nimport { TestUtil } from \"../util/TestUtil.t.sol\";\nimport { ZenBullStrategy } from \"../../src/ZenBullStrategy.sol\";\nimport { CrabStrategyV2 } from \"squeeth-monorepo/strategy/CrabStrategyV2.sol\";\nimport { Controller } from \"squeeth-monorepo/core/Controller.sol\";\nimport { FlashZen } from \"../../src/FlashZen.sol\";\n// lib\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\nimport { UniOracle } from \"../../src/UniOracle.sol\";\nimport { console } from \"forge-std/console.sol\";\n\n/**\n * @notice mainnet fork testing\n */\ncontract FlashZenTestFork is Test {\n    using StrategyMath for uint256;\n\n    uint32 internal constant TWAP = 420;\n    uint128 internal constant ONE = 1e18;\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n\n    TestUtil internal testUtil;\n    FlashZen internal flashBull;\n    ZenBullStrategy internal bullStrategy;\n    CrabStrategyV2 internal crabV2;\n    Controller internal controller;\n    Quoter internal quoter;\n\n    address internal weth;\n    address internal usdc;\n    address internal euler;\n    address internal eulerMarketsModule;\n    address internal eToken;\n    address internal dToken;\n    address internal wPowerPerp;\n    address internal ethWSqueethPool;\n    address internal ethUsdcPool;\n    address internal controllerOwner;\n    uint256 internal user1Pk;\n    uint256 internal deployerPk;\n    uint256 internal cap;\n    uint256 internal bullOwnerPk;\n    address internal user1;\n    address internal deployer;\n    address internal bullOwner;\n\n    // var to avoid stack too deep in test functions\n    uint256 userEthBalanceBeforeTx;\n\n    function setUp() public {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 15781550);\n\n        deployerPk = 0xAB11CE;\n        deployer = vm.addr(deployerPk);\n\n        vm.startPrank(deployer);\n\n        quoter = Quoter(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);\n\n        euler = 0x27182842E098f60e3D576794A5bFFb0777E025d3;\n        eulerMarketsModule = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3;\n        controller = Controller(0x64187ae08781B09368e6253F9E94951243A493D5);\n        crabV2 = CrabStrategyV2(0x3B960E47784150F5a63777201ee2B15253D713e8);\n\n        bullOwnerPk = 0xB11CD;\n        bullOwner = vm.addr(bullOwnerPk);\n\n        bullStrategy = new ZenBullStrategy(\n            address(crabV2),\n            address(controller),\n            euler,\n            eulerMarketsModule\n        );\n        bullStrategy.transferOwnership(bullOwner);\n        flashBull = new FlashZen(\n            address(bullStrategy),\n            0x1F98431c8aD98523631AE4a59f267346ea31F984\n        );\n        usdc = controller.quoteCurrency();\n        weth = controller.weth();\n        eToken = IEulerMarkets(eulerMarketsModule).underlyingToEToken(weth);\n        dToken = IEulerMarkets(eulerMarketsModule).underlyingToDToken(usdc);\n        wPowerPerp = controller.wPowerPerp();\n        ethWSqueethPool = IController(bullStrategy.powerTokenController()).wPowerPerpPool();\n        ethUsdcPool = IController(bullStrategy.powerTokenController()).ethQuoteCurrencyPool();\n        testUtil = new TestUtil(\n            address(bullStrategy),\n            address(controller),\n            eToken,\n            dToken,\n            address(crabV2)\n        );\n        controllerOwner = controller.owner();\n\n        vm.stopPrank();\n\n        cap = 100000e18;\n        vm.prank(bullOwner);\n        bullStrategy.setCap(cap);\n\n        user1Pk = 0xA11CE;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User 1\");\n        vm.label(address(bullStrategy), \"BullStrategy\");\n        vm.label(address(flashBull), \"FlashBull\");\n        vm.label(euler, \"Euler\");\n        vm.label(eulerMarketsModule, \"EulerMarkets\");\n        vm.label(usdc, \"USDC\");\n        vm.label(weth, \"WETH\");\n\n        vm.deal(user1, 100000000e18);\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 100e18);\n        // some WETH and USDC rich address\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(weth).transfer(user1, 10100e18);\n    }\n\n    function testFlashDeposit() public {\n        uint256 ethToCrab = 5e18;\n        (uint256 ethInCrab, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        (uint256 wSqueethToMint, uint256 fee) =\n            _calcWsqueethToMintAndFee(ethToCrab, squeethInCrab, ethInCrab);\n        uint256 crabToBeMinted =\n            _calcSharesToMint(ethToCrab.sub(fee), ethInCrab, IERC20(crabV2).totalSupply());\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        (uint256 wethToLend, uint256 usdcToBorrow) = bullStrategy.calcLeverageEthUsdc(\n            crabToBeMinted, 1e18, ethInCrab, squeethInCrab, crabV2.totalSupply()\n        );\n\n        uint256 totalEthToBull =\n            calcTotalEthToBull(wethToLend, ethToCrab, usdcToBorrow, wSqueethToMint);\n\n        uint256 minEthFromSqueeth;\n        uint256 minEthFromUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            minEthFromSqueeth = wSqueethToMint.wmul(squeethEthPrice.wmul(99e16));\n            minEthFromUsdc =\n                usdcToBorrow.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(uint256(1e18).add(5e15)));\n        }\n\n        uint256 bullToMint = testUtil.calcBullToMint(crabToBeMinted);\n\n        FlashZen.FlashDepositParams memory params = FlashZen.FlashDepositParams({\n            ethToCrab: ethToCrab,\n            minEthFromSqth: minEthFromSqueeth,\n            minEthFromUsdc: minEthFromUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(user1);\n        flashBull.flashDeposit{ value: totalEthToBull }(params);\n        vm.stopPrank();\n\n        assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n        assertApproxEqAbs(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), wethToLend, 1\n        );\n        assertEq(bullStrategy.getCrabBalance().sub(crabToBeMinted), bullCrabBalanceBefore);\n        assertEq(bullToMint, bullStrategy.balanceOf(user1), \"User1 bull balance mismatch\");\n    }\n\n    function testFlashDepositWithFee() public {\n        vm.startPrank(address(controller.owner()));\n        controller.setFeeRecipient(address(controller.owner()));\n        controller.setFeeRate(100);\n        vm.stopPrank();\n        assertEq(controller.feeRecipient(), address(controller.owner()));\n        assertEq(controller.feeRate(), 100);\n\n        uint256 ethToCrab = 5e18;\n        (uint256 ethInCrab, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        (uint256 wSqueethToMint, uint256 fee) =\n            _calcWsqueethToMintAndFee(ethToCrab, squeethInCrab, ethInCrab);\n        uint256 crabToBeMinted =\n            _calcSharesToMint(ethToCrab.sub(fee), ethInCrab, IERC20(crabV2).totalSupply());\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        (uint256 wethToLend, uint256 usdcToBorrow) = bullStrategy.calcLeverageEthUsdc(\n            crabToBeMinted, 1e18, ethInCrab, squeethInCrab, crabV2.totalSupply()\n        );\n\n        uint256 totalEthToBull =\n            calcTotalEthToBull(wethToLend, ethToCrab, usdcToBorrow, wSqueethToMint);\n\n        uint256 minEthFromSqueeth;\n        uint256 minEthFromUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            minEthFromSqueeth = wSqueethToMint.wmul(squeethEthPrice.wmul(99e16));\n            minEthFromUsdc = usdcToBorrow.mul(1e12).wdiv(ethUsdPrice.wmul(uint256(1e18).add(5e15)));\n        }\n\n        uint256 bullToMint = testUtil.calcBullToMint(crabToBeMinted);\n\n        FlashZen.FlashDepositParams memory params = FlashZen.FlashDepositParams({\n            ethToCrab: ethToCrab,\n            minEthFromSqth: minEthFromSqueeth,\n            minEthFromUsdc: minEthFromUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(user1);\n        flashBull.flashDeposit{ value: totalEthToBull }(params);\n        vm.stopPrank();\n\n        assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n        assertApproxEqAbs(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), wethToLend, 1\n        );\n        assertEq(bullStrategy.getCrabBalance().sub(crabToBeMinted), bullCrabBalanceBefore);\n        assertEq(bullToMint, bullStrategy.balanceOf(user1), \"User1 bull balance mismatch\");\n    }\n\n    function testFlashDepositWithHugeSqthSlippage() public {\n        uint256 ethToCrab = 5e18;\n        (uint256 ethInCrab, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        (uint256 wSqueethToMint, uint256 fee) =\n            _calcWsqueethToMintAndFee(ethToCrab, squeethInCrab, ethInCrab);\n        uint256 crabToBeMinted =\n            _calcSharesToMint(ethToCrab.sub(fee), ethInCrab, IERC20(crabV2).totalSupply());\n\n        (uint256 wethToLend, uint256 usdcToBorrow) = bullStrategy.calcLeverageEthUsdc(\n            crabToBeMinted, 1e18, ethInCrab, squeethInCrab, crabV2.totalSupply()\n        );\n\n        uint256 totalEthToBull =\n            calcTotalEthToBull(wethToLend, ethToCrab, usdcToBorrow, wSqueethToMint);\n\n        uint256 minEthFromSqueeth;\n        uint256 minEthFromUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            minEthFromSqueeth = wSqueethToMint.wmul(squeethEthPrice.wmul(101e16));\n            minEthFromUsdc =\n                usdcToBorrow.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(uint256(1e18).add(5e15)));\n        }\n\n        FlashZen.FlashDepositParams memory params = FlashZen.FlashDepositParams({\n            ethToCrab: ethToCrab,\n            minEthFromSqth: minEthFromSqueeth,\n            minEthFromUsdc: minEthFromUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"amount out less than min\"));\n        flashBull.flashDeposit{ value: totalEthToBull }(params);\n        vm.stopPrank();\n    }\n\n    function testFlashDepositWithHugeUsdcSlippage() public {\n        uint256 ethToCrab = 5e18;\n        (uint256 ethInCrab, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        (uint256 wSqueethToMint, uint256 fee) =\n            _calcWsqueethToMintAndFee(ethToCrab, squeethInCrab, ethInCrab);\n        uint256 crabToBeMinted =\n            _calcSharesToMint(ethToCrab.sub(fee), ethInCrab, IERC20(crabV2).totalSupply());\n\n        (uint256 wethToLend, uint256 usdcToBorrow) = bullStrategy.calcLeverageEthUsdc(\n            crabToBeMinted, 1e18, ethInCrab, squeethInCrab, crabV2.totalSupply()\n        );\n\n        uint256 totalEthToBull =\n            calcTotalEthToBull(wethToLend, ethToCrab, usdcToBorrow, wSqueethToMint);\n\n        uint256 minEthFromSqueeth;\n        uint256 minEthFromUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            minEthFromSqueeth = wSqueethToMint.wmul(squeethEthPrice.wmul(99e16));\n            minEthFromUsdc =\n                usdcToBorrow.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(uint256(1e18).sub(5e15)));\n        }\n\n        FlashZen.FlashDepositParams memory params = FlashZen.FlashDepositParams({\n            ethToCrab: ethToCrab,\n            minEthFromSqth: minEthFromSqueeth,\n            minEthFromUsdc: minEthFromUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"amount out less than min\"));\n        flashBull.flashDeposit{ value: totalEthToBull }(params);\n        vm.stopPrank();\n    }\n\n    function testScenarioFlashDepositInsufficientValue() public {\n        uint256 ethToCrab = 5e18;\n        (uint256 ethInCrab, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        (uint256 wSqueethToMint, uint256 fee) =\n            _calcWsqueethToMintAndFee(ethToCrab, squeethInCrab, ethInCrab);\n        uint256 crabToBeMinted =\n            _calcSharesToMint(ethToCrab.sub(fee), ethInCrab, IERC20(crabV2).totalSupply());\n\n        (uint256 wethToLend, uint256 usdcToBorrow) = bullStrategy.calcLeverageEthUsdc(\n            crabToBeMinted, 1e18, ethInCrab, squeethInCrab, crabV2.totalSupply()\n        );\n\n        uint256 totalEthToBull =\n            calcTotalEthToBull(wethToLend, ethToCrab, usdcToBorrow, wSqueethToMint);\n\n        uint256 minEthFromSqueeth;\n        uint256 minEthFromUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            minEthFromSqueeth = wSqueethToMint.wmul(squeethEthPrice.wmul(99e16));\n            minEthFromUsdc =\n                usdcToBorrow.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(uint256(1e18).add(5e15)));\n        }\n\n        FlashZen.FlashDepositParams memory params = FlashZen.FlashDepositParams({\n            ethToCrab: ethToCrab,\n            minEthFromSqth: minEthFromSqueeth,\n            minEthFromUsdc: minEthFromUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(user1);\n        vm.expectRevert();\n        flashBull.flashDeposit{ value: totalEthToBull.sub(5e18) }(params);\n        vm.stopPrank();\n    }\n\n    function testSecondFlashDeposit() public {\n        uint256 ethToCrabInitial = 5e18;\n        (uint256 ethInCrab, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        (uint256 wSqueethToMint, uint256 fee) =\n            _calcWsqueethToMintAndFee(ethToCrabInitial, squeethInCrab, ethInCrab);\n        uint256 crabToBeMinted =\n            _calcSharesToMint(ethToCrabInitial.sub(fee), ethInCrab, IERC20(crabV2).totalSupply());\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        uint256 bullToMint = testUtil.calcBullToMint(crabToBeMinted);\n        (uint256 wethToLend, uint256 usdcToBorrow) = bullStrategy.calcLeverageEthUsdc(\n            crabToBeMinted, 1e18, ethInCrab, squeethInCrab, crabV2.totalSupply()\n        );\n\n        uint256 totalEthToBull =\n            calcTotalEthToBull(wethToLend, ethToCrabInitial, usdcToBorrow, wSqueethToMint);\n\n        uint256 minEthFromSqueeth;\n        uint256 minEthFromUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            minEthFromSqueeth = wSqueethToMint.wmul(squeethEthPrice.wmul(99e16));\n            minEthFromUsdc =\n                usdcToBorrow.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(uint256(1e18).add(5e15)));\n        }\n\n        FlashZen.FlashDepositParams memory firstParams = FlashZen.FlashDepositParams({\n            ethToCrab: ethToCrabInitial,\n            minEthFromSqth: minEthFromSqueeth,\n            minEthFromUsdc: minEthFromUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(user1);\n        flashBull.flashDeposit{ value: totalEthToBull }(firstParams);\n        vm.stopPrank();\n        assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n        assertApproxEqAbs(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), wethToLend, 1\n        );\n        assertEq(bullStrategy.getCrabBalance().sub(crabToBeMinted), bullCrabBalanceBefore);\n        assertEq(bullToMint, bullStrategy.balanceOf(user1), \"User1 bull balance mismatch\");\n        uint256 userBullBalanceBefore = bullStrategy.balanceOf(user1);\n\n        uint256 bullCrabBalanceBeforeSecond = IERC20(crabV2).balanceOf(address(bullStrategy));\n        uint256 bullUsdcDebtBefore = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        (uint256 ethInCrabSecond, uint256 squeethInCrabSecond) = testUtil.getCrabVaultDetails();\n        uint256 ethToCrabSecond = 7e18;\n        (uint256 wSqueethToMintSecond, uint256 feeSecond) =\n            _calcWsqueethToMintAndFee(ethToCrabSecond, squeethInCrabSecond, ethInCrabSecond);\n        uint256 wethToLendFirst = wethToLend;\n        uint256 crabToBeMintedSecond = _calcSharesToMint(\n            ethToCrabSecond.sub(feeSecond), ethInCrabSecond, IERC20(crabV2).totalSupply()\n        );\n\n        uint256 bullToMintSecond = testUtil.calcBullToMint(crabToBeMintedSecond);\n        (uint256 wethToLendSecond, uint256 usdcToBorrowSecond) = bullStrategy.calcLeverageEthUsdc(\n            crabToBeMintedSecond,\n            bullToMintSecond.wdiv(bullStrategy.totalSupply().add(bullToMintSecond)),\n            ethInCrabSecond,\n            squeethInCrabSecond,\n            crabV2.totalSupply()\n        );\n\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n\n            FlashZen.FlashDepositParams memory params = FlashZen.FlashDepositParams({\n                ethToCrab: ethToCrabSecond,\n                minEthFromSqth: wSqueethToMintSecond.wmul(squeethEthPrice.wmul(99e16)),\n                minEthFromUsdc: usdcToBorrowSecond.mul(WETH_DECIMALS_DIFF).wdiv(\n                    ethUsdPrice.wmul(uint256(1e18).add(5e15))\n                    ),\n                wPowerPerpPoolFee: uint24(3000),\n                usdcPoolFee: uint24(3000)\n            });\n\n            vm.startPrank(user1);\n            flashBull.flashDeposit{\n                value: calcTotalEthToBull(\n                    wethToLendSecond, ethToCrabSecond, usdcToBorrowSecond, wSqueethToMintSecond\n                    )\n            }(params);\n            vm.stopPrank();\n        }\n\n        assertEq(\n            userBullBalanceBefore.add(bullToMintSecond),\n            bullStrategy.balanceOf(user1),\n            \"Bull balance mismatch for second flashdeposit\"\n        );\n        assertEq(\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(bullUsdcDebtBefore),\n            usdcToBorrowSecond,\n            \"Bull USDC debt amount mismatch for second flashdeposit\"\n        );\n        assertApproxEqAbs(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)).sub(wethToLendFirst),\n            wethToLendSecond,\n            1\n        );\n        assertEq(\n            bullStrategy.getCrabBalance().sub(crabToBeMintedSecond),\n            bullCrabBalanceBeforeSecond,\n            \"Bull crab balance mismatch for second flashdeposit\"\n        );\n    }\n\n    function testFlashWithdraw() public {\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 10e18);\n        vm.startPrank(user1);\n        _deposit(10e18);\n        vm.stopPrank();\n\n        uint256 bullToRedeem = bullStrategy.balanceOf(user1);\n        (\n            uint256 crabToRedeem,\n            uint256 wPowerPerpToRedeem,\n            uint256 ethToWithdrawFromCrab,\n            uint256 usdcToRepay\n        ) = calcAssetsNeededForFlashWithdraw(bullToRedeem);\n        uint256 maxEthForWPowerPerp;\n        uint256 maxEthForUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            maxEthForWPowerPerp = wPowerPerpToRedeem.wmul(squeethEthPrice.wmul(101e16));\n            maxEthForUsdc =\n                usdcToRepay.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(uint256(1e18).sub(5e15)));\n        }\n\n        FlashZen.FlashWithdrawParams memory params = FlashZen.FlashWithdrawParams({\n            bullAmount: bullStrategy.balanceOf(user1),\n            maxEthForWPowerPerp: maxEthForWPowerPerp,\n            maxEthForUsdc: maxEthForUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        uint256 wethToWithdraw = testUtil.calcWethToWithdraw(bullToRedeem);\n        uint256 userBullBalanceBefore = bullStrategy.balanceOf(user1);\n        uint256 ethInLendingBefore = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        uint256 usdcBorrowedBefore = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        uint256 crabBalanceBefore = crabV2.balanceOf(address(bullStrategy));\n        uint256 ethToWithdrawFromBull =\n            ethToWithdrawFromCrab.sub(maxEthForWPowerPerp).add(wethToWithdraw.sub(maxEthForUsdc));\n        userEthBalanceBeforeTx = user1.balance;\n\n        vm.startPrank(user1);\n        bullStrategy.approve(address(flashBull), params.bullAmount);\n        flashBull.flashWithdraw(params);\n        vm.stopPrank();\n\n        assertEq(\n            usdcBorrowedBefore.sub(usdcToRepay),\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)),\n            \"Bull USDC debt amount mismatch\"\n        );\n        assertEq(\n            ethInLendingBefore.sub(wethToWithdraw),\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)),\n            \"Bull ETH in leverage amount mismatch\"\n        );\n        assertEq(\n            userBullBalanceBefore.sub(bullToRedeem),\n            bullStrategy.balanceOf(user1),\n            \"User1 bull balance mismatch\"\n        );\n        assertEq(\n            crabBalanceBefore.sub(crabToRedeem),\n            bullStrategy.getCrabBalance(),\n            \"Bull crab balance mismatch\"\n        );\n        assertTrue((user1.balance).sub(userEthBalanceBeforeTx).sub(ethToWithdrawFromBull) <= 1e17);\n    }\n\n    function testScenarioFlashWithdrawInsufficientBull() public {\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 10e18);\n        vm.startPrank(user1);\n        _deposit(2e18);\n        vm.stopPrank();\n\n        uint256 bullToRedeem = 10e18;\n        (, uint256 wPowerPerpToRedeem,, uint256 usdcToRepay) =\n            calcAssetsNeededForFlashWithdraw(bullToRedeem);\n        uint256 maxEthForWPowerPerp;\n        uint256 maxEthForUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            maxEthForWPowerPerp = wPowerPerpToRedeem.wmul(squeethEthPrice.wmul(101e16));\n            maxEthForUsdc =\n                usdcToRepay.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(uint256(1e18).sub(5e15)));\n        }\n\n        FlashZen.FlashWithdrawParams memory params = FlashZen.FlashWithdrawParams({\n            bullAmount: bullToRedeem,\n            maxEthForWPowerPerp: maxEthForWPowerPerp,\n            maxEthForUsdc: maxEthForUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(user1);\n        bullStrategy.approve(address(flashBull), params.bullAmount);\n        vm.expectRevert(bytes(\"ERC20: transfer amount exceeds balance\"));\n        flashBull.flashWithdraw(params);\n        vm.stopPrank();\n    }\n\n    function testScenarioFlashWithdrawUsdcSlippage() public {\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 10e18);\n        vm.startPrank(user1);\n        _deposit(10e18);\n        vm.stopPrank();\n\n        uint256 bullToRedeem = bullStrategy.balanceOf(user1);\n        (, uint256 wPowerPerpToRedeem,, uint256 usdcToRepay) =\n            calcAssetsNeededForFlashWithdraw(bullToRedeem);\n        uint256 maxEthForWPowerPerp;\n        uint256 maxEthForUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            maxEthForWPowerPerp = wPowerPerpToRedeem.wmul(squeethEthPrice.wmul(101e16));\n            maxEthForUsdc =\n                usdcToRepay.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(uint256(1e18).add(5e15)));\n        }\n\n        FlashZen.FlashWithdrawParams memory params = FlashZen.FlashWithdrawParams({\n            bullAmount: bullToRedeem,\n            maxEthForWPowerPerp: maxEthForWPowerPerp,\n            maxEthForUsdc: maxEthForUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(user1);\n        bullStrategy.approve(address(flashBull), params.bullAmount);\n        vm.expectRevert(bytes(\"amount in greater than max\"));\n        flashBull.flashWithdraw(params);\n        vm.stopPrank();\n    }\n\n    function testScenarioFlashWithdrawSqthSlippage() public {\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 10e18);\n        vm.startPrank(user1);\n        _deposit(10e18);\n        vm.stopPrank();\n\n        uint256 bullToRedeem = bullStrategy.balanceOf(user1);\n        (, uint256 wPowerPerpToRedeem,, uint256 usdcToRepay) =\n            calcAssetsNeededForFlashWithdraw(bullToRedeem);\n        uint256 maxEthForWPowerPerp;\n        uint256 maxEthForUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            maxEthForWPowerPerp = wPowerPerpToRedeem.wmul(squeethEthPrice.wmul(99e16));\n            maxEthForUsdc =\n                usdcToRepay.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(uint256(1e18).sub(5e15)));\n        }\n\n        FlashZen.FlashWithdrawParams memory params = FlashZen.FlashWithdrawParams({\n            bullAmount: bullToRedeem,\n            maxEthForWPowerPerp: maxEthForWPowerPerp,\n            maxEthForUsdc: maxEthForUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(user1);\n        bullStrategy.approve(address(flashBull), params.bullAmount);\n        vm.expectRevert(bytes(\"amount in greater than max\"));\n        flashBull.flashWithdraw(params);\n        vm.stopPrank();\n    }\n\n    function testSecondFlashWithdraw() public {\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 20e18);\n        vm.startPrank(user1);\n        _deposit(10e18);\n        vm.stopPrank();\n\n        uint256 bullToRedeem = 5e18;\n        (uint256 crabToRedeem, uint256 wPowerPerpToRedeem,, uint256 usdcToRepay) =\n            calcAssetsNeededForFlashWithdraw(bullToRedeem);\n        uint256 maxEthForWPowerPerp;\n        uint256 maxEthForUsdc;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            maxEthForWPowerPerp = wPowerPerpToRedeem.wmul(squeethEthPrice.wmul(101e16));\n            maxEthForUsdc =\n                usdcToRepay.mul(WETH_DECIMALS_DIFF).wdiv(ethUsdPrice.wmul(uint256(1e18).sub(5e15)));\n        }\n\n        FlashZen.FlashWithdrawParams memory params = FlashZen.FlashWithdrawParams({\n            bullAmount: bullToRedeem,\n            maxEthForWPowerPerp: maxEthForWPowerPerp,\n            maxEthForUsdc: maxEthForUsdc,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        uint256 wethToWithdraw = testUtil.calcWethToWithdraw(bullToRedeem);\n        uint256 userBullBalanceBefore = bullStrategy.balanceOf(user1);\n        uint256 ethInLendingBefore = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        uint256 usdcBorrowedBefore = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        uint256 crabBalanceBefore = crabV2.balanceOf(address(bullStrategy));\n        userEthBalanceBeforeTx = user1.balance;\n\n        vm.startPrank(user1);\n        bullStrategy.approve(address(flashBull), params.bullAmount);\n        flashBull.flashWithdraw(params);\n        vm.stopPrank();\n\n        assertEq(\n            usdcBorrowedBefore.sub(usdcToRepay),\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)),\n            \"Bull USDC debt amount mismatch\"\n        );\n        assertApproxEqAbs(\n            ethInLendingBefore.sub(wethToWithdraw),\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)),\n            1\n        );\n        assertEq(\n            userBullBalanceBefore.sub(bullToRedeem),\n            bullStrategy.balanceOf(user1),\n            \"User1 bull balance mismatch\"\n        );\n        assertEq(\n            crabBalanceBefore.sub(crabToRedeem),\n            crabV2.balanceOf(address(bullStrategy)),\n            \"Bull crab balance mismatch\"\n        );\n\n        // Second withdrawal\n\n        uint256 bullToRedeemSecond = bullStrategy.balanceOf(user1);\n        (uint256 crabToRedeemSecond, uint256 wPowerPerpToRedeemSecond,, uint256 usdcToRepaySecond) =\n            calcAssetsNeededForFlashWithdraw(bullToRedeemSecond);\n        uint256 maxEthForWPowerPerpSecond;\n        uint256 maxEthForUsdcSecond;\n        {\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 squeethEthPrice =\n                UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n            maxEthForWPowerPerpSecond = wPowerPerpToRedeemSecond.wmul(squeethEthPrice.wmul(101e16));\n            maxEthForUsdcSecond = usdcToRepaySecond.mul(WETH_DECIMALS_DIFF).wdiv(\n                ethUsdPrice.wmul(uint256(1e18).sub(5e15))\n            );\n        }\n\n        FlashZen.FlashWithdrawParams memory paramsSecond = FlashZen.FlashWithdrawParams({\n            bullAmount: bullToRedeemSecond,\n            maxEthForWPowerPerp: maxEthForWPowerPerpSecond,\n            maxEthForUsdc: maxEthForUsdcSecond,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        uint256 wethToWithdrawSecond = testUtil.calcWethToWithdraw(bullToRedeemSecond);\n        uint256 userBullBalanceBeforeSecond = bullStrategy.balanceOf(user1);\n        uint256 ethInLendingBeforeSecond =\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        uint256 usdcBorrowedBeforeSecond = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        uint256 crabBalanceBeforeSecond = crabV2.balanceOf(address(bullStrategy));\n        userEthBalanceBeforeTx = user1.balance;\n\n        vm.startPrank(user1);\n        bullStrategy.approve(address(flashBull), paramsSecond.bullAmount);\n        flashBull.flashWithdraw(paramsSecond);\n        vm.stopPrank();\n\n        assertEq(\n            usdcBorrowedBeforeSecond.sub(usdcToRepaySecond),\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)),\n            \"Bull USDC debt amount mismatch\"\n        );\n        assertApproxEqAbs(\n            ethInLendingBeforeSecond.sub(wethToWithdrawSecond),\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)),\n            1\n        );\n        assertEq(\n            userBullBalanceBeforeSecond.sub(bullToRedeemSecond),\n            bullStrategy.balanceOf(user1),\n            \"User1 bull balance mismatch\"\n        );\n        assertEq(\n            crabBalanceBeforeSecond.sub(crabToRedeemSecond),\n            crabV2.balanceOf(address(bullStrategy)),\n            \"Bull crab balance mismatch\"\n        );\n    }\n\n    /**\n     * /************************************************************* Helper functions! ************************************************************\n     */\n    function squeethPrice() internal view returns (uint256) {\n        return UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n    }\n\n    function ethPrice() internal view returns (uint256) {\n        return UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n    }\n\n    function calcTotalEthToBull(\n        uint256 wethToLend,\n        uint256 ethToCrab,\n        uint256 usdcToBorrow,\n        uint256 wSqueethToMint\n    ) internal returns (uint256) {\n        uint256 minEthFromSqueeth =\n            quoter.quoteExactInputSingle(wPowerPerp, weth, 3000, wSqueethToMint, 0);\n        uint256 minEthFromUsdc = quoter.quoteExactInputSingle(usdc, weth, 3000, usdcToBorrow, 0);\n\n        uint256 totalEthToBull =\n            wethToLend.add(ethToCrab).sub(minEthFromSqueeth).sub(minEthFromUsdc).add(10e16);\n        return totalEthToBull;\n    }\n\n    function _calcWsqueethToMintAndFee(\n        uint256 _depositedAmount,\n        uint256 _strategyDebtAmount,\n        uint256 _strategyCollateralAmount\n    ) internal view returns (uint256, uint256) {\n        uint256 wSqueethToMint;\n        uint256 wSqueethEthPrice =\n            UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n        uint256 feeRate = IController(bullStrategy.powerTokenController()).feeRate();\n        uint256 feeAdjustment = wSqueethEthPrice.mul(feeRate).div(10000);\n\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\n        );\n\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\n\n        return (wSqueethToMint, fee);\n    }\n\n    /**\n     * @dev calculate amount of strategy token to mint for depositor\n     * @param _amount amount of ETH deposited\n     * @param _strategyCollateralAmount amount of strategy collateral\n     * @param _crabTotalSupply total supply of strategy token\n     * @return amount of strategy token to mint\n     */\n    function _calcSharesToMint(\n        uint256 _amount,\n        uint256 _strategyCollateralAmount,\n        uint256 _crabTotalSupply\n    ) internal pure returns (uint256) {\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\n\n        if (_crabTotalSupply != 0) {\n            return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\n        }\n\n        return _amount;\n    }\n\n    function _deposit(uint256 _crabToDeposit) internal returns (uint256, uint256) {\n        (uint256 wethToLend, uint256 usdcToBorrow) =\n            testUtil.calcCollateralAndBorrowAmount(_crabToDeposit);\n\n        IERC20(crabV2).approve(address(bullStrategy), _crabToDeposit);\n        bullStrategy.deposit{ value: wethToLend }(_crabToDeposit);\n\n        return (wethToLend, usdcToBorrow);\n    }\n\n    function calcAssetsNeededForFlashWithdraw(uint256 _bullAmount)\n        internal\n        view\n        returns (uint256, uint256, uint256, uint256)\n    {\n        uint256 bullShare = _bullAmount.wdiv(bullStrategy.totalSupply());\n        uint256 crabToRedeem = bullShare.wmul(crabV2.balanceOf(address(bullStrategy)));\n        (uint256 ethInCrab, uint256 squeethInCrab) = bullStrategy.getCrabVaultDetails();\n        uint256 crabTotalSupply = crabV2.totalSupply();\n        uint256 wPowerPerpToRedeem = crabToRedeem.wmul(squeethInCrab).wdiv(crabTotalSupply);\n        uint256 ethToWithdraw = crabToRedeem.wmul(ethInCrab).wdiv(crabTotalSupply);\n        uint256 usdcToRepay = bullStrategy.calcUsdcToRepay(bullShare);\n\n        return (crabToRedeem, wPowerPerpToRedeem, ethToWithdraw, usdcToRepay);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/integration-test/ZenAuctionTestFork.t.sol",
    "content": "pragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IWETH9 } from \"squeeth-monorepo/interfaces/IWETH9.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IEulerMarkets } from \"../../src/interface/IEulerMarkets.sol\";\nimport { IEulerEToken } from \"../../src/interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"../../src/interface/IEulerDToken.sol\";\nimport { ISwapRouter } from \"v3-periphery/interfaces/ISwapRouter.sol\";\n// contract\nimport { TestUtil } from \"../util/TestUtil.t.sol\";\nimport { SwapRouter } from \"v3-periphery/SwapRouter.sol\";\nimport { Quoter } from \"v3-periphery/lens/Quoter.sol\";\nimport { ZenBullStrategy } from \"../../src/ZenBullStrategy.sol\";\nimport { CrabStrategyV2 } from \"squeeth-monorepo/strategy/CrabStrategyV2.sol\";\nimport { Controller } from \"squeeth-monorepo/core/Controller.sol\";\nimport { ZenAuction } from \"../../src/ZenAuction.sol\";\nimport { FlashZen } from \"../../src/FlashZen.sol\";\nimport { SigUtil } from \"../util/SigUtil.sol\";\n// lib\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\nimport { UniOracle } from \"../../src/UniOracle.sol\";\n\n/**\n * @notice mainnet fork testing\n */\ncontract ZenAuctionTestFork is Test {\n    using StrategyMath for uint256;\n\n    uint32 internal constant TWAP = 420;\n    uint128 internal constant ONE = 1e18;\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n\n    ZenBullStrategy internal bullStrategy;\n    FlashZen internal flashBull;\n    ZenAuction internal auctionBull;\n    CrabStrategyV2 internal crabV2;\n    Controller internal controller;\n    SwapRouter internal swapRouter;\n    TestUtil internal testUtil;\n    Quoter internal quoter;\n    SigUtil internal sigUtil;\n\n    uint256 internal user1Pk;\n    uint256 internal user2Pk;\n    uint256 internal ownerPk;\n    uint256 internal deployerPk;\n    uint256 internal auctionManagerPk;\n\n    address internal user1;\n    address internal user2;\n    address internal owner;\n    address internal deployer;\n    address internal auctionManager;\n\n    address internal weth;\n    address internal usdc;\n    address internal euler;\n    address internal factory;\n    address internal ethWSqueethPool;\n    address internal ethUsdcPool;\n    address internal eulerMarketsModule;\n    address internal eToken;\n    address internal dToken;\n    address internal wPowerPerp;\n\n    uint256 internal cap;\n\n    /// @dev to avoid stack too deep\n    uint256 initialWethInLeverage;\n    uint256 initialDebt;\n    uint256 currentWethInLeverage;\n    uint256 currentDebt;\n    uint256 targetWethInLeverage;\n    uint256 targetDebt;\n    uint256 userWethBalanceBeforeAuction;\n    uint256 userWPowerPerpBalanceBeforeAuction;\n    uint256 user2WethBalanceBeforeAuction;\n    uint256 user2WPowerPerpBalanceBeforeAuction;\n    ZenAuction.Order[] orders;\n\n    function setUp() public {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        // vm.createSelectFork(FORK_URL, 15939557);\n        vm.createSelectFork(FORK_URL, 15781550);\n\n        ownerPk = 0xA1CCE;\n        owner = vm.addr(ownerPk);\n        auctionManagerPk = 0xA1DCE;\n        auctionManager = vm.addr(auctionManagerPk);\n        deployerPk = 0xA11CE;\n        deployer = vm.addr(deployerPk);\n        user1Pk = 0xA11DE;\n        user1 = vm.addr(user1Pk);\n        user2Pk = 0xC11CE;\n        user2 = vm.addr(user2Pk);\n\n        vm.startPrank(deployer);\n        quoter = Quoter(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);\n        swapRouter = SwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);\n        factory = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\n        euler = 0x27182842E098f60e3D576794A5bFFb0777E025d3;\n        eulerMarketsModule = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3;\n        controller = Controller(0x64187ae08781B09368e6253F9E94951243A493D5);\n        crabV2 = CrabStrategyV2(0x3B960E47784150F5a63777201ee2B15253D713e8);\n        bullStrategy = new ZenBullStrategy(\n            address(crabV2),\n            address(controller),\n            euler,\n            eulerMarketsModule\n        );\n        bullStrategy.transferOwnership(owner);\n        flashBull = new FlashZen(address(bullStrategy), factory);\n        usdc = controller.quoteCurrency();\n        weth = controller.weth();\n        eToken = IEulerMarkets(eulerMarketsModule).underlyingToEToken(weth);\n        dToken = IEulerMarkets(eulerMarketsModule).underlyingToDToken(usdc);\n        wPowerPerp = controller.wPowerPerp();\n        ethWSqueethPool = controller.wPowerPerpPool();\n        ethUsdcPool = controller.ethQuoteCurrencyPool();\n        auctionBull = new ZenAuction(\n            auctionManager,\n            address(bullStrategy),\n            factory,\n            address(crabV2),\n            eToken,\n            dToken\n        );\n        auctionBull.transferOwnership(owner);\n        testUtil = new TestUtil(\n            address(bullStrategy),\n            address(controller),\n            eToken,\n            dToken,\n            address(crabV2)\n        );\n        sigUtil = new SigUtil(auctionBull.DOMAIN_SEPARATOR());\n        vm.stopPrank();\n\n        cap = 100000e18;\n        vm.startPrank(owner);\n        bullStrategy.setCap(cap);\n        bullStrategy.setAuction(address(auctionBull));\n        auctionBull.setCrUpperAndLower(1.8e18, 2.2e18);\n        auctionBull.setDeltaUpperAndLower(0.9e18, 1.1e18);\n        auctionBull.setFullRebalanceClearingPriceTolerance(2e17);\n        auctionBull.setRebalanceWethLimitPriceTolerance(2e17);\n        vm.stopPrank();\n\n        vm.label(user1, \"User 1\");\n        vm.label(user2, \"User 2\");\n        vm.label(address(bullStrategy), \"BullStrategy\");\n        vm.label(euler, \"Euler\");\n        vm.label(eulerMarketsModule, \"EulerMarkets\");\n        vm.label(usdc, \"USDC\");\n        vm.label(weth, \"WETH\");\n        vm.label(wPowerPerp, \"oSQTH\");\n        vm.label(address(crabV2), \"crabV2\");\n        vm.label(address(swapRouter), \"SwapRouter\");\n        vm.label(address(sigUtil), \"SigUtils\");\n\n        vm.deal(user1, 10000000e18);\n        vm.deal(user2, 10000000e18);\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 50e18);\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user2, 50e18);\n        // some WETH and USDC rich address\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(weth).transfer(user1, 5000e18);\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(weth).transfer(user2, 5000e18);\n        vm.prank(0x40ec5B33f54e0E8A33A975908C5BA1c14e5BbbDf);\n        IERC20(usdc).transfer(user1, 250000000e6);\n        vm.prank(0x40ec5B33f54e0E8A33A975908C5BA1c14e5BbbDf);\n        IERC20(usdc).transfer(user2, 250000000e6);\n        //vm.stopPrank();\n        // osQTH whale\n        vm.prank(0x35AeD16f957b39342744B8366A8c13172507D7b8);\n        IERC20(wPowerPerp).transfer(user1, 500e18);\n        vm.prank(0x35AeD16f957b39342744B8366A8c13172507D7b8);\n        IERC20(wPowerPerp).transfer(user2, 500e18);\n        // mint more oSQTH\n        vm.prank(user1);\n        controller.mintWPowerPerpAmount{ value: 100000e18 }(0, 10000e18, 0);\n        vm.prank(user2);\n        controller.mintWPowerPerpAmount{ value: 100000e18 }(0, 10000e18, 0);\n\n        _initateDepositInBull();\n    }\n\n    function testSetup() public {\n        assertEq(auctionBull.deltaUpper(), 1.1e18);\n        assertEq(auctionBull.deltaLower(), 0.9e18);\n        assertEq(auctionBull.crUpper(), 2.2e18);\n        assertEq(auctionBull.crLower(), 1.8e18);\n        assertEq(auctionBull.owner(), owner);\n        assertEq(auctionBull.auctionManager(), auctionManager);\n    }\n\n    function testSetAuctionManagerZeroAddress() public {\n        vm.prank(owner);\n        vm.expectRevert(bytes(\"AB19\"));\n        auctionBull.setAuctionManager(address(0));\n    }\n\n    function testSetAuctionManagerWhenCallerNotOwner() public {\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        auctionBull.setAuctionManager(address(owner));\n    }\n\n    function testSetAuctionManager() public {\n        vm.prank(owner);\n        auctionBull.setAuctionManager(address(owner));\n        assertEq(auctionBull.auctionManager(), address(owner));\n    }\n\n    function testSetAuctionToZeroAddress() public {\n        vm.prank(address(owner));\n        vm.expectRevert(bytes(\"LB2\"));\n        bullStrategy.setAuction(address(0));\n    }\n\n    function testSetAuction() public {\n        vm.prank(address(owner));\n        bullStrategy.setAuction(address(usdc));\n        assertEq(bullStrategy.auction(), address(usdc));\n    }\n\n    function testSetCrUpperLessThanLower() public {\n        vm.prank(owner);\n        vm.expectRevert(bytes(\"AB3\"));\n        auctionBull.setCrUpperAndLower(3e18, 1.5e18);\n    }\n\n    function testSetCrUpperAndLower() public {\n        vm.prank(owner);\n        auctionBull.setCrUpperAndLower(1.5e18, 3e18);\n    }\n\n    function testSetCrUpperAndLowerWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        auctionBull.setCrUpperAndLower(1.5e18, 3e18);\n    }\n\n    function testSetDeltaUpperLessThanLower() public {\n        vm.prank(owner);\n        vm.expectRevert(bytes(\"AB4\"));\n        auctionBull.setDeltaUpperAndLower(1.1e18, 0.9e18);\n    }\n\n    function testSetDeltaUpperAndLower() public {\n        vm.prank(owner);\n        auctionBull.setDeltaUpperAndLower(0.9e18, 1.1e18);\n    }\n\n    function testSetDeltaUpperAndLowerWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        auctionBull.setDeltaUpperAndLower(0.9e18, 1.1e18);\n    }\n\n    function testSetFullRebalanceClearingPriceTolerance() public {\n        vm.prank(owner);\n        auctionBull.setFullRebalanceClearingPriceTolerance(5e16);\n        assertEq(auctionBull.fullRebalanceClearingPriceTolerance(), 5e16);\n    }\n\n    function testSetFullRebalanceClearingPriceToleranceOutOfRange() public {\n        vm.prank(owner);\n        vm.expectRevert(bytes(\"AB14\"));\n        auctionBull.setFullRebalanceClearingPriceTolerance(3e17);\n    }\n\n    function testSetRebalanceWethLimitPriceToleranceOutOfRange() public {\n        vm.prank(owner);\n        vm.expectRevert(bytes(\"AB16\"));\n        auctionBull.setRebalanceWethLimitPriceTolerance(3e17);\n    }\n\n    function testSetRebalanceWethLimitPriceTolerance() public {\n        vm.prank(owner);\n        auctionBull.setRebalanceWethLimitPriceTolerance(5e16);\n        assertEq(auctionBull.rebalanceWethLimitPriceTolerance(), 5e16);\n    }\n\n    function testSetFullRebalanceClearingPriceToleranceWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        auctionBull.setFullRebalanceClearingPriceTolerance(5e16);\n    }\n\n    function testSetRebalanceWethLimitPriceToleranceWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        auctionBull.setRebalanceWethLimitPriceTolerance(5e16);\n    }\n\n    function testFullRebalanceWhenEthUpAndCrTooLow() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n        crabAmount = crabAmount.mul(3);\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.mul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB2\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenEthDownAndCrTooHigh() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 6000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 6000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        crabAmount = crabAmount.mul(2);\n\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(isDepositingInCrab, false);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB2\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(8e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenEthDownAndCrTooLow() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 6000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 6000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        crabAmount = crabAmount.mul(2);\n\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(isDepositingInCrab, false);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB2\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(8e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testLeverageRebalanceWhereCrIsInvalid() public {\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 50000e18 }();\n        IERC20(weth).approve(address(swapRouter), 50000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 50000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 10000);\n\n        uint256 crabPrice = testUtil.getCrabPrice();\n        uint256 usdcDebtTarget =\n            crabPrice.wmul(IERC20(crabV2).balanceOf(address(bullStrategy))).div(1e12);\n        bool isSellingUsdc =\n            (usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))) ? true : false;\n\n        assertEq(isSellingUsdc, false);\n\n        uint256 usdcAmount = (\n            usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))\n        )\n            ? usdcDebtTarget.sub(IEulerDToken(dToken).balanceOf(address(bullStrategy)))\n            : IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcDebtTarget);\n        uint256 maxEthForUsdc = quoter.quoteExactOutputSingle(weth, usdc, 3000, usdcAmount, 0);\n        uint256 limitPrice = usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(maxEthForUsdc);\n        vm.startPrank(auctionManager);\n        vm.expectRevert(bytes(\"AB2\"));\n        auctionBull.leverageRebalance(isSellingUsdc, usdcAmount, limitPrice, 3000);\n        vm.stopPrank();\n    }\n\n    function testLeverageRebalanceWhereWhenCallerNotAuctionManager() public {\n        // move prices up\n        vm.startPrank(user1);\n        IERC20(usdc).approve(address(swapRouter), 10000000e6);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: usdc,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000000e6,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IWETH9(weth).deposit{ value: 100e18 }();\n        IERC20(weth).approve(address(swapRouter), 100e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: wPowerPerp,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 100e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        uint256 crabPrice = testUtil.getCrabPrice();\n        uint256 usdcDebtTarget =\n            crabPrice.wmul(IERC20(crabV2).balanceOf(address(bullStrategy))).div(1e12);\n        bool isSellingUsdc =\n            (usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))) ? true : false;\n\n        assertEq(isSellingUsdc, true);\n\n        uint256 usdcAmount = (\n            usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))\n        )\n            ? usdcDebtTarget.sub(IEulerDToken(dToken).balanceOf(address(bullStrategy)))\n            : IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcDebtTarget);\n        uint256 minEthForUsdc = quoter.quoteExactInputSingle(usdc, weth, 3000, usdcAmount, 0);\n        uint256 limitPrice = usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(minEthForUsdc);\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"AB0\"));\n        auctionBull.leverageRebalance(isSellingUsdc, usdcAmount, limitPrice, 3000);\n        vm.stopPrank();\n    }\n\n    function testFullRebalanceWhenOrderSignerIsInvalid() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: owner,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: owner,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.wmul(squeethEthPrice));\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB11\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenCallerIsNotAuctionManager() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.wmul(squeethEthPrice));\n\n        vm.prank(deployer);\n        vm.expectRevert(bytes(\"AB0\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenNonceAlreadyUsed() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.wmul(squeethEthPrice));\n\n        vm.prank(user1);\n        auctionBull.useNonce(0);\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB13\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenOrderDirectionWrong() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: !isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: ethUsdPrice.wmul(13e17),\n                isBuying: !isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB6\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenBuyOrderBelowClearingPrice() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB9\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenOrderExpired() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.wmul(squeethEthPrice));\n\n        vm.warp(block.timestamp + 10000);\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB12\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenClearingPriceIsZero() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB5\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            0,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenClearingPriceIsOutOfRangeAndDepositingCrab() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.wmul(squeethEthPrice));\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB17\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice.wmul(0.75e18),\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenClearingPriceIsOutOfRangeAndWithdrawingCrab() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 6000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 6000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, false);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB18\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice.wmul(1.25e18),\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenEthLimitOutOfRangeTooLow() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB15\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(0.75e18),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenEthLimitOutOfRangeTooHigh() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB15\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(1.25e18),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenDepositingInCrabAndInvalidOrdersArray() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 2000e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            1,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.wdiv(2e18),\n                price: type(uint256).max - 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.wdiv(2e18),\n                price: type(uint256).max - 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n\n            // trader signing bid\n            orderSig = SigUtil.Order({\n                bidId: 2,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.wdiv(2e18),\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 1\n            });\n            bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            orderData = ZenAuction.Order({\n                bidId: 2,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.wdiv(2e18),\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 1,\n                v: v,\n                r: r,\n                s: s\n            });\n\n            orders.push(orderData);\n        }\n\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), 1, false\n        );\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.wmul(squeethEthPrice));\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB8\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenWithdrawingInCrabWithInvalidOrdersArray() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 6000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 6000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, false);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.wdiv(2e18),\n                price: 2,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.wdiv(2e18),\n                price: 2,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n\n            // trader signing bid\n            orderSig = SigUtil.Order({\n                bidId: 2,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.wdiv(2e18),\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 1\n            });\n            bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            orderData = ZenAuction.Order({\n                bidId: 2,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.wdiv(2e18),\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 1,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB7\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenEthUp() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.mul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), targetWethInLeverage\n        );\n        assertEq(\n            userWPowerPerpBalanceBeforeAuction.add(wPowerPerpAmountToTrade),\n            IERC20(wPowerPerp).balanceOf(user1)\n        );\n        assertEq(\n            userWethBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n            IERC20(weth).balanceOf(user1)\n        );\n        assertApproxEqRel(\n            bullCrabBalanceBefore.add(crabAmount),\n            IERC20(crabV2).balanceOf(address(bullStrategy)),\n            1e5\n        );\n        assertEq(squeethInCrab.add(wPowerPerpAmountToTrade), squeethInCrabAfter);\n    }\n\n    function testFullRebalanceReduceWethInEuler() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.mul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(8e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), targetWethInLeverage\n        );\n        assertEq(\n            userWPowerPerpBalanceBeforeAuction.add(wPowerPerpAmountToTrade),\n            IERC20(wPowerPerp).balanceOf(user1)\n        );\n        assertEq(\n            userWethBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n            IERC20(weth).balanceOf(user1)\n        );\n        assertApproxEqRel(\n            bullCrabBalanceBefore.add(crabAmount),\n            IERC20(crabV2).balanceOf(address(bullStrategy)),\n            1e5\n        );\n        assertEq(squeethInCrab.add(wPowerPerpAmountToTrade), squeethInCrabAfter);\n    }\n\n    function testFullRebalanceDepositCrabDecreaseEthRepayUsdc() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        initialDebt = currentDebt;\n        initialWethInLeverage = currentWethInLeverage;\n\n        uint256 sellUsdcBuyWethAmount = 1;\n        uint256 sellWethBuyWPowerPerpAmount = 200e18;\n        uint256 sellWethBuyUsdcAmount = 1;\n        uint256 sellWPowerPerpAmountBuyWethAmount = 1;\n        {\n            // All possible price moves\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), type(uint256).max);\n            IERC20(weth).approve(address(swapRouter), type(uint256).max);\n            IERC20(wPowerPerp).approve(address(swapRouter), type(uint256).max);\n            IWETH9(weth).deposit{ value: sellWethBuyWPowerPerpAmount }();\n            IWETH9(weth).deposit{ value: sellWethBuyUsdcAmount }();\n            IERC20(wPowerPerp).approve(address(auctionBull), type(uint256).max);\n\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellUsdcBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: usdc,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyUsdcAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyWPowerPerpAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: wPowerPerp,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWPowerPerpAmountBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.mul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            (targetDebt < currentDebt) ? ethUsdPrice.wmul(8e17) : ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), targetWethInLeverage\n        );\n        assertTrue(isDepositingInCrab);\n        assertLt(targetWethInLeverage, initialWethInLeverage);\n        assertLt(targetDebt, initialDebt);\n        if (isDepositingInCrab) {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.add(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.add(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n            assertEq(squeethInCrab.add(wPowerPerpAmountToTrade), squeethInCrabAfter);\n        } else {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.sub(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.add(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.sub(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n        }\n    }\n\n    function testFullRebalanceWithdrawCrabIncreaseEthBorrrowUsdc() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        initialDebt = currentDebt;\n        initialWethInLeverage = currentWethInLeverage;\n        uint256 sellUsdcBuyWethAmount = 1;\n        uint256 sellWethBuyWPowerPerpAmount = 1;\n        uint256 sellWethBuyUsdcAmount = 1;\n        uint256 sellWPowerPerpAmountBuyWethAmount = 200e18;\n        {\n            // All possible price moves\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), type(uint256).max);\n            IERC20(weth).approve(address(swapRouter), type(uint256).max);\n            IERC20(wPowerPerp).approve(address(swapRouter), type(uint256).max);\n            IWETH9(weth).deposit{ value: sellWethBuyWPowerPerpAmount }();\n            IWETH9(weth).deposit{ value: sellWethBuyUsdcAmount }();\n            IERC20(wPowerPerp).approve(address(auctionBull), type(uint256).max);\n\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellUsdcBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: usdc,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyUsdcAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyWPowerPerpAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: wPowerPerp,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWPowerPerpAmountBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.mul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            (targetDebt < currentDebt) ? ethUsdPrice.wmul(8e17) : ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), targetWethInLeverage\n        );\n        assertTrue(!isDepositingInCrab);\n        assertLt(initialWethInLeverage, currentWethInLeverage);\n        assertLt(initialDebt, currentDebt);\n        if (isDepositingInCrab) {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.add(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.add(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n            assertEq(squeethInCrab.add(wPowerPerpAmountToTrade), squeethInCrabAfter);\n        } else {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.sub(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.add(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.sub(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n        }\n    }\n\n    function testFullRebalanceWithdrawCrabDecreaseEthRepayUsdc() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        initialDebt = currentDebt;\n        initialWethInLeverage = currentWethInLeverage;\n        uint256 sellUsdcBuyWethAmount = 1;\n        uint256 sellWethBuyWPowerPerpAmount = 1;\n        uint256 sellWethBuyUsdcAmount = 200e18;\n        uint256 sellWPowerPerpAmountBuyWethAmount = 1;\n        {\n            // All possible price moves\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), type(uint256).max);\n            IERC20(weth).approve(address(swapRouter), type(uint256).max);\n            IERC20(wPowerPerp).approve(address(swapRouter), type(uint256).max);\n            IWETH9(weth).deposit{ value: sellWethBuyWPowerPerpAmount }();\n            IWETH9(weth).deposit{ value: sellWethBuyUsdcAmount }();\n            IERC20(wPowerPerp).approve(address(auctionBull), type(uint256).max);\n\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellUsdcBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: usdc,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyUsdcAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyWPowerPerpAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: wPowerPerp,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWPowerPerpAmountBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.mul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            (targetDebt < currentDebt) ? ethUsdPrice.wmul(8e17) : ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        // assertEq(\n        //     IEulerDToken(dToken).balanceOf(address(bullStrategy)), targetDebt\n        // );\n        assertTrue(!isDepositingInCrab);\n        assertLt(currentWethInLeverage, initialWethInLeverage);\n        assertLt(currentDebt, initialDebt);\n        if (isDepositingInCrab) {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.add(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.add(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n            assertEq(squeethInCrab.add(wPowerPerpAmountToTrade), squeethInCrabAfter);\n        } else {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.sub(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.add(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.sub(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n        }\n    }\n\n    function testFullRebalanceDepositCrabDecreaseEthBorrowUsdc() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        initialDebt = currentDebt;\n        initialWethInLeverage = currentWethInLeverage;\n        uint256 sellUsdcBuyWethAmount = 5000000e6;\n        uint256 sellWethBuyWPowerPerpAmount = 200e18;\n        uint256 sellWethBuyUsdcAmount = 1;\n        uint256 sellWPowerPerpAmountBuyWethAmount = 1;\n        {\n            // All possible price moves\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), type(uint256).max);\n            IERC20(weth).approve(address(swapRouter), type(uint256).max);\n            IERC20(wPowerPerp).approve(address(swapRouter), type(uint256).max);\n            IWETH9(weth).deposit{ value: sellWethBuyWPowerPerpAmount }();\n            IWETH9(weth).deposit{ value: sellWethBuyUsdcAmount }();\n            IERC20(wPowerPerp).approve(address(auctionBull), type(uint256).max);\n\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellUsdcBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: usdc,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyUsdcAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyWPowerPerpAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: wPowerPerp,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWPowerPerpAmountBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.mul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            (targetDebt < currentDebt) ? ethUsdPrice.wmul(8e17) : ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), targetWethInLeverage\n        );\n        assertTrue(isDepositingInCrab);\n        assertLt(currentWethInLeverage, initialWethInLeverage);\n        assertLt(initialDebt, currentDebt);\n        if (isDepositingInCrab) {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.add(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.add(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n            assertEq(squeethInCrab.add(wPowerPerpAmountToTrade), squeethInCrabAfter);\n        } else {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.sub(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.add(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.sub(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n        }\n    }\n\n    function testFullRebalanceDepositCrabIncreaseEthBorrowUsdc() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        initialDebt = currentDebt;\n        initialWethInLeverage = currentWethInLeverage;\n        uint256 sellUsdcBuyWethAmount = 30000000e6;\n        uint256 sellWethBuyWPowerPerpAmount = 1;\n        uint256 sellWethBuyUsdcAmount = 200e18;\n        uint256 sellWPowerPerpAmountBuyWethAmount = 1;\n        {\n            // All possible price moves\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), type(uint256).max);\n            IERC20(weth).approve(address(swapRouter), type(uint256).max);\n            IERC20(wPowerPerp).approve(address(swapRouter), type(uint256).max);\n            IWETH9(weth).deposit{ value: sellWethBuyWPowerPerpAmount }();\n            IWETH9(weth).deposit{ value: sellWethBuyUsdcAmount }();\n            IERC20(wPowerPerp).approve(address(auctionBull), type(uint256).max);\n\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellUsdcBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: usdc,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyUsdcAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyWPowerPerpAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: wPowerPerp,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWPowerPerpAmountBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        {\n            (uint256 delta, uint256 cr) = auctionBull.getCurrentDeltaAndCollatRatio();\n            console.log(\"delta and cr before\", delta, cr);\n        }\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.mul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            (targetDebt < currentDebt) ? ethUsdPrice.wmul(8e17) : ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), targetWethInLeverage\n        );\n        assertTrue(isDepositingInCrab);\n        assertLt(initialWethInLeverage, currentWethInLeverage);\n        assertLt(initialDebt, currentDebt);\n        if (isDepositingInCrab) {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.add(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.add(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n            assertEq(squeethInCrab.add(wPowerPerpAmountToTrade), squeethInCrabAfter);\n        } else {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.sub(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.add(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.sub(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n        }\n    }\n\n    function testFullFullRebalanceWithdrawCrabIncreaseEthRepayUsdc() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        initialDebt = currentDebt;\n        initialWethInLeverage = currentWethInLeverage;\n        uint256 sellUsdcBuyWethAmount = 1;\n        uint256 sellWethBuyWPowerPerpAmount = 1;\n        uint256 sellWethBuyUsdcAmount = 200e18;\n        uint256 sellWPowerPerpAmountBuyWethAmount = 200e18;\n        {\n            // All possible price moves\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), type(uint256).max);\n            IERC20(weth).approve(address(swapRouter), type(uint256).max);\n            IERC20(wPowerPerp).approve(address(swapRouter), type(uint256).max);\n            IWETH9(weth).deposit{ value: sellWethBuyWPowerPerpAmount }();\n            IWETH9(weth).deposit{ value: sellWethBuyUsdcAmount }();\n            IERC20(wPowerPerp).approve(address(auctionBull), type(uint256).max);\n\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellUsdcBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: usdc,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyUsdcAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWethBuyWPowerPerpAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: wPowerPerp,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: sellWPowerPerpAmountBuyWethAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: isDepositingInCrab ? type(uint256).max : 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.mul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            (targetDebt < currentDebt) ? ethUsdPrice.wmul(8e17) : ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertApproxEqRel(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), targetWethInLeverage, 1\n        );\n        assertTrue(!isDepositingInCrab);\n        assertLt(initialWethInLeverage, currentWethInLeverage);\n        assertLt(currentDebt, initialDebt);\n        if (isDepositingInCrab) {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.add(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.add(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n            assertEq(squeethInCrab.add(wPowerPerpAmountToTrade), squeethInCrabAfter);\n        } else {\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.sub(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.add(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.sub(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n        }\n    }\n\n    function testFullRebalanceWhenEthDownAndDeltaTooLow() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 6000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 6000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        crabAmount = crabAmount.mul(0);\n\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(isDepositingInCrab, false);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB1\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage.mul(85).div(100),\n            ethUsdPrice.wmul(8e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function testFullRebalanceWhenEthUpMultipleOrders() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.div(2),\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.div(2),\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user2,\n                quantity: wPowerPerpAmountToTrade.sub(wPowerPerpAmountToTrade.div(2)),\n                price: type(uint256).max - 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user2Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user2,\n                quantity: wPowerPerpAmountToTrade.sub(wPowerPerpAmountToTrade.div(2)),\n                price: type(uint256).max - 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.wmul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        vm.prank(user2);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.wmul(squeethEthPrice));\n        user2WPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        user2WethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), targetWethInLeverage\n        );\n        assertEq(\n            userWPowerPerpBalanceBeforeAuction.add(wPowerPerpAmountToTrade.div(2)),\n            IERC20(wPowerPerp).balanceOf(user1)\n        );\n        assertEq(\n            userWethBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.div(2).wmul(squeethEthPrice)),\n            IERC20(weth).balanceOf(user1)\n        );\n        assertEq(\n            user2WPowerPerpBalanceBeforeAuction.add(\n                wPowerPerpAmountToTrade.sub(wPowerPerpAmountToTrade.div(2))\n            ),\n            IERC20(wPowerPerp).balanceOf(user1)\n        );\n        assertEq(\n            user2WethBalanceBeforeAuction.sub(\n                wPowerPerpAmountToTrade.sub(wPowerPerpAmountToTrade.div(2)).wmul(squeethEthPrice)\n            ),\n            IERC20(weth).balanceOf(user1)\n        );\n        assertApproxEqRel(\n            bullCrabBalanceBefore.add(crabAmount),\n            IERC20(crabV2).balanceOf(address(bullStrategy)),\n            1e5\n        );\n        assertEq(squeethInCrab.add(wPowerPerpAmountToTrade), squeethInCrabAfter);\n    }\n\n    function testFullRebalanceWhenEthUpMultipleOrdersPartialFill() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        {\n            // move prices up\n            vm.startPrank(user1);\n            IERC20(usdc).approve(address(swapRouter), 30000000e6);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: usdc,\n                    tokenOut: weth,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 30000000e6,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            IWETH9(weth).deposit{ value: 200e18 }();\n            IERC20(weth).approve(address(swapRouter), 200e18);\n            swapRouter.exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: weth,\n                    tokenOut: wPowerPerp,\n                    fee: uint24(3000),\n                    recipient: msg.sender,\n                    deadline: block.timestamp,\n                    amountIn: 200e18,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            vm.stopPrank();\n            vm.warp(block.timestamp + 1000);\n        }\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, true);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.div(2),\n                price: type(uint256).max - 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.div(2),\n                price: type(uint256).max - 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user2,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max - 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user2Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user2,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max - 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(user1);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.wmul(squeethEthPrice));\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        vm.prank(user2);\n        IERC20(weth).approve(address(auctionBull), wPowerPerpAmountToTrade.wmul(squeethEthPrice));\n        user2WPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        user2WethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), targetWethInLeverage\n        );\n        assertEq(\n            userWPowerPerpBalanceBeforeAuction.add(wPowerPerpAmountToTrade.div(2)),\n            IERC20(wPowerPerp).balanceOf(user1)\n        );\n        assertEq(\n            userWethBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.div(2).wmul(squeethEthPrice)),\n            IERC20(weth).balanceOf(user1)\n        );\n        assertEq(\n            user2WPowerPerpBalanceBeforeAuction.add(\n                wPowerPerpAmountToTrade.sub(wPowerPerpAmountToTrade.div(2))\n            ),\n            IERC20(wPowerPerp).balanceOf(user1)\n        );\n        assertEq(\n            user2WethBalanceBeforeAuction.sub(\n                wPowerPerpAmountToTrade.sub(wPowerPerpAmountToTrade.div(2)).wmul(squeethEthPrice)\n            ),\n            IERC20(weth).balanceOf(user1)\n        );\n        assertApproxEqRel(\n            bullCrabBalanceBefore.add(crabAmount),\n            IERC20(crabV2).balanceOf(address(bullStrategy)),\n            1e5\n        );\n        assertEq(squeethInCrab.add(wPowerPerpAmountToTrade), squeethInCrabAfter);\n    }\n\n    function testFullRebalanceWhenEthDownMultipleOrdersPartialFill() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 6000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 6000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, false);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.div(2),\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade.div(2),\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user2,\n                quantity: wPowerPerpAmountToTrade,\n                price: 2,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user2Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user2,\n                quantity: wPowerPerpAmountToTrade,\n                price: 2,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), type(uint256).max);\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        vm.prank(user2);\n        IERC20(wPowerPerp).approve(address(auctionBull), type(uint256).max);\n        user2WPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        user2WethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n\n        (, uint256 squeethInCrabAfter) = _getCrabVaultDetails();\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), targetWethInLeverage\n        );\n        assertEq(\n            userWPowerPerpBalanceBeforeAuction.sub(wPowerPerpAmountToTrade.div(2)),\n            IERC20(wPowerPerp).balanceOf(user1)\n        );\n        assertEq(\n            userWethBalanceBeforeAuction.add(wPowerPerpAmountToTrade.div(2).wmul(squeethEthPrice)),\n            IERC20(weth).balanceOf(user1)\n        );\n        assertEq(\n            user2WPowerPerpBalanceBeforeAuction.sub(\n                wPowerPerpAmountToTrade.sub(wPowerPerpAmountToTrade.div(2))\n            ),\n            IERC20(wPowerPerp).balanceOf(user1)\n        );\n        assertEq(\n            user2WethBalanceBeforeAuction.add(\n                wPowerPerpAmountToTrade.sub(wPowerPerpAmountToTrade.div(2)).wmul(squeethEthPrice)\n            ),\n            IERC20(weth).balanceOf(user1)\n        );\n        //crab amount entered in fullRebalance is only an estimate and the real value is updated when crab tokens are transferred in\n        assertApproxEqRel(\n            bullCrabBalanceBefore.sub(crabAmount),\n            IERC20(crabV2).balanceOf(address(bullStrategy)),\n            1e5\n        );\n        assertEq(squeethInCrab.sub(wPowerPerpAmountToTrade), squeethInCrabAfter);\n    }\n\n    function testFullRebalanceWhenEthDown() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 6000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 6000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        assertEq(isDepositingInCrab, false);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: 1,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(auctionManager);\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n        {\n            currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n            currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n            assertEq(\n                IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)),\n                targetWethInLeverage\n            );\n            assertEq(\n                userWPowerPerpBalanceBeforeAuction.sub(wPowerPerpAmountToTrade),\n                IERC20(wPowerPerp).balanceOf(user1)\n            );\n            assertEq(\n                userWethBalanceBeforeAuction.add(wPowerPerpAmountToTrade.wmul(squeethEthPrice)),\n                IERC20(weth).balanceOf(user1)\n            );\n            assertApproxEqRel(\n                bullCrabBalanceBefore.sub(crabAmount),\n                IERC20(crabV2).balanceOf(address(bullStrategy)),\n                1e5\n            );\n        }\n    }\n\n    function testFullRebalanceWhenSellOrderAboveClearingPrice() public {\n        currentDebt = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        currentWethInLeverage = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 6000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 6000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        (targetWethInLeverage, targetDebt) = _calcTargetCollateralAndDebtInLeverage();\n        (uint256 crabAmount, bool isDepositingInCrab) = _calcCrabAmountToTrade(\n            currentWethInLeverage, currentDebt, targetWethInLeverage, targetDebt, ethUsdPrice\n        );\n\n        assertEq(isDepositingInCrab, false);\n\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 wPowerPerpAmountToTrade =\n            _calcWPowerPerpAmountFromCrab(isDepositingInCrab, crabAmount, ethInCrab, squeethInCrab);\n\n        {\n            // trader signature vars\n            uint8 v;\n            bytes32 r;\n            bytes32 s;\n            // trader signing bid\n            SigUtil.Order memory orderSig = SigUtil.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0\n            });\n            bytes32 bidDigest = sigUtil.getTypedDataHash(orderSig);\n            (v, r, s) = vm.sign(user1Pk, bidDigest);\n            ZenAuction.Order memory orderData = ZenAuction.Order({\n                bidId: 1,\n                trader: user1,\n                quantity: wPowerPerpAmountToTrade,\n                price: type(uint256).max,\n                isBuying: isDepositingInCrab,\n                expiry: block.timestamp + 1000,\n                nonce: 0,\n                v: v,\n                r: r,\n                s: s\n            });\n            orders.push(orderData);\n        }\n\n        vm.prank(user1);\n        IERC20(wPowerPerp).approve(address(auctionBull), wPowerPerpAmountToTrade);\n        userWPowerPerpBalanceBeforeAuction = IERC20(wPowerPerp).balanceOf(user1);\n        userWethBalanceBeforeAuction = IERC20(weth).balanceOf(user1);\n\n        squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        vm.prank(auctionManager);\n        vm.expectRevert(bytes(\"AB10\"));\n        auctionBull.fullRebalance(\n            orders,\n            crabAmount,\n            squeethEthPrice,\n            targetWethInLeverage,\n            ethUsdPrice.wmul(12e17),\n            3000,\n            isDepositingInCrab\n        );\n    }\n\n    function _calcCrabAmountToTrade(\n        uint256 _currentWethInLeverage,\n        uint256 _currentDebt,\n        uint256 _targetWeth,\n        uint256 _targetDebt,\n        uint256 _ethUsdPrice\n    ) internal view returns (uint256, bool) {\n        (uint256 wethDeltaInDollar, bool isWethDeltaInDollarPositive) = (\n            _targetWeth > _currentWethInLeverage\n        )\n            ? (_targetWeth.sub(_currentWethInLeverage).wmul(_ethUsdPrice), false)\n            : (_currentWethInLeverage.sub(_targetWeth).wmul(_ethUsdPrice), true);\n        (uint256 debtDeltaInDollar, bool isDebtDeltaInDollarPositive) = (_targetDebt > _currentDebt)\n            ? (_targetDebt.sub(_currentDebt), false)\n            : (_currentDebt.sub(_targetDebt), true);\n        wethDeltaInDollar = wethDeltaInDollar.div(WETH_DECIMALS_DIFF);\n        bool isDepositingInCrab;\n        uint256 dollarToExchangeWithCrab;\n\n        if (isDebtDeltaInDollarPositive) {\n            if (isWethDeltaInDollarPositive) {\n                (dollarToExchangeWithCrab, isDepositingInCrab) = (\n                    debtDeltaInDollar > wethDeltaInDollar\n                )\n                    ? (debtDeltaInDollar.sub(wethDeltaInDollar), false)\n                    : (wethDeltaInDollar.sub(debtDeltaInDollar), true);\n            } else {\n                (dollarToExchangeWithCrab, isDepositingInCrab) =\n                    (debtDeltaInDollar.add(wethDeltaInDollar), false);\n            }\n        } else {\n            if (!isWethDeltaInDollarPositive) {\n                (dollarToExchangeWithCrab, isDepositingInCrab) = (\n                    debtDeltaInDollar > wethDeltaInDollar\n                )\n                    ? (debtDeltaInDollar.sub(wethDeltaInDollar), true)\n                    : (wethDeltaInDollar.sub(debtDeltaInDollar), false);\n            } else {\n                (dollarToExchangeWithCrab, isDepositingInCrab) =\n                    (debtDeltaInDollar.add(wethDeltaInDollar), true);\n            }\n        }\n        uint256 crabAmount =\n            dollarToExchangeWithCrab.mul(WETH_DECIMALS_DIFF).wdiv(testUtil.getCrabPrice());\n\n        return (crabAmount, isDepositingInCrab);\n    }\n\n    function _calcWPowerPerpAmountFromCrab(\n        bool _isDepositingInCrab,\n        uint256 _crabAmount,\n        uint256 _ethInCrab,\n        uint256 _squeethInCrab\n    ) internal view returns (uint256) {\n        uint256 wPowerPerpAmount;\n        if (_isDepositingInCrab) {\n            uint256 ethToDepositInCrab =\n                _crabAmount.wdiv(IERC20(crabV2).totalSupply()).wmul(_ethInCrab);\n            (wPowerPerpAmount,) =\n                _calcWsqueethToMintAndFee(ethToDepositInCrab, _squeethInCrab, _ethInCrab);\n        } else {\n            wPowerPerpAmount = _crabAmount.wmul(_squeethInCrab).wdiv(IERC20(crabV2).totalSupply());\n        }\n\n        return wPowerPerpAmount;\n    }\n\n    function testLeverageRebalanceWhenEthUp() public {\n        uint256 usdcDebtBefore = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        uint256 ethBalanceBefore = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n\n        // move prices up\n        vm.startPrank(user1);\n        IERC20(usdc).approve(address(swapRouter), 10000000e6);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: usdc,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000000e6,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IWETH9(weth).deposit{ value: 100e18 }();\n        IERC20(weth).approve(address(swapRouter), 100e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: wPowerPerp,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 100e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        (uint256 deltaBeforeRebalance, uint256 crBeforeRebalance) =\n            auctionBull.getCurrentDeltaAndCollatRatio();\n\n        uint256 crabPrice = testUtil.getCrabPrice();\n        uint256 usdcDebtTarget =\n            crabPrice.wmul(IERC20(crabV2).balanceOf(address(bullStrategy))).div(WETH_DECIMALS_DIFF);\n        bool isSellingUsdc =\n            (usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))) ? true : false;\n\n        assertEq(isSellingUsdc, true);\n\n        uint256 usdcAmount = (\n            usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))\n        )\n            ? usdcDebtTarget.sub(IEulerDToken(dToken).balanceOf(address(bullStrategy)))\n            : IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcDebtTarget);\n        uint256 minEthForUsdc = quoter.quoteExactInputSingle(usdc, weth, 3000, usdcAmount, 0);\n        uint256 limitPrice = usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(minEthForUsdc);\n        vm.startPrank(auctionManager);\n        auctionBull.leverageRebalance(isSellingUsdc, usdcAmount, limitPrice, 3000);\n        vm.stopPrank();\n\n        (uint256 deltaAfterRebalance, uint256 crAfterRebalance) =\n            auctionBull.getCurrentDeltaAndCollatRatio();\n\n        assertApproxEqAbs(\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)),\n            usdcDebtBefore.add(usdcAmount),\n            1e6\n        );\n        assertGt(deltaAfterRebalance, deltaBeforeRebalance);\n        assertLt(crAfterRebalance, crBeforeRebalance);\n        assertTrue(\n            ethBalanceBefore.add(minEthForUsdc)\n                <= IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy))\n        );\n    }\n\n    function testLeverageRebalanceWhenEthUpWhenDeltaTooHighAfterTrade() public {\n        // move prices up\n        vm.startPrank(user1);\n        IERC20(usdc).approve(address(swapRouter), 10000000e6);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: usdc,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000000e6,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IWETH9(weth).deposit{ value: 100e18 }();\n        IERC20(weth).approve(address(swapRouter), 100e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: wPowerPerp,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 100e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        uint256 crabPrice = testUtil.getCrabPrice();\n        uint256 usdcDebtTarget =\n            crabPrice.wmul(IERC20(crabV2).balanceOf(address(bullStrategy))).div(WETH_DECIMALS_DIFF);\n        bool isSellingUsdc =\n            (usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))) ? true : false;\n\n        assertEq(isSellingUsdc, true);\n\n        uint256 usdcAmountCorrect = (\n            usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))\n        )\n            ? usdcDebtTarget.sub(IEulerDToken(dToken).balanceOf(address(bullStrategy)))\n            : IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcDebtTarget);\n        uint256 usdcAmount = usdcAmountCorrect.mul(12);\n        uint256 minEthForUsdc = quoter.quoteExactInputSingle(usdc, weth, 3000, usdcAmount, 0);\n        uint256 limitPrice = usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(minEthForUsdc);\n        vm.startPrank(auctionManager);\n        vm.expectRevert(bytes(\"AB1\"));\n        auctionBull.leverageRebalance(isSellingUsdc, usdcAmount, limitPrice, 3000);\n        vm.stopPrank();\n    }\n\n    function testLeverageRebalanceWhenEthDownWhenDeltaTooLowAfterTrade() public {\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 900e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 900e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        uint256 crabPrice = testUtil.getCrabPrice();\n        uint256 usdcDebtTarget =\n            crabPrice.wmul(IERC20(crabV2).balanceOf(address(bullStrategy))).div(WETH_DECIMALS_DIFF);\n        bool isSellingUsdc =\n            (usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))) ? true : false;\n\n        assertEq(isSellingUsdc, false);\n\n        uint256 usdcAmountCorrect = (\n            usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))\n        )\n            ? usdcDebtTarget.sub(IEulerDToken(dToken).balanceOf(address(bullStrategy)))\n            : IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcDebtTarget);\n        uint256 usdcAmount = usdcAmountCorrect.mul(10);\n        uint256 maxEthForUsdc = quoter.quoteExactOutputSingle(weth, usdc, 3000, usdcAmount, 0);\n        uint256 limitPrice = usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(maxEthForUsdc);\n\n        vm.startPrank(auctionManager);\n        vm.expectRevert(bytes(\"AB1\"));\n        auctionBull.leverageRebalance(isSellingUsdc, usdcAmount, limitPrice, 3000);\n        vm.stopPrank();\n    }\n\n    function testLeverageRebalanceWhenEthUpWhenCrTooHighAfterTrade() public {\n        // move prices up\n        vm.startPrank(user1);\n        IERC20(usdc).approve(address(swapRouter), 10000000e6);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: usdc,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000000e6,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IWETH9(weth).deposit{ value: 100e18 }();\n        IERC20(weth).approve(address(swapRouter), 100e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: wPowerPerp,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 100e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        uint256 crabPrice = testUtil.getCrabPrice();\n        uint256 usdcDebtTarget =\n            crabPrice.wmul(IERC20(crabV2).balanceOf(address(bullStrategy))).div(WETH_DECIMALS_DIFF);\n        bool isSellingUsdc =\n            (usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))) ? true : false;\n\n        assertEq(isSellingUsdc, true);\n\n        uint256 usdcAmountCorrect = (\n            usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))\n        )\n            ? usdcDebtTarget.sub(IEulerDToken(dToken).balanceOf(address(bullStrategy)))\n            : IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcDebtTarget);\n        uint256 usdcAmount = usdcAmountCorrect.mul(7);\n        uint256 minEthForUsdc = quoter.quoteExactOutputSingle(weth, usdc, 3000, usdcAmount, 0);\n        uint256 limitPrice = usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(minEthForUsdc);\n        vm.startPrank(auctionManager);\n        vm.expectRevert(bytes(\"AB2\"));\n        auctionBull.leverageRebalance(!isSellingUsdc, usdcAmount, limitPrice, 3000);\n        vm.stopPrank();\n    }\n\n    function testLeverageRebalanceWhenEthDownWhenCrTooLowAfterTrade() public {\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 900e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 900e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        uint256 crabPrice = testUtil.getCrabPrice();\n        uint256 usdcDebtTarget =\n            crabPrice.wmul(IERC20(crabV2).balanceOf(address(bullStrategy))).div(WETH_DECIMALS_DIFF);\n        bool isSellingUsdc =\n            (usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))) ? true : false;\n\n        assertEq(isSellingUsdc, false);\n\n        uint256 usdcAmountCorrect = (\n            usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))\n        )\n            ? usdcDebtTarget.sub(IEulerDToken(dToken).balanceOf(address(bullStrategy)))\n            : IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcDebtTarget);\n        uint256 usdcAmount = usdcAmountCorrect.mul(3);\n        uint256 maxEthForUsdc = quoter.quoteExactInputSingle(usdc, weth, 3000, usdcAmount, 0);\n        uint256 limitPrice = usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(maxEthForUsdc);\n        vm.startPrank(auctionManager);\n        vm.expectRevert(bytes(\"AB2\"));\n        auctionBull.leverageRebalance(!isSellingUsdc, usdcAmount, limitPrice, 3000);\n        vm.stopPrank();\n    }\n\n    function testLeverageRebalanceWhenEthUpEthLimitTooHigh() public {\n        // move prices up\n        vm.startPrank(user1);\n        IERC20(usdc).approve(address(swapRouter), 10000000e6);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: usdc,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000000e6,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IWETH9(weth).deposit{ value: 100e18 }();\n        IERC20(weth).approve(address(swapRouter), 100e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: wPowerPerp,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 100e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        uint256 crabPrice = testUtil.getCrabPrice();\n        uint256 usdcDebtTarget =\n            crabPrice.wmul(IERC20(crabV2).balanceOf(address(bullStrategy))).div(WETH_DECIMALS_DIFF);\n        bool isSellingUsdc =\n            (usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))) ? true : false;\n\n        assertEq(isSellingUsdc, true);\n\n        uint256 usdcAmount = (\n            usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))\n        )\n            ? usdcDebtTarget.sub(IEulerDToken(dToken).balanceOf(address(bullStrategy)))\n            : IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcDebtTarget);\n        uint256 minEthForUsdc = quoter.quoteExactInputSingle(usdc, weth, 3000, usdcAmount, 0);\n        uint256 limitPrice = usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(minEthForUsdc);\n        vm.startPrank(auctionManager);\n        vm.expectRevert(bytes(\"AB15\"));\n        auctionBull.leverageRebalance(isSellingUsdc, usdcAmount, limitPrice.wmul(1.25e18), 3000);\n        vm.stopPrank();\n    }\n\n    function testLeverageRebalanceWhenEthDownEthLimitTooLow() public {\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 900e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 900e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        uint256 crabPrice = testUtil.getCrabPrice();\n        uint256 usdcDebtTarget =\n            crabPrice.wmul(IERC20(crabV2).balanceOf(address(bullStrategy))).div(WETH_DECIMALS_DIFF);\n        bool isSellingUsdc =\n            (usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))) ? true : false;\n\n        assertEq(isSellingUsdc, false);\n\n        uint256 usdcAmount = (\n            usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))\n        )\n            ? usdcDebtTarget.sub(IEulerDToken(dToken).balanceOf(address(bullStrategy)))\n            : IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcDebtTarget);\n        uint256 maxEthForUsdc = quoter.quoteExactOutputSingle(weth, usdc, 3000, usdcAmount, 0);\n        uint256 limitPrice = usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(maxEthForUsdc);\n\n        vm.startPrank(auctionManager);\n        vm.expectRevert(bytes(\"AB15\"));\n        auctionBull.leverageRebalance(isSellingUsdc, usdcAmount, limitPrice.wmul(0.75e18), 3000);\n        vm.stopPrank();\n    }\n\n    function testLeverageRebalanceWhenEthDown() public {\n        // move prices down\n        vm.startPrank(user1);\n        IWETH9(weth).deposit{ value: 10000e18 }();\n        IERC20(weth).approve(address(swapRouter), 10000e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: weth,\n                tokenOut: usdc,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 10000e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        IERC20(wPowerPerp).approve(address(swapRouter), 900e18);\n        swapRouter.exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: wPowerPerp,\n                tokenOut: weth,\n                fee: uint24(3000),\n                recipient: msg.sender,\n                deadline: block.timestamp,\n                amountIn: 900e18,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n        vm.stopPrank();\n        vm.warp(block.timestamp + 1000);\n\n        (uint256 deltaBeforeRebalance, uint256 crBeforeRebalance) =\n            auctionBull.getCurrentDeltaAndCollatRatio();\n        uint256 crabPrice = testUtil.getCrabPrice();\n        uint256 usdcDebtTarget =\n            crabPrice.wmul(IERC20(crabV2).balanceOf(address(bullStrategy))).div(WETH_DECIMALS_DIFF);\n        bool isSellingUsdc =\n            (usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))) ? true : false;\n\n        assertEq(isSellingUsdc, false);\n\n        uint256 usdcAmount = (\n            usdcDebtTarget > IEulerDToken(dToken).balanceOf(address(bullStrategy))\n        )\n            ? usdcDebtTarget.sub(IEulerDToken(dToken).balanceOf(address(bullStrategy)))\n            : IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcDebtTarget);\n        uint256 maxEthForUsdc = quoter.quoteExactOutputSingle(weth, usdc, 3000, usdcAmount, 0);\n        uint256 limitPrice = usdcAmount.mul(WETH_DECIMALS_DIFF).wdiv(maxEthForUsdc);\n        uint256 usdcDebtBefore = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        uint256 ethBalanceBefore = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        vm.startPrank(auctionManager);\n        auctionBull.leverageRebalance(isSellingUsdc, usdcAmount, limitPrice, 3000);\n        vm.stopPrank();\n\n        (uint256 deltaAfterRebalance, uint256 crAfterRebalance) =\n            auctionBull.getCurrentDeltaAndCollatRatio();\n\n        assertApproxEqAbs(\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)),\n            usdcDebtBefore.sub(usdcAmount),\n            1e6\n        );\n        assertLt(deltaAfterRebalance, deltaBeforeRebalance);\n        assertGt(crAfterRebalance, crBeforeRebalance);\n        assertApproxEqAbs(\n            ethBalanceBefore.sub(maxEthForUsdc),\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)),\n            1\n        );\n    }\n\n    // Helper functions\n    function _getCrabVaultDetails() internal view returns (uint256, uint256) {\n        VaultLib.Vault memory strategyVault =\n            IController(address(controller)).vaults(crabV2.vaultId());\n\n        return (strategyVault.collateralAmount, strategyVault.shortAmount);\n    }\n\n    function calcTotalEthToBull(\n        uint256 wethToLend,\n        uint256 ethToCrab,\n        uint256 usdcToBorrow,\n        uint256 wSqueethToMint\n    ) internal view returns (uint256) {\n        uint256 totalEthToBull = wethToLend.add(ethToCrab).sub(usdcToBorrow.wdiv(ethPrice())).sub(\n            wSqueethToMint.wmul(squeethPrice())\n        ).add(1e16);\n        return totalEthToBull;\n    }\n\n    /**\n     * @dev calculate amount of strategy token to mint for depositor\n     * @param _amount amount of ETH deposited\n     * @param _strategyCollateralAmount amount of strategy collateral\n     * @param _crabTotalSupply total supply of strategy token\n     * @return amount of strategy token to mint\n     */\n    function _calcSharesToMint(\n        uint256 _amount,\n        uint256 _strategyCollateralAmount,\n        uint256 _crabTotalSupply\n    ) internal pure returns (uint256) {\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\n\n        if (_crabTotalSupply != 0) {\n            return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\n        }\n\n        return _amount;\n    }\n\n    function _calcWsqueethToMintAndFee(\n        uint256 _depositedAmount,\n        uint256 _strategyDebtAmount,\n        uint256 _strategyCollateralAmount\n    ) internal view returns (uint256, uint256) {\n        uint256 wSqueethToMint;\n        uint256 wSqueethEthPrice = squeethPrice();\n        uint256 feeRate = IController(bullStrategy.powerTokenController()).feeRate();\n        uint256 feeAdjustment = wSqueethEthPrice.mul(feeRate).div(10000);\n\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\n        );\n\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\n\n        return (wSqueethToMint, fee);\n    }\n\n    function squeethPrice() internal view returns (uint256) {\n        return UniOracle._getTwap(ethWSqueethPool, wPowerPerp, weth, TWAP, false);\n    }\n\n    function ethPrice() internal view returns (uint256) {\n        return UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n    }\n\n    function _initateDepositInBull() internal {\n        // Put some money in bull to start with\n        uint256 ethToCrab = 5e18;\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        (uint256 wSqueethToMint, uint256 fee) =\n            _calcWsqueethToMintAndFee(ethToCrab, squeethInCrab, ethInCrab);\n        uint256 crabToBeMinted =\n            _calcSharesToMint(ethToCrab.sub(fee), ethInCrab, IERC20(crabV2).totalSupply());\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        uint256 bullShare = 1e18;\n        (uint256 wethToLend, uint256 usdcToBorrow) = bullStrategy.calcLeverageEthUsdc(\n            crabToBeMinted, bullShare, ethInCrab, squeethInCrab, crabV2.totalSupply()\n        );\n\n        uint256 totalEthToBull =\n            calcTotalEthToBull(wethToLend, ethToCrab, usdcToBorrow, wSqueethToMint);\n\n        FlashZen.FlashDepositParams memory params = FlashZen.FlashDepositParams({\n            ethToCrab: ethToCrab,\n            minEthFromSqth: 0,\n            minEthFromUsdc: 0,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(user1);\n        flashBull.flashDeposit{ value: totalEthToBull }(params);\n        vm.stopPrank();\n\n        assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n        assertApproxEqAbs(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), wethToLend, 1\n        );\n        assertEq(bullStrategy.getCrabBalance().sub(crabToBeMinted), bullCrabBalanceBefore);\n    }\n\n    function _calcTargetCollateralAndDebtInLeverage() internal view returns (uint256, uint256) {\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            1,\n            false\n        );\n\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        (uint256 ethInCrab, uint256 squeethInCrab) = _getCrabVaultDetails();\n        uint256 crabUsdPrice = (\n            ethInCrab.wmul(ethUsdPrice).sub(squeethInCrab.wmul(squeethEthPrice).wmul(ethUsdPrice))\n        ).wdiv(crabV2.totalSupply());\n        uint256 equityValue = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)).wmul(\n            ethUsdPrice\n        ).add(IERC20(crabV2).balanceOf(address(bullStrategy)).wmul(crabUsdPrice)).sub(\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)).mul(WETH_DECIMALS_DIFF)\n        );\n        uint256 targetCollateral = equityValue.wdiv(ethUsdPrice);\n        uint256 _targetDebt = targetCollateral.wmul(ethUsdPrice).wdiv(bullStrategy.TARGET_CR()).div(\n            WETH_DECIMALS_DIFF\n        );\n        return (targetCollateral, _targetDebt);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/integration-test/ZenBullStrategyTestFork.t.sol",
    "content": "pragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IEulerMarkets } from \"../../src/interface/IEulerMarkets.sol\";\nimport { IEulerEToken } from \"../../src/interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"../../src/interface/IEulerDToken.sol\";\n// contract\nimport { SwapRouter } from \"v3-periphery/SwapRouter.sol\";\nimport { Quoter } from \"v3-periphery/lens/Quoter.sol\";\nimport { TestUtil } from \"../util/TestUtil.t.sol\";\nimport { ZenBullStrategy } from \"../../src/ZenBullStrategy.sol\";\nimport { CrabStrategyV2 } from \"squeeth-monorepo/strategy/CrabStrategyV2.sol\";\nimport { Controller } from \"squeeth-monorepo/core/Controller.sol\";\nimport { ZenEmergencyShutdown } from \"../../src/ZenEmergencyShutdown.sol\";\nimport { Quoter } from \"v3-periphery/lens/Quoter.sol\";\n// lib\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\nimport { UniOracle } from \"../../src/UniOracle.sol\";\n\n/**\n * @notice Ropsten fork testing\n */\ncontract ZenBullStrategyTestFork is Test {\n    using StrategyMath for uint256;\n\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n\n    TestUtil internal testUtil;\n    ZenBullStrategy internal bullStrategy;\n    CrabStrategyV2 internal crabV2;\n    Controller internal controller;\n    ZenEmergencyShutdown internal emergencyShutdown;\n    Quoter internal quoter;\n\n    uint256 internal bullOwnerPk;\n    uint256 internal deployerPk;\n    uint256 internal user1Pk;\n    uint256 internal ownerPk;\n    address internal user1;\n    address internal owner;\n    address internal deployer;\n    address internal bullOwner;\n\n    address internal weth;\n    address internal usdc;\n    address internal euler;\n    address internal eulerMarketsModule;\n    address internal eToken;\n    address internal dToken;\n    address internal wPowerPerp;\n    uint256 internal cap;\n\n    function setUp() public {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 15781550);\n\n        deployerPk = 0xA11CD;\n        deployer = vm.addr(deployerPk);\n        bullOwnerPk = 0xB11CD;\n        bullOwner = vm.addr(bullOwnerPk);\n\n        vm.startPrank(deployer);\n        quoter = Quoter(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);\n\n        euler = 0x27182842E098f60e3D576794A5bFFb0777E025d3;\n        eulerMarketsModule = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3;\n        controller = Controller(0x64187ae08781B09368e6253F9E94951243A493D5);\n        crabV2 = CrabStrategyV2(0x3B960E47784150F5a63777201ee2B15253D713e8);\n        bullStrategy =\n            new ZenBullStrategy(address(crabV2), address(controller), euler, eulerMarketsModule);\n        bullStrategy.transferOwnership(bullOwner);\n        usdc = controller.quoteCurrency();\n        weth = controller.weth();\n        eToken = IEulerMarkets(eulerMarketsModule).underlyingToEToken(weth);\n        dToken = IEulerMarkets(eulerMarketsModule).underlyingToDToken(usdc);\n        wPowerPerp = controller.wPowerPerp();\n        quoter = Quoter(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);\n        emergencyShutdown =\n        new ZenEmergencyShutdown(address(bullStrategy), 0x1F98431c8aD98523631AE4a59f267346ea31F984);\n        emergencyShutdown.transferOwnership(bullOwner);\n\n        testUtil =\n        new TestUtil(address(bullStrategy), address (controller), eToken, dToken, address(crabV2));\n\n        vm.stopPrank();\n\n        cap = 100000e18;\n        vm.startPrank(bullOwner);\n        bullStrategy.setCap(cap);\n        bullStrategy.setShutdownContract(address(emergencyShutdown));\n        vm.stopPrank();\n        user1Pk = 0xA11CE;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User 1\");\n        vm.label(address(bullStrategy), \"BullStrategy\");\n        vm.label(euler, \"Euler\");\n        vm.label(eulerMarketsModule, \"EulerMarkets\");\n        vm.label(usdc, \"USDC\");\n        vm.label(weth, \"WETH\");\n        vm.label(wPowerPerp, \"oSQTH\");\n        vm.label(address(crabV2), \"crabV2\");\n\n        vm.deal(user1, 100000000e18);\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 100e18);\n        // some WETH and USDC rich address\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(weth).transfer(user1, 10000e18);\n    }\n\n    function testSetUpBullStrategy() public {\n        assertTrue(bullStrategy.owner() == bullOwner);\n        assertTrue(bullStrategy.strategyCap() == cap);\n        assertTrue(emergencyShutdown.owner() == bullOwner);\n        assertTrue(emergencyShutdown.bullStrategy() == address(bullStrategy));\n    }\n\n    function testSetAuctionZeroAddress() public {\n        vm.prank(bullOwner);\n        vm.expectRevert(bytes(\"LB2\"));\n        bullStrategy.setAuction(address(0));\n    }\n\n    function testSetAuctionWhenCallerNotOwner() public {\n        vm.prank(user1);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        bullStrategy.setAuction(address(1));\n    }\n\n    function testSetAuction() public {\n        vm.prank(bullOwner);\n        bullStrategy.setAuction(address(1));\n        assertEq(bullStrategy.auction(), address(1));\n    }\n\n    function testAuctionRepayAndWithdrawFromLeverageWhenCallerNotAuction() public {\n        vm.prank(bullOwner);\n        vm.expectRevert(bytes(\"LB1\"));\n        bullStrategy.auctionRepayAndWithdrawFromLeverage(0, 0);\n    }\n\n    function testdepositAndBorrowFromLeverageWhenCallerNotAuction() public {\n        vm.prank(bullOwner);\n        vm.expectRevert(bytes(\"LB1\"));\n        bullStrategy.depositAndBorrowFromLeverage(0, 0);\n    }\n\n    function testSetCap() public {\n        cap = 0;\n        vm.startPrank(bullOwner);\n        bullStrategy.setCap(cap);\n        assertEq(bullStrategy.strategyCap(), cap);\n    }\n\n    function testRedeemCrabAndWithdrawWEthWhenCallerNotOwner() public {\n        vm.startPrank(deployer);\n        vm.expectRevert(bytes(\"BS8\"));\n        bullStrategy.redeemCrabAndWithdrawWEth(0, 0);\n    }\n\n    function testDepositEthIntoCrabWhenCallerNotOwner() public {\n        vm.startPrank(deployer);\n        vm.expectRevert(bytes(\"BS8\"));\n        bullStrategy.depositEthIntoCrab(0);\n    }\n\n    function testSetCapWhenCallerNotOwner() public {\n        cap = 1000000e18;\n        vm.startPrank(deployer);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        bullStrategy.setCap(10e18);\n    }\n\n    function testDepositWhenCapFull() public {\n        vm.prank(bullOwner);\n        bullStrategy.setCap(1);\n\n        uint256 crabToDeposit = 1e18;\n        (uint256 wethToLend,) = testUtil.calcCollateralAndBorrowAmount(crabToDeposit);\n        vm.startPrank(user1);\n        IERC20(crabV2).approve(address(bullStrategy), crabToDeposit);\n        vm.expectRevert(bytes(\"BS2\"));\n        bullStrategy.deposit{ value: wethToLend }(crabToDeposit);\n        vm.stopPrank();\n    }\n\n    function testDepositWhenTotalSupplyLessThanMinimum() public {\n        uint256 crabToDeposit = WETH_DECIMALS_DIFF;\n        vm.startPrank(user1);\n        (uint256 wethToLend,) = testUtil.calcCollateralAndBorrowAmount(crabToDeposit);\n        IERC20(crabV2).approve(address(bullStrategy), crabToDeposit);\n        vm.expectRevert(bytes(\"BS9\"));\n        bullStrategy.deposit{ value: wethToLend }(crabToDeposit);\n        vm.stopPrank();\n    }\n\n    function testInitialDepositWithInsufficient() public {\n        uint256 crabToDeposit = 10e18;\n\n        vm.startPrank(user1);\n        (uint256 wethToLend,) = testUtil.calcCollateralAndBorrowAmount(crabToDeposit);\n        IERC20(crabV2).approve(address(bullStrategy), crabToDeposit);\n        vm.expectRevert(bytes(\"LB0\"));\n        // Deposit 1 ETH less than needed\n        bullStrategy.deposit{ value: wethToLend.sub(1e18) }(crabToDeposit);\n        vm.stopPrank();\n    }\n\n    function testInitialDepositWithRefund() public {\n        uint256 crabToDeposit = 10e18;\n        uint256 bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n        uint256 userEthBalanceBefore = address(user1).balance;\n\n        vm.startPrank(user1);\n        (uint256 wethToLend, uint256 usdcToBorrow) =\n            testUtil.calcCollateralAndBorrowAmount(crabToDeposit);\n        IERC20(crabV2).approve(address(bullStrategy), crabToDeposit);\n        // Deposit 1 ETH more than needed (will refund)\n        bullStrategy.deposit{ value: wethToLend.add(1e18) }(crabToDeposit);\n        vm.stopPrank();\n        uint256 userEthBalanceAfter = address(user1).balance;\n        uint256 bullCrabBalanceAfter = bullStrategy.getCrabBalance();\n\n        assertEq(userEthBalanceBefore.sub(userEthBalanceAfter), wethToLend);\n        assertEq(bullCrabBalanceAfter.sub(crabToDeposit), bullCrabBalanceBefore);\n        assertEq(bullStrategy.balanceOf(user1), crabToDeposit);\n        assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n        assertTrue(\n            wethToLend.sub(IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy))) <= 1\n        );\n        assertEq(IERC20(usdc).balanceOf(user1), usdcToBorrow);\n    }\n\n    function testInitialDeposit() public {\n        uint256 crabToDeposit = 10e18;\n        uint256 bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n        uint256 userEthBalanceBefore = address(user1).balance;\n        vm.startPrank(user1);\n        (uint256 wethToLend, uint256 usdcToBorrow) = _deposit(crabToDeposit);\n        vm.stopPrank();\n\n        uint256 bullCrabBalanceAfter = bullStrategy.getCrabBalance();\n\n        assertEq(bullCrabBalanceAfter.sub(crabToDeposit), bullCrabBalanceBefore);\n        assertEq(bullStrategy.balanceOf(user1), crabToDeposit);\n        assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n        assertTrue(\n            wethToLend.sub(IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy))) <= 1\n        );\n        assertEq(userEthBalanceBefore.sub(address(user1).balance), wethToLend);\n        assertEq(IERC20(usdc).balanceOf(user1), usdcToBorrow);\n    }\n\n    function testSecondDeposit() public {\n        uint256 crabToDepositInitially = 10e18;\n        uint256 bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n\n        vm.startPrank(user1);\n        (uint256 wethToLend, uint256 usdcToBorrow) = _deposit(crabToDepositInitially);\n        vm.stopPrank();\n\n        uint256 bullCrabBalanceAfter = bullStrategy.getCrabBalance();\n\n        assertEq(bullCrabBalanceAfter.sub(crabToDepositInitially), bullCrabBalanceBefore);\n        assertEq(bullStrategy.balanceOf(user1), crabToDepositInitially);\n        assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n        assertTrue(\n            wethToLend.sub(IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy))) <= 1\n        );\n        assertEq(IERC20(usdc).balanceOf(user1), usdcToBorrow);\n\n        bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n        uint256 userUsdcBalanceBefore = IERC20(usdc).balanceOf(user1);\n        uint256 userBullBalanceBefore = bullStrategy.balanceOf(user1);\n        uint256 crabToDepositSecond = 7e18;\n        uint256 bullToMint = testUtil.calcBullToMint(crabToDepositSecond);\n        vm.startPrank(user1);\n        (uint256 wethToLendSecond, uint256 usdcToBorrowSecond) = _deposit(crabToDepositSecond);\n        vm.stopPrank();\n\n        bullCrabBalanceAfter = bullStrategy.getCrabBalance();\n\n        assertEq(bullCrabBalanceAfter.sub(crabToDepositSecond), bullCrabBalanceBefore);\n        assertEq(bullStrategy.balanceOf(user1).sub(userBullBalanceBefore), bullToMint);\n        assertEq(\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcToBorrow),\n            usdcToBorrowSecond\n        );\n        assertTrue(\n            wethToLendSecond.sub(\n                IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)).sub(wethToLend)\n            ) <= 1\n        );\n\n        assertEq(IERC20(usdc).balanceOf(user1).sub(usdcToBorrowSecond), userUsdcBalanceBefore);\n    }\n\n    function testWithdrawWhenRemainingSupplyLessThanMinimum() public {\n        uint256 crabToDeposit = 15e18;\n\n        // crabby deposit into bull\n        vm.startPrank(user1);\n        _deposit(crabToDeposit);\n        vm.stopPrank();\n\n        uint256 bullToRedeem = crabToDeposit.sub(WETH_DECIMALS_DIFF);\n        (uint256 wPowerPerpToRedeem,) = _calcWPowerPerpAndCrabNeededForWithdraw(bullToRedeem);\n        uint256 usdcToRepay = _calcUsdcNeededForWithdraw(bullToRedeem);\n        // transfer some oSQTH from some squeether\n        vm.prank(0x56178a0d5F301bAf6CF3e1Cd53d9863437345Bf9);\n        IERC20(wPowerPerp).transfer(user1, wPowerPerpToRedeem);\n\n        vm.startPrank(user1);\n        IERC20(usdc).approve(address(bullStrategy), usdcToRepay);\n        IERC20(wPowerPerp).approve(address(bullStrategy), wPowerPerpToRedeem);\n        vm.expectRevert(bytes(\"BS10\"));\n        bullStrategy.withdraw(bullToRedeem);\n        vm.stopPrank();\n    }\n\n    function testWithdraw() public {\n        uint256 crabToDeposit = 15e18;\n        uint256 bullToMint = testUtil.calcBullToMint(crabToDeposit);\n\n        // crabby deposit into bull\n        vm.startPrank(user1);\n        _deposit(crabToDeposit);\n        vm.stopPrank();\n\n        (uint256 wPowerPerpToRedeem, uint256 crabToRedeem) =\n            _calcWPowerPerpAndCrabNeededForWithdraw(bullToMint);\n        uint256 usdcToRepay = _calcUsdcNeededForWithdraw(bullToMint);\n        uint256 wethToWithdraw = testUtil.calcWethToWithdraw(bullToMint);\n        // transfer some oSQTH from some squeether\n        vm.prank(0x56178a0d5F301bAf6CF3e1Cd53d9863437345Bf9);\n        IERC20(wPowerPerp).transfer(user1, wPowerPerpToRedeem);\n\n        uint256 userBullBalanceBefore = bullStrategy.balanceOf(user1);\n        uint256 ethInLendingBefore = IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy));\n        uint256 usdcBorrowedBefore = IEulerDToken(dToken).balanceOf(address(bullStrategy));\n        uint256 userUsdcBalanceBefore = IERC20(usdc).balanceOf(user1);\n        uint256 userWPowerPerpBalanceBefore = IERC20(wPowerPerp).balanceOf(user1);\n\n        uint256 crabBalanceBefore = crabV2.balanceOf(address(bullStrategy));\n\n        vm.startPrank(user1);\n        IERC20(usdc).approve(address(bullStrategy), usdcToRepay);\n        IERC20(wPowerPerp).approve(address(bullStrategy), wPowerPerpToRedeem);\n        bullStrategy.withdraw(bullToMint);\n        vm.stopPrank();\n\n        assertEq(\n            usdcBorrowedBefore.sub(usdcToRepay),\n            IEulerDToken(dToken).balanceOf(address(bullStrategy)),\n            \"Bull USDC debt amount mismatch\"\n        );\n        assertEq(\n            ethInLendingBefore.sub(wethToWithdraw),\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)),\n            \"Bull ETH in leverage amount mismatch\"\n        );\n        assertEq(\n            userUsdcBalanceBefore.sub(usdcToRepay),\n            IERC20(usdc).balanceOf(user1),\n            \"User1 USDC balance mismatch\"\n        );\n        assertEq(\n            userBullBalanceBefore.sub(bullToMint),\n            bullStrategy.balanceOf(user1),\n            \"User1 bull balance mismatch\"\n        );\n        assertEq(\n            userWPowerPerpBalanceBefore.sub(wPowerPerpToRedeem),\n            IERC20(wPowerPerp).balanceOf(user1),\n            \"User1 oSQTH balance mismatch\"\n        );\n        assertEq(\n            crabBalanceBefore.sub(crabToRedeem),\n            crabV2.balanceOf(address(bullStrategy)),\n            \"Bull crab balance mismatch\"\n        );\n    }\n\n    function testReceiveFromNonWethOrCrab() public {\n        vm.startPrank(user1);\n        (bool status, bytes memory returndata) = address(bullStrategy).call{ value: 5e18 }(\"\");\n        vm.stopPrank();\n        assertFalse(status);\n        assertEq(_getRevertMsg(returndata), \"BS1\");\n    }\n\n    function testSendLessEthComparedToCrabAmount() public {\n        uint256 crabToDeposit = 10e18;\n\n        vm.startPrank(user1);\n        (uint256 wethToLend,) = testUtil.calcCollateralAndBorrowAmount(crabToDeposit);\n        IERC20(crabV2).approve(address(bullStrategy), crabToDeposit);\n        vm.expectRevert(bytes(\"LB0\"));\n        bullStrategy.deposit{ value: wethToLend.wdiv(2e18) }(crabToDeposit);\n        vm.stopPrank();\n    }\n\n    function testSendTooMuchCrabRelativeToEth() public {\n        uint256 crabToDeposit = 10e18;\n\n        vm.startPrank(user1);\n        (uint256 wethToLend,) = testUtil.calcCollateralAndBorrowAmount(crabToDeposit.wdiv(2e18));\n        IERC20(crabV2).approve(address(bullStrategy), crabToDeposit);\n        vm.expectRevert(bytes(\"LB0\"));\n        bullStrategy.deposit{ value: wethToLend }(crabToDeposit);\n        vm.stopPrank();\n    }\n\n    function testFarm() public {\n        uint256 daiAmount = 10e18;\n        address dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(dai).transfer(address(bullStrategy), daiAmount);\n\n        uint256 daiBalanceBefore = IERC20(dai).balanceOf(bullOwner);\n\n        vm.prank(bullOwner);\n        bullStrategy.farm(dai, bullOwner);\n\n        assertEq(IERC20(dai).balanceOf(bullOwner).sub(daiAmount), daiBalanceBefore);\n    }\n\n    function testFarmWhenCallerNotOwner() public {\n        uint256 daiAmount = 10e18;\n        address dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(dai).transfer(address(bullStrategy), daiAmount);\n\n        vm.prank(deployer);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        bullStrategy.farm(dai, bullOwner);\n    }\n\n    function testFarmWhenAssetIsNotFarmable() public {\n        vm.prank(bullOwner);\n        vm.expectRevert(bytes(\"BS5\"));\n        bullStrategy.farm(eToken, bullOwner);\n    }\n\n    function testFarmWhenHasRedeemedInShutdownIsTrue() public {\n        uint256 daiAmount = 10e18;\n        address dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(dai).transfer(address(bullStrategy), daiAmount);\n\n        vm.store(address(bullStrategy), bytes32(uint256(10)), bytes32(uint256(1)));\n\n        vm.startPrank(bullOwner);\n        vm.expectRevert(bytes(\"BS12\"));\n        bullStrategy.farm(dai, bullOwner);\n    }\n\n    function testFarmWhenControllerIsShutdown() public {\n        vm.startPrank(controller.owner());\n        controller.shutDown();\n        assertEq(controller.isShutDown(), true);\n        vm.stopPrank();\n\n        uint256 daiAmount = 10e18;\n        address dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(dai).transfer(address(bullStrategy), daiAmount);\n\n        vm.startPrank(bullOwner);\n        vm.expectRevert(bytes(\"BS7\"));\n        bullStrategy.farm(dai, bullOwner);\n    }\n\n    /**\n     *\n     * /************************************************************* Helper functions for testing! ********************************************************\n     */\n    function _deposit(uint256 _crabToDeposit) internal returns (uint256, uint256) {\n        (uint256 wethToLend, uint256 usdcToBorrow) =\n            testUtil.calcCollateralAndBorrowAmount(_crabToDeposit);\n\n        IERC20(crabV2).approve(address(bullStrategy), _crabToDeposit);\n        bullStrategy.deposit{ value: wethToLend }(_crabToDeposit);\n\n        return (wethToLend, usdcToBorrow);\n    }\n\n    function _calcWPowerPerpAndCrabNeededForWithdraw(uint256 _bullAmount)\n        internal\n        view\n        returns (uint256, uint256)\n    {\n        uint256 share = _bullAmount.wdiv(bullStrategy.totalSupply());\n        uint256 crabToRedeem = share.wmul(bullStrategy.getCrabBalance());\n        uint256 crabTotalSupply = IERC20(crabV2).totalSupply();\n        (, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        return (crabToRedeem.wmul(squeethInCrab).wdiv(crabTotalSupply), crabToRedeem);\n    }\n\n    function _calcUsdcNeededForWithdraw(uint256 _bullAmount) internal view returns (uint256) {\n        uint256 share = _bullAmount.wdiv(bullStrategy.totalSupply());\n        return share.wmul(IEulerDToken(dToken).balanceOf(address(bullStrategy)));\n    }\n\n    function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {\n        // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n        if (_returnData.length < 68) return \"Transaction reverted silently\";\n\n        assembly {\n            // Slice the sighash.\n            _returnData := add(_returnData, 0x04)\n        }\n        return abi.decode(_returnData, (string)); // All that remains is the revert string\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/integration-test/ZenEmergencyShutdownTestFork.t.sol",
    "content": "pragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IEulerMarkets } from \"../../src/interface/IEulerMarkets.sol\";\nimport { IEulerEToken } from \"../../src/interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"../../src/interface/IEulerDToken.sol\";\n// contract\nimport { TestUtil } from \"../util/TestUtil.t.sol\";\nimport { ZenBullStrategy } from \"../../src/ZenBullStrategy.sol\";\nimport { CrabStrategyV2 } from \"squeeth-monorepo/strategy/CrabStrategyV2.sol\";\nimport { Controller } from \"squeeth-monorepo/core/Controller.sol\";\nimport { ZenEmergencyShutdown } from \"../../src/ZenEmergencyShutdown.sol\";\nimport { Quoter } from \"v3-periphery/lens/Quoter.sol\";\n// lib\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\nimport { UniOracle } from \"../../src/UniOracle.sol\";\n\n/**\n * @notice Ropsten fork testing\n */\ncontract ZenEmergencyShutdownTestFork is Test {\n    using StrategyMath for uint256;\n\n    TestUtil internal testUtil;\n    ZenBullStrategy internal bullStrategy;\n    CrabStrategyV2 internal crabV2;\n    Controller internal controller;\n    ZenEmergencyShutdown internal emergencyShutdown;\n    Quoter internal quoter;\n\n    uint256 internal bullOwnerPk;\n    uint256 internal deployerPk;\n    uint256 internal user1Pk;\n    uint256 internal user2Pk;\n\n    uint256 internal cap;\n\n    address internal user1;\n    address internal user2;\n    address internal weth;\n    address internal usdc;\n    address internal euler;\n    address internal eulerMarketsModule;\n    address internal eToken;\n    address internal dToken;\n    address internal wPowerPerp;\n    address internal deployer;\n    address internal bullOwner;\n    address internal crabOwner;\n    address internal controllerOwner;\n    address internal ethWSqueethPool;\n    address internal ethUsdcPool;\n\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n    uint256 internal constant ONE = 1e18;\n    uint256 internal constant ONE_ONE = 1e36;\n    uint32 internal constant TWAP = 420;\n    uint256 internal constant INDEX_SCALE = 10000;\n\n    function setUp() public {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 15781550);\n\n        deployerPk = 0xA11CD;\n        deployer = vm.addr(deployerPk);\n        bullOwnerPk = 0xB11CD;\n        bullOwner = vm.addr(bullOwnerPk);\n\n        vm.startPrank(deployer);\n        euler = 0x27182842E098f60e3D576794A5bFFb0777E025d3;\n        eulerMarketsModule = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3;\n        controller = Controller(0x64187ae08781B09368e6253F9E94951243A493D5);\n        controllerOwner = controller.owner();\n        ethWSqueethPool = controller.wPowerPerpPool();\n        ethUsdcPool = controller.ethQuoteCurrencyPool();\n        crabV2 = CrabStrategyV2(0x3B960E47784150F5a63777201ee2B15253D713e8);\n        crabOwner = crabV2.owner();\n        bullStrategy =\n            new ZenBullStrategy(address(crabV2), address(controller), euler, eulerMarketsModule);\n        bullStrategy.transferOwnership(bullOwner);\n        usdc = controller.quoteCurrency();\n        weth = controller.weth();\n        eToken = IEulerMarkets(eulerMarketsModule).underlyingToEToken(weth);\n        dToken = IEulerMarkets(eulerMarketsModule).underlyingToDToken(usdc);\n        wPowerPerp = controller.wPowerPerp();\n        quoter = Quoter(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);\n        emergencyShutdown =\n        new ZenEmergencyShutdown(address(bullStrategy), 0x1F98431c8aD98523631AE4a59f267346ea31F984);\n        emergencyShutdown.transferOwnership(bullOwner);\n        testUtil =\n        new TestUtil(address(bullStrategy), address (controller), eToken, dToken, address(crabV2));\n\n        vm.stopPrank();\n\n        cap = 100000e18;\n        vm.startPrank(bullOwner);\n        bullStrategy.setCap(cap);\n        bullStrategy.setShutdownContract(address(emergencyShutdown));\n        vm.stopPrank();\n        user1Pk = 0xA11CE;\n        user1 = vm.addr(user1Pk);\n        user2Pk = 0xC11CE;\n        user2 = vm.addr(user2Pk);\n\n        vm.label(user1, \"User 1\");\n        vm.label(address(bullStrategy), \"BullStrategy\");\n        vm.label(euler, \"Euler\");\n        vm.label(eulerMarketsModule, \"EulerMarkets\");\n        vm.label(usdc, \"USDC\");\n        vm.label(weth, \"WETH\");\n        vm.label(wPowerPerp, \"oSQTH\");\n        vm.label(address(crabV2), \"crabV2\");\n        vm.label(user2, \"User 2\");\n\n        vm.deal(user1, 100000000e18);\n        vm.deal(user2, 100000000e18);\n        // this is a crab whale, get some crab token from\n        vm.startPrank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 100e18);\n        IERC20(crabV2).transfer(user2, 100e18);\n        vm.stopPrank();\n        // some WETH and USDC rich address\n        vm.startPrank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(weth).transfer(user1, 5000e18);\n        IERC20(weth).transfer(user2, 5000e18);\n        vm.stopPrank();\n    }\n\n    function testSetUpBullStrategy() public {\n        assertTrue(bullStrategy.owner() == bullOwner);\n        assertTrue(bullStrategy.strategyCap() == cap);\n    }\n\n    function testSetUpEmergencyShutdown() public {\n        assertTrue(emergencyShutdown.owner() == bullOwner);\n        assertTrue(emergencyShutdown.bullStrategy() == address(bullStrategy));\n    }\n\n    function testSetEmergencyShutdownContractCallerNotOwner() public {\n        vm.startPrank(deployer);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        bullStrategy.setShutdownContract(address(emergencyShutdown));\n    }\n\n    function testSetEmergencyShutdownContractZeroAddress() public {\n        vm.startPrank(bullOwner);\n        vm.expectRevert(bytes(\"BS6\"));\n        bullStrategy.setShutdownContract(address(0));\n    }\n\n    function testSetEmergencyShutdownContract() public {\n        vm.startPrank(bullOwner);\n        bullStrategy.setShutdownContract(address(emergencyShutdown));\n        assertEq(bullStrategy.shutdownContract(), address(emergencyShutdown));\n    }\n\n    function testSetCapWhenCallerNotOwner() public {\n        cap = 1000000e18;\n        vm.startPrank(deployer);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n        bullStrategy.setCap(10e18);\n    }\n\n    function testRedeemShortShutdownCallerNotwner() public {\n        ZenEmergencyShutdown.ShutdownParams memory params = ZenEmergencyShutdown.ShutdownParams({\n            shareToUnwind: ONE,\n            ethLimitPrice: 1000,\n            ethPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(deployer);\n        vm.expectRevert(bytes(\"Ownable: caller is not the owner\"));\n\n        emergencyShutdown.redeemShortShutdown(params);\n    }\n\n    function testShutdownRepayAndWithdrawFromNotEmergencyShutdownContract() public {\n        vm.startPrank(bullOwner);\n        vm.expectRevert(bytes(\"BS4\"));\n\n        bullStrategy.shutdownRepayAndWithdraw(0, 0);\n    }\n\n    function testDepositShutdown() public {\n        vm.startPrank(controllerOwner);\n        controller.shutDown();\n        assertEq(controller.isShutDown(), true);\n        vm.stopPrank();\n\n        vm.startPrank(user1);\n        vm.expectRevert(bytes(\"BS7\"));\n        bullStrategy.deposit(0);\n        vm.stopPrank();\n    }\n\n    function testWithdrawalShutdown() public {\n        uint256 crabToDeposit = 10e18;\n        uint256 bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n        uint256 userEthBalanceBefore = address(user1).balance;\n        vm.startPrank(user1);\n        (uint256 wethToLend, uint256 usdcToBorrow) = _deposit(crabToDeposit);\n        vm.stopPrank();\n\n        uint256 bullCrabBalanceAfter = bullStrategy.getCrabBalance();\n\n        assertEq(bullCrabBalanceAfter.sub(crabToDeposit), bullCrabBalanceBefore);\n        assertEq(bullStrategy.balanceOf(user1), crabToDeposit);\n        assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n        assertTrue(\n            wethToLend.sub(IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy))) <= 1\n        );\n        assertEq(userEthBalanceBefore.sub(address(user1).balance), wethToLend);\n        assertEq(IERC20(usdc).balanceOf(user1), usdcToBorrow);\n\n        vm.startPrank(controllerOwner);\n        controller.shutDown();\n        assertEq(controller.isShutDown(), true);\n        vm.stopPrank();\n\n        vm.startPrank(user1);\n        vm.expectRevert();\n        bullStrategy.withdraw(0);\n        vm.stopPrank();\n    }\n\n    function testEmergencyShutdown() public {\n        // this is repeat of the testSecondDeposit() logic to set up state for a shutdown\n        {\n            uint256 crabToDepositInitially = 10e18;\n            uint256 bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n\n            vm.startPrank(user1);\n            (uint256 wethToLend, uint256 usdcToBorrow) = _deposit(crabToDepositInitially);\n            vm.stopPrank();\n\n            uint256 bullCrabBalanceAfter = bullStrategy.getCrabBalance();\n\n            assertEq(bullCrabBalanceAfter.sub(crabToDepositInitially), bullCrabBalanceBefore);\n            assertEq(bullStrategy.balanceOf(user1), crabToDepositInitially);\n            assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n            assertTrue(\n                wethToLend.sub(IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy))) <= 1\n            );\n            assertEq(IERC20(usdc).balanceOf(user1), usdcToBorrow);\n\n            bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n            uint256 userUsdcBalanceBefore = IERC20(usdc).balanceOf(user1);\n            uint256 userBullBalanceBefore = bullStrategy.balanceOf(user1);\n            uint256 crabToDepositSecond = 7e18;\n            uint256 bullToMint = testUtil.calcBullToMint(crabToDepositSecond);\n            vm.startPrank(user1);\n            (uint256 wethToLendSecond, uint256 usdcToBorrowSecond) = _deposit(crabToDepositSecond);\n            vm.stopPrank();\n\n            bullCrabBalanceAfter = bullStrategy.getCrabBalance();\n\n            assertEq(bullCrabBalanceAfter.sub(crabToDepositSecond), bullCrabBalanceBefore);\n            assertEq(bullStrategy.balanceOf(user1).sub(userBullBalanceBefore), bullToMint);\n            assertEq(\n                IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcToBorrow),\n                usdcToBorrowSecond\n            );\n            assertTrue(\n                wethToLendSecond.sub(\n                    IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)).sub(wethToLend)\n                ) <= 1\n            );\n            assertEq(IERC20(usdc).balanceOf(user1).sub(usdcToBorrowSecond), userUsdcBalanceBefore);\n        }\n\n        // start shutdown test\n        // percent to redeem\n        uint256 percentToRedeem = ONE;\n        (uint256 crabCollateral, uint256 crabDebt) = testUtil.getCrabVaultDetails();\n        uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n        uint256 crabShares = bullStrategy.getCrabBalance();\n\n        uint256 ethInCrabAfterShutdown = crabCollateral.sub(\n            crabDebt.wmul(controller.normalizationFactor()).wmul(ethUsdPrice.div(INDEX_SCALE))\n        );\n        uint256 ethFromCrabRedemption =\n            crabShares.wdiv(crabV2.totalSupply()).wmul(ethInCrabAfterShutdown);\n\n        vm.startPrank(controllerOwner);\n        controller.shutDown();\n        assertEq(controller.isShutDown(), true);\n        vm.stopPrank();\n\n        vm.startPrank(crabOwner);\n        crabV2.redeemShortShutdown();\n        vm.stopPrank();\n\n        vm.startPrank(bullOwner);\n        bullStrategy.setShutdownContract(address(emergencyShutdown));\n\n        uint256 expectedEthToPay = quoter.quoteExactOutputSingle(\n            weth, usdc, 3000, bullStrategy.calcUsdcToRepay(percentToRedeem), 0\n        );\n        uint256 effectivePrice = bullStrategy.calcUsdcToRepay(percentToRedeem).mul(\n            WETH_DECIMALS_DIFF\n        ).wdiv(expectedEthToPay);\n\n        uint256 ethInLeverage = bullStrategy.calcWethToWithdraw(percentToRedeem);\n        uint256 contractEthBefore = address(bullStrategy).balance;\n\n        ZenEmergencyShutdown.ShutdownParams memory params = ZenEmergencyShutdown.ShutdownParams({\n            shareToUnwind: percentToRedeem,\n            ethLimitPrice: effectivePrice.wmul(0.9e18),\n            ethPoolFee: uint24(3000)\n        });\n\n        emergencyShutdown.redeemShortShutdown(params);\n        vm.stopPrank();\n\n        uint256 expectedContractEthAfter =\n            ethFromCrabRedemption.add(ethInLeverage.sub(expectedEthToPay)).add(contractEthBefore);\n        uint256 contractEthAfter = address(bullStrategy).balance;\n\n        assertEq(contractEthAfter, expectedContractEthAfter);\n        assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), 0);\n        assertEq(IEulerEToken(eToken).balanceOf(address(bullStrategy)), 0);\n        assertEq(IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), 0);\n        assertEq(IERC20(weth).balanceOf(address(bullStrategy)), 0);\n        assertEq(IERC20(usdc).balanceOf(address(bullStrategy)), 0);\n        assertEq(IERC20(crabV2).balanceOf(address(bullStrategy)), 0);\n\n        vm.startPrank(user1);\n\n        contractEthBefore = contractEthAfter;\n        uint256 percentBullToRedeem = 0.5e18; // 50%\n        uint256 userBullBalanceBeforeShutdown = bullStrategy.balanceOf(address(user1));\n        uint256 bullToRedeem = percentBullToRedeem.wmul(userBullBalanceBeforeShutdown);\n        uint256 expectedProceeds =\n            bullToRedeem.wdiv(bullStrategy.totalSupply()).wmul(contractEthBefore);\n        uint256 userEthBalanceBefore = address(user1).balance;\n        uint256 bullSupplyBefore = bullStrategy.totalSupply();\n\n        bullStrategy.withdrawShutdown(bullToRedeem);\n\n        contractEthAfter = address(bullStrategy).balance;\n        uint256 bullSupplyAfter = bullStrategy.totalSupply();\n        uint256 userBullBalanceAfter = bullStrategy.balanceOf(address(user1));\n        //user checks\n        assertEq(address(user1).balance, userEthBalanceBefore.add(expectedProceeds));\n        assertEq(userBullBalanceAfter, userBullBalanceBeforeShutdown.sub(bullToRedeem));\n        //contract state checks\n        assertEq(contractEthAfter, contractEthBefore.sub(expectedProceeds));\n        assertEq(bullSupplyAfter, bullSupplyBefore.sub(bullToRedeem));\n\n        vm.stopPrank();\n\n        vm.startPrank(user1);\n\n        contractEthBefore = contractEthAfter;\n        percentBullToRedeem = 1e18; // 100%\n        userBullBalanceBeforeShutdown = bullStrategy.balanceOf(address(user1));\n        bullToRedeem = percentBullToRedeem.wmul(userBullBalanceBeforeShutdown);\n        expectedProceeds = bullToRedeem.wdiv(bullStrategy.totalSupply()).wmul(contractEthBefore);\n        userEthBalanceBefore = address(user1).balance;\n        bullSupplyBefore = bullStrategy.totalSupply();\n\n        bullStrategy.withdrawShutdown(bullToRedeem);\n\n        contractEthAfter = address(bullStrategy).balance;\n        bullSupplyAfter = bullStrategy.totalSupply();\n        userBullBalanceAfter = bullStrategy.balanceOf(address(user1));\n        //user checks\n        assertEq(address(user1).balance, userEthBalanceBefore.add(expectedProceeds));\n        assertEq(userBullBalanceAfter, userBullBalanceBeforeShutdown.sub(bullToRedeem));\n        //contract state checks\n        assertEq(contractEthAfter, contractEthBefore.sub(expectedProceeds));\n        assertEq(bullSupplyAfter, bullSupplyBefore.sub(bullToRedeem));\n        assertEq(bullSupplyAfter, 0);\n        assertEq(contractEthAfter, 0);\n\n        vm.stopPrank();\n    }\n\n    function testEmergencyShutdownPartial() public {\n        // this is repeat of the testSecondDeposit() logic to set up state for a shutdown\n        {\n            uint256 crabToDepositInitially = 10e18;\n            uint256 bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n\n            vm.startPrank(user1);\n            (uint256 wethToLend, uint256 usdcToBorrow) = _deposit(crabToDepositInitially);\n            vm.stopPrank();\n\n            uint256 bullCrabBalanceAfter = bullStrategy.getCrabBalance();\n\n            assertEq(bullCrabBalanceAfter.sub(crabToDepositInitially), bullCrabBalanceBefore);\n            assertEq(bullStrategy.balanceOf(user1), crabToDepositInitially);\n            assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n            assertTrue(\n                wethToLend.sub(IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy))) <= 1\n            );\n            assertEq(IERC20(usdc).balanceOf(user1), usdcToBorrow);\n\n            bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n            uint256 userUsdcBalanceBefore = IERC20(usdc).balanceOf(user2);\n            uint256 userBullBalanceBefore = bullStrategy.balanceOf(user2);\n            uint256 crabToDepositSecond = 7e18;\n            uint256 bullToMint = testUtil.calcBullToMint(crabToDepositSecond);\n\n            vm.startPrank(user2);\n            (uint256 wethToLendSecond, uint256 usdcToBorrowSecond) = _deposit(crabToDepositSecond);\n            vm.stopPrank();\n\n            bullCrabBalanceAfter = bullStrategy.getCrabBalance();\n\n            assertEq(bullCrabBalanceAfter.sub(crabToDepositSecond), bullCrabBalanceBefore);\n            assertEq(bullStrategy.balanceOf(user2).sub(userBullBalanceBefore), bullToMint);\n            assertEq(\n                IEulerDToken(dToken).balanceOf(address(bullStrategy)).sub(usdcToBorrow),\n                usdcToBorrowSecond\n            );\n            assertTrue(\n                wethToLendSecond.sub(\n                    IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)).sub(wethToLend)\n                ) <= 1\n            );\n            assertEq(IERC20(usdc).balanceOf(user2).sub(usdcToBorrowSecond), userUsdcBalanceBefore);\n        }\n\n        (uint256 crabCollateral, uint256 crabDebt) = testUtil.getCrabVaultDetails();\n\n        {\n            // start shutdown test where we redeem in 2 clips of 50%\n            // percent to redeem\n\n            uint256 percentToRedeem = ONE.div(2); //50%\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 crabBalanceBefore = bullStrategy.getCrabBalance();\n            uint256 crabShares = crabBalanceBefore.wmul(percentToRedeem);\n            uint256 ethFromCrabRedemption =\n                testUtil.calculateCrabRedemption(crabShares, ethUsdPrice, crabCollateral, crabDebt);\n\n            vm.startPrank(controllerOwner);\n            controller.shutDown();\n            assertEq(controller.isShutDown(), true);\n            vm.stopPrank();\n\n            vm.startPrank(crabOwner);\n            crabV2.redeemShortShutdown();\n            vm.stopPrank();\n\n            vm.startPrank(bullOwner);\n            bullStrategy.setShutdownContract(address(emergencyShutdown));\n\n            uint256 usdcDebt = bullStrategy.calcUsdcToRepay(percentToRedeem);\n            uint256 totalUsdcDebt = bullStrategy.calcUsdcToRepay(ONE);\n            uint256 expectedEthToPay = quoter.quoteExactOutputSingle(weth, usdc, 3000, usdcDebt, 0);\n            uint256 effectivePrice = bullStrategy.calcUsdcToRepay(percentToRedeem).mul(\n                WETH_DECIMALS_DIFF\n            ).wdiv(expectedEthToPay);\n\n            uint256 totalEthInLeverage = bullStrategy.calcWethToWithdraw(ONE);\n            uint256 ethInLeverage = bullStrategy.calcWethToWithdraw(percentToRedeem);\n            uint256 contractEthBeforeRedeem = address(bullStrategy).balance;\n\n            ZenEmergencyShutdown.ShutdownParams memory params = ZenEmergencyShutdown.ShutdownParams({\n                shareToUnwind: percentToRedeem,\n                ethLimitPrice: effectivePrice.wmul(0.9e18),\n                ethPoolFee: uint24(3000)\n            });\n\n            emergencyShutdown.redeemShortShutdown(params);\n            vm.stopPrank();\n\n            uint256 contractEthAfterRedeem = address(bullStrategy).balance;\n\n            assertEq(\n                contractEthAfterRedeem,\n                ethFromCrabRedemption.add(ethInLeverage.sub(expectedEthToPay)).add(\n                    contractEthBeforeRedeem\n                )\n            );\n            assertEq(\n                IEulerDToken(dToken).balanceOf(address(bullStrategy)), totalUsdcDebt.sub(usdcDebt)\n            );\n            assertApproxEqAbs(\n                IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)),\n                totalEthInLeverage.sub(ethInLeverage),\n                1\n            );\n            assertEq(IERC20(weth).balanceOf(address(bullStrategy)), 0);\n            assertEq(IERC20(usdc).balanceOf(address(bullStrategy)), 0);\n            assertEq(\n                IERC20(crabV2).balanceOf(address(bullStrategy)), crabBalanceBefore.sub(crabShares)\n            );\n        }\n\n        // try to redeem before strategy has been totally unwound, should revert\n        vm.startPrank(user1);\n        uint256 balanceToWithdraw = bullStrategy.balanceOf(address(user1));\n        vm.expectRevert(bytes(\"BS3\"));\n        bullStrategy.withdrawShutdown(balanceToWithdraw);\n        vm.stopPrank();\n\n        {\n            //redeem the rest of crab\n            uint256 percentToRedeem = ONE; //100%, remainder of crab\n            uint256 ethUsdPrice = UniOracle._getTwap(ethUsdcPool, weth, usdc, TWAP, false);\n            uint256 crabBalanceBefore = bullStrategy.getCrabBalance();\n            uint256 crabShares = crabBalanceBefore.wmul(percentToRedeem);\n            uint256 ethFromCrabRedemption =\n                testUtil.calculateCrabRedemption(crabShares, ethUsdPrice, crabCollateral, crabDebt);\n\n            vm.startPrank(bullOwner);\n\n            uint256 usdcDebt = bullStrategy.calcUsdcToRepay(percentToRedeem);\n            uint256 totalUsdcDebt = bullStrategy.calcUsdcToRepay(ONE);\n            uint256 expectedEthToPay = quoter.quoteExactOutputSingle(weth, usdc, 3000, usdcDebt, 0);\n            uint256 effectivePrice = bullStrategy.calcUsdcToRepay(percentToRedeem).mul(\n                WETH_DECIMALS_DIFF\n            ).wdiv(expectedEthToPay);\n\n            uint256 totalEthInLeverage = bullStrategy.calcWethToWithdraw(ONE);\n            uint256 ethInLeverage = bullStrategy.calcWethToWithdraw(percentToRedeem);\n            uint256 contractEthBeforeRedeem = address(bullStrategy).balance;\n\n            ZenEmergencyShutdown.ShutdownParams memory params = ZenEmergencyShutdown.ShutdownParams({\n                shareToUnwind: percentToRedeem,\n                ethLimitPrice: effectivePrice.wmul(0.9e18),\n                ethPoolFee: uint24(3000)\n            });\n\n            emergencyShutdown.redeemShortShutdown(params);\n            vm.stopPrank();\n\n            uint256 contractEthAfterRedeem = address(bullStrategy).balance;\n\n            assertEq(\n                contractEthAfterRedeem,\n                ethFromCrabRedemption.add(ethInLeverage.sub(expectedEthToPay)).add(\n                    contractEthBeforeRedeem\n                )\n            );\n            assertEq(\n                IEulerDToken(dToken).balanceOf(address(bullStrategy)), totalUsdcDebt.sub(usdcDebt)\n            );\n            assertEq(\n                IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)),\n                totalEthInLeverage.sub(ethInLeverage)\n            );\n            assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), 0);\n            assertEq(IEulerEToken(eToken).balanceOf(address(bullStrategy)), 0);\n            assertEq(IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), 0);\n            assertEq(IERC20(weth).balanceOf(address(bullStrategy)), 0);\n            assertEq(IERC20(usdc).balanceOf(address(bullStrategy)), 0);\n            assertEq(\n                IERC20(crabV2).balanceOf(address(bullStrategy)), crabBalanceBefore.sub(crabShares)\n            );\n            assertEq(IERC20(crabV2).balanceOf(address(bullStrategy)), 0);\n        }\n\n        // can not redeem again\n\n        {\n            vm.startPrank(bullOwner);\n            ZenEmergencyShutdown.ShutdownParams memory params = ZenEmergencyShutdown.ShutdownParams({\n                shareToUnwind: ONE,\n                ethLimitPrice: 0,\n                ethPoolFee: uint24(3000)\n            });\n            vm.expectRevert(bytes(\"ES1\"));\n            emergencyShutdown.redeemShortShutdown(params);\n            vm.stopPrank();\n        }\n\n        vm.startPrank(user1);\n\n        uint256 contractEthBefore = address(bullStrategy).balance;\n        uint256 percentBullToRedeem = 0.5e18; // 50%\n        uint256 userBullBalanceBeforeShutdown = bullStrategy.balanceOf(address(user1));\n        uint256 bullToRedeem = percentBullToRedeem.wmul(userBullBalanceBeforeShutdown);\n        uint256 expectedProceeds =\n            bullToRedeem.wdiv(bullStrategy.totalSupply()).wmul(contractEthBefore);\n        uint256 userEthBalanceBefore = address(user1).balance;\n        uint256 bullSupplyBefore = bullStrategy.totalSupply();\n\n        bullStrategy.withdrawShutdown(bullToRedeem);\n\n        uint256 contractEthAfter = address(bullStrategy).balance;\n        uint256 bullSupplyAfter = bullStrategy.totalSupply();\n        uint256 userBullBalanceAfter = bullStrategy.balanceOf(address(user1));\n        //user checks\n        assertEq(address(user1).balance, userEthBalanceBefore.add(expectedProceeds));\n        assertEq(userBullBalanceAfter, userBullBalanceBeforeShutdown.sub(bullToRedeem));\n        //contract state checks\n        assertEq(contractEthAfter, contractEthBefore.sub(expectedProceeds));\n        assertEq(bullSupplyAfter, bullSupplyBefore.sub(bullToRedeem));\n\n        vm.stopPrank();\n\n        vm.startPrank(user2);\n\n        contractEthBefore = contractEthAfter;\n        percentBullToRedeem = 1e18; // 100%\n        userBullBalanceBeforeShutdown = bullStrategy.balanceOf(address(user2));\n        bullToRedeem = percentBullToRedeem.wmul(userBullBalanceBeforeShutdown);\n        expectedProceeds = bullToRedeem.wdiv(bullStrategy.totalSupply()).wmul(contractEthBefore);\n        userEthBalanceBefore = address(user2).balance;\n        bullSupplyBefore = bullStrategy.totalSupply();\n\n        bullStrategy.withdrawShutdown(bullToRedeem);\n\n        contractEthAfter = address(bullStrategy).balance;\n        bullSupplyAfter = bullStrategy.totalSupply();\n        userBullBalanceAfter = bullStrategy.balanceOf(address(user2));\n        //user checks\n        assertEq(address(user2).balance, userEthBalanceBefore.add(expectedProceeds));\n        assertEq(userBullBalanceAfter, userBullBalanceBeforeShutdown.sub(bullToRedeem));\n        //contract state checks\n        assertEq(contractEthAfter, contractEthBefore.sub(expectedProceeds));\n        assertEq(bullSupplyAfter, bullSupplyBefore.sub(bullToRedeem));\n\n        vm.stopPrank();\n\n        vm.startPrank(user1);\n\n        contractEthBefore = contractEthAfter;\n        percentBullToRedeem = 1e18; // 100%\n        userBullBalanceBeforeShutdown = bullStrategy.balanceOf(address(user1));\n        bullToRedeem = percentBullToRedeem.wmul(userBullBalanceBeforeShutdown);\n        expectedProceeds = bullToRedeem.wdiv(bullStrategy.totalSupply()).wmul(contractEthBefore);\n        userEthBalanceBefore = address(user1).balance;\n        bullSupplyBefore = bullStrategy.totalSupply();\n\n        bullStrategy.withdrawShutdown(bullToRedeem);\n\n        contractEthAfter = address(bullStrategy).balance;\n        bullSupplyAfter = bullStrategy.totalSupply();\n        userBullBalanceAfter = bullStrategy.balanceOf(address(user1));\n        //user checks\n        assertEq(address(user1).balance, userEthBalanceBefore.add(expectedProceeds));\n        assertEq(userBullBalanceAfter, userBullBalanceBeforeShutdown.sub(bullToRedeem));\n        //contract state checks\n        assertEq(contractEthAfter, contractEthBefore.sub(expectedProceeds));\n        assertEq(bullSupplyAfter, bullSupplyBefore.sub(bullToRedeem));\n        assertEq(bullSupplyAfter, 0);\n        assertEq(contractEthAfter, 0);\n\n        vm.stopPrank();\n    }\n\n    /**\n     *\n     * /************************************************************* Helper functions for testing! ********************************************************\n     */\n    function _deposit(uint256 _crabToDeposit) internal returns (uint256, uint256) {\n        (uint256 wethToLend, uint256 usdcToBorrow) =\n            testUtil.calcCollateralAndBorrowAmount(_crabToDeposit);\n\n        IERC20(crabV2).approve(address(bullStrategy), _crabToDeposit);\n        bullStrategy.deposit{ value: wethToLend }(_crabToDeposit);\n\n        return (wethToLend, usdcToBorrow);\n    }\n\n    function _calcWPowerPerpAndCrabNeededForWithdraw(uint256 _bullAmount)\n        internal\n        view\n        returns (uint256, uint256)\n    {\n        uint256 share = _bullAmount.wdiv(bullStrategy.totalSupply());\n        uint256 crabToRedeem = share.wmul(bullStrategy.getCrabBalance());\n        uint256 crabTotalSupply = IERC20(crabV2).totalSupply();\n        (, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        return (crabToRedeem.wmul(squeethInCrab).wdiv(crabTotalSupply), crabToRedeem);\n    }\n\n    function _calcUsdcNeededForWithdraw(uint256 _bullAmount) internal view returns (uint256) {\n        uint256 share = _bullAmount.wdiv(bullStrategy.totalSupply());\n        return share.wmul(IEulerDToken(dToken).balanceOf(address(bullStrategy)));\n    }\n\n    function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {\n        // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n        if (_returnData.length < 68) return \"Transaction reverted silently\";\n\n        assembly {\n            // Slice the sighash.\n            _returnData := add(_returnData, 0x04)\n        }\n        return abi.decode(_returnData, (string)); // All that remains is the revert string\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/unit-test/ZenBullStrategyTest.t.sol",
    "content": "pragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\nimport { console } from \"forge-std/console.sol\";\n\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IEulerMarkets } from \"../../src/interface/IEulerMarkets.sol\";\nimport { IEulerEToken } from \"../../src/interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"../../src/interface/IEulerDToken.sol\";\nimport { IWETH9 } from \"squeeth-monorepo/interfaces/IWETH9.sol\";\n// contract\nimport { SwapRouter } from \"v3-periphery/SwapRouter.sol\";\nimport { TestUtil } from \"../util/TestUtil.t.sol\";\nimport { ZenBullStrategy } from \"../../src/ZenBullStrategy.sol\";\nimport { CrabStrategyV2 } from \"squeeth-monorepo/strategy/CrabStrategyV2.sol\";\nimport { Controller } from \"squeeth-monorepo/core/Controller.sol\";\nimport { ZenEmergencyShutdown } from \"../../src/ZenEmergencyShutdown.sol\";\nimport { FlashZen } from \"../../src/FlashZen.sol\";\n// lib\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\nimport { UniOracle } from \"../../src/UniOracle.sol\";\n\n/**\n * @notice mainnet fork testing\n */\ncontract ZenBullStrategyTest is Test {\n    using StrategyMath for uint256;\n\n    uint128 internal constant ONE = 1e18;\n\n    TestUtil internal testUtil;\n    ZenBullStrategy internal bullStrategy;\n    CrabStrategyV2 internal crabV2;\n    Controller internal controller;\n    ZenEmergencyShutdown internal emergencyShutdown;\n    FlashZen internal flashBull;\n\n    uint256 internal bullOwnerPk;\n    uint256 internal deployerPk;\n    uint256 internal user1Pk;\n    uint256 internal ownerPk;\n    uint256 internal auctionPk;\n    address internal user1;\n    address internal owner;\n    address internal deployer;\n    address internal bullOwner;\n    address internal auction;\n\n    address internal weth;\n    address internal usdc;\n    address internal euler;\n    address internal eulerMarketsModule;\n    address internal eToken;\n    address internal dToken;\n    address internal wPowerPerp;\n    uint256 internal cap;\n\n    function setUp() public {\n        string memory FORK_URL = vm.envString(\"FORK_URL\");\n        vm.createSelectFork(FORK_URL, 15781550);\n\n        deployerPk = 0xA11CD;\n        deployer = vm.addr(deployerPk);\n        bullOwnerPk = 0xB11CD;\n        bullOwner = vm.addr(bullOwnerPk);\n        auctionPk = 0xC11CD;\n        auction = vm.addr(auctionPk);\n\n        vm.startPrank(deployer);\n\n        euler = 0x27182842E098f60e3D576794A5bFFb0777E025d3;\n        eulerMarketsModule = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3;\n        controller = Controller(0x64187ae08781B09368e6253F9E94951243A493D5);\n        crabV2 = CrabStrategyV2(0x3B960E47784150F5a63777201ee2B15253D713e8);\n        bullStrategy =\n            new ZenBullStrategy(address(crabV2), address(controller), euler, eulerMarketsModule);\n        bullStrategy.transferOwnership(bullOwner);\n        address factory = 0x1F98431c8aD98523631AE4a59f267346ea31F984;\n        flashBull = new FlashZen(address(bullStrategy), factory);\n        usdc = controller.quoteCurrency();\n        weth = controller.weth();\n        eToken = IEulerMarkets(eulerMarketsModule).underlyingToEToken(weth);\n        dToken = IEulerMarkets(eulerMarketsModule).underlyingToDToken(usdc);\n        wPowerPerp = controller.wPowerPerp();\n        emergencyShutdown =\n        new ZenEmergencyShutdown(address(bullStrategy), 0x1F98431c8aD98523631AE4a59f267346ea31F984);\n        emergencyShutdown.transferOwnership(bullOwner);\n\n        testUtil =\n        new TestUtil(address(bullStrategy), address (controller), eToken, dToken, address(crabV2));\n\n        vm.stopPrank();\n\n        cap = 100000e18;\n        vm.startPrank(bullOwner);\n        bullStrategy.setCap(cap);\n        bullStrategy.setAuction(auction);\n        bullStrategy.setShutdownContract(address(emergencyShutdown));\n        vm.stopPrank();\n        user1Pk = 0xA11CE;\n        user1 = vm.addr(user1Pk);\n\n        vm.label(user1, \"User 1\");\n        vm.label(address(bullStrategy), \"BullStrategy\");\n        vm.label(euler, \"Euler\");\n        vm.label(eulerMarketsModule, \"EulerMarkets\");\n        vm.label(usdc, \"USDC\");\n        vm.label(weth, \"WETH\");\n        vm.label(wPowerPerp, \"oSQTH\");\n        vm.label(address(crabV2), \"crabV2\");\n\n        vm.deal(user1, 100000000e18);\n        vm.deal(auction, 100000000e18);\n\n        // this is a crab whale, get some crab token from\n        vm.prank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).transfer(user1, 100e18);\n        // some WETH and USDC rich address\n        vm.prank(0x57757E3D981446D585Af0D9Ae4d7DF6D64647806);\n        IERC20(weth).transfer(user1, 10000e18);\n\n        _initateDepositInBull(user1, 5e18);\n    }\n\n    function testDepositEthIntoCrabWhenFeeIsZero() public {\n        uint256 ethToDeposit = 10e18;\n        (uint256 ethInCrab,) = testUtil.getCrabVaultDetails();\n\n        uint256 crabShare = ethToDeposit.wdiv(ethInCrab.add(ethToDeposit));\n        uint256 crabToBeMinted =\n            IERC20(crabV2).totalSupply().wmul(crabShare).wdiv(uint256(ONE).sub(crabShare));\n\n        uint256 bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n\n        vm.startPrank(auction);\n        IWETH9(weth).deposit{ value: ethToDeposit }();\n        IWETH9(weth).approve(address(bullStrategy), ethToDeposit);\n        bullStrategy.depositEthIntoCrab(ethToDeposit);\n        vm.stopPrank();\n\n        assertEq(bullStrategy.getCrabBalance().sub(crabToBeMinted), bullCrabBalanceBefore);\n    }\n\n    function testDepositEthIntoCrabWhenFeeIsNotZero() public {\n        uint256 ethToDeposit = 10e18;\n        (uint256 ethInCrab, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n\n        (, uint256 fee) = testUtil.calcWsqueethToMintAndFee(ethToDeposit, squeethInCrab, ethInCrab);\n\n        uint256 crabShare = (ethToDeposit.sub(fee)).wdiv(ethInCrab.add(ethToDeposit));\n        uint256 crabToBeMinted =\n            IERC20(crabV2).totalSupply().wmul(crabShare).wdiv(uint256(ONE).sub(crabShare));\n\n        uint256 bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n\n        vm.startPrank(auction);\n        IWETH9(weth).deposit{ value: ethToDeposit }();\n        IWETH9(weth).approve(address(bullStrategy), ethToDeposit);\n        bullStrategy.depositEthIntoCrab(ethToDeposit);\n        vm.stopPrank();\n\n        assertEq(bullStrategy.getCrabBalance().sub(crabToBeMinted), bullCrabBalanceBefore);\n    }\n\n    function testUnitRedeemCrabAndWithdrawWEth() public {\n        uint256 crabToRedeem = 5e18;\n        (uint256 wethToLend,) = testUtil.calcCollateralAndBorrowAmount(crabToRedeem);\n        vm.startPrank(0x06CECFbac34101aE41C88EbC2450f8602b3d164b);\n        IERC20(crabV2).approve(address(bullStrategy), crabToRedeem);\n        vm.deal(0x06CECFbac34101aE41C88EbC2450f8602b3d164b, wethToLend);\n        bullStrategy.deposit{ value: wethToLend }(crabToRedeem);\n        vm.stopPrank();\n\n        (, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        uint256 wPowerPerpToRedeem =\n            squeethInCrab.wmul(crabToRedeem).wdiv(IERC20(crabV2).totalSupply());\n\n        uint256 bullCrabBalanceBefore = bullStrategy.getCrabBalance();\n\n        vm.prank(0x82c427AdFDf2d245Ec51D8046b41c4ee87F0d29C);\n        IERC20(wPowerPerp).transfer(auction, wPowerPerpToRedeem);\n\n        vm.startPrank(auction);\n        IERC20(wPowerPerp).approve(address(bullStrategy), wPowerPerpToRedeem);\n        bullStrategy.redeemCrabAndWithdrawWEth(crabToRedeem, wPowerPerpToRedeem);\n        vm.stopPrank();\n\n        assertEq(bullStrategy.getCrabBalance().add(crabToRedeem), bullCrabBalanceBefore);\n    }\n\n    function _initateDepositInBull(address _depositor, uint256 _ethToCrab) internal {\n        // Put some money in bull to start with\n        (uint256 ethInCrab, uint256 squeethInCrab) = testUtil.getCrabVaultDetails();\n        (uint256 wSqueethToMint, uint256 fee) =\n            testUtil.calcWsqueethToMintAndFee(_ethToCrab, squeethInCrab, ethInCrab);\n        uint256 crabToBeMinted =\n            testUtil.calcSharesToMint(_ethToCrab.sub(fee), ethInCrab, IERC20(crabV2).totalSupply());\n        uint256 bullCrabBalanceBefore = IERC20(crabV2).balanceOf(address(bullStrategy));\n\n        uint256 bullShare = 1e18;\n        (uint256 wethToLend, uint256 usdcToBorrow) = bullStrategy.calcLeverageEthUsdc(\n            crabToBeMinted, bullShare, ethInCrab, squeethInCrab, crabV2.totalSupply()\n        );\n\n        uint256 totalEthToBull =\n            testUtil.calcTotalEthToBull(wethToLend, _ethToCrab, usdcToBorrow, wSqueethToMint);\n\n        FlashZen.FlashDepositParams memory params = FlashZen.FlashDepositParams({\n            ethToCrab: _ethToCrab,\n            minEthFromSqth: 0,\n            minEthFromUsdc: 0,\n            wPowerPerpPoolFee: uint24(3000),\n            usdcPoolFee: uint24(3000)\n        });\n\n        vm.startPrank(_depositor);\n        flashBull.flashDeposit{ value: totalEthToBull }(params);\n        vm.stopPrank();\n\n        assertEq(IEulerDToken(dToken).balanceOf(address(bullStrategy)), usdcToBorrow);\n        assertApproxEqAbs(\n            IEulerEToken(eToken).balanceOfUnderlying(address(bullStrategy)), wethToLend, 1\n        );\n        assertEq(bullStrategy.getCrabBalance().sub(crabToBeMinted), bullCrabBalanceBefore);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/unit-test/mock/EulerDtokenMock.t.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.7.6;\n\nimport \"forge-std/Test.sol\";\nimport { ERC20 } from \"openzeppelin/token/ERC20/ERC20.sol\";\nimport { EulerMock } from \"./EulerMock.t.sol\";\n\ncontract EulerDtokenMock is ERC20, Test {\n    // asset to borrow/repay\n    address underlying;\n\n    EulerMock internal euler;\n\n    constructor(\n        address _euler,\n        address _underlying,\n        string memory _name,\n        string memory _symbol,\n        uint8 _decimals\n    ) ERC20(_name, _symbol) {\n        euler = EulerMock(_euler);\n        underlying = _underlying;\n        _setupDecimals(_decimals);\n    }\n\n    function testToAvoidCoverage() public pure {\n        return;\n    }\n\n    function borrow(uint256, /*subAccountId*/ uint256 amount) external {\n        _mint(msg.sender, amount);\n        ERC20(underlying).transfer(msg.sender, amount);\n        euler.executeTransfer(underlying, address(euler), msg.sender, amount);\n    }\n\n    function repay(uint256, /*subAccountId*/ uint256 amount) external {\n        euler.executeTransfer(underlying, msg.sender, address(euler), amount);\n        ERC20(underlying).transferFrom(msg.sender, address(this), amount);\n        _burn(msg.sender, amount);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/unit-test/mock/EulerEtokenMock.t.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.7.6;\n\nimport \"forge-std/Test.sol\";\nimport { ERC20 } from \"openzeppelin/token/ERC20/ERC20.sol\";\nimport { EulerMock } from \"./EulerMock.t.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\n\ncontract EulerEtokenMock is ERC20, Test {\n    using StrategyMath for uint256;\n    // asset to deposit as collateral\n\n    address public underlying;\n\n    EulerMock internal euler;\n\n    mapping(address => uint256) internal underlyingBalance;\n\n    constructor(\n        address _euler,\n        address _underlying,\n        string memory _name,\n        string memory _symbol,\n        uint8 _decimals\n    ) ERC20(_name, _symbol) {\n        euler = EulerMock(_euler);\n        underlying = _underlying;\n        _setupDecimals(_decimals);\n    }\n\n    function testToAvoidCoverage() public pure {\n        return;\n    }\n\n    function deposit(uint256, /*subAccountId*/ uint256 amount) external {\n        euler.executeTransfer(underlying, msg.sender, address(euler), amount);\n        underlyingBalance[msg.sender] = underlyingBalance[msg.sender].add(amount);\n        _mint(msg.sender, amount);\n    }\n\n    function withdraw(uint256, /*subAccountId*/ uint256 amount) external {\n        underlyingBalance[msg.sender] = underlyingBalance[msg.sender].sub(amount);\n        _burn(msg.sender, amount);\n        euler.executeTransfer(underlying, address(euler), msg.sender, amount);\n    }\n\n    function balanceOfUnderlying(address account) external view returns (uint256) {\n        return underlyingBalance[account];\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/unit-test/mock/EulerMarketsMock.t.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.7.6;\n\nimport \"forge-std/Test.sol\";\n\ncontract EulerMarketsMock is Test {\n    mapping(address => address) internal underlyingToEtoken;\n    mapping(address => address) internal underlyingToDtoken;\n\n    function testToAvoidCoverage() public pure {\n        return;\n    }\n\n    function setUnderlyingToEtoken(address _underlying, address _eToken) external {\n        underlyingToEtoken[_underlying] = _eToken;\n    }\n\n    function setUnderlyingToDtoken(address _underlying, address _dToken) external {\n        underlyingToDtoken[_underlying] = _dToken;\n    }\n\n    function enterMarket(uint256, /*_subAccountId*/ address /*_newMarket*/ ) external pure {\n        return;\n    }\n\n    function underlyingToEToken(address _underlying) external view returns (address) {\n        return underlyingToEtoken[_underlying];\n    }\n\n    function underlyingToDToken(address _underlying) external view returns (address) {\n        return underlyingToDtoken[_underlying];\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/unit-test/mock/EulerMock.t.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.7.6;\n\nimport \"forge-std/Test.sol\";\nimport { ERC20 } from \"openzeppelin/token/ERC20/ERC20.sol\";\n\ncontract EulerMock is Test {\n    function executeTransfer(address _asset, address _from, address _to, uint256 _amount)\n        external\n    {\n        ERC20(_asset).transferFrom(_from, _to, _amount);\n    }\n\n    function testToAvoidCoverage() public pure {\n        return;\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/unit-test/mock/Weth9Mock.t.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.7.6;\n\nimport \"forge-std/Test.sol\";\nimport { SafeMath } from \"openzeppelin/math/SafeMath.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { SafeMath } from \"openzeppelin/math/SafeMath.sol\";\nimport { Address } from \"openzeppelin/utils/Address.sol\";\n\ncontract WETH9Mock is ERC20, Test {\n    using SafeMath for uint256;\n    using Address for address payable;\n\n    mapping(address => uint256) public balances;\n\n    constructor() ERC20(\"WETH9\", \"wETH9\") { }\n\n    function testToAvoidCoverage() public pure {\n        return;\n    }\n\n    function deposit() external payable {\n        balances[msg.sender] = balances[msg.sender].add(msg.value);\n        _mint(msg.sender, msg.value);\n    }\n\n    function withdraw(uint256 wad) external {\n        balances[msg.sender] = balances[msg.sender].sub(wad);\n        _burn(msg.sender, wad);\n        payable(msg.sender).sendValue(wad);\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/unit-test/util/UnitSetupUtil.t.sol",
    "content": "pragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\n//interface\nimport { ERC20 } from \"openzeppelin/token/ERC20/ERC20.sol\";\nimport { IUniswapV3Pool } from \"v3-core/interfaces/IUniswapV3Pool.sol\";\n// contract\nimport { MockErc20 } from \"squeeth-monorepo/mocks/MockErc20.sol\";\nimport { UniswapV3Factory } from \"v3-core/UniswapV3Factory.sol\";\nimport { UniswapV3Pool } from \"v3-core/UniswapV3Pool.sol\";\nimport { NonfungiblePositionManager } from \"v3-periphery/NonfungiblePositionManager.sol\";\nimport { WETH9Mock } from \"../mock/Weth9Mock.t.sol\";\nimport { ShortPowerPerp } from \"squeeth-monorepo/core/ShortPowerPerp.sol\";\nimport { Controller } from \"squeeth-monorepo/core/Controller.sol\";\nimport { Oracle } from \"squeeth-monorepo/core/Oracle.sol\";\nimport { WPowerPerp } from \"squeeth-monorepo/core/WPowerPerp.sol\";\nimport { CrabStrategyV2 } from \"squeeth-monorepo/strategy/CrabStrategyV2.sol\";\n// lib\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\n\ncontract BullStrategyUnitTest is Test {\n    using StrategyMath for uint256;\n\n    NonfungiblePositionManager internal uniNonFungibleManager;\n    ShortPowerPerp internal shortPowerPerp;\n    WPowerPerp internal wPowerPerp;\n    Controller internal controller;\n    WETH9Mock internal weth;\n    MockErc20 internal usdc;\n    UniswapV3Factory internal uniFactory;\n    CrabStrategyV2 internal crabV2;\n\n    address internal ethWPowerPerpPool;\n    address internal ethUsdcPool;\n\n    uint256 internal timelockPk;\n    uint256 internal deployerPk;\n    uint256 internal user1Pk;\n    uint256 internal randomPk;\n    address internal deployer;\n    address internal user1;\n    address internal random;\n    address internal timelock;\n\n    function testToAvoidCoverage() public pure {\n        return;\n    }\n\n    function _deployUniswap() internal {\n        uniFactory = new UniswapV3Factory();\n        uniNonFungibleManager =\n            new NonfungiblePositionManager(address(uniFactory), address(weth), address(0));\n    }\n\n    function _deploySqueethEcosystem(uint256 _squeethEthPrice, uint24 _poolFee) internal {\n        usdc = new MockErc20(\"USDC\", \"USDC\", 6);\n        weth = new WETH9Mock();\n\n        ethUsdcPool =\n            _createUniPoolAndInitialize(address(usdc), address(weth), 3300e18, uint24(3000));\n        vm.warp(block.timestamp + 1000);\n        IUniswapV3Pool(ethUsdcPool).increaseObservationCardinalityNext(500);\n\n        wPowerPerp = new WPowerPerp(\"oSQTH\", \"oSQTH\");\n        address _shortPowerPerp = address(new ShortPowerPerp(\"ShortPowerPerp\", \"sOSQTH\"));\n        address _oracle = address(new Oracle());\n\n        ethWPowerPerpPool = _createUniPoolAndInitialize(\n            address(weth), address(wPowerPerp), _squeethEthPrice, _poolFee\n        );\n        vm.warp(block.timestamp + 1000);\n        IUniswapV3Pool(ethWPowerPerpPool).increaseObservationCardinalityNext(500);\n\n        controller = new Controller(\n            _oracle,\n            _shortPowerPerp,\n            address(wPowerPerp),\n            address(weth),\n            address(usdc),\n            ethUsdcPool, \n            ethWPowerPerpPool, \n            address(uniNonFungibleManager),\n            _poolFee\n        );\n\n        wPowerPerp.init(address(controller));\n        ShortPowerPerp(_shortPowerPerp).init(address(controller));\n\n        crabV2 =\n        new CrabStrategyV2(address(controller), _oracle, address(weth), address(uniFactory), ethWPowerPerpPool, timelock, timelock, uint256(100), uint256(1e17));\n    }\n\n    function _createUniPoolAndInitialize(\n        address _tokenA,\n        address _tokenB,\n        uint256 _tokenBPriceInA,\n        uint24 _fee\n    ) internal returns (address) {\n        bool isTokenAToken0 = _tokenA < _tokenB;\n\n        if (ERC20(_tokenA).decimals() < ERC20(_tokenB).decimals()) {\n            _tokenBPriceInA =\n                _tokenBPriceInA.div(10 ** (ERC20(_tokenB).decimals() - ERC20(_tokenA).decimals()));\n        } else {\n            _tokenBPriceInA =\n                _tokenBPriceInA.mul(10 ** (ERC20(_tokenA).decimals() - ERC20(_tokenB).decimals()));\n        }\n\n        // this may be wrong\n        uint160 sqrtX96Price = isTokenAToken0\n            ? uint160(sqrt(uint256(1e18).div(_tokenBPriceInA)).mul(2 ** 96))\n            : uint160(sqrt(_tokenBPriceInA.mul(1e18)).mul(2 ** 96));\n\n        (_tokenA, _tokenB) = isTokenAToken0 ? (_tokenA, _tokenB) : (_tokenB, _tokenA);\n\n        address pool = uniFactory.createPool(_tokenA, _tokenB, _fee);\n\n        IUniswapV3Pool(pool).initialize(sqrtX96Price);\n\n        return pool;\n    }\n\n    function sqrt(uint256 x) internal pure returns (uint256) {\n        uint256 n = x / 2;\n        uint256 lstX = 0;\n        while (n != lstX) {\n            lstX = n;\n            n = (n + x / n) / 2;\n        }\n        return n;\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/util/SigUtil.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity =0.7.6;\n\npragma abicoder v2;\n\ncontract SigUtil {\n    bytes32 internal DOMAIN_SEPARATOR;\n\n    constructor(bytes32 _DOMAIN_SEPARATOR) {\n        DOMAIN_SEPARATOR = _DOMAIN_SEPARATOR;\n    }\n\n    bytes32 private constant _FULL_REBALANCE_TYPEHASH = keccak256(\n        \"Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)\"\n    );\n\n    struct Order {\n        uint256 bidId;\n        address trader;\n        uint256 quantity;\n        uint256 price;\n        bool isBuying;\n        uint256 expiry;\n        uint256 nonce;\n    }\n\n    // computes the hash of a Order\n    function getStructHash(Order memory _order) internal pure returns (bytes32) {\n        return keccak256(\n            abi.encode(\n                _FULL_REBALANCE_TYPEHASH,\n                _order.bidId,\n                _order.trader,\n                _order.quantity,\n                _order.price,\n                _order.isBuying,\n                _order.expiry,\n                _order.nonce\n            )\n        );\n    }\n\n    // computes the hash of the fully encoded EIP-712 message for the domain, which can be used to recover the signer\n    function getTypedDataHash(Order memory _order) public view returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR, getStructHash(_order)));\n    }\n}\n"
  },
  {
    "path": "packages/zen-bull-vault/test/util/TestUtil.t.sol",
    "content": "pragma solidity =0.7.6;\n\npragma abicoder v2;\n\n// test dependency\nimport \"forge-std/Test.sol\";\n//interface\nimport { IERC20 } from \"openzeppelin/token/ERC20/IERC20.sol\";\nimport { IController } from \"squeeth-monorepo/interfaces/IController.sol\";\nimport { IEulerMarkets } from \"../../src/interface/IEulerMarkets.sol\";\nimport { IEulerEToken } from \"../../src/interface/IEulerEToken.sol\";\nimport { IEulerDToken } from \"../../src/interface/IEulerDToken.sol\";\n// contract\nimport { ZenBullStrategy } from \"../../src/ZenBullStrategy.sol\";\nimport { CrabStrategyV2 } from \"squeeth-monorepo/strategy/CrabStrategyV2.sol\";\nimport { Controller } from \"squeeth-monorepo/core/Controller.sol\";\n// lib\nimport { VaultLib } from \"squeeth-monorepo/libs/VaultLib.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\nimport { UniOracle } from \"../../src/UniOracle.sol\";\nimport { StrategyMath } from \"squeeth-monorepo/strategy/base/StrategyMath.sol\"; // StrategyMath licensed under AGPL-3.0-only\n\ncontract TestUtil is Test {\n    using StrategyMath for uint256;\n\n    uint128 internal constant ONE = 1e18;\n    uint32 internal constant TWAP = 420;\n    uint256 internal constant INDEX_SCALE = 10000;\n    uint256 internal constant WETH_DECIMALS_DIFF = 1e12;\n\n    address internal eToken;\n    address internal dToken;\n\n    ZenBullStrategy internal zenBullStrategy;\n    Controller internal controller;\n    CrabStrategyV2 internal crabV2;\n\n    constructor(\n        address payable _zenBullStrategy,\n        address payable _controller,\n        address _eToken,\n        address _dToken,\n        address payable _crabV2\n    ) {\n        zenBullStrategy = ZenBullStrategy(_zenBullStrategy);\n        controller = Controller(_controller);\n        eToken = _eToken;\n        dToken = _dToken;\n        crabV2 = CrabStrategyV2(_crabV2);\n    }\n\n    function testToAvoidCoverage() public pure {\n        return;\n    }\n\n    function getCrabVaultDetails() public view returns (uint256, uint256) {\n        VaultLib.Vault memory strategyVault =\n            IController(address(controller)).vaults(crabV2.vaultId());\n        return (strategyVault.collateralAmount, strategyVault.shortAmount);\n    }\n\n    function calcCollateralAndBorrowAmount(uint256 _crabToDeposit)\n        external\n        view\n        returns (uint256, uint256)\n    {\n        uint256 wethToLend;\n        uint256 usdcToBorrow;\n        if (IERC20(zenBullStrategy).totalSupply() == 0) {\n            {\n                uint256 ethUsdPrice = UniOracle._getTwap(\n                    controller.ethQuoteCurrencyPool(),\n                    controller.weth(),\n                    controller.quoteCurrency(),\n                    TWAP,\n                    false\n                );\n                uint256 squeethEthPrice = UniOracle._getTwap(\n                    controller.wPowerPerpPool(),\n                    controller.wPowerPerp(),\n                    controller.weth(),\n                    TWAP,\n                    false\n                );\n                (uint256 ethInCrab, uint256 squeethInCrab) = getCrabVaultDetails();\n                uint256 crabUsdPrice = (\n                    ethInCrab.wmul(ethUsdPrice).sub(\n                        squeethInCrab.wmul(squeethEthPrice).wmul(ethUsdPrice)\n                    )\n                ).wdiv(crabV2.totalSupply());\n                wethToLend = zenBullStrategy.TARGET_CR().wmul(_crabToDeposit).wmul(crabUsdPrice)\n                    .wdiv(ethUsdPrice);\n                usdcToBorrow = wethToLend.wmul(ethUsdPrice).wdiv(zenBullStrategy.TARGET_CR()).div(\n                    WETH_DECIMALS_DIFF\n                );\n            }\n        } else {\n            uint256 share =\n                _crabToDeposit.wdiv(zenBullStrategy.getCrabBalance().add(_crabToDeposit));\n            wethToLend = IEulerEToken(eToken).balanceOfUnderlying(address(zenBullStrategy)).wmul(\n                share\n            ).wdiv(uint256(1e18).sub(share));\n            usdcToBorrow = IEulerDToken(dToken).balanceOf(address(zenBullStrategy)).wmul(share).wdiv(\n                uint256(1e18).sub(share)\n            );\n        }\n\n        return (wethToLend, usdcToBorrow);\n    }\n\n    function getCrabPrice() external view returns (uint256) {\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        (uint256 ethInCrab, uint256 squeethInCrab) = getCrabVaultDetails();\n        uint256 crabUsdPrice = (\n            ethInCrab.wmul(ethUsdPrice).sub(squeethInCrab.wmul(squeethEthPrice).wmul(ethUsdPrice))\n        ).wdiv(crabV2.totalSupply());\n        return crabUsdPrice;\n    }\n\n    function calcTotalEthDelta(uint256 _crabToDeposit) external view returns (uint256) {\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n        (uint256 ethInCrab, uint256 squeethInCrab) = getCrabVaultDetails();\n        uint256 crabUsdPrice = (\n            ethInCrab.wmul(ethUsdPrice).sub(squeethInCrab.wmul(squeethEthPrice).wmul(ethUsdPrice))\n        ).wdiv(crabV2.totalSupply());\n        uint256 totalEthDelta = (\n            IEulerEToken(eToken).balanceOfUnderlying(address(zenBullStrategy)).wmul(ethUsdPrice)\n        ).wdiv(\n            _crabToDeposit.wmul(crabUsdPrice).add(\n                IEulerEToken(eToken).balanceOfUnderlying(address(zenBullStrategy)).wmul(ethUsdPrice)\n            ).sub(IEulerDToken(dToken).balanceOf(address(zenBullStrategy)).mul(WETH_DECIMALS_DIFF))\n        );\n\n        return totalEthDelta;\n    }\n\n    function calcWethToWithdraw(uint256 _bullAmount) external view returns (uint256) {\n        return (_bullAmount.wdiv(zenBullStrategy.totalSupply())).wmul(\n            IEulerEToken(eToken).balanceOfUnderlying(address(zenBullStrategy))\n        );\n    }\n\n    function calcBullToMint(uint256 _crabToDeposit) external view returns (uint256) {\n        if (IERC20(zenBullStrategy).totalSupply() == 0) {\n            return _crabToDeposit;\n        } else {\n            uint256 share =\n                _crabToDeposit.wdiv(zenBullStrategy.getCrabBalance().add(_crabToDeposit));\n            return share.wmul(zenBullStrategy.totalSupply()).wdiv(uint256(1e18).sub(share));\n        }\n    }\n\n    function calculateCrabRedemption(\n        uint256 crabShares,\n        uint256 ethUsdPrice,\n        uint256 crabCollateral,\n        uint256 crabDebt\n    ) external view returns (uint256) {\n        uint256 ethInCrabAfterShutdown;\n        //this check is not strictly true, but for our tests it works. hasRedeemedInShutdown is a private variable that would be the correct one to check\n        if (controller.isShutDown()) {\n            ethInCrabAfterShutdown = address(crabV2).balance;\n        } else {\n            ethInCrabAfterShutdown = crabCollateral.sub(\n                crabDebt.wmul(controller.normalizationFactor()).wmul(ethUsdPrice.div(INDEX_SCALE))\n            );\n        }\n\n        uint256 ethFromCrabRedemption =\n            crabShares.wdiv(crabV2.totalSupply()).wmul(ethInCrabAfterShutdown);\n\n        // note the below doesnt work as it has wrong order of operations - make sure our order of operations is correct for rounding reasons\n        //uint256 ethFromCrabRedemption = crabShares.wmul(ethInCrabAfterShutdown).wdiv(crabV2.totalSupply())\n\n        return ethFromCrabRedemption;\n    }\n\n    function calcWsqueethToMintAndFee(\n        uint256 _depositedAmount,\n        uint256 _strategyDebtAmount,\n        uint256 _strategyCollateralAmount\n    ) external view returns (uint256, uint256) {\n        uint256 wSqueethToMint;\n        uint256 wSqueethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        uint256 feeRate = IController(zenBullStrategy.powerTokenController()).feeRate();\n        uint256 feeAdjustment = wSqueethEthPrice.mul(feeRate).div(10000);\n\n        wSqueethToMint = _depositedAmount.wmul(_strategyDebtAmount).wdiv(\n            _strategyCollateralAmount.add(_strategyDebtAmount.wmul(feeAdjustment))\n        );\n\n        uint256 fee = wSqueethToMint.wmul(feeAdjustment);\n\n        return (wSqueethToMint, fee);\n    }\n\n    /**\n     * @dev calculate amount of strategy token to mint for depositor\n     * @param _amount amount of ETH deposited\n     * @param _strategyCollateralAmount amount of strategy collateral\n     * @param _crabTotalSupply total supply of strategy token\n     * @return amount of strategy token to mint\n     */\n    function calcSharesToMint(\n        uint256 _amount,\n        uint256 _strategyCollateralAmount,\n        uint256 _crabTotalSupply\n    ) external pure returns (uint256) {\n        uint256 depositorShare = _amount.wdiv(_strategyCollateralAmount.add(_amount));\n\n        if (_crabTotalSupply != 0) {\n            return _crabTotalSupply.wmul(depositorShare).wdiv(uint256(ONE).sub(depositorShare));\n        }\n\n        return _amount;\n    }\n\n    function calcTotalEthToBull(\n        uint256 wethToLend,\n        uint256 ethToCrab,\n        uint256 usdcToBorrow,\n        uint256 wSqueethToMint\n    ) external view returns (uint256) {\n        uint256 ethUsdPrice = UniOracle._getTwap(\n            controller.ethQuoteCurrencyPool(),\n            controller.weth(),\n            controller.quoteCurrency(),\n            TWAP,\n            false\n        );\n        uint256 squeethEthPrice = UniOracle._getTwap(\n            controller.wPowerPerpPool(), controller.wPowerPerp(), controller.weth(), TWAP, false\n        );\n\n        uint256 totalEthToBull = wethToLend.add(ethToCrab).sub(usdcToBorrow.wdiv(ethUsdPrice)).sub(\n            wSqueethToMint.wmul(squeethEthPrice)\n        ).add(1e16);\n        return totalEthToBull;\n    }\n}\n"
  }
]